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

> ## Agent Instructions
> Arcmira has three API capabilities: Search (entities, mentions, appearances, commercial intelligence), Monitors (trackers plus alert delivery), and Transcripts (read, generate, correct). Community Review is the cross-surface correction layer.
> Discover pages at https://docs.arcmira.com/llms.txt, then fetch the matching page's .md export. Each capability has a self-contained '<capability> for coding agents' page; prefer it.
> Auth: Authorization: Bearer arc_sk_... or x-api-key: arc_sk_... (x-api-key wins if both are sent). Never put keys in browser code. Check GET /v1/me for tier, scopes, and remaining rows before metered pulls.
> Search: resolve names with GET /v1/entities/lookup and pin ent_* IDs before pulling metered rows. Only person entities have appearances. Mention and recommendation rows carry canonical numeric timestamps in start_seconds/end_seconds (integer seconds; 0 means full episode); the MM:SS string fields are deprecated. Commercial routes need Pro+ tier AND the recommendations:read scope and bill 10 rows per row.
> Monitors: a tracker watches one entity; a monitor groups trackers with shared delivery (email, Slack, HMAC-signed webhooks). Create trackers with POST /v1/trackers, then attach by id: POST /v1/monitors/{id}/trackers { trackerIds: [...] }. Each fired alert occurrence debits 100 rows. Poll GET /v1/monitors/{id}/alerts?n= for recent deliveries. Send Idempotency-Key on every POST/PATCH.
> Transcripts: switch on the access field (unlocked, locked, premium_pending, not_transcribed, unauthenticated). Honor Retry-After when polling POST /v1/transcriptions jobs. Corrections (POST /v1/videos/{video_id}/corrections; kinds line_edit, speaker_reassign, speaker_identify, add_person, entity_tag, segment_rewrite) cost 0 rows; anchored kinds need revision + anchor.contentHash (djb2 base-36); handle 409 (re-anchor) and 412 (expectedSeq). segment_rewrite replaces an inclusive segment range with new segments (empty replacements array deletes; timestamps repaired server-side).
> Community Review is free (0 rows) and surface-typed: POST /v1/feedback with a type matching the surface you called, the reproducing query, and corrections targeting public IDs (ent_*, men_*, com_*). Nothing auto-applies. Do not send untyped notes.
> Errors: switch on error.code, follow doc_url, quote X-Request-Id to support. Honor Retry-After on 429. Retries of POST/PATCH must reuse the same Idempotency-Key; replays return Idempotency-Replayed: true.

# Errors

> The error envelope, status codes, machine-stable error codes with causes and fixes, and request IDs.

Arcmira returns errors in a stable JSON envelope so client logic can switch on `error.code` without parsing strings.

## Envelope

```json theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_query",
    "message": "Required parameter `q` is missing.",
    "param": "q",
    "doc_url": "https://docs.arcmira.com/errors#invalid_query",
    "request_id": "req_8677e87a-3aeb-4403-a449-9d6ab8a1898b"
  }
}
```

| Field        | Description                                                                                          |
| ------------ | ---------------------------------------------------------------------------------------------------- |
| `type`       | High-level category. Maps roughly to HTTP class.                                                     |
| `code`       | Machine-stable error identifier. **Switch on this.**                                                 |
| `message`    | Human-readable explanation. Safe to surface in dev consoles.                                         |
| `param`      | Reserved: identifies the offending query/body parameter. Not currently populated; rely on `message`. |
| `doc_url`    | Deep link to the matching section on this page.                                                      |
| `request_id` | Same value as the `X-Request-Id` response header.                                                    |

Documented exceptions to the envelope: transcript-correction conflict responses use purpose-built bodies (`409 { error, reason, currentRevision }`, `412 { error, expectedSeq }`; see [Transcripts for coding agents](/transcripts-for-coding-agents#seq-and-the-queue-client-contract)); transcript unlock and submission payment failures return a bare `{ error, quote }` body so the refused price is machine-readable; and tier gates on delivery features (webhook/Slack on a plan without them) return a bare `403 { error, upgradeRequired: true, feature }` body. These are reflected as-is in the docs and spec.

## Request IDs

Every response, successful or not, carries an `X-Request-Id` header; the same value lives in `error.request_id` on failures. When contacting [support](/support), always include the request ID, the endpoint, and a timestamp. It's the fastest path to a fix.

## Status codes

| HTTP | `error.type`            | Cause                                                                                                             | Solution                                                               |
| ---- | ----------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| 400  | `invalid_request_error` | Malformed params or body (`invalid_query`, `invalid_body`, `appearances_person_only`, `invalid_feedback_request`) | Fix the request; `error.message` carries the validator output          |
| 401  | `authentication_error`  | Missing/bad key (`invalid_api_key`)                                                                               | Mint or fix the key; check the header form                             |
| 402  | `quota_exceeded`        | Monthly rows exhausted, on-demand off                                                                             | Enable on-demand in Settings → Billing or wait for the cycle           |
| 403  | `permission_error`      | Plan or scope gate (`api_not_enabled`, `insufficient_scope`, `recommendations_not_enabled`)                       | Upgrade the plan or re-scope the key                                   |
| 404  | `not_found`             | Unresolvable resource (`entity_not_found`, `channel_not_found`, `alert_not_found`, `not_found`)                   | Verify the ID; resolve via search/lookup first                         |
| 409  | `conflict_error`        | `idempotency_conflict`                                                                                            | New logical operation, new `Idempotency-Key`                           |
| 429  | `rate_limit_error`      | `rate_limit_exceeded`                                                                                             | Honor `Retry-After`; see [Usage, limits & billing](/usage-and-billing) |
| 500  | `server_error`          | Unexpected server-side issue                                                                                      | Retry with backoff; report the `X-Request-Id` if it persists           |

## Error code reference

### `invalid_query` / `invalid_body`

The request failed schema validation. `error.message` contains the validator's output and `error.param` (where available) identifies the offending field. Almost always a client-side fix.

### `appearances_person_only`

You called an appearance surface or set `is_appearance=true` for a non-person entity. Only `person` entities have appearances; organizations, products, topics, and channels are mention-only. Use `/v1/mentions` or `/v1/entities/{id}/mentions` instead. See [Search](/search#the-entity-model).

### `invalid_api_key`

The key is missing, malformed, disabled, expired, revoked, or an internal (`arc_int_*`) key, which v1 rejects. Mint an `arc_sk_*` key in [Dashboard → API Keys](https://arcmira.com/dashboard?tab=api-keys).

### `api_not_enabled`

Your plan does not currently include API access. Upgrade your plan or contact [hi@arcmira.com](mailto:hi@arcmira.com).

### `insufficient_scope`

The key is valid but missing the scope required by the endpoint; the message names it (`monitors:write`, `trackers:write`, `recommendations:read`). For commercial scopes the key also needs a **Pro+** plan; if it isn't, you'll see [`recommendations_not_enabled`](#recommendations_not_enabled) first. See [Authentication & scopes](/authentication).

### `recommendations_not_enabled`

You called a [commercial intelligence](/commercial-intelligence) surface (`/v1/recommendations`, `/v1/channels/{id}/sponsors`, `/v1/mentions?details=full`, commercial Community Review, or a `recommendations_summary` block) on a tier below Pro+. The tier gate (`recommendations_api_enabled` on `/v1/me`) is independent of scopes: even a key with `recommendations:read` gets this on a lower plan.

Fix: upgrade to Pro+ (`pro_plus`, `ultra`, `teams`, `enterprise`) or use the non-commercial alternative (e.g. `/v1/mentions` without `details=full`).

### `invalid_feedback_request`

`POST /v1/feedback` rejected the submission shape. Common causes: missing `type`, empty `query`, malformed `?query=` URL-encoded JSON, or a malformed `com_*` / `ent_*` ID in a correction. See [Community Review](/feedback) for the request shape.

### `quota_exceeded`

Your monthly row pool is exhausted and on-demand spending is disabled. Enable on-demand in **Settings → Billing** or wait for the next billing period. A different 402 exists on transcript unlock/submission when the pool cannot cover that specific purchase: it returns a bare `{ error, quote }` body (no envelope) so the refused price is machine-readable.

### `entity_not_found`

The entity ID or name didn't resolve. Try a different `type`, a broader name, or `/v1/entities/search` first.

### `monitor_not_found` / `tracker_not_found`

The monitor or tracker ID doesn't exist or doesn't belong to your account. List your resources with `GET /v1/monitors` / `GET /v1/trackers` and re-check the ID.

### `invalid_video_id`

`video_id` must be an 11-character YouTube video ID (the `dQw4w9WgXcQ` form), not a URL or a slug. Extract it from the watch URL before calling transcript or correction endpoints.

### `not_found`

The path doesn't match any v1 endpoint. Check the method and path against the [API reference](/api-reference/meta/health-check).

### `channel_not_found`

The channel ID passed to `/v1/channels/{id}/sponsors` has no media in the index. Verify the YouTube channel ID (the `UC...` form, not a slug).

### `alert_not_found`

A `monitor_alert` feedback submission referenced an alert row that doesn't exist or doesn't belong to your account. Re-pull `GET /v1/monitors/{id}/alerts` and use the row `id` verbatim.

### `feedback_not_found`

The `feedback_id` passed to `GET /v1/feedback/{feedback_id}` doesn't exist or wasn't submitted by your account. Unknown and foreign IDs are indistinguishable by design.

### `webhook_not_configured`

You called `POST /v1/monitors/{id}/webhook-secret/rotate` on a monitor with no webhook configured. Enable one first with `PATCH { "notifyWebhook": true, "webhookUrl": "..." }`, which returns the secret once.

### `idempotency_conflict`

You reused an `Idempotency-Key` with a different request body. Mint a new key for each new logical operation. See [Requests & conventions](/requests#idempotency).

### `rate_limit_exceeded`

You exceeded the per-minute throttle. Honor `Retry-After`. See [Usage, limits & billing](/usage-and-billing#rate-limits).

### `server_error`

An unexpected server-side issue. Retry with exponential backoff. If it persists, send us the `X-Request-Id`.
