API Reference
Plain REST. One token per WhatsApp line. Every URL is fixed — the token tells us which line your request applies to.
https://wappfly.com/api
Authentication
Every API call needs your session's API token in a request header. One token per WhatsApp line — you get it from the dashboard after pairing a number.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
— click "Show token" next to a connected line. Treat it like a password: anyone with the token can send from that number.
|
Quick test with curl — replace YourAPIToken with the real value:
curl https://wappfly.com/api/me \
-H "X-API-Token: YourAPIToken"
Rotating one session's token in the dashboard doesn't touch the others. If you suspect a leak, rotate immediately and update your automation tool's saved value.
Errors & quota
Every error response is JSON with an error field describing what went wrong.
The HTTP status code tells you the category at a glance:
| Status | Meaning |
|---|---|
| 400 | Invalid request body — missing field, wrong type, or malformed JSON. |
| 401 | Missing or invalid X-API-Token header. |
| 402 | Quota exceeded. Upgrade your plan or wait for the period to reset. |
| 403 | Email not verified, or session is disconnected/banned. |
| 404 | Resource not found — wrong URL or the referenced message/JID doesn't exist. |
Example error response:
{
"error": "Email not verified — confirm your email at /verify-pending before sending."
}
Quota
Every outbound send and every incoming message counts as 1 request.
Reads (/me, /status, /chats, /history, /messages/recent)
and interactions (reactions, edits, deletes) are free.
Free plan: 50 requests on a rolling 30-day window. Paid plans reset monthly.
https://wappfly.com/api/messages/send
Send a text message
Plain text. JID format: <digits>@s.whatsapp.net for users, <id>@g.us for groups.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"text": "Hello from Wappfly"
}
{
"queued": true,
"msg_id": "BD9043CF84A700B5"
}
https://wappfly.com/api/messages/image
Send an image
Base64-encoded image bytes + optional caption.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"file": "<base64 image bytes>",
"caption": "Optional caption",
"mimetype": "image/jpeg"
}
{
"queued": true,
"msg_id": "A85C9CADE68547F4"
}
https://wappfly.com/api/messages/document
Send a document
Any file (PDF, DOCX, ZIP, …). filename is what WhatsApp shows; mimetype determines the icon.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"file": "<base64 file bytes>",
"filename": "invoice.pdf",
"mimetype": "application/pdf",
"caption": "Optional caption"
}
{
"queued": true,
"msg_id": "0D62C99DED30E849"
}
https://wappfly.com/api/messages/video
Send a video
MP4 / WebM. Optional caption.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"file": "<base64 video bytes>",
"caption": "Optional caption",
"mimetype": "video/mp4"
}
{
"queued": true,
"msg_id": "7F1A2BB3C4D5E6F7"
}
https://wappfly.com/api/messages/audio
Send a voice note
OGG Opus is the safest bet; other codecs may not show as a voice note.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"file": "<base64 audio bytes>",
"mimetype": "audio/ogg; codecs=opus"
}
{
"queued": true,
"msg_id": "2C8D9E0F1A2B3C4D"
}
https://wappfly.com/api/messages/reply
Reply to a message
Quotes the target message above your reply. quoted_msg_id is the id from the message you're replying to (find it in messageBody webhook or /api/messages/recent).
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"text": "Got it!",
"quoted_msg_id": "3EB06A40C80DF456A1B2"
}
{
"queued": true,
"msg_id": "7863E1D57F991481"
}
https://wappfly.com/api/messages/reaction
React to a message
Pass an emoji as emoji. Send an empty string to remove your reaction. Does not count against your quota.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"emoji": "👍",
"target_msg_id": "3EB06A40C80DF456A1B2"
}
{
"queued": true,
"msg_id": "112CD0C5AE906886"
}
https://wappfly.com/api/messages/edit
Edit your message
WhatsApp allows editing for ~15 minutes after sending. Does not count against your quota.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"text": "Fixed typo",
"target_msg_id": "BD9043CF84A700B5"
}
{
"queued": true,
"msg_id": "9810D9D042E25594"
}
https://wappfly.com/api/messages/delete
Delete for everyone
Removes the message from both ends. Does not count against your quota.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
| Content-Type |
application/json
The request body must be JSON. This header tells the server how to read it.
|
{
"to": "15551234567@s.whatsapp.net",
"target_msg_id": "BD9043CF84A700B5"
}
{
"queued": true,
"msg_id": "AFB6C87B7BE45D18"
}
https://wappfly.com/api/me
Who am I + quota
Returns the session this token belongs to and how much quota the owner has used. Free, no quota cost.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
{
"session": {
"id": 8,
"name": "sales",
"status": "connected",
"phone_jid": "15551234567:33@s.whatsapp.net",
"me": {
"id": "15551234567:33@s.whatsapp.net",
"name": "Your Business",
"lid": "265777475281011:33@lid"
}
},
"user": {
"id": 1,
"email": "you@example.com",
"plan": { "code": "starter", "name": "Starter" },
"quota": 5000,
"requests_used": 127,
"requests_left": 4873,
"quota_period_start": "2026-04-20 17:10:58",
"quota_period_resets": "2026-05-20T17:10:58+00:00"
}
}
https://wappfly.com/api/status
Connection status
Quick check that this line is still connected. Use it before sending if you're not sure.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
{
"id": 8,
"name": "sales",
"status": "connected",
"phone_jid": "15551234567:33@s.whatsapp.net",
"me": {
"id": "15551234567:33@s.whatsapp.net",
"name": "Your Business"
}
}
https://wappfly.com/api/chats
List chats
Recent conversations this session has seen (since it connected). Empty array until the first message in/out per chat.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
[
{
"jid": "15551234567@s.whatsapp.net",
"name": "Alice",
"is_group": 0,
"last_msg_at": "2026-05-20 17:19:21",
"unread": 0
}
]
https://wappfly.com/api/history?jid=&limit=
Chat history
Messages with a specific JID. Query: jid (required), limit (default 50, max 500). status walks queued → sending → sent → server_ack → delivery_ack → read.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
[
{
"msg_id": "BD9043CF84A700B5",
"from_me": 1,
"sender_jid": "15551234567@s.whatsapp.net",
"type": "text",
"body": "Hello from Wappfly",
"media_path": null,
"timestamp": "2026-05-20 17:19:21",
"status": "delivery_ack"
},
{
"msg_id": "3EB06A40C80DF456A1B2",
"from_me": 0,
"sender_jid": "905451552424@s.whatsapp.net",
"type": "text",
"body": "merhaba",
"media_path": null,
"timestamp": "2026-05-20 17:19:18",
"status": "received"
}
]
https://wappfly.com/api/messages/recent?limit=20
Recent inbox
Latest messages across all chats — handy for a live feed. limit default 20, max 100.
| Name | Value |
|---|---|
| X-API-Token |
YourAPIToken
Your per-session API token. You can reach it from your
dashboard
after you pair a WhatsApp number. Each session has its own token.
|
[
{
"id": 122,
"chat_jid": "15551234567@s.whatsapp.net",
"msg_id": "BD9043CF84A700B5",
"from_me": 1,
"sender_jid": null,
"type": "text",
"body": "Hello from Wappfly",
"timestamp": "2026-05-20 17:19:21",
"status": "delivery_ack"
},
{
"id": 121,
"chat_jid": "15551234567@s.whatsapp.net",
"msg_id": "3EB06A40C80DF456A1B2",
"from_me": 0,
"sender_jid": "15551234567@s.whatsapp.net",
"type": "text",
"body": "merhaba",
"timestamp": "2026-05-20 17:19:18",
"status": "received"
}
]
Webhooks
Set a per-session webhook URL from the dashboard. Wappfly POSTs inbound messages only there in real time — outbound echoes, delivery acks, and connection events are tracked internally but not forwarded (keeps automation flows quiet so they only fire when a real customer message arrives). Every payload uses the same envelope:
{
"event": "messages.received",
"timestamp": 1779285900,
"session": { "id": 8 },
"data": { ... shape below }
}
Wappfly retries are not automatic — your endpoint should always 2xx. If you need durability, persist the payload first, then process.
messages.received
inbound message
Fired the first time an inbound message arrives on this session (de-duplicated by key.id).
cleanedSenderPn strips the device suffix and @s.whatsapp.net so you can match on the bare phone number.
{
"event": "messages.received",
"timestamp": 1779285900,
"session": { "id": 8 },
"data": {
"messages": {
"key": {
"id": "3EB06A40C80DF456A1B2",
"fromMe": false,
"remoteJid": "15551234567@s.whatsapp.net",
"addressingMode": "pn",
"senderPn": "15551234567@s.whatsapp.net",
"cleanedSenderPn": "15551234567",
"senderLid": null
},
"messageBody": "merhaba",
"message": { "conversation": "merhaba" },
"messageTimestamp": 1779285895,
"pushName": "Alice"
}
}
}
For media (image / document / video / audio) messageBody holds the caption (or null),
and message carries the full Baileys payload — imageMessage, documentMessage, etc. —
with the original mimetype and a download URL you can re-fetch via the API.
n8n / Zapier / Make example
In an HTTP Request node, configure the call exactly like this:
- Method:
POST - URL:
https://wappfly.com/api/messages/send - Headers:
X-API-Token: YourAPITokenandContent-Type: application/json - Body (JSON):
{ "to": "15551234567@s.whatsapp.net", "text": "Hello" }
No SDK, no session name in the URL — the token already names the WhatsApp line. Grab the token from your dashboard.