Quickstart
This guide takes you from zero to a delivered WhatsApp message and a webhook on your server.
-
Create an API key
In the Waasl app open Settings → Developers → API keys and create a key. Pick the scopes you need — for this guide
messages:writeandcontacts:read. The full key is shown once; store it in your secret manager.Terminal window export WAASL_API_KEY="wsl_test_your_key_here" -
Check the key
Terminal window curl https://api.waasl.io/v1/me -H "Authorization: Bearer $WAASL_API_KEY"const res = await fetch("https://api.waasl.io/v1/me", {headers: { Authorization: `Bearer ${process.env.WAASL_API_KEY}` },});console.log(await res.json());import os, requestsr = requests.get("https://api.waasl.io/v1/me",headers={"Authorization": f"Bearer {os.environ['WAASL_API_KEY']}"})print(r.json()){ "workspace_id": "ws_26N2SaWtMR", "workspace_name": "Diet Station", "environment": "test","key_prefix": "wsl_test_yo", "scopes": ["messages:write", "contacts:read"] } -
Find your channel
Terminal window curl https://api.waasl.io/v1/channels -H "Authorization: Bearer $WAASL_API_KEY"Note the
idof your WhatsApp channel, e.g.ch_wa_7Yt2. -
Send a template message
A new contact hasn’t written to you in the last 24 hours, so WhatsApp only accepts an approved template. Waasl creates the contact and conversation for you.
Terminal window curl -X POST https://api.waasl.io/v1/messages \-H "Authorization: Bearer $WAASL_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-d '{"channel_id": "ch_wa_7Yt2","to": "+96550001234","kind": "template","template": { "name": "order_ready", "language": "ar", "params": ["سارة", "4821"] }}'const res = await fetch("https://api.waasl.io/v1/messages", {method: "POST",headers: {Authorization: `Bearer ${process.env.WAASL_API_KEY}`,"Content-Type": "application/json","Idempotency-Key": crypto.randomUUID(),},body: JSON.stringify({channel_id: "ch_wa_7Yt2",to: "+96550001234",kind: "template",template: { name: "order_ready", language: "ar", params: ["سارة", "4821"] },}),});const message = await res.json();console.log(message.id, message.status); // msg_Vb3kQ9xP queuedimport os, uuid, requestsr = requests.post("https://api.waasl.io/v1/messages",headers={"Authorization": f"Bearer {os.environ['WAASL_API_KEY']}","Idempotency-Key": str(uuid.uuid4())},json={"channel_id": "ch_wa_7Yt2","to": "+96550001234","kind": "template","template": {"name": "order_ready", "language": "ar", "params": ["سارة", "4821"]},},)r.raise_for_status()print(r.json()["status"]) # queuedThe response is
201withstatus: "queued". Sending is asynchronous — delivery updates arrive as webhooks. -
Receive webhooks
Register an HTTPS endpoint for message events:
Terminal window curl -X POST https://api.waasl.io/v1/webhook-endpoints \-H "Authorization: Bearer $WAASL_API_KEY" \-H "Content-Type: application/json" \-d '{ "url": "https://example.com/waasl/webhook", "events": ["message.received", "message.status_updated"] }'Save the
secretfrom the response, then handle events — always verify the signature:import express from "express";import crypto from "node:crypto";const app = express();app.post("/waasl/webhook", express.raw({ type: "application/json" }), (req, res) => {const [t, v1] = req.header("Waasl-Signature").split(",").map((p) => p.split("=")[1]);const expected = crypto.createHmac("sha256", process.env.WAASL_WEBHOOK_SECRET).update(`${t}.${req.body}`).digest("hex");if (!crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))) return res.sendStatus(401);const event = JSON.parse(req.body);if (event.type === "message.status_updated") console.log(event.data.message.id, event.data.message.status);if (event.type === "message.received") console.log("New message:", event.data.message.body);res.sendStatus(200);});app.listen(3000); -
Reply inside the 24-hour window
When the customer answers, the window is open and you can send free-form messages into the conversation:
Terminal window curl -X POST https://api.waasl.io/v1/conversations/cv_3PzA91/messages \-H "Authorization: Bearer $WAASL_API_KEY" \-H "Content-Type: application/json" \-d '{ "kind": "text", "body": "شكراً سارة! طلبك بالطريق 🚚" }'
Next steps
Section titled “Next steps”- Learn the WhatsApp messaging rules — windows, templates and media.
- Make writes safe to retry with idempotency keys.
- Browse the full API reference.