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

# Workflows

> Let your customers build paths of compositions in your page, and show them with one embed tag

A workflow chains compositions together, with filters between them that decide which composition a visitor sees next. On a page it is still the `<widgetic>` tag you already use: the embed follows the workflow, so the composition on screen is replaced by the next one, in the same place.

You can put the screen where workflows are built in your own page, for **one customer at a time**. Your customer makes workflows from their own compositions, tries them, publishes them and pauses them, without leaving your product and without a Widgetic account. Your server keeps your API key. The page only holds an [editor session](https://widgetic.com/docs/partners/editor-sessions.md). Your server can also read and change your customers' workflows itself, one customer at a time (see [From your server](#from-your-server)). And you can give your customers somewhere to start: workflows of your own that they copy and build on (see [Starting points](#starting-points)).

> [!NOTE]
>
> **Preview.** Workflows are new. They are built and tested, and you can try them now, but small details can still change while this label is on. Tell us what you find at [support@widgetic.com](mailto:support@widgetic.com).

## How it works

**1. Your server makes an editor session**

When the page that holds the screen opens, your server asks Widgetic for a session for the signed-in customer, with the `workflows` surface, and returns the token. See [Make a session](#make-a-session).

**2. Your page mounts the screen**

The [UI SDK](https://widgetic.com/docs/partners/ui-components.md) draws it in your container, with `workspaceId: 'personal'` and a `getToken` that fetches the token from your server. See [Mount the screen](#mount-the-screen).

**3. Your customer builds and publishes**

They chain their own compositions, play a visitor through the draft with **Test run**, and publish. Every call the screen makes carries the token, so it reaches that customer's workflows and compositions and nobody else's. See [What belongs to whom](#what-belongs-to-whom).

**4. Your page shows the embed tag**

The screen tells your page which workflow the customer asked the embed code of, and your page shows the `<widgetic>` tag that goes on the customer's own page. See [Show a workflow on a page](#show-a-workflow-on-a-page).

## Make a session

Call this from your server, as for any other piece (see [Editor Sessions](https://widgetic.com/docs/partners/editor-sessions.md#make-a-session)). `{id}` is Widgetic's `id` for the managed user, not your own `external_id`.

```bash theme={null}
curl -sS -X POST "https://api.widgetic.com/v1/managed-users/$MANAGED_USER_ID/editor-sessions" \
  -H "Authorization: Bearer $WIDGETIC_PARTNER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "surfaces": ["workflows"],
    "expires_in_seconds": 3600,
    "allowed_origin": "https://app.example.com"
  }'
```

* **`workflows` is enough on its own.** The screen uploads no file and calls nothing outside its own workflow calls. A page that also mounts the composition editor or the widget creator asks for their surfaces in the same call, because [the surfaces do not imply one another](https://widgetic.com/docs/partners/editor-sessions.md#surfaces).
* **The rest is the same as for every session.** The token is shown once, the session lasts up to four hours, `allowed_origin` binds it to your page, and it is made only while your account is in force and your own [storage](https://widgetic.com/docs/partners/storage.md) works, even though this screen stores no file.
* **One endpoint of yours serves every piece.** The endpoint in [A server endpoint for your page](https://widgetic.com/docs/partners/editor-sessions.md#a-server-endpoint-for-your-page) makes the session with the surfaces the page needs.

## Mount the screen

Give the container a height: the screen fills it and scrolls inside it.

```javascript theme={null}
import { mountModule } from '@widgetic/ui-sdk';

const workflows = await mountModule('workflows', {
  container: document.querySelector('#workflows'),
  workspaceId: 'personal', // always 'personal' with an editor session
  getToken: async () => (await fetch('/widgetic-session', { method: 'POST' })).json(), // { token, expiresAt }
  workflowId: workflowOfTheAddress(), // optional: the workflow to open first. Leave it out for the list
  on: {
    openWorkflow: ({ workflowId }) => history.pushState(null, '', workflowId ? `/workflows/${workflowId}` : '/workflows'),
    showEmbedCode: ({ workflowId }) => showMyEmbedCodeDialog(workflowId),
    error: ({ message, code, fatal }) => report(code, message),
  },
});

// later:
await workflows.unmount();
```

* **`workspaceId` is `'personal'`.** An editor session can make only the workflow calls of the workspace called `personal`, which is where the customer's workflows are. Another `workspaceId`, such as the id of an organization, is refused with `403` and `EDITOR_SESSION_ROUTE_NOT_ALLOWED`. The screen then says that something went wrong, with a **Try again** button, and does not show an empty list in its place.
* **`getToken` gives the session's token.** It is called when the screen starts and again shortly before the token runs out, as in [Tokens](https://widgetic.com/docs/partners/ui-components.md#tokens). When the session ends, the screen tells your page with an `error` event (`SESSION_ENDED`).
* **The options, the events and the methods are the ones in [UI Components](https://widgetic.com/docs/partners/ui-components.md#workflows).** `theme`, `locale` and `messages` work as for the other pieces.

## What a customer can do

With a session, the screen offers a customer what it offers anybody:

* **The list.** The customer's own workflows, with search, sort and a switch for the archived ones.
* **A new workflow.** Started empty, from one of their own compositions, or from one of your [starting points](#starting-points).
* **The editor.** A canvas of blocks that go forward only, a draft that is saved while they work, and **Test run**, which plays a visitor through the draft.
* **Publish and Discard changes.** A published version never changes. The customer can read the history of versions and restore one as a new draft.
* **Settings.** The time zone, the **Embed code** button, **pause** and **resume**, **archive** and **unarchive**.
* **Duplicate and delete.** A duplicate is a new draft. A customer can delete a workflow in any state (see [Delete a workflow](#delete-a-workflow)).
* **Runs.** How many visitors went through each block.

A session reaches nothing else of the customer's account, and nothing of yours (see [What a session never does](https://widgetic.com/docs/partners/editor-sessions.md#what-a-session-never-does)). It may set only the fields the screen sets: a request that names another one, such as the customer or the state of a workflow, is refused with `403` and `EDITOR_SESSION_FIELD_NOT_ALLOWED`.

### Delete a workflow

A customer can delete a workflow in **any state**: a draft, a live workflow, a paused one or an archived one. The screen asks them to confirm and says what goes: the draft, the published versions and the counts, with how many visitors the workflow had so far. **It cannot be undone**: archiving is what keeps a workflow. The compositions it chained are not touched.

A page whose embed still names the deleted workflow does not break. It shows the embed's first composition, as it does for a paused workflow. Your webhook is told (`workflow.deleted`, see [What you are told](#what-you-are-told)).

Your server deletes with `DELETE /workspaces/personal/workflows/{workflowId}` and the customer's header (see [From your server](#from-your-server)). A workflow that is already gone answers `404` with `RESOURCE_WORKFLOW_NOT_FOUND`.

## What belongs to whom

* **A workflow is filed under the customer when it is made.** A workflow made in a session is filed under the session's managed user, at that moment, and for good: there is no field to name another customer, and no way to move it.
* **A customer sees their own workflows only.** Another customer's workflow, one of yours and one that does not exist all answer `404` with the code `RESOURCE_WORKFLOW_NOT_FOUND` and the same words, so the customer cannot tell them apart. A workflow id that is not an id is not a route at all: it answers `403` and `EDITOR_SESSION_ROUTE_NOT_ALLOWED`.
* **A customer chains their own compositions only.** The compositions the screen offers are the ones filed under that customer (see [Content the editors can open](https://widgetic.com/docs/partners/editor-sessions.md#content-the-editors-can-open)). Another customer's composition, one you made without naming a customer and one of another account all read as missing: starting a workflow from one answers `404` with `RESOURCE_COMPOSITION_NOT_FOUND`, and a draft that holds one as a block cannot be published (`422` with `BUSINESS_OPERATION_INVALID`, and the block is named).
* **A customer is not told who published.** The versions a customer reads carry no name of the person who published them.
* **Your account owns the workflows.** They run under your account and your agreement, as your compositions do. While your account is paused, a workflow is not served either (see [Account Status](https://widgetic.com/docs/partners/account-status.md)). A customer is never asked to upgrade a plan, and is never shown yours: workflows are part of the partner contract.
* **You see all of them.** Signed in as your own account, the same screen lists every customer's workflows next to yours, and you can open, pause or delete any of them. Your key without a customer header does the same: the list holds every customer's workflows, each with the id of its customer in `managedUserId`. A workflow or a copy you make that way is yours, not the customer's.
* **Deleting a managed user does not delete their workflows.** The workflows stay in your account and keep working on every page that shows them, and only the label that said whose they were is removed. Pause or delete a customer's workflows first when they should stop. See [Deleting Managed Users](https://widgetic.com/docs/partners/managed-users.md#deleting-managed-users).

## Limits and cost

* **Up to 50 workflows for each customer, archived ones included.** Another one is refused with `422` and `BUSINESS_OPERATION_INVALID`, with `reason: "too_many_workflows"` in its details and the words "You can have up to 50 workflows. Delete or archive some first." The limit is counted for each customer, so one customer cannot use up the room of another, or yours. What you make yourself has a larger limit of its own, and your customers' workflows do not count towards it. A workflow that a customer starts from one of your [starting points](#starting-points) is one of their 50, and the limit is checked before anything is copied.
* **Workflows take no credits.** Making, saving and publishing one is not an AI call, so it does not use your credits and it is not counted against a customer's allowance. Neither does starting one from a starting point: that copies what already exists and generates nothing.
* **A workflow has up to 25 blocks.** See [UI Components](https://widgetic.com/docs/partners/ui-components.md#workflows).
* **You can offer up to 50 starting points, and each chains at most 10 different widgets.** See [What can be offered](#what-can-be-offered).

## Starting points

A starting point is a workflow of yours that your customers can copy and build on, so that they do not begin with an empty canvas: a welcome page that leads to an offer, a quiz with a result page for each answer. You build and publish it once, in your own account, offer it under a key, and your customers start from it.

> [!NOTE]
>
> The screen calls them **presets**: its **New workflow** dialog lists yours under **Start from**, next to **Blank workflow**. They are not the [preset widgets](https://widgetic.com/docs/partners/managed-users.md#preset-widgets), which are single widgets that your server hands out. A starting point can chain only widgets that you offer that way (see [What can be offered](#what-can-be-offered)).

### What a customer gets

A customer who starts from one of yours gets, in their own account:

* **Their own copy of every widget** the workflow chains: an ordinary private widget, filed under the customer, that serves the published code of yours.
* **A composition of their own on each copy**: a draft, with the content, design, embed settings and tables of the original.
* **A draft workflow**, wired like the live version of yours at that moment. It is named as the customer asks, or after the starting point.

The workflow stays a draft: the customer tries it, changes it and publishes it themselves. **Nothing is shared afterwards.** What a customer changes never reaches your workflow, and what you change later never reaches their copy. Publishing a new version of yours changes what the customers who start after that get, and never what the customers who already started have.

A customer sees only the starting points of **your** account. Widgetic's own are never shown to your customers, and another partner's customers never see yours.

### What can be offered

A starting point is one of **your own published workflows**: one made in your own account (not filed under a customer, and not a team's), that is not archived and has a live version. Because a customer gets copies, it also has to be something you are willing to give away:

* **Every composition in it is one you made for yourself.** A composition made for a customer or for a team is not yours to give.
* **It chains at most 10 different widgets**, because every start copies them.
* **Every one of those widgets is already one of your [preset widgets](https://widgetic.com/docs/partners/managed-users.md#preset-widgets).** Offering a widget as a preset is how you say that it may be copied.

You can offer up to 50 workflows. A workflow is offered once, under one key.

### Offer one

Offer a workflow in your [dashboard](https://widgetic.com/docs/partners/dashboard.md) (**Presets**, then **Workflow starting points**, then **Add a starting point**), or from your server with `PUT /partners/{partnerId}/workflow-presets/{key}`:

```bash theme={null}
curl -sS -X PUT "https://api.widgetic.com/v1/partners/$WIDGETIC_PARTNER_ID/workflow-presets/welcome-then-offer" \
  -H "Authorization: Bearer $WIDGETIC_PARTNER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": "WORKFLOW_ID",
    "title": "Welcome, then an offer",
    "description": "A welcome page that leads to an offer.",
    "position": 1
  }'
```

| Field | What it is |
| - | - |
| `key` (in the address) | The name your code and the picker use: 1 to 64 lowercase letters, digits, hyphens and underscores, starting with a letter or a digit, such as `welcome-then-offer` |
| `workflowId` | **Required.** One of your own published workflows |
| `title` | What the picker shows, up to 120 characters. Without one, it shows the workflow's name |
| `description` | Up to 500 characters |
| `position` | 0 to 10000, and 0 when left out. The list comes back with the smallest first, then by key |

* **Sending the same key again replaces it.** The call answers `200` both times, so it is safe to repeat and needs no `Idempotency-Key`. It replaces the whole starting point: a `title`, `description` or `position` you leave out goes back to its default.
* **What customers get is the live version as it is when they start.** Publishing the workflow changes what the next start gets, so look at a new version before you publish it.
* **Your key makes the call,** or the person who administers your account. An [editor session](https://widgetic.com/docs/partners/editor-sessions.md) cannot: it is for your server.

### Read and remove

`GET /partners/{partnerId}/workflow-presets` lists what you offer, ordered by `position` and then by `key`. Each one says what it is made from and whether customers can start from it now:

```json theme={null}
{
  "success": true,
  "data": {
    "items": [
      {
        "key": "welcome-then-offer",
        "workflowId": "5c1d2e3f-4a5b-4c6d-8e7f-90a1b2c3d4e5",
        "title": "Welcome, then an offer",
        "description": "A welcome page that leads to an offer.",
        "position": 1,
        "available": true,
        "unavailableReason": null,
        "workflowName": "Welcome journey",
        "blockCount": 4,
        "widgets": [
          {
            "id": "4b2f9c1e-6d3a-4f08-9a57-1c2e8b7d5a30",
            "name": "Welcome page",
            "thumbnailUrl": "https://cdn.widgetic.com/thumbnails/welcome-page.png"
          }
        ],
        "createdAt": "2026-10-28T12:00:00.000Z",
        "updatedAt": "2026-10-28T12:00:00.000Z"
      }
    ]
  }
}
```

A starting point that cannot be started has `available` set to `false`, and `unavailableReason` says why: `workflow_missing` (the workflow was deleted), `workflow_not_own`, `workflow_archived` (unarchive it), `workflow_not_published`, `workflow_empty`, `composition_not_own`, `too_many_widgets` or `widget_not_preset` (a widget it chains is no longer offered as a preset). A customer is never shown one that is not available, so read this list to notice a starting point that went stale.

`DELETE /partners/{partnerId}/workflow-presets/{key}` stops offering it and answers `{ "removed": true }`, or `false` (not an error) when nothing was offered under that key. It leaves the workflow, and every workflow a customer already started from it, alone. Deleting the workflow takes its starting point off the list too.

### When an offer is refused

The reason is in `error.details.reason`:

| Status | Code | `reason` | What it means |
| - | - | - | - |
| 404 | `RESOURCE_WORKFLOW_NOT_FOUND` | | The workflow does not exist, or is not one of your account's own (the two look the same) |
| 409 | `BUSINESS_STATE_CONFLICT` | `workflow_archived` | It is archived. Unarchive it first |
| 409 | `BUSINESS_STATE_CONFLICT` | `workflow_not_published` | It was never published. A starting point is what visitors get, never a draft |
| 409 | `BUSINESS_STATE_CONFLICT` | `workflow_already_offered` | It is already offered, under the key in `details.key`. Remove that one, or replace it |
| 409 | `BUSINESS_STATE_CONFLICT` | `too_many_presets` | You already offer 50 (`details.limit`). Remove one first |
| 409 | `BUSINESS_STATE_CONFLICT` | `preset_changed_meanwhile` | Another change to your starting points landed at the same moment. Ask again |
| 422 | `BUSINESS_OPERATION_INVALID` | `workflow_empty` | It shows no composition |
| 422 | `BUSINESS_OPERATION_INVALID` | `composition_not_own` | A block shows a composition made for a customer or for a team |
| 422 | `BUSINESS_OPERATION_INVALID` | `too_many_widgets` | It chains more than 10 widgets (`details.limit`) |
| 422 | `BUSINESS_OPERATION_INVALID` | `widget_not_preset` | A widget it chains is not one of your preset widgets. `details.widgets` lists them, each with its `id` and `name`, so that you can offer them first |

### Start one

A customer starts in the screen: they open **New workflow** and choose one of yours under **Start from**, which shows its title, its description, a picture of every widget it shows and its size. Choosing it makes the copies, which takes a few seconds, and opens the new draft. You write no code for it. A customer you offer nothing to sees the dialog as it was.

> [!NOTE]
>
> The picker comes with the version of the Workflows module that adds it. A page that pins an older version (see [Versions & Changelog](https://widgetic.com/docs/partners/module-versions.md)) starts blank only.

Your server makes the same two calls, with your key and the customer's header (see [From your server](#from-your-server)):

```bash theme={null}
# What this customer is offered
curl -sS "https://api.widgetic.com/v1/workspaces/personal/workflows/presets" \
  -H "Authorization: Bearer $WIDGETIC_PARTNER_KEY" \
  -H "X-Managed-User-Id: $MANAGED_USER_ID"

# A workflow of the customer's own, started from one of yours
curl -sS -X POST "https://api.widgetic.com/v1/workspaces/personal/workflows/from-preset" \
  -H "Authorization: Bearer $WIDGETIC_PARTNER_KEY" \
  -H "X-Managed-User-Id: $MANAGED_USER_ID" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "key": "welcome-then-offer", "name": "Our welcome journey" }'
```

Send the customer's header on both calls. Without it they are your own account's, and the list holds what Widgetic offers to everyone with a Widgetic account, not your starting points.

The list holds only what can be started now, in your order, and shows nothing about who made it and no id of its own:

```json theme={null}
{
  "success": true,
  "data": {
    "items": [
      {
        "key": "welcome-then-offer",
        "title": "Welcome, then an offer",
        "description": "A welcome page that leads to an offer.",
        "blockCount": 4,
        "widgets": [{ "name": "Welcome page", "thumbnailUrl": "https://cdn.widgetic.com/thumbnails/welcome-page.png" }]
      }
    ]
  }
}
```

* **`key` is the one the list gives, and `name` is optional.** It is up to 120 characters. Without it, the new workflow is named after the starting point's title.
* **The answer is `201` with the new workflow,** a draft, as for any new workflow.
* **Send an `Idempotency-Key`.** A start takes a few seconds, because every widget is copied, and an answer lost to a timeout is then repeated and not made twice.
* **A start that is not offered to this customer, or can no longer be started, is `404`** with `RESOURCE_WORKFLOW_PRESET_NOT_FOUND`. The customer cannot fix it, and a half-made copy would be worse, so it reads as missing.
* **The customer's 50 workflows are counted first.** At the limit, nothing is copied and the answer is `422` with `reason: "too_many_workflows"`.
* **A start that fails leaves nothing to clean up.** The answer is `503` with `SERVICE_UNAVAILABLE` and `reason: "preset_copy_failed"`: the compositions it made are removed again, so asking again is safe. The copies of widgets it made stay in the customer's account as ordinary widgets, which they can delete like any other.
* **Your webhook is told** (`workflow.created`, with `presetKey` set to the key). See [What you are told](#what-you-are-told).

## Show a workflow on a page

The screen has an **Embed code** button only when your page listens for `showEmbedCode` at the moment it mounts, and only for a workflow that has been published. It tells your page which workflow, and your page shows the tag: the tag of the workflow's first composition, with `workflow-id` added (see [Show a path of compositions in one place](https://widgetic.com/resources/sdks.md#show-a-path-of-compositions-in-one-place)).

A published workflow tells anyone which composition a new visitor starts on, so your page can read it without a key:

```javascript theme={null}
async function showMyEmbedCodeDialog(workflowId) {
  try {
    const answer = await fetch(`https://api.widgetic.com/embed/workflows/${workflowId}`);
    if (!answer.ok) throw new Error(`The workflow could not be read (${answer.status})`);

    const { data: published } = await answer.json(); // every answer of the API is { success, data }
    // A paused workflow answers with its status and nothing else: there is no first composition to name.
    if (!published.startCompositionId) return showMessage('Resume the workflow to get its embed code.');

    showCode(
      `<widgetic workflow-id="${workflowId}" composition-id="${published.startCompositionId}" ` +
        `resize="fill-width" width="800" embed-target="site"></widgetic>`,
    );
  } catch (error) {
    console.error('[workflows] Could not build the embed code', error);
    showMessage('The embed code is not available right now.');
  }
}
```

* **The tag goes on a page that has the Embed SDK on it,** as for any widget. The visitors on that page need no account and sign in to nothing.
* **A visitor's position stays in their own browser.** See [Show a path of compositions in one place](https://widgetic.com/resources/sdks.md#show-a-path-of-compositions-in-one-place) for what a visitor's browser keeps and what it tells your page.
* **Counts reach the screen.** What the tag reports (how many visitors reached a block or took a line) is what the customer reads in **Runs**.

## From your server

Everything the screen does, your server can do with your API key, for one customer at a time: the same calls, on the same addresses, with the customer named in a header. Send `X-Managed-User-Id` (Widgetic's id for the managed user) or `X-Managed-User-External-Id` (your own `external_id`), one of the two, and the word `personal` as the workspace.

```bash theme={null}
# The customer's workflows
curl -sS "https://api.widgetic.com/v1/workspaces/personal/workflows" \
  -H "Authorization: Bearer $WIDGETIC_PARTNER_KEY" \
  -H "X-Managed-User-Id: $MANAGED_USER_ID"

# A new workflow for the customer, started from one of their compositions
curl -sS -X POST "https://api.widgetic.com/v1/workspaces/personal/workflows" \
  -H "Authorization: Bearer $WIDGETIC_PARTNER_KEY" \
  -H "X-Managed-User-Id: $MANAGED_USER_ID" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Welcome journey", "compositionId": "COMPOSITION_ID" }'
```

The calls are in the [API reference](https://widgetic.com/api-reference/introduction.md) under Workflows. They are in **Preview**, like this page, so small details can still change. They are: the list, making a workflow, reading, saving and deleting one, duplicating, publishing, discarding changes, the versions and restoring one, pausing, resuming, archiving and unarchiving, the counts of runs, the compositions a workflow can start from, and the starting points a customer is offered and starting one from them (see [Start one](#start-one)). The calls you make about your own starting points are under Workflows too, and under Partners (see [Offer one](#offer-one)). Making, duplicating, starting from a starting point and publishing a workflow take an `Idempotency-Key`, as the reference says (see [Idempotency](https://widgetic.com/docs/reference/idempotency.md)). Saving a workflow takes the `revision` you read, so that two writers do not overwrite each other.

Your key reaches no more through the header than the screen does through a session:

* **The customer is the one in the header, and nothing else.** A body or a query that names a customer, an organization or another owner changes nothing: the workflow is filed under the customer in the header, for good.
* **The customer's workflows only.** A workflow of another customer, one you made without a header, one of another account and one that does not exist all answer `404` with `RESOURCE_WORKFLOW_NOT_FOUND`, so you cannot tell them apart. A workflow chains the compositions filed under that customer only: another composition answers `404` with `RESOURCE_COMPOSITION_NOT_FOUND`, and a draft that holds one cannot be published.
* **The workspace is `personal`.** Another workspace, such as the id of an organization, answers `403` with `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`, as does any call that does not take the header.
* **The customer must be yours.** An id that is not one of your managed users, or is another partner's, answers `404` with `MANAGED_USER_NOT_FOUND`. An empty, repeated or malformed header is `400` with `MANAGED_USER_SCOPE_INVALID`, and only an API key may send the header (`403` with `MANAGED_USER_SCOPE_NOT_ALLOWED`).
* **A customer you switched off** keeps its workflows, and you can still read and change them, but you cannot make, copy or start one for it: `409` with `MANAGED_USER_INACTIVE`.
* **The limits are the same.** Up to 50 workflows for each customer, archived ones included, and no credits (see [Limits and cost](#limits-and-cost)).

Without the header, the call is your own account's, as it always was: it sees every customer's workflows next to yours. The two calls for starting points are the one place where that does not mean "everything": without the header they show what Widgetic offers to everyone, not your starting points (see [Start one](#start-one)).

Keep your key on your server. A page in a browser uses an [editor session](#make-a-session) instead.

## What you are told

Your webhook can be told when a customer makes, publishes, changes or deletes a workflow, with or without the screen:

| Event | When |
| - | - |
| `workflow.created` | A workflow was created for a customer: new, copied from another of theirs, or started from one of your starting points (`presetKey` says which, and is `null` for the others) |
| `workflow.published` | A workflow was published as a new version |
| `workflow.state_changed` | A workflow was paused, resumed, archived or unarchived |
| `workflow.deleted` | A workflow was deleted, in whatever state it was, with its versions and counts |

They are about your customers' workflows only: what you make yourself, in your own account, is not told. They carry the ids and the names, and none of the workflow's blocks, so read the workflow for what it holds now. A deleted workflow can no longer be read, so `workflow.deleted` carries its name and the state it was in. A webhook that receives every event receives these too, and one that lists its events needs them added. What each one carries is in [Notifications](https://widgetic.com/docs/partners/notifications.md#what-each-event-carries).

## Errors

The screen handles these for you and tells your page (`error` event). The ones of the session itself are in [Errors](https://widgetic.com/docs/partners/editor-sessions.md#errors).

| Status | Code | Meaning | What to do |
| - | - | - | - |
| 403 | `EDITOR_SESSION_ROUTE_NOT_ALLOWED` | The call is not one a session may make: a `workspaceId` that is not `personal`, or an id that is not an id | Mount the screen with `workspaceId: 'personal'` |
| 403 | `EDITOR_SESSION_FIELD_NOT_ALLOWED` | The request sets a field a session may not set | Not caused by the screen. Remove the field when you call the API yourself |
| 403 | `MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE` | Your key named a customer on a call that is not a workflow call of the workspace `personal` | Use `personal`, or leave the header out for a call that is not about one customer |
| 404 | `RESOURCE_WORKFLOW_NOT_FOUND` | The workflow is not this customer's, or does not exist | Check which customer the session was made for |
| 404 | `RESOURCE_COMPOSITION_NOT_FOUND` | A workflow was started from a composition that is not this customer's | File the composition under the customer (see [Filing Content Under a Managed User](https://widgetic.com/docs/partners/managed-users.md#filing-content-under-a-managed-user)) |
| 404 | `RESOURCE_WORKFLOW_PRESET_NOT_FOUND` | A start named a starting point that is not offered to this customer, or that can no longer be started | Read the list again and start one of those (see [Start one](#start-one)) |
| 404 | `MANAGED_USER_NOT_FOUND` | The customer in the header is not one of your managed users | Check the id, or the `external_id` |
| 409 | `MANAGED_USER_INACTIVE` | You tried to make, copy or start a workflow for a customer you switched off | Switch the customer on, or make the workflow without the header |
| 409 | `BUSINESS_STATE_CONFLICT` | You offered a workflow that cannot be offered now (archived, never published, already offered), or you already offer 50 (`details.reason` says which) | See [When an offer is refused](#when-an-offer-is-refused) |
| 422 | `BUSINESS_OPERATION_INVALID` | The customer has 50 workflows already, the draft cannot be published as it is (`details.issues` names what to fix), or the workflow you offered cannot be given away as it is (`details.reason` says why) | Archive or delete a workflow, fix the block, or see [When an offer is refused](#when-an-offer-is-refused) |
| 503 | `SERVICE_UNAVAILABLE` | A start could not set up the starting point right now (`details.reason` is `preset_copy_failed`) | Ask again: nothing was left that you must clean up (see [Start one](#start-one)) |

`MANAGED_USER_SCOPE_ROUTE_NOT_AVAILABLE`, `MANAGED_USER_NOT_FOUND` and `MANAGED_USER_INACTIVE` come only to a call made with your key and a customer header: the screen cannot cause them.

## Next Steps

> [card] [Editor Sessions](https://widgetic.com/docs/partners/editor-sessions.md)
>
> Make sessions, and what a session can do

> [card] [UI Components](https://widgetic.com/docs/partners/ui-components.md#workflows)
>
> The options, events and methods of the Workflows screen

> [card] [Managed Users](https://widgetic.com/docs/partners/managed-users.md)
>
> File your customers' content under them

> [card] [Embed SDK](https://widgetic.com/resources/sdks.md#show-a-path-of-compositions-in-one-place)
>
> What a workflow does on a page

> [card] [Notifications](https://widgetic.com/docs/partners/notifications.md)
>
> Be told when a customer makes or publishes a workflow


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