Appearance
Webhooks
Webhooks notify an HTTPS endpoint when subscription and invoice activity occurs. They let another system react to billing events without polling this application.
Before you begin
Prepare a publicly reachable endpoint that:
- Accepts
POSTrequests over HTTPS. - Reads a JSON request body.
- Verifies the request signature before acting on the data.
- Returns a
2xxresponse promptly—requests time out after 10 seconds. - Handles duplicate deliveries safely. Delivery is at-least-once, so use the webhook event ID as your idempotency key.
Keep the endpoint secret in a secure server-side configuration store; do not expose it in browser code or source control.
Create an endpoint
- In the admin application, open Settings → Webhook endpoints and select Add new.
- Enter the full receiver URL, for example
https://billing.example.com/webhooks/subtreo. - Enter a long, random Secret shared only with your receiver.
- Leave Active selected.
- Choose the event types your receiver needs and save.
The current event types are:
| Event | Sent when |
|---|---|
subscription.created | A subscription is created. |
subscription.updated | A subscription is changed. |
subscription.immediate_cancellation | A subscription is cancelled immediately. |
invoice.created | An invoice is generated. |
invoice.paid | An invoice is marked paid. |
Each endpoint receives only the event types it subscribes to. Endpoint configuration and deliveries are tenant-specific.
Request format and verification
The service sends a JSON POST with these headers:
| Header | Value |
|---|---|
Content-Type | application/json |
User-Agent | SubTreo-webhooks |
X-Webhook-Event-Id | The persisted webhook event ID. |
X-Webhook-Signature | Hex-encoded HMAC-SHA-256 of the exact raw request body, using the endpoint secret. |
The body has this envelope:
json
{
"id": "123",
"type": "invoice.paid",
"createdAt": "2026-09-30T10:15:00+00:00",
"data": {
"id": 42,
"customerId": 9,
"status": "paid"
}
}data contains the event snapshot. Invoice events include invoice totals, due and paid dates, and line items. Subscription events include the subscription status, term dates, recurring charges, physical assets, one-time charge IDs, and collection settings.
Verify the signature against the unmodified raw bytes before parsing or processing the payload. In pseudocode:
text
expected = HMAC_SHA256_HEX(rawRequestBody, webhookSecret)
accept only when timingSafeEqual(expected, X-Webhook-Signature)After verification, record X-Webhook-Event-Id as processed before performing side effects. Return a 2xx response for successfully accepted events, including events already processed.
Retries and delivery history
A delivery succeeds only on an HTTP 2xx response. Network errors, timeouts, and non-2xx responses are retried up to seven attempts, with delays of 1 minute, 5 minutes, 30 minutes, 2 hours, 12 hours, and 24 hours between retries. After the final unsuccessful attempt, the delivery becomes failed.
Test safely
To pause deliveries, clear Active on the endpoint. Existing queued deliveries to a disabled endpoint are marked failed when the worker encounters them; reactivate the endpoint and manually retry any delivery you still need.
