Skip to content
Docs menu

API reference

Every operation in docs/openapi.yaml, with its auth scope. The contract is the source of truth for all four surfaces.

Download openapi.yamlOpenAPI 3.1 · version 0.1.0 · 150 operations · 485 schemas

Rendered from the contract at build time — the same file make sdk generates both clients from, so nothing here can drift from it. The CLI, the MCP server and the generated SDKs are the clients; this page is the reference.

The open hub for robot data, models and training. One REST API serving the web app, CLI, MCP server and generated SDKs.

Conventions

IDs — every resource has a stable, prefixed, lexicographically sortable id: {prefix}_{26-char Crockford-base32 ULID} (e.g. repo_01J8ZC9EXAMPLE0000000000EX). Prefixes: user_, org_, member_, key_, repo_, file_, run_, rollout_, audit_, ledger_, and from M13 dev_, dreq_, appr_, devt_, from M15 ep_, esess_, and from R1 rchk_. Repos are addressed in URLs by {owner}/{repo} (handles), jobs by id. Pagination — cursor-based everywhere: pass limit and the opaque cursor from the previous page; responses are {items: [...], next_cursor: string|null}. next_cursor: null means exhausted. Cursors are opaque; do not construct them. Errors — RFC 9457 application/problem+json: {type, title, status, detail?, instance?, errors?}. Validation failures use status 422 with per-field errors[]. Auth — Authorization: Bearer <token> where the token is either a Clerk session JWT (web) or a scoped API key lucen_sk_... (CLI/MCP/SDK). Scopes are a strict hierarchy — read ⊂ write ⊂ train: key:read (read + download) < key:write (all data mutations: repos, files, meta, orgs) < key:train (compute and money: submit training runs and rollouts; implies write). Splitting data from money is deliberate — an agent-held key can be allowed to browse and push data while being unable to spend GPU dollars. A session token carries the user's full powers. Every operation declares its minimum programmatic scope in x-auth-scope (none | key:read | key:write | key:train | session); none means anonymous works for public resources — private resources still require auth + access. session means no API key is ever sufficient: only a Clerk session may call it. Two families are session in v0: API key management, so that a leaked write-scoped agent key cannot mint itself a train-scoped one, and device approvals (M13), so that no key of any scope — and therefore no agent — can put a policy on a robot; an agent may only request one.

Visibility — private resources are invisible, not merely forbidden: a caller without access gets 404, never 403, on read paths (a 403 would confirm the resource exists). 403 is reserved for a caller who can see the resource but lacks the scope or membership to act on it.

Rate limits — anonymous, per client IP: 300 requests/minute for a credential-less GET/HEAD (a page view is several reads) and 60/minute for everything else (unsafe methods, and any request whose credential failed to verify); 600/minute authenticated (per session user or per API key). Every /v1 response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (unix seconds); exceeding the limit yields 429 with Retry-After and a problem body. 429 is an infrastructure response and is therefore not enumerated per operation. Timestamps — RFC 3339 UTC (2026-08-31T12:00:00Z).

Auth scopes

Each operation declares one, as the x-auth-scope extension in the spec. A test asserts the spec and the scope table in docs/API.md agree in both directions, so neither can rot.

Auth scopes
ScopeWhat it gates
noneAnonymous. Public repos, episodes, and the Coach corpus.
key:readList and read what the credential's owner can see.
key:writeCreate repos, upload files, import a run. Implies read.
key:trainSpend money: GPU jobs, Coach advice. Implies write.
sessionBrowser session only. Key management and device approvals — no API key may mint another, and no key may put a policy on a robot.

Every operation (150)

Grouped by tag, in the contract’s order. Each path opens the operation’s section: parameters, request body, responses.

meta (1)

Service metadata and probes

meta operations
MethodPathScopeSummary
GET/healthzhealthznoneLiveness probe

install (1)

K3 — the hub's own installer for its clients (lucen, lucen-device, lucen-mcp)

install operations
MethodPathScopeSummary
GET/install.shgetInstallScriptnoneThe installer for this hub's clients

auth (1)

Identity of the caller

auth operations
MethodPathScopeSummary
GET/v1/auth/megetMekey:readWho am I

keys (3)

Scoped API keys for programmatic access (CLI / MCP / SDK)

keys operations
MethodPathScopeSummary
GET/v1/keyslistApiKeyssessionList my API keys
POST/v1/keyscreateApiKeysessionCreate an API key
DELETE/v1/keys/{key_id}revokeApiKeysessionRevoke an API key

users (1)

Public user profiles

users operations
MethodPathScopeSummary
GET/v1/users/{username}getUsernonePublic user profile

orgs (7)

Organizations and membership (CRUD-lite)

orgs operations
MethodPathScopeSummary
GET/v1/orgslistMyOrgskey:readList my organizations
POST/v1/orgscreateOrgkey:writeCreate an organization
GET/v1/orgs/{org}getOrgnoneGet an organization
PATCH/v1/orgs/{org}updateOrgkey:writeUpdate an organization
GET/v1/orgs/{org}/memberslistOrgMemberskey:readList organization members
PUT/v1/orgs/{org}/members/{username}putOrgMemberkey:writeAdd or update a member
DELETE/v1/orgs/{org}/members/{username}removeOrgMemberkey:writeRemove a member

repos (5)

Repos (kind = dataset | model | robot) — create, read, update, delete, search

repos operations
MethodPathScopeSummary
GET/v1/reposlistReposnoneList / search repos
POST/v1/reposcreateRepokey:writeCreate a repo
GET/v1/repos/{owner}/{repo}getRepononeGet a repo
PATCH/v1/repos/{owner}/{repo}updateRepokey:writeUpdate a repo
DELETE/v1/repos/{owner}/{repo}deleteRepokey:writeDelete a repo

files (5)

Repo files — presigned multipart upload/download against object storage, tree listing

files operations
MethodPathScopeSummary
GET/v1/repos/{owner}/{repo}/treegetRepoTreenoneList repo files
POST/v1/repos/{owner}/{repo}/files/presign-uploadpresignUploadkey:writePresign a batch multipart upload
POST/v1/repos/{owner}/{repo}/files/completecompleteUploadkey:writeComplete a batch multipart upload
POST/v1/repos/{owner}/{repo}/files/presign-downloadpresignDownloadnonePresign downloads
POST/v1/repos/{owner}/{repo}/files/deletedeleteFileskey:writeDelete files (batch unlink)

datasets (4)

Dataset-kind repo extras — episode index, frames index, per-episode playback payload, dataset meta

datasets operations
MethodPathScopeSummary
GET/v1/datasets/{owner}/{repo}/episodeslistDatasetEpisodesnoneList dataset episodes
GET/v1/datasets/{owner}/{repo}/episodes/{episode_index}/frames-indexgetEpisodeFramesIndexnoneFrames index for one episode
GET/v1/datasets/{owner}/{repo}/episodes/{episode_index}/seriesgetEpisodeSeriesnonePlayable payload for one episode
PUT/v1/datasets/{owner}/{repo}/metaputDatasetMetakey:writeSet dataset meta

models (1)

Model-kind repo extras — model meta

models operations
MethodPathScopeSummary
PUT/v1/models/{owner}/{repo}/metaputModelMetakey:writeSet model meta

robots (11)

Robot-kind repo extras — robot card

robots operations
MethodPathScopeSummary
GET/v1/robots/{owner}/{repo}/cardgetRobotCardnoneGet a robot card
PUT/v1/robots/{owner}/{repo}/cardputRobotCardkey:writeSet a robot card
POST/v1/robots/{owner}/{repo}/validatevalidateRobotkey:readValidate a robot card against the repo's MJCF, without writing
GET/v1/robot-checkslistRobotCheckskey:readList hosted robot checks
POST/v1/robot-checkscreateRobotCheckkey:writeQueue a hosted check of a robot repo's model
GET/v1/robot-checks/{check_id}getRobotCheckkey:readGet a hosted robot check
POST/v1/robot-checks/{check_id}/claimclaimRobotCheckkey:writeClaim a queued check (robot check worker protocol)
POST/v1/robot-checks/{check_id}/artifactspresignRobotCheckArtifactskey:writePresign uploads for a running check's artifacts
POST/v1/robot-checks/{check_id}/reportreportRobotCheckkey:writeReport progress or the result of a claimed check
POST/v1/robot-checks/{check_id}/publishpublishRobotCheckkey:writePublish a check's draft card into the robot repo, as the caller
POST/v1/robot-checks/{check_id}/cancelcancelRobotCheckkey:writeCancel a hosted robot check

runs (14)

Training runs — submitted here, executed by an executor: a self-hosted worker (M7-RL) or Modal (modal, not built yet)

runs operations
MethodPathScopeSummary
GET/v1/runslistRunskey:readList training runs
POST/v1/runscreateRunkey:trainCreate a training run
POST/v1/runs/importimportRunkey:writeImport a training run trained off-platform
POST/v1/runs/estimateestimateRunkey:trainPrice a training run before submitting it
POST/v1/runs/recommendrecommendRunkey:readRecommend a GPU tier for a training run (deterministic planner)
GET/v1/runs/{run_id}getRunkey:readGet a training run
GET/v1/runs/{run_id}/logsstreamRunLogskey:readStream run logs (SSE)
GET/v1/runs/{run_id}/logs/downloaddownloadRunLogskey:readDownload a run's whole log as text
POST/v1/runs/{run_id}/cancelcancelRunkey:trainCancel a training run
GET/v1/runs/{run_id}/configgetRunConfigkey:readA run's resolved config, flattened, and its diff against the parent
GET/v1/runs/{run_id}/checkpointslistRunCheckpointskey:readList a run's checkpoints
POST/v1/runs/{run_id}/claimclaimRunkey:trainClaim a queued worker run (self-hosted runner protocol)
POST/v1/runs/{run_id}/reportreportRunkey:trainReport progress or a terminal state for a claimed run
GET/v1/hardware_tierslistHardwareTiersnoneGPU tiers and what an hour on each costs

rollouts (11)

Sim rollout jobs — watch a policy run in MuJoCo

rollouts operations
MethodPathScopeSummary
GET/v1/rolloutslistRolloutskey:readList sim rollouts
POST/v1/rolloutscreateRolloutkey:trainCreate a sim rollout
GET/v1/rollouts/{rollout_id}getRolloutkey:readGet a sim rollout
POST/v1/rollouts/{rollout_id}/claimclaimRolloutkey:trainClaim a queued rollout (rollout worker protocol)
POST/v1/rollouts/{rollout_id}/artifactspresignRolloutArtifactskey:trainPresign uploads for a running rollout's artifacts
POST/v1/rollouts/{rollout_id}/reportreportRolloutkey:trainReport progress or the result of a claimed rollout
POST/v1/rollouts/{rollout_id}/cancelcancelRolloutkey:trainCancel a sim rollout
POST/v1/rollouts/{rollout_id}/renderrenderRolloutkey:trainRender an earlier rollout's videos
GET/v1/runs/{run_id}/gatesgetRunGateskey:readThe sim gates a run's checkpoints got while it trained
GET/v1/runs/{run_id}/scangetRunScankey:readA band scan's table
POST/v1/runs/{run_id}/scanscanRunkey:trainBand-scan a run's checkpoints in simulation

devices (23)

Device consent layer (M13) — robot-side runners, approval requests an agent may make, approvals only a human session may sign, and the driver's telemetry summaries. No API key can put a policy on a robot.

devices operations
MethodPathScopeSummary
GET/v1/devices/signing-keygetDeviceSigningKeynoneThe hub's approval verification key
GET/v1/deviceslistDeviceskey:readList devices
POST/v1/devicesregisterDevicekey:writeRegister a robot-side runner
POST/v1/device-pairingscreateDevicePairingkey:writeStart pairing a robot from the platform
POST/v1/device-pairings/claimclaimDevicePairingnoneDeclare this robot to a pairing — with a code, or to get one
GET/v1/device-pairings/{pairing}getDevicePairingkey:readGet a pairing — has the robot joined, what did it declare?
DELETE/v1/device-pairings/{pairing}rejectDevicePairingkey:writeDrop a pairing — "Not my robot"
POST/v1/device-pairings/{pairing}/confirmconfirmDevicePairingsessionConfirm the robot that claimed a pairing (web session only)
POST/v1/device-pairings/{pairing_id}/collectcollectDevicePairingnoneThe robot picks up what a person confirmed
GET/v1/devices/{device_id}getDevicekey:readGet a device
POST/v1/devices/{device_id}/disconnectdisconnectDevicekey:writeDisconnect a device — revoke its credential
POST/v1/devices/{device_id}/trust-modesetDeviceTrustModekey:writeThe robot changes its own trust mode
GET/v1/devices/{device_id}/approval-requestslistApprovalRequestskey:readList a device's approval requests
POST/v1/devices/{device_id}/approval-requestscreateApprovalRequestkey:writeAsk for a policy to be put on a device
GET/v1/devices/{device_id}/approval-requests/{request_id}getApprovalRequestkey:readGet an approval request
POST/v1/devices/{device_id}/approval-requests/{request_id}/denydenyApprovalRequestsessionDeny an approval request (web session only)
GET/v1/devices/{device_id}/approvalslistApprovalskey:readList a device's approvals
POST/v1/devices/{device_id}/approvalscreateApprovalsessionApprove a pending request and mint the signed token (web session only)
GET/v1/devices/{device_id}/approvals/{approval_id}getApprovalkey:readGet an approval
POST/v1/devices/{device_id}/approvals/{approval_id}/stopstopApprovalkey:writeStop an approval now
GET/v1/devices/{device_id}/eventslistDeviceEventskey:readList a device's events
POST/v1/devices/{device_id}/eventspostDeviceEventkey:writeRecord a telemetry summary from the driver
GET/v1/approval-requests/{request_id}getApprovalRequestByIdkey:readGet an approval request by its id alone

endpoints (10)

Inference endpoints (M15) — hub-served inference for the skill / planner layer, never the reflex layer. Claimed by lucen serve, consumed by a device only through a signed approval bound to device + model digest + endpoint id, metered per session.

endpoints operations
MethodPathScopeSummary
GET/v1/endpointslistEndpointskey:readList inference endpoints
POST/v1/endpointscreateEndpointkey:trainCreate an inference endpoint for a skill-layer model
POST/v1/endpoints/estimateestimateEndpointkey:trainPrice an endpoint before creating it
GET/v1/endpoints/{endpoint_id}getEndpointkey:readGet an inference endpoint
DELETE/v1/endpoints/{endpoint_id}stopEndpointkey:trainStop an inference endpoint
POST/v1/endpoints/{endpoint_id}/claimclaimEndpointkey:trainClaim a queued worker endpoint (`lucen serve` protocol)
POST/v1/endpoints/{endpoint_id}/reportreportEndpointkey:trainReport sessions, metering and state for a claimed endpoint
GET/v1/endpoints/{endpoint_id}/sessionslistEndpointSessionskey:readList an endpoint's sessions (metering)
POST/v1/endpoints/{endpoint_id}/sessionsopenEndpointSessionkey:writeOpen a session on an endpoint (a device, with a human's approval)
POST/v1/endpoints/{endpoint_id}/sessions/{session_id}/reportreportEndpointSessionkey:writeThe device's own metering for a session

coach (8)

Training Coach — the experience corpus, run diagnosis with in-whitelist proposals, and programme planning. Every claim cites a card.

coach operations
MethodPathScopeSummary
GET/v1/coach/doctrinegetCoachDoctrinenoneThe coach's doctrine (numbered methodology rules)
GET/v1/coach/cardssearchExperienceCardsnoneSearch the experience corpus
GET/v1/coach/cards/{card_id}getExperienceCardnoneGet one experience card
POST/v1/coach/advicecreateAdvicekey:trainDiagnose a training run
POST/v1/coach/plancreateCoachPlankey:trainPlan a training programme from a task brief
GET/v1/coach/sessionslistAdviceSessionskey:readList coach sessions
GET/v1/coach/sessions/{session_id}getAdviceSessionkey:readGet a coach session
POST/v1/coach/sessions/{session_id}/feedbacksetAdviceFeedbackkey:writeRate a coach report

plans (5)

The planner (M16) — a frontier model orchestrates the three layers for one task on one device through a closed step vocabulary; it can only request approvals (a human signs them), never opens a session, never names a joint. Recorded as an orchestration run.

plans operations
MethodPathScopeSummary
GET/v1/planslistPlanskey:readList plans
POST/v1/planscreatePlankey:trainPlan a task for a robot (the planner makes its first decision)
GET/v1/plans/{plan_id}getPlankey:readGet a plan (steps, timeline, what it is waiting on)
POST/v1/plans/{plan_id}/advanceadvancePlankey:trainRun one orchestrator tick on a plan (idempotent)
POST/v1/plans/{plan_id}/cancelcancelPlankey:trainCancel a plan

campaigns (9)

Campaigns (C3) — the founder's training loop as hub objects: a task on a robot with a budget, whose rounds lock a spec (one declared change, a hypothesis, gates with predictions), train through createRun, are gated and band-scanned in simulation, get a verdict from their locked gates and a decision. Three rules are enforced in code; only a signed-in person may override one, with a reason.

campaigns operations
MethodPathScopeSummary
GET/v1/campaignslistCampaignskey:readList campaigns
POST/v1/campaignscreateCampaignkey:writeStart a campaign — a task on a robot, with a budget and the three rules
GET/v1/campaigns/{campaign_id}getCampaignkey:readGet a campaign (its rounds, spend, and what waits on a person)
PATCH/v1/campaigns/{campaign_id}updateCampaignkey:writeRename, re-describe, change the budget of, or stop a campaign
POST/v1/campaigns/{campaign_id}/roundscreateRoundkey:trainLock a round's spec and start its training run
POST/v1/campaigns/{campaign_id}/rounds/overridecreateRoundWithOverridesessionStart a round that breaks a rule — a person's decision, with a reason
GET/v1/campaigns/{campaign_id}/rounds/{round_n}getRoundkey:readGet a round — its locked spec, the verdict at a step, the variables, the decisions
POST/v1/campaigns/{campaign_id}/rounds/{round_n}/decisiondecideRoundkey:writeDecide a round — shortlist, iterate, stop the lineage, or done
POST/v1/campaigns/{campaign_id}/rounds/{round_n}/gatesaddRoundGatekey:writeAdd a gate after the lock — shown, never counted

trials (14)

Real-robot trials (C4) — a session of trials on one device, each a checkpoint run under its own M13 approval with a run sheet locked at approval, the log and summary the driver uploads signed with the device key, the operator's notes from a phone, and a person's verdict (promote / iterate / stop) that the campaign's rules read.

trials operations
MethodPathScopeSummary
GET/v1/trial-sessionslistTrialSessionskey:readList real-robot sessions
POST/v1/trial-sessionscreateTrialSessionkey:writePlan a real-robot session — one trial per checkpoint, in bracket order
GET/v1/trial-sessions/{session_id}getTrialSessionkey:readGet a real-robot session — its order, bracket check and trials
POST/v1/trial-sessions/{session_id}/requestsfileTrialRequestskey:writeFile the consent requests of a session's unfiled trials
GET/v1/trialslistTrialskey:readList trials
GET/v1/trials/{trial_id}getTrialkey:readGet a trial — run sheet, approval, log, summary, criteria, notes, verdict
PATCH/v1/trials/{trial_id}/run-sheetupdateTrialRunSheetkey:writeEdit a trial's run sheet before its approval locks it
POST/v1/trials/{trial_id}/log/presignpresignTrialLogkey:writePresigned PUTs for the log files a driver will upload
POST/v1/trials/{trial_id}/loguploadTrialLogkey:writeRecord the log and summary the driver computed on the robot, signed
GET/v1/trials/{trial_id}/seriesgetTrialSerieskey:readThe log as plottable series — tilt at 50 Hz, joints on request
PATCH/v1/trials/{trial_id}/notesputTrialNoteskey:writeSave the operator's notes — a partial autosave
POST/v1/trials/{trial_id}/notes/videospresignTrialVideokey:writeStart a phone video's presigned multipart upload
POST/v1/trials/{trial_id}/notes/videos/{video_id}/completecompleteTrialVideokey:writeFinish a phone video's upload and attach it to the notes
POST/v1/trials/{trial_id}/verdictsetTrialVerdictsessionRecord a person's verdict on a candidate trial (web session only)

workspace (2)

The signed-in caller's workspace (UI-API) — the activity feed (the audit log, filtered to what the caller could already see) and one cheap overview for the workspace rail and the Inbox header.

workspace operations
MethodPathScopeSummary
GET/v1/activitylistActivitykey:readThe activity feed — what happened to what you can see
GET/v1/me/overviewgetMyOverviewkey:readCounts for the workspace rail and the Inbox header

agent (14)

The hub's cloud agent (A1/A2) — a session works toward a goal with the hub's own tools and a sandboxed shell, as a short-lived key scoped below its creator's; spends past a pre-approved budget wait for a person, and everything it does is an append-only event stream.

agent operations
MethodPathScopeSummary
GET/v1/agent/sessionslistAgentSessionskey:readList agent sessions
POST/v1/agent/sessionscreateAgentSessionkey:trainStart an agent session (the hub's cloud agent works toward a goal)
GET/v1/agent/sessions/{session_id}getAgentSessionkey:readGet an agent session (status, spend, what it waits on, pending approvals)
POST/v1/agent/sessions/{session_id}/messagespostAgentMessagekey:trainSend the agent a message (a user turn)
GET/v1/agent/sessions/{session_id}/eventsstreamAgentEventskey:readStream a session's events (SSE, resumable)
POST/v1/agent/sessions/{session_id}/approvals/{approval_id}resolveAgentApprovalkey:trainApprove or deny a spend the agent asked for
POST/v1/agent/sessions/{session_id}/cancelcancelAgentSessionkey:trainCancel an agent session
POST/v1/agent/sessions/{session_id}/endendAgentSessionkey:trainEnd an agent session (done; a reply reopens it)
GET/v1/agent/sessions/{session_id}/planslistAgentPlanskey:readThe plans the agent proposed in this session, newest version first
GET/v1/agent/sessions/{session_id}/plans/{plan_id}getAgentPlankey:readOne version of the session's plan
POST/v1/agent/sessions/{session_id}/plans/{plan_id}/approveapproveAgentPlansessionApprove the agent's plan (a signed-in person only)
GET/v1/agent/sessions/{session_id}/decisionslistAgentDecisionskey:readThe session's decisions — plan, spend, shortlist, handoff
GET/v1/agent/sessions/{session_id}/digestgetAgentDigestkey:read"Since you left" — what happened in the session since the viewer last looked
GET/v1/agent/sessions/{session_id}/objectslistAgentObjectskey:readThe session's objects grouped by state — Needs you, Running, Ready for review, Done

Errors

The response families the operations share. Every error body is RFC 9457 application/problem+json; 429 is an infrastructure response and is not listed per operation.

Shared error responses
ResponseDescriptionBody
Unauthorized

Missing or invalid credentials.

Problemapplication/problem+json
Forbidden

Authenticated but not allowed (visibility, membership or scope).

Problemapplication/problem+json
NotFound

Resource not found (or hidden from the caller).

Problemapplication/problem+json
Conflict

State conflict (duplicate handle/slug, wrong repo kind, terminal job, ...).

Problemapplication/problem+json
ValidationError

Request failed validation.

Problemapplication/problem+json
ServiceUnavailable

A service this endpoint needs is not configured in this deployment (M0's boot guarantee: the API boots with zero secrets, and an endpoint that needs one says so instead of returning a stack trace).

Problemapplication/problem+json

Common schemas

What the shared responses carry. Every other schema is on the page of the first tag whose operations use it.

Problem

object

RFC 9457 problem details. Served as application/problem+json.

Problem fields
FieldTypeDescription
typestring

default "about:blank"

URI reference identifying the problem type.

titlerequiredstring

Short human-readable summary of the problem type.

statusrequiredinteger

≥ 100 · ≤ 599

detailstring | null

Human-readable explanation specific to this occurrence.

instancestring | null

URI reference identifying this occurrence.

errorsarray of FieldError | null

Field-level validation errors (422 responses).

FieldError

object

FieldError fields
FieldTypeDescription
locrequiredarray of string | integer

Path to the offending field (body/query/path segments).

msgrequiredstring
typestring | null

Machine-readable error code.

Every schema (485)