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 differ in how data is partitioned. This guide explains how to page through each endpoint without missing history.

Room messages

Endpoint:

GET /v2/rooms/{room_id}/messages

Room messages are stored in time partitions (about 28-day windows). Each request returns messages from one partition at a time, ordered newest first.

How to retrieve all room messages

  1. Call the endpoint with no cursor to query the current partition.
  2. If shard_has_more is true, continue within the same partition using next_cursor_sent_at and next_cursor_message_id.
  3. When shard_has_more is false, move to the next older partition 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 partition has no data.

Example flow

Start at the current partition:

GET /v2/rooms/ROOM_ID/messages

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

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

Paginate within a partition:

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 a single partition (the parent message), so there is no partition navigation. 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 partition is empty, not that the room has no messages.
  • If you only query the current partition, 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?