Quickstart

  • 1. Get a key. Sign in and create one on API Keys. It's shown once, so copy it then. Most new accounts get a small free credit; add more on Credits.
  • 2. Point your client at Router. Base URL https://router.enclave.ai/v1, header Authorization: Bearer <key>. Any OpenAI SDK works.
  • 3. Send a request. cyberouter/auto reads the prompt, picks the task, then picks the best model for it. The opencode and Pi tabs give a ready-made config for those coding agents.
curl https://router.enclave.ai/v1/chat/completions \
  -H "Authorization: Bearer $CYBEROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "cyberouter/auto",
    "messages": [{"role": "user", "content": "Review this diff for injection flaws before we merge."}]
  }'

OpenAI-compatible: point any SDK at https://router.enclave.ai/v1 and use Chat Completions or the stateless Responses API. cyberouter/auto picks the task and the best model; or pick one from Models.

Choosing a model

  • Auto. cyberouter/auto classifies the prompt into one of the tasks below, then routes like that task's alias. The receipt says which task it chose and how sure it was. A prompt with no task signal goes to triage.
  • Task aliases. Name the job and Router picks the model that scores highest on it among endpoints that are up and match your options.
  • A specific model. Send a model id from Models, like cyberouter/glm-5.3. Router only picks the host. Add "task": "vuln_discovery" to rank hosts by that task's score.
AliasFor
cyberouter/vuln-discoveryFind bugs in code, diffs, and configs.Ranking
cyberouter/exploit-devBuild and debug proofs of concept for authorized testing.Ranking
cyberouter/remediationWrite fixes, patches, and mitigations.Ranking
cyberouter/triageSort, summarize, and score findings. Small and fast.Ranking

Scores and their sources are on Rankings. GET /v1/models lists cyberouter/auto, the task aliases, and every model (add ?task= to filter), and GET /v1/models/{author}/{slug}/endpoints lists a model's hosts.

Provider options

Optional provider object on any request. Defaults are the strict choice. Settings holds account-wide defaults for sort, ZDR, fallbacks and blocked hosts, plus provider locks that pin a model to one host (like a preset). A request's own options win (only or order overrides a lock), except that a host blocked in Settings stays blocked. If a locked host can't serve a request, it fails rather than switching hosts.

FieldDefaultWhat it does
zdrtrueOnly use hosts with zero data retention. If none is up, the request fails instead of falling back to one that keeps data.
data_collectiondenySkip hosts that may train on or keep your data.
sorttask_perfRank by task score, or by price, latency or throughput. Task aliases and auto default to task score.
only / ignorenoneAllow or skip hosts by id: together, fireworks, baseten, abliteration.
ordernonePreferred host order.
allow_fallbacksfalseIf the chosen host fails, try another host serving the same model, revision and quantization. Router never swaps in a different model.
max_pricenoneSkip hosts above this USD price per million tokens. A number applies to input and output; {"prompt": 1, "completion": 4} sets each.
preferred_max_latencynoneSkip hosts whose typical time to first token is above this many milliseconds.
require_parameterstrueWhen the request has tools or a JSON response_format, only use hosts that support them.
{
  "model": "cyberouter/vuln-discovery",
  "messages": [{ "role": "user", "content": "Find the bug in this function." }],
  "provider": { "zdr": true, "only": ["together", "baseten"], "allow_fallbacks": true }
}

Routing receipt

  • On every response. Successful replies carry provider (who served it) and cyberouter (why). Routing, billing and host errors carry cyberouter too, so you can see what was filtered out.
  • Key fields. cyberouter.task and task_source (caller, auto or none), chosen (model, host, ZDR), criteria (sort, task score and its source, filters applied), attempts (each host tried and how it went), auto (classifier and confidence) and credits (cost and balance).
  • Look it up later. Every completion returns an X-Generation-Id header. GET /v1/generation?id= returns the receipt, cost and latency; GET /v1/generations lists recent ones with totals. The same data is on Logs.

Request parameters

  • Sampling. temperature (0–2), max_tokens / max_completion_tokens, top_p, top_k, min_p, top_a, frequency_penalty and presence_penalty (−2–2), repetition_penalty, seed, stop (up to 4), logit_bias, logprobs, top_logprobs (0–20), reasoning_effort. Out-of-range values get a 400 rather than being clamped.
  • Tools and JSON. tools, tool_choice and response_format only go to hosts that support them, so they're never silently dropped (unless you set require_parameters: false).
  • Streaming. "stream": true returns server-sent events. The last chunk carries usage with the cost.
  • Reasoning. Reasoning models return their thinking in message.reasoning (delta.reasoning when streaming).
  • Retries. Responses aren't cached and Idempotency-Key isn't supported, so each retry is a new, billed request.

Responses API

  • POST /v1/responses takes the same models, task and provider as chat, with input, instructions, function tools, text.format and streaming.
  • Stateless. Router keeps no prompts or outputs, so resend the whole conversation as input each turn. store: true, previous_response_id, conversation, background and stored prompts return 400 stateful_not_supported.

Errors

Errors use the OpenAI shape: {"error": {"message", "type", "code"}}.

StatusCodeMeaning
400invalid_request, invalid_jsonThe body is malformed or a parameter is out of range. The message says which.
400unknown_vendorA host id in only, ignore or order doesn't exist.
400context_length_exceededThe prompt plus max_tokens doesn't fit the model.
400task_conflict, auto_unclassifiedThe task doesn't match the alias, or auto got an empty prompt.
400stateful_not_supportedA Responses feature that needs stored state.
400unsupported_input, unsupported_content, unsupported_toolResponses input Router can't pass on, like file_id images or non-function tools.
401missing_api_key, invalid_api_keyNo key, or a revoked or wrong one.
402insufficient_creditsThe balance can't cover the request. Add credits or turn on auto-refill.
402budget_exceededYour own spending cap on Credits was hit.
403account_blockedThe account can't use the API.
404model_not_found, no_matching_endpointUnknown model, or no host is up that meets your options. Router won't quietly loosen them; check cyberouter.criteria.filters.
429rate_limit_exceededEvery host tried was rate limited. Retry after Retry-After seconds.
502provider_errorEvery host tried failed. cyberouter.attempts shows each one.

Credits and billing

  • Prepaid. 1 credit = $1. Buy on Credits ($5 minimum). Usage is charged at the host's price per token, plus a small markup, and cached prompt tokens cost less where the host discounts them.
  • What each request cost. usage.cost is what you paid, usage.vendor_cost is the host's price, and cyberouter.credits.balance_usd is what's left.
  • Holds. Router reserves enough for max_tokens before calling the model and refunds the rest after. Without max_tokens it caps the reply at what your balance can pay for and what fits in the context window.
  • Controls. On Credits: auto-refill from a saved card, a spending cap that resets monthly or never, and email alerts when spend passes an amount you set or the balance drops below your refill threshold. GET /v1/billing and GET /v1/billing/ledger return the same over the API.

Privacy

  • No prompts or outputs kept. Router stores routing metadata and token counts, never the content. Requests go only to US-hosted providers, and by default only to hosts that keep no data either.
  • More in the privacy policy and usage policy.