Phone line webhooks
Phone lines send their events to phone-line webhooks: a registry of their own, separate from the number webhooks. The two never mix:- A number webhook — even one subscribed to
"*"— never receives aphone_line.*event. - A phone-line webhook receives only
phone_line.*events, never message or number events.
Configure (dashboard only)
There is no public API for phone-line webhooks. Manage them in the dashboard under Phone lines → Line webhooks (/linhas/webhooks), as an Owner or Admin:
- Destination URL — must be
https. - Events — pick one or more of the events below, or all (
"*"). Inside this registry"*"means every phone-line event. At least one is required. - Signing secret — shown once, when the webhook is created (it starts with
plwh_). Store it right away: nothing shows it again, and there is no rotation. To change it, create a new webhook, move your receiver to its secret, and delete the old one. - Pause / resume, and delete. The dashboard does not edit a webhook’s URL or events: create a new webhook and delete the old one.
- Delivery log — per webhook: event, status (pending, delivered, failed), attempts, the HTTP status your endpoint answered and the last error.
Events
phone_line.code_received fires only when a transcription completes. A request that ends TIMED_OUT, FAILED, or CAPTURED with a failed transcription sends no event — if you wait on the webhook, also watch the request’s pollDeadline, or poll GET /v1/phone-lines/activations/{activationId}.Payload format
Every delivery is aPOST with a JSON body:
Headers:
Numbers here have no
+. number is E.164 digits without the plus sign (551148637200), exactly as in the /v1/phone-lines endpoints — unlike the number webhooks, whose phone fields carry +.Payloads
lineId is the line’s id in GET /v1/phone-lines/{id}.
phone_line.purchased
phone_line.purchased
phone_line.code_received
phone_line.code_received
code is null when the call was transcribed but no 6-digit code was found in it (the request’s failureReason is then no_code_in_transcript). The recording can be played in the dashboard.phone_line.renewed
phone_line.renewed
currentPeriodEnd is the end of the period just paid for.phone_line.payment_failed
phone_line.payment_failed
phone_line.suspended
phone_line.suspended
phone_line.returned
phone_line.returned
phone_line.canceled
phone_line.canceled
phone_line.verification_updated
phone_line.verification_updated
status is one of:There is no public endpoint to read the verification;
verificationId identifies it in support conversations.Verify the signature
Every phone-line webhook has a secret, so every delivery is signed.x-pilot-status-signature is the hex-encoded HMAC-SHA256 of the raw request body, keyed with the webhook’s secret (the whole string, plwh_ prefix included). Compute it over the bytes exactly as received — before any JSON parsing — and compare in constant time:
id to discard duplicates.
Delivery and retries
- Answer with any
2xxwithin 10 seconds. Anything else — another status, a timeout, a connection error — counts as a failed attempt. - 6 attempts in total: the first right away, then retries about 30 s, 1 min, 2 min, 4 min and 8 min apart — normally about 15 minutes end to end. After the last one the delivery is marked failed in the log. A delivery that could not be queued at first is picked up again by an hourly sweep, so its first attempt can come later.
- Redirects are not followed. A
3xxanswer counts as a failed attempt. - At least once. A retry after your endpoint processed the event but did not answer in time delivers it again, with the same
id. Order is not guaranteed. - Paused or deleted webhooks. An event is delivered only to webhooks that are active and subscribed when it happens. Every attempt checks the webhook again: a delivery whose webhook is paused when an attempt is due — including one already in its retries — is marked failed and is not sent later; deleting a webhook drops its pending deliveries. Events are never replayed to a webhook created or resumed afterwards.
- Internal destinations are refused. A URL whose host resolves to a private or internal network address is not called, and is not retried. Such a URL is accepted when the webhook is created — only
httpsand the event names are checked then — so every delivery to it is logged as failed. A DNS lookup that fails is different: it is retried like any other failure.