---
summary: "Every ScaiQueue endpoint \u2014 scopes, queues, messages, routing, streams,\
  \ subscriptions, ACLs, schemas, HITL patterns, audit, API keys, GDPR."
title: API reference
path: reference/api
status: published
---

All endpoints are mounted at `/v1/modules/scaiqueue/` and authenticate with the standard ScaiGrid bearer token. Responses use ScaiGrid's standard envelope (`{ "data": ... }` for success, `{ "error": ... }` for failures). All routes require a tenant-scoped caller — `super_admin` without a tenant cannot use these endpoints.

## Scopes

A scope is a tenant-owned namespace for queues. Creating a scope also creates five system queues: `_dead_letter`, `_events`, `_audit`, `_integrity`, `_corrections`.

### `POST /scopes`

Create a scope. Requires `scaiqueue:manage`.

| Field | Required | Notes |
|---|---|---|
| `slug` | yes | Unique within tenant. |
| `display_name` | no | Defaults to `slug`. |
| `description` | no | |
| `defaults` | no | Object of default settings inherited by queues. |

### `GET /scopes`

List scopes in the caller's tenant. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}`

Fetch one scope. Requires `scaiqueue:view`.

### `POST /scopes/{scope_id}/{pause|resume|drain|archive|unarchive}`

State transitions, each requiring `scaiqueue:manage`. Allowed moves:

- `active` → `paused`, `draining`, `archived`
- `paused` → `active`, `draining`, `archived`
- `draining` → `archived`
- `archived` → `active`

Paused or archived scopes reject new publishes.

### `DELETE /scopes/{scope_id}`

Hard-delete. Scope must be `archived` first. Requires `scaiqueue:manage`.

## Queues

A queue lives in a scope and has an ordering mode (`fifo`, `priority`, `deadline`) and a consumer mode (`competing`, `broadcast`).

### `POST /scopes/{scope_id}/queues`

Create a queue. Requires `scaiqueue:manage`.

| Field | Required | Notes |
|---|---|---|
| `slug` | yes | Unique within scope. |
| `display_name` | no | Defaults to slug. |
| `description` | no | |
| `consumer_mode` | no | `competing` (default) or `broadcast`. |
| `ordering` | no | `fifo` (default), `priority`, or `deadline`. |
| `max_depth` | no | 0 means unlimited. |
| `overflow_policy` | no | `reject` (default) or other strategies. |

### `GET /scopes/{scope_id}/queues`

List queues in a scope. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/queues/{queue_id}`

Fetch one queue. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/queues/{queue_id}/stats`

Current `depth_current`, `depth_pending`, `depth_claimed`. Requires `scaiqueue:view`.

### `POST /scopes/{scope_id}/queues/{queue_id}/{pause|resume}`

Pause and resume. Requires `scaiqueue:manage`. Paused queues reject new publishes.

### `DELETE /scopes/{scope_id}/queues/{queue_id}`

Delete a non-system queue with `depth_current == 0`. Requires `scaiqueue:manage`.

## Messages

### `POST /scopes/{scope_id}/queues/{queue_id}/messages`

Publish. Requires `scaiqueue:publish`.

| Field | Required | Notes |
|---|---|---|
| `body` | yes | String or object; objects are JSON-serialised. |
| `type` | no | `message_type`; default `task`. |
| `priority.tier` | no | `critical`, `high`, `normal` (default), `low`, `background`. |
| `priority.score` | no | 0–1000; default 500. |
| `labels` | no | `{key: value}` map. |
| `content_type` | no | `application/json` default. |
| `correlation_id`, `causation_id`, `parent_id` | no | Lineage. |
| `ttl_seconds` | no | If set, expiry enforcer terminalises after this. |
| `max_retries` | no | Default 3. |
| `visibility_timeout_s` | no | Default 30. |
| `idempotency_key` | no | Replays return original message id. |
| `hitl_spec` | no | Object with rendering spec. |

### `POST /scopes/{scope_id}/queues/{queue_id}/messages/claim`

Claim messages. Requires `scaiqueue:consume`. Body: `{ "batch_size": int, "visibility_timeout_s": int }`. Returns a list of full message representations including body and HITL spec.

### `POST /scopes/{scope_id}/messages/{msg_id}/complete`

Mark complete. Requires `scaiqueue:consume`. Body: `{ "response": object | null }`. Emits a `scaiqueue.message.completed` event on the event bus carrying the original `correlation_id`.

### `POST /scopes/{scope_id}/messages/{msg_id}/fail`

Mark failed. Requires `scaiqueue:consume`. Body: `{ "reason": string }`. Triggers retry or dead-letter depending on `attempts` vs `max_retries`.

### `POST /scopes/{scope_id}/messages/{msg_id}/release`

Return a claimed message to pending. Requires `scaiqueue:consume`.

### `POST /scopes/{scope_id}/messages/{msg_id}/extend`

Extend the visibility timeout. Requires `scaiqueue:consume`. Body: `{ "seconds": int }`.

### `POST /scopes/{scope_id}/messages/{msg_id}/cancel`

Cancel a pending or claimed message. Requires `scaiqueue:manage`.

### `GET /scopes/{scope_id}/queues/{queue_id}/messages`

List messages in a queue. Requires `scaiqueue:view`. Query params: `state` (one of `pending`, `claimed`, `completed`, `failed`, `dead_lettered`, `cancelled`, `expired`), `limit` (default 50), `cursor`.

### `GET /scopes/{scope_id}/queues/{queue_id}/messages/{msg_id}`

Full message including body, hitl_spec, response. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/messages?correlation_id=...`

Return every message in a correlation chain across the scope. Requires `scaiqueue:view`.

## Routing rules

Rules live on a scope and fire on triggers (`message_published` is the default). First matching rule (priority ascending) wins; rule actions move/transform messages, with a 5-hop circuit breaker.

### `POST /scopes/{scope_id}/routing-rules`

Create. Requires `scaiqueue:manage`. Body: `{ name, description, priority, enabled, trigger, conditions, action, source }`.

### `GET /scopes/{scope_id}/routing-rules`

List rules in priority-ascending order. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/routing-rules/{rule_id}`

Fetch one rule. Requires `scaiqueue:view`.

### `PATCH /scopes/{scope_id}/routing-rules/{rule_id}`

Update name, description, priority, trigger, conditions, action, enabled. Requires `scaiqueue:manage`.

### `DELETE /scopes/{scope_id}/routing-rules/{rule_id}`

Delete. Requires `scaiqueue:manage`.

### `POST /scopes/{scope_id}/routing-rules/{rule_id}/{enable|disable}`

Toggle enabled. Requires `scaiqueue:manage`.

### `POST /scopes/{scope_id}/routing-rules/test`

Dry-run rules against a hypothetical message. Body: `{ "trigger": "message_published", "message": { ... } }`. Returns the rules that would match. Requires `scaiqueue:view`.

## Streams

A stream is a sequence of chunk messages that the stream service can assemble.

### `GET /scopes/{scope_id}/streams`

List streams, optional `state` filter. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/streams/{stream_id}`

Stream metadata plus a summary of chunks. Requires `scaiqueue:view`.

### `POST /scopes/{scope_id}/streams/{stream_id}/cancel`

Cancel an open stream. Requires `scaiqueue:manage`.

### `GET /scopes/{scope_id}/streams/{stream_id}/assembled`

Assembled content (default `concatenate` mode). Requires `scaiqueue:view`.

## Subscriptions

A subscription binds a consumer (user, agent) to a queue with a filter and a delivery mode.

### `POST /scopes/{scope_id}/subscriptions`

Create. Requires `scaiqueue:consume`. Body fields include `subscriber_type`, `subscriber_id`, `queue_id`, `filter`, `delivery_mode` (`pull` default), `auto_claim`, `max_in_flight`.

### `GET /scopes/{scope_id}/subscriptions`

List for a scope. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/subscriptions/{sub_id}`

Fetch one. Requires `scaiqueue:view`.

### `PATCH /scopes/{scope_id}/subscriptions/{sub_id}`

Update `filter`, `delivery_mode`, `auto_claim`, `max_in_flight`. Requires `scaiqueue:manage`.

### `DELETE /scopes/{scope_id}/subscriptions/{sub_id}`

Delete. Requires `scaiqueue:manage`.

### `POST /scopes/{scope_id}/subscriptions/{sub_id}/{pause|resume}`

Toggle active. Requires `scaiqueue:manage`.

### `POST /subscriptions/{sub_id}/check-processed`

Return a `{message_id: bool}` map of which message ids the subscription has already processed (Redis-backed dedup). Requires `scaiqueue:consume`.

## Message schemas

JSON-Schema definitions per scope. Used to validate payloads.

### `POST /scopes/{scope_id}/schemas`

Register a schema. Requires `scaiqueue:manage`. Body: `{ name, version, schema }`.

### `GET /scopes/{scope_id}/schemas`

List schemas in scope. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/schemas/{name}/{version}`

Fetch one. Requires `scaiqueue:view`.

### `POST /scopes/{scope_id}/schemas/{name}/{version}/validate`

Validate a payload. Body: `{ "payload": ... }`. Returns `{ valid, errors }`. Requires `scaiqueue:view`.

### `DELETE /scopes/{scope_id}/schemas/{name}/{version}`

Soft-delete (sets `deprecated=true`). Requires `scaiqueue:manage`.

## HITL pattern registry

Reusable rendering specs that messages can reference by name.

### `POST /scopes/{scope_id}/hitl-patterns`

Register a pattern. Requires `scaiqueue:manage`. Body: `{ name, version, spec, parameters }`.

### `GET /scopes/{scope_id}/hitl-patterns`

List. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/hitl-patterns/{name}/{version}`

Fetch the spec and parameters. Requires `scaiqueue:view`.

### `POST /scopes/{scope_id}/hitl-patterns/{name}/expand`

Expand a pattern with parameters (substitutes `{{key}}` placeholders). Body: `{ version, parameters }`. Requires `scaiqueue:view`.

## ACL

Per-scope grants, per-queue ACL entries, and cross-scope trust grants. All routes require `scaiqueue:manage`.

### `GET /scopes/{scope_id}/acl`

Return `{ grants, queue_acl, trusted_scopes }` for the scope.

### `POST /scopes/{scope_id}/acl/grants`

Add a scope grant. Body: `{ actor_type, actor_id, role, conditions }`.

### `DELETE /scopes/{scope_id}/acl/grants/{grant_id}`

Revoke a grant.

### `POST /scopes/{scope_id}/acl/queue-acl`

Add a per-queue ACL entry. Body: `{ queue_id, actor_type, actor_id, role, effect, conditions }` with `effect` of `allow` (default) or `deny`.

### `DELETE /scopes/{scope_id}/acl/queue-acl/{entry_id}`

Remove a per-queue ACL entry.

### `POST /scopes/{scope_id}/acl/trusted-scopes`

Trust another scope for cross-scope routing. Body: `{ target_scope_id, direction, allowed_types, allowed_queues, identity_mode }`.

### `DELETE /scopes/{scope_id}/acl/trusted-scopes/{trust_id}`

Revoke a cross-scope trust.

## API keys

ScaiQueue-specific API keys for service/agent callers, separate from ScaiGrid's tenant API keys. All routes require `scaiqueue:manage`.

### `POST /tenants/{tenant_id}/api-keys`

Mint a key. Body fields include `subject_id`, `subject_type`, `key_type`, `label`, `allowed_scopes`, `allowed_operations`, `ip_allowlist`, `expires_in_days`, `grace_period_seconds`. Returns the raw key once.

### `GET /tenants/{tenant_id}/api-keys`

List keys.

### `GET /tenants/{tenant_id}/api-keys/{key_id}`

Fetch metadata for one key.

### `POST /tenants/{tenant_id}/api-keys/{key_id}/rotate`

Rotate. Returns the new raw key; the old key remains valid for `grace_period_seconds`.

### `POST /tenants/{tenant_id}/api-keys/{key_id}/revoke`

Revoke. Body: `{ reason }`.

## Audit log

### `GET /scopes/{scope_id}/audit`

Query audit events. Filters: `event_type`, `actor_id`, `resource_type`, `correlation_id`, `limit` (default 50). Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/audit/trace/{correlation_id}`

Every audit event for a correlation chain, oldest first. Requires `scaiqueue:view`.

### `GET /scopes/{scope_id}/audit/stats`

`{event_type: count}` aggregate over the scope. Requires `scaiqueue:view`.

## System agents

### `GET /system-agents`

Status of every system agent (visibility-timeout enforcer, expiry enforcer, archiver, dead-letter monitor, priority-aging worker): `status`, `total_runs`, `total_processed`, `total_errors`, `last_run_at`, `last_run_duration_ms`, `last_error`. Requires `scaiqueue:view`.

## GDPR

### `POST /tenants/{tenant_id}/data-erasure`

Submit an erasure request. Body: `{ mode, actor_type, actor_id }` with `mode` of `redact` (default) or other supported modes. Returns a job id. Requires `scaiqueue:manage`.

### `GET /tenants/{tenant_id}/data-erasure/jobs/{job_id}`

Job status. Requires `scaiqueue:manage`.

### `POST /tenants/{tenant_id}/data-export`

Submit an export request. Requires `scaiqueue:manage`.

### `GET /tenants/{tenant_id}/data-export/jobs/{job_id}`

Job status. Requires `scaiqueue:manage`.

## Errors

All endpoints return ScaiGrid's standard error envelope:

```json
{
  "error": {
    "code": "SCAIQUEUE_QUEUE_FULL",
    "message": "Queue depth limit reached",
    "details": { }
  },
  "meta": { "request_id": "req_..." }
}
```

ScaiQueue-specific codes:

| Code | HTTP | Meaning |
|---|---|---|
| `SCAIQUEUE_SCOPE_NOT_FOUND` | 404 | Scope id doesn't exist or isn't visible. |
| `SCAIQUEUE_QUEUE_NOT_FOUND` | 404 | Queue id doesn't exist or isn't visible. |
| `SCAIQUEUE_MESSAGE_NOT_FOUND` | 404 | Message id doesn't exist or isn't visible. |
| `SCAIQUEUE_SLUG_CONFLICT` | 409 | Scope or queue slug already exists at that level. |
| `SCAIQUEUE_CLAIM_FAILED` | 409 | Claim raced with another consumer. |
| `SCAIQUEUE_NOT_CLAIMED` | 409 | Tried to complete/fail/extend a message that isn't claimed. |
| `SCAIQUEUE_INVALID_TRANSITION` | 409 | Disallowed state transition (e.g. resume an archived scope, delete a non-empty queue, delete a system queue). |
| `SCAIQUEUE_QUEUE_FULL` | 429 | Queue's `max_depth` reached and `overflow_policy=reject`. |
| `SCAIQUEUE_RATE_LIMITED` | 429 | Tenant-level rate limit hit. |
| `SCAIQUEUE_IDEMPOTENCY_CONFLICT` | 409 | Idempotency key seen with a different body. |
| `SCAIQUEUE_SCOPE_PAUSED` | 409 | Scope is paused or archived; no publishes accepted. |
| `SCAIQUEUE_QUEUE_PAUSED` | 409 | Queue is paused. |
| `SCAIQUEUE_ATTACHMENT_ERROR` | 500 | Attachment storage failed. |
