---
title: "Developer API and MCP server - Workflow Webhooks"
description: "Manage webhooks from your own code over a scoped REST API, or from an AI assistant over MCP. Read, write and execute access levels."
canonical: "https://docs.workflow-webhooks.app/developer-api-and-mcp"
---

# Developer API and MCP

Everything you manage in the app, you can also manage from your own code or from an AI assistant. Workflow Webhooks exposes two surfaces: a **REST API** and an **MCP server**. Both live on the **Developer** page.

## API keys

Both surfaces authenticate with an API key. On the **Developer** page, under **API keys**, create a key and pick its access level:

- **Read only** - list webhooks, read invocation history and stats.
- **Read & write** - also create, update and delete webhooks.
- **Read, write & execute** - also fire a test invocation or replay a past one.

The full key is shown **once**, at creation. Copy it then and store it securely; you cannot see it again. Keys are stored hashed, never in plain text, and you can revoke a key at any time.

Send the key as a Bearer token on every request:

```text
Authorization: Bearer fwk_your_key_here
```

### Why execute is a separate level

Firing a webhook really does run your Shopify Flow workflows, and those workflows can change your store - tagging orders, sending email, updating inventory. Keeping that behind its own level means a key you hand to a script or an AI assistant for everyday work cannot trigger your automations by accident. Give out read keys by default, and only create an execute key where you genuinely need one.

## Base URL

The API and the MCP server are served from a dedicated hostname:

```text
https://shopify.workflow-webhooks.app
```

So the REST API lives at `https://shopify.workflow-webhooks.app/api/v1` and the MCP server
at `https://shopify.workflow-webhooks.app/api/mcp`. The Developer page shows both with a
copy button.

This hostname serves **only** `/api` - the embedded admin UI stays on its own Shopify
-registered URL. Keeping them apart means the address you paste into a script, a CI job or
an AI client is stable and unrelated to the app's embedding.

## REST API

The base URL is shown on the Developer page. The main endpoints:

| Method | Path | Level | Purpose |
| --- | --- | --- | --- |
| GET | `/api/v1` | none | API index - confirms the API is up |
| GET | `/api/v1/me` | read | Check auth and see your key's level |
| GET | `/api/v1/webhooks` | read | List webhooks |
| POST | `/api/v1/webhooks` | write | Create a webhook |
| GET | `/api/v1/webhooks/:id` | read | Get one webhook |
| PUT / PATCH | `/api/v1/webhooks/:id` | write | Update a webhook |
| DELETE | `/api/v1/webhooks/:id` | write | Delete a webhook |
| POST | `/api/v1/webhooks/:id/test` | execute | Fire a test invocation |
| GET | `/api/v1/history` | read | List invocations |
| GET | `/api/v1/history/:id` | read | Get one invocation, with its payload |
| POST | `/api/v1/history/:id/replay` | execute | Replay a past invocation |
| GET | `/api/v1/stats` | read | Totals, success rate, daily series |
| GET | `/api/v1/templates` | read | Built-in webhook templates |

A quick check that your key works:

```bash
curl https://shopify.workflow-webhooks.app/api/v1/me \
  -H "Authorization: Bearer fwk_your_key_here"
```

```json
{ "authenticated": true, "shop": "your-store.myshopify.com", "level": "READ" }
```

## MCP server

The MCP server lets an AI assistant (Claude, Cursor, VS Code, Gemini CLI and others) work with your webhooks in conversation. On the Developer page, the **MCP** tab shows the server URL and a ready-to-copy connect command per client, with your key already inserted.

The tools mirror the REST endpoints, and **the tool set reflects your key's level**: a read-only key does not even see the tools that create, delete or fire webhooks. All authentication and data handling stay server-side.

## How your data is protected

Two things are worth knowing before you point an automation or an AI assistant at this API.

**Your webhook's auth token is never readable.** The token or signing secret you set on a webhook cannot be read back through the API or MCP at any level. Responses tell you only whether a token is set (`hasToken`), never its value. You can set a new one; you can never retrieve the old one.

**Personal data in payloads is masked.** Webhook payloads come from outside systems and often contain customer details. Before an invocation payload leaves the server, values that look like personal data are replaced with `***`: email addresses, phone numbers, card numbers, and fields named after a person (`customerName`, `shippingAddress` and similar). Request headers are sanitised the same way the app's history screen does it.

This masking is careful but **not a guarantee**. It works on field names and value patterns, so personal data sitting inside a free-text field - a note, a comment, a message body - can still come through. Treat API responses as potentially containing customer data, and store them accordingly.

**Test and replay do not use your quota.** Invocations you fire through the API are recorded as tests, so they do not count toward your plan's monthly allowance. Replays do not count either, because the original invocation already did.

## Next steps

- [Introduction to Workflow Webhooks](https://docs.workflow-webhooks.app/introduction.md) - how webhooks and payload mapping work.
