---
title: "Create your first webhook - Workflow Webhooks"
description: "Step-by-step: create a webhook endpoint, authenticate it, map your payload and connect it to a Shopify Flow workflow."
canonical: "https://docs.workflow-webhooks.app/getting-started"
---

# Create your first webhook

This walks you from an empty app to a Shopify Flow workflow that runs when your own
system says so. About ten minutes.

> [!NOTE]
> Workflow Webhooks needs **Shopify Flow** installed. It is free from Shopify and is what
> actually runs your automation - this app is the bridge that lets outside systems start it.

## 1. Create a webhook

**Webhooks -> Create webhook**. The page first asks **what will call this webhook**, and sets
it up to match:

| Your answer | What you get |
| --- | --- |
| **An automation tool** (n8n, Make, Zapier, your own code) | A generated token, ready to paste into the tool |
| **A service that signs its webhooks** (Stripe, GitHub, ...) | Signature verification for the service you pick - see [Verifying signed webhooks](https://docs.workflow-webhooks.app/signature-verification.md) |
| **A browser or storefront script** | CORS switched on - see [CORS, the app proxy URL and browser calls](https://docs.workflow-webhooks.app/cors-and-app-proxy.md) |
| **Nothing - run it on a schedule** | A webhook that fetches a URL on a timer; its Schedule tab opens next - see [Scheduled URL polling](https://docs.workflow-webhooks.app/scheduled-polling.md) |
| **Something else, or decide later** | You choose the authentication yourself |

Give it a name you will recognise later ("Wallet card reminder", "Contact form") and save.
Every setting can be changed afterwards.

You now have a **webhook URL** ending in a short code, for example
`https://.../webhook/ab12cd34`. That URL is the endpoint your system POSTs to.

![The Create webhook page asking What will call this webhook, with Nothing - run it on a schedule selected and a note that the Schedule tab opens next](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/88723a585a173807.png)
*Creating a webhook starts with what will call it. The answer sets up matching authentication; "Nothing - run it on a schedule" opens the Schedule tab next.*

![The webhook editor: name and authentication on the left, the Endpoint card with status, webhook URL and webhook ID on the right, above Live Preview, Test and Usage](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/e05e58adb26a2069.png)
*The webhook editor. Settings are on the left; the Endpoint card on the right holds the webhook URL to give to the sender and the webhook ID you use in Shopify Flow.*

## 2. Choose how callers prove who they are

Open the webhook and pick an authentication method. See [Authentication](https://docs.workflow-webhooks.app/authentication.md) for the
full comparison - the short version:

- **Static token** - right for almost everyone. Press the generate button, copy the token,
  send it in the `X-Api-Key` header.
- **HMAC SHA-256** - for senders that sign their requests (Stripe, GitHub and similar).
- **None** - testing only. Anyone with the URL can fire your workflow.

## 3. Tell us which fields you care about

Under **Advanced Settings**, map up to four fields out of your JSON payload. If your
system sends:

![The Advanced Settings tab with Field 1 to Field 4 mapped to orderId, status, total and note](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/5e2db99bbebd081c.png)
*Advanced Settings: map up to four values from the request body. They arrive in Shopify Flow as fieldOne to fieldFour.*

```json
{ "customer": { "email": "someone@example.com" }, "orderId": "1001" }
```

map `fieldOne` to `orderId` and `fieldTwo` to `customer.email` - nested paths use dots.
Full detail in [Payload mapping and Flow variables](https://docs.workflow-webhooks.app/payload-mapping.md).

## 4. Send a test request

![One invocation opened in History with its request headers, payload, status, duration and identifiers](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/f9bea621fc658ca9.png)
*After a test request the invocation appears in History with the payload that was received.*

```bash
curl -X POST https://your-app-url/webhook/ab12cd34 \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: your-token" \
  -d '{"orderId":"1001","customer":{"email":"someone@example.com"}}'
```

Open **History**. You should see the call with its status, headers and payload. If it is
not there, [History and troubleshooting](https://docs.workflow-webhooks.app/history-and-troubleshooting.md) lists every rejection reason.

## 5. Build the Flow workflow

In **Shopify Flow**, create a workflow starting with the **Webhook Trigger** trigger.

1. Add the trigger and click **Record Events**.
2. Come back here, open the invocation in **History**, and press **Replay**. Flow now has a
   real example payload to work with - much easier than guessing field names.
3. Add a **Condition**: `Webhook ID` equals your webhook's id (shown on the webhook page).
   Every Webhook Trigger workflow receives events from *all* your webhooks, so this
   condition is what makes the workflow respond to only this one.
4. Add your actions, using `{{fieldOne}}` to `{{fieldFour}}`.
5. Turn the workflow on.

![Shopify Flow's Select trigger panel with Workflow Webhooks opened, listing Webhook Trigger and Sync Webhook Trigger](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/ac1f06a48c663be2.png)
*In Shopify Flow choose Select a trigger, open Workflow Webhooks and pick Webhook Trigger.*

![The plus under the Webhook Trigger step opened, offering Action and Condition](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/9397d20b6b909fc9.png)
*The plus under a step offers the two things a workflow is made of: a condition and an action.*

![A Flow condition: Webhook id is equal to the ID of one webhook](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/90ee4741ac771967.png)
*The first step of every workflow: a condition on the webhook ID, so the workflow only runs for this webhook.*

![Flow's Add a variable panel for Webhook Trigger, listing webhookId and fieldOne to fieldFour with sample values from a recent request](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/c9fa2f8b0294a46d.png)
*What the trigger hands to your workflow: the webhook ID and your four mapped fields, shown with the values of a recent request.*

![Flow's Send internal email action with fieldOne and fieldTwo in the subject and fieldThree and fieldFour in the message](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/375ec5026ecccc0d.png)
*Use the mapped fields anywhere a Flow action takes a variable, here in the subject and message of an internal email.*

![The finished workflow: Webhook Trigger, a condition on the webhook ID, then Send internal email on the True branch](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/8b204c40856b5f47.png)
*The finished workflow: trigger, condition on the webhook ID, then your action on the True branch.*

> [!WARNING]
> Step 3 is the one people skip. Without the Webhook ID condition, every webhook you own
> will run this workflow.

## 6. Go live

Point your real system at the webhook URL. Watch the first few calls in **History** to
confirm they arrive and succeed.

If your sender retries on timeout, turn on [Duplicate delivery protection](https://docs.workflow-webhooks.app/duplicate-delivery.md) so a retry cannot
run your workflow twice.

![The Webhooks page listing six webhooks, each with its invocation count, authentication and an Enabled or Disabled badge](https://cdn-dev.eu.codecreationlabs.cloud/crm-tool/uploads/SjJ78gKLnLlocopCui3Cs62dJbGZ7F1n/12298ad8cb3bf595.png)
*The Webhooks page. Each row shows how often the webhook was called, how callers authenticate and whether it is enabled; the menu on the right enables, disables or deletes it.*
