API Overview & Authentication
Base URL
All API requests are made against the following base URL. Append the endpoint path to the base URL for each request.
https://api.runbios.aiThe Run BiOS console is available at https://platform.runbios.ai. The API gateway is a separate service that handles all programmatic access.
Authentication
api.runbios.ai serves two surfaces and they take different credential headers. Sending the wrong one is a 401, not a fallback.
| Surface | Header |
|---|---|
Platform API — /api/*: datasets, training, deployments, billing. Also what the SDKs and MCP server call. | X-API-Key: sk-bios-… |
Serverless inference — /v1/*: chat completions, messages, models. OpenAI- and Anthropic-compatible. | Authorization: Bearer bios-… |
The /v1 door does not read X-API-Key — with one exception: on /v1/messages and /v1/models it accepts x-api-key as well, because that is the credential header Anthropic’s own SDKs send. Everywhere else under /v1, use Bearer. GET /v1/models is public and needs no credential at all.
Platform API keys are scoped to one workspace and the API resolves the organization and workspace automatically, so no extra headers are needed:
X-API-Key: sk-bios-your_key_here
Content-Type: application/jsonAlternatively, JWT Bearer tokens are supported on the platform API (used by the web console). JWT auth requires additional X-Org-ID and X-Workspace-ID headers.
Error Response Format
Errors are JSON, and the envelope follows the surface you called. There are three, because the two inference dialects answer in their own vendor’s shape — an OpenAI or Anthropic SDK parses the errors it already knows.
Platform API — /api/*:
{
"error": {
"code": "BAD_REQUEST",
"message": "A human-readable description of what went wrong"
}
}code is a stable SCREAMING_SNAKE_CASE symbol — UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR, RATE_LIMITED, INSUFFICIENT_FUNDS — and is what you should branch on. Match the HTTP status too; never the message text.
Serverless inference, OpenAI dialect — /v1/chat/completions, /v1/models:
{
"error": {
"code": "invalid_request_error",
"message": "missing required field: model",
"type": "invalid_request_error"
}
}Serverless inference, Anthropic dialect — /v1/messages:
{
"type": "error",
"error": {
"type": "authentication_error",
"code": "invalid_request_error",
"message": "missing API key — set x-api-key: <your key> (or Authorization: Bearer <your key>)"
}
}On the inference surface the same condition is typed per dialect (a missing credential is invalid_request_error on the OpenAI door and authentication_error on the Anthropic one), so branch on the HTTP status and, where you need more, on the field your own SDK reads.
Rate Limits
Rate limits are enforced per API key, and on the inference surface additionally per workspace and model. Exceeding one returns 429 Too Many Requests with a Retry-After header.
A 429 also carries the ceiling, what is left, and when the window resets, under the name your client reads: RateLimit-Limit /-Remaining /-Reset everywhere, the x-ratelimit-* family on both inference doors, and anthropic-ratelimit-* on /v1/messages. These appear on the refusal; a successful response does not currently carry your remaining allowance, so treat the 429 plus Retry-After as the backoff signal rather than polling for headroom.
Common Status Codes
| Code | Meaning |
|---|---|
| 200 | OK: request succeeded |
| 201 | Created: resource created successfully |
| 400 | Bad Request: invalid input or validation error |
| 401 | Unauthorized: missing or expired token |
| 403 | Forbidden: insufficient permissions |
| 404 | Not Found: resource does not exist |
| 405 | Method Not Allowed: wrong HTTP verb for this path (the Allow header names the accepted ones) |
| 413 | Payload Too Large: request body over the 32 MiB ceiling |
| 422 | Validation Error: request body failed validation |
| 429 | Too Many Requests: rate limit exceeded |
| 500 | Internal Server Error: something went wrong on our end |
Run BiOS Documentation. Need help? Email contact@runbios.ai