ultrarouter docs
API reference

Call types

Programmatic call-type config (the objects the dashboard edits).

Programmatic call-type config (the objects the dashboard edits).

This page is GENERATED from the OpenAPI spec (openapi.yaml) — it can never drift from the served API. Set UR_BASE_URL (required: your gateway’s URL) and UR_API_KEY (an ur_sk_* key); secrets are always the $UR_API_KEY placeholder.

List call types

GET /v1/call-types

Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types" \
  -H "Authorization: Bearer $UR_API_KEY"

Create a call type

POST /v1/call-types

Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "string"
  }'

Get a call type

GET /v1/call-types/{id}

Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000" \
  -H "Authorization: Bearer $UR_API_KEY"

Update a call type config

PATCH /v1/call-types/{id}

Writes a new immutable config version + repoints + bumps config_version. A partial update: a field you omit keeps its current value, and an explicit null clears it — so a body that only sets learned_context_delivery or self_improve_mode never changes the pin, router mode, fallbacks or provider preferences. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X PATCH "$UR_BASE_URL/v1/call-types/req_0000000000000000" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model_pin": "string",
    "router_mode": "pinned"
  }'

List eval runs

GET /v1/call-types/{id}/evals

A call type’s eval runs, their candidate summaries, and each run’s immutable RunSpec (the pinned ExecutionProfile components). Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/evals" \
  -H "Authorization: Bearer $UR_API_KEY"

Enqueue a manual eval run

POST /v1/call-types/{id}/evals

Kicks an eval.run job for this call type. An optional body selects the runner mode (request default, or task for the whole-trace $/task runner). Returns 202 with the enqueued run, or 200 with a documented no-op — a dedupe (deduped:true) also names the prior run it deduped onto (prior_run_id + its trigger/status), so a client can follow it. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/evals" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "request"
  }'

List routing recommendations

GET /v1/call-types/{id}/recommendations

Eval-backed model-migration recommendations for this call type. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/recommendations" \
  -H "Authorization: Bearer $UR_API_KEY"

List hosted prompt versions

GET /v1/call-types/{id}/prompts

The call type’s hosted prompt versions (newest first) + the active pointer. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/prompts" \
  -H "Authorization: Bearer $UR_API_KEY"

Create a hosted prompt version

POST /v1/call-types/{id}/prompts

Append a new (immutable) hosted prompt version for this call type. The version is INACTIVE until activated; activating an older version is the rollback. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/prompts" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "string"
  }'

Get the host-your-prompt onboarding proposal

GET /v1/call-types/{id}/prompts/proposal

The "host your prompt" onboarding proposal for a CODE-OWNED call type: v1 is the MOST COMMON leading system message in the call type’s CONSENTED captured traffic (no body is read without consent). Accepting it is the ordinary create + activate with gateway_apply:false — nothing is applied silently. available:false carries a NAMED reason. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/prompts/proposal" \
  -H "Authorization: Bearer $UR_API_KEY"

Get a hosted prompt version

GET /v1/call-types/{id}/prompts/{version}

Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/prompts/{version}" \
  -H "Authorization: Bearer $UR_API_KEY"

Activate a hosted prompt version

POST /v1/call-types/{id}/prompts/{version}/activate

Make this version the call type’s ACTIVE hosted prompt (writes a new config version + bumps config_version; visible to the gateway within one 5 s config window). Activating an OLDER version is the rollback. gateway_apply makes the proxy path render + substitute it as the leading system instruction. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/prompts/{version}/activate" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "gateway_apply": true
  }'

Deactivate the hosted prompt

POST /v1/call-types/{id}/prompts/deactivate

Back to CODE-OWNED (the request’s own messages pass through untouched). Writes a new config version with the hosted-prompt pointer cleared. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/prompts/deactivate" \
  -H "Authorization: Bearer $UR_API_KEY"

Get the verified-memory status

GET /v1/call-types/{id}/verified-memory

The frozen verified-memory setting on the call type’s ACTIVE config version (rule version, thresholds, pool hash, the calibration + pool accounting), the workspace’s lab authorisation, and a LIVE servability check of the pinned pool (consent, revocation / dispute tombstones, the per-snapshot item budget — over_budget — and the pool hash). A stored setting the gateway cannot load is reported enabled:true, setting:null, servable.reason = setting_unreadable — never shown as off. Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/verified-memory" \
  -H "Authorization: Bearer $UR_API_KEY"

Enable verified memory

POST /v1/call-types/{id}/verified-memory/enable

A LAB-AUTHORISED pre-evidence lever (staff grant flywheel.verified_memory_lab; no customer route grants it — 403 without it). Builds the call type’s pool from its FULL admitted, non-holdout verified outcomes, calibrates the confidence rule (similarity + top-k agreement) by grouped cross-fitting against the DECLARED target precision, and — only when an operating point clears it — persists the pool and appends a config version carrying the frozen setting (config_version bumped: served within one 5 s window). The pool holds at most 250 items (the newest), and the workspace’s memory call types together at most 250 — the budget one config snapshot re-loads on every 5 s refresh (a gateway-overhead bound); past it the enable is refused snapshot_budget_exceeded. The frozen setting is re-parsed from its own stored form before any config version carries it: a setting the gateway could not load is refused setting_unreadable, so an enable that succeeds always serves. An evidence refusal (enabled:false + a NAMED reason + the pool / calibration read) writes no config version. Re-enabling re-derives the pool (e.g. after a revoked or disputed item tombstoned it). Once enabled, memory answers only a request whose meaning its key captures (one instruction message + one text user turn; no image / audio part, earlier turn, extra context message, prompt variables or unsupported parameter) and whose response_format, stop and max_tokens the verbatim answer provably honours — every other request reaches the model, the reason named on its request row. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/verified-memory/enable" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_precision": 0
  }'

Disable verified memory (kill switch)

POST /v1/call-types/{id}/verified-memory/disable

The KILL SWITCH / rollback: appends a config version with memory OFF (config_version bumped), so every request of the call type reaches the model again within one 5 s window. Never gated on the lab authorisation; idempotent (changed:false when already off). Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/verified-memory/disable" \
  -H "Authorization: Bearer $UR_API_KEY"

Get the episode-memory status

GET /v1/call-types/{id}/episode-memory

The frozen episode-memory setting on the call type’s ACTIVE config version (k, char budgets, the pinned/live memory instant, an optional source call type, the record switch), the workspace’s lab authorisation, the episode-trace accounting (total / pass / fail / unverified + the latest pass verification), and a content-addressed PREVIEW of the memory the setting would serve now (memory.digest = emd1_… over the ordered eligible set, memory.verified_pass its size). The optional ?as_of=<iso> overrides the pin FOR THIS READ ONLY, so a checkpoint instant can be digested before the call type is pinned to it. The preview is consent-gated (empty without consent). Requires API-key scope: config:read or config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X GET "$UR_BASE_URL/v1/call-types/req_0000000000000000/episode-memory" \
  -H "Authorization: Bearer $UR_API_KEY"

Enable episode memory

POST /v1/call-types/{id}/episode-memory/enable

A LAB-AUTHORISED pre-evidence lever (staff grant flywheel.episode_memory_lab; no customer route grants it — 403 without it). Freezes a setting on a new config version (config_version bumped: served within one 5 s window), so the gateway records this call type’s agent episodes and injects the most similar VERIFIED past episodes (by task) into EVERY step of later episodes. Invalid knobs are a 400 (the named reason); an unknown source_call_type_id is a 404. No client-side code, no special headers. Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/episode-memory/enable" \
  -H "Authorization: Bearer $UR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "k": 0,
    "max_chars_per_episode": 0
  }'

Disable episode memory (kill switch)

POST /v1/call-types/{id}/episode-memory/disable

The KILL SWITCH / rollback: appends a config version with episode memory OFF (config_version bumped), so the call type serves model-only again within one 5 s window. Never gated on the lab authorisation; idempotent (changed:false when already off). Requires API-key scope: config:write.

Auth: API key (Authorization: Bearer ur_sk_…).

curl -sS -X POST "$UR_BASE_URL/v1/call-types/req_0000000000000000/episode-memory/disable" \
  -H "Authorization: Bearer $UR_API_KEY"