Mechanic webhooks
Receive data from external services and trigger Mechanic tasks via webhooks.
A Mechanic webhook allows data to be submitted directly to Mechanic, resulting in a new event having a particular topic, containing the submitted data. Webhooks are called with simple HTTP POST requests, which means they can be called from any programming language, and from many applications. This makes Mechanic an integration endpoint for your Shopify stack — any system that can make an HTTP POST (an ERP, a CRM, a fulfillment service, a form builder) can trigger Mechanic tasks and pass along data. Combined with the HTTP action for outbound requests, this gives you bidirectional integration with any API-accessible service.
Mechanic's webhook API includes CORS support for all origins, making these requests available for use in online user experiences. For securing webhooks against unauthorized access, see Securing Mechanic webhooks.
Looking for custom Shopify webhooks?
Two different features in Mechanic share the word "webhooks" — make sure you're on the right page.
This page (Mechanic webhooks) — inbound HTTP from any system. Any service that can POST to a URL (a form builder, an ERP, a CRM, a fulfillment service) can trigger Mechanic tasks via these. Creates
user/...events.Custom Shopify webhooks — Shopify-side filtering and payload customization for Shopify's own webhook deliveries. Trim payloads with
include_fields, filter at Shopify (e.g. onlystatus:activeproducts), receive metafields and metaobject events. Also createsuser/...events.
Quick decision: data coming from Shopify? Start with a regular shopify/... task subscription. Use Custom Shopify webhooks only when Shopify needs to filter or reshape the delivery first. Data coming from anywhere else? Stay here.
Storefront form submissions
Storefront forms let you build customer-facing forms visually in Mechanic and place them in your theme. In Submission settings, select an ordinary Mechanic webhook. The storefront posts to that webhook URL, and its event topic determines which subscribed tasks receive the answers. Forms uses the same webhook ingress and event processing as any other sender.
For task authors, answers appear under event.data.fields in Auto mode, or event.data.body.fields in Full request mode. Each answer uses the field's data key. Keep those keys stable once tasks depend on them; labels can change independently.
These are multipart form submissions:
Scalar answers are strings, including numbers and checkbox values (
"true"or"false").Checkbox groups are arrays; empty groups and unselected files are omitted. Hidden conditional fields are omitted too.
Address fields contain their component values in a nested hash.
Uploaded files use the standard webhook file format. The Forms builder limits files to 3 MB total per submission.
form.ididentifies the form,form.revisionidentifies its published version, andsubmission_ididentifies the browser's submission attempt. In Full request mode, these are underevent.data.bodyalong with the answers.
Treat all submitted data as visitor input and validate what your task needs. Form visibility determines whether the theme shows a form; it does not authenticate requests to its public webhook. A submitted email address or identifier does not establish the visitor's identity. The browser's submission ID is useful for correlation; it does not make webhook delivery or task actions run exactly once.
The form's confirmation acknowledges receipt, not completed task actions. See Responses for how queued processing works, and the Forms guide for email, Google Sheets/Drive, and Shopify metaobject tasks.
Cart contents and customer context
With Include the cart with each submission enabled, the multipart body also contains cart as a JSON string and customer_context as a signed string. In Auto mode, read event.data.cart; in Full request mode, read event.data.body.cart. Parse the cart with parse_json. It contains up to 100 lines and 64 KB, including product/variant IDs, quantities, properties, and subscription/bundle indicators. Prices, discounts, and the private cart token are omitted.
Cart contents and answers remain visitor input. To link a Shopify customer, use event.storefront_form_customer rather than trusting an entered email or customer ID. This helper verifies the context only when your task reads it. The submission is still an ordinary webhook event; other subscribed tasks are unaffected.
The cart quote walkthrough uses the Create a draft order from a storefront form task, which validates the cart and lets Shopify supply prices.
Configuration

Name — Something to remember this webhook by ✨
Event topic — The topic used for events created via this webhook
Event data mode — Either "Auto" or "Full request"; see below
Webhook URL — A unique, permanent, webhook-specific URL, supplied by Mechanic after creating the webhook
Event data mode
Each webhook has a choice of modes used to translate request data into event data.
Auto (default)
In "Auto" mode, event data is the result of merging an interpreted hash of parameters from the request body with an interpreted hash of parameters from the request query string.
If no parameters from the request body are found, or if parsing the request body fails for any reason, event data is set to parameters from the request query string.
If no structured parameters are found from either the request body or the request query string, event data is set to the request body in string form. If the string is blank (i.e. zero-length or consisting only of whitespace), event data is set to null.
Full request
In "Full request" mode, event data is set to a hash with the following keys:
body_base64
Base64-encoded string
The raw request body, encoded in base64
body
Hash or null
The interpreted set of structured parameters from the request body, or null if parsing fails for any reason
client_ip
String
The IP address of the requesting client
headers
Hash
Represents the request headers, keyed by lowercased header names, containing arrays of string values (⚠️ see warning below)
mime_type
String or null
The MIME type of the request as interpreted from the content-type request header, or null if that header was not found
query_string
String or null
Contains everything after the "?" character in the request URL, or null if no such value was found
query
Hash or null
Contains the interpreted set of structured parameters from the query string, or null if none were found
request_id
UUID string
Uniquely identifies the request, having the same value found in the original webhook request response in the x-request-id header
webhook_id
UUID string
Identifies the Mechanic webhook which handled the request
Requests
The Mechanic webhook API only accepts POST requests. (All other methods will receive a 405 Method Not Allowed response.)
Mechanic's webhook API includes CORS support for all origins, making these requests available for use in online user experiences.
File uploads
File uploads are supported via multipart/form-data webhook requests. Each uploaded file will be represented in event data (regardless of event data mode) as a structured hash having the following keys:
content_base64— A base64 string representation of the file contentmime_type— The MIME type of the file, as declared in the headers for that filename— The original name of the file, as declared in the headers for that filesize— An integer reflecting the size of the file in bytes
Client-specific endpoints
When configuring an integration with external apps and services, some require specific behavior from webhook hosts – usually for the purposes of validating a webhook before it's enabled. Mechanic includes specific support for some known webhook clients; request new ones at mechanic.canny.io.
A webhook invocation signals its client selection via a path suffix. Given a webhook URL of webhooks.mechanic.dev/0000..0000, a client-specific endpoint for Ship24 (for example) would be available at webhooks.mechanic.dev/0000..0000/ship24.
Examples
With cURL:
With fetch:
With jQuery:
Responses
A properly-formatted webhook request will always receive a 204 No Content response, even in the case of an incorrect webhook ID in the URL.
If an active webhook ID was used, then an event will be created with the submitted data. The event will be run asynchronously, along with any generated task and action runs that follow.
Webhook request ID
All POST requests to webhooks.mechanic.dev will receive an x-request-id response header, containing a UUID. This ID can be used as a search term when looking up a Mechanic event, and can be referenced in Liquid as a part of the Event object via event.webhook_request_id.
Retrieving run results
The webhook ingress API is solely for ingesting data to form a new event. Because of this, the webhook response necessarily does not contain any data resulting from the runs that might follow. (To further explain the point: there could be zero task runs that follow, or many, and there are no hard guarantees for when those runs would finish.)
This means that the caller must use another avenue for retrieving the results of any generated runs. In general, there are three options for this:
For a consistently re-occurring call with a single caller, the task responding to the webhook event may write its results to the Mechanic cache, allowing the caller to retrieve results using a cache endpoint.
For calls with variable or multiple callers, use the webhook request ID by reading the
x-request-idresponse header in your client code, and by referencingevent.webhook_request_idin your task's Liquid code in. Tasks responding to the webhook event should store their results keyed by that UUID, using an external storage mechanism (possibly via the HTTP or FTP actions).For calls triggered by customer activity on an online Shopify storefront, consider (a) requiring the customer to be logged in, (b) sending the customer ID in the webhook request data, (c) storing task results in a customer metafield (using the Shopify action), and (d) using storefront Liquid to render the content of that metafield, polling until a value is present.
Last updated
Was this helpful?