Skip to main content

Webhook Events

Settlx sends HTTP POST requests to your endpoint when invoice, payment, and subscription lifecycle events occur. Webhooks let you react to events in real time — confirming orders, provisioning access, updating your database, or triggering downstream workflows — without polling the API.

Setting up webhooks

Configure your webhook URL in Settings → Developer on the dashboard. This single URL receives all event types — both invoice and subscription events. Your webhook secret is also set from Settings → Developer. You will need it to verify incoming requests.

Invoice event types

EventWhen it fires
invoice.confirmedRequired confirmations reached, invoice ready for settlement. data.payment_quality distinguishes full from overpaid.
invoice.underpaidCustomer sent less than the required amount — invoice stays open for top-up
invoice.settledFunds transferred to your settlement wallet — fulfil here
invoice.expiredInvoice expired without full payment. data.expiry_reason is no_payment or underpaid_unresolved.
invoice.failedNon-recoverable failure (currently fires for wrong-token resolutions). data.failure_reason carries the specific cause.

Subscription event types

EventWhen it fires
subscriber.enrolledCustomer enrolled — first invoice created, awaiting payment
subscriber.activatedPayment confirmed — subscription is now active
subscriber.past_dueNew billing cycle started — renewal invoice created
subscriber.expiredGrace period elapsed without payment
subscriber.cancelledSubscription cancelled by merchant
subscriber.pausedSubscription paused by merchant
subscriber.resumedPaused subscription resumed

Payload format

Invoice events

Invoice events use a nested data envelope:
{
  "event": "invoice.settled",
  "eventId": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890_invoice.settled_1744455900000",
  "timestamp": "2024-01-15T10:04:15.000Z",
  "data": {
    "invoice": { ... },
    "payment": { ... },
    "settlement": { ... }
  }
}
FieldTypeDescription
eventstringEvent type
eventIdstringUnique event ID — use this for idempotency
timestampstringISO 8601 timestamp when the event was generated
dataobjectEvent-specific payload

Subscription events

Subscription events use a flat payload — fields are at the top level:
{
  "event": "subscriber.activated",
  "subscriberId": "9f1e2d3c-4b5a-6789-abcd-ef0123456789",
  "merchantId": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
  "planId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "customer@example.com",
  "status": "active",
  "currentPeriodEnd": "2026-05-19T00:00:00.000Z",
  "timestamp": "2026-04-19T10:45:00.000Z"
}
Both event types are delivered to the same webhook URL and signed with the same secret. Use the event field to distinguish them — invoice events start with invoice., subscription events start with subscriber..
Invoice and subscription webhooks share the same signing scheme but have different headers, retry policies, and persistence behaviour. The sections below call out where they diverge.

Request headers

Invoice webhooks

HeaderDescription
X-Webhook-SignatureStripe-style signature: t=<unix_seconds>,v1=<hex>. The v1 portion is HMAC-SHA256 over <timestamp>.<rawRequestBody>.
X-Webhook-EventEvent type string (e.g. invoice.settled)
X-Webhook-Event-IdUnique event ID (same as eventId in the body)
X-Webhook-TimestampUnix seconds (string, e.g. "1777623628") — informational only; verification uses the t= value inside X-Webhook-Signature

Subscription webhooks

HeaderDescription
X-Webhook-SignatureSame scheme as invoice webhooks — verify the same way
X-Settlx-EventEvent type string (e.g. subscriber.activated) — note: NOT X-Webhook-Event
X-Settlx-DeliveryUnique delivery ID for this attempt (e.g. sub_1777623628000_<subscriberId>)
X-Webhook-TimestampUnix seconds (string)
If you filter incoming webhooks on the X-Webhook-Event header, you will silently drop subscription events. Either also check X-Settlx-Event, or use the top-level event field in the parsed JSON body — that field is consistent across both webhook types.

Idempotency

Webhook typeIdempotency key
Invoice eventseventId field in the body — stable across retries
Subscription eventsNo eventId is sent. Use subscriberId + event + timestamp to deduplicate, or just make your handler idempotent on the destination state (e.g. “is the subscription already active?”).

Signature verification

Every delivery includes an X-Webhook-Signature header. You must verify it before processing any event. See Webhook Integration for full verification examples in Node.js, Python, PHP, and Go.

Retry policy

The retry policy differs by webhook type.

Invoice webhooks

If your endpoint returns a non-2xx status or does not respond within 30 seconds, Settlx retries up to 10 times with exponential backoff:
AttemptDelay after previous failure
11 minute
25 minutes
315 minutes
41 hour
56 hours
6–1024 hours each
After 10 failed attempts the delivery is marked permanently failed. Failed and pending deliveries appear in Webhook Logs in the dashboard, where you can inspect the payload and manually retry.

Subscription webhooks

Subscription webhooks use a much shorter retry budget — 3 attempts with 1s and 2s backoff, ~10 second per-attempt timeout. They are not persisted to the dashboard’s Webhook Logs. If your endpoint is down for more than a few seconds, the subscription event is lost and cannot be replayed. If reliability matters more than latency, run an idempotent reconciliation job that periodically pulls subscriber state via the API and brings your local cache up to date.

Response requirements

Your endpoint must return a 2xx HTTP status within 30 seconds (invoice) / 10 seconds (subscription). Any 2xx code is accepted — 200, 201, and 204 all count as successful delivery.

Delivery status (invoice webhooks only)

The webhook_logs.status field can be one of:
StatusMeaning
pendingDelivery is queued or scheduled for retry
deliveredEndpoint returned 2xx — no further attempts
failedAll 10 attempts exhausted — delivery permanently failed
Subscription webhooks do not have a status field because they are not persisted.

Testing webhooks

Use the Test Webhook endpoint to send a simulated event to your URL without waiting for a real payment. Useful for verifying your handler logic and signature verification during development.
Test webhooks do not appear in the dashboard’s Webhook Logs view. They are sent ad-hoc and not persisted. Real events fired by actual invoice or subscription state changes are logged.