Skip to content
Euler Docs

API reference

The hosted API is at https://api.euler.sudotank.com. It serves its own schema and interactive explorer:

https://api.euler.sudotank.com/openapi.json
https://api.euler.sudotank.com/docs

The versioned contract is committed at openapi/euler.openapi.json. Generated clients live in sdks/typescript and sdks/python; release tags publish them only when the repository has npm and PyPI tokens configured.

This page maps the surfaces by area. It is a map, not a substitute for the schema: request and response shapes come from openapi.json.

Conventions

export EULER_BASE_URL="https://api.euler.sudotank.com"
export EULER_TOKEN="…"
curl -fsS -H "Authorization: Bearer $EULER_TOKEN" "$EULER_BASE_URL/v1/projects"

Health

MethodPath
GET/healthz
GET/readyz
GET/openapi.json

Tenancy, identity and access

MethodPath
POST · GET/v1/tenants
POST/v1/login
POST/v1/signup
POST · GET/v1/users
PATCH/v1/users/{email}
POST · GET/v1/invites
POST/v1/invites/{invite_id}/resend
POST/v1/invites/{invite_id}/revoke
GET/v1/invites/lookup
POST/v1/invites/accept
POST · GET/v1/tokens
POST/v1/tokens/refresh
GET/v1/audit
POST/v1/secrets/seal

Workspaces and projects

MethodPath
GET/v1/use-cases
POST · GET/v1/workspaces
PUT/v1/workspaces/{workspace_id}/use-case
POST · GET/v1/projects
GET · DELETE/v1/projects/{project_id}
PUT/v1/projects/{project_id}/name
PUT/v1/projects/{project_id}/workspace
PUT/v1/projects/{project_id}/data-kind
PUT/v1/projects/{project_id}/target-profile
GET/v1/target-profiles
GET/v1/source-formats

Sources, uploads and runs

MethodPath
POST · GET/v1/projects/{project_id}/sources
POST/v1/projects/{project_id}/sources/upload
PUT/v1/projects/{project_id}/sources/{source_id}/name
POST/v1/projects/{project_id}/sources/{source_id}/test-connection
DELETE/v1/projects/{project_id}/sources/{source_id}
POST/v1/projects/{project_id}/sources/{source_id}/transfer
GET · PUT/v1/projects/{project_id}/ingest/settings
POST/v1/projects/{project_id}/uploads
GET/v1/projects/{project_id}/uploads/{upload_id}
PUT/v1/projects/{project_id}/uploads/{upload_id}/parts/{index}
POST/v1/projects/{project_id}/uploads/{upload_id}/complete
PUT/v1/projects/{project_id}/uploads/{upload_id}/artifact
POST · GET/v1/projects/{project_id}/runs
POST/v1/projects/{project_id}/runs/{run_id}/cancel
POST · GET/v1/projects/{project_id}/runs/{run_id}/actions
GET/v1/projects/{project_id}/runs/{run_id}/checkpoints
POST/v1/projects/{project_id}/runs/{run_id}/checkpoints/resolve
POST/v1/projects/{project_id}/runs/{run_id}/ask
POST/v1/projects/{project_id}/command

Annotation

See annotation layers, pipeline settings, annotation jobs and the automated review pass.

MethodPathNotes
GET · PUT/v1/projects/{project_id}/annotation/settingsResolved layer catalog; write modes, per-layer config, model choice and presets
PUT/v1/workspaces/{workspace_id}/annotation/settingsWorkspace defaults
GET/v1/projects/{project_id}/annotation/statusWhat actually ran, per layer
GET/v1/projects/{project_id}/annotation/coveragePer-layer, per-kind coverage and quality; ?layer=, ?kind=
POST · GET/v1/projects/{project_id}/annotation/jobsEnqueue (202) and list. 409 already_produced unless force: true
GET/v1/projects/{project_id}/annotation/jobs/streamSSE progress feed
GET/v1/projects/{project_id}/annotation/jobs/{job_id}One job
POST/v1/projects/{project_id}/annotation/jobs/{job_id}/cancelCancel from queued or running
GET · PUT/v1/projects/{project_id}/ontology/summaryObserved classes with property distributions, joined against the declared ontology; rename, merge and declared-class edits

Re-derivations from stored data (no GPU, no spend; send a few episodes per call):

MethodPath
POST/v1/projects/{project_id}/layers/threed/reattach
POST/v1/projects/{project_id}/layers/hand_pose/wearer-filter
POST/v1/projects/{project_id}/layers/tracking/consolidate
POST/v1/projects/{project_id}/media/overlays/purge

annotation_review is a valid layer_id on the jobs endpoint and is not an annotation-catalog layer; it grades what the other layers produced.

Synchronous per-episode annotation surfaces remain available alongside the queue:

MethodPath
POST/v1/projects/{project_id}/perception
PATCH/v1/projects/{project_id}/episodes/{episode_id}/annotation
PUT/v1/projects/{project_id}/episodes/{episode_id}/labels
POST/v1/projects/{project_id}/episodes/{episode_id}/labels/agent
POST · PUT/v1/projects/{project_id}/episodes/{episode_id}/dense-text
POST/v1/projects/{project_id}/episodes/{episode_id}/video/hand-pose
POST/v1/projects/{project_id}/episodes/{episode_id}/video/track
POST · PUT/v1/projects/{project_id}/episodes/{episode_id}/video/subtasks
PUT/v1/projects/{project_id}/episodes/{episode_id}/video/tracks
POST/v1/projects/{project_id}/episodes/{episode_id}/video-quality
PUT/v1/projects/{project_id}/ontology
GET · PUT/v1/workspaces/{workspace_id}/label-ontology

Readiness, utility and certification

See readiness and data utility.

MethodPath
GET · PUT/v1/projects/{project_id}/readiness/settings
POST/v1/projects/{project_id}/readiness/remeasure
POST/v1/projects/{project_id}/readiness/rescore
GET/v1/projects/{project_id}/utility
POST/v1/projects/{project_id}/ablation
GET/v1/projects/{project_id}/distribution-gap
GET/v1/projects/{project_id}/target-readiness
GET/v1/projects/{project_id}/data-strategy
GET/v1/projects/{project_id}/vision-audit
GET · POST/v1/projects/{project_id}/certification/policies
GET/v1/projects/{project_id}/certification/report
GET/v1/projects/{project_id}/certification/report.html
POST/v1/projects/{project_id}/certification/export
POST/v1/projects/{project_id}/certification/import
POST/v1/projects/{project_id}/certification/audits

Episodes, review and media

MethodPath
GET/v1/projects/{project_id}/episodes (?fields=summary&page=&page_size=)
GET/v1/projects/{project_id}/episodes/{episode_id}
POST/v1/projects/{project_id}/episodes/{episode_id}/decision
POST/v1/projects/{project_id}/review/reroute
GET/v1/projects/{project_id}/episodes/{episode_id}/playback
GET/v1/projects/{project_id}/episodes/{episode_id}/media
POST/v1/projects/{project_id}/episodes/{episode_id}/media-token
GET/v1/projects/{project_id}/episodes/{episode_id}/media-stream

Paging episodes

The plain list returns every episode in full. For anything larger than a handful, ask for slim rows a page at a time and fetch one episode in full when you need it:

curl -fsS -H "Authorization: Bearer $EULER_TOKEN" \
  "$EULER_BASE_URL/v1/projects/$PROJECT/episodes?fields=summary&page=1&page_size=100"
curl -fsS -H "Authorization: Bearer $EULER_TOKEN" \
  "$EULER_BASE_URL/v1/projects/$PROJECT/episodes/$EPISODE"

A summary page carries total and pages. Each row has the episode id, session id, start, end and duration, frame rate and count, task, a short caption, data kind, review decision, readiness score, flags, the worst certificate status and the rules behind it, counts (labels, tracks, sub-tasks, dense actions, hand and body tracks, cameras) and the layers with stored output. page_size defaults to 50 and is at most 500. Episode ids may contain a slash; send them as they are.

Review surface

The routes the review screen reads. Every time is in the episode’s stored source-clock seconds, the same clock as every annotation. Each data route has a signed twin (telemetry-stream, signals-stream, frame-stream, artifact-stream) that takes ?token= from POST .../media-token instead of a header, for an image tag or a canvas.

MethodPathReturns
GET/v1/projects/{project_id}/episodes/{episode_id}/telemetrythe camera’s sensor streams, bucketed
GET/v1/projects/{project_id}/episodes/{episode_id}/signalsseries derived from the annotations, plus bands and markers
GET/v1/projects/{project_id}/episodes/{episode_id}/frameone JPEG of the clean clip
GET · HEAD/v1/projects/{project_id}/episodes/{episode_id}/layers/{layer_id}/artifacta layer’s stored file; for threed, ?part= returns JSON
GET/v1/projects/{project_id}/episodes/{episode_id}/threed/timelinethe 3D layer keyed by time
GET/v1/projects/{project_id}/episodes/{episode_id}/threed/keyframes/{name}one keyframe point cloud
E="$EULER_BASE_URL/v1/projects/$PROJECT/episodes/$EPISODE"
curl -fsS -H "Authorization: Bearer $EULER_TOKEN" "$E/telemetry?streams=ACCL,GYRO,GRAV,CORI&points=1200"
curl -fsS -H "Authorization: Bearer $EULER_TOKEN" "$E/signals?points=600&t0=20&t1=50"
curl -fsS -o frame.jpg -H "Authorization: Bearer $EULER_TOKEN" "$E/frame?t=42.5&w=640"
curl -fsS -H "Authorization: Bearer $EULER_TOKEN" "$E/layers/threed/artifact?part=trajectory"

Telemetry. streams defaults to ACCL,GYRO,GRAV,CORI (accelerometer, gyroscope, gravity, camera orientation); the camera may also record ISOE, SHUT and YAVG (exposure). points is 1200 by default (10 to 5000); t0/t1 zoom into a window. Each stream is {name, columns, units, rate_hz, n_raw, bucket_s, t, min, max, mean}, where min/max/mean map each column to one value per bucket, so a one-sample spike survives. Empty buckets are left out, never zero-filled. derived adds gyro_mag, accel_mag, tilt_deg and yaw_deg/pitch_deg/roll_deg. withheld names streams that are never served (location and face); missing names requested streams the recording does not have. No telemetry at all is a 404 with the reason.

Signals. The same block shape under streams: hand_presence_left/right, hand_speed_left/right, object_count, head_speed_mps (estimated) and head_angular_speed_dps. bands are sub-task, action and flagged spans (kind, start, end, label, and the check and severity for a flag); markers are instants (flags, depth keyframes).

Frame. t in stored seconds (422 outside the episode), w from 64 to 1280 (default 320). Returns image/jpeg, cached; fetch it as a file, not as JSON.

3D parts (?part= on the threed artifact):

partReturns
trajectorycamera poses (t, xyz, quat, conf), the smoothed path with speed and turn rate, and path_length_m raw and smoothed
hands_3dper instant, a hand’s 21 joints with a confidence; experimental
keyframesper depth keyframe: time, cloud name, intrinsics used, and a note on depth scale
objectsobject-track centres placed in 3D (after a 3D rebuild)

The SDKs expose these as get_episode, episode_telemetry, episode_signals, episode_frame and episode_layer_artifact. Query parameters are not yet arguments of those methods; for paging, windows or parts use the client’s request with the full path:

rows = client.request("GET", f"/v1/projects/{project}/episodes?fields=summary&page=1&page_size=100")
traj = client.request("GET", f"/v1/projects/{project}/episodes/{episode}/layers/threed/artifact?part=trajectory")

Search, slices and curation

See curation and the search and slices recipe.

MethodPath
POST/v1/projects/{project_id}/search
POST/v1/projects/{project_id}/search/reindex
POST · GET/v1/projects/{project_id}/slices
GET/v1/projects/{project_id}/curation/strategies
POST/v1/projects/{project_id}/curation/preview
POST/v1/projects/{project_id}/curation/apply
GET/v1/projects/{project_id}/curation/recommend
POST/v1/projects/{project_id}/curate
POST/v1/projects/{project_id}/feedback/suggestions
POST/v1/projects/{project_id}/feedback/close-loop

Exports

MethodPath
POST · GET/v1/projects/{project_id}/exports
DELETE/v1/projects/{project_id}/exports/{export_id}
POST/v1/projects/{project_id}/exports/{export_id}/seal
GET/v1/projects/{project_id}/exports/{export_id}/download
GET/v1/projects/{project_id}/exports/{export_id}/artifact
GET/v1/projects/{project_id}/exports/{export_id}/archive
POST/v1/projects/{project_id}/reexport

Copilot

See Euler Copilot.

MethodPath
POST/v1/copilot/chat (SSE)
GET/v1/copilot/models
GET/v1/copilot/suggestions
POST · GET/v1/copilot/support
GET/v1/copilot/threads
GET · DELETE/v1/copilot/threads/{thread_id}

The earlier planning surface remains available:

MethodPath
POST/v1/agent/plan
POST/v1/agent/execute

Models, budget and cost

MethodPath
GET/v1/models
PUT/v1/models/{surface}
GET · PUT/v1/budget
GET/v1/costs
POST/v1/costs/simulate

GET /v1/models returns the active model per surface with its evidence and the vetted alternatives. PUT accepts only a vetted option on a selectable surface.