Skip to content

Overview

The shard command line and the SDKs talk to the daemon over this API. This request creates a sandbox named web, over the daemon’s socket:

Terminal window
curl --unix-socket /var/lib/shard/shard.sock -X POST -H 'Content-Type: application/json' -d '{"name":"web","image":"alpine:3.20","resources":{"memory_mib":512}}' http://localhost/v0/sandboxes

The daemon answers 201 with the Sandbox as JSON. Each page under REST API covers one group of routes, and the Routes tables below list them all.

On the host, the daemon listens on a unix socket, /var/lib/shard/shard.sock by default, and never on TCP. The socket needs no token, and a request on it can do anything. If the host has a shard group, its members can open the socket without root.

From another host, you reach the API through shard serve. It listens on 127.0.0.1:7850 by default, checks each request’s token, then passes the request to the socket. Put a proxy that terminates TLS in front of it. Mint a token on the host, then send it in the Authorization header:

Terminal window
export SHARD_API_KEY=$(shard tokens mint --name ci --scopes sandbox:read,exec | jq -r .token)
curl -H "Authorization: Bearer $SHARD_API_KEY" http://127.0.0.1:7850/v0/sandboxes

A client on another host sends the same header to the proxy.

Each route names the scope a token needs to reach it. A token with no scopes, or with *, reaches every route in this reference. A route marked “any token” accepts every valid token. GET /v0/scopes lists the scopes, and shard tokens mint --scopes takes them.

shard serve refuses some requests before they reach the daemon:

Status Code When
401 unauthorized The token is missing, does not verify, has expired, or was revoked.
403 forbidden The token’s scopes do not cover the route, or the route is unknown or local.

A create that names a secret also needs secret:*, and one that names a policy also needs policy:*. A fork of a sandbox that holds a secret or a policy needs the same scope. Without it, the daemon answers 403 with forbidden.

The local routes answer only on the socket, and this reference leaves them out. They are GET /v0/daemon, which shard daemon status reads, and the four images routes, which shard pull and shard image use.

A list returns every row unless the request passes limit. With limit, it returns at most that many rows, and next names the last row when more remain. Pass next as cursor to read the page after it. On the last page, next is null.

Terminal window
curl --unix-socket /var/lib/shard/shard.sock 'http://localhost/v0/sandboxes?limit=20'
curl --unix-socket /var/lib/shard/shard.sock 'http://localhost/v0/sandboxes?limit=20&cursor=<next>'

A refused request gets a 4xx or 5xx status and the Error body. A HEAD request gets the status alone. Match on the code, never on the message. Errors and exit codes lists every code and when the daemon returns it.

The routes that follow a stream, such as an exec attach or a logs follow, upgrade to a WebSocket and answer 101. Their sections list the messages. An exec, a process attach and a logs follow send binary messages, and each message starts with a stream byte. An egress-log follow sends one text message per decision.

Sandboxes

Method Path Scope Description
GET /v0/sandboxes sandbox:read List active sandboxes
GET /v0/sandboxes/{id} sandbox:read Read a sandbox and the egress rules the host enforces for it
POST /v0/sandboxes sandbox:write Create a sandbox
POST /v0/sandboxes/{id}/start sandbox:write Start a stopped sandbox with its saved files
POST /v0/sandboxes/{id}/stop sandbox:write Stop a sandbox and preserve its files
DELETE /v0/sandboxes/{id} sandbox:delete Remove a sandbox and its files
POST /v0/sandboxes/{id}/pause sandbox:write Save a sandbox’s state and suspend it
POST /v0/sandboxes/{id}/resume sandbox:write Resume a paused sandbox from its saved state
POST /v0/sandboxes/{id}/fork sandbox:write Create a sandbox from a running sandbox’s memory and files
GET /v0/sandboxes/{id}/egress-log sandbox:read Read or follow the egress decisions of a sandbox
POST /v0/sandboxes/{id}/secrets/{name} secret:* Grant a secret to a sandbox
DELETE /v0/sandboxes/{id}/secrets/{name} secret:* Ungrant a secret from a sandbox
PUT /v0/sandboxes/{id}/policy policy:* Attach a policy to a sandbox
DELETE /v0/sandboxes/{id}/policy policy:* Detach the policy of a sandbox

Files

Method Path Scope Description
PUT /v0/sandboxes/{id}/files exec Copy a file into a running sandbox
GET /v0/sandboxes/{id}/files exec Copy a file out of a running sandbox
HEAD /v0/sandboxes/{id}/files exec Read the type, size and mode of a path
DELETE /v0/sandboxes/{id}/files exec Delete a path
GET /v0/sandboxes/{id}/ls exec List a directory
POST /v0/sandboxes/{id}/mkdir exec Make a directory
PUT /v0/sandboxes/{id}/archive exec Copy a directory into a running sandbox
GET /v0/sandboxes/{id}/archive exec Copy a directory out of a running sandbox

Exec

Method Path Scope Description
POST /v0/sandboxes/{id}/exec exec Execute a command in a running sandbox
GET /v0/sandboxes/{id}/exec exec List the execs of a sandbox
GET /v0/sandboxes/{id}/exec/{exec} exec Read, wait for or attach to an exec
POST /v0/sandboxes/{id}/exec/{exec}/kill exec Send a signal to a running exec
DELETE /v0/sandboxes/{id}/exec/{exec} exec Forget an exec that ended
POST /v0/sandboxes/{id}/exec/{exec}/resize exec Resize the terminal of an exec

Snapshots

Method Path Scope Description
POST /v0/snapshots sandbox:write Snapshot a sandbox
GET /v0/snapshots sandbox:read List snapshots
GET /v0/snapshots/{ref} sandbox:read Read a snapshot
DELETE /v0/snapshots/{ref} sandbox:delete Remove a snapshot

Policies

Method Path Scope Description
GET /v0/policies policy:* List policies
GET /v0/policies/{name} policy:* Read a policy
PUT /v0/policies/{name} policy:* Create or replace a policy
DELETE /v0/policies/{name} policy:* Remove a policy

Secrets

Method Path Scope Description
GET /v0/secrets secret:* List secrets, never their values
PUT /v0/secrets/{name} secret:* Create or rotate a secret
DELETE /v0/secrets/{name} secret:* Remove a secret

Meta

Method Path Scope Description
GET /v0/version any token Read the daemon and API versions
GET /v0/capabilities any token List the lifecycle verbs and whether this server supports each
GET /v0/scopes any token List the scopes a token can carry

Processes

Method Path Scope Description
POST /v0/sandboxes/{id}/processes exec Run a named process under supervision in a running sandbox
GET /v0/sandboxes/{id}/processes sandbox:read List the processes of a sandbox
GET /v0/sandboxes/{id}/processes/{name} sandbox:read Read a process
POST /v0/sandboxes/{id}/processes/{name}/kill exec End a process and cancel its restarts
GET /v0/sandboxes/{id}/processes/{name}/logs sandbox:read Read or follow the output of a process
GET /v0/sandboxes/{id}/processes/{name}/attach sandbox:read Wait for or attach to a process until its restart policy ends it

Ports

Method Path Scope Description
GET /v0/ports port:read List the host ports forwarded into every sandbox
GET /v0/sandboxes/{id}/ports port:read List the host ports forwarded into a sandbox
PUT /v0/sandboxes/{id}/ports/{host_port} port:write Forward a host port into a sandbox, or change that forward
DELETE /v0/sandboxes/{id}/ports/{host_port} port:write Remove the forward on a host port
Field Type Required
error ErrorObject yes
Field Type Required Description
code string yes What a program matches on: invalid_request, body_too_large, not_found, sandbox_not_running, sandbox_not_stopped, sandbox_not_paused, sandbox_live, sandbox_failed, no_checkpoint, unsupported, in_use, name_taken, exec_exited, exec_running, exec_limit, no_process, process_limit, unauthorized, forbidden, timeout, command_not_started or internal. A later daemon may add a code, so a client must take one it does not know.
exit_code integer (int64) no The exit code of the command that never started, with command_not_started.
holders array of string no The sandboxes or snapshots that hold the resource, with in_use.
message string yes A line for a human; match on code, never on this text.