# Referință API (/ro/docs/api)

Cum citești referința — URL-uri de bază, autentificare, plicul de eroare, convențiile SSE și unde se anunță schimbările.

Referința e generată din documente OpenAPI 3.1 scrise de mână, care oglindesc codul rută cu rută. Un test de paritate din repo pică ori de câte ori o rută publică există fără documentație sau o rută documentată nu mai există, așa că ce citești aici e ce înregistrează serverele.

## Trei servicii, trei URL-uri de bază [#trei-servicii-trei-url-uri-de-bază]

| Serviciu | URL de bază | Referință | Autentificare |
| --- | --- | --- | --- |
| Gateway (inferență + platformă) | `https://ai.codai.ro` | [Gateway](./gateway/index.mdx) | `Authorization: Bearer codai_…` |
| Resolve (fix-uri verificate) | `https://resolve.codai.ro` | [Resolve](./resolve.mdx) | aceeași cheie `codai_` |
| Auth (OpenID Provider) | `https://auth.codai.ro` | [Auth](./auth.mdx) | OAuth 2.1 / OIDC |

Panourile „încearcă” din fiecare operație trimit cereri reale din browserul tău. Lipește o cheie cu care ești dispus să cheltuiești câțiva cenți; panourile nu o stochează niciodată.

## Autentificare [#autentificare]

Fiecare apel către gateway și Resolve poartă o cheie API codai în header-ul bearer. Cheile încep cu `codai_`, sunt afișate o singură dată în [hub](https://hub.codai.ro) și pot fi revocate de acolo. `/v1/messages` acceptă și header-ul `x-api-key` în stil Anthropic. Tokenurile efemere de la `POST /v1/tokens` sunt acceptate doar de WebSocket-ul realtime — o cheie brută în query string e refuzată.

Aplicațiile care autentifică utilizatori obțin o cheie cu scope-uri prin [fluxul connect](../auth/connect-flow.mdx) OIDC, în loc să ceară una.

## Plicul de eroare [#plicul-de-eroare]

Gateway-ul răspunde la orice eșec cu o singură formă JSON:

```json
{
  "error": {
    "message": "Invalid request body",
    "type": "invalid_request_error",
    "code": "bad_request",
    "details": { "fieldErrors": { "messages": ["Required"] } }
  }
}
```

| Status | `code` | Când |
| --- | --- | --- |
| 400 | `bad_request` | Body-ul sau query-ul a picat validarea — `details` conține erorile pe câmpuri |
| 401 | `invalid_api_key` | Cheie lipsă, revocată sau pusă pe pauză |
| 402 | `subscription_inactive` | Abonamentul din spatele cheii e inactiv |
| 403 | `forbidden` | A picat verificarea de allow-list de modele, rol sau proprietate |
| 404 | `not_found` | Resursa nu există sau aparține altcuiva |
| 409 | `lease_held`, `seq_conflict`, `task_not_confirmable`, `host_offline` | Conflicte de concurență optimistă pe sesiuni, sarcini și host-uri |
| 413 | `payload_too_large` | Body-ul cererii depășește 12 MB |
| 429 | `rate_limit_exceeded`, `quota_exceeded` | Limită de rată / plafon de cheltuieli sau cotă de sarcini — citește `Retry-After` |
| 502 | `upstream_error` | Toate lane-urile upstream au picat după failover |
| 503 | `search_unavailable` | Serviciul de căutare din spatele `/v1/tools/search` e căzut |
| 500 | `internal_error` | Defect neașteptat; ne-a fost deja raportat |

Resolve și Auth sunt servicii diferite, cu forme proprii, mai simple: Resolve returnează `{ "error": "<string>" }`, Auth returnează perechea OAuth `{ "error", "error_description" }`. Fiecare pagină de referință o documentează pe a sa.

## Convenții de streaming [#convenții-de-streaming]

- Endpoint-urile SSE răspund cu `text/event-stream`. Chat Completions, Messages și Responses folosesc framing-ul formatului lor wire; chunk-ul de usage pe un stream Chat Completions e emis mereu, indiferent ce spune `stream_options`.
- Stream-urile proprii codai (agenți, sesiuni, host-uri) folosesc frame-uri `event:` numite, documentate la fiecare operație, plus comentarii `: ping` ca heartbeat acolo unde e notat.
- Niciun stream nu emite linii `id:` și `Last-Event-ID` nu e citit. Reiei cu cursorul oferit de endpoint (`after` la sesiuni) sau accepți un replay complet (agenți).
- Header-ele de cost pe un stream arată `x-codai-cost-estimate: pending`; costul măsurat ajunge mai târziu în `GET /v1/receipt`.

## Versionare și schimbări [#versionare-și-schimbări]

Gateway-ul nu e versionat dincolo de prefixul `/v1`. Schimbările aditive (câmpuri noi, header-e noi, endpoint-uri noi) se livrează fără anunț; orice elimină sau redenumește e anunțat întâi în [changelog](https://codai.ro/changelog). Numele câmpurilor sunt returnate exact cum le trimite codul — câteva obiecte amestecă `camelCase` și `snake_case`, iar referința reflectă asta în loc s-o ascundă.
