List messages (history)
Chat
List messages (history)
Cursor-paginated message history for a conversation, newest first.
GET
List messages (history)
Overview
Returns messages for a conversation, newest first (createdAt desc). Pagination is cursor-based on createdAt: pass the oldest createdAt you’ve already seen as ?before=... to fetch the next older page. This is the standard “infinite scroll up” mobile pattern.
The endpoint reuses the participant gate from Get conversation, so the same 403 FORBIDDEN / 404 NOT_FOUND semantics apply.
Authentication
Bearer <accessToken> required. requireOnboarded middleware applied.
Path parameters
| Name | Type | Required | Notes | Example |
|---|---|---|---|---|
id | string | yes | 24-char hex ObjectId of the conversation. | 66400a8f1c2b4d5e6f7a9000 |
Query parameters
| Name | Type | Required | Default | Notes | Example |
|---|---|---|---|---|---|
before | string | no | (none) | ISO 8601 UTC datetime. Returns messages with createdAt < before. Use the oldest createdAt from the previous page. | 2026-05-22T14:35:12.001Z |
limit | integer | no | 50 | 1..200 inclusive. The client typically fetches 50 per page. | 50 |
Request body
None.Response — 200 OK
| Field | Type | Notes | Example |
|---|---|---|---|
messages | object[] | Array of message rows sorted by createdAt desc. Empty array ([]) when the cursor has reached the start of history. |
Message object
| Field | Type | Allowed values / Notes | Example |
|---|---|---|---|
id | string | 24-char hex ObjectId. Use as upToMessageId for mark-read. | 66400a8f1c2b4d5e6f7aa000 |
conversationId | string | 24-char hex ObjectId. Always matches the path :id. | 66400a8f1c2b4d5e6f7a9000 |
senderId | string | 24-char hex ObjectId of the sender. One of the conversation’s participantIds. | 66400a8f1c2b4d5e6f7a8b01 |
clientMessageId | string | 1..64 chars. The token the sender’s client used to dedup at send time. Useful for matching local optimistic UI rows to server rows. | cm_01HZQ7K3M4N5P6Q7R8S9T0V1W2 |
messageType | enum | text, image, video, or file. | image |
text | string | Body for text messages (non-empty); caption for media (may be empty). 0..4000 chars. | Hi! Loved your kitchen. |
media | object | null | Present iff messageType is image/video/file; null for text. Fields: url, thumbnailUrl, fileName, mimeType, sizeBytes, width, height, durationSec (see send-message → Media object). | |
deliveredTo | object[] | One Receipt per recipient that has received the message. Phase 4 returns [] — delivery receipts are wired up but not yet emitted by the worker. | [] |
readBy | object[] | One Receipt per recipient that has marked the message read. Excludes the sender (you don’t “read” your own messages). | [] |
editedAt | string | null | ISO 8601 UTC if this message has been edited. null in Phase 4 — edit is not exposed yet. | null |
deletedAt | string | null | ISO 8601 UTC if this message has been soft-deleted. null in Phase 4 — delete is not exposed yet. | null |
createdAt | string | ISO 8601 UTC with millisecond precision. Used as the pagination cursor. | 2026-05-22T14:35:12.001Z |
updatedAt | string | ISO 8601 UTC. Equal to createdAt until edits/receipts mutate the row. | 2026-05-22T14:35:12.001Z |
Receipt object
| Field | Type | Notes | Example |
|---|---|---|---|
userId | string | 24-char hex ObjectId of the recipient that issued the receipt. | 66400a8f1c2b4d5e6f7a8b00 |
at | string | ISO 8601 UTC when the receipt was recorded server-side. | 2026-05-22T14:35:18.420Z |
Example response
Paging sequence
createdAt < before, never <=. Use the previous page’s oldest createdAt verbatim — you will not get duplicate rows.
Error responses
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | before is not an ISO 8601 datetime, or limit is outside 1..200. |
| 401 | UNAUTHENTICATED | Missing, malformed, or expired access token. |
| 403 | ONBOARDING_INCOMPLETE | Caller has not finished onboarding. |
| 403 | FORBIDDEN | Caller is not a participant of this conversation. |
| 404 | NOT_FOUND | No conversation with that id. |
Side effects
None — pure read. Reading a message does not add areadBy receipt; that requires an explicit mark-read call.
See also
- Send message — produces rows this endpoint returns.
- Mark conversation read — issues the
readByreceipts. - Pagination conventions.
- Socket events —
chat:message:newdelivers messages live; history is the catch-up channel.