The endpoints behind the dashboard's Workloads and Routing pages and the CLI's workloads/routes commands. Routing is always expressed with public model ids from the catalog — provider deployments are never exposed on this surface.
method & path does GET /customer/v1/orgs/:org_id/projects/:project_id/workloadsList the project's workloads. POST .../workloadsCreate. Body: { "name", "capture_enabled"? }. Names are lowercase alphanumerics/hyphens/underscores, 1–63 chars, unique per project. PATCH .../workloads/:workload_idRename and/or toggle capture. Body: any of { "name", "capture_enabled" }.
method & path does GET /admin/v1/orgs/:org_id/modelsList active catalog models: { id, display_name, active, created_at }. The same ids GET /v1/models returns on the gateway.
Two equivalent write surfaces; use whichever fits your shape:
method & path does PUT /admin/v1/orgs/:org_id/projects/:project_id/workloads/:workload_id/routeSet or clear the route in one call. Body: { "model_id": string | null, "route_traffic_pct"?, "capture_enabled"? }. null clears to passthrough. PATCH /admin/v1/orgs/:org_id/projects/:project_id/workloads/:workload_idPartial update across all routing + capture fields: { "model_id"?, "route_traffic_pct"?, "capture_enabled"?, "capture_sample_rate"?, "name"? }. model_id is tri-state: omitted = unchanged, null = clear, string = route.
route 10% of a workload to a catalog model curl -X PUT "https://api.understudylabs.com/admin/v1/orgs/$ORG_ID/projects/$PROJECT_ID/workloads/$WORKLOAD_ID/route" \
-H "Authorization: Bearer $UNDERSTUDY_API_KEY" \
-H "content-type: application/json" \
-d '{"model_id": "glm-5.1", "route_traffic_pct": 10}'workload object (response shape) {
"id": "usp_...",
"project_id": "proj_...",
"name": "ad-relevance",
"capture_enabled": true, // turned on by the route write above
"route_model_id": "glm-5.1",
"route_traffic_pct": 10,
"capture_sample_rate": 1.0,
"is_default": false,
"created_at": "2026-06-12T00:00:00Z"
}rule why Setting a route turns capture on unless you pass capture_enabled: false. Routed traffic is the traffic worth evidence; opting out is explicit. Omitted route_traffic_pct on a new route defaults to 100 (full cutover). Pass a lower value to canary — e.g. 5 to start small — but the default sends all matching traffic to the route immediately. Clearing (model_id: null) with capture_enabled omitted leaves capture as-is. Rollback shouldn't silently stop your evidence collection. The default workload can't be deleted, and exactly one exists per project. Unscoped traffic always has somewhere to land.
note
Unknown model_id values are rejected with 422 — the catalog (GET .../models) is the authority on what's routable.