7. Webhooks
Configure endpoints in the console and pick what to receive: certification.completed /
.failed, balance.low, balance.exhausted, events.unpaid_limit_reached,
consumption.limit_reached, recharge.auto_completed / .auto_failed. From the console you can also request a test delivery
(webhook.test) to any endpoint.
Every delivery shares the same JSON envelope: id (the same on retries), type, created_at,
mode (live or test: balance and limit notices are always live; certification notices carry
the certification's mode) and data, whose model depends on type:
type |
Sent when | data fields |
|---|---|---|
certification.completed |
The certification has been issued | certification_id, channel_id, status, event_count, verification_code |
certification.failed |
The certification could not be issued (the charge is refunded) | certification_id, channel_id, status, event_count, incident_id |
balance.low |
The balance drops below an alert threshold (once per crossing) | threshold_id, threshold, balance |
balance.exhausted |
The first event is registered as unpaid | channel_id |
events.unpaid_limit_reached |
The unpaid-events limit is reached: the API rejects registrations with 402 |
unpaid_limit, unpaid_events, unpaid_credits |
consumption.limit_reached |
A consumption limit reaches its maximum for the period | limit_id, scope, channel_id, key_id, period, period_key, max_events, action |
recharge.auto_completed |
An automatic top-up was charged and its credits are in the balance | recharge_id, pack_id, credits, amount, currency, threshold, balance |
recharge.auto_failed |
An automatic top-up failed and was turned off | recharge_id, pack_id, credits, amount, currency, threshold, reason, payment_url, auto_recharge_disabled |
webhook.test |
You request a test delivery in the console | endpoint_id, message |
{
"id": "ntc_…",
"type": "balance.low",
"created_at": "2026-09-28T07:00:16.526317Z",
"mode": "live",
"data": { "threshold_id": "thr_…", "threshold": 1000, "balance": 999 }
}
Credits are integers and timestamps are UTC with six fractional digits. Each field is described in
the API reference (Webhook…Data schemas). We may add fields to data over time: ignore the ones
you do not know.
Every delivery is signed with the endpoint secret and retried with exponential backoff for up to 24 hours (1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h). The delivery log lives in the console; an endpoint that keeps failing is disabled and we notify you by email.
How to verify a delivery before processing it:
- Read the
X-SC-Timestamp(Unix seconds) andX-SC-Signature(v1=<hex>) headers. - Compute HMAC-SHA256 with your secret (
whsec_…) over<X-SC-Timestamp>.<raw body>and compare it with<hex>in constant time. - Reject timestamps older than 5 minutes.
- Reply with any 2xx; de-duplicate by
X-SC-Webhook-Id(the envelopeid, the same on retries).