Skip to content
Beta — the Waasl API is in private beta. Endpoints marked Coming soon are designed but not live yet. Request early access

Messages

Send and read messages. Free-form messages need an open 24-hour WhatsApp window; outside it, send an approved template.

POST/v1/messagesBeta

The one call most integrations need. Address the recipient by channel identity; Waasl finds or creates the contact and the conversation for you.

  • Inside the 24-hour window you can send any kind.
  • Outside it (or to a brand-new contact) WhatsApp only accepts template.

Sending is asynchronous: the response is the stored message with status: queued. Follow delivery through the message.status_updated webhook.

Headers

Field Type Description
Idempotency-Key string A unique key (UUID recommended). Retrying with the same key returns the original result instead of acting twice. Kept for 24 hours.

Request body

Field Type Description
channel_id string Which number to send from. Optional when the workspace has one channel.
to required string Recipient identity (E.164 for WhatsApp).
contact_id string Alternative to to.
kind required “text” | “image” | “video” | “file” | “voice” | “template” | “location” | “interactive” | “reaction”
body string Text, or the caption for media.
media_id string From POST /media.
reply_to_id string Quote an earlier message.
template object
template.name string
template.language string
template.params string[] Values for {{1}}, {{2}}… in order.
template.header_media_id string For image/video/document headers (coming soon).
interactive object Coming soon.
interactive.type “buttons” | “list”
interactive.buttons object[]
location object Coming soon.
location.latitude number
location.longitude number
location.name string
location.address string
Terminal window
curl -X POST "https://api.waasl.io/v1/messages" \
-H "Authorization: Bearer $WAASL_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "ch_wa_7Yt2",
"to": "+96550001234",
"kind": "template",
"template": {
"name": "order_ready",
"language": "ar",
"params": [
"سارة",
"4821"
]
}
}'
Response 201 — Message accepted and queued
{
"id": "msg_Vb3kQ9xP",
"conversation_id": "string",
"direction": "in",
"kind": "text",
"body": "string",
"caption": "string",
"media_id": "string",
"filename": "string",
"mime": "string",
"size_bytes": 0,
"reply_to_id": "string",
"actor_kind": "contact",
"actor_id": "string",
"status": "queued",
"error": "Re-engagement message (131047)",
"created_at": "2026-10-01T08:15:00Z"
}

Errors: 409 The resource’s state doesn’t allow this · 422 The request body is invalid · 429 Too many requests

GET/v1/messages/{message_id}Beta

Includes the latest delivery status and, for failures, Meta’s error.

Path parameters

Field Type Description
message_id required string
Terminal window
curl "https://api.waasl.io/v1/messages/msg_Vb3kQ9xP" \
-H "Authorization: Bearer $WAASL_API_KEY"
Response 200 — The message
{
"id": "msg_Vb3kQ9xP",
"conversation_id": "string",
"direction": "in",
"kind": "text",
"body": "string",
"caption": "string",
"media_id": "string",
"filename": "string",
"mime": "string",
"size_bytes": 0,
"reply_to_id": "string",
"actor_kind": "contact",
"actor_id": "string",
"status": "queued",
"error": "Re-engagement message (131047)",
"created_at": "2026-10-01T08:15:00Z"
}

Errors: 404 Not found in this workspace

GET/v1/conversations/{conversation_id}/messagesAvailable

Each page is oldest-first; the first page holds the newest messages and cursor walks back in time.

Path parameters

Field Type Description
conversation_id required string

Query parameters

Field Type Description
cursor string The next_cursor from the previous page.
Terminal window
curl "https://api.waasl.io/v1/conversations/cv_3PzA91/messages" \
-H "Authorization: Bearer $WAASL_API_KEY"
Response 200 — A page of messages
{
"data": [
{
"id": "msg_Vb3kQ9xP",
"conversation_id": "string",
"direction": "in",
"kind": "text",
"body": "string",
"caption": "string",
"media_id": "string",
"filename": "string",
"mime": "string",
"size_bytes": 0,
"reply_to_id": "string",
"actor_kind": "contact",
"actor_id": "string",
"status": "queued",
"error": "Re-engagement message (131047)",
"created_at": "2026-10-01T08:15:00Z"
}
],
"next_cursor": "MjAyNi0xMC0wMVQwODoxNTowMC4wMDBafGN2XzNQekE5MQ",
"has_more": true
}
POST/v1/conversations/{conversation_id}/messagesAvailable

Sends into an existing conversation. Fails with 409 and a precise code when the conversation can’t take a message: window_closed, conversation_closed, contact_blocked or bot_in_control.

Path parameters

Field Type Description
conversation_id required string

Headers

Field Type Description
Idempotency-Key string A unique key (UUID recommended). Retrying with the same key returns the original result instead of acting twice. Kept for 24 hours.

Request body

Field Type Description
kind required “text” | “image” | “video” | “file” | “voice” | “template” | “location” | “interactive” | “reaction”
body string Text, or the caption for media.
media_id string From POST /media.
reply_to_id string Quote an earlier message.
template object
template.name string
template.language string
template.params string[] Values for {{1}}, {{2}}… in order.
template.header_media_id string For image/video/document headers (coming soon).
interactive object Coming soon.
interactive.type “buttons” | “list”
interactive.buttons object[]
location object Coming soon.
location.latitude number
location.longitude number
location.name string
location.address string
Terminal window
curl -X POST "https://api.waasl.io/v1/conversations/cv_3PzA91/messages" \
-H "Authorization: Bearer $WAASL_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"kind": "text",
"body": "Thanks Sara — your plan is renewed until 30 Oct ✅"
}'
Response 201 — Message accepted and queued
{
"id": "msg_Vb3kQ9xP",
"conversation_id": "string",
"direction": "in",
"kind": "text",
"body": "string",
"caption": "string",
"media_id": "string",
"filename": "string",
"mime": "string",
"size_bytes": 0,
"reply_to_id": "string",
"actor_kind": "contact",
"actor_id": "string",
"status": "queued",
"error": "Re-engagement message (131047)",
"created_at": "2026-10-01T08:15:00Z"
}

Errors: 409 The resource’s state doesn’t allow this · 422 The request body is invalid