REST
LivePlain HTTPS and JSON, with an OpenAPI 3.1 spec per product.
GET /tracez/v1/sessions/{id}
POST /tracez/v1/sessions/{id}/redact
Recurz API · v1
Every product, one shape. Learn one endpoint and you can guess the rest: the same IDs, errors, paging and versioning everywhere, served as REST, GraphQL and MCP from one schema.
# Any product, same token, same shape
curl https://api.recurz.ai/tracez/v1/sessions?harness=codex \
-H "Authorization: Bearer $RECURZ_TOKEN"
{"data": [{"id": "9f2c41…", "title": "Fix the flaky auth test", "source": "codex",
"steps": 214, "errors": 3, "live": false}],
"next_cursor": "1760541002113", "has_more": true}
Preview This is the v1 layout. Endpoints marked live answer on api.recurz.ai today; built ones run inside their product (Tracez's at tracez.recurz.ai) and are on their way here. The cookbook uses today's addresses.
Every operation exists on all three, spelled the way each one's users expect. Tracez has all three today; the other products have REST and MCP, and every endpoint below says what is live.
Plain HTTPS and JSON, with an OpenAPI 3.1 spec per product.
GET /tracez/v1/sessions/{id}
POST /tracez/v1/sessions/{id}/redact
One graph across every product. Follow a finding to its session to its turns in one query.
finding(id: "fnd_01J9…") {
kind session { turns(first: 5) { … } }
}
For agents. One server per product, or one for the whole platform.
https://api.recurz.ai/tracez/v1/mcp get_session
https://api.recurz.ai/mcp tracez_get_session
One operation, three spellings. Each column follows the convention its own users already know, so nothing reads like a translation.
| RESTHTTP verb on a plural noun, like Stripe | GraphQLcamelCase fields, Relay connections and inputs | MCP toolverb_noun, like GitHub's MCP server |
|---|---|---|
GET /sessions | sessions(first:) | list_sessions |
GET /sessions/{id} | session(id:) | get_session |
POST /sessions/{id}/redact | redactSession(input:) | redact_session |
Each product owns a few nouns and the verbs on them. LiveBuilt, not on the API yetPlanned
Sessions, turns, artifacts and a change feed for every agent run from every harness.
api.recurz.ai/tracez/v1
/sessionsList sessions; filter with q, harness, project/sessions/{id}Get one session/sessions/{id}/turnsPage through its turns, with revisions/sessions/{id}/childrenEvery sub-agent it spawned, as a tree/sessions/{id}/redactScrub a session, keep its shape/sessions/{id}Delete it for good/artifactsAttach a file to a session/changes?follow=trueEvery change, live, resumable/searchFull-text search across turns, with highlights/saved_searchesKeep a search; follow it for new matches/rollups?period=daySessions, turns, cost and findings per day/legal_holdsKeep sessions past retention/exportsStart an export of everythingRolls transcripts up from turn to day, flags hangs, loops and waste, and can step in.
api.recurz.ai/sentinelz/v1
/findingsHangs, loops, stalls, premature stops, waste/findings/{id}/resolveFixed it; acknowledge and dismiss too/findings/{id}/feedbackUseful, wrong or noise: tunes the detectors/findings/{id}/export_testTurn it into a Verdictz test/sessions/{id}/summaryHeadline, status and next step/rulesStanding instructions for an org or repo/hooksHarness hook in, decision out/interventionsEvery nudge, and whether it worked/decisions?status=openStops that are waiting on a person/retrosGrade a finished session for waste/digests?period=dayWhat moved, what slipped, what waitsEvery running agent as one line of words, with a hand on the wheel.
api.recurz.ai/observerz/v1
/diary/days/{day}What your agents did that day, by project/moodsHow each session felt, turn by turn/ideasIdeas your agents raised, filed by project/askAsk a question about your agents' work/nudgesNudges sent to running agents, and their rules/agents?follow=trueEvery live agent, one line each/agents/{id}/timelineTurns, findings and nudges, interleaved/agents/{id}/treeIts parent, children and handoffs/inboxEvery agent waiting on a person/agents/{id}/nudgeSay something to a running agent/agents/{id}/pauseHold it at the next step; resume later/agents/{id}/stopStop it/agents/{id}/handoffTake over/alert_rulesPage on loops, stalls or spend/notification_channelsSlack, email, Pushover or a webhookBranched evals: change one thing, run the same scenarios on the same seeds, keep it only if the interval clears zero.
api.recurz.ai/verdictz/v1
/loadoutsHarness × model × reasoning × memory × skills × MCP/mapsPublished task sets to score against/runs/quoteWhat a run will cost, before it runs/runsRun a loadout on a campaign/experiments/prepareBaseline vs branch, with confirmation; then {id}/start/experiments/{id}/resultsA 95% interval on the difference/task-runs/{id}/trajectoryEvery step, searchable and narrated/runs/{id}/assessmentThe judge's verdict, with evidence/task_candidatesTasks mined from your own repos/testsTurn an Observerz finding into a test/recommendationsThe setup that wins on your workSmall first, frontier when it matters. Speaks the provider APIs unchanged, so your SDK only needs a new base URL.
api.recurz.ai/steerz/v1
/chat/completionsOpenAI Chat Completions, unchanged/responsesOpenAI Responses, unchanged/messagesAnthropic Messages, unchanged/classifyWhat class a call is, without calling/policiesAdaptive, rewrite or cascade routing/armsEvery route's quality, cost and latency/decisions/{id}Why a call went where it did/backtestsTry a policy on last month's sessions/modelsEvery model your Steerz routes to, with list prices/providersWhich providers have your own keyKeys, members, devices, spend and events, shared by every product.
api.recurz.ai/platform/v1
/orgs/meThe org this key belongs to/api_keysCreate a key; the secret is shown once/devicesEnrolled machines/devices/{id}/revokeCut a machine off/grantsInstall an app with a data policy/provider_credentialsBring your own model keys/spend_limitsCap spend per product or key/usage?group_by=productWhat you used, by product and day/audit_logEvery admin change/events?follow=trueEverything that happened, live/webhook_endpointsGet events pushed to youModel calls go through Steerz unchanged: OpenAI(base_url="https://steerz.recurz.ai/v1") or Anthropic(base_url="https://steerz.recurz.ai") with a Steerz key (stz_…), and the route it picked comes back in x-steerz-* headers. Collectors and OTLP exporters send to ingest.recurz.ai.
The rules every product follows, so nothing in the second product surprises you after the first.
Opaque, prefixed, sortable by time. Paste one anywhere and you know what it is.
ses_ session fnd_ finding run_ run job_ job org_ org req_ request
Tracez v1 session ids are the 64-character hex ids your harness already logs; ses_ ids arrive with v2. Money is in US dollars, in fields ending _usd.
?limit= and ?cursor= in; data, next_cursor and has_more out. Add ?follow=true to any list to get it live over Server-Sent Events, resumable with Last-Event-ID.
{"error": {"type": "invalid_request",
"code": "session_not_found",
"param": "session_id",
"request_id": "req_01J9ZP…"}}
The shape OpenAI and Anthropic clients already parse. code is stable; message is for people.
Send Idempotency-Key on any POST and a retry returns the first result instead of doing it twice. Every response carries Recurz-Request-Id.
Evals and other long jobs return a run with one status set: queued, running, succeeded, failed, cancelled. Poll it, follow it, or get a webhook.
snake_case fields. Times in RFC 3339 UTC. Money as a decimal string, "cost_usd": "0.0042", never a float. Big numbers as strings.
One event log per org. Webhooks and Server-Sent Events read it today, with GraphQL subscriptions to follow, and every one resumes from the same event ID.
# Every event, on every transport
{"id": "evt_01J9ZQ4C2W",
"type": "sentinelz.finding.created",
"created_at": "2026-10-09T15:30:02Z",
"api_version": "sentinelz/v1",
"livemode": true,
"data": {"object": {"id": "fnd_01J9ZM2Q8B",
"kind": "loop",
"session_id": "ses_01J9ZK4M7T", …}}}
| Way in | What you write |
|---|---|
| WebhookServers that should be called | POST /platform/v1/webhook_endpoints{"url": "…", "events": ["sentinelz.finding.*"]} |
| SSEScripts, dashboards, curl | GET /platform/v1/events?types=sentinelz.*&follow=true |
| GraphQLUIs that want linked objects | subscription { events(types: […]) { … on Finding { session { title } } } } |
{product}.{noun}.{verb}, like Stripe's invoice.paid with the product in front: tracez.rollup.ready, loadoutz.run.failed. Subscribe with globs like sentinelz.*.
Signed to the Standard Webhooks spec, so existing libraries verify them in one line. Retried for three days, replayable from any event, and every attempt is listed under deliveries.
data.object is the resource exactly as its own GET returns it, at the version you pinned. Delivery is at least once, so dedupe on the event ID.
If it's on this page, it won't break.
/tracez/v2 can ship while /sentinelz/v1 stays put.@deprecated first and leave only after the window.Deprecation and Sunset headers and the changelog.Recurz-Preview: feature-name. Previews can change; nothing else does.Authorization: Bearer recurz_key_live_… on every product except Steerz, or recurz_key_test_… for test data. Steerz at steerz.recurz.ai takes its own stz_… keys, as Authorization: Bearer or x-api-key. A key belongs to one org, so no call ever takes an org parameter. Keys are recognisable by prefix, so a leaked one gets caught by secret scanning.
recurz_device_…, made on the machine by recurz-collector login. It can only send transcripts to ingest.recurz.ai, and you can revoke one machine without touching anything else.
Common jobs end to end against Tracez as it runs today, each with a sequence diagram and the exact calls.
Enroll a device, then stream batches until every one has a matching receipt.
RESTPoint an MCP client at Tracez and let the agent find and read earlier sessions.
MCPTake a consistent snapshot, then poll the change feed without missing a write.
RESTGraphQLFetch a session, its turns and where they came from in a single GraphQL query.
GraphQLUpload a report or patch next to the run that produced it. Retries are safe.
RESTMCPTake your data out, scrub one session, or remove it for good.
RESTSpecs: signed in, Tracez serves its own at tracez.recurz.ai/api/specs/ (openapi.json, tracez.proto, schema.graphql, mcp-tools.json); every product's at api.recurz.ai/{product}/v1/openapi.json is on the way. Want in? founders@recurz.ai