Skip to main content

Get the WhatsApp activation code

WhatsApp verifies a landline by calling it and speaking a 6-digit code. These endpoints capture that call for you: you open a capture window on the line, ask WhatsApp to call, and read the code — transcribed from the call — from the API.
Requires a tenant-scoped key. With an OAuth / MCP token, the user must be an Owner or Admin (phone_lines:read) — 403 PERMISSION_DENIED otherwise. Every response that carries an activation is sent with Cache-Control: no-store: the code is a credential — whoever holds it can register a WhatsApp account on the line.

How it works

1

Open a request — before WhatsApp calls

POST /v1/phone-lines/{id}/activations. The line is reset at the carrier, so the recording of an earlier call can never be read as this one’s code, and a request opens in WAITING until pollDeadline — 5 minutes later. A call that arrives before this request exists is not captured.
2

Ask WhatsApp to call the line

Register the number in WhatsApp Business and, when asked how to receive the code, choose the phone call option (“Call me”). The line is a landline and does not receive SMS — waiting for an SMS only burns the window.
3

We capture and transcribe

We check the line about every 15 seconds while the window is open. When a recording appears we store it (CAPTURED), transcribe it and extract the code (TRANSCRIBED).
4

Read the code

Poll GET /v1/phone-lines/activations/{activationId} every few seconds — or listen for the phone_line.code_received webhook — and type code into WhatsApp.

Request a code

POST https://pilotstatus.com.br/v1/phone-lines/{id}/activations — no body. Answers 201 with the new request.
  • Allowed while the line is ACTIVE or PAYMENT_PENDING (including an ACTIVE line cancelled at period end). A SUSPENDED, RETURNED or CANCELED line gets 409 LINE_NOT_ACTIVE.
  • One waiting request per line. While a request is WAITING and its pollDeadline is still ahead, another POST answers 409 ACTIVATION_IN_PROGRESS — poll the one you have instead.
  • No limit on requests over time. Ask again whenever you need to (re-registering WhatsApp, a window that timed out); each request that opens increments the line’s activationCount.

Poll the request

GET https://pilotstatus.com.br/v1/phone-lines/activations/{activationId} returns { "activation": { … } }. A request of another workspace answers 404 ACTIVATION_NOT_FOUND, the same as one that does not exist.
Polling every few seconds is plenty: the status can only move after our next 15-second check of the line.

Statuses

Do not stop polling at the first status that is not WAITING. CAPTURED is also the in-between state while the transcription runs: keep polling while status is WAITING, or CAPTURED with failureReason: null. And TRANSCRIBED does not guarantee a code — check code. The transcription takes seconds: if a request stays CAPTURED with failureReason: null for more than a few minutes, treat it as failed — listen to the recording in the dashboard, or request a new code.
  • TIMED_OUT is recorded at the first check after pollDeadline, so it can show up to about 15 seconds after the deadline. That check closes the request without looking for a recording, so a call that lands in the last seconds of the window can be missed — ask WhatsApp to call as soon as the request is open. If a request still reads WAITING well after its pollDeadline, treat it as timed out: a new POST is already allowed, because the one-at-a-time rule only counts requests whose pollDeadline is still ahead.
  • failureReason is always one of the fixed values in the table (no_call_in_window, no_code_in_transcript, transcription_failed, audio_download_failed, audio_store_failed, poll_not_scheduled) or null. You can branch on it; treat an unknown value as a failure, since new ones may be added.
  • The code comes from speech-to-text. WhatsApp speaks the code during the call; we transcribe the recording and keep the 6-digit sequence heard most often. If WhatsApp rejects the code, listen to the recording in the dashboard.
  • The recording is dashboard-only. hasAudio: true only tells you there is one to play in Phone lines → the line. There is no audio endpoint in the public API, and the raw transcription is never returned.

Code history

GET https://pilotstatus.com.br/v1/phone-lines/{id}/activations returns the line’s requests, newest first, codes included: { "activations": [ … ] }. It works on suspended lines too — they keep their history.
integer
default:"20"
1 to 100. Anything else (0, 101, a decimal, text, empty) → 400 INVALID_LIMIT.
A line of another workspace answers 404 LINE_NOT_FOUND — never an empty list.

Activation object fields

string
The request id (activationId).
string
The line the request belongs to.
string
WAITING, CAPTURED, TRANSCRIBED, TIMED_OUT or FAILED — see Statuses.
string
ISO 8601 — when the request was opened.
string
ISO 8601 — end of the capture window, 5 minutes after the request.
string | null
The 6-digit code, once TRANSCRIBED and found. null otherwise.
string | null
ISO 8601 — when the call recording was stored.
string | null
ISO 8601 — when the transcription finished.
string | null
Why a final request has no code — see Statuses.
boolean
Whether a recording of the call is stored and can be played in the dashboard.

Errors