Skip to main content

Sandboxes and previews

A session's sandbox pauses when nobody uses it. Before you read its files, diff or git state, request the session's preview. That request wakes the sandbox, or creates it. A paused sandbox wakes in the background, so the answer can come back before it is up, with provisioning: true and no URLs.

When you need a running sandbox​

You want toWhat to do
List files, read the diff or read git stateThe read answers without the data. The file list, the changed files and the commit list come back empty, and the patch answers 503. Git state reports available: false. Wake the sandbox first.
Read or write one fileWake the sandbox first.
Reset the previewWake the sandbox first. The reset restarts services in a running sandbox.
Commit or pushNothing to do. These wake a paused sandbox themselves.
Send a messageNothing to do. Sending wakes a paused sandbox itself, and creates one for a session that has none. The turn starts once the sandbox is up.

Wake the sandbox​

Request the session's preview. Leave out sessionId to ask for the project's main preview instead.

curl -s "https://app.kosuke.ai/api/projects/$PROJECT_ID/preview?sessionId=$SESSION_ID" \
-H "Authorization: Bearer $KOSUKE_API_KEY"

With the CLI, run kosuke preview get <projectId> --session-id <sessionId>.

{
"data": {
"frontendUrls": { "web": "https://…" },
"projectId": "3f1c2a9e-…",
"sandboxKey": "9b2e4f60-…"
}
}

frontendUrls maps each endpoint the project shows in the preview to its URL. The key is the service name, or <service>-<endpoint> for a service's second and later endpoints.

Read the response​

Read the flags before the URLs. A refusal about capacity or billing still answers 200.

ResponseMeaningWhat to do
frontendUrls has URLsThe sandbox is up.Wait for its services, then read.
provisioning: true, empty frontendUrlsThe sandbox is already starting.Poll the health request until state is healthy.
creditLimitReached: true, empty frontendUrlsThe workspace is blocked on billing, so nothing started.Stop. Retrying fails until an admin sorts out billing under Plans and billing.
sandboxLimitReached: true, empty frontendUrlsThe workspace already runs as many session sandboxes as its plan allows.Free a slot, or wait for an idle sandbox to pause, then ask again.
Empty frontendUrls and no flagThe session is in the Backlog, Completed or Archived. Or the main preview is being deployed. Or no service is exposed as a preview.Read the session again. For a live session, poll the health request.
400 with an error messageThe project has never been deployed, a deploy is under way, the session has no branch yet, or the project's GitHub access needs reconnecting.Act on the message. Ask again once the deploy ends.

Wait for the services​

The preview request returns when the sandbox is up. Its services may still be starting. Poll the health request until state is healthy:

curl -s "https://app.kosuke.ai/api/projects/$PROJECT_ID/preview/health?sessionId=$SESSION_ID" \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"state": "healthy",
"frontendUrls": { "web": "https://…" },
"services": [{ "name": "agent", "httpResult": "healthy" }, { "name": "web", "httpResult": "healthy" }],
"sandboxAvailable": true
}
}

state is starting or healthy. paused: true or needsStart: true means nothing is bringing the sandbox up, so request the preview once more. indeterminate: true means this read learned nothing, because a pause or resume held the sandbox or it did not answer. Ignore the rest of the answer and ask again in a few seconds, without requesting the preview. With the CLI, run kosuke preview health <projectId> --session-id <sessionId>.

A sandbox you woke pauses again when it sits idle. Request the preview again before a later read.

Free a slot​

Set WORKSPACE_ID to the project's orgId, from GET /api/projects/{projectId}. Then read how many sandboxes may run at once, and which sessions hold them:

curl -s "https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/sandbox-limit" \
-H "Authorization: Bearer $KOSUKE_API_KEY"
{
"data": {
"maxConcurrentSandboxes": 5,
"runningSessions": [
{ "sessionId": "9b2e4f60-…", "title": "Add a healthz endpoint", "projectName": "storefront", "branch": "…" }
]
}
}

maxConcurrentSandboxes is null on a plan with no limit. Pause the sandboxes of up to 50 sessions at once:

curl -s -X POST "https://app.kosuke.ai/api/organizations/$WORKSPACE_ID/stop-sandboxes" \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sessionIds": ["9b2e4f60-…"]}'

The response lists each session with stopped: true or false. A paused sandbox keeps its work and wakes on the next preview request or message. Plans and billing lists each plan's limit.

Reset the preview​

A reset restarts the preview's services inside the running sandbox. Wake the sandbox first.

curl -s -X POST "https://app.kosuke.ai/api/projects/$PROJECT_ID/preview/reset" \
-H "Authorization: Bearer $KOSUKE_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"sessionId\": \"$SESSION_ID\"}"

The reset answers with status: "queued" inside data, next to projectId and sandboxKey, and runs in the background. Poll the health request to see the services come back. A reset of a Backlog, Completed or Archived session answers 400.

Next steps​