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.
This article is an introduction to webhooks. To get started quickly, see Creating a Mechanic webhook.
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.
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.
Changing a webhook's event data mode takes effect immediately for all incoming requests. It does not apply retroactively, i.e. it has no impact on webhook events that were received prior to the change.
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
Decode the base64-encoded request body with Liquid, using Mechanic's [decode\_base64](liquid/filters/#base64-decode_base64) filter.
Mechanic's webhook request header representation has an important limitation: the array of values for each header is currently limited to a size of one (1). If multiple request headers are given using the same header name, their values will be concatenated with commas and represented in a single string, as the sole array element.
This means that a request which defines both X-Foo: Bar and X-Foo: Baz headers will be represented thusly:
Let us first acknowledge that this is ridiculous. π― β
As of this writing (2023-03-08), an upstream provider of Mechanic's does not have proper support for requests containing repeated header names. Mechanic's behavior here is a compromise chosen (1) to allow us to resolve this in the future without requiring a change to the format of this representation, and (2) for consistency with HTTP action's response format.
When this issue is resolved, the header example above will be represented as follows:
Task code that reads webhook request headers should take these two possible representations into account.
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
Decode base64-encoded file content with Liquid, using Mechanic's [decode\_base64](liquid/filters/#base64-decode_base64) filter.
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?