Getting Started

From signup to your first sent message: create a channel, link a number by QR or pairing code, issue a Bearer token and call the REST API.

Updated getting-startedchannelsmessages

Wapito turns a WhatsApp number you already own into a REST API with webhooks. There are four things between you and a working integration: a channel (one linked number), its token, a linked phone, and a webhook so events reach you. This guide walks through all four in the order they happen. Nothing here needs Meta approval, a message template or a business verification — and nothing here is official either, which is worth reading about in the anti-ban guide before you point real traffic at a number you care about.

Before you start

You need a phone with WhatsApp installed and a number you can afford to lose. The free Sandbox plan gives you one channel, 150 sent messages a day and 1,000 API requests a month, with webhooks on, which is enough to build and test everything on this page. A card is not needed.

There is one base URL for everyone: https://api.wapito.com/v1. A sandbox channel uses the same host with lower limits; there is no separate sandbox environment and nothing to switch when you upgrade.

1. Create a channel

Sign in at wapito.com/app and choose New channel. Give it a name — only you see it; it is how the channel is labelled in the dashboard. Under Advanced you can pick the protocol engine. Leave it on GOWS unless a specific feature in the API reference says it needs NOWEB; GOWS is the default because it is the steadier of the two for everyday messaging.

Choose Create. The channel exists from that moment, with status created until a phone is linked, and the dialog moves to its second step: the token.

2. Copy the token

The token is shown once, right there in the dialog, and stays visible on the channel's API tab until you reload the page. It looks like wpt_ followed by forty letters and digits. Copy it into your secret store now: Wapito keeps only a hash, so after a reload the dashboard can show a masked preview and offer to rotate, but never the token itself.

Close the dialog and you land on the channel page with five tabs: Connect, Settings, API, Logs and Usage.

Every request authenticates with that one token as a Bearer header. The token is bound to the channel, which is why no request carries a channel id:

Authorization: Bearer wpt_9f2c4a7b1de35086c4b2e7a0f3d8c1b6a9e2f5d4

Read Authentication for what a bad or rotated token returns and how to keep the token out of logs and URLs.

Open the Connect tab. It opens on the pairing code, which is the recommended path: enter the phone number in international format and Wapito asks WhatsApp for an eight-character code that stays valid for about two minutes. On the phone go to Settings → Linked devices → Link a device, tap Link with phone number instead, and type the code.

If you would rather scan, the QR code is one link away on the same tab. It refreshes itself while you look at it; the panel switches on its own the moment the phone confirms.

You can also drive this step from the API instead of the dashboard — useful when the phone belongs to a customer you are onboarding remotely:

curl -X POST https://api.wapito.com/v1/channel/pairing-code \
  -H "Authorization: Bearer $WAPITO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"phone": "+15557654321"}'

The status moves from pairing (or qr) to connected. Watch it with GET /channel, or subscribe to the channel webhook event and stop polling — the dashboard itself reads the same state, so the two never disagree:

curl https://api.wapito.com/v1/channel \
  -H "Authorization: Bearer $WAPITO_TOKEN"
{
  "id": "ch_01JRQ8F4X9N2K7YB3C5V6W8H0T",
  "name": "Acme Support",
  "status": "connected",
  "phone": "15557654321",
  "engine": "gows",
  "plan": "sandbox",
  "settings": { "send_delay_ms": 1500, "typing_simulation": "auto", "auto_read": false, "reject_calls": true, "include_raw": false, "proxy": null },
  "webhooks_count": 0
}

4. Send your first message

Send a text to a number that already has a conversation with the linked phone — your own second number, or a colleague who messages you first. That matters more than it sounds: a brand-new channel writing to strangers is exactly what the cold-send guard exists to slow down, and a first test that trips a limit teaches the wrong lesson.

curl -X POST https://api.wapito.com/v1/messages/text \
  -H "Authorization: Bearer $WAPITO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"to": "+15551234567", "body": "Hello from Wapito 👋"}'

to accepts +E.164, bare digits, 15551234567@s.whatsapp.net, a group's @g.us id, an @lid or a Channel's @newsletter id. The response is the message object — the same shape you will later see as the data of a messages webhook event — with status: "sent". The call returns as soon as the message is on the channel's send queue, which spaces sends about a second and a half apart with a little jitter so the number behaves like a person typing. Delivery and read receipts arrive later as messages.status events, not in this response.

If the response is a 4xx, the body is always the same envelope and the code is what you branch on:

{
  "error": {
    "code": "channel_not_connected",
    "message": "The channel is not connected.",
    "details": { "status": "pairing" },
    "request_id": "req_01JRQ8F4X9N2K7YB3C5V6W8H0T"
  }
}

Every code is listed, with its cause and fix, under error codes.

5. Receive your first webhook

Register an HTTPS endpoint and choose the events you want. Start with messages and messages.status; add more later, or use * for everything:

curl -X POST https://api.wapito.com/v1/webhooks \
  -H "Authorization: Bearer $WAPITO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://hooks.example.com/wapito", "events": ["messages", "messages.status"]}'

The 201 response is the only place the signing secret (whsec_…) ever appears in full, so store it next to the token. Then fire a synthetic event at your endpoint with POST /webhooks/{id}/test — it reports the status code your server answered, the round-trip time and the exact X-Wapito-Signature header that was sent, so you can replay the verification locally before any real traffic arrives.

Now send yourself a message from another phone. Within a second or two your endpoint receives:

{
  "id": "evt_01JRQ8F4X9N2K7YB3C5V6W8H0T",
  "event": "messages",
  "channel_id": "ch_01JRQ8F4X9N2K7YB3C5V6W8H0T",
  "timestamp": 1789459200123,
  "api_version": "v1",
  "data": {
    "id": "false_15551234567@s.whatsapp.net_9F31A0C4D7E2B6081A55",
    "chat_id": "15551234567@s.whatsapp.net",
    "from": "15551234567",
    "from_me": false,
    "type": "text",
    "text": { "body": "Hi! Got your message." }
  }
}

Answer with any 2xx quickly and do the real work afterwards; Wapito retries anything else on a back-off schedule. The webhooks guide has the full event list, the envelope, the signature check in Node, Python and PHP, and the retry table.

Where to go next

Try it on your own number

Create a channel, link a WhatsApp number by QR or pairing code, and call the API in a couple of minutes. The Sandbox plan is free and needs no card.