{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Webhooks"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"webhooks","__idx":0},"children":["Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Orderwerks can notify your systems when something happens in your account: an order is submitted, a shipment is created, a catalog item changes, an order enters a workflow step you care about. Instead of polling the REST API, register an HTTPS endpoint and Orderwerks posts a signed JSON envelope to it."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A business admin switches webhooks on under ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Business Integrations"]}," in the web app. Endpoints are then managed under ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Business Settings > Webhooks"]},", or through the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/openapi#tag/Webhooks"},"children":["Webhooks endpoints"]}," of the REST API with an API key."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"registering-an-endpoint","__idx":1},"children":["Registering an endpoint"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["An endpoint has a name, an HTTPS URL, and what it subscribes to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Events"]}," from the catalog below (for example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.submitted"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shipment.created"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Workflow triggers"]},": a workflow step (optionally restricted to one workflow). When an order enters that step the endpoint receives ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["workflow.fired"]},". The same event can also be sent from a workflow step's own \"send webhook\" action in the workflow editor."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Optionally add up to ten ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["static headers"]},", such as an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization"]}," header your receiver expects. Header values are stored encrypted and never shown again."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The URL must use HTTPS, must not contain credentials, and must resolve to a public address. Redirects are not followed. A business may register up to ten endpoints."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When you create an endpoint you receive its ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["signing secret once"]},". Store it. If it is lost, rotate it."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-delivery","__idx":2},"children":["The delivery"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every delivery is an HTTP ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Content-Type: application/json"]}," and these headers:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Header"},"children":["Header"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Value"},"children":["Value"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Orderwerks-Event"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The event type, e.g. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.submitted"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Orderwerks-Delivery"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The delivery id (also ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["id"]}," in the body)"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Orderwerks-Api-Version"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The payload version pinned on the endpoint"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Orderwerks-Signature"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["t=<unix seconds>,v1=<hex HMAC>"]}," (see below)"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["User-Agent"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Orderwerks-Webhooks/1.0 (+https://docs.orderwerks.com)"]}]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The body is an envelope:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"id\": \"8c0b1d3e-5f6a-4b7c-9d8e-0f1a2b3c4d5e\",\n  \"type\": \"order.submitted\",\n  \"api_version\": \"2026-10-27\",\n  \"occurred_at\": \"2026-10-27T18:04:11.000Z\",\n  \"supplier_guid\": \"3a1f...\",\n  \"data\": {\n    \"guid\": \"9b2e...\",\n    \"number\": \"ABC-10231\",\n    \"state\": { \"id\": 2, \"name\": \"SUBMITTED\" },\n    \"grand_total\": 1240.5,\n    \"customer\": { \"guid\": \"...\", \"name\": \"Acme, Inc.\", \"email\": \"orders@acme.example\", \"customer_internal_id\": \"ACME01\" },\n    \"ship_to\": { \"...\": \"...\" },\n    \"items\": [ { \"guid\": \"...\", \"sku\": \"WIDGET-1\", \"qty\": 12, \"unit_price\": 100, \"total\": 1200, \"...\": \"...\" } ],\n    \"items_truncated\": false\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data"]}," is shaped per event type; the exact fields are in the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/openapi#tag/Webhooks"},"children":["webhook definitions"]}," of the reference. Payloads are a curated view of the record: internal notes, costs, commissions and integration identifiers are never included. When you need the full record, fetch it through the REST API using the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["guid"]}," in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Respond with any ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["2xx"]}," status within 10 seconds to acknowledge the delivery. Do the real work after you have responded. Response bodies are stored (first 4 KB) for troubleshooting but otherwise ignored."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"verifying-the-signature","__idx":3},"children":["Verifying the signature"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every delivery is signed with HMAC-SHA256 over the string ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<timestamp>.<raw request body>"]}," using your endpoint's signing secret. The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Orderwerks-Signature"]}," header carries the timestamp and one or more signatures:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"X-Orderwerks-Signature: t=1761588251,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e4...\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To verify:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Split the header on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[","]},". Read ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["t"]}," and every ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["v1"]}," value."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Compute ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HMAC_SHA256(secret, t + \".\" + rawBody)"]}," with the raw bytes of the request body, not a re-serialised object."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Compare it against each ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["v1"]}," using a constant-time comparison. Accept if any matches."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Reject if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["t"]}," is more than a few minutes from the current time, to defeat replays."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"const crypto = require('crypto');\n\nfunction verify(rawBody, header, secret, toleranceSeconds = 300) {\n  const parts = Object.fromEntries(header.split(',').map((p) => p.trim().split('=')));\n  const timestamp = Number(parts.t);\n  if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false;\n\n  const expected = crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');\n  return header\n    .split(',')\n    .filter((p) => p.trim().startsWith('v1='))\n    .some((p) => {\n      const sig = Buffer.from(p.trim().slice(3), 'hex');\n      return sig.length === expected.length / 2 && crypto.timingSafeEqual(sig, Buffer.from(expected, 'hex'));\n    });\n}\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After you ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["rotate"]}," the secret, deliveries carry two ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["v1"]}," values for 24 hours, one per secret, so a receiver that still holds the old secret keeps working while you switch."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Static headers are a convenience for your receiver; they are not a substitute for verifying the signature."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"retries-and-failures","__idx":4},"children":["Retries and failures"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A delivery that gets no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["2xx"]}," is retried with increasing delays, about eight attempts over a day (30 s, 2 min, 10 min, 30 min, 1 h, 3 h, 6 h, 12 h). After that it is marked ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["failed"]}," and can be redelivered manually from Business Settings or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /v1/webhook-deliveries/{deliveryGuid}/redeliver"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Failures are also counted per endpoint. Any ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["2xx"]}," resets the count; after 50 consecutive failed attempts the endpoint is ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["disabled"]},", its queued deliveries are cancelled, and the business admins are emailed. A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["410 Gone"]}," response disables the endpoint immediately. Fix the receiver, then re-enable the endpoint and redeliver what you missed."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"idempotency-and-ordering","__idx":5},"children":["Idempotency and ordering"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Retries and redeliveries carry the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["same delivery id"]}," (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["id"]}," in the envelope, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Orderwerks-Delivery"]}," header). Store the ids you have processed and ignore repeats."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Deliveries are ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["not ordered"]},". Two events on the same order can arrive out of sequence, especially when one was retried. Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["occurred_at"]}," and the resource's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updated_at"]}," when the order of events matters, or fetch the current record from the REST API."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Some events are delivered on purpose a little after they happen: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.created"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["quote.created"]}," wait about 30 seconds so that line items added right after the order row are included, and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["*.updated"]}," events fold saves within a few seconds of each other into one delivery."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"events","__idx":6},"children":["Events"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Event"},"children":["Event"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"When"},"children":["When"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"data"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data"]}]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.created"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["An order row was created (web app, API, integrations)"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Order"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.submitted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["An order left ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PRELIMINARY"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Order"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.state_changed"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["An order moved to another workflow state; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.previous_state"]}," names the one it left and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.state"]}," the one it entered"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Order"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.deleted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["An order was deleted"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Deleted record (guid, order number)"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["quote.created"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A quote was created"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Order"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["quote.sent"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A quote was emailed to the customer"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Order"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["quote.converted_to_order"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A quote became an order; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.quote"]}," names the quote"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Order"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shipment.created"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A shipment was created"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Shipment"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shipment.voided"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A shipment was voided"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Shipment"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["shipment.deleted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A shipment was deleted"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Deleted record"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["catalog_item.created"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updated"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deleted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A catalog item changed"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Catalog item / Deleted record (guid, SKU)"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vendor.created"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updated"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deleted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A customer changed"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Customer / Deleted record"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vendor_source.created"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["updated"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deleted"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A vendor source changed"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Vendor source / Deleted record"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["workflow.fired"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["An order entered a step named by the endpoint's workflow triggers or by a step's \"send webhook\" action; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.workflow"]}," names the step"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Order"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["test"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Sent by the \"send test\" action; the envelope carries ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"test\": true"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Sample order"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.state_changed"]}," is the superset of the order lifecycle. If you subscribe to it and to a named status event such as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["order.submitted"]},", you receive two deliveries for that transition."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The transition itself (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.previous_state"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.state"]},") is captured when the change happens. The rest of the order is read when the delivery is sent, so an order that moved again in between still reports the original transition alongside its latest totals, items and dates."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Changes made with bulk database operations by some imports and integrations do not produce ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["*.updated"]}," events. The REST API's delta sync (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["lastUpdatedAt"]},") remains the way to catch everything."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"testing","__idx":7},"children":["Testing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Send test"]}," on an endpoint queues a real delivery of type ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["test"]}," with a sample order and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"test\": true"]},", attempts it immediately and shows you the response. The ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Deliveries"]}," log on each endpoint shows every delivery with its status, attempts, the endpoint's last response and the envelope that was sent."]}]},"headings":[{"value":"Webhooks","id":"webhooks","depth":1},{"value":"Registering an endpoint","id":"registering-an-endpoint","depth":2},{"value":"The delivery","id":"the-delivery","depth":2},{"value":"Verifying the signature","id":"verifying-the-signature","depth":2},{"value":"Retries and failures","id":"retries-and-failures","depth":2},{"value":"Idempotency and ordering","id":"idempotency-and-ordering","depth":2},{"value":"Events","id":"events","depth":2},{"value":"Testing","id":"testing","depth":2}],"frontmatter":{"seo":{"title":"Webhooks"}},"lastModified":"2026-10-28T02:49:03.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/webhooks","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}