---
title: "Get messages from multiple chats in bulk"
method: POST
path: "/chats/messages/batch"
---

# Get messages from multiple chats in bulk

`POST /chats/messages/batch`

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 newer than the cursor message, newest first. The cursor is the message itself, not its timestamp, so a message sharing the cursor's publish instant is still returned.

**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>

## Headers

- `X-Fanvue-API-Version` string, required

## Request body

- object
  - `chatUuids` string[], required — Array of chat UUIDs (counterpart user UUIDs) to fetch messages for (1-50)
  - `sinceMessageUuid` string, uuid — Optional cursor for incremental walks: returns only messages strictly newer than this message in each chat. Anchored on the message, not its timestamp, so a message published in the same instant is not skipped
  - `limit` integer — Maximum messages to return per chat (1-50, default: 20)

## Response `200`

Per-chat messages or error for each requested chat. Always 200 when the request itself is valid, even if every key fails.

- object
  - `byChat` object, required — Map of input chat UUID to messages or a per-key error

## Other responses

- `400` — Bad Request - API version not supported OR validation failed
- `401` — Unauthorized Response
- `403` — Unauthorized Response
- `410` — API version no longer supported (sunset)
- `429` — Too many requests - rate limit exceeded

## Changes

- **2026-08-30** `dce5621fe589` — 1 info
  - added the required property `byChat/additionalProperties/anyOf[subschema #1]/messages/items/appUuid` to the response with the `200` status

[Change history](https://skmtc.dev/fanvue/apis/fanvue-api/changes/chats/messages/batch/post.md)

---

[API](https://skmtc.dev/fanvue/apis/fanvue-api.md) · [All operations](https://skmtc.dev/fanvue/apis/fanvue-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fanvue/apis/fanvue-api/revisions/431868e8a264?raw)
