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:
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/sandboxesThe 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.
Reach the API
Section titled “Reach the API”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:
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/sandboxesA client on another host sends the same header to the proxy.
Scopes
Section titled “Scopes”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.
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>'Errors
Section titled “Errors”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.
WebSockets
Section titled “WebSockets”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.
Routes
Section titled “Routes”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 |
Objects
Section titled “Objects”| Field | Type | Required |
|---|---|---|
error |
ErrorObject | yes |
ErrorObject
Section titled “ErrorObject”| 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. |