Events and webhooks
Webhooks: endpoints, signatures, retries and replay
Register an https endpoint, verify the X-CC-Signature header, understand retries, and replay deliveries from the log.
Updated
Browse the developer docs
Steps
- In the app, open the Webhooks tab of the Developer console and select Register endpoint. In the Register webhook endpoint dialog, enter the Endpoint URL and an optional Description, then select Register endpoint. Copy the secret from the Signing secret created dialog.
- Subscribe the endpoint to events with the buttons on its card. Each is labelled with a plus sign and the event type, for example + invoice.paid. An endpoint registered in the console starts with no events.
- Through the API, send
POST /with anv1/ webhook_endpoints Idempotency-Keyheader and{ "url", "event_types": [1 to 20 types], "description" (optional, up to 500 characters) }. It returns 201 withid,event_typesandsigning_secret. This needswebhooks:write. - Use a public https URL. http URLs, hosts that do not resolve, and hosts that resolve to private, loopback or link-local addresses are rejected. Through the API this is a 400.
- Verify each delivery. ChessCore sends a
POSTwithcontent-typeapplication/and the headersjson X-CC-Signature,X-CC-Timestamp(Unix seconds) andX-Request-Id(starts withwhreq_). - Compute HMAC-SHA256 with your signing secret (the full
whsec_string) over the exact text<X-CC-Timestamp>.<raw request body>, as lowercase hex. Compare it toX-CC-Signaturein constant time. Reject timestamps more than 300 seconds from your clock. - Reply with any 2xx status within 10 seconds to mark the delivery as succeeded.
- Check the log in the Deliveries tab. Each row shows the event type, attempts used out of the maximum, the request ID, the last HTTP code, and Retry scheduled when a retry is due. Through the API, use
GET /(v1/ webhook_endpoints/ {id}/ deliveries webhooks:read). - To send an event again, select Replay on its row, or send
POST /with anv1/ webhook_deliveries/ {id}/ replay Idempotency-Keyheader (webhooks:write). This creates a new delivery and returns 202 withnew_delivery_idand status queued. You can replay a delivery in any state. - To stop deliveries, send
DELETE /with anv1/ webhook_endpoints/ {id} Idempotency-Keyheader. The endpoint is disabled and its subscriptions are removed. The response is{ "deleted": true, "id" }. A second delete returns 404. The console has no button for this.
Notes
- The delivery body is the event envelope:
{ id, type, version, resource: { type, id }, data }. The data part holds only ids, status values, counts and amounts, never a copy of the record. - Retries: network errors, timeouts, 408, 429 and 5xx are retried after about 1 minute, 5 minutes, 15 minutes, 1 hour, 3 hours, 6 hours, 12 hours and then every 24 hours (each plus or minus 10%), up to 10 attempts by default. Any other non-2xx status, including redirects, stops retries at once and marks the delivery dead.
- Redirects are never followed. Point the endpoint at the final URL.
- Deliveries for a disabled endpoint are marked dead with the error
"endpoint missing or disabled". - Rotate secret creates a second secret and the endpoint shows
"Rotation in progress (secondary secret active)". Deliveries are still signed with the original secret, and there is no step yet that switches signing to the new one. Keep verifying with the original secret. - Managing endpoints and replaying deliveries in the console needs the integration write permission. Viewing them needs integration read.
Related guides
Still need help?
Email hello@chesscore.io. Using ChessCore day to day? Visit the Help centre.