Getting Started
Introduction
Everything that applies to every endpoint - authentication, conventions, errors, rate limits, and idempotency. Skim this once before wiring up the first call.
Base URL & versioning
There are two, because the platform runs in two places. Management endpoints live on the hosted control plane. The /v1/evaluate/* endpoints are served by the runtime you host, so their base URL is your own runtime address and your prompts never leave your boundary to be evaluated.
https://api.znyx.ai/v1 # control plane: policies, bundles, traces, evidence https://your-runtime.internal:8080/v1 # your runtime: /v1/evaluate/* - prompts stay here
The current version is v1. Breaking changes are cut as v2; minor additions (new fields, new endpoints) happen within v1 without a bump. Evaluation is only served by the runtime you host: there is no supported production endpoint on our side that will evaluate your application’s prompts. (The console’s policy playground does evaluate text you paste into it yourself, which is covered on the data-handling page.)
Self-hosted control planes use whatever hostname the operator assigns.
Authentication
Every request authenticates with a bearer token in the Authorization header. There are three token types, issued by the POST /v1/orgs/{org_id}/tokens/* family of endpoints:
- runtime - scoped to one project + environment. Used by the SDK to call
/v1/evaluate/*and fetch the latest bundle. Ship these to workloads. - ci - project-scoped, higher-privilege than runtime. Use from CI to publish / activate / promote bundles.
- admin - org-wide. Keep these tight - they can create other tokens, invite members, and edit billing.
curl -H 'Authorization: Bearer $ZNYX_TOKEN' \ https://api.znyx.ai/v1/bundles/latest
Tokens are shown once on creation - there is no retrieval endpoint. Store them in your secret manager the first time.
Conventions
- IDs are UUIDs (v4). Some tokens use a
gr_prefix. - Timestamps are ISO-8601 in UTC, e.g.
2026-04-22T12:00:00Z. - Request and response bodies are JSON (
application/json) unless the endpoint explicitly returns a binary stream (e.g. CSV / ZIP exports). - Policy scopes are identified by the 4-tuple
tenant_id / app_id / agent_id / env. In most flows,tenant_id=org_idandapp_id=project_id.
Errors
Errors return HTTP 4xx / 5xx with a consistent JSON envelope. The detail field is either a string (for simple errors) or a typed object with a machine-readable error code.
{
"detail": {
"error": "runtime_key_exists",
"message": "A runtime key for this project/environment already exists."
}
}| Status | When |
|---|---|
| 400 | Missing or malformed parameter. |
| 401 | Missing / invalid Authorization header. |
| 402 | Payment required (billing blocked). |
| 403 | Token lacks scope (e.g. runtime token trying to publish a bundle), or the plan quota is exhausted. |
| 404 | Resource not found or not in caller's org. |
| 409 | Conflict (e.g. token already exists, bundle version race). |
| 422 | Schema validation failed on the request body. |
| 423 | Account locked (too many failed logins). |
| 429 | Per-IP rate limit hit (retry with backoff). Plan quotas return 403, not this. |
| 5xx | Server-side bug or transient DB / upstream failure. Safe to retry. |
Rate limits
Two layers: a per-IP login limit (auth endpoints only) and per-organization quotas enforced per-call. Quotas scale with plan:
- Starter - 10,000 evaluations / month against the hosted console. A standalone self-hosted runtime is not metered at all.
- Growth - 250,000 evaluations / month. Contact us to raise the limit.
- Enterprise - unlimited, volume pricing.
A hit quota returns 403 Forbidden with an error of plan_limit_exceeded - not 429, which is reserved for the per-IP rate limiter, so the two are worth handling on separate branches. Billing-blocked organizations get 402 Payment Required. Use GET /v1/billing/summary to read the remaining allowance.
Pagination
List endpoints use limit + offset query parameters. Responses include a total count so you know when you've reached the end.
GET /v1/orgs/{org_id}/traces?limit=100&offset=200Default limit is 50 on most list endpoints, max 200. Check the per-endpoint reference for exceptions.
Idempotency
Read endpoints and evaluation calls are safe to retry. Write endpoints that return 2xx have already taken effect - retrying the same call may create duplicate resources (bundles, traces, annotations). If you need retry-safety on a mutation, wrap it with an application-side idempotency key before calling. An HTTP Idempotency-Key header is on the roadmap.