Sidekick Robotics, Inc.

The API for Physical AI™

World models, vision-language-action policies and embodied reasoning behind a single endpoint. One key, one balance, one request shape. Sidekick picks the model and the provider that fit your latency budget, action space and price ceiling, and falls past whichever one is down.

Install with pip install sidekick-sdk

Four contracts, one request shape

Physical AI does not fit one verb. A model that imagines the next second of video and a model that emits joint targets are different products, so they are different endpoints rather than one endpoint that returns whatever the backend happened to produce.

POST /v1/predict

Roll the world forward. Observations in, predicted frames out.

POST /v1/act

Observations in, an action chunk out, in a declared action space.

POST /v1/ground

Embodied reasoning. Where is the mug, what is graspable, which way to the drawer. Served live by Gemini Robotics ER 2. Points and boxes normalised 0 to 1, never actions: coordinates executed as joint targets would move the wrong way.

POST /v1/evaluate

Score a policy inside a world model against a registered benchmark.

Your first call

Ask for a job, not a checkpoint. sidekick/auto:manipulation is a router alias: Sidekick picks whichever manipulation policy and pool fit, and the response tells you which one answered. This is a real exchange, and it is one where the first choice did not answer.

1 Send this


    

2 Get this back

{
  "id": "req_29e72634fd584a87b801",
  "object": "world.action",
  "model": "physical-intelligence/pi-0",
  "action": {
    "space": "joint_pos_14",
    "steps": [
      [ 0.0614, -0.0042, -0.0120, -0.0567, ..., 0.5865],
      [ 0.0672, -0.0008, -0.0104, -0.0579, ..., 0.5878],
      ...
    ],
    "dt_ms": 66,
    "note": "4 steps, 14 joint targets each: 7 per arm"
  },
  "route": {
    "model": "physical-intelligence/pi-0",
    "region": "us-east",
    "precision": "bf16",
    "attempts": [
      { "model": "physical-intelligence/pi-0-5",
        "status": "error", "latency_ms": 30188,
        "reason": "upstream did not answer within 30s" },
      { "model": "physical-intelligence/pi-0",
        "status": "ok", "latency_ms": 684 }
    ],
    "fallback_used": true,
    "simulated": false
  },
  "usage": {
    "action_steps": 4, "gpu_seconds": 0.6844,
    "cost_usd": 0.005416
  }
}

The caller named a job, not a checkpoint. The router tried π0.5 first, that pool did not answer inside its 30-second budget, so it fell past to π0 and had an answer 684 ms later. The client retried nothing and knew neither model name in advance. route.attempts is the audit trail and it includes the failure rather than hiding it. simulated is the honesty flag: true means placeholder output rather than a model prediction, so you can never mistake one for the other. usage.cost_usd is what came off your balance, and it covers the call that succeeded.

Say what you care about, and how far you want to go

One field. You are not tuning a router, you are stating a priority, and the router turns that into an ordering over every model and pool that can serve your request.

{ "model": "sidekick/auto:manipulation", "preference": "fastest" }
default "balanced"

Spread load across healthy pools, weighted toward the cheaper ones.

When you have no strong opinion. Not a sort: the absence of one.

"fastest"

Lowest measured latency first, not the advertised p50.

Closed-loop control, where 100 ms is a deadline and not a preference.

"cheapest"

Lowest cost per action step or frame.

Batch rollouts, data generation, evaluation sweeps. Nothing is waiting.

"reliable"

Highest uptime and precision, price ignored.

Production traffic where a retry costs more than the call.

The model field, and what outranks what

Three forms, and three places to state a priority. If you write more than one, the narrower one wins.

physical-intelligence/pi-0

An exact slug. This checkpoint, whichever pool serves it best.

sidekick/auto:manipulation

A router alias. Name the job and let the router pick the checkpoint.

pi-0-5:turbo

A variant suffix: :nitro throughput, :floor price, :turbo latency, :quality precision.

provider.sort :turbo preference

So {"model": "physical-intelligence/pi-0-5:turbo", "preference": "cheapest"} routes for latency: the suffix is attached to the model you named, so it outranks the preference you set for the request.

The whole request, and where each option sits

One call. The top level says what you want; the provider block says how to choose who serves it. Nothing here is required except model and observations.

POST /v1/act
Idempotency-Key: ep-8f21-step-014
{
  "model": "sidekick/auto:manipulation",
  "preference": "fastest",
  "instruction": "put the spoon on the towel",
  "action_space": "ee_delta_6d_grip",
  "horizon": 16,
  "observations": [{
    "frames": [{"camera": "primary", "url": "https://..."}],
    "proprio": [0, 0, 0, 0, 0, 0, 0]
  }],
  "provider": {
    "objective": {"latency": 0.7, "price": 0.3},
    "deadline_ms": 200,
    "max_cost_usd": 0.05,
    "min_uptime_30d": 0.995,
    "session_id": "ep-8f21",
    "hedge": {"after_ms": 80},
    "data_collection": "deny"
  }
}

Idempotency-Key makes a retry return the first answer instead of a second, different future. These models are stochastic, so a naive retry bills twice and moves the robot twice.

action_space is a contract, not a hint. A policy that emits a different dimensionality is refused rather than reshaped, because the alternative is a robot moving along the wrong axes with nothing in the response to say so.

provider is the whole control surface, applied in the order below. Send none of it and you still get live-only routing, fallback and circuit breaking.

Routing with the Sidekick API

  1. Declare an intent, not a machine. modelpreferenceaction_spacehorizon
  2. Expand into every offering that could serve it. modelsallow_simulated
  3. Remove hard what a constraint excludes. Final. onlyignoreregiondata_collectionmax_latency_msmin_uptime_30dmax_cost_usd
  4. Order soft what survived, live above advertised. ordersortobjectivesession_id
  5. Attempt top to bottom, falling past what fails. allow_fallbacksdeadline_mshedge
  6. Record what was tried, and what it cost. route.attemptsroute.simulatedusage.cost_usd

Ordering is on measured latency, so a pool whose real traffic disagrees with its advertised p50 is demoted rather than believed. The terminal below runs this planner against live supply for free, and lists every field in full.

Three loops, three blocks worth copying

The same API, tuned to what is actually waiting on the answer.

Closed-loop control

A robot is moving. Late is the same as wrong.

"provider": {
  "objective": {"latency": .8, "reliability": .2},
  "deadline_ms": 150,
  "hedge": {"after_ms": 80},
  "session_id": "ep-8f21",
  "min_uptime_30d": 0.995
}

Hedge the tail, hold the policy steady for the episode, and fail fast rather than answer late.

Batch rollouts and evals

Nothing is waiting. Volume is the cost.

"provider": {
  "sort": "price",
  "max_cost_usd": 0.02,
  "allow_fallbacks": true
}

Cheapest first, a ceiling on each call so a long horizon cannot surprise the invoice, and no hedging: paying twice to save milliseconds nobody is waiting on is waste.

Production fleet

Someone else's data, and an auditor.

"provider": {
  "only": ["modal-sidekick-2"],
  "region": ["us-east"],
  "data_collection": "deny",
  "allow_fallbacks": false
}

Pin the pool you have contracted, keep frames in one jurisdiction, and refuse a substitution rather than serve one silently.

Every field above is enforced by the router and previewable for free: the terminal below runs this exact planner against live supply and shows you the plan it would call, without calling anything. Full reference with worked examples in the API section.

The model registry

Every world model in Awesome-World-Models, normalized across five domains: a stable slug, the contracts it serves, the embodiments and action spaces it speaks, and which providers will run it. Benchmarks and survey papers are catalogued separately, because they are not models and are never routable.

Where the models are

Every entry by domain and by how far along it is toward being servable. The routable column is what a developer can call today. Counts include the policy and embodied reasoning models below, which are tracked here because they are what most developers reach for, and labelled because they are not world models: a policy has no generative video head, and a reasoner returns neither frames nor joint targets.

Task families

The source list's own taxonomy, preserved. Each family is addressable as a router alias (sidekick/auto:manipulation) so callers name a job rather than a checkpoint.

Providers

Who can serve these models, and at what cost and latency. Median price is across every offering that provider carries.

ProviderKindModelsMedian $/frame p50ThroughputMax horizon Uptime 30dRegions

Search by name, paper title or slug. Every row links back to its source.

ModelDomainFamilyStatusContracts Action spacesRate p50Source

API reference

Every endpoint, with the fields that matter. The full interactive reference with request bodies, schemas and a "Try it" button lives at /docs; the machine-readable spec is at /openapi.json.

Authentication

One bearer token per key. Keys are scoped and can be limited to specific models, a workspace budget and a rate limit.

Authorization: Bearer sk-sidekick-...

Never put a key in browser JavaScript. Call Sidekick from your own server, or use the server-side proxy pattern in the SDK. A key in a client bundle is a key on someone else's machine.

Inference

EndpointTakesReturnsBilled on
POST /v1/predict observations, horizon predicted visual futureframes out
POST /v1/predict/stream sameSSE: route, frame×N, done frames out
POST /v1/act observations, instruction, action_space an action chunkaction steps
POST /v1/ground observations, instruction points and boxes, normalised 0–1tokens
POST /v1/evaluate policy_endpoint, scenario, episodes a job id, then scoresepisodes

Four contracts rather than one because the outputs are not interchangeable. A world model rolls video forward, a policy emits joint targets, a reasoner returns image coordinates. Collapsing them into one endpoint would let a caller execute pixel coordinates as joint targets, and nothing in the response would say so.

Choosing a model

The model field takes three things, and a provider block steers the choice within them.

FormExampleMeaning
Exact slugphysical-intelligence/pi-0 this checkpoint, any provider that serves it
Router aliassidekick/auto:manipulation name the job, let the router pick the checkpoint
Variant suffixnvidia/gr00t-n1-7:nitro :nitro throughput, :floor cheapest, :turbo latency
"provider": {
  "order": ["modal", "baseten"],   // try these first, in this order
  "only":  ["modal"],              // or restrict to these entirely
  "ignore": ["fal"],               // never route here
  "sort": "price",                 // price | throughput | latency
  "max_latency_ms": 150,           // hard deadline; providers over it are skipped
  "allow_fallbacks": true,         // false means fail rather than substitute
  "data_collection": "deny",       // skip providers that retain your frames
  "require_parameters": true       // skip providers that would drop seed, etc.
}

GET /v1/routes lists every alias and variant. GET /v1/models is the whole registry as JSON, filterable by domain, contract, embodiment and action space.

Reliability and cost control

FeatureHow
Automatic fallback Providers are attempted in plan order; every attempt is returned in route.attempts so you can see what happened.
Circuit breaking A provider that fails repeatedly is skipped until it recovers. GET /v1/status shows the state.
Idempotent retries Send Idempotency-Key (header or body). A retry returns the original response and bills once, which matters because these models are stochastic and a naive retry returns a different future.
Free dry run POST /v1/routes/preview returns the plan and an estimated cost without running anything.
Honesty flag Every response carries route.simulated. true means placeholder output, not a model prediction.

Account, billing and ops

EndpointWhat it does
GET /v1/billing/balancecredits and lifetime spend
POST /v1/billing/topupreturns a Stripe Checkout URL
GET /v1/usageper-request ledger and totals
GET /v1/keythe calling key: scopes, budget, rate limit
GET /v1/runtimeswire protocols, and which offerings are real
GET /v1/statuscircuit-breaker state, jobs, cache
GET /healthdeployment config, warnings, live providers

Developer console

Everything an account needs: a balance, credits, keys and a dry run of the router. It talks to this API from your browser with your own key, so nothing here is a mock.

Your account

Paste a Sidekick API key. It is held in this tab's memory only, never written to storage and never sent anywhere except this API, because a key in localStorage is readable by every script that ever runs on this origin.

No key yet? Accounts are provisioned by the Sidekick team while the API is in preview. Ask for one, then come back here to top up.

Credits

One balance covers every model and every provider. Prepaid rather than metered on purpose: a rollout that runs long is not fraud, and a prepaid balance means the gateway refuses work with a 402 before renting a GPU instead of sending you an invoice you did not expect.

Route preview

What this is: when you send a request, Sidekick does not call one fixed model. It builds a ranked plan of model-and-provider pairs that satisfy your constraints, calls the first, and falls to the next if that one errors or times out. This runs exactly that planner and shows you the list, without calling any model. Nothing is billed, so it doubles as a pricing calculator. Change the preference and watch the order change; the same planner answers your /v1/act calls.

Two prices, and the gap between them is the point. List is the published rate for the horizon you set. Now is what this call would actually cost at this moment, and it is higher only when the container is scaled to zero, because waking a GPU costs real money and so does the minute it stays warm afterwards. We charge that to the request that caused it rather than spreading it across everyone. A call inside a running control loop extends the warm window by its own duration and prices at list, so the two numbers are the same. Press the button twice in a row and watch the second one drop.

Every option this terminal is standing in for

The three dropdowns above set model, the contract, and preference. A real call can say a great deal more, and all of it is enforced by the same planner this terminal runs. The stage each field acts at is described above; this is the whole list in one place. A hard constraint removes candidates from the plan, a soft one only reorders what survived. When constraints leave nothing, the request fails with 409 no_route_available and names every offering it dropped and why, rather than quietly relaxing one.

FieldWhat it does
sortsoft One axis: price, latency, throughput, quality.
objectivesoft Several axes at once, weighted, e.g. {"latency":0.6,"price":0.3,"reliability":0.1}. Each axis is normalised before the weights apply, so only the ratios matter. A stated objective is answered deterministically; the default is a weighted shuffle that spreads load. Setting it alongside sort is a 422.
order / only / ignorehard Pin the provider order, restrict to a set, or exclude one. order with allow_fallbacks:false is the strong form.
session_idsoft Pin an episode to the checkpoint and provider that served its first call. Switching policy mid-episode changes the action distribution discontinuously. Promotion only: a pin never routes around a constraint you set, and it expires after 15 minutes of silence.
max_latency_mshard Drop providers whose advertised p95 exceeds it, before anything runs.
deadline_mshard The real clock across the whole request, fallbacks included. A step the router does not expect to finish in the time left is skipped rather than started. A control loop is better served by a fast error at 200 ms than a correct answer at 600 ms.
max_cost_usdhard Ceiling on this call's bill, priced against the horizon you set. The per-unit ceilings below bound a rate; this bounds the total.
max_price_per_frame
max_price_per_action_step
hard Per-unit ceilings. Frames bind on predict, action steps on act, so a ceiling on one does nothing to the other.
min_uptime_30dhard Reliability floor, e.g. 0.995.
region / data_collectionhard Data residency, and dropping providers that retain frames.
hedgesoft {"after_ms":80} dispatches a second provider when the first is late and takes whichever answers. You pay for both, itemised as route.hedge_cost_usd: a remote GPU cannot be recalled.
allow_simulatedhard Off by default. On, the plan may include catalogued offerings with no live deployment, which return structurally valid placeholder output. Every such response carries route.simulated: true.

Full guide with worked examples: the API reference and docs/ROUTING.md.