List messages in a chat
GEThttps://api.wapito.com/v1/messages/list/{chat_id}
Send a channel token on every request: Authorization: Bearer wpt_YOUR_TOKEN
Returns a page of messages from one chat, newest first, with filters for direction and time window. History comes from the engine store, so a channel only sees messages received or sent since it connected, and only when engine storage is enabled. Treat this as a convenience for recent context, not as an archive: keep your own copy of anything you need permanently.
Parameters
| Name | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
chat_id | path | string | Required | Chat to read, in any accepted recipient form. | 15551234567@s.whatsapp.net |
count | query | integer | Optional | Page size, 1-500. Defaults to 100.1–500 · default 100 | 50 |
offset | query | integer | Optional | Items to skip before the first returned item. Use it with `count` to page.min 0 · default 0 | 0 |
from_me | query | boolean | Optional | Return only outbound (`true`) or only inbound (`false`) messages. | true |
time_from | query | integer | Optional | Only messages at or after this Unix epoch millisecond timestamp. | 1789372800000 |
time_to | query | integer | Optional | Only messages at or before this Unix epoch millisecond timestamp. | 1789459200000 |
Responses
200
A page of messages.
| Field | Type | Required | Description |
|---|---|---|---|
count | integer | Required | Number of items in this page. |
messages | array of object | Required | Page of results. |
audio | object | Optional | Media attached to a message. `link` is a signed Wapito URL, not a WhatsApp CDN URL. |
caption | string | null | Required | Caption sent alongside the media. |
error | string | Optional | Set to `unavailable` when the media could not be copied before it expired on the engine.one of unavailable |
file_name | string | null | Required | Original file name when the sender supplied one. |
file_size | integer | null | Required | Size in bytes. |
id | string | null | Required | Wapito media id (`med_` + ULID), or `null` when the copy from the engine failed. |
link | string | null | Required | Signed `/v1/media/{id}?exp&sig` URL, valid 24 h on sandbox and 7 days on premium. |
mime_type | string | Required | IANA media type reported by WhatsApp. |
chat_id | string | Required | Chat the message belongs to, as `@s.whatsapp.net`, `@g.us` or `@newsletter`. |
contact | object | Optional | Contact card payload of a `contact` message. |
vcard | string | Required | Raw vCard 3.0 text as WhatsApp stores it. |
context | object | Optional | Reply, forward and mention context for a message. |
forwarded | boolean | Required | Whether WhatsApp marked the message as forwarded. |
mentions | array of string | Required | Phone numbers mentioned with @ in the body. |
quoted_author | string | null | Required | Sender of the quoted message. |
quoted_id | string | null | Required | Id of the quoted message, when this message is a reply. |
document | object | Optional | Media attached to a message. `link` is a signed Wapito URL, not a WhatsApp CDN URL. |
caption | string | null | Required | Caption sent alongside the media. |
error | string | Optional | Set to `unavailable` when the media could not be copied before it expired on the engine.one of unavailable |
file_name | string | null | Required | Original file name when the sender supplied one. |
file_size | integer | null | Required | Size in bytes. |
id | string | null | Required | Wapito media id (`med_` + ULID), or `null` when the copy from the engine failed. |
link | string | null | Required | Signed `/v1/media/{id}?exp&sig` URL, valid 24 h on sandbox and 7 days on premium. |
mime_type | string | Required | IANA media type reported by WhatsApp. |
from | string | null | Required | Sender in digits for direct chats, or the group id for group chats. `null` when only a LID is known. |
from_lid | string | null | Required | Sender LID when WhatsApp addressed the message by LID rather than phone number. |
from_me | boolean | Required | True when the channel sent the message, false when it received it. |
from_name | string | null | Required | Push name of the sender as WhatsApp reports it. |
id | string | Required | Engine message id, unique within the channel. |
image | object | Optional | Media attached to a message. `link` is a signed Wapito URL, not a WhatsApp CDN URL. |
caption | string | null | Required | Caption sent alongside the media. |
error | string | Optional | Set to `unavailable` when the media could not be copied before it expired on the engine.one of unavailable |
file_name | string | null | Required | Original file name when the sender supplied one. |
file_size | integer | null | Required | Size in bytes. |
id | string | null | Required | Wapito media id (`med_` + ULID), or `null` when the copy from the engine failed. |
link | string | null | Required | Signed `/v1/media/{id}?exp&sig` URL, valid 24 h on sandbox and 7 days on premium. |
mime_type | string | Required | IANA media type reported by WhatsApp. |
location | object | Optional | Location payload of a `location` message. |
address | string | null | Required | Street address shown under the place name. |
latitude | number | Required | Decimal degrees. |
longitude | number | Required | Decimal degrees. |
name | string | null | Required | Place name shown in the bubble. |
participant | string | null | Required | In group chats, the individual sender behind `from`. |
poll | object | Optional | Poll payload of a `poll` message. Votes arrive later as `polls` webhook events. |
multiple | boolean | Required | Whether voters may select more than one option. |
options | array of string | Required | Answer options in display order. |
title | string | Required | Poll question. |
raw | object | Optional | Untouched engine payload. Present only while `settings.include_raw` is enabled. |
source | string | Required | `app` when the message came from the linked phone, `api` when Wapito sent it.one of app, api |
status | string | Optional | Delivery state of an outbound message.one of failed, pending, sent, delivered, read, played |
sticker | object | Optional | Media attached to a message. `link` is a signed Wapito URL, not a WhatsApp CDN URL. |
caption | string | null | Required | Caption sent alongside the media. |
error | string | Optional | Set to `unavailable` when the media could not be copied before it expired on the engine.one of unavailable |
file_name | string | null | Required | Original file name when the sender supplied one. |
file_size | integer | null | Required | Size in bytes. |
id | string | null | Required | Wapito media id (`med_` + ULID), or `null` when the copy from the engine failed. |
link | string | null | Required | Signed `/v1/media/{id}?exp&sig` URL, valid 24 h on sandbox and 7 days on premium. |
mime_type | string | Required | IANA media type reported by WhatsApp. |
text | object | Optional | Body of a `text` message. |
body | string | Required | Message text, WhatsApp markdown allowed. |
timestamp | integer | Required | Unix epoch milliseconds. |
type | string | Required | Message kind; selects which payload field is populated.one of text, image, video, audio, voice, document, sticker, location, contact, poll, reaction, unknown |
video | object | Optional | Media attached to a message. `link` is a signed Wapito URL, not a WhatsApp CDN URL. |
caption | string | null | Required | Caption sent alongside the media. |
error | string | Optional | Set to `unavailable` when the media could not be copied before it expired on the engine.one of unavailable |
file_name | string | null | Required | Original file name when the sender supplied one. |
file_size | integer | null | Required | Size in bytes. |
id | string | null | Required | Wapito media id (`med_` + ULID), or `null` when the copy from the engine failed. |
link | string | null | Required | Signed `/v1/media/{id}?exp&sig` URL, valid 24 h on sandbox and 7 days on premium. |
mime_type | string | Required | IANA media type reported by WhatsApp. |
voice | object | Optional | Media attached to a message. `link` is a signed Wapito URL, not a WhatsApp CDN URL. |
caption | string | null | Required | Caption sent alongside the media. |
error | string | Optional | Set to `unavailable` when the media could not be copied before it expired on the engine.one of unavailable |
file_name | string | null | Required | Original file name when the sender supplied one. |
file_size | integer | null | Required | Size in bytes. |
id | string | null | Required | Wapito media id (`med_` + ULID), or `null` when the copy from the engine failed. |
link | string | null | Required | Signed `/v1/media/{id}?exp&sig` URL, valid 24 h on sandbox and 7 days on premium. |
mime_type | string | Required | IANA media type reported by WhatsApp. |
offset | integer | Required | Offset this page started at. |
total | integer | null | Required | Total matches when the engine can count them, otherwise `null`. |
{
"count": 2,
"messages": [
{
"chat_id": "15551234567@s.whatsapp.net",
"context": {
"forwarded": false,
"mentions": [],
"quoted_author": null,
"quoted_id": null
},
"from": "15551234567",
"from_lid": "187264518273645@lid",
"from_me": false,
"from_name": "Dana Whitfield",
"id": "false_15551234567@s.whatsapp.net_9F31A0C4D7E2B6081A55",
"image": {
"caption": "Here is the receipt you asked for",
"file_name": "receipt.jpg",
"file_size": 184213,
"id": "med_01JRQ8F4X9N2K7YB3C5V6W8H0T",
"link": "https://api.wapito.com/v1/media/med_01JRQ8F4X9N2K7YB3C5V6W8H0T?exp=1790064121&sig=8f2c1d94b6a70e35",
"mime_type": "image/jpeg"
},
"participant": null,
"source": "app",
"status": "delivered",
"timestamp": 1789459321000,
"type": "image"
},
{
"chat_id": "15551234567@s.whatsapp.net",
"context": {
"forwarded": false,
"mentions": [],
"quoted_author": null,
"quoted_id": null
},
"from": "15557654321",
"from_lid": null,
"from_me": true,
"from_name": "Acme Support",
"id": "true_15551234567@s.whatsapp.net_3EB0C767D82B0A1E4F2B",
"participant": null,
"source": "api",
"status": "sent",
"text": {
"body": "Your order #4182 has shipped. Track it here: https://acme.example/t/4182"
},
"timestamp": 1789459200000,
"type": "text"
}
],
"offset": 0,
"total": 184
}400
The request body or query string is malformed, or the recipient cannot be parsed into a WhatsApp id.
Show 2 example bodies
invalid_recipient — `to` is not a dialable number or valid WhatsApp id
{
"error": {
"code": "invalid_recipient",
"details": {
"to": "+1555"
},
"message": "The recipient is not a valid WhatsApp address.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}invalid_request — schema validation failed
{
"error": {
"code": "invalid_request",
"details": {
"issues": [
{
"message": "Array must contain at least 2 element(s)",
"path": "body.options"
}
]
},
"message": "The request payload failed validation.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}401
The channel token is missing, malformed, revoked or belongs to a deleted channel.
Show 2 example bodies
token_revoked — the token was rotated in the dashboard
{
"error": {
"code": "token_revoked",
"message": "This channel token has been revoked.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}unauthorized — no or unusable Bearer token
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid channel token.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}403
The token is valid but the channel may not perform this action right now.
Show 2 example bodies
channel_locked — billing lapsed or the channel was locked by an operator
{
"error": {
"code": "channel_locked",
"details": {
"reason": "plan_required"
},
"message": "This channel is locked.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}forbidden — the channel does not own the target object
{
"error": {
"code": "forbidden",
"message": "You are not allowed to perform this action.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}404
The addressed object does not exist, or the number is not on WhatsApp.
Show 3 example bodies
message_not_found — the message id is unknown to the engine
{
"error": {
"code": "message_not_found",
"message": "The requested message does not exist.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}not_found — unknown id
{
"error": {
"code": "not_found",
"message": "The requested resource does not exist.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}not_on_whatsapp — the number is not registered
{
"error": {
"code": "not_on_whatsapp",
"message": "This number is not registered on WhatsApp.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}409
The channel is in the wrong state for this action, or the account type does not support it.
Show 3 example bodies
business_account_required — labels need WhatsApp Business
{
"error": {
"code": "business_account_required",
"message": "This action requires a WhatsApp Business account.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}channel_not_connected — link the number first
{
"error": {
"code": "channel_not_connected",
"details": {
"status": "qr"
},
"message": "The channel is not connected.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}channel_not_in_qr_state — no QR available while the session boots
{
"error": {
"code": "channel_not_in_qr_state",
"details": {
"status": "created"
},
"message": "The channel is not waiting for a QR scan.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}429
A rate limit, a plan quota or one of the anti-ban guards stopped the request. Every one of these is safe to retry later; read `Retry-After` when present.
Show 5 example bodies
cold_send_limit — too many first messages to new recipients this hour
{
"error": {
"code": "cold_send_limit",
"details": {
"resets_at": "2026-09-15T09:00:00.000Z",
"window_cap": 20
},
"message": "The hourly limit for messages to new recipients is reached.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}quota_exceeded — plan quota for the day or month
{
"error": {
"code": "quota_exceeded",
"details": {
"quota": "sent",
"resets_at": "2026-09-16T00:00:00.000Z",
"used": 150
},
"message": "The plan quota for this resource is exhausted.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}rate_limited — per-minute API rate limit
{
"error": {
"code": "rate_limited",
"details": {
"retry_after": 12
},
"message": "Too many requests.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}send_rate_limited — the send queue did not drain within 20 s
{
"error": {
"code": "send_rate_limited",
"details": {
"retry_after": 5
},
"message": "The send queue for this channel is saturated.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}warmup_limit — the warm-up ladder cap for today
{
"error": {
"code": "warmup_limit",
"details": {
"cap": 200,
"day": 2
},
"message": "The warm-up limit for this channel is reached.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}500
Something went wrong inside Wapito. Quote `request_id` when reporting it.
Show the example body
internal_error — unexpected failure
{
"error": {
"code": "internal_error",
"message": "Something went wrong on our side.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}502
The engine answered with an error Wapito could not translate into a more specific code.
Show the example body
engine_error — unexpected engine failure
{
"error": {
"code": "engine_error",
"details": {
"engine": "gows",
"status": 500
},
"message": "The WhatsApp engine returned an error.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}503
The engine session is not reachable. Retry with backoff.
Show the example body
engine_unavailable — engine down or restarting
{
"error": {
"code": "engine_unavailable",
"details": {
"engine": "gows"
},
"message": "The WhatsApp engine is unavailable.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}504
The engine did not answer before the upstream timeout.
Show the example body
engine_timeout — no answer within the deadline
{
"error": {
"code": "engine_timeout",
"details": {
"timeout_ms": 20000
},
"message": "The WhatsApp engine did not respond in time.",
"request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
}
}Errors
Code examples
import requests
url = "https://api.wapito.com/v1/messages/list/15551234567@s.whatsapp.net"
querystring = {"count":"50","offset":"0","from_me":"true","time_from":"1789372800000","time_to":"1789459200000"}
headers = {"Authorization": "Bearer wpt_YOUR_TOKEN"}
response = requests.get(url, headers=headers, params=querystring)
print(response.json())Related
Other endpoints in this group
Glossary
Reference
Try it on your own number
Create a channel, link a WhatsApp number by QR or pairing code, and call the API in a couple of minutes. The Sandbox plan is free and needs no card.