# API reference

Caller-owned entity registration, entity-type discovery and sequence admission. The API key supplies tenant, lane and integration association. HTTP 202 describes admission, not completed execution. Schemas cover transport shapes; handler checks and Zod refinements are described per operation. Browser, pairing, health and management interfaces are outside this public-v1 reference.

Generated from the registered public-v1 routes and their schemas. Edit source contracts and operation descriptions, then regenerate; do not edit this page directly.

Download the [OpenAPI specification](https://docs.amonsul.io/downloads/openapi.json) for the complete nested transport shapes. Use the [machine API guide](https://docs.amonsul.io/developers/api/) for the registration-to-execution flow.

## Authentication and interpretation

Use your administrator-provided HTTPS API origin. Send `Authorization: Bearer <api-key>` or `X-API-Key: <api-key>`; the latter takes precedence if both are supplied. The key supplies tenant, lane and integration association. Request fields cannot change that identity.

Scope checks, policy bindings, input-contract validation and execution ownership are runtime checks. JSON schemas do not express all of them. Framework authentication, rate-limit and validation errors can have different shapes from handler errors. HTTP 202 does not mean work has completed.

Enqueue and entity routes configure standard/premium/enterprise limits of 300/1000/5000 requests per minute per key, with an IP fallback. `entity-types/{entityType}/statuses` and `association/entity-counts` fall under the platform's blanket limit of 1,000 requests per minute per client IP.

## Count associated entities

`GET /api/public/v1/association/entity-counts` — required scope: `read_entities`

Count entities owned by the authenticated integration association within its lane, grouped by entity type. Associations with no entities return an empty counts array.

Schema source: Authored from TypeScript return shape; not runtime validation.

### Responses

| Status | Meaning                                         |
| ------ | ----------------------------------------------- |
| 200    | Association identity and counts by entity type. |
| 401    | Authentication failed.                          |
| 403    | Lane or scope refused.                          |
| 404    | The API key has no integration association.     |
| 429    | Rate limit exceeded; inspect response headers.  |

Successful response fields:

| Field           | Type   | Required | Default |
| --------------- | ------ | -------- | ------- |
| `associationId` | string | yes      |         |
| `counts`        | array  | yes      |         |

## Admit a sequence

`POST /api/public/v1/enqueue` — required scope: `enqueue`

Start offered work for a registered entity under its pinned policy. HTTP 202 means admission was accepted; it does not mean the sequence or external effects have completed. Use the concrete sequence_id offered by the entity response. executed_by is an audit label; the key remains the authenticated caller.

Schema source: Fastify route schema.

- Supply entity_id or external_id, plus sequence_id or sequence_code. UUID selectors must have valid UUID v4 format.
- Sequence selection, policy availability, input contracts, execution ownership and association/lane context are validated by the handler.
- After an uncertain response, inspect execution evidence before retrying; no blanket idempotency guarantee is made.

### Request body

| Field                 | Type   | Required | Default |
| --------------------- | ------ | -------- | ------- |
| `entity_id`           | string | no       |         |
| `external_id`         | string | no       |         |
| `entity_type`         | string | yes      |         |
| `sequence_id`         | string | no       |         |
| `sequence_code`       | string | no       |         |
| `starting_parameters` | object | no       |         |
| `executed_by`         | string | no       |         |

Admit offered invoice work

```json
{
  "external_id": "INV-001",
  "entity_type": "invoice",
  "sequence_id": "00000000-0000-4000-8000-000000000001",
  "starting_parameters": {
    "invoice_number": "INV-001"
  }
}
```

### Responses

| Status | Meaning                                                               |
| ------ | --------------------------------------------------------------------- |
| 202    | Sequence admission accepted; execution has not necessarily completed. |
| 400    | Missing selector or invalid UUID.                                     |
| 401    | Authentication failed.                                                |
| 403    | Scope or admission refused.                                           |
| 404    | Entity or permitted sequence not found.                               |
| 409    | Conflicting execution ownership or context.                           |
| 422    | Sequence input or policy validation failed.                           |
| 429    | Rate limit exceeded; inspect response headers.                        |
| 500    | Unexpected admission error; inspect evidence before retrying.         |

Successful response fields:

| Field           | Type    | Required | Default |
| --------------- | ------- | -------- | ------- |
| `success`       | boolean | yes      |         |
| `message`       | string  | yes      |         |
| `entity_id`     | string  | yes      |         |
| `external_id`   | string  | yes      |         |
| `sequence_id`   | string  | yes      |         |
| `sequence_code` | string  | yes      |         |
| `tenant_id`     | string  | yes      |         |
| `run_id`        | string  | no       |         |

## Register an entity

`POST /api/public/v1/entities` — required scope: `enqueue`

Register a caller-owned external entity under the authenticated lane and integration association. Published policy bindings determine its matrix or composite tracks. Initial status selection must be valid for the bound policy. registration_context records evidence and does not confer access.

Schema source: Fastify route schema.

- The external identifier is scoped to entity type, lane and integration association.
- Initial status codes are checked against the bound policy. Composite role selection and status validation occur in the handler.

### Request body

| Field                  | Type   | Required | Default |
| ---------------------- | ------ | -------- | ------- |
| `external_id`          | string | yes      |         |
| `entity_type`          | string | yes      |         |
| `initial_status_code`  | string | no       |         |
| `initial_status_codes` | object | no       |         |
| `description`          | string | no       |         |
| `metadata`             | object | no       |         |
| `registration_context` | object | no       |         |

Register an invoice

```json
{
  "external_id": "INV-001",
  "entity_type": "invoice",
  "description": "Invoice awaiting review",
  "metadata": {
    "sourceRecordId": "INV-001"
  }
}
```

### Responses

| Status | Meaning                                        |
| ------ | ---------------------------------------------- |
| 201    | Entity registered with its policy context.     |
| 400    | Invalid registration request.                  |
| 401    | Authentication failed.                         |
| 403    | Default Response                               |
| 409    | Entity is already registered.                  |
| 422    | Invalid policy or initial status context.      |
| 429    | Rate limit exceeded; inspect response headers. |
| 500    | Default Response                               |

Successful response fields:

| Field         | Type    | Required | Default |
| ------------- | ------- | -------- | ------- |
| `success`     | boolean | yes      |         |
| `entity_id`   | string  | yes      |         |
| `external_id` | string  | yes      |         |
| `entity_type` | string  | yes      |         |
| `status`      | object  | yes      |         |
| `matrix`      | object  | yes      |         |
| `tracks`      | array   | no       |         |

## Register entities in a batch

`POST /api/public/v1/entities/batch` — required scope: `enqueue`

Register up to 500 caller-owned entities in one call. Each row is a POST /entities body and is judged on its own. The answer lists one { status, body } per row, in request order: 201 with the registered entity, 409 when it is already registered, or 422 for an invalid policy or initial status context. A 422 row leaves nothing behind. Anything unexpected rolls back the whole batch with 500.

Schema source: Fastify route schema.

- Each row follows the POST /entities rules; a row's status is 201, 409 or 422.
- The batch is one request against the registration rate limit.

### Request body

| Field      | Type  | Required | Default |
| ---------- | ----- | -------- | ------- |
| `entities` | array | yes      |         |

`entities` holds 1-500 registration bodies, each with the fields of [Register an entity](#register-an-entity).

Register two invoices

```json
{
  "entities": [
    {
      "external_id": "INV-001",
      "entity_type": "invoice",
      "description": "Invoice awaiting review"
    },
    {
      "external_id": "INV-002",
      "entity_type": "invoice",
      "description": "Invoice awaiting review"
    }
  ]
}
```

### Responses

| Status | Meaning                                        |
| ------ | ---------------------------------------------- |
| 200    | One result per row, in request order.          |
| 400    | Invalid registration request.                  |
| 401    | Authentication failed.                         |
| 403    | Default Response                               |
| 429    | Rate limit exceeded; inspect response headers. |
| 500    | Default Response                               |

Successful response fields:

| Field         | Type   | Required | Default |
| ------------- | ------ | -------- | ------- |
| `observed_at` | string | yes      |         |
| `results`     | array  | yes      |         |

## Read entity and offered work

`GET /api/public/v1/entities/{identifier}` — required scope: `read_entities`

Use the internal entity UUID, or an external identifier with entity_type. Reads preserve key lane and association ownership. Choose an available concrete sequence_id from the offered sequences; sequence codes can be ambiguous across tracks.

Schema source: Fastify route schema.

- External identifiers require entity_type. Entity lookup is lane, type and association scoped.

### Parameters

| Name          | Location | Required | Type / default |
| ------------- | -------- | -------- | -------------- |
| `entity_type` | query    | no       | string         |
| `identifier`  | path     | yes      | string         |

### Responses

| Status | Meaning                                              |
| ------ | ---------------------------------------------------- |
| 200    | Entity identity, policy state and offered sequences. |
| 400    | Default Response                                     |
| 401    | Authentication failed.                               |
| 403    | Default Response                                     |
| 404    | Entity not found in the authenticated context.       |
| 429    | Rate limit exceeded; inspect response headers.       |
| 500    | Default Response                                     |

Successful response fields:

| Field                 | Type   | Required | Default |
| --------------------- | ------ | -------- | ------- |
| `entity_id`           | string | yes      |         |
| `external_id`         | string | yes      |         |
| `entity_type`         | string | yes      |         |
| `current_status`      | object | yes      |         |
| `available_sequences` | array  | yes      |         |
| `tracks`              | array  | no       |         |
| `workflow_state`      | object | no       |         |

## Read execution history

`GET /api/public/v1/entities/{identifier}/history` — required scope: `read_entities`

Read paginated action execution history for a permitted entity. Use entity_type with an external identifier. History defaults to limit 50 and offset 0. This endpoint describes recorded evidence and does not authorize execution.

Schema source: Fastify route schema.

- External identifiers require entity_type. Entity lookup is lane, type and association scoped.

### Parameters

| Name          | Location | Required | Type / default |
| ------------- | -------- | -------- | -------------- |
| `entity_type` | query    | no       | string         |
| `limit`       | query    | no       | number / 50    |
| `offset`      | query    | no       | number / 0     |
| `identifier`  | path     | yes      | string         |

### Responses

| Status | Meaning                                        |
| ------ | ---------------------------------------------- |
| 200    | History records and pagination.                |
| 400    | Default Response                               |
| 401    | Authentication failed.                         |
| 403    | Default Response                               |
| 404    | Entity not found in the authenticated context. |
| 429    | Rate limit exceeded; inspect response headers. |
| 500    | Default Response                               |

Successful response fields:

| Field            | Type   | Required | Default |
| ---------------- | ------ | -------- | ------- |
| `entity_id`      | string | yes      |         |
| `external_id`    | string | yes      |         |
| `entity_type`    | string | yes      |         |
| `current_status` | object | yes      |         |
| `history`        | array  | yes      |         |
| `pagination`     | object | yes      |         |

## Read permitted entity statuses

`GET /api/public/v1/entity-types/{entityType}/statuses` — required scope: `read_entities`

Read the exact entity type and its lane-resolved track/status catalog. Existing types without a binding can return an empty tracks array. Track statusCodes must mirror statuses in order.

Schema source: Zod EntityTypeStatusesResponseSchema; refinements described in prose.

### Parameters

| Name         | Location | Required | Type / default |
| ------------ | -------- | -------- | -------------- |
| `entityType` | path     | yes      | string         |

### Responses

| Status | Meaning                                               |
| ------ | ----------------------------------------------------- |
| 200    | Entity type and permitted tracks.                     |
| 401    | Authentication failed.                                |
| 403    | Scope or authenticated context refused.               |
| 404    | Entity type does not exist in the authenticated lane. |
| 429    | Rate limit exceeded; inspect response headers.        |

Successful response fields:

| Field        | Type   | Required | Default |
| ------------ | ------ | -------- | ------- |
| `entityType` | string | yes      |         |
| `tracks`     | array  | yes      |         |
