Authentication Flow
Every /v1 request (except health) passes through a fixed middleware pipeline: API-key authentication, request logging, then rate limiting.
The Bearer key
Send your key in the Authorization header on every request:
Authorization: Bearer carrier_sk_live_xxxxxxxxxxxxThe API accepts secret keys (carrier_sk_…) and publishable keys (carrier_pk_…). Protected endpoints (chat, sessions, files, search, usage) require a secret key — see Authentication.
The request pipeline
Request → GET /v1/health ─────────────────────────► (public, no key)
Request → /v1/* (everything else)
│
▼
authenticateApiKey validate Bearer key → attach scope, or 401
│
▼
requestLogger record the request, stamp X-Request-Id
│
▼
rateLimiter enforce the key's daily limit, or 429
│
▼
route handler chat / sessions / files / …1. Authentication
authenticateApiKey parses the Bearer token, validates the key, and attaches the resolved scope to the request:
| Field | Type | Description |
|---|---|---|
| req.apiKey | object | id, name, type, workspaceId, projectId, userId |
| req.workspace | object | The key's workspace record |
| req.project | object | The key's project record |
It also updates the key's last-used timestamp. A missing, malformed, or invalid key never reaches your route — it is rejected with 401.
2. Request logging
requestLogger writes one row per request to developer_request_logs — capturing tokens, estimated cost, model, Carrier mode, and session id — and stamps an X-Request-Id response header. Writes are best-effort, so a logging hiccup never blocks your request. These rows power the dashboard Logs and Usage views.
3. Rate limiting
rateLimiter enforces a per-key daily limit based on the key's tier. It counts the day's logged requests and sets standard headers:
| Field | Type | Description |
|---|---|---|
| X-RateLimit-Limit | header | Requests allowed per day for the key's tier (or "unlimited") |
| X-RateLimit-Remaining | header | Requests left in the current window |
| X-RateLimit-Reset | header | Unix time when the window resets (next UTC midnight) |
Exceeding the limit returns 429 TOO_MANY_REQUESTS with the reset time in the message. The limiter is fail-open: if it errors internally, the request is allowed through rather than blocked.
Errors this flow can return
| Code | HTTP | When it occurs |
|---|---|---|
| MISSING_API_KEY | 401 | No Authorization header, or an empty token. |
| INVALID_AUTH_HEADER | 401 | Header is not in the form 'Bearer <api-key>'. |
| INVALID_API_KEY | 401 | Key not found, revoked, disabled, or the wrong type for the endpoint. |
| TOO_MANY_REQUESTS | 429 | The key's daily rate limit has been reached. |
401.{ success, data?, error? }. Base URL: https://api.carrieros.ai/v1. Full list in Error Codes and Rate Limits.