Reference
Public API
The complete versioned REST API, organized by resource and operation.
On this page
REST API reference
The versioned public control-plane API at https://api.zei.sh/api/v1.
The machine-readable contract is available at /api/docs-json and the interactive Swagger explorer is at /api/docs. Public routes use /public and authenticate with X-API-Key or Bearer. The API returns structured errors under an error object with code, message, requestId, and optional details.
List endpoints return data and nextCursor. Use limit and cursor for sandboxes, templates, volumes, and networks. Mutation requests should send Idempotency-Key and reuse it when retrying the same logical request.
The complete public route map is below. The clone, secret grant, and secret lease routes are included because they are part of the live controller surface even when an older contract snapshot does not list every advanced route.
1# Resources2GET /public/templates3GET /public/templates/:templateId4GET /public/ssh-keys5POST /public/ssh-keys6DELETE /public/ssh-keys/:keyId7POST /public/volumes8GET /public/volumes9GET /public/volumes/:volumeId10DELETE /public/volumes/:volumeId11POST /public/networks12GET /public/networks13GET /public/networks/:networkId14DELETE /public/networks/:networkId1516# Sandboxes17POST /public/sandboxes18GET /public/sandboxes19GET /public/sandboxes/:sandboxId20PATCH /public/sandboxes/:sandboxId21DELETE /public/sandboxes/:sandboxId22POST /public/sandboxes/:sandboxId/clone23GET /public/sandboxes/:sandboxId/exec-access24GET /public/sandboxes/:sandboxId/terminal-url25POST /public/sandboxes/:sandboxId/preview-codes26POST /public/sandboxes/:sandboxId/tunnel-access27POST /public/sandboxes/:sandboxId/ports28PUT /public/sandboxes/:sandboxId/ports/:port/share29POST /public/sandboxes/:sandboxId/ssh-keys/sync30GET /public/sandboxes/:sandboxId/logs31GET /public/sandboxes/:sandboxId/events32POST /public/sandboxes/:sandboxId/{start|pause|resume|stop|kill}33POST /public/sandboxes/:sandboxId/snapshots34GET /public/sandboxes/:sandboxId/snapshots35DELETE /public/sandboxes/:sandboxId/snapshots/:snapshotId3637# Secrets38GET /public/secrets39POST /public/secrets40GET /public/secrets/:secretId41PATCH /public/secrets/:secretId42DELETE /public/secrets/:secretId43POST /public/secrets/:secretId/grants44POST /public/secrets/:sandboxId/leasesList templates
List templates visible to the authenticated organization.
GET /public/templates?limit=20&cursor=...
Permission: MACHINE_READ.
Use this to discover template IDs and their default runtime resources before creating a sandbox.
Response: A paginated data array and nextCursor. The default limit is 20 and the maximum is 100.
1curl -X GET https://api.zei.sh/api/v1/public/templates?limit=20&cursor=... \2 -H "X-API-Key: $ZEISH_API_KEY"Get a template
Fetch one visible sandbox template by ID.
GET /public/templates/:templateId
Permission: MACHINE_READ.
The response includes the image, CPU, memory, machine kind, and declared ingress settings.
1curl -X GET https://api.zei.sh/api/v1/public/templates/:templateId \2 -H "X-API-Key: $ZEISH_API_KEY"List SSH keys
List public SSH keys registered by the authenticated user.
GET /public/ssh-keys
Permission: MACHINE_READ.
Keys are used for SSH access to sandboxes created for the user.
Response: An array of key metadata and public key material. Private keys are never stored.
1curl -X GET https://api.zei.sh/api/v1/public/ssh-keys \2 -H "X-API-Key: $ZEISH_API_KEY"Register an SSH key
Register a public key for future sandbox access.
POST /public/ssh-keys
Permission: MACHINE_UPDATE.
Register the public half of a key before creating a sandbox or sync it into an existing runtime.
Request body: {"name":"workstation","publicKey":"ssh-ed25519 AAAA..."}
Response: The created key with id, name, publicKey, isManaged, and createdAt.
1curl -X POST https://api.zei.sh/api/v1/public/ssh-keys \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"workstation","publicKey":"ssh-ed25519 AAAA..."}'Delete an SSH key
Remove a registered public SSH key.
DELETE /public/ssh-keys/:id
Permission: MACHINE_UPDATE.
Deletion affects future provisioning. Call the sandbox SSH key sync operation to update an existing runtime.
Response: {"ok":true}
1curl -X DELETE https://api.zei.sh/api/v1/public/ssh-keys/:id \2 -H "X-API-Key: $ZEISH_API_KEY"Create a volume
Create persistent organization storage.
POST /public/volumes
Permission: ORG_MANAGE.
Volumes are region-scoped and survive sandbox stop and runtime replacement.
Request body: {"name":"agent-data","slug":"agent-data","region":"bremen","sizeGb":20}
Response: The created volume with id, organizationId, name, slug, region, sizeGb, and timestamps.
1curl -X POST https://api.zei.sh/api/v1/public/volumes \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"agent-data","slug":"agent-data","region":"bremen","sizeGb":20}'List volumes
List persistent volumes in the organization.
GET /public/volumes?limit=20&cursor=...
Permission: ORG_MANAGE.
Use limit and the returned nextCursor to walk the collection.
Response: A paginated data array and nextCursor. Limits range from 1 through 100.
1curl -X GET https://api.zei.sh/api/v1/public/volumes?limit=20&cursor=... \2 -H "X-API-Key: $ZEISH_API_KEY"Get a volume
Fetch one organization volume by ID.
GET /public/volumes/:volumeId
Permission: ORG_MANAGE.
Use the volume ID in sandbox create or update requests.
Response: The volume resource, including its region and sizeGb.
1curl -X GET https://api.zei.sh/api/v1/public/volumes/:volumeId \2 -H "X-API-Key: $ZEISH_API_KEY"Delete a volume
Delete one organization volume.
DELETE /public/volumes/:volumeId
Permission: ORG_MANAGE.
Confirm that no sandbox still depends on the volume before deleting it.
Response: The deleted volume resource.
1curl -X DELETE https://api.zei.sh/api/v1/public/volumes/:volumeId \2 -H "X-API-Key: $ZEISH_API_KEY"Create a network
Create an organization-scoped logical network.
POST /public/networks
Permission: ORG_MANAGE.
Attach the network to sandboxes with networkId.
Request body: {"name":"agent-network","slug":"agent-network","region":"bremen"}
Response: The created network with id, organizationId, name, slug, region, and createdAt.
1curl -X POST https://api.zei.sh/api/v1/public/networks \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"agent-network","slug":"agent-network","region":"bremen"}'List networks
List logical networks in the organization.
GET /public/networks?limit=20&cursor=...
Permission: ORG_MANAGE.
Use cursor pagination for stable iteration over organization networks.
Response: A paginated data array and nextCursor.
1curl -X GET https://api.zei.sh/api/v1/public/networks?limit=20&cursor=... \2 -H "X-API-Key: $ZEISH_API_KEY"Get a network
Fetch one organization network by ID.
GET /public/networks/:networkId
Permission: ORG_MANAGE.
Use the network ID in sandbox create or update requests.
Response: The network resource.
1curl -X GET https://api.zei.sh/api/v1/public/networks/:networkId \2 -H "X-API-Key: $ZEISH_API_KEY"Delete a network
Delete an organization network.
DELETE /public/networks/:networkId
Permission: ORG_MANAGE.
Remove the network from dependent sandboxes before deleting it.
Response: The deleted network resource.
1curl -X DELETE https://api.zei.sh/api/v1/public/networks/:networkId \2 -H "X-API-Key: $ZEISH_API_KEY"Create a sandbox
Provision a MicroVM sandbox with optional resources, ingress, and secret injection.
POST /public/sandboxes
Permission: MACHINE_CREATE.
The request needs name and templateId or template. CPU is cores, memory is MB, and omitted resources use the template defaults.
Request body: {"name":"agent-run","templateId":"TEMPLATE_ID","cpu":4,"memory":4096,"region":"bremen","networkId":"NETWORK_ID","volumeIds":["VOLUME_ID"]}
Response: The sandbox record. Provisioning is asynchronous and normally requests a running runtime.
Reuse the same Idempotency-Key when retrying one logical create request.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"agent-run","templateId":"TEMPLATE_ID","cpu":4,"memory":4096,"region":"bremen","networkId":"NETWORK_ID","volumeIds":["VOLUME_ID"]}'List sandboxes
List compact sandbox records in the organization.
GET /public/sandboxes?limit=20&cursor=...
Permission: MACHINE_READ.
Use this for dashboards and polling. Fetch a detail record when you need enriched access information.
Response: A paginated data array and nextCursor.
1curl -X GET https://api.zei.sh/api/v1/public/sandboxes?limit=20&cursor=... \2 -H "X-API-Key: $ZEISH_API_KEY"Get sandbox details
Fetch one sandbox with runtime and access URL enrichment.
GET /public/sandboxes/:sandboxId
Permission: MACHINE_READ.
Use the detail response to decide whether a runtime-dependent operation is ready.
Response: The sandbox record with current status and available runtime metadata.
1curl -X GET https://api.zei.sh/api/v1/public/sandboxes/:sandboxId \2 -H "X-API-Key: $ZEISH_API_KEY"Update a sandbox
Change mutable sandbox configuration.
PATCH /public/sandboxes/:sandboxId
Permission: MACHINE_UPDATE.
Update name, templateId, region, CPU, memory, networkId, volumeIds, or labels.
Request body: {"name":"agent-run-final","cpu":6,"memory":8192,"labels":{"run":"2026-08-30"}}
Response: The updated sandbox record.
Set networkId to null to detach the current network.
1curl -X PATCH https://api.zei.sh/api/v1/public/sandboxes/:sandboxId \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"agent-run-final","cpu":6,"memory":8192,"labels":{"run":"2026-08-30"}}'Delete a sandbox
Permanently delete a sandbox.
DELETE /public/sandboxes/:sandboxId
Permission: MACHINE_DELETE.
Deletion is a lifecycle action and is irreversible.
Response: The lifecycle result for the delete request.
1curl -X DELETE https://api.zei.sh/api/v1/public/sandboxes/:sandboxId \2 -H "X-API-Key: $ZEISH_API_KEY"Clone a sandbox
Create a new sandbox from an existing sandbox state.
POST /public/sandboxes/:sandboxId/clone
Permission: MACHINE_CREATE.
Use clones for parallel agent branches and repeatable evaluation runs.
Request body: {"name":"agent-run-copy"}
Response: The new sandbox record.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/clone \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"agent-run-copy"}'Mint data-plane access
Mint short-lived credentials for commands, files, and terminal sessions.
GET /public/sandboxes/:sandboxId/exec-access
Permission: MACHINE_UPDATE.
The token is scoped to one sandbox and is valid for about ten minutes.
Response: sandboxUrl, sandboxRpcUrl, token, and expiresAt.
Send the token as Authorization: Bearer <token>. Never log or persist it.
1curl -X GET https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/exec-access \2 -H "X-API-Key: $ZEISH_API_KEY"Get a terminal URL
Create a browser terminal URL for a sandbox.
GET /public/sandboxes/:sandboxId/terminal-url
Permission: MACHINE_READ.
Open the returned URL in a browser to use the sandbox terminal.
Response: A terminal URL and its expiration metadata.
1curl -X GET https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/terminal-url \2 -H "X-API-Key: $ZEISH_API_KEY"Sync SSH keys
Apply the user's current SSH keys to an existing sandbox runtime.
POST /public/sandboxes/:sandboxId/ssh-keys/sync
Permission: MACHINE_UPDATE.
Call this after registering or removing a user SSH key.
Response: The updated sandbox result.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/ssh-keys/sync \2 -H "X-API-Key: $ZEISH_API_KEY"Create a preview code
Mint temporary HTTP browser or agent access to an exposed port.
POST /public/sandboxes/:sandboxId/preview-codes
Permission: MACHINE_READ.
Use the browser handoff URL for a real browser and base_url with the bearer code for fetch, WebSocket, Playwright, or CDP.
Request body: {"port":3000,"ttl_seconds":300,"path":"/health"}
Response: url, handoff_url, base_url, code, and expires_at.
TTL is 1 through 3600 seconds. Do not append paths to the browser handoff URL.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/preview-codes \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"port":3000,"ttl_seconds":300,"path":"/health"}'Mint tunnel access
Mint a short-lived WebSocket tunnel for exposed TCP ports.
POST /public/sandboxes/:sandboxId/tunnel-access
Permission: MACHINE_UPDATE.
Use this for CDP, databases, and other protocols that do not work through an HTTP Host header.
Request body: {"ttl_seconds":60}
Response: ws_url, token, and expires_at.
TTL is 1 through 3600 seconds. The default is 60 seconds.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/tunnel-access \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"ttl_seconds":60}'Add a sandbox port
Expose a TCP or UDP port from a sandbox.
POST /public/sandboxes/:sandboxId/ports
Permission: MACHINE_UPDATE.
Declare raw L4 ingress with an internal port and optional external port and access policy.
Request body: {"internalPort":3000,"externalPort":3000,"protocol":"tcp","accessPolicy":"org"}
Response: The created port exposure.
Ports must be between 1 and 65535. Access policy is org or public.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/ports \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"internalPort":3000,"externalPort":3000,"protocol":"tcp","accessPolicy":"org"}'List sandbox logs
Read bounded captured output from a sandbox.
GET /public/sandboxes/:sandboxId/logs?limit=100&source=app&service=...
Permission: MACHINE_READ.
Filter by source or service when diagnosing boot, memory, or application output.
Response: A bounded log history.
1curl -X GET https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/logs?limit=100&source=app&service=... \2 -H "X-API-Key: $ZEISH_API_KEY"List sandbox events
Read lifecycle events for a sandbox.
GET /public/sandboxes/:sandboxId/events?limit=100
Permission: MACHINE_READ.
Poll events to correlate asynchronous lifecycle transitions with an agent run.
Response: Events with status, source, timestamp, and optional message.
1curl -X GET https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/events?limit=100 \2 -H "X-API-Key: $ZEISH_API_KEY"Start a sandbox
Request a sandbox runtime to start.
POST /public/sandboxes/:sandboxId/start
Permission: MACHINE_UPDATE.
Use start after a sandbox is stopped and poll its detail or events until it is running.
Response: The lifecycle result.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/start \2 -H "X-API-Key: $ZEISH_API_KEY"Pause a sandbox
Pause a sandbox while preserving its state.
POST /public/sandboxes/:sandboxId/pause
Permission: MACHINE_UPDATE.
Pause is useful when you want to preserve state without keeping the runtime active.
Response: The lifecycle result.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/pause \2 -H "X-API-Key: $ZEISH_API_KEY"Resume a sandbox
Resume a paused sandbox.
POST /public/sandboxes/:sandboxId/resume
Permission: MACHINE_UPDATE.
Poll the sandbox detail until the runtime is running before requesting data-plane access.
Response: The lifecycle result.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/resume \2 -H "X-API-Key: $ZEISH_API_KEY"Stop a sandbox
Stop a sandbox runtime while retaining the sandbox record.
POST /public/sandboxes/:sandboxId/stop
Permission: MACHINE_UPDATE.
Stop releases the active runtime and preserves the sandbox configuration.
Response: The lifecycle result.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/stop \2 -H "X-API-Key: $ZEISH_API_KEY"Kill a sandbox
Force-stop a stuck sandbox runtime.
POST /public/sandboxes/:sandboxId/kill
Permission: MACHINE_UPDATE.
Use kill for a runtime that does not respond to a normal stop request.
Response: The lifecycle result.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/kill \2 -H "X-API-Key: $ZEISH_API_KEY"Create a snapshot
Capture a sandbox runtime state for reuse.
POST /public/sandboxes/:sandboxId/snapshots
Permission: MACHINE_UPDATE.
Create snapshots from a live runtime and wait for the snapshot to become ready before using it.
Request body: {"displayName":"dependencies-v4"}
Response: The new snapshot with its status and ID.
1curl -X POST https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/snapshots \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"displayName":"dependencies-v4"}'List snapshots
List snapshots belonging to one sandbox.
GET /public/sandboxes/:sandboxId/snapshots
Permission: MACHINE_READ.
Use sandbox-scoped snapshot IDs for cleanup and repeatable fan-out.
Response: An array of sandbox snapshots.
1curl -X GET https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/snapshots \2 -H "X-API-Key: $ZEISH_API_KEY"Delete a snapshot
Delete one sandbox snapshot.
DELETE /public/sandboxes/:sandboxId/snapshots/:snapshotId
Permission: MACHINE_UPDATE.
Snapshot deletion is irreversible.
Response: {"ok":true}
1curl -X DELETE https://api.zei.sh/api/v1/public/sandboxes/:sandboxId/snapshots/:snapshotId \2 -H "X-API-Key: $ZEISH_API_KEY"List secret metadata
List organization secrets without returning their values.
GET /public/secrets
Permission: ORG_MANAGE.
Use this to discover secret IDs and metadata. Values are excluded from list responses.
Response: Secret metadata only.
1curl -X GET https://api.zei.sh/api/v1/public/secrets \2 -H "X-API-Key: $ZEISH_API_KEY"Create a secret
Store a provider-backed plaintext or JSON secret.
POST /public/secrets
Permission: ORG_MANAGE.
The current deployment uses Vault. Other provider values require that provider to be configured.
Request body: {"name":"github-token","provider":"vault","providerReference":"secret/data/ci/github","providerKey":"token","format":"plaintext","value":"replace-me"}
Response: The secret metadata.
Values are audited when viewed or edited. Keep provider credentials out of sandbox records.
1curl -X POST https://api.zei.sh/api/v1/public/secrets \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"github-token","provider":"vault","providerReference":"secret/data/ci/github","providerKey":"token","format":"plaintext","value":"replace-me"}'Get a secret
Read one secret value and its metadata.
GET /public/secrets/:secretId
Permission: ORG_MANAGE.
This operation is audited and returns no-store response headers.
Response: The secret metadata and resolved value.
Treat the response as sensitive data and do not log it.
1curl -X GET https://api.zei.sh/api/v1/public/secrets/:secretId \2 -H "X-API-Key: $ZEISH_API_KEY"Update a secret
Update secret metadata or material.
PATCH /public/secrets/:secretId
Permission: ORG_MANAGE.
Send only the fields that should change.
Request body: {"name":"github-token-rotated","value":"replace-me","version":"v2","format":"plaintext"}
Response: The updated secret metadata.
1curl -X PATCH https://api.zei.sh/api/v1/public/secrets/:secretId \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"name":"github-token-rotated","value":"replace-me","version":"v2","format":"plaintext"}'Delete a secret
Remove a secret from its configured provider.
DELETE /public/secrets/:secretId
Permission: ORG_MANAGE.
Deletion archives the secret metadata after provider removal.
Response: The deletion result.
1curl -X DELETE https://api.zei.sh/api/v1/public/secrets/:secretId \2 -H "X-API-Key: $ZEISH_API_KEY"Grant a secret to a sandbox
Authorize a secret for environment or file delivery.
POST /public/secrets/:secretId/grants
Permission: ORG_MANAGE.
Grant startup or command delivery to a specific sandbox and target.
Request body: {"sandboxId":"SANDBOX_ID","target":"env","targetName":"GITHUB_TOKEN","mode":"command"}
Response: The grant result.
Environment names must match shell variable syntax. File targets must be below /run/secrets.
1curl -X POST https://api.zei.sh/api/v1/public/secrets/:secretId/grants \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"sandboxId":"SANDBOX_ID","target":"env","targetName":"GITHUB_TOKEN","mode":"command"}'Mint a secret lease
Mint a short-lived lease for secret resolution.
POST /public/secrets/:sandboxId/leases
Permission: ORG_MANAGE.
Leases are scoped to organization, sandbox, operation, secret IDs, expiry, and nonce.
Request body: {"operation":"command"}
Response: The short-lived lease claims.
Operation is startup, command, or file. Do not persist lease tokens.
1curl -X POST https://api.zei.sh/api/v1/public/secrets/:sandboxId/leases \2 -H "X-API-Key: $ZEISH_API_KEY"3 -H "Content-Type: application/json" \4 -d '{"operation":"command"}'