Skip to content

Webhooks overview

Waiting calls answer a question you ask. Webhooks tell you about things you did not ask about: a number’s status changed, a mailbox needs to be authorized again, the balance is low. You subscribe a URL of yours to events and we send a signed POST to it for each one.

Webhook endpoints belong to a project and receive that project’s events. balance.low is a team event and is sent to the endpoints of all of the team’s projects.

Create an endpoint in the console (Webhooks), or with the API:

curl -X POST https://api.clearance.rest/webhooks/endpoints \
-H "X-API-Key: $CLEARANCE_REST_API_KEY" \
-H "content-type: application/json" \
-d '{ "url": "https://app.example.com/hooks/clearance", "event_types": ["number.*", "balance.low"], "description": "production" }'
  • url must be https (plain http is accepted only for localhost), at most 2048 characters, without embedded credentials, and not on a clearance.rest host.
  • event_types is a list of up to 32 patterns: an exact name (number.renewal_failed), a family (number.*, email_account.*, balance.*) or * for everything. Opt-in events are delivered only when named exactly.
  • secret (16 to 128 characters) is optional; one is generated if you omit it.
  • A project can have 20 endpoints.

The response contains the endpoint’s signing secret, a whsec_... string. It is returned only here and by rotate-secret; store it. You need it to verify signatures.

Each delivery is a POST with a JSON body, the event:

{
"id": "evt_0190...",
"type": "number.status_changed",
"created_at": "2026-10-25T10:00:00.000Z",
"data": { }
}

and these headers:

Header
X-Webhook-Id The delivery’s id.
X-Webhook-Event-Id The event’s id. It does not change across retries.
X-Webhook-Event The event type.
X-Webhook-Timestamp Unix time in seconds, used in the signature. Renewed on every attempt.
X-Webhook-Attempt The attempt number, from 1.
X-Webhook-Signature v1= and the hex HMAC-SHA256 signature.
  • At least once, unordered. Deduplicate on event.id; do not rely on the order events arrive in.
  • Acknowledge with any 2xx. Anything else is a failure: other statuses (redirects are not followed), connection errors, and a response that takes longer than 10 seconds.
  • Retries. After a failure we retry after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours (each varied by up to 20%). Then the delivery is marked failed.
  • Auto-disable. An endpoint with 50 failed deliveries in a row is disabled (disabled_reason: "failing"). Fix the receiver and set enabled: true to turn it back on.
  • Respond quickly and process the event afterwards.
Request
GET /webhooks/event-types The event types you can subscribe to, and which are opt-in.
GET, POST /webhooks/endpoints List and create endpoints.
GET, PATCH, DELETE /webhooks/endpoints/{id} Read, change and remove one.
POST /webhooks/endpoints/{id}/rotate-secret Issue a new secret. The old one stops working at once.
POST /webhooks/endpoints/{id}/test Queue a webhook.test event to this endpoint.
GET /webhooks/endpoints/{id}/deliveries Delivery history, newest first. Filter by status: pending, succeeded, failed.
GET /webhooks/deliveries/{id} One delivery, with the event that was sent.
POST /webhooks/deliveries/{id}/retry Queue a failed delivery again.

Delivery records are kept, so you can always see what was sent to you and how your server answered.