Overview
This reference covers the technical details of SureDone webhook payloads — what you'll receive at your endpoint, how events are structured, and how to verify their authenticity. For setup instructions, see Getting Started with Webhooks.
Additional documentation can be found here and here.
Payload Format (CloudEvents 1.0)
All webhook payloads follow the CloudEvents 1.0 specification — an industry standard for describing event data. Every delivery to your endpoint will have a JSON body structured like this:
{
"specversion": "1.0",
"type": "suredone.order.created",
"source": "/suredone/users/12345",
"id": "evt_a1b2c3d4e5f6a1b2c3d4e5f6",
"time": "2026-02-19T15:30:45.123456Z",
"datacontenttype": "application/json",
"data": {
"oid": "98765",
"channel": "ebay1",
"status": "READY",
"resource_type": "order",
"resource_id": "98765"
}
}Envelope Fields
| Field | Description |
|---|---|
specversion | Always "1.0" (CloudEvents version). |
type | The event type, prefixed with suredone. (e.g., suredone.order.created). |
source | Identifies the SureDone account: /suredone/users/{user_id}. |
id | A unique event ID (format: evt_ followed by a 24-character hex string). Use this for idempotency — see Handling Duplicates below. |
time | ISO-8601 UTC timestamp of when the event occurred (microsecond precision). |
datacontenttype | Always "application/json". |
data | The event-specific payload (see below). |
Event Types & Data Fields
The data object contains different fields depending on the event type. All event types include resource_type and resource_id.
order.created
Fired when a new order is imported into SureDone from any sales channel.
"data": {
"oid": "98765",
"channel": "ebay1",
"status": "READY",
"resource_type": "order",
"resource_id": "98765"
}order.updated
Fired whenever any field on an existing order is modified. This event fires on every order edit, in addition to any more specific events (like order.status_changed or order.fulfilled).
"data": {
"oid": "98765",
"channel": "ebay1",
"status": "SHIPPED",
"resource_type": "order",
"resource_id": "98765"
}order.status_changed
Fired when an order's status field changes. Includes the previous status so you can track the transition.
"data": {
"oid": "98765",
"channel": "ebay1",
"status": "SHIPPED",
"previous_status": "READY",
"resource_type": "order",
"resource_id": "98765"
}order.fulfilled
Fired the first time an order's shipping status transitions to Partial or Complete. Includes tracking information when available.
"data": {
"oid": "98765",
"channel": "ebay1",
"status": "SHIPPED",
"tracking_number": "1Z999AA10123456784",
"ship_carrier": "UPS",
"resource_type": "order",
"resource_id": "98765"
}Note: If tracking number or carrier is empty, those fields will be omitted from the payload. This event fires only on the first fulfillment transition — if an order goes from Partial to Complete, the event does not fire again.
Multiple Events per Operation
A single order edit can trigger multiple webhook events. For example, if you update an order and change its status to "SHIPPED" with tracking info, you could receive up to three events from that one operation:
order.updated— always fires on any editorder.status_changed— because the status changedorder.fulfilled— because shipping status transitioned to Partial/Complete
Each event has its own unique id, so they won't be deduplicated against each other. Your system should be prepared to receive multiple events for the same order in quick succession.
Thin Payloads
Webhook payloads are intentionally lightweight — they contain key identifiers and status information, but not the full order object. This design keeps deliveries fast and reliable.
To get complete order details, use the order ID (oid) from the webhook to fetch the full order via the SureDone API:
GET https://api.suredone.com/v3/orders/{oid}Signature Verification
Every webhook delivery includes three headers you can use to verify authenticity:
| Header | Description |
|---|---|
webhook-id | Unique message identifier (consistent across retries of the same delivery). |
webhook-timestamp | Unix timestamp (seconds since epoch) of when the webhook was sent. |
webhook-signature | HMAC-SHA256 signature(s) for verification. |
How to verify
- Get your secret key: Take the signing secret you saved when creating the endpoint (starts with
whsec_). Strip thewhsec_prefix and Base64-decode the remainder to get the raw key bytes. - Build the signed content: Concatenate the
webhook-id,webhook-timestamp, and raw request body with periods as separators:{webhook-id}.{webhook-timestamp}.{raw_body} - Compute the signature: Calculate an HMAC-SHA256 of the signed content using the decoded secret key, then Base64-encode the result.
- Compare: The
webhook-signatureheader contains one or more signatures in the formatv1,{base64_signature}(space-separated). Compare your computed signature to each one using a constant-time comparison function. - Check timestamp: Optionally, verify that
webhook-timestampis within a few minutes of your server's current time to protect against replay attacks.
Use the raw request body exactly as received — do not re-serialize or modify whitespace before computing the signature.
For ready-made verification libraries in multiple languages, see the webhook verification documentation which is compatible with SureDone's webhook signatures.
Retry Behavior
If your endpoint doesn't return a 2xx HTTP status code (200-299) within 15 seconds, the delivery is considered failed and SureDone will retry with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | ~5 seconds |
| 2nd retry | ~5 minutes |
| 3rd retry | ~30 minutes |
| 4th retry | ~2 hours |
| 5th retry | ~5 hours |
| 6th retry | ~10 hours |
| 7th retry | ~10 hours |
After 8 total attempts (1 initial + 7 retries), the delivery is marked as Failed. You can manually retry failed deliveries from the delivery logs in the UI.
Automatic disabling: If all deliveries to an endpoint fail continuously for 5 days, the endpoint will be automatically disabled. You can re-enable it from the Webhooks settings after resolving the issue with your server.
Handling Duplicates (Idempotency)
While SureDone makes every effort to deliver each event exactly once, in rare cases the same event may be delivered more than once. This can happen due to network issues, retries, or edge cases in message processing.
To handle this safely:
- Extract the
idfield from the CloudEvents payload (e.g.,evt_a1b2c3d4e5f6a1b2c3d4e5f6). - Before processing, check whether you've already handled an event with this ID.
- If you have, skip it. If not, process it and record the ID.
The event ID is stable across retries — the same event will always have the same id, so this approach reliably prevents duplicate processing.
Best Practices Summary
- Return 200 quickly — Accept the webhook and return a 2xx response within 15 seconds. Do heavy processing in a background job.
- Implement idempotency — Track event IDs to safely handle duplicate deliveries.
- Verify signatures — Use HMAC-SHA256 verification to confirm webhooks are from SureDone.
- Use webhooks + polling together — For critical workflows, supplement webhooks with periodic API polling as a safety net to catch any events that might have been missed after all retry attempts.
- Fetch full data via API — Webhook payloads are lightweight notifications. Use the SureDone API to retrieve complete order details when needed.
- Monitor endpoint health — Check the Statistics dashboard and endpoint health badges regularly. Investigate degraded or failing endpoints promptly.