Shopify Order Routing
This use case demonstrates content-based routing for Shopify order webhooks. Orders are routed to different systems based on their value and topic—high-value orders trigger priority fulfillment and PagerDuty alerts, all orders update inventory, and refunds notify the finance team via Slack.
Architecture
flowchart LR
Shopify[Shopify Webhooks] --> Source[Hookbase Source]
Source --> R1[Route: High-Value]
Source --> R2[Route: Inventory]
Source --> R3[Route: Refunds]
R1 --> |Filter: $500+| D1A[Priority Fulfillment API]
R1 --> |Filter: $500+| D1B[PagerDuty Alert]
R2 --> |All Orders| D2[Inventory Management]
R3 --> |Filter: Refunds| D3["Slack #finance"]Flow:
- Shopify sends order webhooks to Hookbase source endpoint
- Source verifies Shopify HMAC signature
- Three routes evaluate the event in parallel
- Filters match based on order total and topic
- Transforms reshape payloads for each destination system
Step 1: Create the Source
Create a Shopify source with HMAC signature verification:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify Production",
"slug": "shopify-prod",
"description": "Production Shopify order webhooks",
"verificationConfig": {
"type": "shopify",
"secret": "your_shopify_webhook_signing_secret"
}
}'Response:
{
"data": {
"id": "src_shopify456",
"name": "Shopify Production",
"slug": "shopify-prod",
"url": "https://api.hookbase.app/ingest/your-org/shopify-prod",
"verificationConfig": {
"type": "shopify"
},
"createdAt": "2026-02-11T10:00:00Z"
}
}TIP
Configure this URL in your Shopify Admin under Settings → Notifications → Webhooks → Create webhook. Subscribe to orders/create, orders/updated, and refunds/create topics.
Step 2: Create Destinations
Create three destinations for priority fulfillment, inventory, and finance notifications:
Priority Fulfillment API
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/destinations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Priority Fulfillment API",
"type": "http",
"config": {
"url": "https://fulfillment.yourcompany.com/api/priority-orders",
"method": "POST",
"headers": {
"Authorization": "Bearer YOUR_FULFILLMENT_API_KEY",
"Content-Type": "application/json",
"X-Priority": "high"
}
},
"retryConfig": {
"maxAttempts": 5,
"backoffMultiplier": 2,
"initialInterval": 1000
}
}'PagerDuty Alert Destination
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/destinations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "PagerDuty High-Value Orders",
"type": "http",
"config": {
"url": "https://events.pagerduty.com/v2/enqueue",
"method": "POST",
"headers": {
"Content-Type": "application/json"
}
},
"retryConfig": {
"maxAttempts": 3,
"backoffMultiplier": 2,
"initialInterval": 1000
}
}'Inventory Management System
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/destinations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Inventory Management",
"type": "http",
"config": {
"url": "https://inventory.yourcompany.com/api/webhooks/shopify",
"method": "POST",
"headers": {
"Authorization": "Bearer YOUR_INVENTORY_API_KEY",
"Content-Type": "application/json"
}
},
"retryConfig": {
"maxAttempts": 5,
"backoffMultiplier": 2,
"initialInterval": 1000
}
}'Slack #finance Channel
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/destinations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Slack #finance",
"type": "slack",
"config": {
"url": "https://hooks.slack.com/services/YOUR/FINANCE/WEBHOOK"
},
"retryConfig": {
"maxAttempts": 2,
"backoffMultiplier": 1.5,
"initialInterval": 500
}
}'Step 3: Create Filters
High-Value Order Filter ($500+)
Filter for orders with a total price of $500 or more:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/filters \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "High-Value Orders ($500+)",
"conditions": [
{
"field": "headers.x-shopify-topic",
"operator": "in",
"value": ["orders/create", "orders/updated"]
},
{
"field": "total_price",
"operator": "gte",
"value": "500.00"
}
],
"logic": "AND"
}'TIP
Shopify sends total_price as a string (e.g., "749.95"). The filter engine handles string-to-number coercion for comparison operators like gte.
All Orders Filter
Match all order creation and update events:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/filters \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "All Order Events",
"conditions": [
{
"field": "headers.x-shopify-topic",
"operator": "in",
"value": ["orders/create", "orders/updated"]
}
],
"logic": "AND"
}'Refunds Filter
Match only refund events:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/filters \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Refund Events",
"conditions": [
{
"field": "headers.x-shopify-topic",
"operator": "eq",
"value": "refunds/create"
}
],
"logic": "AND"
}'Step 4: Create Routes
High-Value → Priority Fulfillment
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/routes \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify → Priority Fulfillment",
"sourceId": "src_shopify456",
"destinationId": "dst_fulfillment123",
"filterId": "flt_highvalue123",
"transformId": "tfm_fulfillment123",
"enabled": true
}'High-Value → PagerDuty Alert
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/routes \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify → PagerDuty Alert",
"sourceId": "src_shopify456",
"destinationId": "dst_pagerduty123",
"filterId": "flt_highvalue123",
"transformId": "tfm_pagerduty123",
"enabled": true
}'All Orders → Inventory
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/routes \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify → Inventory",
"sourceId": "src_shopify456",
"destinationId": "dst_inventory123",
"filterId": "flt_allorders123",
"transformId": "tfm_inventory123",
"enabled": true
}'Refunds → Slack #finance
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/routes \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify Refunds → #finance",
"sourceId": "src_shopify456",
"destinationId": "dst_slack_finance123",
"filterId": "flt_refunds123",
"transformId": "tfm_refund_slack123",
"enabled": true
}'Step 5: Add Transforms
Priority Fulfillment Transform
Extract order details for the fulfillment system with priority flags:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/transforms \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify → Priority Fulfillment",
"type": "jsonata",
"config": {
"expression": "{\n \"order_id\": $string(id),\n \"order_number\": $string(order_number),\n \"priority\": $number(total_price) >= 1000 ? \"critical\" : \"high\",\n \"total\": $number(total_price),\n \"currency\": currency,\n \"customer\": {\n \"id\": $string(customer.id),\n \"name\": customer.first_name & \" \" & customer.last_name,\n \"email\": customer.email\n },\n \"shipping_address\": {\n \"line1\": shipping_address.address1,\n \"line2\": shipping_address.address2,\n \"city\": shipping_address.city,\n \"state\": shipping_address.province_code,\n \"zip\": shipping_address.zip,\n \"country\": shipping_address.country_code\n },\n \"line_items\": line_items.{\n \"sku\": sku,\n \"title\": title,\n \"quantity\": quantity,\n \"price\": $number(price)\n },\n \"requires_shipping\": line_items[requires_shipping = true] ? true : false,\n \"created_at\": created_at\n}"
}
}'Example Output:
{
"order_id": "5678901234",
"order_number": "1042",
"priority": "high",
"total": 749.95,
"currency": "USD",
"customer": {
"id": "7890123456",
"name": "Jane Smith",
"email": "[email protected]"
},
"shipping_address": {
"line1": "123 Main St",
"line2": "Suite 400",
"city": "San Francisco",
"state": "CA",
"zip": "94105",
"country": "US"
},
"line_items": [
{
"sku": "WIDGET-PRO-001",
"title": "Widget Pro Bundle",
"quantity": 2,
"price": 299.99
},
{
"sku": "ADDON-PREMIUM",
"title": "Premium Add-on",
"quantity": 1,
"price": 149.97
}
],
"requires_shipping": true,
"created_at": "2026-02-11T14:30:00-05:00"
}PagerDuty Alert Transform
Format as a PagerDuty Events API v2 payload:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/transforms \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify → PagerDuty Alert",
"type": "jsonata",
"config": {
"expression": "{\n \"routing_key\": \"YOUR_PAGERDUTY_INTEGRATION_KEY\",\n \"event_action\": \"trigger\",\n \"dedup_key\": \"shopify-order-\" & $string(id),\n \"payload\": {\n \"summary\": \"High-value Shopify order #\" & $string(order_number) & \" - $\" & total_price & \" \" & currency,\n \"severity\": $number(total_price) >= 1000 ? \"critical\" : \"warning\",\n \"source\": \"shopify-hookbase\",\n \"component\": \"order-processing\",\n \"group\": \"e-commerce\",\n \"class\": \"high-value-order\",\n \"custom_details\": {\n \"order_id\": $string(id),\n \"order_number\": $string(order_number),\n \"total_price\": total_price,\n \"currency\": currency,\n \"customer_email\": customer.email,\n \"item_count\": $count(line_items),\n \"created_at\": created_at\n }\n },\n \"links\": [\n {\n \"href\": \"https://your-store.myshopify.com/admin/orders/\" & $string(id),\n \"text\": \"View Order in Shopify\"\n }\n ]\n}"
}
}'Example Output:
{
"routing_key": "YOUR_PAGERDUTY_INTEGRATION_KEY",
"event_action": "trigger",
"dedup_key": "shopify-order-5678901234",
"payload": {
"summary": "High-value Shopify order #1042 - $749.95 USD",
"severity": "warning",
"source": "shopify-hookbase",
"component": "order-processing",
"group": "e-commerce",
"class": "high-value-order",
"custom_details": {
"order_id": "5678901234",
"order_number": "1042",
"total_price": "749.95",
"currency": "USD",
"customer_email": "[email protected]",
"item_count": 2,
"created_at": "2026-02-11T14:30:00-05:00"
}
},
"links": [
{
"href": "https://your-store.myshopify.com/admin/orders/5678901234",
"text": "View Order in Shopify"
}
]
}Inventory Transform
Normalize order data for inventory tracking:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/transforms \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify → Inventory Format",
"type": "jsonata",
"config": {
"expression": "{\n \"event_type\": \"order_placed\",\n \"order_id\": $string(id),\n \"order_number\": $string(order_number),\n \"items\": line_items.{\n \"sku\": sku,\n \"variant_id\": $string(variant_id),\n \"product_id\": $string(product_id),\n \"quantity\": quantity,\n \"fulfillable_quantity\": fulfillable_quantity,\n \"requires_shipping\": requires_shipping\n },\n \"fulfillment_status\": fulfillment_status ? fulfillment_status : \"unfulfilled\",\n \"shipping_method\": shipping_lines[0].title,\n \"warehouse_hint\": shipping_address.country_code = \"US\" ? (shipping_address.province_code $in [\"CA\",\"OR\",\"WA\",\"NV\",\"AZ\"] ? \"west\" : \"east\") : \"international\",\n \"timestamp\": created_at\n}"
}
}'Example Output:
{
"event_type": "order_placed",
"order_id": "5678901234",
"order_number": "1042",
"items": [
{
"sku": "WIDGET-PRO-001",
"variant_id": "44567890123",
"product_id": "8901234567",
"quantity": 2,
"fulfillable_quantity": 2,
"requires_shipping": true
},
{
"sku": "ADDON-PREMIUM",
"variant_id": "44567890456",
"product_id": "8901234890",
"quantity": 1,
"fulfillable_quantity": 1,
"requires_shipping": true
}
],
"fulfillment_status": "unfulfilled",
"shipping_method": "Standard Shipping",
"warehouse_hint": "west",
"timestamp": "2026-02-11T14:30:00-05:00"
}Refund Slack Transform
Format refund events as Slack Block Kit messages for the finance team:
curl -X POST https://api.hookbase.app/api/organizations/{orgId}/transforms \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Shopify Refund → Slack Blocks",
"type": "jsonata",
"config": {
"expression": "(\n $refundTotal := $sum(refund_line_items.(quantity * $number(line_item.price)));\n $isFullRefund := $count(refund_line_items) = $count(order.line_items);\n $color := $isFullRefund ? \"#d73a49\" : \"#e36209\";\n $emoji := $isFullRefund ? \":rotating_light:\" : \":warning:\";\n {\n \"attachments\": [\n {\n \"color\": $color,\n \"blocks\": [\n {\n \"type\": \"header\",\n \"text\": {\n \"type\": \"plain_text\",\n \"text\": $emoji & \" \" & ($isFullRefund ? \"Full Refund\" : \"Partial Refund\") & \" Processed\"\n }\n },\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Order:*\\n#\" & $string(order.order_number)\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Refund Amount:*\\n$\" & $string($round($refundTotal, 2)) & \" \" & order.currency\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Customer:*\\n\" & order.customer.first_name & \" \" & order.customer.last_name\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Reason:*\\n\" & (note ? note : \"_No reason provided_\")\n }\n ]\n },\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*Refunded Items:*\\n\" & $join(refund_line_items.(\"- \" & line_item.title & \" (x\" & $string(quantity) & \") - $\" & $string($round(quantity * $number(line_item.price), 2))), \"\\n\")\n }\n },\n {\n \"type\": \"context\",\n \"elements\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"Refund ID: \" & $string(id) & \" | <https://your-store.myshopify.com/admin/orders/\" & $string(order.id) & \"|View in Shopify>\"\n }\n ]\n }\n ]\n }\n ]\n }\n)"
}
}'Example Output (Slack Message):
{
"attachments": [
{
"color": "#e36209",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": ":warning: Partial Refund Processed"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Order:*\n#1042"
},
{
"type": "mrkdwn",
"text": "*Refund Amount:*\n$299.99 USD"
},
{
"type": "mrkdwn",
"text": "*Customer:*\nJane Smith"
},
{
"type": "mrkdwn",
"text": "*Reason:*\nItem arrived damaged"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Refunded Items:*\n- Widget Pro Bundle (x1) - $299.99"
}
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Refund ID: 9012345678 | <https://your-store.myshopify.com/admin/orders/5678901234|View in Shopify>"
}
]
}
]
}
]
}Step 6: Test the Pipeline
Send a test Shopify order payload to verify routing:
curl -X POST https://api.hookbase.app/ingest/your-org/shopify-prod \
-H "Content-Type: application/json" \
-H "X-Shopify-Topic: orders/create" \
-H "X-Shopify-Hmac-Sha256: test_signature" \
-H "X-Shopify-Shop-Domain: your-store.myshopify.com" \
-d '{
"id": 5678901234,
"order_number": 1042,
"total_price": "749.95",
"subtotal_price": "699.95",
"currency": "USD",
"financial_status": "paid",
"fulfillment_status": null,
"customer": {
"id": 7890123456,
"first_name": "Jane",
"last_name": "Smith",
"email": "[email protected]"
},
"shipping_address": {
"address1": "123 Main St",
"address2": "Suite 400",
"city": "San Francisco",
"province_code": "CA",
"zip": "94105",
"country_code": "US"
},
"line_items": [
{
"id": 1234567890,
"sku": "WIDGET-PRO-001",
"title": "Widget Pro Bundle",
"variant_id": 44567890123,
"product_id": 8901234567,
"quantity": 2,
"price": "299.99",
"fulfillable_quantity": 2,
"requires_shipping": true
},
{
"id": 1234567891,
"sku": "ADDON-PREMIUM",
"title": "Premium Add-on",
"variant_id": 44567890456,
"product_id": 8901234890,
"quantity": 1,
"price": "149.97",
"fulfillable_quantity": 1,
"requires_shipping": true
}
],
"shipping_lines": [
{
"title": "Standard Shipping",
"price": "50.00"
}
],
"created_at": "2026-02-11T14:30:00-05:00"
}'TIP
For production testing, create a test order in Shopify Admin or use the Shopify CLI: shopify app dev with test webhooks enabled.
Verify Deliveries:
curl https://api.hookbase.app/api/organizations/{orgId}/deliveries?limit=10 \
-H "Authorization: Bearer YOUR_TOKEN"For a $749.95 order, you should see:
- Delivery to Priority Fulfillment API (matches $500+ filter)
- Delivery to PagerDuty (matches $500+ filter)
- Delivery to Inventory Management (matches all orders filter)
- No delivery to Slack #finance (not a refund)
Production Considerations
1. Enable Deduplication
Shopify may retry webhooks if it does not receive a timely response. Prevent duplicate processing:
curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/sources/src_shopify456 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"deduplicationConfig": {
"enabled": true,
"keyPath": "id",
"windowSeconds": 86400
}
}'2. Adjust the Value Threshold
The $500 threshold in this example is a starting point. Update the filter to match your business:
curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/filters/flt_highvalue123 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"conditions": [
{
"field": "headers.x-shopify-topic",
"operator": "in",
"value": ["orders/create", "orders/updated"]
},
{
"field": "total_price",
"operator": "gte",
"value": "1000.00"
}
],
"logic": "AND"
}'3. Configure Circuit Breaker for Fulfillment
Protect your fulfillment API during sale events when order volume spikes:
curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/destinations/dst_fulfillment123 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"circuitBreakerConfig": {
"enabled": true,
"failureThreshold": 10,
"windowSeconds": 60,
"resetTimeoutSeconds": 300
}
}'4. Set Up Failover for Critical Orders
Ensure high-value orders always reach fulfillment, even if the primary endpoint is down:
curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/routes/rte_fulfillment123 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"failoverConfig": {
"enabled": true,
"destinationId": "dst_fulfillment_backup123",
"triggerAfterAttempts": 3
}
}'Related Guides
- Shopify Integration - Provider-specific setup and signature verification
- Transforms - JSONata syntax and advanced examples
- Filters - Content-based routing and complex conditions
- Deduplication - Prevent duplicate event processing
- Failover - Ensure critical events are delivered
- Circuit Breaker - Protect downstream services during traffic spikes
- Notification Channels - Configure delivery alerts