Zernio
Zernio
API Reference

Messages

Conversations

List conversationsGETSearch conversationsGETCreate conversationPOSTGet conversationGETUpdate conversation statusPUTMark a conversation as readPOSTHand a conversation to or from Meta Business AgentPOST

Messages

List messagesGETSend messagePOSTEdit messagePATCHDelete messageDELETEUpload media filePOSTResolve message attachmentGET

Reactions & Typing

Add reactionPOSTRemove reactionDELETESend typing indicatorPOST
Dashboard
llms.txtOpenAPI
OverviewPlatformsAPI ReferenceResources
Messages

List messages

Fetch messages for a specific conversation, with cursor-based pagination and ordering control.

Pagination: pass pagination.nextCursor from a prior response back as the cursor query param to fetch the next page. The cursor is opaque; do not parse or construct it client-side.

Sort order: defaults to asc (oldest first, chat style). For the "show me the latest messages" pattern, pass ?sortOrder=desc&limit=N. X, Instagram, Telegram, WhatsApp and Reddit honor the requested order from the local message store. For Facebook and Bluesky, the upstream APIs only return newest-first and have no order parameter, so sort order is best-effort and only reverses items within a single page (pages still walk newest→oldest). The response field sortOrderApplied tells you what was actually applied.

Reddit threads are paginated client-side because Reddit's API has no per-thread cursor. Very long threads may be upstream-truncated by Reddit's inbox/sent windows (~100 most-recent items each); this is a Reddit platform limitation.

Instagram and Facebook conversations include history from before the account was connected, replayed from Meta. That replay covers the 500 most recent messages per conversation: a longer thread keeps its newest 500 and older messages are not retrievable. Messages that arrived after the account was connected are unaffected. Replayed messages are stored as already read and emit no webhooks.

X limitation: X's encrypted "X Chat" messages are not accessible via the API. Conversations where the other participant uses encrypted X Chat may only show your outgoing messages. See the list conversations endpoint for more details.

This endpoint is read-only and does NOT mark messages as read or send read receipts. To mark a conversation read (and send WhatsApp blue ticks on eligible accounts), call POST /v1/inbox/conversations/{conversationId}/read.


GET
/v1/inbox/conversations/{conversationId}/messages

Authorization

bearerAuth
AuthorizationBearer <token>

API key authentication: send your Zernio API key in the Authorization header, prefixed with Bearer.

In: header

Path Parameters

conversationId*string

Opaque conversation identifier, accepted verbatim from the list endpoint or from the conversationId on inbox webhooks. Format not to be assumed.

Query Parameters

accountId*string

Account ID

limit?integer

Number of messages to return per page. Default 100, max 100.

Range1 <= value <= 100
Default100
cursor?string

Opaque pagination cursor. Pass pagination.nextCursor from a prior response verbatim: a cursor we cannot parse returns 400 rather than silently restarting from the first page.

sortOrder?string

Order of returned messages. Default asc (oldest first, chat style). X, Instagram, Telegram, WhatsApp and Reddit honor this order across cursor pages. For Facebook and Bluesky, only intra-page ordering is affected. Pages always walk newest→oldest. See sortOrderApplied in the response.

Default"asc"

Value in

  • "asc"
  • "desc"

Response Body

application/json

application/json

application/json

application/json

application/json

{  "status": "string",  "pagination": {    "hasMore": true,    "nextCursor": "string"  },  "sortOrderApplied": "asc",  "messages": [    {      "id": "string",      "conversationId": "string",      "accountId": "string",      "platform": "string",      "message": "string",      "senderId": "string",      "senderName": "string",      "senderVerifiedType": "blue",      "direction": "incoming",      "createdAt": "2019-08-24T14:15:22Z",      "attachments": [        {          "id": "string",          "type": "image",          "originalType": "string",          "url": "string",          "refreshUrl": "string",          "filename": "string",          "previewUrl": "string"        }      ],      "subject": "string",      "storyReply": true,      "isStoryMention": true,      "isEdited": true,      "editedAt": "2019-08-24T14:15:22Z",      "editCount": 0,      "editHistory": [        {          "text": "string",          "attachments": [            {              "type": "string",              "url": "string",              "payload": {}            }          ],          "editedAt": "2019-08-24T14:15:22Z"        }      ],      "isDeleted": true,      "deletedAt": "2019-08-24T14:15:22Z",      "deliveryStatus": "sent",      "deliveredAt": "2019-08-24T14:15:22Z",      "readAt": "2019-08-24T14:15:22Z",      "sentAt": "2019-08-24T14:15:22Z",      "deliveryError": {        "code": 0,        "title": "string",        "message": "string"      },      "reactions": [        {          "emoji": "string",          "fromMe": true,          "reactedAt": "2019-08-24T14:15:22Z"        }      ],      "metadata": {},      "sentVia": "human"    }  ],  "lastUpdated": "2019-08-24T14:15:22Z"}
Was this page helpful?

Hand a conversation to or from Meta Business Agent

WhatsApp only, on numbers with Meta Business Agent enabled. Wraps Meta's thread control: - `release`: hand the conversation back to the agent so it resumes answering. You must currently hold control (sending any message takes it implicitly). - `take`: take control before sending anything, so the agent stops replying while an operator reads the thread. Meta accepts this only from the business configured as the number's escalation partner; other apps take control by sending a message. - `pass`: transfer control to the number's configured escalation partner, or to the agent with `target: ai_agent`. Meta's Cloud API currently rejects it ("Pass action is not supported", verified 2026-09-08); use `release` to hand a thread back to the agent. The conversation's `threadControl` follows the result; a `conversation.control_changed` webhook fires when Meta later reports the change.

Send message

Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp per-recipient rate limit: WhatsApp caps how many messages you may send to the same recipient in a short window and rejects the excess with error code `131056` ("Too many messages sent to this recipient"). Pace sends to a single recipient at roughly 10 per minute; bursts above that return a `400` with code `131056`. Sends to other recipients are unaffected, so parallelise across recipients rather than flooding one. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ "elements": [{ "name": ..., "language": ..., "components": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the "request succeeded but the response was lost" case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation's messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.