# wasender.dev > WhatsApp API Gateway. Send and receive WhatsApp messages over plain HTTP, on a normal phone > number, with no Meta business verification and no per-message fees. Pricing is a flat subscription per connected number: the first number on an account is free, each additional number is $4/month. There is no message metering or credit balance. ## Authentication Every request carries a channel token — one per connected WhatsApp number: Authorization: Bearer wsk_sg_xxxxxxxxxxxxxxxxxxxxxxxx or, for clients that cannot set headers: ?token=wsk_sg_xxxxxxxxxxxxxxxxxxxxxxxx The token prefix encodes the region the number runs in (sg, use, usw, eu). Treat it as a password: it grants full control of that WhatsApp number. ## Base URL https://api.wasender.dev This resolves to the nearest edge automatically. Region-pinned hosts also exist (sg.api.wasender.dev, eu.api.wasender.dev, us.api.wasender.dev) for callers that want to skip geo-DNS. A channel is pinned to the region it was created in and its token only works there. ## Connecting a number 1. Create a channel in the dashboard at https://app.wasender.dev 2. GET /users/login/image — returns a PNG QR code 3. Scan it in WhatsApp: Settings -> Linked devices -> Link a device 4. Poll GET /health until status.text is "connected" QR codes rotate roughly every 20 seconds; re-request when one expires. After the first scan, credentials are stored and reconnects need no further scanning. ## Quick example curl -X POST https://api.wasender.dev/messages/text \ -H "Authorization: Bearer $WASENDER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"to": "61371989950", "body": "Hello from wasender.dev"}' Response: {"sent": true, "message": {"id": "...", "type": "text", "chat_id": "...", "from_me": true, "timestamp": 1735689600, "status": "pending"}} ## Things that will bite you if you do not read them - A 2xx means WhatsApp ACCEPTED the message, not that it was delivered. WhatsApp does not reject an unreachable recipient synchronously. Confirm real delivery via webhooks or GET /statuses/{MessageID}. A message resting at "sent" is not diagnostic on its own. - Recipients are phone numbers in international format WITHOUT a leading "+" (e.g. "61371989950"), or a full chat id ("61371989950@s.whatsapp.net", "1234...@g.us" for groups). - This service drives WhatsApp through an unofficial client — the same mechanism as WhatsApp Web. Meta does not sanction it. Use a dedicated number you can afford to lose. Sending first-contact messages to people who never opted in is the single most reliable way to get a number restricted. For regulated workloads, use Meta's official Cloud API instead. - Rate limits exist to protect the number from WhatsApp's anti-abuse systems, not to upsell you. Back off on 429 rather than retrying immediately. ## Error format Every error, on every endpoint: {"error": {"code": 429, "message": "Rate limit exceeded", "details": "...", "href": "https://docs.wasender.dev/errors#rate-limit", "support": "support@wasender.dev"}} Notable statuses: 401 unknown/revoked token, 402 free-tier limit or past-due subscription, 403 not permitted (often a group action needing admin), 429 rate limited (see Retry-After), 501 endpoint not implemented yet, 503 session reconnecting or waking — retry with backoff. ## Compatibility The API is request- and response-compatible with whapi.cloud for the endpoints listed below, so migrating is a change of base URL and token. Endpoints outside this document return 501. ## Endpoints ### Channel - GET /health — Check channel health - GET /settings — Get channel settings - PATCH /settings — Update channel settings - GET /users/login/image — Get the QR code to link this number - GET /users/profile — Get this number's own profile - PATCH /users/profile — Update this number's own profile - POST /users/logout — Unlink this number ### Messages - GET /messages/list — List messages across all chats - GET /messages/list/{ChatID} — List messages in one chat - POST /messages/text — Send a text message - POST /messages/image — Send an image - POST /messages/video — Send a video - POST /messages/audio — Send an audio file - POST /messages/voice — Send a voice note - POST /messages/document — Send a document - POST /messages/sticker — Send a sticker - POST /messages/location — Send a location - POST /messages/contact — Send a contact card - POST /messages/link_preview — Send a link with a rich preview - POST /messages/poll — Send a poll - GET /messages/{MessageID} — Get one message - POST /messages/{MessageID} — Mark a message as read - PUT /messages/{MessageID} — Edit a message - DELETE /messages/{MessageID} — Delete a message - PUT /messages/{MessageID}/reaction — React to a message - DELETE /messages/{MessageID}/reaction — Remove your reaction - PUT /messages/{MessageID}/star — Star or unstar a message - GET /statuses/{MessageID} — Get delivery and read receipts for a message ### Chats - GET /chats — List chats - GET /chats/{ChatID} — Get one chat - POST /chats/{ChatID} — Mark a chat as read - PATCH /chats/{ChatID} — Archive, pin or mute a chat - DELETE /chats/{ChatID} — Delete a chat ### Contacts - GET /contacts — List contacts - POST /contacts — Check whether numbers are on WhatsApp - GET /contacts/{ContactID} — Get one contact - GET /contacts/{ContactID}/profile — Get a contact's public profile ### Groups - GET /groups — List groups - POST /groups — Create a group - GET /groups/{GroupID} — Get one group - PATCH /groups/{GroupID} — Update a group's subject or description - DELETE /groups/{GroupID} — Leave a group - POST /groups/{GroupID}/participants — Add participants - DELETE /groups/{GroupID}/participants — Remove participants - GET /groups/{GroupID}/invite — Get the group invite link - DELETE /groups/{GroupID}/invite — Revoke and regenerate the invite link ### Media - GET /media — List uploaded media - POST /media — Upload a file - GET /media/{MediaID} — Download a media file - DELETE /media/{MediaID} — Delete a media file ### Presences - PUT /presences/me — Set your own online presence - PUT /presences/{EntryID} — Send a typing or recording indicator ## Full reference - OpenAPI 3.1 spec: https://docs.wasender.dev/openapi.yaml - Expanded version of this file: https://docs.wasender.dev/llms-full.txt - Interactive reference: https://docs.wasender.dev