Skip to content

Shopify Webhook

The Shopify Webhook trigger fires your workflow whenever a selected event occurs in your store. Any Shopify webhook topic is supported.

For Shopify Webhook triggers, data is the raw Shopify webhook payload passed directly as the top-level object. There is no wrapper — you access order fields, customer fields, etc. directly:

class Workflow {
async start(data, headers, api) {
// data IS the order (for orders/* topics)
api.log('Order ID:', data.id);
api.log('Total:', data.total_price);
api.log('Customer email:', data.email);
}
}

The headers object includes all Shopify webhook headers:

HeaderDescription
x-shopify-shop-domainYour store’s myshopify.com domain
x-shopify-topicThe webhook topic, e.g. orders/paid
x-shopify-webhook-idUnique ID for this delivery
x-shopify-attempt-numberWhich retry attempt this is (1 = first)
class Workflow {
async start(data, headers, api) {
const shop = headers['x-shopify-shop-domain'];
const topic = headers['x-shopify-topic'];
api.log(`Received ${topic} from ${shop}`);
}
}
CategoryTopics
Ordersorders/create, orders/updated, orders/paid, orders/fulfilled, orders/cancelled, orders/partially_fulfilled
Customerscustomers/create, customers/update, customers/delete
Productsproducts/create, products/update, products/delete
Inventoryinventory_levels/update, inventory_items/update
Refundsrefunds/create
Checkoutscheckouts/create, checkouts/update, checkouts/delete
Fulfilmentsfulfillments/create, fulfillments/update
Collectionscollections/create, collections/update, collections/delete

Calling the Shopify API from within the workflow

Section titled “Calling the Shopify API from within the workflow”

Use the global fetch() with your store’s myshopify.com URL. The platform automatically injects the X-Shopify-Access-Token header — no manual token management needed. Use env.SHOPIFY_STORE and env.SHOPIFY_API_VERSION which are always available:

class Workflow {
async start(data, headers, api) {
// Token is injected automatically — env.SHOPIFY_STORE is "mystore.myshopify.com"
const resp = await fetch(
`https://${env.SHOPIFY_STORE}/admin/api/${env.SHOPIFY_API_VERSION}/graphql.json`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `mutation UpdateOrderNote($input: OrderInput!) {
orderUpdate(input: $input) {
order { id note }
userErrors { field message }
}
}`,
variables: { input: { id: `gid://shopify/Order/${data.id}`, note: 'Processed by JsWorkflows' } },
}),
}
);
const { data: gqlData } = await resp.json();
const { order, userErrors } = gqlData.orderUpdate;
if (userErrors.length) { api.log('Errors:', userErrors); return; }
api.log('Updated note:', order.note);
}
}

Shopify retries undelivered webhooks up to 19 times over 48 hours. JsWorkflows automatically deduplicates deliveries using the x-shopify-webhook-id header — if a webhook ID has already been processed, subsequent retries are silently ignored within a 120-second window.