Skip to main content

List Message Logs

Lists the message logs — sent and received — of the WhatsApp number tied to your API key, newest first, with pagination and filters. For the full detail of a single message, use GET /v1/messages/{messageId}.
The dashboard Logs & Analytics page is the visual counterpart of this endpoint — the same rows, filters, and statuses you see there are what this endpoint returns as JSON.

Headers

  • x-api-key: ps_... (or x-api-key-id: <api_key_id>) — a number-scoped key. Tenant-scoped keys receive 403.

Query parameters

24h service window: WhatsApp opens a 24-hour customer-service window every time a contact messages you. serviceWindowOpenAtSend records the state of that window at the moment each outbound message was accepted: true means it was a reply inside an open window and was sent immediately; false means it was a “cold” send outside the window — paced by the anti-block engine on Pilot Status web numbers, and requiring an approved template on Meta Cloud API numbers; null means the window was not computed (inbound rows, group/channel destinations). Filter with window=open / window=closed.

Examples

Response (200)

Response fields

Retention: rows respect the number’s PII retention mode. On RELAY_ONLY numbers the rows are returned redacted (content: null).

origin — which rail the message left by

origin: null does not mean “inbound”. Read direction for that. A null on an OUT row means the send carried a source we do not map to a public tag; treat it as “unclassified outbound”, not as received traffic, or a billing report will silently under-count your own sends.
The set grows. Treat a value you do not recognise as “unclassified outbound”, not as an error.

Outbound rows with no send request

Three kinds of OUT row were not sent by Pilot Status, so there is no send request behind them: APP, LAYER, and CHATWOOT from a native WhatsApp Cloud inbox. On these rows:
  • correlationId, template, serviceWindowOpenAtSend, errorCode and errorMessage are null;
  • GET /v1/messages/{messageId} answers 404 — the list row is all there is;
  • status follows the statuses Meta reports: SENT, DELIVERED, READ or FAILED;
  • the message does not count toward your plan’s message usage;
  • on a number whose PII retention mode redacts the row, to and content are null and redacted: true is added, as on any other row.
A CHATWOOT row from an API mirror inbox is a regular send: it has a correlationId and full detail. On LAYER rows and native-inbox CHATWOOT rows, content is what the Graph API request carried: the text body, a media caption, or the body text of an interactive message. Three types get a short generated text instead:
  • a template reads Template: <name> — the rendered body is not stored, and template stays null;
  • a location reads Location: <latitude>, <longitude>, followed by its name and address when the request had them;
  • contacts read Contacts: <names>.
Audio and stickers have content: null. A native-inbox CHATWOOT row:
The status, direction=out, templateId and window filters leave these rows out. They return only messages that had a send request, so APP, LAYER and native-inbox CHATWOOT rows never match them, even though they are OUT. To get these rows, list without those filters (startDate, endDate and a phone-number search keep them) and read direction and origin.
LAYER rows, and CHATWOOT rows from a native inbox, are recorded only from the moment Pilot Status started recording layer sends for the number. Earlier sends are not backfilled. What is and is not recorded: Meta layer → Sends are recorded in Logs.

Common errors