+ Integration Docs

Project documentation

Shopify orders,
connected to MuleSoft.

A reliable webhook pipeline that validates Shopify orders, maps line items, and writes both to your database in one transaction.

Documentation prepared byDagnachew · Senior MuleSoft Expert
ShopifyOrder created
MuleSoftValidate and map
DatabaseOrder and items

How it works

One event. One transaction.

Shopify sends an HTTPS webhook when an order is created. Mule validates the request, transforms the payload, and persists the order with its line items.

  1. 01
    Receive

    The HTTP Listener accepts the Shopify orders/create webhook.

  2. 02
    Validate

    The flow rejects payloads that do not contain both id and email.

  3. 03
    Transform

    DataWeave maps the Shopify payload into order and line-item records.

  4. 04
    Persist

    The database connector upserts the order, obtains its key, then upserts every line item.

Environment snapshot

Current live status

The local integration stack is active and currently contains one test order with one line item.

All integration components are runningLocal development environment
Operational
ComponentStatusDetails
MySQLRunningXAMPP MariaDB, PID 5400
Mule AppRunningAnypoint Studio, port 8091
ngrok tunnelRunningwigglier-rose-nonplussedly.ngrok-free.dev
Database contents1 order · 1 line itemCurrent snapshot. Row counts vary across test sessions.

Runtime reference

Configuration in use

Local database, HTTP listener, Shopify webhook, and project-file settings for this integration.

MySQL

src/main/resources/application.properties

Host
localhost
Port
3306
Database
shopify_orders_db
Username
shopify_user
Password
changeme

Development credential. Replace it before production.

HTTP listener

src/main/resources/application.properties

http.port8091

Shopify webhook

Configured manually in Shopify Admin

Event
Order creation
Format
JSON
API version
2026-07 stable
URL
https://wigglier-rose-nonplussedly.ngrok-free.dev/shopify/orders

Project files

Files used to configure, test, and run the order sync.

  • sql/shopify_orders_setup.sqlDatabase schema
  • postman/mulesync-store.postman_collection.jsonManual test requests
  • src/main/mule/global.xmlHTTP listener and MySQL connection
  • src/main/mule/mulesync-store.xmlOrder-sync flow

Integration journey

How the project works, end to end

From checkout to a committed MySQL transaction, every order follows the same controlled path.

  1. Storefront

    Customer places an order

    A customer completes checkout on the connected Shopify store.

  2. Shopify event

    Shopify fires the webhook

    The Order creation event sends a JSON POST automatically.

  3. Public tunnel

    ngrok forwards the request

    The public URL routes the request to localhost:8091.

  4. Mule HTTP listener

    /shopify/orders receives it

    The Mule listener accepts the POST and begins the order flow.

  5. Validation

    Required fields are checked

    The payload must contain id and email, otherwise Mule returns 400.

  6. DataWeave

    JSON becomes database records

    Order and line-item values are normalized into DB-shaped variables.

  7. Transactional upsert

    MySQL stores order and items

    shopify_orders and shopify_order_items update together without duplicate rows during retries.

  8. Confirmation

    Shopify receives HTTP 200

    Mule returns a JSON confirmation containing the order ID and saved item count.

Webhook endpoint

Request contract

POSThttps://your-domain.com/shopify/orders

Shopify delivery headers

X-Shopify-Hmac-Sha256
Shopify's request signature. Add verification to this Mule flow before production.
X-Shopify-Topic
Expected value: orders/create.
X-Shopify-Webhook-Id
Unique delivery ID used for duplicate protection.
shopify.app.toml
[[webhooks.subscriptions]]
topics = ["orders/create"]
uri = "https://your-domain.com/shopify/orders"

Implementation reference

Mule order webhook flow

The current project flow covers validation, mapping, transactional writes, the success response, and global error handling.

MuleSoft Shopify order webhook flow showing validation, order and line-item database writes, success response, and error handlers
mulesync-store.pngOpen full size

Source walkthrough

The Mule flow, step by step.

These snippets come directly from the XML behind the flow image. Each block shows one job in the order pipeline.

Download complete XML
01

Receive the webhook

The listener accepts only POST requests at /shopify/orders. Both success and error responses use the status stored in vars.httpStatus.

Listener · XML
<http:listener
  config-ref="HTTP_Listener_config"
  path="/shopify/orders"
  allowedMethods="POST"
  doc:name="Receive Shopify webhook">
  <http:response statusCode="#[vars.httpStatus default 200]">
    <http:body>#[payload]</http:body>
  </http:response>
  <http:error-response statusCode="#[vars.httpStatus default 500]">
    <http:body>#[payload]</http:body>
  </http:error-response>
</http:listener>
02

Reject incomplete orders

A Choice router checks the minimum payload shape. Missing id or email raises APP:VALIDATION.

Validation · XML
<choice doc:name="Has required fields?">
  <when expression="#[(payload.id default null) == null
    or (payload.email default null) == null]">
    <raise-error
      type="APP:VALIDATION"
      description="Webhook payload is missing required fields (id, email)"
      doc:name="Reject invalid payload"/>
  </when>
</choice>
03

Map Shopify data

DataWeave creates an order object and a clean array of line items. Defaults keep optional Shopify fields from breaking the flow.

Mapping · DataWeave
%dw 2.0
output application/java
---
{
  shopify_order_id: payload.id,
  customer_email: payload.email
    default (payload.contact_email default ""),
  order_number: ((payload.order_number
    default payload.number) default 0) as Number,
  financial_status: payload.financial_status
    default "pending",
  total_price: (payload.total_price default 0) as Number,
  currency: payload.currency default "USD"
}

(payload.line_items default []) map (item) -> {
  shopify_line_item_id: item.id,
  title: item.title default "Unknown Product",
  quantity: (item.quantity default 1) as Number,
  price: (item.price default 0) as Number
}
04

Write without duplicates

ALWAYS_BEGIN makes the order and items one database transaction. The upsert handles Shopify retries without creating another order row.

Order upsert · SQL
INSERT INTO shopify_orders
  (shopify_order_id, customer_email,
   order_number, total_price, currency)
VALUES
  (:shopify_order_id, :customer_email,
   :order_number, :total_price, :currency)
ON DUPLICATE KEY UPDATE
  id = LAST_INSERT_ID(id),
  customer_email = VALUES(customer_email),
  order_number = VALUES(order_number),
  total_price = VALUES(total_price),
  currency = VALUES(currency);
05

Return clear responses

The flow returns 200 after a successful write, 400 for invalid data, 503 for database connectivity, and 500 for any other error.

Error mapping · XML
<error-handler>
  <on-error-continue type="APP:VALIDATION">
    <set-variable variableName="httpStatus" value="#[400]"/>
  </on-error-continue>

  <on-error-continue type="DB:CONNECTIVITY">
    <set-variable variableName="httpStatus" value="#[503]"/>
  </on-error-continue>

  <on-error-continue type="ANY">
    <set-variable variableName="httpStatus" value="#[500]"/>
  </on-error-continue>
</error-handler>

Configuration

Setup checklist

1

Create the Shopify app

Install the app on a development store and grant the order scope required by the webhook topic.

2

Configure Mule properties

Store the Shopify client secret and database credentials in secure configuration properties.

3

Expose the HTTPS listener

Deploy Mule behind a valid TLS endpoint and use its public URL as the webhook destination.

4

Subscribe and test

Register orders/create, send a test delivery, and confirm one order plus all line items are stored.

Operational behavior

Error handling

ScenarioMule errorResponseAction
Missing or invalid fieldsAPP:VALIDATION400 Bad RequestLog the validation failure and return a safe error body.
Database unavailableDB:CONNECTIVITY503 Service UnavailableRoll back the transaction and allow Shopify to retry.
Unexpected failureANY500 Internal Server ErrorLog the correlation ID without exposing internals.

Ready to verify

Test the full delivery path.

Use a Shopify development store, create a test order, then verify the Mule logs, HTTP status, order record, and line-item count.

Webhook setup guide