Skip to main content
Xenovia has two surfaces and they return errors in different shapes. Check which one you are calling.

Management API errors (cp.xenovia.io)

The management API returns FastAPI’s error shape — a JSON object with a detail field:
Validation errors (422) return detail as a list describing each invalid field:
Every response carries an X-Request-ID header. Send your own value to have it echoed and recorded in the audit log, or read the generated one and log it alongside failures.

Management API status codes

400 Bad Request

A domain rule was violated — for example activating an agent with no API key, or enabling a policy that is not attached to an active agent.

401 Unauthorized

Missing, malformed, expired, or revoked credential — or an agent xe_ key used against the management API.

403 Forbidden

Valid credential without access: a read-scoped key on a write, an org key on a human-only endpoint, or an org_id that does not match your key’s organization. (A resource that belongs to another organization returns 404, not 403.)

404 Not Found

The resource does not exist or belongs to another organization. Cross-organization reads return 404, not 403.

409 Conflict

A uniqueness constraint — a duplicate agent, provider, policy, or guardrail name, or the 20-key limit for organization keys.

422 Unprocessable

Schema validation failed, or a policy’s Rego did not compile. The detail list names the problem.
500 is an unexpected failure ({"detail": "Internal server error"}); include the X-Request-ID when contacting support. 503 means a dependency (key verification, or the config write path) is briefly unavailable — retry with backoff.

Runtime errors (runtime.xenovia.io)

The runtime returns the gateway error envelope:
is_bifrost_error is true when the error came from the upstream provider (a timeout, say), in which case extra_fields names the provider, model, and request type. OpenAI-compatible SDKs raise these as their usual typed errors (403 → PermissionDeniedError, 429 → RateLimitError, and so on). Errors raised before the request reaches the pipeline — body validation, authentication, and provider resolution (the 502 below) — use a shorter body, { "error": { "message": "..." } }. An invalid agent ID in the URL returns 404 with an empty body, and a completely unknown path returns 404 with the plain-text body Not Found. The SDK’s POST /v1/execute returns its own decision body; see the Python SDK.

Runtime status codes

Policy and guardrail blocks

A policy block, a guardrail block, and a policy escalation all return 403 with a generic message. A guardrail escalation does not block. The specific reason is recorded server-side and is never returned to the caller. The X-Xenovia-Trace-Id header on the response identifies the trace — look it up in the platform to see the policy or guardrail that fired.

Fallback providers

For an agent with fallback providers, the runtime returns 503 when every provider it tried failed with an error the agent fails over on:
The body also carries extra_fields. Match on error.code. If the last provider answered with an error the agent doesn’t fail over on, you get that error as you would without fallbacks: a 400 comes back as the provider’s error, and a 401, 402 or 403 (while Rejects the key or model is off) as a 502 with type upstream_credentials_exhausted. Responses to requests that ran through the fallback route, errors included, also carry X-Xenovia-Provider, X-Xenovia-Provider-Id, X-Xenovia-Model, X-Xenovia-Attempts and, when the request switched providers, X-Xenovia-Fallback-Reason. Log them with X-Xenovia-Trace-Id.

Rate limits

The management API does not rate-limit requests today. The runtime has no per-agent rate limit. Requests are metered against the organization’s request allowance; when it is exhausted the runtime returns 402. Upstream provider rate limits pass through as the provider’s error (for example 429, with is_bifrost_error: true), unless a fallback provider takes the request.

Retry guidance

Retries are not idempotent on the management API — no idempotency-key header is supported, so a retried POST can create a second resource (or return 409 where names are unique). Log X-Request-ID and X-Xenovia-Trace-Id for every non-2xx response.