From nothing to a delivered message
Five steps. You need a phone with WhatsApp installed and a terminal. There is no business verification, no template review and nothing to wait for.
1 · Get an API key
Create an organisation at the console, then open API keys and issue one. The secret is shown once, at creation — it is stored hashed, so if you lose it you rotate rather than recover it.
export WAVESENDA_API_KEY="ws_live_..." export WAVESENDA_URL="https://api.wavesenda.com/api/v1"
ws_test_ is bound to a sandbox session. Calls succeed, messages get ids and webhooks fire, but nothing leaves the building. Use one in CI.2 · Create a session
A session is one WhatsApp number. The name is a handle you choose — it can be used in place of the id everywhere in the API, which keeps your configuration readable.
curl -X POST "$WAVESENDA_URL/sessions/" \
-H "Authorization: Bearer $WAVESENDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "support", "label": "Support line", "login_method": "qr"}'{
"id": "8f14e45f-ceea-467a-9c1e-9d1a2b3c4d5e",
"name": "support",
"status": "initialising",
"phone_number": "",
"login_method": "qr"
}3 · Link the number
Ask the gateway to open a socket. The session moves to awaiting_scan and a QR code is produced; it expires after about a minute and is replaced automatically until someone scans it.
curl -X POST "$WAVESENDA_URL/sessions/support/connect/" \ -H "Authorization: Bearer $WAVESENDA_API_KEY"
The console renders the code for you under the session — open it, and on the phone go to WhatsApp → Settings → Linked devices → Link a device. If the handset cannot scan, request a pairing code instead and type it on the phone:
curl -X POST "$WAVESENDA_URL/sessions/support/pairing-code/" \
-H "Authorization: Bearer $WAVESENDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phone_number": "+237670000000"}'Poll the session, or subscribe to session.connected, until the status settles:
| Status | Meaning |
|---|---|
initialising | Accepted; the gateway is bringing the socket up. |
awaiting_scan | A QR or pairing code is waiting for the handset. |
connecting | Credentials accepted, handshake in progress. |
connected | Linked. You can send and receive. |
disconnected | The socket dropped. Reconnects on its own by default. |
logged_out | Unlinked from the phone. Needs a fresh scan. |
failed | Gave up; see last_error. |
4 · Send a message
Sending is asynchronous by default: the call returns as soon as the message is queued on the session. Pass wait: true to block briefly for the WhatsApp id instead.
curl -X POST "$WAVESENDA_URL/messages/send/" \
-H "Authorization: Bearer $WAVESENDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"session": "support",
"to": "+237670000000",
"text": "Your order is on its way.",
"idempotency_key": "order-1042-dispatched"
}'5 · Receive the reply
Inbound messages arrive as webhooks. Point one at a URL you control and subscribe it to the events you actually want — an endpoint with no events filter gets the full firehose, acks included.
curl -X POST "$WAVESENDA_URL/webhooks/" \
-H "Authorization: Bearer $WAVESENDA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/wavesenda",
"events": ["message.received", "session.disconnected"]
}'The response includes a signing secret, returned once. Verify every delivery with it — see webhooks.
The same thing, in an SDK
import { WaveSenda } from '@kunshort/wavesenda'
const wa = new WaveSenda({ apiKey: process.env.WAVESENDA_API_KEY! })
await wa.sessions.create({ name: 'support', label: 'Support line' })
await wa.messages.send({
session: 'support',
to: '+237670000000',
text: 'Your order is on its way.',
idempotencyKey: 'order-1042-dispatched',
})from wavesenda import WaveSenda
wa = WaveSenda(api_key=os.environ["WAVESENDA_API_KEY"])
wa.sessions.create("support", label="Support line")
wa.messages.send(
session="support",
to="+237670000000",
text="Your order is on its way.",
idempotency_key="order-1042-dispatched",
)Before you send to anyone real
/v1/sessions/{id}/health/ before a large send. Message people who asked to hear from you.