REST API
The REST API is the way in for your own code. MCP is the way in for an agent: see Connect an agent. Both reach the same tools, balance and calls.
Every request and response is JSON. The base URL is https://api.voxoria.ai, and every path starts with the version, /v1.
Authentication
Send an API key as a bearer token in the Authorization header. Create keys in the console: see Account and API key. The REST API takes API keys only, not OAuth tokens.
A missing, wrong or revoked key answers 401 with INVALID_AUTH_TOKEN. GET /v1/tools and GET /v1/tools/{tool} also answer without a key.
A key's scope is All endpoints or Read only. A read-only key is refused with 403 and NOT_ALLOWED by the two endpoints that change something: calling a tool and labelling a call. It can still quote a call.
A test key (vox_test_...) cannot call tools yet: it answers 403 with TEST_KEY_NOT_ALLOWED. Use a live key (vox_live_...).
curl https://api.voxoria.ai/v1/ping \ -H "Authorization: Bearer $VOXORIA_API_KEY"Requests and responses
Send a body as JSON with Content-Type: application/json. Field names are snake_case.
Every field of a response is always present. A field marked nullable can be null. New fields may be added to a response, so ignore those you do not know.
Money is a decimal string in US dollars, such as "0.0214", never a float. Times are ISO 8601 in UTC.
The API calls a workspace an organization. They are the same thing.
Errors
A request that fails answers with an HTTP error status and a JSON body with detail and code. Branch on code, not on detail, which may change.
An invalid request adds errors, one per problem. A call that ran and failed adds call_id. Each endpoint's page lists the statuses it answers with. The call response has the fields of each error body.
Each code an endpoint can answer with, and the status it usually comes with.
| Code | Status | Meaning |
|---|---|---|
INVALID_AUTH_TOKEN | 401 | The API key is missing, wrong or revoked. |
INSUFFICIENT_BALANCE | 402 | Your available balance cannot cover the call. |
NOT_ALLOWED | 403 | The key's scope does not permit the endpoint, or the account needs a subscription. |
TEST_KEY_NOT_ALLOWED | 403 | Test keys cannot call tools yet. Use a live key. |
MODEL_NOT_FOUND | 404 | The tool or call does not exist. |
TOOL_NOT_CALLABLE | 409 | The tool cannot be called yet. |
VALIDATION | 422 | The request is not valid. errors lists each problem. |
NO_ELIGIBLE_PROVIDER | 422 | No provider can serve the request as sent. |
IDEMPOTENCY_KEY_REUSED | 422 | The idempotency key was already used with a different request. |
RATE_LIMITED | 429 | Too many requests. Retry after Retry-After seconds. |
PROVIDER_RATE_LIMITED | 429 | Every provider that could serve the call refused it for its own rate limit. Not charged. |
UNKNOWN | 500 | Something went wrong on our side. |
TOOL_CALL_FAILED | 502 | No provider served the call. Not charged, unless its provider billed the failure. |
TOOL_UNAVAILABLE | 503 | The tool or the call cannot be served right now. Not charged. Retry shortly. |
CALL_RESULT_DEFERRED | 503 | The call ran, but its result could not be returned now. Read it with GET /v1/calls/{call_id}. |
TOOL_CALL_TIMED_OUT | 504 | The call ran out of time. Not charged. |
Pagination
GET /v1/calls returns one page at a time, newest first. Set the page size with limit: 50 by default, 1 to 100.
A page has items, has_more and next_cursor. Pass next_cursor as cursor to read the next page, with the same filters. Stop when has_more is false. A cursor is opaque: do not build or change one.
GET /v1/tools returns the whole list in one response.
Rate limits
With a key: 600 requests a minute per API key, REST and MCP together. Without a key: 60 requests a minute per IP address.
Over the limit, a request answers 429 with RATE_LIMITED and a Retry-After header: the seconds until the limit resets.
Providers have rate limits of their own. When every provider that could serve a call refuses it for one, the call fails with 429 and PROVIDER_RATE_LIMITED. It is not charged. Retry after the Retry-After header's seconds.
Retries
Reads are safe to retry. A call is not: two requests make two calls, and two charges. Send an Idempotency-Key header to retry a call safely. See Call a tool and Retry a call safely.
Versioning
The version is in the path: /v1. Each tool's input and output has a contract version of its own, listed on its page under Tools.
Endpoints
Every endpoint of the REST API.