understudydocs

control plane api

Reporting & health

Read-only endpoints that answer three questions without asking us: what's routed, is anything broken, and which workloads are affected. Designed to be agent-callable with your normal sk_* key.

Routing status

method & pathdoes
GET /admin/v1/orgs/:org_id/projects/:project_id/routing-statusPer-workload routing topology for the project. Shows which workloads route through Understudy, at what traffic percentage, and which provider/model is active.
response shape
{
  "project_id": "proj_...",
  "workloads": [
    {
      "workload_id": "usp_...",
      "display_name": "chat",
      "environment": null,
      "route_mode": "understudy",     // "primary" | "understudy" | "passthrough"
      "active_traffic_pct": 30,
      "provider_label": "managed",
      "model": "understudy-managed",
      "updated_at": "2026-06-30T00:00:00Z"
    },
    {
      "workload_id": "usp_...",
      "display_name": "automation",
      "environment": null,
      "route_mode": "passthrough",
      "active_traffic_pct": 0,
      "provider_label": null,
      "model": null,
      "updated_at": "2026-06-28T00:00:00Z"
    }
  ],
  "workload_count": 2,
  "generated_at": "2026-06-30T18:30:00.000Z"
}
fieldmeaning
route_modeLegacy enum (kept for compatibility; prefer workload-status): primary — 100% of matching traffic routes through Understudy. understudy — a partial canary split (1–99%). passthrough — no Understudy route; models served as requested.
active_traffic_pct0–100. The percentage of matching requests routed to the managed model.
provider_labelWhere the route is served: anthropic or openai for frontier-API routes, managed for routes served by Understudy's serving infrastructure. null when passthrough.
modelThe model id the route targets. Managed routes report understudy-managed until catalog ids land. null when passthrough.

Provider health

method & pathdoes
GET /admin/v1/orgs/:org_id/projects/:project_id/provider-health?window=30mRecent error and health metrics for the project's providers, aggregated by provider, workload, and model.
paramdefaultdetails
window30mLookback window. Accepts 30m, 1h, 6h, up to 24h.
response shape
{
  "project_id": "proj_...",
  "window": "30m",
  "window_start": "2026-06-30T18:00:00.000Z",
  "window_end": "2026-06-30T18:30:00.000Z",
  "total_requests": 1200,
  "total_errors": 11,
  "providers": [
    {
      "provider": "anthropic",
      "workload": "chat",
      "model": "claude-haiku-4-5",
      "request_count": 600,
      "error_5xx_count": 11,
      "error_5xx_rate": 0.0183,
      "timeout_count": 2,
      "fallback_count": 8,
      "last_failing_at": "2026-06-30T18:28:12.000Z",
      "example_request_ids": [
        "0190a7c2-7e11-7cc3-a312-9f1b22d40e88",
        "0190a7c2-8a22-7cc3-b413-1a2c33e51f99"
      ]
    }
  ],
  "generated_at": "2026-06-30T18:30:00.000Z"
}
fieldmeaning
error_5xx_rateerror_5xx_count / request_count, rounded to four decimal places.
timeout_countRequests where the upstream timed out and triggered a fallback.
fallback_countTotal requests that fell back to an alternative route for any reason.
example_request_idsUp to 5 request ids from failing requests in the window. Look them up via the captures endpoint or x-understudy-request-id in your logs.

Compact status

method & pathdoes
GET /admin/v1/orgs/:org_id/projects/:project_id/statusOne dense summary combining routing topology and recent health. Returns human-readable lines alongside the full structured data.
response shape
{
  "project_id": "proj_...",
  "lines": [
    "chat: 30% routed through Understudy / managed (understudy-managed)",
    "  Last 30m: 11 provider 500s, 1.83% error rate",
    "automation: primary — models served as requested"
  ],
  "routing": { ... },   // full routing-status response
  "health": { ... },    // full provider-health response
  "generated_at": "2026-06-30T18:30:00.000Z"
}

The lines array is the quick answer — print it as-is for a human or feed it to an agent. The nested routing and health objects carry the same structured data as the individual endpoints.

The optional ?window= param works the same as on provider-health (default 30m, max 24h).

Workload status

method & pathdoes
GET /admin/v1/orgs/:org_id/projects/:project_id/workload-status?window=24hOne row per workload: your declared routing config joined server-side with observed traffic. Replaces reconciling routing-status against provider-health by hand. Default window 24h, max 24h.
response shape
{
  "project_id": "proj_...",
  "window": "24h",
  "window_start": "2026-07-19T18:30:00.000Z",
  "window_end": "2026-07-20T18:30:00.000Z",
  "workloads": [
    {
      "workload_id": "usp_...",
      "display_name": "chat",
      "status": "healthy",            // "healthy" | "degraded" | "idle"
      "mode": "anthropic",            // observed: "anthropic" | "openai" | "managed"
      "declared": { "routed": "pin", "split_pct": 30 },
      "requests": 1200,
      "route_shares": { "primary": 0.68, "understudy": 0.3, "fallback": 0.02 },
      "error_rate": 0.002,
      "last_error_at": "2026-07-20 14:02:11.000",
      "example_request_ids": ["0190a7c2-..."],
      "served_models": [
        { "model": "claude-haiku-4-5", "provider_label": "anthropic",
          "requests": 840, "share": 0.7 },
        { "model": "understudy-managed", "provider_label": "managed",
          "requests": 360, "share": 0.3 }
      ],
      "rerouted_pct": 0.3
    }
  ],
  "workload_count": 1,
  "generated_at": "2026-07-20T18:30:00.000Z"
}
fieldmeaning
statushealthy — traffic flowing, 5xx rate under 5%. degraded — 5xx rate at or above 5% over the window. idle — configured but no traffic in the window.
modeObserved provider label (dominant when traffic is mixed). Compare against declared to spot drift — e.g. a flag that isn't actually sending traffic.
declaredYour configured route: pin (routed to a specific deployment), steer (routed to a model), or none — no Understudy route, traffic is primary (models served as requested). split_pct is the traffic dial.
route_sharesObserved shares by route outcome, matching the per-request x-understudy-route header: primary — your requested model served, no route fired; understudy — an Understudy route moved the traffic; fallback — recovery re-issue of your original model after a failed understudy route.
rerouted_pctShare of requests moved by an Understudy-configured route (equals route_shares.understudy; kept as its own field for convenience). The number to watch during a model cutover or canary ramp. Picking a catalog model by name is not rerouting — that traffic stays primary.

Usage summary

method & pathdoes
GET /admin/v1/orgs/:org_id/projects/:project_id/usage-summary?window=7d&group_by=workload,dayAggregate token, cost, cache, and error rollups. Longer windows than the other endpoints (default 7d, max 30d) because it returns aggregates only — no per-request ids.
paramdefaultdetails
window7dLookback window. Accepts m/h/d units, up to 30d.
group_byworkloadComma-separated subset of workload, model, day. Anything else is a 400.
response shape
{
  "project_id": "proj_...",
  "window": "7d",
  "window_start": "2026-07-13T18:30:00.000Z",
  "window_end": "2026-07-20T18:30:00.000Z",
  "group_by": ["workload", "day"],
  "groups": [
    {
      "workload_id": "usp_...",
      "workload": "chat",
      "model": null,
      "day": "2026-07-19",
      "requests": 5200,
      "input_tokens": 1250000,
      "output_tokens": 310000,
      "cache_read_input_tokens": 4100000,
      "cache_creation_input_tokens": 220000,
      "cache_read_pct": 0.7362,
      "customer_cost_usd": 14.8215,
      "error_rate": 0.0008
    }
  ],
  "generated_at": "2026-07-20T18:30:00.000Z"
}

cache_read_pctis the share of prompt tokens served from cache — the "savings this week" number. customer_cost_usd is what the traffic cost you over the group, from the same records that drive billing.