Skip to content
Docs menu

trials

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.

14 operations · 52 schemas

GET /v1/trial-sessions

List real-robot sessions

listTrialSessions · scope key:read

Newest first. No session is public: a session is visible to its owner (the campaign's, else the device's) and the owner org's members; filters narrow within that.

Parameters

listTrialSessions parameters
NameInTypeDescription
campaignquerystring

length ≤ 64

A campaign id or slug.

device_idqueryId
statusqueryTrialSessionStatus
limitqueryinteger

default 20 · ≥ 1 · ≤ 100

Page size.

cursorquerystring

length ≤ 512

Opaque cursor from the previous page's next_cursor.

Responses

listTrialSessions responses
StatusDescriptionBody
200

A page of sessions.

TrialSessionPage
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/trial-sessions

Plan a real-robot session — one trial per checkpoint, in bracket order

createTrialSession · scope key:write

C4. A session is a sequence of trials on one device, each a checkpoint run under its own M13 approval, in an order the hub writes down before anything runs: the control first, the candidates by ascending sim risk (fewer locked gates passed, then fewer seeds upright, runs later), the control again last — the founder's A/B/A bracket (700 → A800 → 700), whose rule is checked once both control runs have a log (TrialSession.bracket). Each trial gets a run sheet drafted from the review — the stages (hang → floor → teleop), gain profile, kd and power scale, the environment, the abort rules, the predictions copied from the round's locked gates with the sim conditions they were measured under, and the criteria the log will be judged against — editable until its approval is issued, and locked then (RunSheet.locked_at; the token carries its digest). With a device_id (or when exactly one of the owner's devices embodies the robot and accepts every trial's contract) the hub files one consent request per trial at once — never an approval (M13). decideRound {shortlist} calls this for the round it shortlists; AG1's agent shortlist files its requests through the same trials. key:write: a plan and requests a person must still approve, one by one.

Request body

application/json · required · TrialSessionCreate

createTrialSession request body
FieldTypeDescription
campaignstring | null

length ≤ 64

A campaign id or slug.

roundinteger | null

≥ 1

The round whose shortlist to trial (with campaign).

candidatesarray of TrialCheckpoint

items ≤ 4

controlsarray of TrialCheckpoint

items ≤ 2

device_idId | null

The device to trial on. Default: the only one of the owner's devices that embodies the robot and accepts every trial's contract; none or several leave the trials unfiled.

minutesinteger

default 10 · ≥ 1 · ≤ 240

Each trial's approval window — the whole run sheet, hang to teleop.

reasonstring | null

length ≤ 1024

Why these checkpoints go to the robot; each consent request carries it.

bracket_tolerance_degnumber

default 1 · > 0 · ≤ 45

How far the two control runs' tilt max may differ for the bracket to hold (default 1.0°, DECISIONS "C4").

Responses

createTrialSession responses
StatusDescriptionBody
201

The session, its trials and their run sheets.

TrialSession
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/trial-sessions/{session_id}

Get a real-robot session — its order, bracket check and trials

getTrialSession · scope key:read

Parameters

getTrialSession parameters
NameInTypeDescription
session_idrequiredpathId

A real-robot session id (tses_...).

Responses

getTrialSession responses
StatusDescriptionBody
200

The session.

TrialSession
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json

POST /v1/trial-sessions/{session_id}/requests

File the consent requests of a session's unfiled trials

fileTrialRequests · scope key:write

For a session created without a device (none of the owner's devices accepted every contract, or several did): names the device and files one M13 consent request per trial that has none, each pinned to the checkpoint's ONNX and its digest and carrying the session's reason. A contract the device does not accept is 409 naming the trial, and nothing is filed. Idempotent: a trial that already has a request is left alone. Never approves anything (M13).

Parameters

fileTrialRequests parameters
NameInTypeDescription
session_idrequiredpathId

A real-robot session id (tses_...).

Request body

application/json · required · TrialRequestsCreate

fileTrialRequests request body
FieldTypeDescription
device_idrequiredId

Responses

fileTrialRequests responses
StatusDescriptionBody
200

The session, with the trials' requests.

TrialSession
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/trials

List trials

listTrials · scope key:read

Newest first, under the session's visibility rule. status=needs_verdict is what the Inbox's "needs your verdict" card reads; approval_id is how a driver finds the trial an approval belongs to.

Parameters

listTrials parameters
NameInTypeDescription
session_idqueryId
campaignquerystring

length ≤ 64

A campaign id or slug.

device_idqueryId
approval_idqueryId
statusqueryTrialStatus
limitqueryinteger

default 20 · ≥ 1 · ≤ 100

Page size.

cursorquerystring

length ≤ 512

Opaque cursor from the previous page's next_cursor.

Responses

listTrials responses
StatusDescriptionBody
200

A page of trials.

TrialPage
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/trials/{trial_id}

Get a trial — run sheet, approval, log, summary, criteria, notes, verdict

getTrial · scope key:read

One real-robot trial as a record. criteria are judged on every read from the uploaded summary against what was written down before the run: the run sheet's criteria (locked with its approval) and the round's locked gates the log can measure, each with the sim measurement beside it; a comparison with the session's control trials is pending until one of them has a log. log.files[].url are presigned GETs (1 h). Invisible is 404.

Parameters

getTrial parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

Responses

getTrial responses
StatusDescriptionBody
200

The trial.

Trial
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json

PATCH /v1/trials/{trial_id}/run-sheet

Edit a trial's run sheet before its approval locks it

updateTrialRunSheet · scope key:write

Partial: a key that is absent is unchanged, and null clears an optional one. Stages, gain profile, kd and power scale, environment, abort rules and criteria may change until the trial's approval is issued; from then on the sheet is what a person approved and this is 409 — "no tuning on site". The approval token carries the locked sheet's digest (run_sheet_sha256), and the driver refuses a sheet that does not hash to it.

Parameters

updateTrialRunSheet parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

Request body

application/json · required · RunSheetUpdate

updateTrialRunSheet request body
FieldTypeDescription
stagesarray of RunSheetStage

items 1–8

gain_profilestring

pattern ^[A-Za-z0-9_.-]{1,64}$

kd_scalenumber

> 0 · ≤ 5

power_scalenumber

> 0 · ≤ 1

environmentRunSheetEnvironment
abort_rulesarray of string

items ≤ 12

criteriaarray of RunSheetCriterion

items ≤ 16

Responses

updateTrialRunSheet responses
StatusDescriptionBody
200

The trial, with the edited run sheet.

Trial
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/trials/{trial_id}/log/presign

Presigned PUTs for the log files a driver will upload

presignTrialLog · scope key:write

The driver's first step after a trial's run stops: one presigned PUT (1 h) per log file, under trials/{trial_id}/log/. Bytes never pass through the API. Allowed only while the trial's approval is running or stopped and no log has been recorded; the upload is not a record until uploadTrialLog names each file's sha256 under the device's signature.

Storage (L0). The declared sizes count toward the trial session owner's storage quota (STORAGE_QUOTA_BYTES, the same 50 GiB as repo files): over it is 413 and no URL is issued.

Parameters

presignTrialLog parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

Request body

application/json · required · TrialLogPresignRequest

presignTrialLog request body
FieldTypeDescription
approval_idrequiredId
filesrequiredarray of object

items 1–8

namerequiredstring

pattern ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

bytesrequiredinteger

≥ 0 · ≤ 268435456

Responses

presignTrialLog responses
StatusDescriptionBody
200

One PUT per file.

TrialLogPresign
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
413

A file is over TRIAL_LOG_MAX_BYTES, or the session owner's storage quota would be exceeded (L0).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/trials/{trial_id}/log

Record the log and summary the driver computed on the robot, signed

uploadTrialLog · scope key:write

The driver's word on what the robot-side command wrote: state: uploaded with each file's sha256, bytes and rows and the summary it computed on the box (tilt mean and max over the log's steady second half, the worst left–right joint asymmetry, per-joint tracking error, the motor temperatures the command printed at stop, battery, falls, what stopped it, the stages it ran), or missing / malformed with the reason — a stated failure, never silence. Signed with the device's own Ed25519 key over the canonical payload (trial_log_payload: approval, device, trial, state, files, summary, stages, detail, ts) and verified against the key registered for the trial's device, exactly like postDeviceEvent. The hub then hashes every uploaded object and refuses (422) a file whose bytes do not match the signed digest, re-derives the log's own numbers (tilt, asymmetry, tracking) from the CSV and stores whether they agree (summary.hub_check). Once only (409 after), while the approval is running or stopped. Audited trial.log.

Parameters

uploadTrialLog parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

Request body

application/json · required · TrialLogUpload

uploadTrialLog request body
FieldTypeDescription
approval_idrequiredId
staterequiredstring

one of uploaded · missing · malformed

filesarray of TrialLogFile

items ≤ 8

summaryobject

The TrialSummary the driver computed (capped at 64 KiB).

detailstring | null

length ≤ 2000

tsrequiredstring

length ≤ 64

The driver's clock, ISO 8601, exactly as signed.

signaturerequiredstring

length 16–128

Responses

uploadTrialLog responses
StatusDescriptionBody
201

The trial, with its log and summary.

Trial
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
413

The summary exceeds the device event cap (64 KiB) or a file its cap.

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

GET /v1/trials/{trial_id}/series

The log as plottable series — tilt at 50 Hz, joints on request

getTrialSeries · scope key:read

Read out of the uploaded log files (every stage, on the trial's own clock, with the stage boundaries) and decimated like getEpisodeSeries: min/max per bucket, so a one-frame tilt spike survives. channels picks what to return: tilt (degrees, from the logged gravity vector — the founder's acos(−g_z)), q:<joint>, tgt:<joint>, act:<joint>; default tilt. 409 while no log is recorded.

Parameters

getTrialSeries parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

channelsquerystring

length ≤ 2000

Comma-separated channel names (default tilt).

max_pointsqueryinteger

default 2000 · ≥ 16 · ≤ 20000

Responses

getTrialSeries responses
StatusDescriptionBody
200

The series.

TrialSeries
401

Missing or invalid credentials.

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json

PATCH /v1/trials/{trial_id}/notes

Save the operator's notes — a partial autosave

putTrialNotes · scope key:write

The phone form's autosave: a key that is absent is unchanged, null clears it, and the response carries filed_at (the time of this save) so the form can say "notes saved 14:33". Fields are taps — stability 1–5, drift, four toggles, which motors were hot — plus free text kept in the language it was written in (lang, detected when absent). A machine translation (translation), when the hub has one, is labelled as one and never replaces the text; this hub fills it from recorded fixtures only (no live model call). The first save is audited trial.notes; later saves update the same record. Notes may be filed from the moment the trial is approved, and until its verdict.

Parameters

putTrialNotes parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

Request body

application/json · required · TrialNotesUpdate

putTrialNotes request body
FieldTypeDescription
stabilityinteger | null

≥ 1 · ≤ 5

driftTrialNotesDrift | null
drift_whenstring | null

length ≤ 80

feet_lift_cleanboolean | null
landing_noiseboolean | null
motors_hotTrialMotorsHot | null
fellboolean | null
textstring | null

length ≤ 8000

langstring | null

length ≤ 16

Responses

putTrialNotes responses
StatusDescriptionBody
200

The notes as saved.

TrialNotes
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/trials/{trial_id}/notes/videos

Start a phone video's presigned multipart upload

presignTrialVideo · scope key:write

One multipart upload under trials/{trial_id}/videos/, straight from the phone to object storage (M3's presigned multipart, 8 MiB parts, 1 h URLs); completeTrialVideo takes the part list from storage and attaches the video to the notes. Up to 2 GiB and eight videos a trial.

Parameters

presignTrialVideo parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

Request body

application/json · required · TrialVideoCreate

presignTrialVideo request body
FieldTypeDescription
filenamerequiredstring

length 1–128

bytesrequiredinteger

≥ 1

content_typestring | null

length ≤ 64

duration_snumber | null

≥ 0

Responses

presignTrialVideo responses
StatusDescriptionBody
201

The upload, with a presigned PUT per part.

TrialVideoUpload
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
413

Larger than 2 GiB, or the session owner's storage quota would be exceeded (L0: trial videos count toward it).

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

POST /v1/trials/{trial_id}/notes/videos/{video_id}/complete

Finish a phone video's upload and attach it to the notes

completeTrialVideo · scope key:write

Completes the multipart upload from the parts object storage holds (the phone need not keep ETags), checks the stored size against the declared one, and adds the video to TrialNotes.videos. Audited trial.video.

Parameters

completeTrialVideo parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

video_idrequiredpathId

Request body

application/json · TrialVideoComplete

completeTrialVideo request body
FieldTypeDescription
duration_snumber | null

≥ 0

Responses

completeTrialVideo responses
StatusDescriptionBody
200

The notes, with the video.

TrialNotes
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json

POST /v1/trials/{trial_id}/verdict

Record a person's verdict on a candidate trial (web session only)

setTrialVerdict · scope session

Session only — a person decides what a real robot showed; no API key of any scope, and so no agent, can (403). Three options, none the default, each with a reason: promote — this checkpoint becomes the campaign's policy on the robot (Campaign.policy_on_robot, and the baseline the next session's criteria are drafted from); iterate — back to simulation: the checkpoint stays a valid parent, and an agent session attached to the campaign is woken with the verdict, the notes and the summary to draft the next round from (a person still approves it); stop — this checkpoint's lineage ends the way a FAIL does: no round may resume from it (rule.fail_ends_lineage), and iterating from it is refused. Only a candidate trial takes a verdict (a control is measured, not judged), only once, and only after its run started. Audited trial.verdict, with a sentence in listActivity.

Parameters

setTrialVerdict parameters
NameInTypeDescription
trial_idrequiredpathId

A trial id (trial_...).

Request body

application/json · required · TrialVerdictCreate

setTrialVerdict request body
FieldTypeDescription
actionrequiredTrialVerdictAction
reasonrequiredstring

length 3–1000

Responses

setTrialVerdict responses
StatusDescriptionBody
200

The trial, with its verdict.

Trial
401

Missing or invalid credentials.

Problemapplication/problem+json
403

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

Problemapplication/problem+json
404

Resource not found (or hidden from the caller).

Problemapplication/problem+json
409

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

Problemapplication/problem+json
422

Request failed validation.

Problemapplication/problem+json

Schemas (52)

The schemas these operations reach before any other tag’s do. A type that links elsewhere is rendered on that tag’s page.

TrialSessionPage

object

TrialSessionPage fields
FieldTypeDescription
itemsrequiredarray of TrialSession
next_cursorrequiredstring | null

TrialSessionCreate

object

Either a campaign round (campaign + round), whose shortlist supplies the candidates and controls, or explicit candidates and controls (checkpoints the caller can read). One control is run first and again last; two controls are run first and last.

TrialSessionCreate fields
FieldTypeDescription
campaignstring | null

length ≤ 64

A campaign id or slug.

roundinteger | null

≥ 1

The round whose shortlist to trial (with campaign).

candidatesarray of TrialCheckpoint

items ≤ 4

controlsarray of TrialCheckpoint

items ≤ 2

device_idId | null

The device to trial on. Default: the only one of the owner's devices that embodies the robot and accepts every trial's contract; none or several leave the trials unfiled.

minutesinteger

default 10 · ≥ 1 · ≤ 240

Each trial's approval window — the whole run sheet, hang to teleop.

reasonstring | null

length ≤ 1024

Why these checkpoints go to the robot; each consent request carries it.

bracket_tolerance_degnumber

default 1 · > 0 · ≤ 45

How far the two control runs' tilt max may differ for the bracket to hold (default 1.0°, DECISIONS "C4").

TrialSession

object

TrialSession fields
FieldTypeDescription
idrequiredId
ownerrequiredRepoOwner
campaignTrialCampaignRef | null
roundTrialRoundRef | null
robotRepoRef | null
deviceTrialDeviceRef | null
statusrequiredTrialSessionStatus
orderrequiredarray of TrialRef

The trials in the order they run.

order_rulestring

How the order was written — "control first and last; candidates by sim risk, lowest first".

bracketrequiredTrialBracket
minutesrequiredinteger
reasonstring | null
unfiled_reasonstring | null

Why trials are unfiled — no device named and none or several could be chosen.

created_byUserPublic | null
created_atrequiredstring (date-time)
trialsarray of Trial

Every trial in full (createTrialSession, getTrialSession; omitted from list pages).

TrialRequestsCreate

object

TrialRequestsCreate fields
FieldTypeDescription
device_idrequiredId

TrialPage

object

TrialPage fields
FieldTypeDescription
itemsrequiredarray of Trial
next_cursorrequiredstring | null

Trial

object

Trial fields
FieldTypeDescription
idrequiredId
session_idrequiredId
indexrequiredinteger

≥ 1

This trial's place in the session's order (1-based).

ofrequiredinteger

How many trials the session has.

rolerequiredTrialRole
labelrequiredstring
statusrequiredTrialStatus
campaignTrialCampaignRef | null
roundTrialRoundRef | null
model_reporequiredRepoRef
run_idstring | null
checkpoint_stepinteger | null
onnx_pathstring | null
deviceTrialDeviceRef | null
request_idstring | null
approvalApproval | null

The approval the trial rides on — the consent record, linked, never replaced.

withdrawn_reasonstring | null
refused_reasonstring | null

The device's machine reason when it refused the run.

simTrialSim | null
run_sheetrequiredRunSheet
logrequiredTrialLog
summaryTrialSummary | null
criteriarequiredarray of TrialCriterion
notesTrialNotes | null
verdictTrialVerdict | null
sessionTrialSession | null

The session without its full trials (getTrial only) — the strip and the bracket.

created_atrequiredstring (date-time)

RunSheetUpdate

object

RunSheetUpdate fields
FieldTypeDescription
stagesarray of RunSheetStage

items 1–8

gain_profilestring

pattern ^[A-Za-z0-9_.-]{1,64}$

kd_scalenumber

> 0 · ≤ 5

power_scalenumber

> 0 · ≤ 1

environmentRunSheetEnvironment
abort_rulesarray of string

items ≤ 12

criteriaarray of RunSheetCriterion

items ≤ 16

TrialLogPresignRequest

object

TrialLogPresignRequest fields
FieldTypeDescription
approval_idrequiredId
filesrequiredarray of object

items 1–8

namerequiredstring

pattern ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

bytesrequiredinteger

≥ 0 · ≤ 268435456

TrialLogPresign

object

TrialLogPresign fields
FieldTypeDescription
filesrequiredarray of object
namerequiredstring
urlrequiredstring (uri)
expires_atrequiredstring (date-time)

TrialLogUpload

object

Signed like a device event: signature is the device key's Ed25519 signature (base64url) over the canonical JSON of {approval_id, device_id, trial_id, kind: "trial_log", state, files: [{name, stage, sha256, bytes, rows}], summary, detail, ts} — ts exactly as sent.

TrialLogUpload fields
FieldTypeDescription
approval_idrequiredId
staterequiredstring

one of uploaded · missing · malformed

filesarray of TrialLogFile

items ≤ 8

summaryobject

The TrialSummary the driver computed (capped at 64 KiB).

detailstring | null

length ≤ 2000

tsrequiredstring

length ≤ 64

The driver's clock, ISO 8601, exactly as signed.

signaturerequiredstring

length 16–128

TrialSeries

object

TrialSeries fields
FieldTypeDescription
trial_idrequiredId
rowsinteger | null
rate_hznumber | null
duration_snumber | null
sampled_pointsrequiredinteger
downsamplerequiredstring

one of none · minmax

channelsrequiredarray of TrialChannel
pointsrequiredarray of EpisodeSeriesPoint
stagesrequiredarray of TrialSeriesStage
baselineobject | null

The tilt-max criterion's threshold, drawn as a line.

namerequiredstring
valuerequirednumber
warningsrequiredarray of string

TrialNotesUpdate

object

A partial save — absent keys are unchanged, null clears.

TrialNotesUpdate fields
FieldTypeDescription
stabilityinteger | null

≥ 1 · ≤ 5

driftTrialNotesDrift | null
drift_whenstring | null

length ≤ 80

feet_lift_cleanboolean | null
landing_noiseboolean | null
motors_hotTrialMotorsHot | null
fellboolean | null
textstring | null

length ≤ 8000

langstring | null

length ≤ 16

TrialNotes

object

TrialNotes fields
FieldTypeDescription
trial_idrequiredId
stabilityinteger | null

≥ 1 · ≤ 5

1 fell or nearly, 5 like the best run so far.

driftTrialNotesDrift | null
drift_whenstring | null

length ≤ 80

When it drifted, e.g. "while standing".

feet_lift_cleanboolean | null
landing_noiseboolean | null
motors_hotTrialMotorsHot | null
fellboolean | null
textstring | null

length ≤ 8000

langstring | null

length ≤ 16

The text's language as written (zh, en, …), detected when not given.

translationTrialTranslation | null
videosarray of TrialVideo
filed_atstring (date-time) | null (date-time)

The last save.

first_filed_atstring (date-time) | null (date-time)
filed_byUserPublic | null
filed_viastring | null

one of session · api_key

TrialVideoCreate

object

TrialVideoCreate fields
FieldTypeDescription
filenamerequiredstring

length 1–128

bytesrequiredinteger

≥ 1

content_typestring | null

length ≤ 64

duration_snumber | null

≥ 0

TrialVideoUpload

object

TrialVideoUpload fields
FieldTypeDescription
video_idrequiredId
part_sizerequiredinteger
partsrequiredarray of object
part_numberrequiredinteger
urlrequiredstring (uri)
expires_atrequiredstring (date-time)

TrialVideoComplete

object

TrialVideoComplete fields
FieldTypeDescription
duration_snumber | null

≥ 0

TrialVerdictCreate

object

TrialVerdictCreate fields
FieldTypeDescription
actionrequiredTrialVerdictAction
reasonrequiredstring

length 3–1000

TrialCheckpoint

object

A checkpoint to trial — checkpoints/step_<step>/ of a run's output model repo.

TrialCheckpoint fields
FieldTypeDescription
run_idrequiredId
steprequiredinteger

≥ 0

TrialCampaignRef

object

TrialCampaignRef fields
FieldTypeDescription
idrequiredId
slugrequiredstring
namerequiredstring

TrialRoundRef

object

TrialRoundRef fields
FieldTypeDescription
idrequiredId
nrequiredinteger
namerequiredstring

TrialDeviceRef

object

TrialDeviceRef fields
FieldTypeDescription
idrequiredId
namerequiredstring
adapterrequiredstring
adapter_infoDeviceAdapterInfo | null

TrialBracket

object

The A/B/A bracket check, the founder's rule: run the control first and last, and when the two control runs differ by more than the tolerance the session was polluted (battery, floor, temperature) and its A/B decides nothing. holds is null until both control runs have a log, or when the session has no second control run.

TrialBracket fields
FieldTypeDescription
metricrequiredstring

one of tilt_max_deg

tolerancerequirednumber
controlsarray of object
trial_idrequiredId
indexrequiredinteger
valuenumber | null
deltanumber | null
holdsrequiredboolean | null
sentencerequiredstring

One line the page prints, e.g. "The two 700 runs agree within 0.35°…".

TrialSim

object

The checkpoint's verdict in simulation, from its round's locked gates.

TrialSim fields
FieldTypeDescription
verdictstring | null
gates_passedinteger | null
gates_totalinteger | null
alivestring | null

RunSheet

object

What will be done on the robot, written before anything runs: drafted from the review when the trial is planned, editable until its approval is issued, locked then (locked_at = the approval's issued_at; digest is what the token's run_sheet_sha256 binds). "No tuning on site" is the rule, not a field.

RunSheet fields
FieldTypeDescription
stagesrequiredarray of RunSheetStage

items 1–8

gain_profilerequiredstring

pattern ^[A-Za-z0-9_.-]{1,64}$

The robot's PD gain profile, by the name its own config uses (rl_default).

kd_scalerequirednumber

> 0 · ≤ 5

power_scalerequirednumber

> 0 · ≤ 1

environmentrequiredRunSheetEnvironment
abort_rulesrequiredarray of string

items ≤ 12

criteriarequiredarray of RunSheetCriterion

items ≤ 16

baselineRunSheetBaseline | null
predictedRunSheetPredicted | null
locked_atread-onlystring (date-time) | null (date-time)
locked_byread-onlyUserPublic | null
digestrequiredread-onlystring

sha256 of the canonical sheet (stages without their status, settings, environment, abort rules, criteria).

TrialLog

object

TrialLog fields
FieldTypeDescription
staterequiredTrialLogState
filesarray of TrialLogFile
rowsinteger | null
rate_hznumber | null
columnsarray of string
formatstring | null

deploy_policy_csv — t,gx,gy,gz,q_*,tgt_*,act_* (the founder's tools/policy_io.summarize), plus any extra columns.

detailstring | null

The driver's stated reason for missing / malformed.

uploaded_atstring (date-time) | null (date-time)
uploaded_bystring | null

The device that signed it.

signaturestring | null

The device's Ed25519 signature (base64url) over trial_log_payload.

signedboolean

True when the signature verified against the device's registered key (always, for a stored log).

TrialSummary

object

Computed on the robot box by the driver from the log the robot-side command wrote, with the founder's own formulas (tools/policy_io.summarize, docs/DECISIONS.md "C4"): tilt = acos(−g_z) over the judged stage's steady second half; a pair's asymmetry = |mean(l) + mean(r)| there (his mirror convention, l ≈ −r); tracking error = mean(target − measured) per joint; the motor temperatures his deploy script prints at stop; falls when its tilt protection fired. Numbers the log cannot give are null, never invented.

TrialSummary fields
FieldTypeDescription
judged_stagestring | null
windowstring

second_half — the founder's steady-state rule.

rowsinteger | null
duration_snumber | null
rate_hznumber | null

Rows over logged time.

loop_hznumber | null

The control rate the command itself reported, else rate_hz.

stopped_bystring | null

operator (Ctrl+C or the quit key), window (the approval ran out), duration, tilt_protection, imu_dropout, bus_fault, error, unknown.

stopped_detailstring | null
fallsinteger | null
tilt_mean_degnumber | null
tilt_max_degnumber | null
asym_maxTrialAsymmetry | null
asymmetryarray of TrialAsymmetry
tracking_error_radarray of TrialPair
temps_carray of TrialPair
temps_sourcestring | null

Where the temperatures came from — stdout (the table the command printed at stop), csv, or null.

battery_vTrialBattery | null
stagesarray of TrialStageResult
transcript_tailarray of string

items ≤ 40

The last lines the command printed.

hub_checkTrialHubCheck | null

TrialCriterion

object

TrialCriterion fields
FieldTypeDescription
namerequiredstring
metricrequiredRunSheetCriterionMetric
oprequiredRunSheetCriterionOp
thresholdnumber | null

The threshold used — for <=control, the controls' mean at read time.

referencestring | null
jointstring | null
measurednumber | null
measured_textstring | null

As printed — "2.4° ankle_pitch", "+0.199 / −0.203 rad".

sim_valuenumber | null
verdictrequiredTrialCriterionVerdict
sourcerequiredstring

one of run_sheet · round_gate

TrialVerdict

object

TrialVerdict fields
FieldTypeDescription
actionrequiredTrialVerdictAction
reasonrequiredstring
decided_byUserPublic | null
decided_atrequiredstring (date-time)
effectstring

What the verdict did — one sentence (the campaign's policy, a lineage ended, an agent woken).

RunSheetStage

object

One stage of the run sheet, as a person reads it and as the driver maps it onto a command configured on the robot box (the hub sends values, never a command line). duration_s null runs until the operator stops it (teleop). status comes from the driver's signed log upload.

RunSheetStage fields
FieldTypeDescription
namerequiredstring

pattern ^[a-z][a-z0-9_-]{0,31}$

hang, floor, teleop, or a name the box's config knows.

labelstring | null

length ≤ 80

commandRunSheetCommand | null
imuboolean

default true

False runs without the IMU (hanging, feet off the floor).

teleopRunSheetTeleop | null
duration_snumber | null

> 0 · ≤ 3600

notestring | null

length ≤ 200

What must be true, e.g. "feet off the floor", "someone within reach".

judgedboolean

default false

The stage whose log the headline summary is computed on (default the last).

statusread-onlystring | null

one of done · stopped · aborted · failed · skipped · not_configured

elapsed_sread-onlynumber | null

RunSheetEnvironment

object

RunSheetEnvironment fields
FieldTypeDescription
floorstring | null

length ≤ 120

The floor's material, as the operator names it.

mu_estimatenumber | null

≥ 0 · ≤ 3

calibration_commitstring | null

length ≤ 64

battery_vnumber | null

≥ 0 · ≤ 1000

The battery at the start, as the operator read it.

notesstring | null

length ≤ 500

RunSheetCriterion

object

RunSheetCriterion fields
FieldTypeDescription
namerequiredstring

length 1–120

metricrequiredRunSheetCriterionMetric
oprequiredRunSheetCriterionOp
thresholdnumber | null
jointstring | null

length ≤ 64

tracking_error_rad: the joint without its side, e.g. hip_roll.

sim_valuenumber | null

The value measured in simulation (as_in_sim), or shown beside the verdict.

tolerancenumber | null

≥ 0

as_in_sim: how far from sim_value still reads as in sim (default 25 %).

referencestring | null

length ≤ 120

Where the threshold was written down, e.g. "s1e baseline 08-08", "round gate".

TrialLogFile

object

TrialLogFile fields
FieldTypeDescription
namerequiredstring

pattern ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

The file's name on the box, e.g. stage-3-teleop.csv.

stagestring | null

length ≤ 32

sha256requiredSha256
bytesrequiredinteger

≥ 0

rowsinteger | null

≥ 0

urlread-onlystring (uri) | null (uri)

A presigned GET (1 h), on read.

TrialChannel

object

TrialChannel fields
FieldTypeDescription
namerequiredstring
unitrequiredstring

one of deg · rad

TrialSeriesStage

object

TrialSeriesStage fields
FieldTypeDescription
namerequiredstring
start_srequirednumber
end_snumber | null

TrialNotesDrift

string

one of none · left · right · forward · back · turning

TrialMotorsHot

object

TrialMotorsHot fields
FieldTypeDescription
hotrequiredboolean
jointsarray of string

items ≤ 24

Which, as the operator felt them, e.g. hip_roll.

TrialTranslation

object

A machine translation of the notes' text, labelled as one and never replacing it. This hub fills it only from recorded fixtures (TRIAL_TRANSLATION=recorded); no live model call is made.

TrialTranslation fields
FieldTypeDescription
textrequiredstring
langrequiredstring
sourcerequiredstring

one of recorded · machine

modelstring | null

TrialVideo

object

TrialVideo fields
FieldTypeDescription
idrequiredId
filenamerequiredstring
bytesrequiredinteger
content_typestring | null
duration_snumber | null
staterequiredstring

one of uploading · uploaded

urlread-onlystring (uri) | null (uri)

A presigned GET (1 h) once uploaded.

uploaded_atstring (date-time) | null (date-time)

RunSheetBaseline

object

The real-robot numbers a <=control criterion compares against when the campaign has a promoted policy: that trial's own summary.

RunSheetBaseline fields
FieldTypeDescription
trial_idrequiredId
labelrequiredstring
tilt_mean_degnumber | null
tilt_max_degnumber | null
asym_max_degnumber | null

RunSheetPredicted

object

RunSheetPredicted fields
FieldTypeDescription
linesrequiredarray of RunSheetPrediction
batterystring | null

The sim battery the lines were measured on.

sim_power_scalenumber | null
sim_kd_scalenumber | null
caveatstring | null

Computed: e.g. "sim numbers are at power 1.0; this trial runs 0.8".

TrialLogState

string

one of awaiting · uploaded · missing · malformed

awaiting — the run has not ended or the driver has not reported; uploaded — files and a summary, signed; missing — the driver found no log where the box's config said the command would write one; malformed — it found one it could not read.

TrialAsymmetry

object

TrialAsymmetry fields
FieldTypeDescription
jointrequiredstring

The pair without its side, e.g. ankle_pitch.

degrequirednumber

TrialPair

object

A left / right pair of one joint.

TrialPair fields
FieldTypeDescription
jointrequiredstring
leftnumber | null
rightnumber | null

TrialBattery

object

TrialBattery fields
FieldTypeDescription
startnumber | null
endnumber | null

TrialStageResult

object

TrialStageResult fields
FieldTypeDescription
namerequiredstring
statusrequiredstring

one of done · stopped · aborted · failed · skipped · not_configured

start_snumber | null

Seconds from the trial's start (the first stage's launch).

end_snumber | null
rowsinteger | null
returncodeinteger | null
stopped_bystring | null
detailstring | null

TrialHubCheck

object

The hub re-derived the log's own numbers from the uploaded CSV.

TrialHubCheck fields
FieldTypeDescription
agreesrequiredboolean
differencesarray of string

RunSheetCriterionMetric

string

one of tilt_mean_deg · tilt_max_deg · asym_max_deg · falls · tracking_error_rad · loop_hz · temp_max_c

What the log measures: tilt_mean_deg, tilt_max_deg (over the judged stage's steady second half), asym_max_deg (the worst left–right pair), falls, tracking_error_rad (|mean target − measured| of joint, both sides), loop_hz, temp_max_c.

RunSheetCriterionOp

string

one of <= · < · >= · > · == · <=control · as_in_sim

<= < >= > == against threshold; <=control against the mean of the session's control trials (or the campaign's promoted baseline, baseline); as_in_sim — within tolerance of sim_value, reported as as_in_sim / differs_from_sim, never pass/fail.

TrialCriterionVerdict

string

one of PASS · FAIL · as_in_sim · differs_from_sim · pending · unmeasured

PASS / FAIL against a threshold; as_in_sim / differs_from_sim for a comparison with simulation (never a pass); pending — the control it compares with has no log yet; unmeasured — the log does not carry the metric.

RunSheetCommand

object

RunSheetCommand fields
FieldTypeDescription
vxrequirednumber

≥ -2 · ≤ 2

vyrequirednumber

≥ -2 · ≤ 2

wzrequirednumber

≥ -3 · ≤ 3

RunSheetTeleop

object

RunSheetTeleop fields
FieldTypeDescription
speedrequirednumber

≥ 0 · ≤ 2

W/S, m/s.

turnrequirednumber

≥ 0 · ≤ 3

Q/E, rad/s.

siderequirednumber

≥ 0 · ≤ 2

A/D, m/s.

hold_srequirednumber

> 0 · ≤ 10

How long one key press holds its command.

RunSheetPrediction

object

RunSheetPrediction fields
FieldTypeDescription
gaterequiredstring
predictedstring | null

As written when the round's spec was locked.

measured_in_simstring | null

The value the round measured at this checkpoint.

verdictstring | null