---
title: "List messages"
method: GET
path: "/api/v1/gateway/messages"
tags: ["gateway"]
---

# List messages

`GET /api/v1/gateway/messages`

## Request

- Base URL: `https://api.textbee.dev`
- URL: `https://api.textbee.dev/api/v1/gateway/messages`
- Auth: API key in header `x-api-key`

Sent and received messages across your whole account, newest first, with delivery status on each. Filter by device, direction, status, text, and time range. Two pagination modes: page numbers for browsing, or cursor for polling. To poll for new messages: request order=asc with a from timestamp, follow nextCursor until hasMore is false, then resume from the last nextCursor on the next poll. Time filters apply to createdAt (when the platform stored the message). For received messages this is upload time, which can lag receivedAt if the device was offline. A received message uploaded more than 24 hours after receivedAt is stored with createdAt set to receivedAt and the upload time in originalCreatedAt, so a poll that has already moved past receivedAt does not return it.

## Query parameters

- `cursor` string
- `limit` integer
- `page` integer
- `order` 'desc' | 'asc'
- `to` string
- `from` string
- `search` string
- `status` 'pending' | 'dispatched' | 'sent' | 'delivered' | 'failed' | 'unknown' | 'received'
- `smsBatchId` string
- `type` 'all' | 'sent' | 'received'
- `direction` 'all' | 'sent' | 'received'
- `deviceIds` string

## Response `200`

A page of messages.

- MessageListResponseDTO
  - `data` MessageDTO[], required: Messages, newest first unless order=asc.
    - `_id` string, required: Message id.
    - `message` string: Message text. Empty when the message is end to end encrypted.
    - `device` MessageDeviceDTO, required
      - `_id` string, required: Device id.
      - `enabled` boolean, required: Whether the device may send and receive SMS.
      - `name` string: Your own label for the device.
      - `brand` string, required: Device brand.
      - `model` string, required: Device model.
      - `buildId` string, required: Android build id.
    - `type` 'SENT' | 'RECEIVED', required: Direction of the message, uppercase. Deprecated: read the lowercase direction field instead, whose values match the direction query filter.
    - `status` 'pending' | 'dispatched' | 'sent' | 'delivered' | 'failed' | 'unknown' | 'received', nullable: Delivery state, lowercase. Incoming messages are always received. Outgoing messages move from pending to sent, then to delivered when the carrier confirms. Absent on messages stored before status tracking, so treat a missing value as unknown.
    - `sender` string: Sender number. Set on received messages.
    - `recipient` string: Destination number. Set on sent messages.
    - `smsBatch` string: Id of the batch this message was sent in.
    - `encrypted` boolean: Whether the body is end to end encrypted. Encrypted bodies can only be read by your own client.
    - `simSubscriptionId` number: SIM requested for this send, as passed in the send request. Not necessarily the SIM used: read simUsed for that.
    - `simUsed` SimUsedDTO
      - `subscriptionId` number: Subscription id of the SIM.
      - `slotIndex` number: Zero-based slot of the SIM: 0 is SIM 1, 1 is SIM 2.
    - `receivedAt` string, date-time: When the message was received. Received messages only.
    - `requestedAt` string, date-time: When the send was requested. Sent messages only.
    - `dispatchDueAt` string, date-time: When the queue is due to hand the message to the push service. Set for queued messages that wait server-side before dispatch: scheduled sends, and large sends, which are released in waves paced to the device send delay so the phone is never asked to hold more than it can send. Absent for immediate sends.
    - `dispatchedAt` string, date-time: When the push service accepted the message for delivery to the device. Does not mean the device has received it; sentAt is the first device-confirmed timestamp.
    - `dispatchAttempts` number: How many times the message has been handed to the push service. Normally 1; higher when a message was dispatched again.
    - `pushReceivedAt` string, date-time: When the device received the push for this message. Absent for messages handled by app versions that do not report it.
    - `sendAttemptedAt` string, date-time: When the device handed the message to the radio. The gap to sentAt is time spent in the radio; the gap from pushReceivedAt is time the message waited on the device.
    - `sentAt` string, date-time: When the device reported the message as sent.
    - `deliveredAt` string, date-time: When the carrier confirmed delivery.
    - `failedAt` string, date-time: When the message failed.
    - `errorCode` string: Failure code reported by the device.
    - `errorMessage` string: Failure reason reported by the device.
    - `overLimit` boolean: True when the message was received while the account was over its plan limit. Received messages only. Absent otherwise.
    - `originalCreatedAt` string, date-time: When the platform stored the message. Set only on a received message uploaded more than 24 hours after receivedAt, whose createdAt is set to receivedAt.
    - `createdAt` string, date-time, required: When the record was created. For a received message uploaded more than 24 hours after receivedAt, this equals receivedAt and originalCreatedAt holds the upload time.
    - `updatedAt` string, date-time, required: When the record was last updated.
    - `direction` 'sent' | 'received', required: Direction of the message, lowercase. Values match the direction query filter, so a response value can be passed straight back as a filter. Not the same thing as status: direction=sent means outbound, status=sent means the device dispatched it.
    - `channel` 'sms': Message channel. Currently always sms; mms will appear here when supported. Absent means sms.
  - `meta` union, required: Pagination metadata. Page mode (no cursor) returns page, limit, total, totalPages plus nextCursor and hasMore; cursor mode returns limit, nextCursor, and hasMore only, skipping the expensive total count. anyOf rather than oneOf: a page-mode object also satisfies the cursor-mode shape, and oneOf would make strict validators reject it.
    - MessagePageMetaDTO
      - `page` integer, required: Current page number
      - `limit` integer, required: Number of items per page
      - `total` integer, required: Total number of items
      - `totalPages` integer, required: Total number of pages
      - `nextCursor` string, nullable, required: Opaque cursor positioned after the last message on this page. Pass it back as the cursor query parameter. Null on the final page.
      - `hasMore` boolean, required: Whether more messages exist beyond this page.
    - CursorPaginationMetaDTO
      - `limit` integer, required: Number of items per page.
      - `nextCursor` string, nullable, required: Opaque cursor for the next page. Pass it back as the cursor query parameter. Null when there is nothing further.
      - `hasMore` boolean, required: Whether more messages exist beyond this page.

## Other responses

- `400`: Invalid deviceIds, smsBatchId, direction, status, from, to, order, or cursor value. Unknown filter values fail rather than silently applying no filter.
- `401`: Missing, invalid, or revoked API key.
- `404`: A deviceIds entry or the smsBatchId is not on your account.

---

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