How to Build a Webhook-Triggered Order Processing Workflow

Process orders automatically when they arrive via webhook.

What This Integration Does

When an order comes in through a storefront, marketplace, or custom checkout, several downstream things usually need to happen at once: the order has to land in the ERP, inventory has to be decremented, the customer needs a confirmation, and the warehouse needs the pick list. Doing this synchronously inside the checkout request is fragile and slow. Doing it in a Spojit webhook-triggered workflow keeps the checkout fast, runs the downstream steps reliably with retries, and gives you a clean audit log of every order that came through.

The pattern is simple: a Webhook trigger receives the order JSON, a Condition validates it, a Parallel node fans the work out into independent branches (ERP, email, inventory), and a Response node closes the loop back to the storefront so it knows the order was accepted. Failures in any branch are caught and routed to a notification or a dead-letter collection without affecting the other branches.

Prerequisites

  • A storefront or order-source that can send a webhook on new orders - shopify, woocommerce, bigcommerce, or a custom checkout that POSTs JSON.
  • An ERP connection - netsuite, an internal API via http, or another business system.
  • An email path - resend send-email, smtp send-email, or the built-in Send Email node.
  • A notification channel for failures - typically slack send-message.

Step 1: Configure the Webhook Trigger

Create the workflow, drop a Trigger node, and set its type to Webhook. Save and copy the generated URL into your storefront's webhook config (in Shopify, under Settings > Notifications > Webhooks, choose the Order created event). To reject unauthenticated requests, attach a signing connection to the trigger so Spojit verifies the request HMAC before it reaches your workflow. Spojit ships signing schemes for Spojit, Shopify, GitHub, Slack, and Custom; pick Shopify here and add the connection that holds your storefront's signing secret. A verified webhook returns 202 with an executionId to the caller immediately, then the rest of the workflow runs.

Step 2: Validate the Payload

The Webhook trigger exposes the parsed JSON body as {{ input }}. Add a Condition node right after the trigger that checks required fields and basic sanity rules: {{ input.id }} is non-empty, {{ input.email }} looks like an email (use the validation connector's email tool for a real check), {{ input.total }} > 0, and line items aren't empty. Route invalid payloads to a slack send-message alert so they can be investigated rather than silently dropped.

Step 3: Look Up or Create the Customer

Before fan-out, resolve the customer in your ERP so each branch has a consistent ID to reference. A Connector node calling netsuite list-customers filtered by email returns either an existing record or empty; follow with a Condition that calls netsuite create-customer on the empty branch. Extracting this into a Subworkflow (e.g. Shared: Customer Lookup or Create) keeps the main workflow tidy.

Step 4: Fan Out with a Parallel Node

Add a Parallel node with three branches that can run independently:

  • ERP branch - netsuite create-record for the sales order, mapping line items, customer ID, totals, and shipping address.
  • Confirmation branch - resend send-email to the customer with the order summary, or the built-in Send Email node if you do not need a custom sending domain. Use a Transform node to build the body from {{ input }}.
  • Inventory branch - for each line item, call shopify adjust-inventory (or your warehouse system's equivalent) to decrement stock. Wrap in a Loop over the line items.

If you also need a warehouse pick list or shipping label, add it as a fourth branch via shipstation create-order or shippit create-order.

Step 5: Handle Branch-Level Failures

Inside each branch, add a Condition right after the main Connector call to check success. On failure: log the input and error to a mongodb insert-documents dead-letter collection and send a slack send-message to the ops channel. Don't fail the whole workflow on a single branch error - the storefront has already accepted the order, and you want the other branches to complete. Keep failure metadata explicit so a later replay workflow can pick up where this one left off.

Step 6: Return a Response to the Storefront

End the workflow with a Response node returning a small JSON acknowledgement to the storefront's webhook call, for example { "received": true, "internalId": "{{ erp.orderId }}" }. The Response node lets you reply synchronously even though the fan-out work happened first. If you want to ack faster, move the Response node above the Parallel node so the storefront gets its acknowledgement straight away and accept that the slower branches finish on their own afterwards.

Tips

  • Use an idempotency check on the ERP create step - if the storefront retries the webhook, you don't want two orders. Look up by the storefront's order ID before creating.
  • Storefronts have webhook delivery timeouts (Shopify is 5 seconds). If your ERP is slow, ack the webhook with Response first, then run the heavy work.
  • For high-volume stores, set the trigger's concurrency cap so a burst of orders doesn't fan out into thousands of concurrent ERP calls.
  • Use the date connector's format tool to render order timestamps in the customer's timezone in the confirmation email.

Common Pitfalls

  • Duplicate orders on retry - storefronts retry on non-2xx responses, and without an idempotency check you'll create duplicates. Always look up by source order ID before creating.
  • Signature mismatch - HMAC validation depends on the signing scheme matching your source. Spojit verifies the request against the signing connection you attached, so choose the scheme that matches your storefront (for example Shopify), or use the Custom scheme for a bespoke checkout.
  • Inventory negative race conditions - parallel orders for the last item in stock both decrement and now you're oversold. Either gate inventory updates through a serialised Subworkflow or accept the risk and reconcile in a separate sweep.
  • Partial failures hidden from the customer - if the ERP failed but the email went out, the customer thinks the order is good. Make the confirmation branch wait until the ERP branch succeeds, or send a different email on partial success.

Testing

Hit the trigger URL with a small representative order payload using curl or the storefront's test-event feature first. Inspect the execution log to see each branch and confirm the ERP record, the confirmation email, and the inventory adjustment all landed as expected. Then deliberately break one branch (point the ERP at an invalid URL temporarily) and confirm the failure path logs to Slack and the dead-letter collection without taking the rest of the workflow down.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.