> ## Documentation Index
> Fetch the complete documentation index at: https://api.fanvue.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Get messages from multiple chats in bulk

> Returns the most recent messages for up to 50 chats in a single request, keyed by the input chat UUID (the counterpart user UUID).

This is the bulk counterpart to `GET /chats/{userUuid}/messages`. It collapses N per-chat round trips into one POST and is intended for initial-sync flows and incremental refreshes.

Per-key errors are reported inside the 200 response body so a single unreachable chat never collapses the whole request — consumers keep the rest and only retry the failing keys.

**Modes:**
- **Default**: returns the latest `limit` messages per chat, newest first. `hasMore` indicates older messages exist.
- **Incremental (`sinceMessageUuid`)**: returns messages strictly published after the cursor message's publish date, newest first.

**Out of scope:** Backwards history pagination (a `before` cursor). Use `oldestMessageUuid` from the response as the anchor when that ships.

<Note>Maximum 50 chat UUIDs per request. Failed keys are reported as `{ "error": "not_found" }` — this covers both chats that don't exist and chats the caller isn't part of.</Note>

<Note>Read-only: fetching messages in bulk does not mutate read state — messages are not marked read and `isRead` reflects each message's state at read time.</Note>

<Info>
  **Required scope**

  * `read:chat` — Read chat conversations, messages, and chat-related data. This includes viewing chat lists and message history.
</Info>


## OpenAPI

````yaml /openapi-v1.json post /v1/chats/messages/batch
openapi: 3.1.0
info:
  title: Fanvue API
  version: '0.1'
servers:
  - url: https://api.fanvue.com
security: []
paths:
  /v1/chats/messages/batch:
    post:
      summary: Get messages from multiple chats in bulk
      description: >-
        Returns the most recent messages for up to 50 chats in a single request,
        keyed by the input chat UUID (the counterpart user UUID).


        This is the bulk counterpart to `GET /chats/{userUuid}/messages`. It
        collapses N per-chat round trips into one POST and is intended for
        initial-sync flows and incremental refreshes.


        Per-key errors are reported inside the 200 response body so a single
        unreachable chat never collapses the whole request — consumers keep the
        rest and only retry the failing keys.


        **Modes:**

        - **Default**: returns the latest `limit` messages per chat, newest
        first. `hasMore` indicates older messages exist.

        - **Incremental (`sinceMessageUuid`)**: returns messages strictly
        published after the cursor message's publish date, newest first.


        **Out of scope:** Backwards history pagination (a `before` cursor). Use
        `oldestMessageUuid` from the response as the anchor when that ships.


        <Note>Maximum 50 chat UUIDs per request. Failed keys are reported as `{
        "error": "not_found" }` — this covers both chats that don't exist and
        chats the caller isn't part of.</Note>


        <Note>Read-only: fetching messages in bulk does not mutate read state —
        messages are not marked read and `isRead` reflects each message's state
        at read time.</Note>
      operationId: messagesBatch
      parameters:
        - $ref: '#/components/parameters/ApiVersionHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                chatUuids:
                  type: array
                  items:
                    type: string
                    format: uuid
                  minItems: 1
                  maxItems: 50
                  description: >-
                    Array of chat UUIDs (counterpart user UUIDs) to fetch
                    messages for (1-50)
                sinceMessageUuid:
                  type: string
                  format: uuid
                  description: >-
                    Optional cursor for incremental walks: returns only messages
                    strictly after this message's publish date in each chat
                limit:
                  type: integer
                  minimum: 1
                  maximum: 50
                  default: 20
                  description: 'Maximum messages to return per chat (1-50, default: 20)'
              required:
                - chatUuids
      responses:
        '200':
          description: >-
            Per-chat messages or error for each requested chat. Always 200 when
            the request itself is valid, even if every key fails.
          content:
            application/json:
              schema:
                type: object
                properties:
                  byChat:
                    type: object
                    additionalProperties:
                      anyOf:
                        - type: object
                          properties:
                            messages:
                              type: array
                              items:
                                type: object
                                properties:
                                  uuid:
                                    type: string
                                    format: uuid
                                  text:
                                    type:
                                      - string
                                      - 'null'
                                  sentAt:
                                    type:
                                      - string
                                      - 'null'
                                    format: date
                                  sender:
                                    type: object
                                    properties:
                                      uuid:
                                        type: string
                                        format: uuid
                                      handle:
                                        type: string
                                    required:
                                      - uuid
                                      - handle
                                  recipient:
                                    type: object
                                    properties:
                                      uuid:
                                        type: string
                                        format: uuid
                                      handle:
                                        type: string
                                  hasMedia:
                                    type:
                                      - boolean
                                      - 'null'
                                  mediaType:
                                    type:
                                      - string
                                      - 'null'
                                    enum:
                                      - image
                                      - video
                                      - audio
                                      - document
                                  mediaUuids:
                                    type: array
                                    items:
                                      type: string
                                      format: uuid
                                    description: >-
                                      Ordered list of media UUIDs attached to
                                      this message (display order)
                                  mediaPreviewUuid:
                                    type:
                                      - string
                                      - 'null'
                                    format: uuid
                                    description: >-
                                      UUID of the media item shown for free as a
                                      preview of this pay-to-view message, or
                                      null when no free preview was configured.
                                      Mirrors the `mediaPreviewUuid` set when
                                      sending the message.
                                  gif:
                                    type:
                                      - object
                                      - 'null'
                                    properties:
                                      id:
                                        type: string
                                        description: >-
                                          The GIF provider's durable identifier
                                          for this GIF. Stable across renditions;
                                          use it to de-duplicate or re-resolve the
                                          GIF.
                                      format:
                                        type: string
                                        enum:
                                          - GIF
                                          - WEBP
                                          - MP4
                                          - WEBM
                                        description: >-
                                          Encoding of the asset at `url`. Only
                                          `GIF` and `WEBP` are produced today, and
                                          both render in a plain <img> tag.
                                      title:
                                        type:
                                          - string
                                          - 'null'
                                        description: >-
                                          Human-readable GIF title, suitable as
                                          alt text.
                                      url:
                                        type:
                                          - string
                                          - 'null'
                                        description: >-
                                          Hotlink URL of the GIF, served from the
                                          provider's CDN — Fanvue does not host or
                                          proxy the asset. Null when the URL is
                                          temporarily withheld; the message is
                                          still a GIF message, so render a
                                          placeholder at `width`/`height` rather
                                          than treating it as empty.
                                      width:
                                        type: integer
                                        exclusiveMinimum: 0
                                        description: >-
                                          Intrinsic width of the asset at `url`,
                                          in pixels
                                      height:
                                        type: integer
                                        exclusiveMinimum: 0
                                        description: >-
                                          Intrinsic height of the asset at `url`,
                                          in pixels
                                    required:
                                      - id
                                      - format
                                      - title
                                      - url
                                      - width
                                      - height
                                    description: >-
                                      The third-party GIF attached to this
                                      message, or null for an ordinary message.
                                      A GIF message carries no media and no
                                      price, but `text` may be set — a GIF can
                                      be sent with a caption.
                                  type:
                                    type: string
                                    enum:
                                      - AUTOMATED_CANCELED
                                      - AUTOMATED_NEW_FOLLOWER
                                      - AUTOMATED_NEW_PURCHASE
                                      - AUTOMATED_NEW_SUBSCRIBER
                                      - AUTOMATED_RE_SUBSCRIBED
                                      - AUTOMATED_RENEWED
                                      - AUTOMATED_CHAT_MESSAGE_REPLY
                                      - AUTOMATED_FIRST_MESSAGE_REPLY
                                      - CHAT_TEXT_GENERATION
                                      - CHAT_TEXT_REPLY
                                      - CHAT_TEXT_REWRITE
                                      - SINGLE_RECIPIENT
                                      - TIP
                                      - VOICE_CALL
                                      - BROADCAST
                                      - GHOST_PROMOTION
                                  pricing:
                                    type:
                                      - object
                                      - 'null'
                                    properties:
                                      USD:
                                        type: object
                                        properties:
                                          price:
                                            type: number
                                            description: Price in cents
                                        required:
                                          - price
                                    required:
                                      - USD
                                    description: >-
                                      Pricing information for pay-to-view
                                      messages
                                  purchasedAt:
                                    type:
                                      - string
                                      - 'null'
                                    format: date
                                    description: >-
                                      Timestamp when this message was purchased,
                                      or null if not purchased
                                  tipSource:
                                    type:
                                      - string
                                      - 'null'
                                    enum:
                                      - chat
                                      - post
                                      - media_link
                                    description: >-
                                      For TIP messages, where the tip
                                      originated: 'chat' (direct in-chat tip),
                                      'post' (tipped a feed post) or
                                      'media_link' (tipped via a shared media
                                      link). Null for non-tip messages.
                                  sentByUserId:
                                    type:
                                      - string
                                      - 'null'
                                    format: uuid
                                    description: >-
                                      UUID of the team member who sent the
                                      message on behalf of the creator, or null
                                      if sent directly by the creator
                                  appUuid:
                                    type:
                                      - string
                                      - 'null'
                                    format: uuid
                                    description: >-
                                      UUID of the third-party app that created
                                      this message through the public API. Null
                                      when the message was sent from the Fanvue
                                      dashboard, and for every message sent
                                      before app attribution was recorded.
                                  isRead:
                                    type: boolean
                                    description: >-
                                      Whether the message has been read by the
                                      recipient
                                required:
                                  - uuid
                                  - text
                                  - sentAt
                                  - sender
                                  - recipient
                                  - hasMedia
                                  - mediaType
                                  - mediaUuids
                                  - mediaPreviewUuid
                                  - gif
                                  - type
                                  - pricing
                                  - purchasedAt
                                  - tipSource
                                  - sentByUserId
                                  - appUuid
                                  - isRead
                            hasMore:
                              type: boolean
                              description: >-
                                Whether more messages exist beyond the returned
                                set (older than `oldestMessageUuid` for the
                                default newest-first read, or in the queried
                                range for incremental walks)
                            oldestMessageUuid:
                              type:
                                - string
                                - 'null'
                              format: uuid
                              description: >-
                                UUID of the oldest message in the returned
                                batch, or null if no messages were returned
                          required:
                            - messages
                            - hasMore
                            - oldestMessageUuid
                        - type: object
                          properties:
                            error:
                              type: string
                              enum:
                                - forbidden
                                - not_found
                                - internal
                          required:
                            - error
                    description: Map of input chat UUID to messages or a per-key error
                required:
                  - byChat
              example:
                byChat:
                  b2c3d4e5-6f7g-8h9i-0j1k-l2m3n4o5p6q7:
                    messages:
                      - uuid: a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6
                        text: Hey there! How are you doing?
                        sentAt: '2024-01-15T00:00:00.000Z'
                        sender:
                          uuid: f47ac10b-58cc-4372-a567-0e02b2c3d479
                          handle: sarah-jones
                          nickname: SarahK
                          displayName: Sarah Jones
                          isTopSpender: true
                          avatarUrl: https://media.fanvue.com/avatars/example-avatar.jpg
                          registeredAt: '2024-01-10T12:00:00.000Z'
                        recipient:
                          uuid: 3bbe6394-2830-4646-a8ba-4a0a05426947
                          handle: johnny-doey
                          nickname: JohnnyD
                          displayName: Johnny Doey
                          isTopSpender: true
                          avatarUrl: https://media.fanvue.com/avatars/example-avatar.jpg
                          registeredAt: '2024-01-10T12:00:00.000Z'
                        type: SINGLE_RECIPIENT
                        hasMedia: false
                        mediaType: null
                        mediaUuids: []
                        mediaPreviewUuid: null
                        gif: null
                        pricing: null
                        purchasedAt: null
                        sentByUserId: null
                        appUuid: f6a7b8c9-0123-4567-89ab-cdef01234567
                        isRead: true
                    hasMore: true
                    oldestMessageUuid: a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6
                  c3d4e5f6-7890-1234-5678-9abcdef01234:
                    error: not_found
        '400':
          description: Bad Request - API version not supported OR validation failed
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/UnsupportedVersionError'
                  - $ref: '#/components/schemas/ValidationError'
        '401':
          $ref: '#/components/responses/UnauthorizedResponse'
        '403':
          $ref: '#/components/responses/UnauthorizedResponse'
        '410':
          $ref: '#/components/responses/SunsetVersionResponse'
        '429':
          $ref: '#/components/responses/RateLimitResponse'
      security:
        - BearerAuth:
            - read:chat
components:
  parameters:
    ApiVersionHeader:
      name: X-Fanvue-API-Version
      in: header
      required: true
      schema:
        type: string
        default: '2025-06-26'
        example: '2025-06-26'
      description: API version to use for the request
  schemas:
    UnsupportedVersionError:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
      required:
        - error
        - message
      description: API version not supported
    ValidationError:
      type: object
      properties:
        errors:
          type: array
          items:
            type: string
      required:
        - errors
      description: Request validation failed
  responses:
    UnauthorizedResponse:
      description: Unauthorized Response
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
            required:
              - error
    SunsetVersionResponse:
      description: API version no longer supported (sunset)
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              message:
                type: string
              nextVersion:
                type: string
            required:
              - error
              - message
    RateLimitResponse:
      description: Too many requests - rate limit exceeded
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying the request
          schema:
            type: integer
        X-RateLimit-Limit:
          description: The maximum number of requests allowed in the current window
          schema:
            type: integer
        X-RateLimit-Remaining:
          description: The number of requests remaining in the current window
          schema:
            type: integer
        X-RateLimit-Reset:
          description: The Unix timestamp (seconds) when the rate limit window resets
          schema:
            type: integer
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
            required:
              - error
  securitySchemes:
    BearerAuth:
      type: oauth2
      description: >-
        OAuth 2.0 access token, presented as a JWT bearer token in the
        `Authorization` header. Obtain a token via the authorization-code flow;
        the scopes granted to the token determine which operations it may call.
      flows:
        authorizationCode:
          authorizationUrl: https://auth.fanvue.com/oauth2/auth
          tokenUrl: https://auth.fanvue.com/oauth2/token
          refreshUrl: https://auth.fanvue.com/oauth2/token
          scopes:
            read:self: >-
              Access your own user profile information, including basic account
              details and settings.
            read:chat: >-
              Read chat conversations, messages, and chat-related data. This
              includes viewing chat lists and message history.
            write:chat: >-
              Create new chats and send messages. This scope is required for any
              chat-related actions that modify data.
            read:experience: >-
              Exchange a fan's experience token for the resolved experience and
              the fan's identity, so an embedded fan-facing experience can
              render the right content.
            write:experience: >-
              Request that the creator publish or unpublish a fan-facing
              experience. The app mints a request token; the creator confirms
              and Fanvue performs the change.
            read:fan: Access fan-related data and information within the platform.
            read:post: Read posts, including post details, comments, likes, and tips.
            write:post: Create, edit, and manage posts and content on behalf of users.
            read:media: Access media files, images, videos, and other content assets.
            write:media: >-
              Upload, modify, and manage media files and content assets. Also
              required for vault folder management.
            read:creator: >-
              Access creator profiles, content, and creator-specific
              information.
            write:creator: Modify creator profiles, settings, and creator-specific data.
            read:insights: >-
              Access analytics, metrics, and insights data for performance
              tracking.
            read:tracking_links: >-
              Read tracking links and the users associated with them, including
              per-user tracking metadata.
            write:tracking_links: Create and delete tracking links.
            read:agency: Read agency information, including the agency's team members.
            write:agency: >-
              Manage agency team members and invites, including inviting new
              team members and creators.

````