# Engagement types and stages

An engagement type is a named kind of client work in a Space, such as grooming, tutoring or repairs, with its own ordered stages. Managers set them up on the Engagements page, and an AI agent with its own key can read and manage them through the API.

Available

## How a type works

- **The status stays the machine state.** Every engagement keeps one of the existing statuses, so payments, emails and the portal behave as before.
- **A stage is a labelled step inside a status.** Each stage names the status it sits in (`status_bucket`). Moving to a stage may move the status along an allowed forward step, never backwards. A move the status cannot make is refused with `409`.
- **Stages must be reachable.** Consecutive stages in different buckets must be one allowed step apart: `submitted` to `in_review` or `awaiting_payment`, `in_review` to `filing`, then `filing`, `filed`, `issued`, `closed` one at a time. A list that skips a step is refused with `stage_unreachable` and the allowed next buckets.
- **Stages follow the status order.** A type has 1 to 12 stages, and their buckets may not go backwards through draft, submitted, awaiting_payment, in_review, filing, filed, issued, closed.
- **Clients see only some stages.** A stage with `client_visible: false` is shown to staff only. The portal returns `type` and `stage` with each engagement (`{key, label}` or null).
- **Default items** are priced lines in whole cents, checked by the same rules as an engagement's own charges.

## Give an agent access

1. Create an [agent key](https://bynefit.com/docs/agent-keys). It starts in test mode.
2. The agent asks for `read:engagement-types` and `write:engagement-types` with `POST /dash/api/v1/agent/access-requests` and a `reason`.
3. The key owner, a manager or admin of the Space, approves each on the key page. If they stop being a manager or admin, the key switches off.
4. To write for real, the owner moves the key to live. In test mode every write is a dry run.

## The calls

All calls are under `/dash/api/v1` and only see the key's own Space. A type from another Space answers `404`.

| Call | What it does |
| --- | --- |
| `GET /engagement-types`, `GET /engagement-types/{key}` | Read. The id of a type is its `key`. |
| `POST /engagement-types` | Create. Body: `key`, `label`, `stages`, and optionally `kind` (`service` or `formation`), `form_id` (a `frm_` id), `booking_type_id`, `default_items`, `site` (the key or id of one of the Space's sites, so the type shows only on that site's portal; leave it out for the whole Space). Honours `Idempotency-Key`. |
| `PATCH /engagement-types/{key}` | Change `label`, `kind`, `form_id`, `booking_type_id`, `site`, `stages`, `default_items` or `is_active`. The key never changes. A stage that an engagement sits in cannot be removed. |
| `DELETE /engagement-types/{key}` | Delete a type no engagement uses. Otherwise set `is_active` to false. |

**Create a type (bash)**

```
curl -X POST -H "Authorization: Bearer $BYNEFIT_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: grooming-type-1" \
  -d '{"key": "grooming", "label": "Grooming", "stages": [
        {"key": "requested", "label": "Requested", "status_bucket": "submitted"},
        {"key": "booked", "label": "Booked", "status_bucket": "in_review"},
        {"key": "groomed", "label": "Groomed", "status_bucket": "filing"},
        {"key": "ready", "label": "Ready for pickup", "status_bucket": "filed"},
        {"key": "picked-up", "label": "Picked up", "status_bucket": "issued"}
      ], "default_items": [{"label": "Full groom", "kind": "service", "qty": 1, "unit_cents": 7500}]}' \
  https://bynefit.com/dash/api/v1/engagement-types
```

## Limits and safety

- **Key.** 2 to 40 characters of a-z, 0-9, `_` or `-`, unique in the Space.
- **Size.** At most 50 types in a Space. Labels are 1 to 80 characters, stage labels 1 to 60.
- **No client data.** These permissions never read or change an engagement or a client.
- **Ceiling.** Live writes share the key's daily write budget with forms. A key in test mode, or a call with `"dry_run": true`, is checked and writes nothing.
- **Log.** Every live change is recorded in the Space activity log with the key, the type key and the action, never the content.

## Errors

| Status | `error` | What to do |
| --- | --- | --- |
| 403 | `insufficient_scope` | Request the permission and have the owner approve it. |
| 404 | `not_found` | The type is not in this Space. |
| 409 | `key_taken`, `type_in_use`, `stage_in_use`, `type_limit_reached` | Pick another key, deactivate instead of deleting, move the engagements first, or delete a type. |
| 422 | `invalid_key`, `invalid_label`, `invalid_stages`, `invalid_stage_key`, `invalid_stage_label`, `invalid_status_bucket`, `stage_order`, `stage_unreachable`, `duplicate_stage_key`, `invalid_default_items`, `form_not_found` | Fix the field named in `message`. |
| 429 | `agent_write_budget_spent`, `agent_limits_unavailable` | Wait for midnight, server time, or try again in a minute. |

## What exists and what does not

- [Read community resources](https://bynefit.com/docs/resources-read) - List and filter community resources with a developer key. JSON, cursor paging. (Available)
- [Submit a resource for review](https://bynefit.com/docs/resources-submit) - Propose a new entry. A moderator reviews it before it goes live. (Available)
- [Partner events](https://bynefit.com/docs/partner-events) - Partners send their own product events from a page, a server or an app, and read the totals back. Bynefit turns it on per partner. (By approval)
- [Hosted sites runtime](https://bynefit.com/docs/sites-runtime-api) - Events, resources, media, forms and page views for a hosted site, with no key. (Available)
- [Read and edit hosted site files](https://bynefit.com/docs/manage-site-files) - An agent key lists a Space's sites and reads, replaces and deletes their files, with versions, secret scanning and a daily write ceiling. The key owner approves the permission. (Available)
- [Create and manage forms](https://bynefit.com/docs/manage-forms) - An agent key creates forms for a Space, changes their settings and fields, pauses them and deletes unanswered ones, with a daily write ceiling and a test mode. Registration forms and submissions stay out of reach. The key owner approves the permission. (Available)
- [Engagement types and stages](https://bynefit.com/docs/manage-engagement-types) - A Space defines its own kinds of client work with ordered stages inside the existing statuses. Managers edit them on the Engagements page, and an agent key reads and manages them with a daily write budget and a test mode. The key owner approves the permissions. (Available)
- [Client portal API](https://bynefit.com/docs/client-portal-api) - A signed-in client reads their own engagements, documents and messages; a practice manager runs the pipeline. (Available)
- Engagements through an API key or a webhook - Read engagements from your own server, or hear about a change, without a person signed in. (Planned)
- [Every docs page as Markdown](https://bynefit.com/docs/ai-agents) - Add ?format=md to any docs page, or send Accept: text/markdown. (Available)
- [llms.txt index](https://bynefit.com/docs/ai-agents) - A short index of the docs for tools that read llms.txt, at /docs?format=llms. (Available)
- [OpenAPI spec](https://bynefit.com/docs/ai-agents) - An OpenAPI 3.1 description of the v1 API, with the error envelope and security schemes, at /docs?format=openapi. (Available)
- [Agent skill and integration brief](https://bynefit.com/docs/agent-skill) - An installable SKILL.md and a paste-in brief, generated from the same code as the spec. (Available)
- [Agent keys](https://bynefit.com/docs/agent-keys) - A key made for an AI agent: read-only to start, short-lived, test mode first, every call logged, and the owner approves anything more. (Available)
- Request id and docs link on every error - Every error body carries an id to quote to support and a link to the page that explains it. (Planned)
- [Test keys and a sandbox](https://bynefit.com/docs/test-mode) - Keys that only touch sample data, ready at once with no review, so a first attempt cannot break anything. (Available)
- [Idempotency-Key on writes](https://bynefit.com/docs/authentication) - Retry a v1 write without doing it twice: the first answer is replayed for 24 hours, per key. (Available)
- [Status page](https://bynefit.com/docs/status) - Live state, 90-day uptime and incident history for the API, sign-in, webhook delivery, the widget, hosted sites and email. Atom and JSON feeds. (Available)
- [Docs MCP server](https://bynefit.com/docs/docs-mcp) - Read-only search of these docs from an AI tool. (Available)

---

Source: https://bynefit.com/docs/manage-engagement-types
Checked against the live API on October 18, 2026.
