Account
Usage, budgets, keys, and receipted data deletion.
GET /v1/usage
Get usage for a period
Robot-hours by tier, environment-hours by class, and dollars. Stateless test mode cannot see runs it wasn't shown: pass `run_ids=<id,id,...>` to aggregate them (hours come from each run's result; sandbox episodes cost $0 — usd figures show what live mode would have metered). `period` must be YYYY-MM and defaults to the current month.
| Parameter | In | Type | Description |
|---|---|---|---|
period | query | string | |
run_ids | query | string | Comma-separated run ids to aggregate (exact, result-derived hours and cost). |
Example response (200)
{
"object": "usage",
"period": "2026-09",
"robot_hours": {
"verify": 141.2,
"soak": 2210.5
},
"env_hours": {
"bare": 96,
"standard": 402.3,
"replica": 118.9,
"instrumented-replica": 6.2
},
"usd_total": 18940,
"budget": {
"monthly_usd": 25000,
"hard": true,
"remaining_usd": 6060
}
}PUT /v1/budgets
Set the monthly budget
With `hard: true`, new work is rejected and running work is stopped at the cap (`monthly_budget_exceeded`). Metered live.
| Parameter | In | Type | Description |
|---|---|---|---|
monthly_usd * | body | number | |
hard | body | boolean | Hard stop: reject new work and stop running work at the cap. |
remaining_usd | body | number |
Example request
{
"monthly_usd": 25000,
"hard": true
}Example response (200)
{
"monthly_usd": 25000,
"hard": true
}POST /v1/keys
Create an API key
Keys are scoped (e.g. `runs:write`, `streams:read`, `data:purge`). The secret (`rbr_live_` prefix) is shown once at creation.
| Parameter | In | Type | Description |
|---|---|---|---|
scope * | body | array<runs:read | runs:write | streams:read | data:purge | keys:admin | calibration:export> |
Example request
{
"scope": [
"runs:write",
"streams:read"
]
}Example response (201)
{
"object": "key",
"id": "key_51ab",
"scope": [
"runs:write",
"streams:read"
],
"secret": "rbr_live_4eC39HqLyjWDarjtT1zdp7dc",
"created": "2026-09-01T12:00:00Z"
}GET /v1/keys
List API keys
Lists keys for the account. Secrets are never returned after creation.
Example response (200)
{
"object": "list",
"data": [
{
"object": "key",
"id": "key_51ab",
"scope": [
"runs:write",
"streams:read"
],
"created": "2026-09-01T12:00:00Z"
}
]
}DELETE /v1/data/{run_id}
Purge run data (receipted)
Customer-initiated deletion of all artifacts for a run. Returns a deletion receipt. Requires the `data:purge` scope.
| Parameter | In | Type | Description |
|---|---|---|---|
run_id * | path | string |
Example response (200)
{
"object": "purge_receipt",
"id": "prg_77c2",
"run_id": "run_8842",
"status": "completed",
"purged_at": "2026-09-01T13:14:00Z"
}POST /v1/webhooks
Register a webhook endpoint
Register a delivery URL for webhook events. Deliveries are signed with a Stripe-style `Roborama-Signature` header (`t=<unix>,v1=<hmac-sha256>`); the test-mode signing secret is `whsec_test`. Pass the returned id as `webhook` on any create.
| Parameter | In | Type | Description |
|---|---|---|---|
url * | body | string | |
events | body | array<string> | Event types to deliver; defaults to all. |
Example request
{
"url": "https://ci.example.com/hooks/roborama",
"events": [
"run.completed",
"run.requeued"
]
}Example response (201)
{
"object": "webhook_endpoint",
"id": "whk_s...",
"url": "https://ci.example.com/hooks/roborama",
"events": [
"run.completed",
"run.requeued"
],
"secret": "whsec_test",
"note": "stateless: pass this id as \"webhook\" on POST /v1/runs; deliveries fire when a GET or POST /poke touches the run."
}POST /v1/uploads
Create an upload slot (test mode)
Mints a presigned PUT slot for checkpoint or scenario bytes. PUT any bytes to `put_url`; the response carries the real sha256 and an `upl_` id to reference from `policy.checkpoint.upload_id` or `scenarios_upload_id` — the digest appears on the run and its report (custody, testable). Test-mode surface; live mode ingests from your registry/Hub.
| Parameter | In | Type | Description |
|---|---|---|---|
filename | body | string |
Example response (201)
{
"object": "upload",
"status": "awaiting_bytes",
"put_url": "https://api.roborama.com/v1/uploads/<token>?e=...&sig=...",
"expires": "2026-09-12T15:00:00Z"
}POST /v1/webhook-inbox/{box}
Webhook testing inbox (test mode)
An unauthenticated inbox so the whole webhook loop is provable with nothing but the sandbox: register `{base}/v1/webhook-inbox/<yourbox>` as a webhook URL, then GET the box to see deliveries with their Roborama-Signature headers. Instance-local, like the delivered-set.
GET /v1/webhook-inbox/{box}
Read the webhook testing inbox (test mode)
Deliveries this instance captured for the box (last 50).
Example response (200)
{
"object": "list",
"box": "yourbox",
"data": [
{
"received": "2026-09-12T14:00:00Z",
"roborama_signature": "t=...,v1=...",
"body": {
"type": "run.completed"
}
}
]
}