POST whenever one fires.
Use them to sync data, trigger your own automations, fulfill purchases, and feed analytics — anything where your code needs to react to something happening in Crevio.
Webhooks notify your server so your code acts. If you instead want Crevio’s AI to act on an event, use an event-triggered Task. See How webhooks differ from event-triggered Tasks.
Creating an endpoint
Create endpoints from the dashboard, via the API, or with the TypeScript SDK.Via dashboard
1
Open Developer settings
In your dashboard, go to Settings → Developer.
2
Create a new endpoint
Click New webhook endpoint and enter the HTTPS URL that should receive events. (HTTP is allowed only in local development.)
3
Select events
Choose which event types to subscribe to, individually or all at once.
4
Save and copy the secret
Crevio generates a signing secret (prefixed
whsec_) shown once. Copy it now — you’ll use it to verify incoming requests.Via API
Like every Crevio endpoint, params go at the top level (no{"webhook_endpoint": {...}} wrapper). Subscribe with enabled_events.
- cURL
- SDK (TypeScript)
secret — returned only on creation:
url can point at a Crevio site that only signed-in visitors can open, on any path. Crevio’s deliveries to your own account’s sites pass its sign-in check, while anyone else is still asked to sign in. Verify the signature in your handler all the same, as you would on a public site.
List the available event types programmatically:
Testing an endpoint
Send a synthetic event to any active endpoint to verify your handler:event_type must be one the endpoint is subscribed to. A test delivery is signed like a real one, but it carries "test": true, "livemode": false and an empty data.object — acknowledge it as soon as the signature checks out, or your own validation will fail a test that was never going to carry an order. The response is what your server answered, so a handler that rejects the event tells you why:
delivered is true for any 2xx. If nothing answers at all — DNS failure, refused connection, timeout — the call returns 502 instead. The test event is signed like a real one, so it exercises your signature check.
You can also test from the dashboard: Settings → Developer → Send test, then pick an event type. Test deliveries include "test": true in the body and are not persisted to your delivery history.
Testing a paid order end to end
A test event proves your endpoint is reachable and your secret is right. To run your real fulfillment code on a real order without charging a card, make a test purchase:1
Create the checkout the way your site does
POST /v1/checkouts with your line items and metadata, exactly as in production. See Checkouts.2
Complete it as a test purchase
POST /v1/checkouts/{id}/test_purchase with a key or OAuth token of an account admin. Or open its purchase_url in a browser signed in to Crevio as an admin of the store: the card form is replaced by a Test purchase notice.3
Watch your endpoint
No card is charged and Stripe is not called. Crevio creates the order and sends
order.created and order.paid to your endpoint, plus subscription.created when the checkout starts a subscription.test flag, they are signed and retried like any other, and data.object is the full order. The checkout’s metadata is copied onto the order, so the key your site saved before checkout comes back in the event. What marks the order as a test is livemode. It is on the event itself and on the order:
livemode wherever your handler acts on the outside world. Every event has it, including events whose data.object has no livemode of its own, so one check covers all of them:
email or customer on the checkout, so Crevio’s own receipt goes to you. A test order uses up no stock and doesn’t count toward sales. Its amount is what the checkout would have charged, and charge is null.
The rest of the order’s life works without Stripe too, and every event it sends has livemode: false:
Test subscriptions renew and end on an hourly check, so
subscription.renewed and subscription.ended can arrive up to an hour after the period closes. A test renewal sends no renewal receipt, because nothing was charged. GET /v1/refunds and GET /v1/refunds/{id} return test refunds too, with livemode: false.
There is no Stripe test mode for checkouts, so test card numbers like 4242 4242 4242 4242 are declined. A test purchase covers everything except the card charge itself.
Available events
These are the event types you can subscribe to viaenabled_events. Each has a dedicated page under Webhook Events in the API reference showing its exact payload.
Commerce
subscription.canceled means the customer keeps access until ends_at. A subscription that is canceled immediately skips it and sends only subscription.ended. These events fire however the change was made — the API, the customer’s billing portal, or Stripe.
Subscription renewals
Every paid renewal of a subscription or payment plan is recorded as a new order. Each one sendsorder.created and order.paid, then subscription.renewed. Tell a renewal apart from a purchase by the order’s billing_reason, named as Stripe names the invoice:
Both subscription values come with
subscription, the id of the subscription (sub_…) the order started or renewed. A renewal order has the purchase’s line_items and customer, its own charge and amount, checkout: null, and empty metadata: the metadata you set on the checkout stays on the purchase order, so your own order numbers are never reused.
A handler that fulfils purchases on order.paid should branch on it, or every renewal will look like a new sale:
subscription.renewed.
A subscription that starts with a free trial has no payment to tie it to an order, so its order is null. customer is always present.
Leads & customers
Filter on
data.tag.id to react to one specific tag. Bulk CSV imports and deleting a tag outright do not send per-customer tag events.
Catalog
AI Tasks & Jobs
Social
Payload format
Every delivery is an HTTPPOST with a JSON body in this shape:
data.object is the resource exactly as the API returns it — an order.paid event carries the same object as GET /v1/orders/{id}, so one parser handles both. References are ids you can fetch (checkout, order), and the ones you almost always need arrive already expanded: customer on checkout, order, refund, invoice and subscription events, plus line_items on orders and order.line_items on subscriptions.
Refund events carry the refunded order as data.object — its amount_refunded and status reflect the refund.
Dispute events carry the disputed order. On order.disputed its status is disputed. On order.dispute_closed the status tells you the outcome: back to succeeded (or partially_refunded) when the dispute was won or the inquiry closed, still disputed when it was lost. A lost dispute also removes the buyer’s access, as a full refund does, except on a renewal order: access there comes from the subscription, which keeps running.
Tag events carry the customer as data.object and the tag that was added or removed as data.tag.
Delivery history
Each delivered event is persisted as a webhook event you can inspect. List your delivery history:?webhook_endpoint=wh_abc123, or by status and event_type. Fetch a single delivery with GET /webhook_events/{id}; add ?expand[]=request to see the response code, response body and attempt count.
Redelivering an event
Send a delivered or failed event again, unchanged:id and the same payload, so a handler that deduplicates on id treats it as the event it already saw. Events are kept for 7 days. The call returns 409 while the event is still being delivered, or when its endpoint is disabled.
Versioning
Every endpoint is pinned to a payload version —api_version on the endpoint, repeated in each event. A new endpoint is pinned to the current version, and that never changes for you: when a payload changes in a way that could break a parser, it ships as a new version, and existing endpoints keep receiving the one they were built against. Opt in when you are ready:
v1.
Retry behavior
Crevio expects a2xx response within 5 seconds. Redirects are not followed. Anything else — a timeout, a 4xx, a 5xx — counts as a failure, and the event is retried on this schedule:
That is about three days in all. After the last attempt the event is marked failed; you can still redeliver it for 7 days.
Delivery is at least once, and order is not guaranteed — a retry of an older event can land after a newer one. Deduplicate on
id, and fetch the resource from the API when order matters.
When an endpoint keeps failing
- After 24 hours in which every delivery failed, the account owner gets a warning email.
- After 72 hours, the endpoint is switched to
inactiveand the owner is told. Events still waiting to retry are marked failed.
active and redeliver what it missed.
Endpoint statuses
Deactivate an endpoint without deleting it; reactivating resumes delivery for new events. Crevio sets
inactive itself only after 72 hours of failures.
Security
Verifying signatures
Crevio signs deliveries to the Standard Webhooks specification, so you verify them with an existing library instead of writing HMAC code. Every request carries three headers:webhook-timestamp more than five minutes old, which is what stops a captured request being replayed.
Verifying without a library
Verifying without a library
The signature is the base64 HMAC-SHA256 of
<webhook-id>.<webhook-timestamp>.<raw body>. The key is the bytes your secret encodes: strip the whsec_ prefix and base64-decode the rest — do not use the secret’s text as the key. Compare in constant time against the part of webhook-signature after v1,, and reject a timestamp more than five minutes old.Best practices
- Respond fast — return
200immediately, then process asynchronously to avoid timeouts. - Deduplicate — use the event
id(whev_…); the same event may arrive more than once. - Use HTTPS — required in production.
- Protect your secret — store it in env vars or a secrets manager; never commit it.
Output formats
Beyond the default JSON, Crevio can format deliveries for chat platforms:
Select the format when creating or editing the endpoint.
How webhooks differ from event-triggered Tasks
Both react to platform events, but they do different jobs:
The subscribable internal events (and any third-party triggers) are documented under Events.
Next steps
Events
Internal and third-party triggers for event Tasks.
Tasks
Let Crevio’s AI react to events on your behalf.
Autonomous outreach
A worked event-triggered Task on
order.paid.API overview
The full set of primitives.

