Skip to content
RehearsalDocs

REST API

Every operation of the Rehearsal API, 72 in all, with the access it needs, its parameters and its request body.

The console, the CLI, the Python client and the MCP tools all call this API. You can call it from any language. Every address starts with your server's address, and every operation is under /v1.

Make a request

Send your key in the Authorization header, and send and expect JSON.

curl https://rehearsal.example.com/v1/me \
  -H "Authorization: Bearer <your_key>"
curl -X POST https://rehearsal.example.com/v1/evaluations \
  -H "Authorization: Bearer <your_key>" -H "Content-Type: application/json" \
  -d '{"world_version_id": "<wv_id>", "profile_ids": ["<profile_id>"], "splits": ["dev"], "repeats": 2}'
  • A request that works answers 200, 201 when it created something, or 202 when it started work that continues on the server.
  • A request that fails answers with a status of 400 or above and a JSON body whose detail says why: see Errors.
  • A request with a body that is not valid answers 422, and detail lists each field that is wrong.

Access

Each operation below shows the least access it accepts. admin is accepted everywhere.

Shown asA key needsIn the console
noneNo key
any keyAny key or console session, whatever its access
readThe read scope, which write and evaluator includeRead only
writeThe write scopeBuild and evaluate
evaluatorThe evaluator scopeBuild and evaluate
write and evaluatorBoth scopesBuild and evaluate
adminThe admin scopeFull access
or agentThe agent scope alone is also enough
operator adminA console sign-in by an operator of the server. A key is refused

Sign in and keys explains the scopes.

All operations

OperationDoes
GET /v1/meWho the key or the session is: the project, the organisation, the scopes and the plan
GET /v1/healthWhether the server is up, and whether it offers sign-up and Google sign-in
GET /v1/applicationsThe applications of the project
POST /v1/applicationsAdds an application
POST /v1/applications/import-catalogRegisters the pinned third-party applications from the packaged catalog (rehearsal/assets/catalog.yaml)
DELETE /v1/applications/{app_id}Removes an application from the console
GET /v1/applications/{app_id}One application
POST /v1/applications/{app_id}/sourceUploads a .tar.gz of the application source (extracted safely by the runner)
POST /v1/world-buildsStarts a build of a new world version from an application
GET /v1/jobsThe server jobs of the project, newest first
GET /v1/jobs/{job_id}One server job: its status, attempts, spend, finished phases, result and error
POST /v1/jobs/{job_id}/commandsPauses, resumes, stops or retries a server job
GET /v1/worldsThe worlds of the project, each with its versions and their status
GET /v1/world-versions/{wv_id}One world version: its manifest of services, roles and tools, its validation report and its provenance
GET /v1/world-versions/{wv_id}/scenariosThe jobs of a world version, with their split, status and specification
POST /v1/world-versions/{wv_id}/scenariosAdds a scenario to a published world; it is validated before it can be approved
GET /v1/scenarios/{sc_id}One job, with its specification and validation report
POST /v1/scenarios/{sc_id}/approveApproves a job, so that runs use it
POST /v1/scenarios/{sc_id}/rejectRejects a job, so that runs do not use it
POST /v1/world-versions/{wv_id}/validateRe-checks a published world: replays every job, tries each with a live agent, and withdraws the unfair ones
GET /v1/agent-profilesThe agent profiles of the project, every version
POST /v1/agent-profilesCreates an agent profile
GET /v1/agent-profiles/{prof_id}One agent profile
POST /v1/evaluationsStarts a run: the agents attempt the jobs of a published world version
GET /v1/runsThe runs of the project, newest first
GET /v1/runs/{run_id}One run: its status, its configuration and its summary of scores
POST /v1/runs/{run_id}/commandsA run is several shard jobs; the command goes to every shard it applies to
GET /v1/runs/{run_id}/episodesThe episodes of a run, each with its job, split, agent, status, reward and ending
GET /v1/compareCompares profiles within one run, or two runs on the same pinned world version
POST /v1/improvementsProposes the next version of an agent from its failed train and dev episodes in a run
GET /v1/episodes/{ep_id}One episode in full: the job, each action, each message and the result of each check
POST /v1/episodes/{ep_id}/interventionsChanges a running episode by hand: a message from the customer, a new version of the request, a fault, or a tool taken from or given to a role
GET /v1/episodes/{ep_id}/observationThe turn that waits for a bring-your-own agent, if one does
POST /v1/episodes/{ep_id}/actionsSends the one action of the waiting turn
GET /v1/episodes/{ep_id}/actions/{key}The result of an action, by its idempotency key
GET /v1/jobs/{job_id}/eventsThe events of a server job, as a stream that stays open until the job ends
GET /v1/runs/{run_id}/eventsThe events of a run, as a stream that stays open until the run ends
GET /v1/streams/{stream}/events/pageNon-streaming page of events (for replay and reconnect snapshots)
POST /v1/dataset-exportsExports episodes of runs as a dataset
POST /v1/world-versions/{wv_id}/bundleExports a world version as a bundle file
GET /v1/artifactsExported files: datasets and bundles
GET /v1/artifacts/{art_id}One exported file's record
GET /v1/artifacts/{art_id}/downloadThe exported file itself
GET /v1/dashboardEverything the overview screen needs in one call
GET /v1/usageModel spend this month, the workspace allowance, and what is left of it
GET /v1/billingThe workspace's plan, what it has used this month, and what can be bought
POST /v1/billing/checkoutA Dodo Payments checkout page for a plan or a top-up; the browser goes there and comes back to the Billing page
POST /v1/billing/changeMoves an existing subscription to another plan now; Dodo charges or credits the difference for the rest of the period
POST /v1/billing/portalDodo's customer portal: invoices, payment method, cancellation
POST /v1/billing/syncReads the subscription and top-ups back from Dodo now (after checkout, or when a webhook could not reach us)
GET /v1/pricingBilling price and market range for every configured model, with sources
GET /v1/api-keysThe keys of the project: name, prefix, scopes and last use
POST /v1/api-keysCreates a key
DELETE /v1/api-keys/{key_id}Revokes a key
GET /v1/credentialsThe credential references of the project
POST /v1/credentialsRegisters a credential by reference: the runner reads it from its own environment
DELETE /v1/credentials/{cred_id}Removes a credential reference
POST /v1/auth/signupCreates an account and signs the browser in; onboarding then creates the workspace
POST /v1/auth/loginSigns a browser in with an email address and a password, and sets the session cookie
POST /v1/auth/googleSigns in (registering on first use) with a Google Identity Services ID token
POST /v1/onboarding/workspaceFirst step after a new user signs in: the organisation they own and its first project
DELETE /v1/sessionSigns the browser out
POST /v1/cli/loginsStarts a terminal sign-in
GET /v1/cli/logins/{code}What the approval page shows: which terminal asks, from where, and for which workspace
POST /v1/cli/logins/{code}/{decision}Approves or denies a terminal sign-in
POST /v1/cli/logins/pollThe terminal asks whether its request was approved
GET /v1/admin/organizationsEvery workspace on this server with its plan, owner, and this month's use
PUT /v1/admin/organizations/{org_id}Puts a workspace on any plan, without payment, and optionally changes single limits (null = no limit)
POST /v1/admin/organizations/{org_id}/creditsAdds builds or episodes to a workspace for this month
GET /v1/training-jobsTraining jobs
POST /v1/training-jobsAnswers that training is coming soon
GET /v1/training-jobs/{tj_id}One training job

Who you are

Check a key and the server.

GET /v1/me

GET/v1/meNeeds access: any key

Who the key or the session is: the project, the organisation, the scopes and the plan. Use it to check a key.

Answers 200 with project_id, project, organization, key_id, scopes, plan, user, is_admin, needs_onboarding.

GET /v1/health

GET/v1/healthNeeds access: none

Whether the server is up, and whether it offers sign-up and Google sign-in. Needs no key.

Answers 200 with status, signup, google_client_id, client_wheel.

Applications

The software that worlds are built from. See Add an application.

GET /v1/applications

GET/v1/applicationsNeeds access: read

The applications of the project.

Answers 200.

POST /v1/applications

POST/v1/applicationsNeeds access: write

Adds an application. The name must be unique in the project. Adding starts nothing.

Request body, as JSON:

FieldTypeDefaultMeaning
namestring, 1 to 200 charactersrequiredA name, unique in the project.
sourceobjectrequiredWhere the source is: see the fields of source below.
imagesobjectnoneEach service name with its pinned image, image:tag@sha256:....
policiesstring""Rules the agent must follow, in plain words.
notesstring""Free text for your own use.
connection_modestring"source"Only source is accepted.

Fields of source:

FieldTypeDefaultMeaning
kindone of git, local_path, uploadrequiredgit for a repository, upload for an archive you send afterwards, local_path for a folder on the server's disk.
urlstringnoneFor git: an https:// address, or git@host:path.
refstringnoneFor git: a branch or tag, kept as a note of where the commit came from.
commitstringnoneFor git: the full commit id, 40 or 64 lowercase hexadecimal characters.
pathstringnoneFor local_path: a folder inside the server's REHEARSAL_SOURCE_ROOTS.

Answers 201 with The application: id, name, source, images, policies, notes, connection_mode, created_at.

POST /v1/applications/import-catalog

POST/v1/applications/import-catalogNeeds access: write

Registers the pinned third-party applications from the packaged catalog (rehearsal/assets/catalog.yaml). A plan with an application limit gets as many as it has room for, in catalog order (the free plan: the first, Gitea), so a new free workspace can start from a sample instead of being refused.

Answers 201.

DELETE /v1/applications/{app_id}

DELETE/v1/applications/<app_id>Needs access: admin

Removes an application from the console. Its builds stop; finished runs stay in the run history.

ParameterInTypeDefault
app_idthe pathstringrequired

Answers 200.

GET /v1/applications/{app_id}

GET/v1/applications/<app_id>Needs access: read

One application.

ParameterInTypeDefault
app_idthe pathstringrequired

Answers 200.

POST /v1/applications/{app_id}/source

POST/v1/applications/<app_id>/sourceNeeds access: write

Uploads a .tar.gz of the application source (extracted safely by the runner).

ParameterInTypeDefault
app_idthe pathstringrequired

The body is a form upload with one part, file: the archive.

Answers 201.

World builds and server jobs

Start a build, and follow or control any long piece of work. See Build a practice world.

POST /v1/world-builds

POST/v1/world-buildsNeeds access: write$ Costs money

Starts a build of a new world version from an application. It spends model budget.

Request body, as JSON:

FieldTypeDefaultMeaning
application_idstringrequiredThe application to build from.
modelstringnoneA model chain for the World Compiler, in place of the server's default.
budget_usdnumber, 0 or morenoneModel spend at which the build stops itself.
auto_approvebooleantrueApprove the jobs that pass validation. With false, they wait for you to approve them.
scenario_targetinteger, 1 to 308How many jobs to write.
max_repair_roundsinteger, 0 to 52How many times the compiler may repair a job that fails validation before it gives the job up.
check_determinismbooleantrueReplay each job to prove that it gives the same result twice.

Answers 202 with job_id, world_id, world_version_id, version.

GET /v1/jobs

GET/v1/jobsNeeds access: read

The server jobs of the project, newest first. kind narrows the list.

ParameterInTypeDefault
kindthe querystringnone

Answers 200.

GET /v1/jobs/{job_id}

GET/v1/jobs/<job_id>Needs access: read

One server job: its status, attempts, spend, finished phases, result and error.

ParameterInTypeDefault
job_idthe pathstringrequired

Answers 200 with id, kind, status, attempts, spent_usd, budget_usd, completed_phases, result, error.

POST /v1/jobs/{job_id}/commands

POST/v1/jobs/<job_id>/commandsNeeds access: write

Pauses, resumes, stops or retries a server job. retry restarts a failed or stopped job from its last saved step.

ParameterInTypeDefault
job_idthe pathstringrequired

Request body, as JSON:

FieldTypeDefaultMeaning
commandone of pause, resume, stop, retryrequiredWhat to do with the job or the run.

Answers 200 with status, pause_requested, cancel_requested.

Worlds and their jobs

Worlds, world versions, and the jobs inside them. The API calls a job a scenario.

GET /v1/worlds

GET/v1/worldsNeeds access: read

The worlds of the project, each with its versions and their status.

Answers 200.

GET /v1/world-versions/{wv_id}

GET/v1/world-versions/<wv_id>Needs access: evaluator

One world version: its manifest of services, roles and tools, its validation report and its provenance.

ParameterInTypeDefault
wv_idthe pathstringrequired

Answers 200.

GET /v1/world-versions/{wv_id}/scenarios

GET/v1/world-versions/<wv_id>/scenariosNeeds access: evaluator

The jobs of a world version, with their split, status and specification.

ParameterInTypeDefault
wv_idthe pathstringrequired

Answers 200.

POST /v1/world-versions/{wv_id}/scenarios

POST/v1/world-versions/<wv_id>/scenariosNeeds access: write and evaluator

Adds a scenario to a published world; it is validated before it can be approved.

ParameterInTypeDefault
wv_idthe pathstringrequired

Request body, as JSON:

FieldTypeDefault
scenarioobjectrequired

Answers 202.

GET /v1/scenarios/{sc_id}

GET/v1/scenarios/<sc_id>Needs access: evaluator

One job, with its specification and validation report.

ParameterInTypeDefault
sc_idthe pathstringrequired

Answers 200.

POST /v1/scenarios/{sc_id}/approve

POST/v1/scenarios/<sc_id>/approveNeeds access: write and evaluator

Approves a job, so that runs use it.

ParameterInTypeDefault
sc_idthe pathstringrequired

Answers 200.

POST /v1/scenarios/{sc_id}/reject

POST/v1/scenarios/<sc_id>/rejectNeeds access: write and evaluator

Rejects a job, so that runs do not use it.

ParameterInTypeDefault
sc_idthe pathstringrequired

Answers 200.

POST /v1/world-versions/{wv_id}/validate

POST/v1/world-versions/<wv_id>/validateNeeds access: write and evaluator$ Costs money

Re-checks a published world: replays every job, tries each with a live agent, and withdraws the unfair ones. It spends model budget.

ParameterInTypeDefault
wv_idthe pathstringrequired

Answers 202.

Agent profiles

Versions of the agents under test.

GET /v1/agent-profiles

GET/v1/agent-profilesNeeds access: read

The agent profiles of the project, every version.

Answers 200.

POST /v1/agent-profiles

POST/v1/agent-profilesNeeds access: write

Creates an agent profile. A second profile with the same name becomes the next version.

Request body, as JSON:

FieldTypeDefaultMeaning
namestringrequiredThe agent's name. A second profile with the same name becomes the next version.
system_promptstring""The agent's instructions. Empty uses the platform default.
tool_guidanceobjectnoneExtra guidance for single tools: tool name to text. It is added to the tool's description.
modelstringnoneA model chain for this agent, in place of the server's default.
temperaturenumber0.2The model's sampling temperature.
max_turns_per_actorinteger25How many turns each actor may take in an episode.
driverone of llm, external"llm"llm: Rehearsal runs a model with these instructions. external: your own agent sends the actions.

Answers 201.

GET /v1/agent-profiles/{prof_id}

GET/v1/agent-profiles/<prof_id>Needs access: read

One agent profile.

ParameterInTypeDefault
prof_idthe pathstringrequired

Answers 200.

Evaluations and runs

Start a run, read it, control it and compare it. See Evaluate an agent.

POST /v1/evaluations

POST/v1/evaluationsNeeds access: write$ Costs money

Starts a run: the agents attempt the jobs of a published world version. It spends model budget.

Request body, as JSON:

FieldTypeDefaultMeaning
world_version_idstringrequiredA published world version.
profile_idslist of stringrequiredOne or more agent profiles. They get the same jobs.
splitslist of train, dev, holdoutnoneWhich splits to run. Without it, all three.
scenario_idslist of stringnoneRun only these jobs, in place of whole splits.
repeatsinteger, 1 to 202Attempts at each job by each agent.
default_stressbooleantrueAdd the stress layer to every episode: one refused change, and one repeated request.
budget_usdnumber, 0 or morenoneModel spend at which the run stops itself.
max_episode_cost_usdnumber, 0 or morenoneModel spend at which one episode ends with the ending budget.

Answers 202 with run_id, job_id, episodes, shards, and starts_at when the run waits for quiet hours.

GET /v1/runs

GET/v1/runsNeeds access: read

The runs of the project, newest first.

Answers 200.

GET /v1/runs/{run_id}

GET/v1/runs/<run_id>Needs access: read

One run: its status, its configuration and its summary of scores.

ParameterInTypeDefault
run_idthe pathstringrequired

Answers 200 with The run, with status and summary. summary.profiles has one entry for each agent, named name@vN: see Read results.

POST /v1/runs/{run_id}/commands

POST/v1/runs/<run_id>/commandsNeeds access: write

A run is several shard jobs; the command goes to every shard it applies to.

ParameterInTypeDefault
run_idthe pathstringrequired

Request body, as JSON:

FieldTypeDefaultMeaning
commandone of pause, resume, stop, retryrequiredWhat to do with the job or the run.

Answers 200.

GET /v1/runs/{run_id}/episodes

GET/v1/runs/<run_id>/episodesNeeds access: evaluator

The episodes of a run, each with its job, split, agent, status, reward and ending.

ParameterInTypeDefault
run_idthe pathstringrequired

Answers 200 with A list. Each item has id, scenario, split, profile, status, reward, termination, cost_usd, tokens and oracle.

GET /v1/compare

GET/v1/compareNeeds access: read

Compares profiles within one run, or two runs on the same pinned world version.

ParameterInTypeDefault
run_athe querystringrequired
run_bthe querystringnone

Answers 200 with world_version_id, world_content_hash, and runs: the summary of each run, by run id.

POST /v1/improvements

POST/v1/improvementsNeeds access: write$ Costs money

Proposes the next version of an agent from its failed train and dev episodes in a run. It spends a little model budget.

Request body, as JSON:

FieldTypeDefaultMeaning
profile_idstringrequiredThe agent profile to improve.
run_idstringrequiredA finished run with train or dev episodes of that profile.

Answers 202 with job_id. The job's result names the new profile version and gives the reason for each change.

Episodes

One attempt by one agent at one job.

GET /v1/episodes/{ep_id}

GET/v1/episodes/<ep_id>Needs access: evaluator

One episode in full: the job, each action, each message and the result of each check.

ParameterInTypeDefault
ep_idthe pathstringrequired

Answers 200 with status, termination, reward, scenario, oracle (with check_results, duplicate_effects, false_completion, environment_error), actions and messages.

POST /v1/episodes/{ep_id}/interventions

POST/v1/episodes/<ep_id>/interventionsNeeds access: write and evaluator

Changes a running episode by hand: a message from the customer, a new version of the request, a fault, or a tool taken from or given to a role.

ParameterInTypeDefault
ep_idthe pathstringrequired

Request body, as JSON:

FieldTypeDefaultMeaning
kindone of customer_message, goal_change, fault, revoke_tool, grant_toolrequiredWhat to do in the running episode.
textstringnoneFor customer_message and goal_change: what the customer says.
goal_versionintegernoneFor goal_change: the version of the request to move to.
toolstringnoneFor fault, revoke_tool and grant_tool: the tool it applies to.
fault_modeone of drop_response, error, timeout_before, rate_limitnoneFor fault: how the next call of the tool goes wrong.
rolestringnoneFor revoke_tool and grant_tool: the role that loses or gets the tool.
countinteger1For fault: how many calls it applies to.

Answers 202.

Bring your own agent

Read the waiting turn of an episode and send its action. See Bring your own agent.

GET /v1/episodes/{ep_id}/observation

GET/v1/episodes/<ep_id>/observationNeeds access: read, or agent

The turn that waits for a bring-your-own agent, if one does.

ParameterInTypeDefault
ep_idthe pathstringrequired

Answers 200 with episode_status, awaiting_action, and turn. turn.data has actor, new and tools.

POST /v1/episodes/{ep_id}/actions

POST/v1/episodes/<ep_id>/actionsNeeds access: write, or agent

Sends the one action of the waiting turn. The answer comes at once; the result is read with the next operation.

ParameterInTypeDefault
ep_idthe pathstringrequired

Request body, as JSON:

FieldTypeDefaultMeaning
actorstringrequiredThe actor that the waiting turn names.
toolstringrequiredOne of the tools that the turn offers.
argsobjectnoneThe tool's arguments.
idempotency_keystring, 8 to 64 charactersrequiredYour own name for this action, different for each action. Sending the same action again with the same key does not carry it out twice.

Answers 202 with event_id, and duplicate: true when the same action with the same key was sent before.

GET /v1/episodes/{ep_id}/actions/{key}

GET/v1/episodes/<ep_id>/actions/<key>Needs access: read, or agent

The result of an action, by its idempotency key.

ParameterInTypeDefault
ep_idthe pathstringrequired
keythe pathstringrequired

Answers 200 with {"status": "pending"}, or {"status": "done", "result": ...}.

Events

Follow a build or a run as it happens. See The event format at the end of this page.

GET /v1/jobs/{job_id}/events

GET/v1/jobs/<job_id>/eventsNeeds access: evaluator

The events of a server job, as a stream that stays open until the job ends.

ParameterInTypeDefault
job_idthe pathstringrequired
cursorthe queryintegernone

Answers 200.

GET /v1/runs/{run_id}/events

GET/v1/runs/<run_id>/eventsNeeds access: evaluator

The events of a run, as a stream that stays open until the run ends.

ParameterInTypeDefault
run_idthe pathstringrequired
cursorthe queryintegernone

Answers 200.

GET /v1/streams/{stream}/events/page

GET/v1/streams/<stream>/events/pageNeeds access: evaluator

Non-streaming page of events (for replay and reconnect snapshots).

ParameterInTypeDefault
streamthe pathstringrequired
cursorthe queryinteger0
limitthe queryinteger500

Answers 200.

Exports

Datasets of verified episodes, world bundles, and the files they produce.

POST /v1/dataset-exports

POST/v1/dataset-exportsNeeds access: write

Exports episodes of runs as a dataset. Only train and dev episodes can be exported.

Request body, as JSON:

FieldTypeDefaultMeaning
run_idslist of stringrequiredThe runs to export from.
splitslist of train, devnonetrain, dev or both. Holdout episodes cannot be exported. Without it, train.
verified_onlybooleantrueExport only verified episodes.

Answers 202.

POST /v1/world-versions/{wv_id}/bundle

POST/v1/world-versions/<wv_id>/bundleNeeds access: write and evaluator

Exports a world version as a bundle file.

ParameterInTypeDefault
wv_idthe pathstringrequired
include_imagesthe querybooleanfalse

Answers 202.

GET /v1/artifacts

GET/v1/artifactsNeeds access: evaluator

Exported files: datasets and bundles. kind narrows the list.

ParameterInTypeDefault
kindthe querystringnone

Answers 200.

GET /v1/artifacts/{art_id}

GET/v1/artifacts/<art_id>Needs access: evaluator

One exported file's record.

ParameterInTypeDefault
art_idthe pathstringrequired

Answers 200.

GET /v1/artifacts/{art_id}/download

GET/v1/artifacts/<art_id>/downloadNeeds access: evaluator

The exported file itself.

ParameterInTypeDefault
art_idthe pathstringrequired

Answers 200.

Usage and billing

Model spend, the plan, and payments.

GET /v1/dashboard

GET/v1/dashboardNeeds access: evaluator

Everything the overview screen needs in one call.

Answers 200.

GET /v1/usage

GET/v1/usageNeeds access: read

Model spend this month, the workspace allowance, and what is left of it.

Answers 200 with month, spent_usd, by_kind, allowance_usd (null when there is no limit), left_usd, renews.

GET /v1/billing

GET/v1/billingNeeds access: read

The workspace's plan, what it has used this month, and what can be bought.

Answers 200 with plan (its limits), usage (what is used), month, renews, quiet_hours_utc, next_quiet_start, and the subscription.

POST /v1/billing/checkout

POST/v1/billing/checkoutNeeds access: admin

A Dodo Payments checkout page for a plan or a top-up; the browser goes there and comes back to the Billing page.

Request body, as JSON:

FieldTypeDefault
itemone of pro_monthly, pro_yearly, team_monthly, team_yearly, episodes_1000, build_1required
quantityinteger, 1 to 501

Answers 200.

POST /v1/billing/change

POST/v1/billing/changeNeeds access: admin

Moves an existing subscription to another plan now; Dodo charges or credits the difference for the rest of the period.

Request body, as JSON:

FieldTypeDefault
itemone of pro_monthly, pro_yearly, team_monthly, team_yearlyrequired

Answers 200.

POST /v1/billing/portal

POST/v1/billing/portalNeeds access: admin

Dodo's customer portal: invoices, payment method, cancellation.

Answers 200.

POST /v1/billing/sync

POST/v1/billing/syncNeeds access: write

Reads the subscription and top-ups back from Dodo now (after checkout, or when a webhook could not reach us).

Answers 200.

GET /v1/pricing

GET/v1/pricingNeeds access: read

Billing price and market range for every configured model, with sources.

Answers 200.

Keys

Create, list and revoke API keys, and the references to credentials that a runner reads from its own environment.

GET /v1/api-keys

GET/v1/api-keysNeeds access: admin

The keys of the project: name, prefix, scopes and last use. Never the key itself.

Answers 200.

POST /v1/api-keys

POST/v1/api-keysNeeds access: admin

Creates a key. The answer holds the key, once.

Request body, as JSON:

FieldTypeDefaultMeaning
namestringrequiredA name that says who or what uses the key.
scopeslist of admin, read, write, evaluator, agentnoneThe key's access. The console's "Build and evaluate" is write with evaluator. Without it, admin.

Answers 201 with api_key, shown once, and a note.

DELETE /v1/api-keys/{key_id}

DELETE/v1/api-keys/<key_id>Needs access: admin

Revokes a key. It stops working at once.

ParameterInTypeDefault
key_idthe pathstringrequired

Answers 200.

GET /v1/credentials

GET/v1/credentialsNeeds access: admin

The credential references of the project.

Answers 200.

POST /v1/credentials

POST/v1/credentialsNeeds access: admin

Registers a credential by reference: the runner reads it from its own environment.

Request body, as JSON:

FieldTypeDefault
namestringrequired
kindone of model_provider, application, trainingrequired
env_varstringrequired

Answers 201.

DELETE /v1/credentials/{cred_id}

DELETE/v1/credentials/<cred_id>Needs access: admin

Removes a credential reference.

ParameterInTypeDefault
cred_idthe pathstringrequired

Answers 200.

Sign-in

What the console and rehearsal login use. A program with a key does not need these.

POST /v1/auth/signup

POST/v1/auth/signupNeeds access: none

Creates an account and signs the browser in; onboarding then creates the workspace.

Request body, as JSON:

FieldTypeDefault
namestring, 1 to 200 charactersrequired
emailstringrequired
passwordstring, 10 to 200 charactersrequired

Answers 201.

POST /v1/auth/login

POST/v1/auth/loginNeeds access: none

Signs a browser in with an email address and a password, and sets the session cookie.

Request body, as JSON:

FieldTypeDefault
emailstringrequired
passwordstring, 1 to 200 charactersrequired

Answers 200.

POST /v1/auth/google

POST/v1/auth/googleNeeds access: none

Signs in (registering on first use) with a Google Identity Services ID token.

Request body, as JSON:

FieldTypeDefault
credentialstring, 20 to 8192 charactersrequired

Answers 200.

POST /v1/onboarding/workspace

POST/v1/onboarding/workspaceNeeds access: any key

First step after a new user signs in: the organisation they own and its first project.

Request body, as JSON:

FieldTypeDefault
organizationstring, 1 to 200 charactersrequired
projectstring, 1 to 200 characters"default"

Answers 201.

DELETE /v1/session

DELETE/v1/sessionNeeds access: none

Signs the browser out.

Answers 200.

POST /v1/cli/logins

POST/v1/cli/loginsNeeds access: none

Starts a terminal sign-in. Returns the code to show, the page to open, and the secret device code to poll with.

Request body, as JSON:

FieldTypeDefault
clientstring""

Answers 201 with user_code, device_code, verification_url, expires_in, interval.

GET /v1/cli/logins/{code}

GET/v1/cli/logins/<code>Needs access: read

What the approval page shows: which terminal asks, from where, and for which workspace.

ParameterInTypeDefault
codethe pathstringrequired

Answers 200.

POST /v1/cli/logins/{code}/{decision}

POST/v1/cli/logins/<code>/<decision>Needs access: admin

Approves or denies a terminal sign-in. Only an owner or an admin can approve.

ParameterInTypeDefault
codethe pathstringrequired
decisionthe pathone of approve, denyrequired

Answers 200.

POST /v1/cli/logins/poll

POST/v1/cli/logins/pollNeeds access: none

The terminal asks whether its request was approved. On the first poll after approval it receives a new API key, exactly once.

Request body, as JSON:

FieldTypeDefault
device_codestring, 20 to 200 charactersrequired

Answers 200 with status: pending, approved (with api_key, once), denied or expired.

Operator admin

For the people who run the server. These need a console sign-in by an operator admin, not a key.

GET /v1/admin/organizations

GET/v1/admin/organizationsNeeds access: operator admin

Every workspace on this server with its plan, owner, and this month's use.

Answers 200.

PUT /v1/admin/organizations/{org_id}

PUT/v1/admin/organizations/<org_id>Needs access: operator admin

Puts a workspace on any plan, without payment, and optionally changes single limits (null = no limit).

ParameterInTypeDefault
org_idthe pathstringrequired

Request body, as JSON:

FieldTypeDefault
plan_overrideone of free, pro, team, enterprise, internalnone
limits_overrideobjectnone

Answers 200.

POST /v1/admin/organizations/{org_id}/credits

POST/v1/admin/organizations/<org_id>/creditsNeeds access: operator admin

Adds builds or episodes to a workspace for this month.

ParameterInTypeDefault
org_idthe pathstringrequired

Request body, as JSON:

FieldTypeDefault
kindone of episodes, buildsrequired
quantityinteger, 1 to 1e+06required
notestring""

Answers 201.

Training

Not built yet: see Not built yet.

GET /v1/training-jobs

GET/v1/training-jobsNeeds access: read

Training jobs. None can exist yet.

Answers 200.

POST /v1/training-jobs

POST/v1/training-jobsNeeds access: write

Answers that training is coming soon.

Request body, as JSON:

FieldTypeDefault
world_version_idstringrequired
base_modelstring"Qwen/Qwen3-1.7B"
roundsinteger, 1 to 62
rollouts_per_scenariointeger, 1 to 324
serve_base_urlstring"http://127.0.0.1:8001/v1"
kaggle_gpuone of NvidiaTeslaT4, NvidiaTeslaP100"NvidiaTeslaT4"
budget_usdnumbernone

Answers 202.

GET /v1/training-jobs/{tj_id}

GET/v1/training-jobs/<tj_id>Needs access: read

One training job. None can exist yet.

ParameterInTypeDefault
tj_idthe pathstringrequired

Answers 200.

The event format

A build and a run record what happens as events. The two event operations answer with a stream of server-sent events that stays open until the work ends.

curl -N "https://rehearsal.example.com/v1/runs/<run_id>/events?cursor=0" \
  -H "Authorization: Bearer <your_key>"

Each event is one JSON object in a data: line. Its fields:

FieldMeaning
event_idA number that grows. Pass the last one you saw as cursor to continue after a lost connection
typeWhat happened, for example compiler.phase.started, action.succeeded, goal.revised, episode.finished
summaryOne line of text for people
created_atWhen, in UTC
streamThe id of the server job or the run that the event belongs to
episode_id, actor_id, goal_versionSet when the event belongs to an episode, an actor, or a version of the request
dataMore fields, by type

The stream ends with an event named stream.end. The Python client reads the stream and reconnects for you: rh.jobs.events(job_id) and rh.runs.events(run_id).

To read events without a stream, use GET /v1/streams/<stream>/events/page, which answers one page as a list.

The schema

The server publishes the OpenAPI document of this API at /openapi.json, and a page to try each operation at /api/docs. rehearsal openapi prints the same document on a machine that has the server installed.

Generated from the code of rehearsal-kit 0.1.2.

Was this page helpful?

On this page

Make a requestAccessAll operationsWho you areGET /v1/meGET /v1/healthApplicationsGET /v1/applicationsPOST /v1/applicationsPOST /v1/applications/import-catalogDELETE /v1/applications/{app_id}GET /v1/applications/{app_id}POST /v1/applications/{app_id}/sourceWorld builds and server jobsPOST /v1/world-buildsGET /v1/jobsGET /v1/jobs/{job_id}POST /v1/jobs/{job_id}/commandsWorlds and their jobsGET /v1/worldsGET /v1/world-versions/{wv_id}GET /v1/world-versions/{wv_id}/scenariosPOST /v1/world-versions/{wv_id}/scenariosGET /v1/scenarios/{sc_id}POST /v1/scenarios/{sc_id}/approvePOST /v1/scenarios/{sc_id}/rejectPOST /v1/world-versions/{wv_id}/validateAgent profilesGET /v1/agent-profilesPOST /v1/agent-profilesGET /v1/agent-profiles/{prof_id}Evaluations and runsPOST /v1/evaluationsGET /v1/runsGET /v1/runs/{run_id}POST /v1/runs/{run_id}/commandsGET /v1/runs/{run_id}/episodesGET /v1/comparePOST /v1/improvementsEpisodesGET /v1/episodes/{ep_id}POST /v1/episodes/{ep_id}/interventionsBring your own agentGET /v1/episodes/{ep_id}/observationPOST /v1/episodes/{ep_id}/actionsGET /v1/episodes/{ep_id}/actions/{key}EventsGET /v1/jobs/{job_id}/eventsGET /v1/runs/{run_id}/eventsGET /v1/streams/{stream}/events/pageExportsPOST /v1/dataset-exportsPOST /v1/world-versions/{wv_id}/bundleGET /v1/artifactsGET /v1/artifacts/{art_id}GET /v1/artifacts/{art_id}/downloadUsage and billingGET /v1/dashboardGET /v1/usageGET /v1/billingPOST /v1/billing/checkoutPOST /v1/billing/changePOST /v1/billing/portalPOST /v1/billing/syncGET /v1/pricingKeysGET /v1/api-keysPOST /v1/api-keysDELETE /v1/api-keys/{key_id}GET /v1/credentialsPOST /v1/credentialsDELETE /v1/credentials/{cred_id}Sign-inPOST /v1/auth/signupPOST /v1/auth/loginPOST /v1/auth/googlePOST /v1/onboarding/workspaceDELETE /v1/sessionPOST /v1/cli/loginsGET /v1/cli/logins/{code}POST /v1/cli/logins/{code}/{decision}POST /v1/cli/logins/pollOperator adminGET /v1/admin/organizationsPUT /v1/admin/organizations/{org_id}POST /v1/admin/organizations/{org_id}/creditsTrainingGET /v1/training-jobsPOST /v1/training-jobsGET /v1/training-jobs/{tj_id}The event formatThe schema

Was this page helpful?