POST with the order, profile, or review the event concerns, so you can act on it without polling for changes.
Every request is signed, so you can verify it came from Cevoid. Requests are fixed POST calls with a JSON body; custom methods, custom authorization headers, and inbound webhooks are not supported.
Prerequisites
- You can access Settings and Flows in your Cevoid workspace.
- You have a public HTTPS receiver that accepts
POSTrequests, preserves the exact raw request body for signature verification, does not redirect, and returns a2xxresponse after accepting an event.
Set up a webhook
- Go to Settings → Integrations → Cevoid API.
- Create a webhook destination. Result: Cevoid shows the signing secret once — copy it now and store it securely.
- Go to Settings → Flows and create a Flow.
- Choose
order.fulfilled,order.delivered,product-review.submitted, orcompany-review.submittedas the trigger. - Add a webhook action and choose your destination.
- Publish the Flow. Result: matching events start being delivered.
Request contract
Cevoid sends an HTTPSPOST with content-type: application/json and these Standard Webhooks headers:
webhook-id: stable public event ID; retries keep the same valuewebhook-timestamp: Unix seconds for this attemptwebhook-signature: one or morev1,<base64>signatures
type tells you what happened, data holds the resources it concerns, and origin.flow names the Flow that sent it — useful when several Flows point at one destination.
type: "cevoid.test".
Verify the exact raw body
Verify the signature before parsing JSON. Build the signed content as:whsec_, calculate HMAC-SHA256, encode the digest as base64, and compare it in constant time with any v1 signature in webhook-signature. Reject stale timestamps according to your replay-risk policy. During secret rotation, accept a match from either current secret while both signatures are present.
Node.js
rawBody directly from your framework’s raw-body middleware. Do not use JSON.stringify(req.body).
Python
HMAC test vector
This fixture is derived from the automated signing contract:Respond and deduplicate
- Return any
2xxresponse once you have durably accepted the event. Result: Cevoid stops retrying it. - Store
webhook-idand skip an ID you have already processed. Result: a retry after a lost response cannot create a duplicate on your side. - Sequence your own state from
created_ator from the resource indata, not from arrival order. Events for the same order or profile can arrive in any sequence. - Do not redirect. Cevoid sends every request to the URL you configured.
Retries
Cevoid retries408, 425, 429, and 5xx responses with a widening delay, over roughly a day. A Retry-After header is honoured when it asks for longer.
Other 3xx and 4xx responses stop the delivery. Fix your receiver, then retry it from the delivery log.
URL requirements
Destination URLs must use HTTPS and resolve to a public address. They cannot contain credentials, fragments, or query strings.Test, retry, and replay
- Send test sends a real signed
cevoid.testrequest so you can check your receiver end to end. - Retry sends the same event again, with the same
webhook-idand the same body. Use it after fixing your receiver. - Replay sends the same event data as a new event, with a new
webhook-id, to your destination’s current URL. Because the ID is new, your deduplication will not filter it.
Troubleshooting
- No request arrives: confirm the destination and the Flow are active, then check the delivery log.
- Signature mismatch: verify against the exact raw bytes, not parsed JSON, and remove
whsec_before base64 decoding. - Repeated events: deduplicate on
webhook-id. - Redirect or network error: point the destination at the final public HTTPS URL. Redirects and private addresses are blocked.
- Delivery stopped retrying: fix the reason shown in the delivery log, then retry it.
- Secret was lost: rotate it. Accept both signatures during the overlap, deploy the new secret, then finish rotation.