2026-10-22
Praxis is the Agent Cloud Platform. The API is organized by service: agents, models, sandboxes, search, and automation, each under its own prefix. Requests and responses use JSON, streaming responses use SSE, and standard HTTP verbs and status codes apply. All prefixes share one address and one Key.
https://api.deepraxis.comUse the client libraries listed on each service's API page. Compatible APIs use official protocol SDKs. For local installation of the automation TypeScript SDK, see Automation API.
| Service | Prefix | API page |
|---|---|---|
| Agents | /agent | Agent API |
| Models | /model | Model API |
| Sandboxes | /sandbox | Sandbox API |
| Search | /search | Search API |
| Automation | /automation | Automation API |
Code already using OpenAI, Anthropic, Google, E2B, or Tavily doesn't need to be rewritten for Praxis: the platform offers compatible prefixes that match those vendors' official APIs — change the address and go.
| Vendor | Prefix | API page |
|---|---|---|
| OpenAI | /openai | OpenAI compatible |
| Anthropic | /anthropic | Anthropic compatible |
/google | Google compatible | |
| E2B | /e2b | E2B compatible |
| Tavily | /tavily | Tavily compatible |
All prefixes share the API Key created in the console, sent with each request in the Authorization header. See Authentication.
429, and a response header tells you when to retry. See Rate limits./meta prefix.curl https://api.deepraxis.com/model/v1/chat/completions \
-H "Authorization: Bearer $PRAXIS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "deepseek-flash", "messages": [{"role": "user", "content": "Hello"}]}'Every endpoint uses the same credential: an API Key created in the console, sent with each request in the Authorization header. There is no other authentication method and no per-endpoint rules.
Authorization: Bearer {key}| Part | Meaning | Example |
|---|---|---|
Bearer | Literal scheme | Bearer |
{key} | Your API Key, starting with sk-praxis- | sk-praxis-a1b2… |
One Key works across every prefix. Keys are created, rotated, and revoked at Console → API Keys; revocation takes effect immediately.
You don't assemble the header yourself — the official SDKs do it; we also accept the header names those SDKs send by default.
| SDK | What you set | Header actually sent |
|---|---|---|
| OpenAI SDK | apiKey | Authorization: Bearer … |
| Anthropic SDK | apiKey | X-API-Key: … |
| Google GenAI SDK | apiKey | x-goog-api-key: … |
| E2B SDK | apiKey | X-API-Key: … |
| Tavily SDK / HTTP | apiKey | Authorization: Bearer … |
curl https://api.deepraxis.com/model/v1/models \
-H "Authorization: Bearer $PRAXIS_API_KEY"A missing, invalid, or revoked Key returns 401, with a body in the format of that prefix (see Errors). Never retry a 401 — fix the Key and send again.
PRAXIS_API_KEY in the examples), not code.When something fails, the HTTP status code tells you the class of the failure; the body gives the specific cause in the format of that prefix; and every error response also carries four x-praxis-problem-* headers plus one x-praxis-recovery-action, so retry logic only needs the headers, whatever the body looks like.
| Status | Meaning | What to do |
|---|---|---|
400 | Invalid request fields or format | Correct the parameters; do not retry unchanged |
401 | Missing or invalid credentials | Check your API key |
402 | Insufficient balance or paid allowance | Add funds or contact your account administrator |
403 | Access denied | Check key permissions and resource ownership; contact support if needed |
404 | Resource, model or route not found | Check the ID, model name and path |
408 | Request timed out | Check connectivity before retrying; verify whether writes completed first |
409 | Resource state or concurrent update conflict | Read the current state and adjust the request |
413 | Payload or file too large | Reduce the payload or use a URL input supported by the endpoint |
422 | Request content cannot be processed | Correct parameters or input using the error details |
429 | Rate, concurrency or model quota exceeded | Honor retry-after; let in-flight requests finish when concurrency is full |
500 | Internal platform error | Retry later; contact support with X-Request-Id if it persists |
501 | Capability not implemented | Use a supported endpoint; do not retry |
502 | Upstream call failed or returned an invalid response | Back off and retry; switch models or contact support if it persists |
503 | Service or eligible route temporarily unavailable | Back off and retry, or select another model |
504 | Upstream response timed out | Back off and retry; check write results first to avoid duplicate creation |
These are common machine-readable codes, not an exhaustive enum for every endpoint. Compatible error bodies may use protocol-specific code/type values. For cross-protocol handling, read x-praxis-problem-code, which can differ from the body code. Codes are case-sensitive.
| code | When it occurs and what to do |
|---|---|
AUTHENTICATION_ERROR | The key is missing or invalid; check or replace your credentials. |
VALIDATION_ERROR | A parameter violates a format, type or range requirement; correct it using the details. |
INPUT_NOT_REPRESENTABLE | The selected model or protocol cannot represent an input option; remove the option or switch models. |
NOT_FOUND | The resource is absent or not visible to this account; check the ID and account. |
MODEL_NOT_FOUND | The model is absent or not visible; select an available name from the model list. |
MODEL_PROTOCOL_NOT_OFFERED | The model does not offer this protocol; use a supported endpoint or another model. |
MODEL_PROTOCOL_LINE_UNAVAILABLE | Qualified routes for the protocol are unavailable; back off and retry or switch models. |
GENERATION_NOT_FOUND | The generation is absent or belongs to another account; check the generation ID from the response headers and the key. |
RATE_LIMITED | A rate or concurrency limit was exceeded; honor retry-after and reduce rate or concurrency. |
UPSTREAM_ERROR | The upstream call failed or returned an invalid response; retry with backoff when retryable, then switch models or contact support if it persists. |
PROVIDER_SELECTION_NOT_ALLOWED | Provider order/only was supplied without BYOK; remove provider selection or provide your own upstream key. |
not_implemented | The endpoint or capability is not implemented; use a supported capability instead of retrying. |
model_protocol_not_offered | HTTP 404: the model does not declare the requested protocol. Check supported_apis in GET /model/v1/models and use the corresponding endpoint. For Google models, use /google/v1beta/models/{model}:generateContent with a Google request body; changing only the prefix is insufficient. |
provider_unavailable | HTTP 502: all available routes for this request failed. Retry with backoff; if failures persist, switch models and contact support with X-Request-Id. |
thinking_disable_unsupported | HTTP 400: thinking cannot be disabled, for example reasoning_effort="none" on glm-5.3. Omit the disabling setting or choose a supported effort level; switch models if you need thinking disabled. |
insufficient_quota / INSUFFICIENT_BALANCE | HTTP 402: insufficient balance; body or header codes vary by endpoint. Add funds or contact your account administrator before retrying; avoid immediate retry loops. |
validation_error (response_format) | HTTP 400, for example: Model "deepseek-flash" does not support json_schema on this API. Switch to a model supporting json_schema on this endpoint. If valid JSON alone is sufficient, use json_object; it does not enforce a schema. |
validation_error (named parameter) | HTTP 400: with provider.require_parameters=true, the model may reject a requested parameter. For example, param: "logprobs" accompanies does not support the requested logprobs value. Adjust the named parameter or switch models. Disabling the check does not prove the parameter takes effect. |
The body format follows the first segment of the address, same as success responses — your SDK needs no special handling for errors.
Vendor prefixes (/openai /anthropic /google /e2b /tavily): identical to that vendor's official API error body.
// /openai
{ "error": { "code": 401, "message": "Invalid API key." } }// /anthropic
{ "type": "error", "error": { "type": "authentication_error", "message": "Invalid API key." } }Praxis prefixes (/agent /model /sandbox /search /meta): standard Problem Details (RFC 9457), Content-Type: application/problem+json.
{
"type": "https://deepraxis.ai/problems/authentication_error",
"title": "authentication_error",
"status": 401,
"detail": "Invalid API key.",
"instance": "problem_eqfnxu",
"code": "AUTHENTICATION_ERROR",
"retryable": false
}| Field | Meaning |
|---|---|
type | URL of the error type, stable, safe to branch on |
title / detail | Human-readable summary and specific cause |
status | Same as the HTTP status code |
instance | ID of this error, attach it when contacting support |
code | Machine-readable error code |
retryable | Whether retrying verbatim might succeed |
The five common headers are independent of body format; the sixth, scope, applies to rate-limit errors:
| Header | Meaning | Example |
|---|---|---|
x-praxis-problem-code | Cross-protocol classification; may differ from the body's code | AUTHENTICATION_ERROR |
x-praxis-problem-kind | Broad class — what broke | authentication_failure |
x-praxis-problem-origin | Who owns it — who can fix it: user (your request or credential), platform (us), upstream_provider (the vendor), etc. | unknown |
x-praxis-problem-retryable | Whether retrying verbatim might succeed | false |
x-praxis-problem-scope | Rate-limit layer, when applicable: platform or model | platform |
x-praxis-recovery-action | Suggested action | relogin |
retryable is true (or status 429 502 503): retry with exponential backoff; for 429 honor retry-after first.Praxis rate limiting has two layers: the platform layer caps requests per second and concurrent requests per Key; the model layer caps requests per minute (RPM) and tokens per minute (TPM) per model. Every response — success or 429 — carries three x-ratelimit-* headers stating your current allowance and when it resets, so you never have to guess or spend a request to check.
| Layer | Counted by | Capped | When exceeded |
|---|---|---|---|
| Platform | Your Key (source IP when no credential is sent) | Requests per second, concurrent requests | 429 + retry-after; wait and retry |
| Model | Model × tenant | Requests per minute (RPM), tokens per minute (TPM), monthly budget | 429, see the model layer below |
Both layers return the same three rate limit headers; which layer tripped is stated in the error body (Errors).
By default, each API key allows 5 requests per second and 4 concurrent in-flight requests. Streams occupy a concurrency slot until they finish. Exceeding either limit returns 429 with ratelimit-limit, ratelimit-remaining, ratelimit-reset and retry-after; when concurrency is full, let an existing request finish.
Configured limits may differ; use the actual response headers and concurrency error details.
x-ratelimit-limit-requests: 5
x-ratelimit-remaining-requests: 4
x-ratelimit-reset-requests: 850ms| Header | Meaning |
|---|---|
x-ratelimit-limit-requests | This credential's requests-per-second ceiling |
x-ratelimit-remaining-requests | Requests still available in this second |
x-ratelimit-reset-requests | Time until the allowance resets: 850ms under a second, 1s or more above it |
The same three numbers are also available under the IETF names RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset (whole seconds). The default is 5 requests/second and 4 in flight; response headers reflect configured request-rate overrides.
The (N+1)th request within one second — N being the Key's per-second ceiling — is answered 429 with a retry-after header (whole seconds, usually 1). Rejected requests do not consume the allowance: x-ratelimit-remaining-requests stays 0, and the window simply resets.
When the number of in-flight requests — including unfinished streaming responses, which hold their slot until the stream ends — exceeds the Key's concurrency ceiling, extra requests get 429 with retry-after: 1. Resetting the per-second window does not free a concurrency slot: an in-flight request must finish first. Which limit tripped is spelled out in the error message ("Concurrent request limit …" / "Requests per second limit …").
The error body follows the first path segment (see Errors). Native endpoints such as /model/v1/chat/completions return Problem Details:
{
"type": "https://deepraxis.ai/problems/rate_limit",
"title": "rate_limited",
"status": 429,
"detail": "Requests per second limit of 5 exceeded for this credential. Retry after the listed wait.",
"instance": "problem_eqfnxu",
"kind": "rate_limit",
"scope": "platform",
"retryable": true
}scope: "platform" means the platform layer triggered it. Vendor-prefixed endpoints speak that vendor's own error format — for the OpenAI-compatible endpoints:
{ "error": { "code": 429, "type": "rate_limit_error", "message": "Requests per second limit of 5 exceeded for this credential. Retry after the listed wait." } }Public endpoints (such as GET /model/v1/models) can be called without a Key; those are counted per source IP against a smaller anonymous allowance, with the same response headers. Sending a Key switches accounting to the Key, regardless of IP.
GET /meta/v1/health is never rate limited — point uptime monitors at it freely.
The model layer counts per model × tenant × minute, not per API Key:
0 means unlimited.429 with type rate_limit_error, Retry-After: 60, and problem.details.rateLimit carrying the current value and the cap.429 is returned.Models also carry a monthly budget based on cumulative revenue for the month; exceeding it returns 429 with type budget_error (QUOTA_EXHAUSTED) and no Retry-After — waiting does not help; the model's budget must be raised.
For status codes and error bodies see Errors; for account quotas see Quotas & rate limits.
The version is part of the address, immediately after the first segment; each prefix is versioned independently — there is no site-wide version number.
https://api.deepraxis.com/{protocol}/{version}/…| Prefix | Version segment | Decided by |
|---|---|---|
/openai /anthropic | v1 | Follows the vendor |
/google | v1beta | Follows the vendor |
/e2b /tavily | none | Follows the vendor |
/agent /model /sandbox /search /meta | v1 | Praxis |
Under vendor prefixes, version-related headers (such as Anthropic's anthropic-version) are passed through to the vendor as-is, behaving exactly like the official API.
Removing fields, changing a field's type or meaning, changing defaults, tightening validation, changing what an error code means. Adding fields, adding endpoints, and loosening validation are not breaking.
/model/v2/…); the old version keeps working.When an old version or endpoint is deprecated:
Deprecation (RFC 9745, when it was deprecated) and Sunset (RFC 8594, when it goes away), plus a Link header pointing to migration notes;404.Deprecation: @1767225600
Sunset: Sat, 04 Apr 2026 00:00:00 GMT
Link: </docs/changelog>; rel="deprecation"