> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.nyra-labs.com/authentication/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nyra-labs.com/_mcp/server. # Authentication Every request carries an API key in the `Authorization` header: ``` Authorization: Bearer nl_live_... ``` Keys are issued per organization from the [dashboard](https://platform.nyra-labs.com/api-keys). ## Key format A key is a prefix followed by 32 bytes of randomness encoded in base62 — 51 characters in total: ``` nl_live_YxQFoF6p2xKvStMzWhYhwPMNSlEnWTwzYL83OJCbyTo └──────┘└─────────────────────────────────────────┘ prefix 43 base62 characters (32 random bytes) ``` Every request made with a key is billed against the organization's wallet. Only the SHA-256 hash of a key is stored, so the plaintext is shown **once** at creation and cannot be recovered afterwards. Lose it and you mint a new one. The dashboard and the API only ever show the first 12 characters (`nl_live_YxQF`), which is enough to tell your keys apart and useless on its own. A key carries its organization, its scopes, an optional expiry, its own rate limit, and a last-used timestamp. ## Errors Authentication failures return the standard error envelope with `type: "authentication_error"` and HTTP `401`. No key at all: ```json { "error": { "message": "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer nl_live_...). You can find your API key at https://platform.nyra-labs.com/api-keys.", "type": "authentication_error", "param": null, "code": "missing_api_key" } } ``` A key that is unknown, malformed, revoked or expired. The key is echoed back redacted to its first 8 and last 4 characters, so you can tell *which* key failed without the error log becoming a place credentials leak: ```json { "error": { "message": "Incorrect API key provided: nl_live_…byTo. You can find your API key at https://platform.nyra-labs.com/api-keys.", "type": "authentication_error", "param": null, "code": "invalid_api_key" } } ``` All four causes return the same message. Distinguishing "unknown" from "revoked" would confirm to whoever holds a leaked key that it used to be real. ## Scopes A key can be narrowed to a subset of the API. The available scopes are: | Scope | Grants | | ---------------------- | ------------------------------------------ | | `transcriptions:write` | `POST /v1/audio/transcriptions` | | `models:read` | `GET /v1/models`, `GET /v1/models/{model}` | A key created **without** scopes is unrestricted — that is the default. Narrowing is opt-in, and it is worth doing for any key that leaves your own infrastructure: a key that only transcribes cannot enumerate the catalogue, and a key that only reads the catalogue cannot spend money. Calling an endpoint your key lacks the scope for returns HTTP `403`: ```json { "error": { "message": "You have insufficient permissions for this operation. Your API key is missing the 'transcriptions:write' scope. Grant it at https://platform.nyra-labs.com/api-keys, or use a key with no scope restrictions.", "type": "permission_error", "param": null, "code": "insufficient_scope" } } ``` ## Rate limits Limits are per key and reset on a rolling one-minute window. The default is 600 requests per minute; a lower or higher limit can be set on each key in the dashboard. Every `/v1` response carries: | Header | Meaning | | -------------------------------- | ---------------------------------------- | | `x-ratelimit-limit-requests` | Requests allowed in the window | | `x-ratelimit-remaining-requests` | Requests left in the current window | | `x-ratelimit-reset-requests` | Time until the window resets, e.g. `43s` | | `retry-after` | Seconds to wait. Sent on `429` only | Counters are shared across every API instance, so a limit is a limit no matter which server answers. Exceeding the limit returns HTTP `429`: ```json { "error": { "message": "Rate limit reached for requests. Please slow down or contact support to raise your limit.", "type": "rate_limit_error", "param": null, "code": "rate_limit_exceeded" } } ``` A request that arrives with no usable key is limited by client IP instead, at a deliberately low rate — it is on its way to a `401` regardless. > Bearer API keys, scoped to an organization.