> ## 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.

# Usage, limits & billing

> How rows, monthly quotas, on-demand spend, and per-minute rate limits work across the API.

Arcmira bills premium usage by **rows**, not by API calls. Rows are the unit of indexed content surfaced to your account: mention and appearance rows, related-entity rows, commercial rows, transcript blocks.

**API and web usage share the same row pool.** A row counted for a web request is not counted again via the API. There is no separate API tier; heavy automation uses rows faster than browsing.

## What counts as a row

* Mention / appearance rows returned in a list: one row each. The first 5 rows of each distinct pull are free, and repeating the exact same request within 7 days is not re-billed.
* Related-entity rows on aggregated views: one row each, same 5-row allowance.
* Commercial rows (`/v1/recommendations`, `/v1/channels/{id}/sponsors`, `details=full` enrichment items): **10 rows each**, because the commercial pipeline is more expensive to run and curate. No free allowance.
* Transcripts: **75 rows per 15-minute block** of video, minimum one block, unlock permanent per account. See [Transcripts](/transcripts#pricing).
* Free: `/v1/me`, `/v1/health`, `/v1/openapi.json`, search, lookup, discovery search (including its `recommendations_summary`), `recommendations_summary` aggregate blocks, teasers, and all [Community Review](/feedback) submissions and corrections.

Practical consequences: a 40-sponsor list costs 400 rows, ten times a 40-mention page; `details=full` charges the mention row plus 10 rows per attached commercial item, so omit it when you don't need the overlay; searches are free but the rows you then fetch are not.

## Checking usage

```bash theme={null}
curl https://api.arcmira.com/v1/me \
  -H "Authorization: Bearer $ARCMIRA_API_KEY"
```

```json theme={null}
{
  "user_id": "usr_...",
  "tier": "pro_plus",
  "scopes": ["read", "recommendations:read"],
  "rate_limit": 240,
  "recommendations_api_enabled": true,
  "usage": {
    "rows_used": 1234,
    "rows_remaining": 98766,
    "monthly_rows": 100000,
    "current_spend_cents": 0
  }
}
```

`current_spend_cents` reflects on-demand spend in the current period; it stays `0` until you exceed the allotment with on-demand enabled. `/v1/me` is free: check it before large pulls.

## Exceeding your monthly allotment

| Condition                                   | Outcome                                                                                  |
| ------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Allotment exhausted, on-demand **enabled**  | Requests keep serving; each row over the allotment bills on demand, up to your spend cap |
| Allotment exhausted, on-demand **disabled** | `402 quota_exceeded` until the next billing cycle                                        |

Toggle on-demand usage and set a hard spend cap in **Settings → Billing**.

## Rate limits

Separate from rows: every key is throttled per minute over a fixed 60-second window (the counter resets on the minute boundary).

| Plan tier               | Requests per minute |
| ----------------------- | ------------------- |
| Free                    | 60                  |
| Paid (Pro, Pro+, Ultra) | 240                 |
| Teams / Enterprise      | 600                 |

Each key has its own bucket; mint separate keys per agent, environment, or job from [Dashboard → API Keys](https://arcmira.com/dashboard?tab=api-keys). Per-key overrides are common for high-throughput integrations: ask via [support](/support).

Every authenticated response (including errors past the key check) carries the bucket state:

| Header                | Description                                   |
| --------------------- | --------------------------------------------- |
| `RateLimit-Limit`     | Requests allowed per minute for this key      |
| `RateLimit-Remaining` | Requests left in the current window           |
| `RateLimit-Reset`     | Unix epoch (seconds) when the window resets   |
| `Retry-After`         | On 429 only: seconds to wait. Always honor it |

Throttle errors are `429 rate_limit_exceeded`; quota exhaustion is `402 quota_exceeded`. They are different problems with different fixes.

### Backoff pattern

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function callWithBackoff(url: string, init: RequestInit, maxRetries = 5) {
    for (let attempt = 0; ; attempt++) {
      const res = await fetch(url, init);
      if (res.status !== 429 || attempt >= maxRetries) return res;
      const retry = Number(res.headers.get('Retry-After') ?? '1');
      await new Promise((r) => setTimeout(r, retry * 1000));
    }
  }
  ```

  ```python Python theme={null}
  import asyncio, httpx

  async def call_with_backoff(client, method, url, max_retries=5, **kw):
      for attempt in range(max_retries + 1):
          r = await client.request(method, url, **kw)
          if r.status_code != 429 or attempt == max_retries:
              return r
          await asyncio.sleep(int(r.headers.get('retry-after', '1')))
  ```
</CodeGroup>

## Per-key tracking

Each key tracks lifetime `total_requests`, `total_rows_used`, and `total_cost_cents`, visible in [Dashboard → API Keys](https://arcmira.com/dashboard?tab=api-keys). Separate keys per integration make usage, rate limits, and Community Review reputation easy to attribute.

## Reducing costs

* Cache resolved `ent_*` IDs; don't re-run lookups.
* Pass `entity_id` instead of `entity_name` so no resolution rides inside metered requests.
* Scope pulls with `date_from` / `date_to`.
* Pull larger pages (up to `limit=100`) when iterating: rows cost the same, the request count drops.
* Quote transcripts before unlocking (`meta.quote` is free) and check `usage.rows_remaining` first.
