POST with the full JSON of the order, payment, customer, store and gateway every time something happens.
They’re managed from the CRM, under Account → Webhooks. Only the main account can see and configure them: collaborators don’t have access to this section.
How it works
Create an endpoint
https URL and check the events you want to receive. If needed, limit the endpoint to specific stores and add your own headers.Store the secret
whsec_.... Store it in your receiver: you’ll use it to verify the signature of each delivery. You can view it again or rotate it from the endpoint card.Verify the signature and respond 2xx
X-Hurry-Signature header against the raw body and respond with a 2xx code within 10 seconds. If you don’t respond 2xx, Hurry retries automatically.Test it
ping event and shows you the HTTP code and your server’s response.Events
Each endpoint subscribes to the events you choose. The event code travels in the JSONtype field and in the X-Hurry-Event header.
Store scope
An endpoint can receive events from all stores (including recurring charges, which have no store) or only some. If you choose specific stores, charges without a store aren’t sent to that endpoint.Custom headers
You can add up to 5 custom headers per endpoint, for exampleAuthorization: Bearer ... if your receiver requires a token. Names can contain letters, numbers and hyphens. You can’t set the headers Hurry defines: Host, Content-Type, Content-Length, Transfer-Encoding, User-Agent or any starting with X-Hurry-.
Event format
All events share the same envelope. What changes is the content ofdata.
evt_ + 24 characters). It’s the same across all endpoints, all retries and manual resends of the same occurrence. Use it to ignore duplicates.order.paid, payment.failed, refund.created…2026-11-01. Each endpoint is pinned to the version it was created with.id and name of the endpoint receiving the event.null.4980 is 49.80 EUR), with the currency alongside and a readable version in the *Formatted fields. Dates are in ISO 8601 with time offset.What data contains for each event
data.order: the order
data.order: the order
#1001.PENDING, IN_PROGRESS, REQUIRES_ACTION, PAID, PARTIALLY_REFUNDED, REFUNDED or CANCELED. Read the note below before using it to tell whether the order has been paid.true if the order has been paid. Derived from the payment, it works for all gateways.CREATED, REQUIRES_ACTION, PROCESSING, SUCCEEDED, CANCELED or FAILED.currency, subtotal, tax, shipping, discount, upsells, total and totalFormatted.fxRate when there was a conversion.id, productId, sku, name, imageUrl, quantity, unitAmount, taxAmount and totalAmount.shipped, shippedAt, trackingNumber and trackingUrl.data.payment: the payment
data.payment: the payment
CREATED, REQUIRES_ACTION, PROCESSING, SUCCEEDED, CANCELED or FAILED.STRIPE, STRIPE_EVERVAULT, WHOP, ONE, SUMUP, SQUARE, MAMO, AIRWALLEX, SHOPIFY, MOR, SLASH, NEXI, NEXI_ALIAS, REDSYS or REVOLUT.pi_...).true if it’s a recurring charge without an order (rebill).type, brand, last4, expMonth, expYear, country and funding. The full card number is never sent.code and message of the decline when the charge fails.data.refund.data.customer: the customer
data.customer: the customer
id, email, name, phone, address (line1, line2, city, state, postalCode, country) and createdAt. It doesn’t include any card data.data.shop and data.gateway: store and gateway
data.shop and data.gateway: store and gateway
id, name, url, slug, customDomain, type (EXTERNAL or NATIVE) and platform (SHOPIFY, WORDPRESS or API).gateway: id, name and psp of the payment credential used for the charge.data.refund: the refund (refund.created)
data.refund: the refund (refund.created)
id, providerRefundId, amount, currency, amountFormatted, status (PENDING, SUCCEEDED, FAILED or CANCELED), reason, failureReason, createdAt and updatedAt.data.dispute: the dispute (dispute.opened and dispute.closed)
data.dispute: the dispute (dispute.opened and dispute.closed)
CHARGEBACK, INQUIRY or EARLY_FRAUD_WARNING.NEEDS_RESPONSE, UNDER_REVIEW, WON, LOST, CHARGE_REFUNDED or CLOSED.dispute.closed to know where it came from.ping: the test
ping: the test
message with fixed text and endpoint with id, name, url and the list of events it’s subscribed to. Use it to check that your receiver is reachable and that you verify the signature correctly.Full example: order.paid
HTTP headers
Each delivery is aPOST with Content-Type: application/json and User-Agent: Hurry-Webhooks/1.0. It also includes these headers:
Verify the signature
Each delivery is signed with HMAC-SHA256 using the endpoint’s secret. Verify the signature before trusting the content:- Read the raw request body, exactly as it arrives, before parsing the JSON.
- Extract
tandv1from theX-Hurry-Signatureheader. - Reject the request if
tdiffers by more than 300 seconds from your current time. This way a captured delivery can’t be replayed later. - Compute
HMAC-SHA256(secret, t + "." + body)and convert it to lowercase hexadecimal. - Compare the result with
v1in constant time.
Responses, retries and duplicates
Respond2xx within 10 seconds and process the event afterwards, in the background. Any other response, a timeout or a network failure counts as a failed delivery. Hurry doesn’t follow redirects: a 3xx response also counts as a failure.
If a delivery fails, Hurry retries it with increasing waits: the first attempt plus 6 retries, spread over about 9 hours.
ping) and manual resends are attempted only once.
id field (or the X-Hurry-Event-Id header) of each processed event and ignore repeats.Automatic shutdown
To avoid hammering a receiver that’s down, Hurry turns off the endpoint in two cases:- 10 consecutive permanent failures: the endpoint switches to Turned off due to failures and we notify you via the CRM bell. A success at any point resets the streak.
410 Goneresponse: your server says the URL no longer exists and the endpoint is turned off immediately.
Deliveries
In Deliveries you see the history of everything Hurry has sent or tried to send, most recent first, with filters by endpoint and status.id as a new delivery. History is kept for 30 days.
Secret and security
- Secret per endpoint. Each endpoint has its own
whsec_...secret, encrypted in the database. The list only shows a hint with the last 4 characters. You can view or rotate it whenever you want. - Immediate rotation. When you rotate, the previous secret stops working right away: update your receiver with the new one before rotating if you don’t want to lose deliveries.
- HTTPS and public hosts only. The URL must be
https://, point to a public internet domain and not include a username or password. Hurry rejectslocalhost, internal names, private or loopback addresses and the Hurry platform itself, and checks again before each send. - No card data. The JSON never includes the full card number or CVC: only brand, last 4 digits, expiry, country and type.
- Main account only. Collaborators don’t see the section, and it can’t be changed while impersonating another user.
Limits
Integration with Make, Zapier and n8n
Create a Webhook module or node in the tool, copy the URL it gives you and paste it as the endpoint URL in Hurry. Choose the events and click Test so the tool receives aping you can use to map the fields.
If the tool doesn’t let you verify the signature, add at least one custom header with a token only you and the tool know, and check it in the first step of the flow.
Management from the Hurry MCP
If you use the Hurry MCP connector with an AI assistant, webhooks can also be managed conversationally with these tools. The secret is never returned through the MCP; to view or rotate it you need to use the screen.Frequently asked questions
My receiver isn't getting anything
My receiver isn't getting anything
https, public and that you respond 2xx. If Hurry turned it off due to failures, turn it back on with the toggle.What happens if my server goes down?
What happens if my server goes down?
Can I receive events in Make, Zapier or n8n?
Can I receive events in Make, Zapier or n8n?
What data is sent?
What data is sent?
Why isn't order.status PAID if the order has been paid?
Why isn't order.status PAID if the order has been paid?
order.status is the order status in the CRM and only Shopify stores set it to PAID. On other gateways, the source of truth for the charge is the payment. Use order.paid, order.paidAt and order.paymentStatus, which work for all of them.Why do I get two events for one sale?
Why do I get two events for one sale?
order.paid and payment.succeeded at the same time, with the same content in data. Subscribe to only one of them unless you also want subscription recurring charges, which only arrive as payment.succeeded.My secret has leaked
My secret has leaked
Can I pause an endpoint without deleting it?
Can I pause an endpoint without deleting it?
