Skip to content
Docs Check signed webhooks and filter calls

Check signed webhooks and filter calls

Refuse a webhook call that does not come from its service by checking its signature, and take only the calls you want, such as GitHub’s new issues.

Check a webhook’s signature and take only some calls

A signed webhook proves that a call comes from its service. Services such as GitHub and Shopify sign each call: they send, in a header, a code worked out from what they send and a secret only you and they know. An incoming webhook can check the code, so a call that does not come from the service is refused, even from someone who has the URL. An incoming webhook can also take only some of the calls, such as GitHub's new issues and not the rest. For the users who build the base, on a webhook's automation (Make an item from each incoming webhook):

  1. Click Settings, then Secrets, and add the service's signing secret, such as GITHUB_HOOK, saying It checks calls that come in (Store the keys of other services). Only such a secret checks a signature: one that is sent somewhere is refused, with "the secret GITHUB_HOOK does not check calls that come in", and so is a name the base has no secret for.
  2. In the automation, turn on Check the signature. Give the Header the service signs in, such as X-Hub-Signature-256, and the Encoding it writes the code in, Hex or Base64, as the service's documentation says (Use GitHub's and Use Shopify's fill both in), then pick the Signing secret.
  3. Under Only if the call matches, click Add condition for each condition on what comes in: it reads the Body, by a path, such as action or issue.labels.0.name, or a Header, by its name, such as X-GitHub-Event; then an operator, equals, does not equal, is one of (values separated by commas), contains, is empty or is not empty; and a value. Each must hold.
  4. Save the automation.

Limits and details

  • A call whose signature is missing or wrong is refused with "Invalid signature" and makes nothing.
  • A call that misses a condition is answered as received, so the service does not send it again, and makes nothing either.
  • A condition compares text: a number or true and false as written, a header whatever its capitals, and a value the call does not have is empty.
  • A webhook with neither a signature nor conditions takes every call to its URL.

Ask the assistant in your words, such as "only take GitHub's new issues, checked with the GITHUB_HOOK secret": it proposes the signature and the conditions on a card, in plain words, for you to apply.

Make an item from each new GitHub issue

A signed GitHub webhook can make a quote request from each new issue. The example shop's GitHub issues is this:

  1. Make up a long random value and add it in Secrets as GITHUB_HOOK, checking calls that come in.
  2. In the automation, Check the signature with the header X-Hub-Signature-256, Hex, and GITHUB_HOOK. Add two conditions: the header X-GitHub-Event equals issues, and the body's action equals opened. Take the quote request's values from {{payload.issue.title}} and {{payload.issue.html_url}}.
  3. In GitHub, on the repository's Settings, Webhooks, click Add webhook. The Payload URL is the webhook's URL, the Content type application/json, and the Secret the same value as GITHUB_HOOK. Pick the Issues event, or leave the default: the conditions keep only new issues.

Make an item from each new Shopify order

A signed Shopify webhook can make a quote request from each new order. The example shop's Shopify orders is this:

  1. In Shopify, under Settings, Notifications, Webhooks, create a webhook for the event Order creation, in JSON, with the webhook's URL. Copy the key Shopify says your webhooks are signed with; for an app of your own, its client secret.
  2. Add it in Secrets as SHOPIFY_HOOK, checking calls that come in.
  3. In the automation, Check the signature with the header X-Shopify-Hmac-Sha256, Base64, and SHOPIFY_HOOK, and take the values from {{payload.name}} and {{payload.email}}.

Keep a Shopify store’s stock in step with yours

With the add-on Store sync (it needs Stock, which Inventory, Online shop and Small production have), a Shopify store and your base keep one stock: each order the store sends lowers the stock here, once, and each change of the stock here, a sale, goods received or a count, goes to the store within a minute. The add-on's webhook checks Shopify's signature, so its secret comes first:

  1. In Shopify, under Settings, Apps and sales channels, Develop apps, add a custom app for your base. Give it the Admin API scopes write_inventory and read_inventory, install it, and copy its Admin API access token.
  2. In the base, click Settings, then Secrets. Add the token as SHOPIFY_TOKEN, sent to your store's host, such as your-shop.myshopify.com. Add a long random value of your own as STORESYNC_HOOK, checking calls that come in. Add the same host under Allowed hosts in Settings, General.
  3. In Shopify, under Settings, Notifications, Webhooks, create a webhook for the event Order creation, in JSON, with the URL https://<your base's address>/api/hooks/df6e2bf7-085c-54dc-9366-e9213061991c/<the value of STORESYNC_HOOK>. Copy the key Shopify says your webhooks are signed with and add it in Secrets as SHOPIFY_HOOK, checking calls that come in.
  4. Add the add-on Store sync (Modules). Without SHOPIFY_HOOK in Secrets it is refused with "the base has no secret SHOPIFY_HOOK".
  5. In the base, open Stores and add the store: its name, the kind Shopify, its host, and its Store location id, the number at the end of the location's address in Shopify's Settings, Locations. Access token secret and Signing secret hold the names SHOPIFY_TOKEN and SHOPIFY_HOOK, never the values.
  6. On each product that the store sells, give Store item id, the inventory item id of its variant in Shopify, and a Store SKU only when the store's SKU is not the product's.

What happens then

  • Each new order is a Store order. Each line whose SKU is a product's makes a stock movement Sold of its quantity (with Inventory, sold through Online shop), and What it made says what each line did. Shopify sends an order again when it gets no answer in time: the second call makes nothing new.
  • With Inventory and Bill of materials, a kit sold in the store takes its parts out of stock, as Record a sale does, and a kit has no Store item id: give it to each part, and Shopify works out the kit's stock from its parts.
  • A call whose signature is wrong is refused with "Invalid signature" and makes nothing.
  • Each change of a product's On hand sends the new level to every connected store, the one that sold it too. The product shows Level sent, Sent to stores, each store's answer, and Level the stores took; the store shows its Last sent and Last answer. A store that refuses the level is said there, and the level the stores took stays as it was.
  • A store whose host is not under Allowed hosts, or whose token's secret is not sent to its host, stops the call: the product's Stores' answer stays at "Waiting to send", and the level goes to no store until you fix the host or the secret, or turn off Connected on that store.
Loading