Docs
Motor's REST API is at /api. People and their agents use it to manage teams,
register agents, read usage, listen to what happens, and run code in Piston. Every endpoint
is in an OpenAPI 3.1 spec.
APIs
3 available-
Motor API Users, teams, members, keys, sessions, agents, usage, and invoices.
-
Meta API The stream of each team's events.
-
Piston API Sandboxed runs of code: sources, plans, runs, logs, outputs, volumes, and secrets.
Getting started
- Sign up, make a passkey, and add a card.
- Run
motor auth. It opens this site, you approve with your passkey, and the CLI gets a session key for 24 hours, bound to your device. - Register an agent:
motor agent start --team team_… --name reviewer --scope "current:*". The CLI prints the agent's token. Usemotor agent token <agent>to get a new token before it expires.
Or, with the API and a session key:
curl -X POST https://new.motor.dev/api/agents \
-H "Authorization: Bearer $MOTOR_SESSION_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"team_id": "team_…", "name": "reviewer", "scopes": ["current:*"]}'
Credentials
Send a credential in the Authorization header. There are three kinds:
| Credential | Prefix | Lasts | For |
|---|---|---|---|
| Session key | motor_sk_ | 24 hours | Day-to-day work. motor auth gets one with your approval in the browser; a user key mints one with POST /api/sessions. It acts as you, registers agents, and renews their tokens, but it can't manage keys. |
| User key | motor_uk_ | Until it expires | Automation, such as CI, where nobody can approve in a browser. You make one in the console. It manages keys and mints session keys; it can't register agents. |
| Agent token | motor_tk_ | At most 4 hours | An agent, in one team, with the agent's scopes. The session key that registered the agent, or a parent agent, gives it a new token with POST /api/agents/{agent_id}/tokens. An agent can't renew its own token. |
Revoking a key revokes the session keys that it minted and deregisters their agents. Deregistering an agent deregisters its sub-agents and revokes their tokens.
Session keys bound to a device
motor auth binds its session key to a key of your device: in the TPM, where the
device has one, and in the keychain otherwise. A bound session key works only with a fresh
proof that the device's key signs (DPoP, RFC 9449):
Authorization: DPoP motor_sk_…
DPoP: <a JWT that the device key signs, with the method, the URL, the time, and the hash of the key>
Each proof works once, for one minute. A session key that leaks, such as into a log, is useless
without the device. The Motor CLI makes the proofs; to bind a key that you mint with a user key,
send a proof with POST /api/sessions.
Scopes
An agent may do what its scopes cover. A scope is <area>:<action>,
such as current:write; current:* covers every action of an area,
and * covers everything. Each service checks the scopes of its own area. Motor's,
with Piston's, whose API Motor serves, are:
| Scope | Allows |
|---|---|
agents:start | Register sub-agents, and renew their tokens. A sub-agent's scopes, lifetime, and spending limit are at most its parent's. |
events:read | Read and stream the team's events. |
team:read | Read the team and its members. |
usage:read | Read the team's usage. |
piston:run | Upload sources, check plans, start and cancel runs, and delete volumes in Piston. |
piston:read | Read Piston's runs, logs, outputs, and volumes. |
piston:secrets | List, set, and delete the team's secrets in Piston. Nobody reads a secret's value back. |
Conventions
Requests and responses
- Bodies are JSON objects, sent as
application/json, of at most 1 MiB. Motor refuses fields that it doesn't know. - IDs are a prefix and 22 characters, such as
team_1BbA6sXxyUWHYvKqN5T3dM. IDs of one kind sort by when Motor made them. - Times are RFC 3339 in UTC, with milliseconds, such as
2026-10-22T09:00:00.250Z. - Money is in whole cents, in fields that end in
_cents. - In a
PATCH, a missing field keeps its value, andnullclears it. - Each response has a
Request-Idheader. Give it to support with a question.
Pagination
A list answers {"data": […], "next_cursor": …}. Pass limit (1 to
100, 50 if you don't) and, for the next page, cursor with the value of
next_cursor, which is null on the last page.
Idempotency
Send an Idempotency-Key header, 1 to 128 printable characters, with each request
that makes something, such as POST /api/agents. For 24 hours, the same key and the
same request get the first answer again, with Idempotency-Replayed: true, so a
client can retry without making two agents. The same key with another request is a
409 idempotency_conflict. Motor seals the stored answer with your credential, so
only you can see it again.
Rate limits
Each credential may make 600 requests a minute. Past that, Motor answers
429 rate_limited with a Retry-After header.
Errors
An error answers with its status and a body like this:
{"error": {"code": "invalid_field", "message": "`name` is required.", "field": "name", "retryable": false}}
| Status | Codes |
|---|---|
| 400 | invalid_json, and in the CLI's sign-in: authorization_pending, slow_down, access_denied, invalid_grant |
| 401 | unauthorized, dpop_required, invalid_dpop_proof |
| 402 | billing_required: the team needs a card; over_limit: the team or the agent spent its spending limit for the month |
| 403 | forbidden, insufficient_scope, session_key_required, user_key_required, account_suspended, team_suspended |
| 404 | not_found |
| 409 | conflict, idempotency_conflict, request_in_progress |
| 413, 415 | body_too_large, unsupported_media_type |
| 422 | invalid_field, and in Piston: invalid_plan, with each problem of the config in diagnostics |
| 429 | rate_limited |
| 500, 501, 503 | internal_error, not_implemented, temporarily_unavailable, unavailable |
When retryable is true, try again after retry_after_seconds, if the body has it.
Billing
Every service bills the five meters on the home page. A team pays for what its people and agents use, at the start of each month; a personal team gets $10 a month for free. A team and each agent can have a spending limit: when one is reached, the services stop starting new work for it until the next month.