Hosting API

Run commands

Run any shell command inside an instance from your backend, the escape hatch for anything the API does not wrap.

POST /v1/instances/{id}/exec runs a shell command inside the instance, straight from your backend. It is the escape hatch for anything the API does not wrap as its own call.

The command runs through sh -c as the image's default user, on the same box the agent works on, so it sees the agent's files, tools, and credentials.

Request

commandstringrequired

The shell command to run inside the instance. It is passed to sh -c, so pipes, redirects, and && chains all work. It must not contain a null byte, which no shell can carry: one returns 400 invalid_request.

Note

Only running instances accept commands. Exec against any other status returns 400 invalid_request (a deleted instance returns 404 not_found), and it does not wake a sleeping instance: start it, or hit one of its URLs, first. If the platform cannot reach the instance at all, you get 502 provisioning_failed.

Response

A command that runs but exits nonzero is a normal result: you get 200 with its exit_code, stdout, and stderr. Errors are reserved for the platform, not your command.

exit_codeinteger

The command's exit code. Nonzero is still a 200; read this to branch.

stdoutstring

Standard output, capped at 512 KB. See truncated.

stderrstring

Standard error, with its own separate 512 KB cap.

truncatedboolean

true when either stream spilled past its 512 KB cap. The middle of the output is cut and a truncation marker is left in its place.

Note

exit_code values 125, 126, and 127 may come from the container runtime rather than your command, for example 127 when the binary is not found. A command runs for up to 280 seconds, after which the call fails with 502 provisioning_failed; start longer jobs in the background (nohup ... &) and poll with a second exec.

Example

curl -X POST https://api.pusk.ai/v1/instances/ab12cd34ef/exec \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "command": "node --version" }'

Build on exec

Anything the API does not wrap as its own endpoint, you build on exec. For moving files, prefer the instance's own files endpoints at https://{instanceId}.pusk.app (PUT /v1/files/content to upload, GET /v1/files/content to download), but a quick text read works over exec too. A "Download the report" button in your product can be one exec call that reads the file the agent wrote:

curl -X POST https://api.pusk.ai/v1/instances/ab12cd34ef/exec \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "command": "cat ~/reports/ev-makers-memo.md" }'

Pushing a file in is the same trick in reverse. Encode it on your side and decode it inside the instance:

curl -X POST https://api.pusk.ai/v1/instances/ab12cd34ef/exec \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "command": "mkdir -p ~/data && echo aGVsbG8sd29ybGQK | base64 -d > ~/data/ev-prices.csv" }'

For binary or large files, use the files endpoints on the instance URL instead, where GET /v1/files/content streams a download of any size with no 512 KB cap, or stage them at a URL your backend controls and curl them down from inside the instance.