Skip to content
WaveSenda
Start free
Docs / Quickstart

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.

shell
export WAVESENDA_API_KEY="ws_live_..."
export WAVESENDA_URL="https://api.wavesenda.com/api/v1"
Test keys
A key beginning 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
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"}'
200 OK
{
  "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
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
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:

StatusMeaning
initialisingAccepted; the gateway is bringing the socket up.
awaiting_scanA QR or pairing code is waiting for the handset.
connectingCredentials accepted, handshake in progress.
connectedLinked. You can send and receive.
disconnectedThe socket dropped. Reconnects on its own by default.
logged_outUnlinked from the phone. Needs a fresh scan.
failedGave 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
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"
  }'
Always send an idempotency key
A retry after a timeout returns the original message instead of sending a second one. On WhatsApp a duplicate is not a tidy-up job — the recipient has already been notified twice, and duplicates are one of the fastest ways to earn a spam report.

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
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

TypeScript
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',
})
Python
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

Warm the number up
A brand-new number that sends two hundred messages on its first day is the exact signature WhatsApp bans for. Open a warm-up plan on the session, let the daily cap climb, and check /v1/sessions/{id}/health/ before a large send. Message people who asked to hear from you.
Quickstart · WaveSenda Docs