> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shoppex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflows

> Build, test, and report on deterministic merchant automations through the Developer API and MCP.

The dashboard calls this feature **Automations**. The Developer API resource is `workflows`.

Workflows run **when** a trigger fires, **if** conditions match, **then** execute steps.
The engine is deterministic and uses no LLM. Agents can design workflows, but the
saved rules run without an agent. See the [merchant guide](/selling/automations) for
the dashboard builder.

## Safe agent flow

1. Read `GET /dev/v1/workflows/catalog`. Use its trigger, field, operator and action keys.
2. Build a definition, optionally starting from `/templates`.
3. Call `/validate` and fix every returned field path.
4. Call `/test` to inspect planned steps and warnings. Testing never applies actions or stores a run.
5. Create a workflow. It is **always DRAFT**, even if a create request supplies `status: "ACTIVE"`.
6. Show the merchant the trigger, conditions, effects, run limits and test results.
7. Only after explicit merchant approval, call `/:id/status` with `{"status":"ACTIVE"}`.

Workflow writes can blacklist customers, create coupons and credit balances.
Do not interpret permission to design a workflow as permission to activate it.

## Definition format

A definition contains `trigger`, `conditions`, `steps` and `settings`:

* `trigger`: catalog `type` and its `config` parameters.
* `conditions`: `match` (`all` or `any`) and a list of `{id, field, operator, value}` conditions.
* `steps`: ordered actions (`id`, `kind: "action"`, `action`, `params`, `continue_on_error`),
  delays (`kind: "delay"`, `amount`, `unit`: `minutes`, `hours` or `days`), or checks
  (`kind: "check"`, `conditions`). Every step needs a unique `id`.
* `settings`: `run_limit` (`every_time`, `once_per_customer` or `once_per_order`) and `max_runs_per_hour`.

Variables use `{{namespace.field}}`. The catalog's `variables.trigger_fields`
lists variables per trigger; `variables.action_outputs` lists values available
only after the producing action. Read catalog parameter requirements and limits
at runtime. Some templates have `needs_setup: true` and need merchant choices.

This definition alerts the merchant in the dashboard when a first-time buyer
pays at least 150 in the shop's currency:

```json theme={"system"}
{
  "trigger": { "type": "order:paid", "config": {} },
  "conditions": {
    "match": "all",
    "conditions": [
      { "id": "first", "field": "order.is_first_order", "operator": "is_true", "value": null },
      { "id": "amount", "field": "order.total", "operator": "gte", "value": 150 }
    ]
  },
  "steps": [
    {
      "id": "notify",
      "kind": "action",
      "action": "notify_merchant",
      "params": {
        "channels": ["dashboard"],
        "title": "Large first order: {{order.total}}",
        "message": "{{customer.email}} paid {{order.total}}. Review the order: {{order.url}}"
      },
      "continue_on_error": false
    }
  ],
  "settings": { "run_limit": "once_per_order", "max_runs_per_hour": 100 }
}
```

Send it as `{"definition": ...}` to `/validate`. A valid response is
`{"data":{"issues":[]}}`. Invalid definitions return HTTP 422 with
`error.details` entries containing `field` and `message` (for example,
`steps.0.params.channels`). Structural validation errors also return 422.

For `/test`, add `"sample":{"kind":"example"}`, `{"kind":"latest"}`, or
`{"kind":"order","order_id":"your-order-id"}`. The response includes sample
source, evaluated conditions, step outcomes, warnings and visible context.
A test is a preview against that sample, not a guarantee about future events.

For creation, send `name`, optional `note`, and `definition`. Incomplete drafts
are allowed and return `issues`; activating a draft or changing an active
workflow definition requires a valid definition. Metadata-only edits and pausing
remain available when a definition has issues. PATCH changes only supplied fields;
`note: null` clears the note. Running and waiting executions retain their
original definition snapshots.

## Endpoints and scopes

All paths below start with `/dev/v1/workflows` and are scoped to the authenticated
key's shop. IDs are UUIDs. Send `Authorization: Bearer shx_...`.

| Method | Path | Purpose | Scope |
| - | - | - | - |
| GET | `/` | Cursor list; `status`, `trigger_type` filters | `workflows.read` |
| GET | `/:id` | Definition and issues | `workflows.read` |
| POST | `/` | Create a draft | `workflows.write` |
| PATCH | `/:id` | Edit name, note, definition | `workflows.write` |
| DELETE | `/:id` | Delete workflow and run history | `workflows.write` |
| POST | `/:id/status` | Set `ACTIVE` or `PAUSED` | `workflows.write` |
| POST | `/:id/duplicate` | Copy as a draft | `workflows.write` |
| GET | `/catalog` | Live definition vocabulary and limits | `workflows.read` |
| GET | `/templates` | Starter definitions | `workflows.read` |
| POST | `/validate` | Validate without saving | `workflows.read` |
| POST | `/test` | Dry-run without side effects | `workflows.read`; a `latest` or `order` sample also needs `orders.read` and `customers.read` |
| GET | `/runs` | Cursor list; `workflow_id`, `status`, ISO `since` filters | `workflows.read`, `orders.read`, `customers.read` |
| GET | `/runs/:id` | Run snapshot and steps | `workflows.read`, `orders.read`, `customers.read` |
| POST | `/runs/:id/cancel` | Cancel running or waiting run | `workflows.write` |
| POST | `/runs/:id/retry` | Retry failed run; real effects resume | `workflows.write` |
| GET | `/report` | Statistics for the last `days` calendar days in the shop's time zone, today included; `days=1..90`, default 7 | `workflows.read` |

Choose `workflows.read` and `workflows.write` explicitly in a custom API key.
No convenience preset or legacy write/delete permission grants `workflows.write`.
Full access (`*`) includes it. Write scope does not imply read scope.
Writes are audited as the authenticated shop owner; request logs identify the credential.

Run reads require both data scopes because errors and step outputs can contain
customer and order data. Missing either scope returns `403` before loading runs.

Use an `Idempotency-Key` header when creating or duplicating a workflow and reuse
that key when retrying the same request. Creation and duplication return HTTP 201.
Other successful operations return HTTP 200 with a `data` envelope.

Lists accept `limit` (1–100, default 50) and `cursor`; responses include `data`,
`pagination: {next_cursor, has_more}` and the echoed `limit`. Workflows sort by
`created_at DESC, id DESC`; runs use their creation timestamp `started_at DESC, id DESC`.
Keep filters unchanged between pages. The last page has `next_cursor: null`.

To pause, send `{"status":"PAUSED","cancel_waiting_runs":true}` if waiting runs
should also be cancelled. An action already in flight may finish; subsequent
steps wait until the workflow is active again. Retrying a failed run also requires
an active workflow.
Use the run cancellation endpoint for a running execution. Cancellation does
not reverse completed actions. A draft cannot be paused because it is not running.

## Reports

Reports return `days`, `since`, `until`, a `workflows` array and shop `totals`.
Each workflow has `workflow_id`, `name`, `runs`, `succeeded`, `failed`, `skipped`,
`check_stopped`, `skipped_by_reason` (reason/count pairs), `success_rate`, `last_run_at`,
`top_failures` (up to three message/count pairs), `running` and `waiting`.
Totals use the same metric fields.

`runs` includes every non-test run status in the window.

As of Automations 2.0, `succeeded` excludes runs stopped by an unmet check.
Those runs still have status `SUCCEEDED` in run history, but reports count them
in `check_stopped` and exclude them from the success-rate denominator.
An email step missing order or customer email context fails visibly.

`success_rate` is a percentage: succeeded / (succeeded + failed), or `null` when neither exists.
`last_run_at` is the latest start in the window. Current running/waiting counts
include work started before the window. Failed runs without a message count in
`failed` but not `top_failures`. Workflows with no runs appear with zero counts.
Skipped history is retained for 14 days and finished history for 90 days, so
older report windows cannot recover pruned skipped runs or deleted workflows.

## MCP tools

The commerce MCP server exposes:

* `workflows_catalog`, `workflows_templates`, `workflows_list`, `workflows_get`
* `workflows_create`, `workflows_update`, `workflows_set_status`, `workflows_duplicate`, `workflows_delete`
* `workflows_validate`, `workflows_test`
* `workflow_runs_list`, `workflow_runs_get`, `workflow_runs_cancel`, `workflow_runs_retry`
* `workflows_report`

The `shoppex://workflows/definition` resource fetches the live catalog. The
`design_workflow` prompt takes a `goal` and guides an agent through proposing,
validating, testing and creating a draft. Destructive tool annotations mark
status changes, updates, deletion, cancellation and retry. MCP list tools retain
pagination metadata. Create and duplicate accept `idempotency_key`.

## Use with Claude Code or Codex

Install using the commerce server's documented installer:

```bash theme={"system"}
npx @shoppexio/mcp-shoppex install --api-key shx_your_dev_api_key
```

For a manual stdio connection, the documented standalone installation is:

```bash theme={"system"}
npm install -g @shoppexio/mcp-commerce-server
```

Configure your client's MCP connection to run `shoppex-mcp-commerce-server`
with `SHOPPEX_SHOP_API_KEY` set to your custom key. These tools require a commerce
server build containing workflow support; this change does not publish a package.
Then ask: “Design a workflow that alerts me about large first orders. Validate
and test it, save a draft, and show me the plan before activation.”


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.