Webhooks
Last updated
Last updated
Important Updates
đŖ Shopify REST DeprecationA 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.
Mechanic's webhook API includes CORS support for all origins, making these requests available for use in online user experiences.
This article is an introduction to webhooks. To get started quickly, see Creating a Mechanic webhook.
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
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.
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
.
In "Full request" mode, event data is set to a hash with the following keys:
Key | Type | Notes |
---|---|---|
| Base64-encoded string | The raw request body, encoded in base64 |
| Hash or null | The interpreted set of structured parameters from the request body, or null if parsing fails for any reason |
| String | The IP address of the requesting client |
| Hash | Represents the request headers, keyed by lowercased header names, containing arrays of string values (â ī¸ see warning below) |
| String or null | The MIME type of the request as interpreted from the |
| String or null | Contains everything after the "?" character in the request URL, or null if no such value was found |
| Hash or null | Contains the interpreted set of structured parameters from the query string, or null if none were found |
| UUID string | Uniquely identifies the request, having the same value found in the original webhook request response in the |
| UUID string | Identifies the Mechanic webhook which handled the request |
Decode the base64-encoded request body with Liquid, using Mechanic's decode_base64 filter.
Mechanic's webhook request header representation has an important limitation: the array of header values 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.
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 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 content
mime_type
â The MIME type of the file, as declared in the headers for that file
name
â The original name of the file, as declared in the headers for that file
size
â An integer reflecting the size of the file in bytes
Decode base64-encoded file content with Liquid, using Mechanic's decode_base64 filter.
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
.
Client | Webhook suffix | Behavior notes | |
Asana | asana | Supports the | |
Ship24 | ship24 | Supports HEAD requests for webhook verification |
With cURL:
With fetch:
With jQuery:
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.
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
.
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-id
response header in your client code, and by referencing event.webhook_request_id
in 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.