Webhooks and the Snowflake connector
Overview
Webhooks are messages sent via a HTTP request to an external system. They are normally used to notify systems when something happens in order to trigger an action.
Webhooks use the “push” model, where a request is made to an external system, as opposed to the “pull” model, when an external system makes a request to an API.
For more information, see:
What are webhooks? (article from Zapier)
What is a webhook? (article)
It’s important to distinguish between a webhook subscription and a webhook invocation:
A webhook subscription is a configuration record that specifies when and where the messages are sent. The subscriptions are normally set up initially and rarely updated. They’re managed by the /api/v1/webhooks API.
A webhook invocation is the event triggered at a specific time with a specific payload. A single webhook subscription may trigger several webhook invocations.
API
The API to manage webhook subscriptions is /api/v1/webhooks.
See the Inventory Planner public APIs document for more information on how to generate a token and access it. Note that any requests to the webhooks API require full access to the Inventory Planner account.
Operations
Operation | Description |
GET /api/v1/webhooks | Get a list of registered webhook subscriptions, paged |
GET /api/v1/webhooks/{id} | Get a specific webhook subscription using its ID |
POST /api/v1/webhooks | Create a new webhook subscription. An ID will be automatically generated. |
PUT /api/v1/webhooks/{id} | Update an existing webhook subscription |
DELETE /api/v1/webhooks/{id} | Delete a specific webhook subscription using its ID |
Webhook structure
The following is an example of the body of a POST request used to create a new webhook subscription:
{
"address": "https:\/\/hooks.zapier.com\/hooks\/catch\/2815839\/362u5xw\/",
"fields": "id,reference,items.id,items.sku",
"topic": "purchase-orders\/connection-save",
},
The following is an example of a single webhook payload returned by a GET request:
{
"id": "645decc9128198c9a30d8022",
"address": "https:\/\/hooks.zapier.com\/hooks\/catch\/2815839\/362u5xw\/",
"fields": "id,reference,items.id,items.sku",
"topic": "purchase-orders\/connection-save",
"created_at": "2023-05-12T07:37:45+00:00",
"updated_at": "2023-05-15T10:53:20+00:00",
"version": 1,
"removed": false,
},
The following are the public fields for webhooks:
Field | Description |
id | A unique identifier for a webhook, automatically generated |
topic | A webhook topic in the “resource/event” format (for example, purchase-orders/connection-save) |
address | The destination URI where the webhook should be sent |
fields | A comma-separated list of resource fields to send. If not specified, only the identifier field of the resource will be sent by default. |
filter | A json object that describes which collection resource filter to send webhooks for |
Webhook invocation headers
When a webhook invocation is triggered, Inventory Planner makes a POST request to the webhook subscription address URI, providing the requested fields in the payload. The following is an example of a webhook payload:
{
"topic": "purchase-orders\/connection-save",
"created_at": "2023-05-16T06:29:08+00:00",
"resource": {
"reference": "1023",
"expected_date": "2023-08-27",
"items": [
{
"sku": "SKU-88DAFB8E",
"replenishment": 10
},
{
"sku": "BU234",
"replenishment": 20
}
],
"id": "6459de7f1d3e1b51f00dae6d"
},
}
Additionally, the following HTTP headers are provided in the request:
Header | Description |
X-InventoryPlanner-Webhook-Id | The webhook invocation unique identifier, which remains the same for all retries of the webhook |
X-InventoryPlanner-Webhook-Hash | The webhook signature created using the webhook secret and request data |
X-InventoryPlanner-Webhook-Created-At | The date/time when the webhook event was raised |
Here is an example of the headers:
x-inventoryplanner-webhook-created-at: 2023-05-16T06:29:08+00:00
x-inventoryplanner-webhook-hash: XXhZqkDKWSagboBdGTbmD4MItx6iakX3+x1CFvBpSXo=
x-inventoryplanner-webhook-id: 287a4126-93c4-4c71-b30d-ca4f78e2391c
The webhook invocation expects a 200 HTTP response code. If it’s unsuccessful, the webhook is retried several times with exponentially increasing delays. If all the retries are unsuccessful, the webhook is removed and a new webhook must be created once the problem is resolved.
Signature and verification
Inventory Planner signs webhook messages so that a listener can verify the webhook was sent from Inventory Planner.
A signature is created using the webhook’s secret key and request data, and is included in the webhook request as the X-InventoryPlanner-Webhook-Hash header. The webhook listener can compute the request signature and compare it with the value sent in the request header.
A webhook signature is a base64-encoded HMAC-SHA256 digest of the webhook request data. If the listener is using PHP, the signature can be calculated using the following code:
$calculatedSignature = base64_encode(hash_hmac('sha256', $requestData, WEBHOOK_SECRET_KEY, true));
The secret key used to sign requests is managed using the webhooks secret API.
Webhooks secret API
The webhooks secret API is the API for managing the secret for webhooks used for the signature.
Resource: /api/v1/webhooks-secret
POST: Generates new random secret. The secret is only available once in the response.
DELETE: Deletes the current secret
GET: Returns null or '< Hidden >'