# Quickstart for AI agents

> The zero-human-intervention integration path — discover, provision, integrate, self-verify.


# Quickstart for AI agents

This page is the condensed integration contract for coding agents. Everything here is machine-verifiable; nothing requires a human until you need live (paid) processing.

## Discovery

| Artifact | URL |
|---|---|
| OpenAPI 3.1 spec | `https://api.primateintelligence.ai/v1/openapi.json` |
| llms.txt | `https://primateintelligence.ai/llms.txt` (alias: `/.well-known/llms.txt`) |
| llms-full.txt | `https://primateintelligence.ai/llms-full.txt` |
| This page as markdown | `https://primateintelligence.ai/docs/agents.md` |
| Error registry (machine-readable) | `GET https://api.primateintelligence.ai/v1/errors` |
| MCP server | `npx @primate-intelligence/mcp` (env: `PRIMATE_API_KEY`) |

Every docs page is also served as clean markdown — append `.md` to the path.

## Provision (zero-touch)

```bash
curl -s -X POST https://api.primateintelligence.ai/v1/sandbox
```

Returns a `pv_test_` key instantly: no email, no card, no human. Limits: IP-rate-limited, fixture-corpus only, deterministic canned results, 7-day expiry, can never spend credits. A pre-seeded fixture video is already in the account.

Live (`pv_live_`) keys require human signup + card — that is a **billing gate, not an integration gate**. Code written against a test key works unchanged with a live key.

## Credentials contract

- Env var: `PRIMATE_API_KEY`. Both SDKs and the MCP server read it.
- Header: `Authorization: Bearer $PRIMATE_API_KEY`. Keys never go in URLs.
- Keys are shown once at creation. Store securely.
- MCP tools never accept keys as arguments.

## The 3-call core loop

```
POST /v1/videos      {"url": "https://…/video.mp4"}          → {id: "video_…", status: "processing"}
POST /v1/analyses    {"video_id": "video_…", "prompt": "…"}  → {id: "an_…", status: "queued"}
GET  /v1/analyses/{id}                                        → {status: "completed", result: {…}}
```

Collapse the poll with `Prefer: wait=60` on the create (caps at 120s), or register a [webhook](/docs/guides/webhooks).

For file uploads instead of URLs: `POST /v1/videos {filename, content_type, size_bytes}` → PUT bytes to `upload.url` → `POST /v1/videos/{id}/complete`. Details: [uploading guide](/docs/guides/uploading).

## Result contract

`result.answer` ∈ `yes | no | indeterminate`. `result.confidence` ∈ [0,1]. `result.clips[]` carry `start_s`/`end_s`/`confidence`. Prompts that can't be assessed appear in `query.unassessable_components` — the API answers what it can and tells you what it couldn't.

## Error retry table

Every error response is `{"error": {code, message, status, param, docs_url, request_id}}`. The full registry with retry flags is at `GET /v1/errors`. Key rows:

| code | status | retry? |
|---|---|---|
| `rate_limit_exceeded` | 429 | yes — honor `Retry-After` |
| `concurrency_limit_exceeded` | 429 | yes — wait for an active analysis |
| `capacity_exhausted` | 503 | yes — honor `Retry-After` |
| `inference_unavailable` | 503 | yes — backoff |
| `internal_error` | 500 | yes — backoff |
| `insufficient_credits` | 402 | **no** — check `GET /v1/usage`, top up or enable auto-refill |
| `validation_failed` | 400 | no — fix `error.errors[]` |
| `invalid_api_key` | 401 | no — check the key + env var |
| `parse_failed` | 422 | yes — rephrase the prompt or send structured `query` |

Idempotency: send `Idempotency-Key: <uuid4>` on POST creates; replays return the stored response with `Idempotency-Replayed: true`. The SDKs do this automatically.

## Self-verification

```bash
curl -s https://api.primateintelligence.ai/v1/test-fixture
```

Returns a stable video URL + prompt + expected answer (`yes`, confidence ≥ 0.8). Assert against it in CI. On test keys, fixture analyses complete in seconds with deterministic results.

```bash
# assertion snippet
ANSWER=$(curl -s -X POST https://api.primateintelligence.ai/v1/analyses \
  -H "Authorization: Bearer $PRIMATE_API_KEY" -H "Content-Type: application/json" \
  -H "Prefer: wait=60" \
  -d "{\"video_id\": \"$FIXTURE_VIDEO_ID\", \"prompt\": \"Is there a person in this video?\"}" \
  | python3 -c "import json,sys; print(json.load(sys.stdin)['result']['answer'])")
[ "$ANSWER" = "yes" ] || { echo "integration broken"; exit 1; }
```

## SDKs

- TypeScript: `npm install @primate-intelligence/sdk` — `client.analyses.createAndWait(…)`
- Python: `pip install primate-intelligence` — `client.analyses.create_and_wait(…)`

Both auto-retry per the registry, auto-generate idempotency keys, and paginate with iterators.

## Rate limits

Per key, sliding window: reads 600/min, writes 300/min, `analyses.create` 60/min. Headers on every response: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`; 429s add `Retry-After`.
