6 min read
Jan 30, 2026

Message retrieval

How to paginate room and thread messages in the Pivot REST API.

Room messages and thread messages use cursor-based pagination, but they page through history differently. This guide explains how to use each endpoint without missing older messages.

Room messages

Endpoint:

GET /v2/rooms/{room_id}/messages

Room messages are returned in history windows, ordered newest first. Follow the response cursors to continue through the current window or move to the next older window.

How to retrieve all room messages

  1. Call the endpoint with no cursor to query the latest history window.
  2. If shard_has_more is true, continue within the current window using next_cursor_sent_at and next_cursor_message_id.
  3. When shard_has_more is false, move to the next older history window by setting cursor_sent_at to next_partition_cursor.
  4. Repeat until next_partition_cursor is older than the room’s created_at timestamp.

next_partition_cursor is always returned. An empty messages array can still be a valid response when the current history window has no data.

Example flow

Start at the latest history window:

GET /v2/rooms/ROOM_ID/messages

If you know messages exist around a specific date, you can jump directly to that point in history:

GET /v2/rooms/ROOM_ID/messages?cursor_sent_at=2025-09-30T23:59:59Z

Paginate within the current history window:

GET /v2/rooms/ROOM_ID/messages?cursor_sent_at=2025-09-30T23:59:59Z&cursor_message_id=MSG_ID

Thread messages

Endpoint:

GET /v2/rooms/{room_id}/threads/{parent_id}/messages

Thread messages are scoped to the selected parent message. Messages are returned oldest first.

For nested threads, parent_id refers to the top-level parent message (the one without a parent), not the immediate reply.

Pagination

  1. Call the endpoint without cursors to fetch the first page.
  2. If has_more is true, pass next_cursor_sent_at and next_cursor_message_id to fetch the next page.
GET /v2/rooms/ROOM_ID/threads/PARENT_ID/messages?cursor_sent_at=2025-09-30T23:59:59Z&cursor_message_id=MSG_ID

Common pitfalls

  • Empty messages with a valid next_partition_cursor usually means the current history window is empty, not that the room has no messages.
  • If you only query the latest history window, you will miss older history for rooms with long-lived activity.
  • For thread messages, pass both cursor_sent_at and cursor_message_id when paginating.
  • If you receive Not Found, verify the integration has access to the room (try another room-level endpoint).

Was this guide helpful?