API
Your backend manages Sandboxes over HTTPS with an organization key. Every request is scoped to that organization, and request and response bodies are JSON. Routes for output, files and Connections are [to be published].
Authentication
Send Authorization: Bearer <key> on every request. Keys start with ortam_, are shown once when issued, and act for the whole organization. A revoked key fails from its next request; work it already started keeps running. Ortam issues your keys: the first when it sets up your organization, and another whenever you ask. A lost key can’t be recovered, so ask for a new one and have the old one revoked.
Resources from another organization return 404, the same as missing ones.
Retries
Every request that changes something needs an Idempotency-Key header. If a request fails or times out, retry it with the same key: Ortam returns the original outcome instead of acting twice. Reusing a key with different inputs returns 409.
A 202 response means Ortam accepted the action, not that it finished. Keep the operation and resource IDs it returns, and read the operation to see its outcome.
request=$(uuidgen) # keep this for retries of the same request
curl -X POST "$ORTAM_API/v1/sandboxes/$SANDBOX_ID/start" \
-H "Authorization: Bearer $ORTAM_API_KEY" \
-H "Idempotency-Key: $request"Sandboxes
Create Sandboxes, read their state, and start, stop or delete them.
Create a Sandbox
/v1/sandboxes
Creates a stopped Sandbox from a base or a Snapshot. Nothing runs until it starts.
namestring, required- Your name for it.
basestring- The base image. Defaults to
ubuntu-24.04-v1. snapshot_idUUID- Create it with this Snapshot’s files instead of a fresh base.
settings.envobject- Environment variables every command gets unless it sets its own. Names starting with
SYSBOX_are reserved. settings.connection_idUUID- The Connection commands use unless they choose another.
Returns 201. The create operation, already completed, and the new Sandbox.
curl -X POST "$ORTAM_API/v1/sandboxes" \
-H "Authorization: Bearer $ORTAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"name":"agent-checkout","settings":{"env":{"CI":"1"}}}'{
"operation": {
"id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"kind": "create",
"resource_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"state": "completed",
"accepted_at": "2026-11-02T09:14:05Z",
"deadline": "2026-11-02T09:16:05Z",
"result": null
},
"resource": {
"id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"name": "agent-checkout",
"phase": "stopped",
"generation": 0,
"activation_id": null,
"latest_save_id": null,
"source_snapshot_id": null,
"created_at": "2026-11-02T09:14:05Z"
}
}List Sandboxes
/v1/sandboxes
Lists up to 1,000 of your Sandboxes, newest first. Deleted ones aren’t listed.
Returns 200. An array of Sandboxes.
curl "$ORTAM_API/v1/sandboxes" \
-H "Authorization: Bearer $ORTAM_API_KEY"[
{
"id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"name": "agent-checkout",
"phase": "ready",
"generation": 1,
"activation_id": "a41e9c07-62f5-4b1a-8d3e-0c9f7e25b618",
"latest_save_id": "7b1e4d90-c35a-4f62-8e07-d2a96f1b3c58",
"source_snapshot_id": null,
"created_at": "2026-11-01T16:40:12Z"
}
]Get a Sandbox
/v1/sandboxes/{id}
Reads one Sandbox’s state. Reading never starts it.
Returns 200. The Sandbox.
curl "$ORTAM_API/v1/sandboxes/$SANDBOX_ID" \
-H "Authorization: Bearer $ORTAM_API_KEY"{
"id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"name": "agent-checkout",
"phase": "ready",
"generation": 1,
"activation_id": "a41e9c07-62f5-4b1a-8d3e-0c9f7e25b618",
"latest_save_id": "7b1e4d90-c35a-4f62-8e07-d2a96f1b3c58",
"source_snapshot_id": null,
"created_at": "2026-11-01T16:40:12Z"
}Start a Sandbox
/v1/sandboxes/{id}/start
Boots it from its last save. Starts requested while one is under way share it, and starting a running Sandbox completes at once.
Returns 202. The start operation and the Sandbox. A retry with the same idempotency key returns the same operation, with resource holding the operation’s result, or {"resource_id": …} until it has one.
curl -X POST "$ORTAM_API/v1/sandboxes/$SANDBOX_ID/start" \
-H "Authorization: Bearer $ORTAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"{
"operation": {
"id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"kind": "start",
"resource_id": "a41e9c07-62f5-4b1a-8d3e-0c9f7e25b618",
"state": "pending",
"accepted_at": "2026-11-02T09:14:05Z",
"deadline": "2026-11-02T09:16:05Z",
"result": null
},
"resource": {
"id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"name": "agent-checkout",
"phase": "starting",
"generation": 1,
"activation_id": "a41e9c07-62f5-4b1a-8d3e-0c9f7e25b618",
"latest_save_id": "7b1e4d90-c35a-4f62-8e07-d2a96f1b3c58",
"source_snapshot_id": null,
"created_at": "2026-11-01T16:40:12Z"
}
}Stop a Sandbox
/v1/sandboxes/{id}/stop
Ends its commands, takes a final save and releases the VM. Ending and saving are reported separately, and a second Stop can’t extend the first one’s deadline.
Returns 202. The stop operation, and where ending (termination) and the final save (final_save) stand: pending, or completed and not_required if nothing was running. Read the operation for how they turn out; its result is filled in after this response.
curl -X POST "$ORTAM_API/v1/sandboxes/$SANDBOX_ID/stop" \
-H "Authorization: Bearer $ORTAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"{
"operation": {
"id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"kind": "stop",
"resource_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"state": "pending",
"accepted_at": "2026-11-02T09:14:05Z",
"deadline": "2026-11-02T09:16:05Z",
"result": null
},
"resource": {
"sandbox_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"phase": "stopping",
"termination": "pending",
"final_save": "pending"
}
}Delete a Sandbox
/v1/sandboxes/{id}
Stops it if it’s running and removes it for good. It accepts no new work from the moment the request is accepted.
Returns 202. The delete operation and where ending and the final save stand, as for Stop. The Sandbox’s phase is deleted at once.
curl -X DELETE "$ORTAM_API/v1/sandboxes/$SANDBOX_ID" \
-H "Authorization: Bearer $ORTAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"{
"operation": {
"id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"kind": "delete",
"resource_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"state": "pending",
"accepted_at": "2026-11-02T09:14:05Z",
"deadline": "2026-11-02T09:16:05Z",
"result": null
},
"resource": {
"sandbox_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"phase": "deleted",
"termination": "pending",
"final_save": "pending"
}
}Commands
Run a command in a Sandbox and read its result.
Run a command
/v1/sandboxes/{id}/executions
Runs a program in the Sandbox, starting the Sandbox first if it’s stopped. argv runs as given, without a shell; for shell syntax, send ["/bin/bash", "-lc", "your command"].
argvarray of strings, required- The program and its arguments, up to 1,024.
cwdstring- The absolute directory to run in. Defaults to
/home/developer. envobject- Environment variables, on top of the Sandbox’s defaults.
timeout_secondsinteger- Ends the command after this many seconds, counted from launch, not while it waits to start. None if left out.
connection_idUUID- The Connection to use. Defaults to the Sandbox’s.
Returns 202. The execute operation and the Execution.
curl -X POST "$ORTAM_API/v1/sandboxes/$SANDBOX_ID/executions" \
-H "Authorization: Bearer $ORTAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"argv":["/bin/bash","-lc","npm test"],"timeout_seconds":900}'{
"operation": {
"id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"kind": "execute",
"resource_id": "e2b7a915-0d4c-4e8f-a3b6-91f05c7d2e40",
"state": "pending",
"accepted_at": "2026-11-02T09:14:05Z",
"deadline": "2026-11-02T09:16:05Z",
"result": null
},
"resource": {
"id": "e2b7a915-0d4c-4e8f-a3b6-91f05c7d2e40",
"sandbox_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"activation_id": "a41e9c07-62f5-4b1a-8d3e-0c9f7e25b618",
"state": "accepted",
"accepted_at": "2026-11-02T09:14:05Z",
"launched_at": null,
"ended_at": null,
"exit_code": null,
"durable_output_bytes": 0
}
}Get an Execution
/v1/executions/{id}
Reads a command’s state, times and exit code. Its inputs, including environment values, aren’t returned.
Returns 200. The Execution.
curl "$ORTAM_API/v1/executions/$EXECUTION_ID" \
-H "Authorization: Bearer $ORTAM_API_KEY"{
"id": "e2b7a915-0d4c-4e8f-a3b6-91f05c7d2e40",
"sandbox_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"activation_id": "a41e9c07-62f5-4b1a-8d3e-0c9f7e25b618",
"state": "exited",
"accepted_at": "2026-11-02T09:14:05Z",
"launched_at": "2026-11-02T09:14:09Z",
"ended_at": "2026-11-02T09:15:31Z",
"exit_code": 0,
"durable_output_bytes": 48213
}Snapshots
Keep a Sandbox’s files to create new Sandboxes from.
Take a Snapshot
/v1/sandboxes/{id}/snapshots
Captures the Sandbox’s files. Taking a Snapshot says which version it captures and when a Sandbox refuses one.
Returns 202. The snapshot operation and the Snapshot, pending until its save completes.
curl -X POST "$ORTAM_API/v1/sandboxes/$SANDBOX_ID/snapshots" \
-H "Authorization: Bearer $ORTAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"{
"operation": {
"id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"kind": "snapshot",
"resource_id": "9d3f6b21-48ac-4e07-b5d9-6a1c2e8f0b73",
"state": "pending",
"accepted_at": "2026-11-02T09:14:05Z",
"deadline": "2026-11-02T09:16:05Z",
"result": null
},
"resource": {
"id": "9d3f6b21-48ac-4e07-b5d9-6a1c2e8f0b73",
"sandbox_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"operation_id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"save_id": null,
"base": "ubuntu-24.04-v1",
"state": "pending",
"accepted_at": "2026-11-02T09:14:05Z"
}
}Get a Snapshot
/v1/snapshots/{id}
Reads a Snapshot and whether it has completed.
Returns 200. The Snapshot.
curl "$ORTAM_API/v1/snapshots/$SNAPSHOT_ID" \
-H "Authorization: Bearer $ORTAM_API_KEY"{
"id": "9d3f6b21-48ac-4e07-b5d9-6a1c2e8f0b73",
"sandbox_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"operation_id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"save_id": "7b1e4d90-c35a-4f62-8e07-d2a96f1b3c58",
"base": "ubuntu-24.04-v1",
"state": "completed",
"accepted_at": "2026-11-02T09:14:05Z"
}Operations
An operation is the record of one accepted change, returned by every route that changes something.
Get an operation
/v1/operations/{id}
Reads an accepted change and its outcome. Its state moves from pending through running to completed, failed or unknown; a passed deadline alone doesn’t mean it failed.
Returns 200. The operation.
curl "$ORTAM_API/v1/operations/$OPERATION_ID" \
-H "Authorization: Bearer $ORTAM_API_KEY"{
"id": "c8d2f1a0-7e4b-4f39-b6a5-2e91d0c3f847",
"kind": "stop",
"resource_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"state": "completed",
"accepted_at": "2026-11-02T09:14:05Z",
"deadline": "2026-11-02T09:16:05Z",
"result": {
"sandbox_id": "5f0c2a8e-3b1d-4c47-9e2a-7d6b1f30a9c4",
"phase": "stopped",
"termination": "completed",
"final_save": "completed"
}
}Records
Times are ISO 8601 in UTC, and a field that doesn’t apply yet is null.
Sandbox
idUUID- Goes in the
{id}of the/v1/sandboxes/{id}routes. namestring- Your name for it.
phasestringstopped,starting,ready,stopping,lost(its host failed) ordeleted.generationinteger- How many times it has started.
activation_idUUID or null- Its latest run: a new one each time it starts.
latest_save_idUUID or null- Its last completed save, which the next start uses.
source_snapshot_idUUID or null- The Snapshot it was created from.
created_attime- When it was created.
Operation
idUUID- Read it with
GET /v1/operations/{id}. kindstringcreate,start,stop,delete,executeorsnapshot.resource_idUUID- The ID of what it acts on.
statestringpending,running,completed,failedorunknown.accepted_attime- When it was accepted.
deadlinetime- When it should be done by. A later identical request can’t move it.
resultobject or null- What’s established so far: for Stop and Delete,
terminationandfinal_save; for a start a Stop overtook, itsreason.
Execution
idUUID- Read it with
GET /v1/executions/{id}. sandbox_idUUID- The Sandbox it runs in.
activation_idUUID- The Sandbox’s run it belongs to.
statestringaccepted,running,exited,not_launched,launch_failed,timed_out,interrupted,resource_exhausted,infrastructure_lostorunknown.accepted_attime- When it was accepted.
launched_attime or null- When the program started.
ended_attime or null- When it ended.
exit_codeinteger or null- The program’s exit code. Nonzero is the program’s own result, not a failure of Ortam’s.
durable_output_bytesinteger- How much of its output has been kept so far, in bytes.
Snapshot
idUUID- Pass it as
snapshot_idto create a Sandbox with its files. sandbox_idUUID- The Sandbox it was taken from.
operation_idUUID- The operation that takes it.
save_idUUID or null- The save it holds, once it completes.
basestring- The base image its files build on.
statestringpending,running,completed,failedorunknown.accepted_attime- When it was requested.
Errors
Errors return a JSON body with an error message, such as {"error":"unauthorized"}, except when the body itself can’t be read: those come as plain text.
- 400
- The request is invalid, such as an empty
argvor an environment name starting withSYSBOX_, which is reserved. A body that isn’t valid JSON also returns 400. Requests are limited to 1 MiB. - 401
- The key is missing or not valid.
- 404
- The resource doesn’t exist in your organization.
- 409
- It conflicts with the Sandbox’s state, or an idempotency key was reused with different inputs.
- 422
- The body is JSON but doesn’t fit the route: a required field is missing, a field is unknown, or a value has the wrong type.
- 503
- Ortam can’t check authorization right now. Retry with the same idempotency key.