# AI Employees

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## POST /ai-employees/me/hello

**Say hello from its runtime**

`operationId: AIEmployeeController_hello`

The AI employee, once running and signed in as itself, says what runs it. This is the proof from its side that it exists and can reach the platform; it marks the employee connected and is shown on its setup checklist.

#### Signature

```http
POST /ai-employees/me/hello (body) -> { ok, you, status, next }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `AI (the employee itself)`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `403` | AI_EMPLOYEE_ONLY | This is for AI employees, signed in as themselves. | The caller is not an AI employee's own user. | — |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `GET /ai-employees/me/briefing`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Request body

```json
{
  "provider": "session-manager",
  "agentId": "ag_4821",
  "model": "claude-sonnet-5",
  "version": "1.4.0"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { ok, you, status, next } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | This is for AI employees, signed in as themselves. — The caller is not an AI employee's own user. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/me/briefing

**Get its briefing**

`operationId: AIEmployeeController_briefing`

Everything the employee needs on every sign-in and job, current: who it is (identity, supervisor, what it listens to, its approval policy, its phone numbers and voice), the company and its knowledge, its instructions (platform, org, its own job description), where to find the API reference, where its work stands (open jobs, what waits on a person, recent decisions), the time where it works, its own notes, the AI team workspace and its meetings in the next day.

#### Signature

```http
GET /ai-employees/me/briefing () -> The briefing
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `AI (the employee itself)`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `403` | AI_EMPLOYEE_ONLY | This is for AI employees, signed in as themselves. | The caller is not an AI employee's own user. | — |
| `404` | NO_EMPLOYEE_FOR_SIGN_IN | No AI employee uses this sign-in. | The signed-in AI user belongs to no employee (it was removed). | — |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `POST /ai-employees/worker/{name}/lease`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The briefing |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | This is for AI employees, signed in as themselves. — The caller is not an AI employee's own user. |
| `404` | No AI employee uses this sign-in. — The signed-in AI user belongs to no employee (it was removed). |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/worker/{name}/summary

**What an employee did over a period**

`operationId: AIEmployeeController_summary`

For its reports: job counts by outcome, approvals asked / approved / rejected / waiting, cost, check-ins (pings), and each job it finished. Pings on which it did nothing are not counted as work. An AI employee may call this only for itself.

#### Signature

```http
GET /ai-employees/worker/{name}/summary (name: string, since?: string) -> { since, until, counts, approvals, costUsd, pings, items }
```

#### Access

Requires either a bearer JWT or an API key. Required role(s): `System`, `AI (for its own jobs)`, `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `403` | NOT_OWN_JOB | An AI employee can only work on its own jobs. | An AI employee called this for another employee or another employee's job. | — |

Plus the standard platform errors: `401`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |
| `since` | query | string | — | ISO date-time; default 24 hours ago. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { since, until, counts, approvals, costUsd, pings, items } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | An AI employee can only work on its own jobs. — An AI employee called this for another employee or another employee's job. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/worker/{name}/lease

**Lease the next job**

`operationId: AIEmployeeController_lease`

The runtime asks for the employee's next job. The platform decides when it works: when it is not active, off shift, over today's budget, at its concurrency limit, or has nothing queued, the answer is `{ job: null, reason }` (still a success). A job this worker already held and was interrupted on is handed back first; otherwise in-progress work whose lease lapsed, then queued work by priority (high, normal, low), oldest first. A queued job that has used its attempts is failed and the next one is tried.

A lease lasts 15 minutes and is extended by each step reported. The answer carries the job, the employee's profile and approval policy, the company context and the budget left today.

#### Signature

```http
POST /ai-employees/worker/{name}/lease (name: string, body) -> The leased job, or `{ job: null, reason }`
```

#### Access

Requires either a bearer JWT or an API key. Required role(s): `System`, `AI (for its own jobs)`, `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `403` | NOT_OWN_JOB | An AI employee can only work on its own jobs. | An AI employee called this for another employee or another employee's job. | — |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `POST /ai-employees/worker/work/{id}/step`
- `POST /ai-employees/worker/work/{id}/complete`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "worker": "runner-1"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The leased job, or `{ job: null, reason }` |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | An AI employee can only work on its own jobs. — An AI employee called this for another employee or another employee's job. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

Example response:

```json
{
  "job": null,
  "reason": "Outside its working hours."
}
```

## POST /ai-employees/worker/work/{id}/step

**Report a step on a job**

`operationId: AIEmployeeController_step`

Adds a step to the job's timeline and extends the lease by 15 minutes. `costUsd` is added to the job's cost (and counts against today's budget). An unknown `kind` is recorded as `note`.

#### Signature

```http
POST /ai-employees/worker/work/{id}/step (id: string, body) -> The job with the new step
```

#### Access

Requires either a bearer JWT or an API key. Required role(s): `System`, `AI (for its own jobs)`, `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |
| `403` | NOT_OWN_JOB | An AI employee can only work on its own jobs. | An AI employee called this for another employee or another employee's job. | — |
| `409` | JOB_NOT_IN_PROGRESS | This job is queued, not in progress. | The job is not in progress (queued, waiting for approval, or finished). | Lease it first. |
| `400` | STEP_TEXT_REQUIRED | A step needs text. | `text` is missing. | — |

Plus the standard platform errors: `401`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Request body

```json
{
  "kind": "action",
  "text": "Replied to the customer with the delivery date.",
  "costUsd": 0.012
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The job with the new step |
| `400` | A step needs text. — `text` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | An AI employee can only work on its own jobs. — An AI employee called this for another employee or another employee's job. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `409` | This job is queued, not in progress. — The job is not in progress (queued, waiting for approval, or finished). |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/worker/work/{id}/approval

**Ask for approval before an action**

`operationId: AIEmployeeController_requestApproval`

The runtime asks before an action its policy may reserve for a person. Answered at once with `{ allowed: true }` when the employee's approval policy allows the action, or when the same request was already approved (on this job, or on another job in the last day — for money, up to the amount approved). Otherwise the job waits: status `waiting_approval`, lease released, `{ allowed: false, waiting: true }`. It is leased back with the decision in its steps once a person decides. `other` (or any unknown action) always needs a person.

#### Signature

```http
POST /ai-employees/worker/work/{id}/approval (id: string, body) -> `{ allowed: true, approvedBy? }` or `{ allowed: false, waiting: true }`
```

#### Access

Requires either a bearer JWT or an API key. Required role(s): `System`, `AI (for its own jobs)`, `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |
| `403` | NOT_OWN_JOB | An AI employee can only work on its own jobs. | An AI employee called this for another employee or another employee's job. | — |
| `409` | JOB_NOT_IN_PROGRESS | This job is queued, not in progress. | The job is not in progress (queued, waiting for approval, or finished). | Lease it first. |
| `400` | SUMMARY_REQUIRED | Say what it wants to do (summary). | `summary` is missing. | — |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `POST /ai-employees/work/{id}/decide`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Request body

```json
{
  "action": "money",
  "summary": "Refund order #1043 ($42.50) — the item arrived broken.",
  "amountUsd": 42.5
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | `{ allowed: true, approvedBy? }` or `{ allowed: false, waiting: true }` |
| `400` | Say what it wants to do (summary). — `summary` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | An AI employee can only work on its own jobs. — An AI employee called this for another employee or another employee's job. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `409` | This job is queued, not in progress. — The job is not in progress (queued, waiting for approval, or finished). |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/worker/work/{id}/complete

**Finish a job**

`operationId: AIEmployeeController_complete`

Marks the job done with its result and releases the lease. `costUsd` is added to the job's cost. A ping on which it took an action is retitled "On its own: <first line of the result>" and counted as work.

#### Signature

```http
POST /ai-employees/worker/work/{id}/complete (id: string, body) -> The finished job
```

#### Access

Requires either a bearer JWT or an API key. Required role(s): `System`, `AI (for its own jobs)`, `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |
| `403` | NOT_OWN_JOB | An AI employee can only work on its own jobs. | An AI employee called this for another employee or another employee's job. | — |
| `409` | JOB_NOT_IN_PROGRESS | This job is queued, not in progress. | The job is not in progress (queued, waiting for approval, or finished). | Lease it first. |

Plus the standard platform errors: `401`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Request body

```json
{
  "result": "Confirmed the reservation for 7pm and emailed the guest.",
  "costUsd": 0.03
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The finished job |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | An AI employee can only work on its own jobs. — An AI employee called this for another employee or another employee's job. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `409` | This job is queued, not in progress. — The job is not in progress (queued, waiting for approval, or finished). |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/worker/work/{id}/fail

**Report a failed attempt**

`operationId: AIEmployeeController_fail`

A failed attempt goes back in the queue until the job has used the employee's `limits.maxAttempts`; then (or with `retry: false`) the job is failed with the error.

#### Signature

```http
POST /ai-employees/worker/work/{id}/fail (id: string, body) -> The job — queued again, or failed
```

#### Access

Requires either a bearer JWT or an API key. Required role(s): `System`, `AI (for its own jobs)`, `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |
| `403` | NOT_OWN_JOB | An AI employee can only work on its own jobs. | An AI employee called this for another employee or another employee's job. | — |
| `409` | JOB_NOT_IN_PROGRESS | This job is queued, not in progress. | The job is not in progress (queued, waiting for approval, or finished). | Lease it first. |

Plus the standard platform errors: `401`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Request body

```json
{
  "error": "The customer record is locked by another user."
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The job — queued again, or failed |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | An AI employee can only work on its own jobs. — An AI employee called this for another employee or another employee's job. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `409` | This job is queued, not in progress. — The job is not in progress (queued, waiting for approval, or finished). |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/config

**Get the org's AI employee settings**

`operationId: AIEmployeeController_getConfig`

The settings in force, section by section (`company`, `knowledge`, `defaults`, `escalation`): the org's own, else the platform's (the shared org's), else empty — and where each came from.

#### Signature

```http
GET /ai-employees/config () -> { config, from, isPlatform }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { config, from, isPlatform } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /ai-employees/config

**Save the org's AI employee settings**

`operationId: AIEmployeeController_saveConfig`

Saves the sections sent; a section sent as `null` goes back to inheriting; a section left out is untouched. `system` (ping, unclaimed and handling minutes) is the platform's only — the shared org may set it, and a change applies to every switched-on employee at once.

#### Signature

```http
PUT /ai-employees/config (body) -> The settings in force after saving (as GET)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | AI_EMPLOYEE_INVALID | "owner@" is not an email address. | An escalation contact that is not an email, whenStuck not ask/fail/pause, a knowledge source without a valid type or reference (a url that is not http(s)), a knowledge entry without title or content, an unknown timezone, `system` from an org other than the platform, or minutes out of range. Every problem is listed, joined; the body also carries `problems[]`. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Request body

```json
{
  "escalation": {
    "contact": "owner@example.com",
    "whenStuck": "ask"
  },
  "knowledge": null
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The settings in force after saving (as GET) |
| `400` | "owner@" is not an email address. — An escalation contact that is not an email, whenStuck not ask/fail/pause, a knowledge source without a valid type or reference (a url that is not http(s)), a knowledge entry without title or content, an unknown timezone, `system` from an org other than the platform, or minutes out of range. Every problem is listed, joined; the body also carries `problems[]`. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/templates

**List templates to hire from**

`operationId: AIEmployeeController_templates`

Every template this org can hire from in one list: the platform's (the shared org's — read-only here: use it or copy it) and the org's own. Sorted by category and title.

#### Signature

```http
GET /ai-employees/templates () -> { data, isPlatform }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /ai-employees`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { data, isPlatform } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /ai-employees/templates

**Save one of the org's templates**

`operationId: AIEmployeeController_saveTemplate`

Creates or changes one of the org's own templates (in the shared org: one of the platform's). Only template fields are kept. An org saving a new template under a platform template's name gets a `-copy` name instead of shadowing it.

#### Signature

```http
PUT /ai-employees/templates (body) -> The saved template
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | AI_EMPLOYEE_INVALID | Give the template a name. Give the template a title. | No name/title. Every problem is listed, joined; the body also carries `problems[]`. | — |
| `409` | NAME_TAKEN_BY_EMPLOYEE | An AI employee is already called "night-desk". Give the template another name. | An employee has that handle. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Request body

```json
{
  "title": "Night desk",
  "category": "front-desk",
  "jobTitle": "Night receptionist",
  "listensTo": [
    "chat_queue",
    "sms"
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The saved template |
| `400` | Give the template a name. Give the template a title. — No name/title. Every problem is listed, joined; the body also carries `problems[]`. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `409` | An AI employee is already called "night-desk". Give the template another name. — An employee has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/templates/{name}

**Get one template**

`operationId: AIEmployeeController_template`

One template by name; the org's own wins over the platform's of the same name.

#### Signature

```http
GET /ai-employees/templates/{name} (name: string) -> The template
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | TEMPLATE_NOT_FOUND | No template "front-desk" | Neither the org nor the platform has a template by that name. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | Template name. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The template |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No template "front-desk" — Neither the org nor the platform has a template by that name. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /ai-employees/templates/{name}

**Delete one of the org's templates**

`operationId: AIEmployeeController_deleteTemplate`

Deletes one of the org's own templates. The platform's are not the org's to delete.

#### Signature

```http
DELETE /ai-employees/templates/{name} (name: string) -> { deleted }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | TEMPLATE_NOT_FOUND | This organization has no template "night-desk" of its own to delete. | No template of the org's own by that name. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | Template name. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { deleted } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | This organization has no template "night-desk" of its own to delete. — No template of the org's own by that name. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/instructions

**Get the org's instructions to its AI employees**

`operationId: AIEmployeeController_instructions`

The instructions the org gives its AI employees, in order. The platform's own system instructions also apply to every employee but are shown only in the shared org (`platform` is empty elsewhere).

#### Signature

```http
GET /ai-employees/instructions () -> { data, platform, isPlatform }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /ai-employees/{name}/instructions`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { data, platform, isPlatform } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /ai-employees/instructions

**Replace the org's instructions**

`operationId: AIEmployeeController_saveInstructions`

Replaces the whole list, in the order given. Each employee the change affects is told which instruction is new, changed or no longer applies to it (in its next briefing). In the shared org these are the platform's system instructions.

#### Signature

```http
PUT /ai-employees/instructions (body) -> The instructions after saving (as GET)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | INSTRUCTIONS_NOT_A_LIST | Send the instructions as a list. | `instructions` is not an array. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Request body

```json
{
  "instructions": [
    {
      "title": "Refunds",
      "content": "Never promise a refund; ask for approval with the order number.",
      "who": "all"
    },
    {
      "title": "Spanish",
      "content": "Answer in Spanish when the customer writes in Spanish.",
      "who": "only",
      "employees": [
        "ava"
      ]
    }
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The instructions after saving (as GET) |
| `400` | Send the instructions as a list. — `instructions` is not an array. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/team

**Get the AI team workspace**

`operationId: AIEmployeeController_getTeam`

The org's AI team workspace — where its AI employees get goals, tasks and meetings, report, and ask for approvals. Made by the first hire.

#### Signature

```http
GET /ai-employees/team () -> { workspace }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { workspace } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /ai-employees/team

**Set the AI team workspace**

`operationId: AIEmployeeController_setTeam`

Uses the workspace given (one the caller can see), or makes a new private one when none is given. Every AI employee and the caller are added to it.

#### Signature

```http
PUT /ai-employees/team (body) -> { workspace } (as GET)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | NOT_A_WORKSPACE | Choose a workspace, not a conversation. | The id is missing or is a conversation. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Request body

```json
{
  "workspaceId": "6710c0ffee0000000000beef"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { workspace } (as GET) |
| `400` | Choose a workspace, not a conversation. — The id is missing or is a conversation. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/work

**List work items**

`operationId: AIEmployeeController_listWork`

Work across employees, most recently changed first. Pings on which the employee did nothing are left out unless `pings=true`.

#### Signature

```http
GET /ai-employees/work (employee?: string, status?: string, q?: string, source?: string, pings?: boolean, page?: integer, pageSize?: integer) -> { page, pageSize, total, data }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `source` | query | "assigned" \| "ping" \| "direct" \| "message" \| "call" \| "config" | — |  |
| `pings` | query | boolean | — |  |
| `pageSize` | query | integer | — | Up to 200. |
| `page` | query | integer | — |  |
| `q` | query | string | — | Text in the title. |
| `status` | query | string | — | Comma-separated statuses. |
| `employee` | query | string | — | Handle. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { page, pageSize, total, data } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/work/approvals

**List what waits for an approval**

`operationId: AIEmployeeController_approvals`

Every work item waiting for a person to approve, oldest first (up to 200).

#### Signature

```http
GET /ai-employees/work/approvals () -> { total, data }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /ai-employees/work/{id}/decide`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { total, data } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/work/{id}

**Get a work item**

`operationId: AIEmployeeController_getWork`

One work item with its full timeline. Attached records are described from the records themselves.

#### Signature

```http
GET /ai-employees/work/{id} (id: string) -> The work item
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The work item |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/work/{id}/decide

**Approve or reject a request**

`operationId: AIEmployeeController_decide`

A person's answer to what the employee asked permission for. The job goes back to its runtime either way (in progress, unleased) with the decision in its steps. The same request waiting on the employee's other jobs (same action, summary and amount) gets the same answer.

#### Signature

```http
POST /ai-employees/work/{id}/decide (id: string, body) -> The work item
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | DECISION_INVALID | decision must be "approved" or "rejected". | `decision` is anything else. | — |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |
| `403` | AI_CANNOT_DECIDE | An AI employee cannot decide approvals. | The caller is an AI employee. | — |
| `409` | NOT_WAITING | This work is not waiting for an approval. | The job is not `waiting_approval`. | — |

Plus the standard platform errors: `401`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Request body

```json
{
  "decision": "approved",
  "note": "Fine — refund to the original card."
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The work item |
| `400` | decision must be "approved" or "rejected". — `decision` is anything else. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | An AI employee cannot decide approvals. — The caller is an AI employee. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `409` | This work is not waiting for an approval. — The job is not `waiting_approval`. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/work/{id}/cancel

**Cancel a work item**

`operationId: AIEmployeeController_cancel`

#### Signature

```http
POST /ai-employees/work/{id}/cancel (id: string) -> The cancelled work item
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |
| `409` | ALREADY_FINISHED | It is already done. | The job is done, failed or cancelled. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The cancelled work item |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `409` | It is already done. — The job is done, failed or cancelled. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/work/{id}/retry

**Put failed or cancelled work back in the queue**

`operationId: AIEmployeeController_retry`

Queues the job again with its attempts reset and its error cleared.

#### Signature

```http
POST /ai-employees/work/{id}/retry (id: string) -> The queued work item
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | WORK_NOT_FOUND | No such work item | No `ai_employee_work` has that id. | — |
| `409` | NOT_RETRYABLE | Only failed or cancelled work can be retried. | The job is queued, in progress, waiting or done. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `id` | path | string | yes | Work item id (`ai_employee_work` sk). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The queued work item |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No such work item — No `ai_employee_work` has that id. |
| `409` | Only failed or cancelled work can be retried. — The job is queued, in progress, waiting or done. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees

**List AI employees**

`operationId: AIEmployeeController_list`

Every AI employee (templates excluded) with its queue, spend today, whether it is on shift, why it is idle, and totals across all of them.

#### Signature

```http
GET /ai-employees () -> { totals, data }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { totals, data } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees

**Hire an AI employee**

`operationId: AIEmployeeController_create`

Creates the employee and the user it works as (`<name>@<orgId>.ai-employee.local`, no password, locked until switched on, in the `AI` group only). It starts from the org's defaults, then the `template` if one is named, then what is sent. It starts as `draft`: give it groups (`PUT /ai-employees/{name}/access`) and switch it on. Its supervisor gets a direct conversation with it, and it joins (or creates) the AI team workspace with the person who hired it.

#### Signature

```http
POST /ai-employees (body) -> The created employee
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | AI_EMPLOYEE_INVALID | Give it a name people will call it (title). | No title; handle characters; a supervisor that is not an email; unknown listensTo channels; voice platform/voice/greeting/eagerness/speakingSpeed/tools invalid; unknown timezone. Every problem is listed, joined; the body also carries `problems[]`. | — |
| `404` | TEMPLATE_NOT_FOUND | No template "front-desk" | The named template does not exist. | — |
| `409` | HANDLE_TAKEN | There is already an AI employee called "ava". Choose another handle. | An employee or template has that handle. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /ai-employees/templates`
- `PUT /ai-employees/{name}/access`
- `POST /ai-employees/{name}/switch-on`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |

### Request body

```json
{
  "title": "Ava",
  "template": "front-desk",
  "supervisor": "owner@example.com",
  "listensTo": [
    "chat_queue",
    "sms"
  ],
  "workingHours": {
    "alwaysOn": false,
    "timezone": "America/Chicago",
    "days": [
      "mon",
      "tue",
      "wed",
      "thu",
      "fri"
    ],
    "start": "08:00",
    "end": "18:00"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created employee |
| `400` | Give it a name people will call it (title). — No title; handle characters; a supervisor that is not an email; unknown listensTo channels; voice platform/voice/greeting/eagerness/speakingSpeed/tools invalid; unknown timezone. Every problem is listed, joined; the body also carries `problems[]`. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No template "front-desk" — The named template does not exist. |
| `409` | There is already an AI employee called "ava". Choose another handle. — An employee or template has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/{name}/instructions

**Everything an employee is told**

`operationId: AIEmployeeController_instructionsFor`

Its instructions in the order it gets them: the org's that apply to it (`from: org`), then its own job description (`from: employee`). The platform's system instructions come first too, but are listed only in the shared org.

#### Signature

```http
GET /ai-employees/{name}/instructions (name: string) -> { data: [{ title, content, from }] }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { data: [{ title, content, from }] } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/provision

**Create the agent on its provider**

`operationId: AIEmployeeController_provision`

Creates the agent on its runtime provider with its brief (and, for a provider that signs in as it, a fresh sign-in). `stub` records the provisioning and does no work.

#### Signature

```http
POST /ai-employees/{name}/provision (name: string) -> The provider status after provisioning
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | NO_PROVIDER | There is no connection to the provider "external" yet. | The employee's `runtime.provider` has no connection here. | — |
| `502` | PROVIDER_ERROR | The provider refused. | The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /ai-employees/{name}/provider-status`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The provider status after provisioning |
| `400` | There is no connection to the provider "external" yet. — The employee's `runtime.provider` has no connection here. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |
| `502` | The provider refused. — The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. |

## GET /ai-employees/{name}/provider-status

**Ask its provider whether the agent is running**

`operationId: AIEmployeeController_providerStatus`

What the provider says (exists, state), beside when the agent itself was last heard from. A provider that does not answer gives `state: error` with the reason, not an HTTP error.

#### Signature

```http
GET /ai-employees/{name}/provider-status (name: string) -> { provider, status, connection }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | NO_PROVIDER | There is no connection to the provider "external" yet. | The employee's `runtime.provider` has no connection here. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { provider, status, connection } |
| `400` | There is no connection to the provider "external" yet. — The employee's `runtime.provider` has no connection here. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/handover/sign-in

**Issue a sign-in for the system that runs it**

`operationId: AIEmployeeController_issueSignIn`

A new password and a new authenticator secret for its user, replacing any earlier ones (earlier sign-ins stop working). Returned **once** and never stored in the clear — lose it and issue another. Give it only to the system that runs this employee; that system signs in as the employee and gets its own token.

#### Signature

```http
POST /ai-employees/{name}/handover/sign-in (name: string) -> The sign-in, shown once
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Notes

- Treat the response as a credential.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `409` | USER_MISSING | Its user record is missing — recreate the employee. | The employee's user was deleted. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The sign-in, shown once |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `409` | Its user record is missing — recreate the employee. — The employee's user was deleted. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/{name}

**Get an AI employee**

`operationId: AIEmployeeController_detail`

One employee: its state (as in the list), its setup checklist, its record, its user's access, its contact details and phone numbers, and the AI team workspace.

#### Signature

```http
GET /ai-employees/{name} (name: string) -> The employee
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The employee |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /ai-employees/{name}

**Change an AI employee**

`operationId: AIEmployeeController_update`

Changes its profile, hours, limits, approvals, voice and job description. `name`, `userId`, `userEmail`, `status`, `kind` and `voiceAgent` are the server's and ignored here — status changes through switch-on / pause / shut-down. `limits` and `voice` merge into what it has. The employee is told what changed in its next briefing; a new title also renames its user.

#### Signature

```http
PUT /ai-employees/{name} (name: string, body) -> The updated employee
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | AI_EMPLOYEE_INVALID | "Mars/Olympus" is not a timezone. | As on create. Every problem is listed, joined; the body also carries `problems[]`. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "limits": {
    "dailyBudgetUsd": 10
  },
  "approvals": {
    "money": "allow",
    "moneyThresholdUsd": 50
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated employee |
| `400` | "Mars/Olympus" is not a timezone. — As on create. Every problem is listed, joined; the body also carries `problems[]`. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /ai-employees/{name}

**Remove an AI employee**

`operationId: AIEmployeeController_remove`

Takes the agent off its provider, cancels its open work, locks and deactivates its user, removes its voice agent and takes it out of the AI team workspace. Work history stays.

#### Signature

```http
DELETE /ai-employees/{name} (name: string) -> { removed, cancelledWork, provider }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { removed, cancelledWork, provider } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/phones

**Assign a phone number, or release it**

`operationId: AIEmployeeController_setPhone`

Gives one of the org's numbers to the employee (calls to it are then answered by it, and its outbound calls come from it), or takes it away with `assign: false`. Other people on the number keep it. The employee is told.

#### Signature

```http
POST /ai-employees/{name}/phones (name: string, body) -> { phoneNumber, assigned, phones }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `409` | NO_USER | Ava has no user yet, so no number can be assigned to it. | The employee has no login identity. | — |
| `400` | NUMBER_REQUIRED | Say which number (phoneId or phoneNumber). | Neither given. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "phoneNumber": "+15125550143",
  "assign": true
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { phoneNumber, assigned, phones } |
| `400` | Say which number (phoneId or phoneNumber). — Neither given. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `409` | Ava has no user yet, so no number can be assigned to it. — The employee has no login identity. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /ai-employees/{name}/access

**Get its access**

`operationId: AIEmployeeController_access`

The groups its user holds (besides `AI`, which it always has), and the org's groups it could be given (platform/Root groups never).

#### Signature

```http
GET /ai-employees/{name}/access (name: string) -> { email, groups, always, available }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { email, groups, always, available } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /ai-employees/{name}/access

**Set its access**

`operationId: AIEmployeeController_setAccess`

Gives its user exactly these groups (plus `AI`), through the same user service User Management uses. The employee is told its new groups.

#### Signature

```http
PUT /ai-employees/{name}/access (name: string, body) -> Its access after the change (as GET)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | GROUPS_NOT_A_LIST | groups must be a list of group names. | `groups` is not an array. | — |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `409` | USER_MISSING | Its user record is missing — recreate the employee. | The employee's user was deleted. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "groups": [
    "FrontDesk",
    "Reservations"
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Its access after the change (as GET) |
| `400` | groups must be a list of group names. — `groups` is not an array. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `409` | Its user record is missing — recreate the employee. — The employee's user was deleted. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/switch-on

**Switch it on**

`operationId: AIEmployeeController_switchOn`

Status `active`: it takes work, its user is unlocked, it is pinged on schedule, and a shut-down agent is started again on its provider. It needs at least one group first.

#### Signature

```http
POST /ai-employees/{name}/switch-on (name: string) -> The employee (as GET)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `409` | USER_MISSING | Its user record is missing — recreate the employee. | The employee's user was deleted. | — |
| `400` | NO_ACCESS | Give Ava access first: choose at least one group for it under Access. Without one it can do nothing. | Its user has no group or role besides `AI`. | Set its access, then switch it on. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `PUT /ai-employees/{name}/access`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The employee (as GET) |
| `400` | Give Ava access first: choose at least one group for it under Access. Without one it can do nothing. — Its user has no group or role besides `AI`. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `409` | Its user record is missing — recreate the employee. — The employee's user was deleted. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/budget

**Adjust today's budget**

`operationId: AIEmployeeController_budget`

`reset` counts spend again from now; `credit` adds `amountUsd` on top of today's budget. Both lapse at midnight in its timezone. Budget alerts can fire again after either.

#### Signature

```http
POST /ai-employees/{name}/budget (name: string, body) -> The employee (as GET)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | BUDGET_ACTION_INVALID | action must be "reset" or "credit". | Any other action. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "action": "reset"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The employee (as GET) |
| `400` | action must be "reset" or "credit". — Any other action. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/pause

**Pause it**

`operationId: AIEmployeeController_pause`

Status `paused`: it takes no work and its login is locked, so a runtime holding a token is stopped at its next call. A running session is not ended — use shut-down for that.

#### Signature

```http
POST /ai-employees/{name}/pause (name: string, body) -> The employee (as GET)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /ai-employees/{name}/shut-down`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "reason": "Reviewing its refunds"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The employee (as GET) |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/shut-down

**Shut it down**

`operationId: AIEmployeeController_shutDown`

Harder than pause: its running session is ended now, what it had taken goes back in the queue, and it is paused (login locked). Switch it on to start it again.

#### Signature

```http
POST /ai-employees/{name}/shut-down (name: string) -> Provider status plus `requeued` (jobs put back)
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | NO_PROVIDER | There is no connection to the provider "external" yet. | The employee's `runtime.provider` has no connection here. | — |
| `502` | PROVIDER_ERROR | The session manager did not stop it. | The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Provider status plus `requeued` (jobs put back) |
| `400` | There is no connection to the provider "external" yet. — The employee's `runtime.provider` has no connection here. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |
| `502` | The session manager did not stop it. — The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. |

## POST /ai-employees/{name}/restart

**Restart it**

`operationId: AIEmployeeController_restart`

Ends its session now and starts a fresh one that reads its briefing anew; what it had taken goes back in the queue. `forget: true` also drops the conversations it would resume.

#### Signature

```http
POST /ai-employees/{name}/restart (name: string, body) -> Provider status plus `requeued` and `forgotten`
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | NO_PROVIDER | There is no connection to the provider "external" yet. | The employee's `runtime.provider` has no connection here. | — |
| `502` | PROVIDER_ERROR | The session manager did not restart it. | The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "forget": true
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Provider status plus `requeued` and `forgotten` |
| `400` | There is no connection to the provider "external" yet. — The employee's `runtime.provider` has no connection here. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |
| `502` | The session manager did not restart it. — The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. |

## GET /ai-employees/{name}/memory

**Get its working memory**

`operationId: AIEmployeeController_memory`

The notes it wrote for itself (newest first) and, when its provider says, the conversations it would resume.

#### Signature

```http
GET /ai-employees/{name}/memory (name: string) -> { notes, rememberedSessions, canForgetSessions }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | NO_PROVIDER | There is no connection to the provider "external" yet. | The employee's `runtime.provider` has no connection here. | — |
| `409` | NO_USER | Ava has no user, so it keeps no notes. | The employee has no user. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | { notes, rememberedSessions, canForgetSessions } |
| `400` | There is no connection to the provider "external" yet. — The employee's `runtime.provider` has no connection here. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `409` | Ava has no user, so it keeps no notes. — The employee has no user. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/memory/notes/remove

**Remove notes from its memory**

`operationId: AIEmployeeController_forgetNotes`

`at` removes the note written at that time; without it, all its notes are cleared.

#### Signature

```http
POST /ai-employees/{name}/memory/notes/remove (name: string, body) -> Its notes after the change
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | NOTE_TIME_INVALID | Say which note (its time). | `at` is not a date. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "at": "2026-09-28T14:03:11.000Z"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Its notes after the change |
| `400` | Say which note (its time). — `at` is not a date. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /ai-employees/{name}/memory/forget-sessions

**Drop the conversations it would resume**

`operationId: AIEmployeeController_forgetSessions`

So its next job starts clean.

#### Signature

```http
POST /ai-employees/{name}/memory/forget-sessions (name: string) -> Its memory (as GET) plus `forgotten`
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | NO_PROVIDER | There is no connection to the provider "external" yet. | The employee's `runtime.provider` has no connection here. | — |
| `502` | PROVIDER_ERROR | The session manager did not answer. | The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Responses

| Status | Meaning |
| --- | --- |
| `201` | Its memory (as GET) plus `forgotten` |
| `400` | There is no connection to the provider "external" yet. — The employee's `runtime.provider` has no connection here. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |
| `502` | The session manager did not answer. — The runtime provider (session manager) refused or did not answer; the text is its reason when it gave one. |

## POST /ai-employees/{name}/work

**Give an employee work**

`operationId: AIEmployeeController_enqueue`

Queues a direct request. The title defaults to the first line of the instructions. Attachments are records (`kind: record`, datatype, id) and documents (`kind: file`, path or url), each with a comment on what it is for; a record is described from the record itself.

#### Signature

```http
POST /ai-employees/{name}/work (name: string, body) -> The queued work item
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `Owner`, `ConfigAdmin`, `RootAdmin`, `RootSystem`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | AI_EMPLOYEE_NOT_FOUND | No AI employee "ava" | No employee (templates excluded) has that handle. | — |
| `400` | WORK_TITLE_REQUIRED | Say what the work is. | No title and no instructions. | — |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `orgid` | header | string | yes |  |
| `name` | path | string | yes | The employee's handle (`ai_employee.name`). |

### Request body

```json
{
  "title": "Call back the Garcia party",
  "instructions": "They asked to move Friday's booking to 8pm. Confirm by text.",
  "priority": "high",
  "attachments": [
    {
      "kind": "record",
      "datatype": "reservation",
      "id": "6710c0ffee0000000000f00d",
      "comment": "The booking"
    }
  ]
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The queued work item |
| `400` | Say what the work is. — No title and no instructions. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | No AI employee "ava" — No employee (templates excluded) has that handle. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

