Webhooks
Partners can configure one HTTPS webhook endpoint in the dashboard. RoamWorks sends signed events for completed and processing orders and for redemptions. The delivery log is visible in the dashboard.
Events
| Event | When | Data |
|---|---|---|
order.completed | The purchase is complete and every child order is fulfilled. | purchaseId, reference, orderIds, amountMinor, currency, status, pendingOrderIds |
order.processing | The purchase is paid but at least one unit awaits upstream fulfilment. | Same shape as order.completed. |
esim.redeemed | A redemption batch was created. | batchId, purchaseId, orderIds, itemIds, format |
No webhook payload contains LPA text, QR data, a secret, card data or customer personal data. Use the purchase or batch id to fetch authorised data through the API when needed.
Partner webhook management is currently dashboard-only. A management API is Planned.
Envelope
Code
Signature
Every delivery carries:
Code
The signed content is:
Code
v1 is the lowercase hex HMAC-SHA256 of that string using your webhook signing secret. The
secret is shown once when you save or rotate the endpoint in the dashboard. Store it in a secret
manager.
Verify
Verify against the raw bytes before parsing JSON. Reject a timestamp older than five minutes. Compare digests in constant time.
Code
Reject the delivery with a non-2xx response when verification fails. Do not parse and re-serialize the body before verification; whitespace matters.
Delivery and retries
- Request timeout: 10 seconds.
- Success: any 2xx response.
- Retry: connection errors, timeouts, non-2xx responses and redirects (redirects are not followed).
- Attempts: up to 10.
- Delay after attempt 1 to 9: 5 seconds, 15 seconds, 60 seconds, 5 minutes, 15 minutes, 30 minutes, 1 hour, 2 hours, 4 hours.
- After the tenth failed attempt the event is marked dead in the dashboard.
Deliveries are at least once. Deduplicate on the envelope id. A duplicate delivery can arrive
after a timeout even if your handler processed the first one.
Endpoint requirements
- Public HTTPS URL. HTTP, loopback, link-local, private and local-only addresses are rejected.
- No embedded username or password in the URL.
- A valid public certificate. The API does not disable certificate validation.
- Return a 2xx quickly, then process asynchronously. A slow handler increases retry pressure.
- Use a dedicated endpoint path. Do not expose the signing secret in a query string.
Local testing
Use a tunnel with a public HTTPS URL. The API resolves the hostname and rejects private addresses, so a localhost URL will not work. Verify the signature with the same raw body your framework received.
Stripe funding webhook
POST /v1/webhooks/stripe is a separate server-to-server receiver for Stripe. It is not a
partner-configured endpoint and partners do not call it. It returns 501 when Stripe funding is
not enabled and 400 for an invalid Stripe signature.