Skip to content

Latest commit

 

History

History
88 lines (64 loc) · 3.91 KB

File metadata and controls

88 lines (64 loc) · 3.91 KB

Webhooks API

Base path: /api/webhooks. The gateway requires JWT for every route; API keys are not substitutes. CSRF is skipped for webhook paths. Subscriptions are scoped by JWT address.

Routes

Method Path Purpose
POST /api/webhooks/subscribe Create subscription
GET /api/webhooks List subscriptions
DELETE /api/webhooks/:id Delete subscription
GET /api/webhooks/:id/deliveries Delivery history

POST /api/webhooks/subscribe

Body: url (required HTTPS URL), eventTypes (required non-empty string array, max 20). Limited to 10 requests per 10 minutes per address.

curl -X POST http://localhost:3001/api/webhooks/subscribe -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"url":"https://integrations.acme.test/stellar/webhooks","eventTypes":["esc_crt","mil_apr","funds_rel"]}'
{"data":{"id":"cmc9x7h3q0001w9j1a2b3c4d5","url":"https://integrations.acme.test/stellar/webhooks","eventTypes":["esc_crt","mil_apr","funds_rel"],"createdAt":"2026-06-25T11:18:42.000Z","updatedAt":"2026-06-25T11:18:42.000Z","secret":"d30fb4cd94173a09c0aefcc9ae473f0a6fd1713a3c6eecb9e40a708b520770a1"}}
Status Response
201 Subscription and one-time secret above
400 {"error":"url must be a valid HTTPS URL"}
400 {"error":"eventTypes must be a non-empty array"}
400 {"error":"eventTypes may not exceed 20 entries"}
429 {"error":"Too many webhook subscription requests — try again later","code":"RATE_LIMIT_EXCEEDED"}
401/403/404/429/500 Shared responses

GET /api/webhooks

curl http://localhost:3001/api/webhooks -H "Authorization: Bearer $TOKEN"
{"data":[{"id":"cmc9x7h3q0001w9j1a2b3c4d5","url":"https://integrations.acme.test/stellar/webhooks","eventTypes":["esc_crt","mil_apr","funds_rel"],"isActive":true,"createdAt":"2026-06-25T11:18:42.000Z","updatedAt":"2026-06-25T11:18:42.000Z"}]}
Status Response
200 {data: subscriptions}; secrets omitted
401/403/404/429/500 Shared responses

DELETE /api/webhooks/:id

curl -X DELETE http://localhost:3001/api/webhooks/cmc9x7h3q0001w9j1a2b3c4d5 -H "Authorization: Bearer $TOKEN"
Status Response
204 Empty body
404 {"error":"Webhook subscription not found"}; also used for another owner's subscription
401/403/429/500 Shared responses

GET /api/webhooks/:id/deliveries

Query: page (default 1, not validated), limit (default 30, maximum 100, no lower-bound validation).

curl 'http://localhost:3001/api/webhooks/cmc9x7h3q0001w9j1a2b3c4d5/deliveries?page=1&limit=30' -H "Authorization: Bearer $TOKEN"
{"page":1,"limit":30,"total":2,"deliveries":[{"id":"cmc9yb6pk0002w9j1e6f7g8h9","eventType":"funds_rel","status":"success","attempts":1,"responseCode":200,"errorMessage":null,"lastAttemptAt":"2026-06-25T11:25:03.000Z","createdAt":"2026-06-25T11:25:02.000Z"},{"id":"cmc9y4x9c0001w9j1i0j1k2l3","eventType":"mil_apr","status":"failed","attempts":5,"responseCode":503,"errorMessage":"Webhook returned HTTP 503","lastAttemptAt":"2026-06-25T11:23:44.000Z","createdAt":"2026-06-25T11:20:00.000Z"}]}

Unknown/differently owned subscriptions return 200 with an empty list.

Status Response
200 {page,limit,total,deliveries}
500 {"error":"<database or invalid pagination message>"}
401/403/404/429 Shared responses

Delivered request

Headers: X-Webhook-Signature, X-Webhook-Delivery-Id, and X-Webhook-Event-Type. Signature is lowercase hex HMAC-SHA256 of the exact JSON body using the subscription secret.

{"eventType":"funds_rel","deliveryId":"cmc9yb6pk0002w9j1e6f7g8h9","timestamp":"2026-06-25T11:25:02.000Z","data":{"escrowId":"1042","amount":"750000000","recipient":"GDQP2WX3YJQZC6KLE5Q7PH7L4QK6RFKX2HM5FMVNNK7KXQMS3RYM4B7A"}}