{"openapi":"3.1.0","info":{"title":"orkestr API","description":"Public REST API for orkestr, the EU-hosted deployment platform. Manage projects, environments, deployments, serverless functions, sandboxes, add-ons, domains, and monitoring. Authenticate with an orkestr API token (console -> Settings -> API) sent as `Authorization: Bearer <token>`.","version":"0.1.0","contact":{"name":"orkestr","url":"https://orkestr.eu/contact"}},"paths":{"/api/v1/projects":{"get":{"tags":["v1","v1:projects"],"summary":"List Projects","description":"List all your projects (including ones in teams you belong to).","operationId":"listProjects","security":[{"apiToken":[]}],"parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","v1:projects"],"summary":"Create Project","description":"Create a new project. Auto-creates a production environment.","operationId":"createProject","security":[{"apiToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}":{"get":{"tags":["v1","v1:projects"],"summary":"Get Project","description":"Get a single project by ID.","operationId":"getProject","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","v1:projects"],"summary":"Update Project","description":"Update project settings.","operationId":"updateProject","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","v1:projects"],"summary":"Delete Project","description":"Delete a project and destroy its containers.","operationId":"deleteProject","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/analyze":{"post":{"tags":["v1","v1:projects"],"summary":"Analyze Project","description":"Analyze a project's repository — detect framework, generate Dockerfile.","operationId":"analyzeProject","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepoAnalysis"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/environments":{"get":{"tags":["v1","v1:environments"],"summary":"List Environments","description":"List environments for a project.","operationId":"listEnvironments","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentResponse"},"title":"Response List Environments Api V1 Projects  Project Id  Environments Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","v1:environments"],"summary":"Create Environment","description":"Create a new environment for a project.","operationId":"createEnvironment","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/environments/{env_id}":{"patch":{"tags":["v1","v1:environments"],"summary":"Update Environment","description":"Update an environment's settings.","operationId":"updateEnvironment","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"env_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Env Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","v1:environments"],"summary":"Delete Environment","description":"Delete a non-production environment.","operationId":"deleteEnvironment","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"env_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Env Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/deployments":{"post":{"tags":["v1","v1:deployments"],"summary":"Trigger Deployment","description":"Trigger a new deployment. Defaults to production environment.","operationId":"triggerDeployment","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"environment_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1","v1:deployments"],"summary":"List Deployments","description":"List deployments for a project.","operationId":"listDeployments","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/deployments/{deployment_id}":{"get":{"tags":["v1","v1:deployments"],"summary":"Get Deployment","description":"Get deployment details including pipeline steps.","operationId":"getDeployment","security":[{"apiToken":[]}],"parameters":[{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Deployment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/deployments/{deployment_id}/logs":{"get":{"tags":["v1","v1:deployments"],"summary":"Get Deployment Logs","description":"Get all stored logs for a deployment, ordered by pipeline step.","operationId":"getDeploymentLogs","security":[{"apiToken":[]}],"parameters":[{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Deployment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/deployments/{deployment_id}/rollback":{"post":{"tags":["v1","v1:deployments"],"summary":"Rollback Deployment","description":"Rollback to a previous deployment's Docker image. Requires Pro or Team plan.\n\nBehavior mirrors the internal endpoint in `app/api/deployments.py`:\n  * Instant: image still in the registry → pipeline reuses it (~10s).\n  * Rebuild (only when allow_rebuild=true): image was pruned → full\n    clone + checkout the original commit + rebuild.","operationId":"rollbackDeployment","security":[{"apiToken":[]}],"parameters":[{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Deployment Id"}},{"name":"allow_rebuild","in":"query","required":false,"schema":{"type":"boolean","description":"When true and the target's image was pruned from the registry, rebuild from the original commit instead of failing. Default false keeps the rollback strictly instant -- recommended for auto-rollback scripts where slow rebuilds would defeat the recovery SLA.","default":false,"title":"Allow Rebuild"},"description":"When true and the target's image was pruned from the registry, rebuild from the original commit instead of failing. Default false keeps the rollback strictly instant -- recommended for auto-rollback scripts where slow rebuilds would defeat the recovery SLA."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/addons":{"get":{"tags":["v1","v1:addons"],"summary":"List Addons","description":"List add-ons for a project.","operationId":"listAddons","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","v1:addons"],"summary":"Create Addon","description":"Provision a new add-on.","operationId":"createAddon","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/addons/{addon_id}":{"delete":{"tags":["v1","v1:addons"],"summary":"Delete Addon","description":"Destroy an add-on and its data.","operationId":"deleteAddon","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1","v1:addons"],"summary":"Addon Get","description":"Get a single add-on's details including connection URL.","operationId":"addonGet","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/stats":{"get":{"tags":["v1","v1:monitoring"],"summary":"Get Project Stats","description":"Get container resource stats (CPU, memory, network I/O).","operationId":"getProjectStats","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"environment_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/logs":{"get":{"tags":["v1","v1:monitoring"],"summary":"Get Runtime Logs","description":"Get application runtime logs (stdout/stderr).","operationId":"getRuntimeLogs","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"environment_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"}},{"name":"lines","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":200,"title":"Lines"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/health":{"get":{"tags":["v1","v1:monitoring"],"summary":"Get Container Health","description":"Get container health info: status, uptime, restart count.","operationId":"getContainerHealth","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"environment_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/check-name/{name}":{"get":{"tags":["v1","v1:functions"],"summary":"Fn Check Name","description":"Check if a function slug is available.","operationId":"fnCheckName","security":[{"apiToken":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions":{"get":{"tags":["v1","v1:functions"],"summary":"Fn List","description":"List your serverless functions.","operationId":"fnList","security":[{"apiToken":[]}],"parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"workspace","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","v1:functions"],"summary":"Fn Create","description":"Create a serverless function. Returns the API key in plaintext if auth_mode=api_key.","operationId":"fnCreate","security":[{"apiToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/{function_id}":{"get":{"tags":["v1","v1:functions"],"summary":"Fn Get","description":"Get function details.","operationId":"fnGet","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","v1:functions"],"summary":"Fn Update","description":"Update a function. Code/dep changes flag pending_deploy=True.","operationId":"fnUpdate","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","v1:functions"],"summary":"Fn Delete","description":"Delete a function and destroy its container.","operationId":"fnDelete","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/{function_id}/deploy":{"post":{"tags":["v1","v1:functions"],"summary":"Fn Deploy","description":"Build and deploy the function from its current handler_code/dependencies.","operationId":"fnDeploy","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/{function_id}/logs":{"get":{"tags":["v1","v1:functions"],"summary":"Fn Logs","description":"Get runtime logs from the function's container.","operationId":"fnLogs","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}},{"name":"lines","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Lines"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/{function_id}/invoke":{"post":{"tags":["v1","v1:functions"],"summary":"Fn Invoke","description":"Invoke a deployed function. Body fields: method, path, body, headers, query.","operationId":"fnInvoke","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvokeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/{function_id}/env-vars":{"get":{"tags":["v1","v1:functions"],"summary":"Fn Env Vars","description":"Return decrypted environment variables for a function.","operationId":"fnEnvVars","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/{function_id}/metrics":{"get":{"tags":["v1","v1:functions"],"summary":"Fn Metrics","description":"Get request metrics: requests/min, error rate, latency percentiles.","operationId":"fnMetrics","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(5m|15m|1h|6h|24h)$","default":"1h","title":"Period"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/functions/{function_id}/rotate-api-key":{"post":{"tags":["v1","v1:functions"],"summary":"Fn Rotate Key","description":"Rotate the function's API key. Only valid when auth_mode='api_key'.","operationId":"fnRotateKey","security":[{"apiToken":[]}],"parameters":[{"name":"function_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Function Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/check-name/{name}":{"get":{"tags":["v1","v1:projects"],"summary":"Project Check Name","description":"Check if a project slug is available.","operationId":"projectCheckName","security":[{"apiToken":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/env-vars":{"get":{"tags":["v1","v1:projects"],"summary":"Project Env Vars","description":"Return decrypted env vars for a project (project-level defaults).","operationId":"projectEnvVars","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/webhook":{"get":{"tags":["v1","v1:projects"],"summary":"Project Webhook","description":"Get webhook info for a project: provider, URL, last delivery.","operationId":"projectWebhook","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/webhook/toggle":{"post":{"tags":["v1","v1:projects"],"summary":"Project Webhook Toggle","description":"Enable or disable auto-deploy on git push.","operationId":"projectWebhookToggle","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"enable","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Enable"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/environments/{env_id}/env-vars":{"get":{"tags":["v1","v1:environments"],"summary":"Env Env Vars","description":"Return decrypted env vars for a specific environment.","operationId":"envEnvVars","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"env_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Env Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/deployments/{deployment_id}/build-log":{"get":{"tags":["v1","v1:deployments"],"summary":"Deployment Build Log","description":"Return the full builder output (Kaniko stderr) for a deployment.","operationId":"deploymentBuildLog","security":[{"apiToken":[]}],"parameters":[{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Deployment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/addons/{addon_id}/auto-backup":{"patch":{"tags":["v1","v1:addons"],"summary":"Addon Toggle Auto Backup","description":"Toggle daily auto-backup for an add-on. Pro/Team only.","operationId":"addonToggleAutoBackup","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/addons/{addon_id}/backup-info":{"get":{"tags":["v1","v1:addons"],"summary":"Addon Backup Info","description":"Get backup plan info: retention days, daily quota, next scheduled run.","operationId":"addonBackupInfo","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/addons/{addon_id}/backups":{"get":{"tags":["v1","v1:addons"],"summary":"Backups List","description":"List backups for an add-on.","operationId":"backupsList","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["v1","v1:addons"],"summary":"Backups Create","description":"Trigger a manual backup.","operationId":"backupsCreate","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/addons/{addon_id}/backups/{backup_id}/download":{"get":{"tags":["v1","v1:addons"],"summary":"Backups Download","description":"Get a presigned download URL for a completed backup.","operationId":"backupsDownload","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}},{"name":"backup_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Backup Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/addons/{addon_id}/backups/{backup_id}":{"delete":{"tags":["v1","v1:addons"],"summary":"Backups Delete","description":"Delete a backup.","operationId":"backupsDelete","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Addon Id"}},{"name":"backup_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Backup Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/sleep":{"post":{"tags":["v1","v1:monitoring"],"summary":"Project Sleep","description":"Manually put a container to sleep to stop billing CPU.","operationId":"projectSleep","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"environment_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/wake":{"post":{"tags":["v1","v1:monitoring"],"summary":"Project Wake","description":"Wake a sleeping container.","operationId":"projectWake","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"environment_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/deployment-stats":{"get":{"tags":["v1","v1:monitoring"],"summary":"Project Deployment Stats","description":"Get deployment success rate, average duration, last deploy.","operationId":"projectDeploymentStats","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/request-metrics":{"get":{"tags":["v1","v1:monitoring"],"summary":"Project Request Metrics","description":"Request volume, error rate, p50/p95/p99 latency.","operationId":"projectRequestMetrics","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(5m|15m|1h|6h|24h)$","default":"1h","title":"Period"}},{"name":"environment_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/app-health":{"get":{"tags":["v1","v1:monitoring"],"summary":"Project App Health","description":"Live app health from Traefik buckets, with deploy-status fallback.","operationId":"projectAppHealth","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/domains":{"get":{"tags":["v1","v1:domains"],"summary":"Domains List","description":"List all projects with their custom domain status.","operationId":"domainsList","security":[{"apiToken":[]}],"parameters":[{"name":"workspace","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/domains/{project_id}/verify":{"post":{"tags":["v1","v1:domains"],"summary":"Domains Verify","description":"Verify the project's custom domain DNS points to orkestr.","operationId":"domainsVerify","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/activity":{"get":{"tags":["v1","v1:activity"],"summary":"Activity List","description":"Recent activity (audit log) for the current user.","operationId":"activityList","security":[{"apiToken":[]}],"parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}},{"name":"workspace","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace"}},{"name":"actor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by actor: a worker UUID, or \"user\" for human sessions and personal tokens only.","title":"Actor"},"description":"Filter by actor: a worker UUID, or \"user\" for human sessions and personal tokens only."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard/summary":{"get":{"tags":["v1","v1:activity"],"summary":"Dashboard Summary","description":"Project count, recent deployments, plan usage.","operationId":"dashboardSummary","security":[{"apiToken":[]}],"parameters":[{"name":"workspace","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/images":{"get":{"tags":["v1","v1:registry"],"summary":"Registry List Images","description":"List Docker images stored in the registry for a project.","operationId":"registryListImages","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/images/{tag}/scan":{"post":{"tags":["v1","v1:registry"],"summary":"Registry Scan Image","description":"Trigger an on-demand security scan for an image tag.","operationId":"registryScanImage","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"tag","in":"path","required":true,"schema":{"type":"string","title":"Tag"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/images/{tag}":{"delete":{"tags":["v1","v1:registry"],"summary":"Registry Delete Image","description":"Delete an image tag from the registry. The currently-live image is protected.","operationId":"registryDeleteImage","security":[{"apiToken":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"tag","in":"path","required":true,"schema":{"type":"string","title":"Tag"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications":{"get":{"tags":["v1","v1:notifications"],"summary":"Notifications List","description":"50 most recent notifications for the current user.","operationId":"notificationsList","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"apiToken":[]}]}},"/api/v1/notifications/{notification_id}/read":{"patch":{"tags":["v1","v1:notifications"],"summary":"Notifications Mark Read","description":"Mark a notification as read.","operationId":"notificationsMarkRead","security":[{"apiToken":[]}],"parameters":[{"name":"notification_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Notification Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/read-all":{"post":{"tags":["v1","v1:notifications"],"summary":"Notifications Mark All Read","description":"Mark all notifications as read.","operationId":"notificationsMarkAllRead","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"apiToken":[]}]}},"/api/v1/api-tokens":{"get":{"tags":["v1","v1:tokens"],"summary":"Tokens List","description":"List your API tokens (hashes only, never the raw token).","operationId":"tokensList","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"apiToken":[]}]},"post":{"tags":["v1","v1:tokens"],"summary":"Tokens Create","description":"Create a new API token. The plaintext token is returned exactly once.","operationId":"tokensCreate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiTokenCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiToken":[]}]}},"/api/v1/api-tokens/{token_id}":{"delete":{"tags":["v1","v1:tokens"],"summary":"Tokens Delete","description":"Revoke an API token.","operationId":"tokensDelete","security":[{"apiToken":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups":{"get":{"tags":["v1","v1:groups"],"summary":"Groups List","description":"List your project groups (workspaces).","operationId":"groupsList","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"apiToken":[]}]},"post":{"tags":["v1","v1:groups"],"summary":"Groups Create","description":"Create a project group.","operationId":"groupsCreate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiToken":[]}]}},"/api/v1/groups/{group_id}":{"get":{"tags":["v1","v1:groups"],"summary":"Groups Get","description":"Get a group with its assigned projects.","operationId":"groupsGet","security":[{"apiToken":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["v1","v1:groups"],"summary":"Groups Update","description":"Update a group's name or description.","operationId":"groupsUpdate","security":[{"apiToken":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","v1:groups"],"summary":"Groups Delete","description":"Delete a group. Projects are not deleted, just unassigned.","operationId":"groupsDelete","security":[{"apiToken":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_id}/projects/{project_id}":{"post":{"tags":["v1","v1:groups"],"summary":"Groups Add Project","description":"Assign a project to a group.","operationId":"groupsAddProject","security":[{"apiToken":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1","v1:groups"],"summary":"Groups Remove Project","description":"Remove a project from a group.","operationId":"groupsRemoveProject","security":[{"apiToken":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Create a sandbox","operationId":"createASandbox","security":[{"apiToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"List sandboxes owned by the caller","description":"Lists the caller's sandboxes, newest first. Filter by `status` and by metadata tags with repeated `metadata[key]=value` params (AND across keys, exact match - the 'find user X's session' pattern). Cursor-paged: when `next_cursor` is non-null, pass it back as `cursor` for the next page. Keep the filters identical across pages.","operationId":"listSandboxesOwnedByTheCaller","security":[{"apiToken":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/snapshots":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Capture a named, forkable snapshot of a running sandbox","operationId":"captureANamedForkableSnapshotOfARunningSandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/snapshots":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"List named snapshots","operationId":"listNamedSnapshots","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotList"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/snapshots/{snapshot_id}":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Get a named snapshot","operationId":"getANamedSnapshot","security":[{"apiToken":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","title":"Snapshot Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Delete a named snapshot","operationId":"deleteANamedSnapshot","security":[{"apiToken":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","title":"Snapshot Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/limits":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Sandbox sizes and limits available to the caller","description":"Report the caller's sandbox envelope - allowed sizes, caps, usage.\n\nLets SDK and agent callers stay inside their plan without learning\nthe limits from a rejected create. Declared before the\n`/sandboxes/{sandbox_id}` route so `limits` is not parsed as an id.","operationId":"sandboxSizesAndLimitsAvailableToTheCaller","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLimitsResponse"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/usage":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Per-sandbox compute usage this billing month","description":"Per-sandbox GB-hours / CPU-hours this month, keyed by sandbox id.\n\nLets the console show usage per row without a query per sandbox.\nDeclared before `/sandboxes/{sandbox_id}` so `usage` is not parsed as\nan id. Sandboxes with no samples yet are omitted (treat as zero).","operationId":"perSandboxComputeUsageThisBillingMonth","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxUsageResponse"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/billing":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"PAYG spend + cap status for the current billing month","description":"This month's PAYG spend, the effective cap, and where spend sits\nagainst it. Declared before `/sandboxes/{sandbox_id}` so `billing` is not\nparsed as an id.","operationId":"paygSpendCapStatusForTheCurrentBillingMonth","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxBillingResponse"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/spend-cap":{"patch":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Set or clear the monthly sandbox spend cap (paid plans only)","description":"Set, reset, or opt out of the monthly spend cap. Session-only: an API\ntoken must not be able to raise the cap on the account that issued it.\n\nThe free sandbox tier has no PAYG, so there is no cap to manage (400).\nOtherwise: uncapped wins; else a number enforces that cap; else null falls\nback to the platform default.","operationId":"setOrClearTheMonthlySandboxSpendCapPaidPlansOnly","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpendCapUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxBillingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/log-retention":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"How long sandbox activity records are kept for this account","description":"The account's activity-log retention window, the tier ceiling, and the\ncutoff the next daily purge would apply. Declared before\n`/sandboxes/{sandbox_id}` so `log-retention` is not parsed as an id.","operationId":"howLongSandboxActivityRecordsAreKeptForThisAccount","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLogRetentionResponse"}}}}},"security":[{"apiToken":[]}]},"patch":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Set or clear the sandbox activity-log retention window","description":"Choose how long this account's sandbox activity records are kept, or\npass null to keep them for the life of the account (the default).\n\nSession-only, like the spend cap: an API token must not be able to shorten\nretention - and so destroy the audit trail of its own activity - on the\naccount that issued it.","operationId":"setOrClearTheSandboxActivityLogRetentionWindow","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLogRetentionUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxLogRetentionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/pay-now":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Settle the outstanding PAYG balance now (paid plans only)","description":"Charge the caller's outstanding balance immediately instead of waiting\nfor the monthly invoice. For consolidated (non-subscription) users this\nsettles the WHOLE account - plan + seats + project overage + sandbox PAYG -\nas one charge; subscription users settle sandbox PAYG only (their plan rides\nthe Mollie sub, which handles its own retries). Session-only: an API token\nmust not be able to trigger a real charge. Ignores the monthly EUR 10 floor -\nthe user opted in - but never charges below Mollie's minimum (a zero/sub-\nminimum balance returns the snapshot unchanged).","operationId":"settleTheOutstandingPAYGBalanceNowPaidPlansOnly","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxBillingResponse"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/volumes":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"List persistent volumes owned by the caller","operationId":"listPersistentVolumesOwnedByTheCaller","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeListResponse"}}}}},"security":[{"apiToken":[]}]},"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Create a persistent volume","description":"Register a persistent volume (ORK-155). The ext4 file is materialized\nlazily on the host the first sandbox that attaches it lands on - so this\nonly reserves the name + size; node_id stays null until first attach.\nAn explicit ``region`` (ORK-182) pins where that first materialization\nhappens; omitted, the volume follows the first sandbox that attaches it.","operationId":"createAPersistentVolume","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/volumes/{volume_id}/move":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Move a persistent volume to another region","description":"Re-home a detached volume to another region (ORK-182).\n\nThe live ext4 is checkpointed to object storage synchronously first - the\npost-terminate checkpoint is best-effort and can lag, and an intentional\nmove must carry the latest bytes - then the old box's file is dropped and\nthe volume re-materializes from the checkpoint in the target region on its\nnext attach. Rejected while a live sandbox holds the volume.","operationId":"moveAPersistentVolumeToAnotherRegion","security":[{"apiToken":[]}],"parameters":[{"name":"volume_id","in":"path","required":true,"schema":{"type":"string","title":"Volume Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeMove"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/volumes/{volume_id}":{"patch":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Update a persistent volume's auto-destroy lifetime","description":"Set, change, or clear (null) a volume's auto-destroy lifetime. The\ndeadline is always counted from the volume's creation, not from this call,\nso shortening the lifetime of an old volume can make it eligible for\ndestruction on the next sweep - the response's ``expires_at`` says exactly\nwhen.","operationId":"updateAPersistentVolumeSAutoDestroyLifetime","security":[{"apiToken":[]}],"parameters":[{"name":"volume_id","in":"path","required":true,"schema":{"type":"string","title":"Volume Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VolumeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Delete a persistent volume","description":"Delete a volume and its data. Rejected while the volume is attached to a\nlive sandbox - terminate that sandbox first.","operationId":"deleteAPersistentVolume","security":[{"apiToken":[]}],"parameters":[{"name":"volume_id","in":"path","required":true,"schema":{"type":"string","title":"Volume Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/webhooks":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"List lifecycle webhooks","operationId":"listLifecycleWebhooks","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookListResponse"}}}}},"security":[{"apiToken":[]}]},"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Register a lifecycle webhook","description":"Register an endpoint to receive sandbox lifecycle events as signed POSTs (sandbox.created / .paused / .resumed / .terminated / .expired, template.build_finished, volume.moved) instead of polling the events feed. The response includes the signing `secret` ONCE - verify each delivery by comparing X-Orkestr-Signature against 'sha256=' + HMAC-SHA256(secret, raw body). Deliveries are retried 3 times, 10 seconds apart; after too many consecutive failed deliveries the webhook is disabled until you re-enable it.","operationId":"registerALifecycleWebhook","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiToken":[]}]}},"/v1/sandboxes/webhooks/{webhook_id}/enable":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Re-enable a disabled webhook","description":"Re-arm a webhook that was disabled after consecutive failed deliveries. Resets the failure counter; the URL is re-validated.","operationId":"reEnableADisabledWebhook","security":[{"apiToken":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/webhooks/{webhook_id}":{"delete":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Delete a lifecycle webhook","operationId":"deleteALifecycleWebhook","security":[{"apiToken":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/events":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Account-wide sandbox activity feed","description":"Every activity row across all your sandboxes, newest first - the polling side of lifecycle observability. Filter with `sandbox_id` and repeated `event_type` params; page older history with `before` (pass back `next_before`); poll for new activity with `since` (strictly newer than a timestamp you have seen).","operationId":"accountWideSandboxActivityFeed","security":[{"apiToken":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Return events strictly older than this timestamp.","title":"Before"},"description":"Return events strictly older than this timestamp."},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Return events strictly newer than this timestamp.","title":"Since"},"description":"Return events strictly newer than this timestamp."},{"name":"sandbox_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only events from this sandbox (public sbx_... id).","title":"Sandbox Id"},"description":"Only events from this sandbox (public sbx_... id)."},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Only these event types (repeatable), e.g. event_type=created&event_type=terminate.","title":"Event Type"},"description":"Only these event types (repeatable), e.g. event_type=created&event_type=terminate."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountEventsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Get sandbox state","operationId":"getSandboxState","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Terminate a sandbox","operationId":"terminateASandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/host":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Public preview URL for a sandbox port","description":"Return the public URL that maps to a port the sandbox guest is serving (e.g. a dev server on 3000). The URL is public: its capability is the unguessable sandbox id in the hostname. Requires a card on file and a networked sandbox (network 'restricted' or 'open'); an 'off' sandbox has no port to expose. The URL is stable for the sandbox's lifetime, but only serves traffic while it is running.","operationId":"publicPreviewURLForASandboxPort","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"port","in":"query","required":true,"schema":{"type":"integer","maximum":65535,"minimum":1,"description":"The guest port to expose.","title":"Port"},"description":"The guest port to expose."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxHostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/events":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Activity record for a sandbox","description":"The audit trail of what happened in this sandbox - commands run, files written/read/deleted, pause/resume/terminate - newest first. Not command output: each row is the action plus its outcome. Page with `before` (pass back the response's `next_before`).","operationId":"activityRecordForASandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Return events strictly older than this timestamp.","title":"Before"},"description":"Return events strictly older than this timestamp."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxEventsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/usage":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Lifetime compute usage for one sandbox","description":"This sandbox's total GB-hours and CPU-hours over its whole life (not month-scoped). Powers the per-sandbox usage card in the console. Zero until the first metering sample lands.","operationId":"lifetimeComputeUsageForOneSandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxUsageEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/metrics":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Live CPU + memory metrics for one sandbox","description":"Live per-sandbox CPU and memory - the latest reading plus a rolling ~60s sample window, and the sandbox's lifetime totals. Read-only telemetry: a paused or terminated sandbox returns 200 with null live usage and an empty sample window (read `sandbox_status` to tell why), not an error. Pass `since` (Unix seconds) to fetch only samples newer than your last poll. Poll no faster than `sample_interval_seconds`.","operationId":"liveCPUMemoryMetricsForOneSandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Return only samples with t > this Unix-seconds value.","title":"Since"},"description":"Return only samples with t > this Unix-seconds value."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxMetricsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/exec":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Run a command in a sandbox","description":"Run a shell command. With `stream=false` (default) the buffered result is returned. With `stream=true` the response is a Server-Sent-Events stream: one `chunk` event per stdout/stderr burst, then a final `exit` event.","operationId":"runACommandInASandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/files":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Write a file into a sandbox","operationId":"writeAFileIntoASandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileWriteRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Read a file or list a directory","description":"Returns one shape for both files and directories. `is_dir` flags which fields are populated: file -> `content` + `size`; directory -> `entries`.","operationId":"readAFileOrListADirectory","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"path","in":"query","required":true,"schema":{"type":"string","description":"Absolute path inside the sandbox","title":"Path"},"description":"Absolute path inside the sandbox"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileGetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Delete a file from a sandbox","operationId":"deleteAFileFromASandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"path","in":"query","required":true,"schema":{"type":"string","description":"Absolute path inside the sandbox","title":"Path"},"description":"Absolute path inside the sandbox"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/files/mkdir":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Create a directory","description":"Create a directory. With parents=true (default) it is `mkdir -p` - missing parents are created and an existing directory is a no-op. With parents=false the parent must exist and an existing path errors.","operationId":"createADirectory","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MkdirRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/files/move":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Move or rename a file or directory","description":"Move/rename `source` to `destination` (mv). Both absolute.","operationId":"moveOrRenameAFileOrDirectory","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/files/stat":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Stat a path (exists / type / size / mode)","description":"Metadata for a path. `exists=false` is a normal result (not a 404), so this doubles as an existence check. When it exists: `is_dir`, `size` (bytes), `mode` (octal int), `modified_at`.","operationId":"statAPathExistsTypeSizeMode","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"path","in":"query","required":true,"schema":{"type":"string","description":"Absolute path inside the sandbox","title":"Path"},"description":"Absolute path inside the sandbox"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileStatResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/files/presign-download":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Mint a pre-signed download URL for a file","description":"Returns an expiring URL that streams the file straight from the sandbox's host with a plain GET - no auth header, no base64, no 16 MiB cap. Hand it to a browser or another service; it stops working at `expires_at`.","operationId":"mintAPreSignedDownloadURLForAFile","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/files/presign-upload":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Mint a pre-signed upload URL for a file","description":"Returns an expiring URL that accepts a raw PUT body (Content-Length required) and writes it to the given path - the large-file upload path. Uploads land with mode 0644 under the writable roots.","operationId":"mintAPreSignedUploadURLForAFile","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/files/batch":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Write many files in one call","description":"Up to 64 files in one request - an agent scaffolding a project without N round-trips. Files are written in order; a failed file reports in its own result row and never aborts the rest.","operationId":"writeManyFilesInOneCall","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileBatchWriteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileBatchWriteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/commands":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Start a background command","description":"Run a shell command detached from the request: returns immediately with a command handle while the process keeps running - a dev server, a build, a long job. The process survives pause/resume and dies with the sandbox. Inspect with GET /commands, read output via GET /commands/{id}/logs, stop with DELETE /commands/{id}.","operationId":"startABackgroundCommand","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackgroundCommandStart"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackgroundCommand"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"List background commands","description":"Every background command started in this sandbox, with live status: running, exited (exit_code set), or killed (stopped without an exit code - DELETE, a signal, or the OOM killer).","operationId":"listBackgroundCommands","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackgroundCommandList"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/commands/{command_id}":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Get one background command's status","operationId":"getOneBackgroundCommandSStatus","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"command_id","in":"path","required":true,"schema":{"type":"string","title":"Command Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackgroundCommand"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Kill a background command","description":"SIGTERM to the command's process group, a ~5s grace wait, then SIGKILL for anything still alive. Idempotent: 204 also when the command already finished.","operationId":"killABackgroundCommand","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"command_id","in":"path","required":true,"schema":{"type":"string","title":"Command Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/commands/{command_id}/logs":{"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Read or follow a background command's output","description":"Combined stdout+stderr. Buffered by default: a capped slice from `offset` plus the total size, so callers page through with increasing offsets. With `follow=true` the response is the same SSE stream as streaming exec (chunk frames, then exit when the follow window ends) - reattach to a dev server's output at any time.","operationId":"readOrFollowABackgroundCommandSOutput","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"command_id","in":"path","required":true,"schema":{"type":"string","title":"Command Id"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Byte offset to read from","default":0,"title":"Offset"},"description":"Byte offset to read from"},{"name":"follow","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Follow"}},{"name":"timeout_seconds","in":"query","required":false,"schema":{"type":"integer","maximum":3600,"minimum":1,"description":"follow=true only: how long the stream stays open.","default":300,"title":"Timeout Seconds"},"description":"follow=true only: how long the stream stays open."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/code":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Run code in a persistent kernel","description":"Execute code in a stateful interpreter context: variables, imports and figures persist across calls to the same context, and results come back rich (text, HTML tables, base64 PNG charts, structured tracebacks) rather than as flat stdout. Requires the `code-interpreter` template. Omit `context_id` for the default context. A timeout interrupts the running cell but preserves the context's variables. Kernel contexts survive pause/resume.","operationId":"runCodeInAPersistentKernel","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeExecuteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/code/contexts":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Create an isolated kernel context","operationId":"createAnIsolatedKernelContext","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeContextCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"List kernel contexts","operationId":"listKernelContexts","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeContextList"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/code/contexts/{context_id}/restart":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Restart a kernel context (fresh namespace, same id)","operationId":"restartAKernelContextFreshNamespaceSameId","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"context_id","in":"path","required":true,"schema":{"type":"string","title":"Context Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeContext"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/code/contexts/{context_id}":{"delete":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Shut down and remove a kernel context","operationId":"shutDownAndRemoveAKernelContext","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}},{"name":"context_id","in":"path","required":true,"schema":{"type":"string","title":"Context Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/pause":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Snapshot and suspend a sandbox","description":"Captures the sandbox's memory state to a snapshot and stops billing for compute. Snapshot retention is tier-capped (free: 1, payg: 10, enterprise: 50). Returns 409 if the cap is reached. Works for every network mode - a networked sandbox's IP is held across the pause and rebuilt on resume.","operationId":"snapshotAndSuspendASandbox","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/resume":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Restore a paused sandbox from its snapshot","description":"Restores a paused sandbox's memory image and resumes execution. The sandbox's lifetime clock restarts from the resume. The snapshot is consumed - pause again to take a new one.","operationId":"restoreAPausedSandboxFromItsSnapshot","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/sandboxes/{sandbox_id}/timeout":{"post":{"tags":["v1:sandboxes","v1:sandboxes"],"summary":"Extend a running sandbox's lifetime","description":"Reset the auto-termination clock to run timeout_seconds from now (ORK-200 keep-alive) - the countdown restarts, it is not added to the remaining time. Keep-alive is a compute extension, so a no-card account past its trial credit/window is refused (429). Capped by your tier's max_timeout_seconds. A tier may also set max_running_lifetime_seconds - a hard ceiling on the continuous running window that repeated calls cannot exceed; once the window is used up this returns 409 (lifetime_cap_reached) and the sandbox must be paused/resumed to start a fresh window. Near the cap the effective timeout is clamped to the remaining budget. Only a running sandbox has a wall-clock lifetime; a paused one is on its snapshot TTL, so this returns 409 for a paused or terminated one.","operationId":"extendARunningSandboxSLifetime","security":[{"apiToken":[]}],"parameters":[{"name":"sandbox_id","in":"path","required":true,"schema":{"type":"string","title":"Sandbox Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxTimeoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/templates":{"get":{"tags":["v1:sandboxes","v1:templates"],"summary":"List your custom templates","operationId":"listYourCustomTemplates","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CustomTemplateResponse"},"type":"array","title":"Response List Templates V1 Templates Get"}}}}},"security":[{"apiToken":[]}]},"post":{"tags":["v1:sandboxes","v1:templates"],"summary":"Create (build) a custom template","operationId":"createBuildACustomTemplate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomTemplateCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"apiToken":[]}]}},"/v1/templates/{template_id}":{"get":{"tags":["v1:sandboxes","v1:templates"],"summary":"Get a custom template","operationId":"getACustomTemplate","security":[{"apiToken":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1:sandboxes","v1:templates"],"summary":"Delete a custom template","operationId":"deleteACustomTemplate","security":[{"apiToken":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/templates/{template_id}/tags/{tag}":{"put":{"tags":["v1:sandboxes","v1:templates"],"summary":"Assign a tag to a template build","description":"Point `tag` at this build under the build's name. If the tag already\nexists on another build of the same name it moves here (promotion\nwithout rebuild); the previous build keeps its immutable tmpl_ id and\ncan still be pinned directly.","operationId":"assignATagToATemplateBuild","security":[{"apiToken":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}},{"name":"tag","in":"path","required":true,"schema":{"type":"string","title":"Tag"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["v1:sandboxes","v1:templates"],"summary":"Remove a tag from a template build","operationId":"removeATagFromATemplateBuild","security":[{"apiToken":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}},{"name":"tag","in":"path","required":true,"schema":{"type":"string","title":"Tag"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AccountEventEntry":{"properties":{"id":{"type":"string","title":"Id"},"event_type":{"type":"string","title":"Event Type","description":"created | exec | file_write | file_read | file_delete | pause | resume | terminate"},"outcome":{"type":"string","title":"Outcome","description":"ok | error"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Command run or path touched (truncated)."},"exit_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exit Code"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Ms"},"bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bytes","description":"Bytes written or read."},"detail":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Detail"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"sandbox_id":{"type":"string","title":"Sandbox Id","description":"Public id (sbx_...) of the sandbox the event belongs to."}},"type":"object","required":["id","event_type","outcome","created_at","sandbox_id"],"title":"AccountEventEntry","description":"One activity row in the account-wide feed: a SandboxEventEntry plus\nwhich sandbox it happened in."},"AccountEventsResponse":{"properties":{"events":{"items":{"$ref":"#/components/schemas/AccountEventEntry"},"type":"array","title":"Events"},"next_before":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Before"}},"type":"object","required":["events"],"title":"AccountEventsResponse","description":"A page of the account's sandbox activity across all sandboxes,\nnewest first (ORK-205).\n\nPage older history with `before` (pass back `next_before`); poll for\nnew activity with `since` (events strictly newer than a timestamp you\nhave already seen)."},"ApiTokenCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes","default":["*"]},"expires_in_days":{"anyOf":[{"type":"integer","maximum":365.0,"minimum":1.0},{"type":"null"}],"title":"Expires In Days"}},"type":"object","required":["name"],"title":"ApiTokenCreate"},"BackgroundCommand":{"properties":{"id":{"type":"string","title":"Id","description":"Command id, format cmd_<ulid>"},"command":{"type":"string","title":"Command"},"pid":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pid","description":"In-VM process id (the command's process group)."},"status":{"type":"string","title":"Status"},"exit_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exit Code"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"}},"type":"object","required":["id","command","status"],"title":"BackgroundCommand"},"BackgroundCommandList":{"properties":{"commands":{"items":{"$ref":"#/components/schemas/BackgroundCommand"},"type":"array","title":"Commands"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["commands","total"],"title":"BackgroundCommandList"},"BackgroundCommandStart":{"properties":{"command":{"type":"string","minLength":1,"title":"Command","description":"Shell command to run in the background. Returns immediately with a handle; the process keeps running (and survives pause/resume) until it exits, is killed via DELETE, or the sandbox terminates."},"cwd":{"type":"string","title":"Cwd","description":"Working directory inside sandbox","default":"/workspace"},"env":{"additionalProperties":{"type":"string"},"type":"object","title":"Env","description":"Per-command env overrides"}},"type":"object","required":["command"],"title":"BackgroundCommandStart"},"CodeContext":{"properties":{"context_id":{"type":"string","title":"Context Id"},"language":{"type":"string","title":"Language","default":"python"},"cwd":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cwd"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"executions":{"type":"integer","title":"Executions","default":0},"alive":{"type":"boolean","title":"Alive","description":"False when the kernel process died and has not been restarted by a subsequent call.","default":true}},"type":"object","required":["context_id"],"title":"CodeContext"},"CodeContextCreate":{"properties":{"language":{"type":"string","const":"python","title":"Language","default":"python"},"cwd":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cwd","description":"Working directory for the context's kernel (absolute path; default /workspace)."}},"type":"object","title":"CodeContextCreate"},"CodeContextList":{"properties":{"contexts":{"items":{"$ref":"#/components/schemas/CodeContext"},"type":"array","title":"Contexts"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["contexts","total"],"title":"CodeContextList"},"CodeErrorInfo":{"properties":{"name":{"type":"string","title":"Name","description":"Exception class name."},"value":{"type":"string","title":"Value","description":"Exception message."},"traceback":{"items":{"type":"string"},"type":"array","title":"Traceback","description":"Traceback lines, ANSI-stripped."}},"type":"object","required":["name","value"],"title":"CodeErrorInfo","description":"A structured exception from the kernel (not an HTTP error - the call\nitself succeeded and state advanced up to the raise)."},"CodeExecuteResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CodeResult"},"type":"array","title":"Results"},"stdout":{"type":"string","title":"Stdout"},"stderr":{"type":"string","title":"Stderr"},"error":{"anyOf":[{"$ref":"#/components/schemas/CodeErrorInfo"},{"type":"null"}]},"execution_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Execution Count","description":"Kernel execution counter (the Jupyter In[n])."},"context_id":{"type":"string","title":"Context Id"},"duration_ms":{"type":"integer","title":"Duration Ms"},"interrupted":{"type":"boolean","title":"Interrupted","description":"True when the call hit timeout_seconds and the kernel was interrupted. Variables survive an interrupt.","default":false},"restarted":{"type":"boolean","title":"Restarted","description":"True when the context's kernel had died (e.g. OOM-killed) and was restarted for this call - its previous variables are gone.","default":false},"truncated":{"items":{"type":"string"},"type":"array","title":"Truncated","description":"Outputs cut by size caps, e.g. 'stdout' or 'results[0]:image/png'. Empty when nothing was dropped."}},"type":"object","required":["results","stdout","stderr","context_id","duration_ms"],"title":"CodeExecuteResponse"},"CodeRequest":{"properties":{"code":{"type":"string","minLength":1,"title":"Code","description":"Source code to execute."},"language":{"type":"string","const":"python","title":"Language","description":"Kernel language. Stateful execution is python-only for now; use exec (or the MCP run_code fallback) for node/bash.","default":"python"},"context_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context Id","description":"Kernel context to run in. Omit for the sandbox's default context (created on first use). Create isolated contexts via POST .../code/contexts."},"timeout_seconds":{"type":"integer","maximum":3600.0,"minimum":1.0,"title":"Timeout Seconds","description":"Per-call limit. On timeout the kernel is interrupted - the running cell dies but the context's variables survive.","default":60},"stream":{"type":"boolean","title":"Stream","description":"If true, the response is Server-Sent Events: one `stream` event per output burst, one `result` event per rich result as it is produced, `error` events, then a terminal `done` event with the summary fields. If false, the buffered result is returned.","default":false}},"type":"object","required":["code"],"title":"CodeRequest","description":"Execute code in a persistent kernel (POST /v1/sandboxes/{id}/code).\n\nUnlike exec, calls against the same context share one interpreter:\nvariables, imports and open figures persist between calls. Requires a\ntemplate with the interpreter runtime (code-interpreter, or a custom\ntemplate built from it) - other templates get 409 interpreter_unavailable."},"CodeResult":{"properties":{"type":{"type":"string","enum":["text","html","image_png","json","chart"],"title":"Type"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"text/plain rendering."},"html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Html","description":"text/html rendering."},"png":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Png","description":"Base64-encoded PNG."},"json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"items":{},"type":"array"},{"type":"null"}],"title":"Json","description":"application/json payload."},"chart":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Chart","description":"Parsed chart data (type, axis labels, series) for re-rendering; emitted alongside `png` for supported figures."}},"type":"object","required":["type"],"title":"CodeResult","description":"One rich output of an execution - a display item or the final\nexpression value. `type` names the richest representation present;\nthe individual fields carry every representation the kernel emitted\n(a pandas DataFrame arrives with both `text` and `html`, a matplotlib\nfigure with `png` and - once chart extraction lands - `chart`)."},"CustomTemplateCreate":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name","description":"Human-friendly template name."},"base_template":{"$ref":"#/components/schemas/Template","description":"Built-in base image the template is built on."},"recipe":{"items":{"type":"string"},"type":"array","maxItems":50,"minItems":1,"title":"Recipe","description":"Ordered shell steps run in the build VM, e.g. 'pip install pandas numpy'. Each runs as root with HOME=/root; installs persist into the captured image."},"description":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Description"},"network":{"$ref":"#/components/schemas/NetworkMode","description":"Egress policy while building (installs usually need network). Default 'restricted' (package registries + major APIs).","default":"restricted"},"allow_domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allow Domains","description":"Default custom egress allowlist baked into the template (paid plans). Restricted sandboxes booted from this template inherit these domains - replacing the platform default - unless the create call overrides them with its own allow_domains. Bare hostnames only; omit to use the platform default."},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":10},{"type":"null"}],"title":"Tags","description":"Tags to assign when the build succeeds, e.g. ['v2', 'latest']. A tag that already exists on another build of the same name moves to this one. The first successful build of a name also gets 'default' automatically; later builds only take 'default' by listing it here (or via tag assignment after the build)."},"start_command":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Start Command","description":"Optional command run once, detached, on the first boot of every sandbox created from this template (e.g. 'cd app && npm run dev') - so a sandbox is self-starting with no post-create exec call. Runs as root with cwd /workspace and the sandbox's env (so PORT and create-time env vars are visible). It does NOT re-run on resume (the snapshot already holds the process). Retrievable + non-fatal: if it fails to launch or exits non-zero the sandbox still comes up; check the activity feed / background commands."}},"type":"object","required":["name","base_template","recipe"],"title":"CustomTemplateCreate"},"CustomTemplateResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Template id, format tmpl_<ulid>"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"base_template":{"type":"string","title":"Base Template"},"recipe":{"items":{"type":"string"},"type":"array","title":"Recipe"},"allow_domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allow Domains"},"status":{"type":"string","title":"Status","description":"building | ready | failed"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"size_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Mb"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"start_command":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Command"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"built_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Built At"}},"type":"object","required":["id","name","base_template","recipe","status","created_at"],"title":"CustomTemplateResponse"},"DeploymentListResponse":{"properties":{"deployments":{"items":{"$ref":"#/components/schemas/DeploymentResponse"},"type":"array","title":"Deployments"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["deployments","total"],"title":"DeploymentListResponse"},"DeploymentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"environment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Environment Id"},"trigger":{"type":"string","title":"Trigger"},"commit_sha":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commit Sha"},"commit_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commit Message"},"status":{"type":"string","title":"Status"},"degraded":{"type":"boolean","title":"Degraded","default":false},"docker_image":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Docker Image"},"infrastructure_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Infrastructure Config"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"warnings":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Warnings","default":[]},"failure_diagnostics":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Failure Diagnostics"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"steps":{"items":{"$ref":"#/components/schemas/DeploymentStepResponse"},"type":"array","title":"Steps","default":[]}},"type":"object","required":["id","project_id","trigger","commit_sha","commit_message","status","docker_image","infrastructure_config","duration_seconds","error_message","created_at","completed_at"],"title":"DeploymentResponse"},"DeploymentStepResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"step_name":{"type":"string","title":"Step Name"},"status":{"type":"string","title":"Status"},"log_output":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Log Output"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","step_name","status","log_output","started_at","completed_at"],"title":"DeploymentStepResponse"},"EnvironmentCreate":{"properties":{"name":{"type":"string","maxLength":50,"minLength":2,"pattern":"^[a-z0-9][a-z0-9-]*$","title":"Name"},"branch":{"type":"string","maxLength":100,"title":"Branch"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"auto_deploy":{"type":"boolean","title":"Auto Deploy","default":true}},"type":"object","required":["name","branch"],"title":"EnvironmentCreate"},"EnvironmentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"name":{"type":"string","title":"Name"},"branch":{"type":"string","title":"Branch"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"ip_allowlist":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Ip Allowlist"},"access_policy":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Access Policy"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"},"custom_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Domain"},"is_production":{"type":"boolean","title":"Is Production"},"is_preview":{"type":"boolean","title":"Is Preview","default":false},"preview_meta":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preview Meta"},"auto_deploy":{"type":"boolean","title":"Auto Deploy"},"memory_override_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Memory Override Mb"},"auto_sleep_enabled":{"type":"boolean","title":"Auto Sleep Enabled"},"status":{"type":"string","title":"Status"},"tls_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tls Status"},"tls_issued_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Tls Issued At"},"tls_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Tls Expires At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","project_id","name","branch","env_vars","ip_allowlist","domain","custom_domain","is_production","auto_deploy","memory_override_mb","auto_sleep_enabled","status","created_at","updated_at"],"title":"EnvironmentResponse"},"EnvironmentUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":50,"minLength":2,"pattern":"^[a-z0-9][a-z0-9-]*$"},{"type":"null"}],"title":"Name"},"branch":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Branch"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"auto_deploy":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Deploy"},"ip_allowlist":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Ip Allowlist"},"access_policy":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Access Policy"},"memory_override_mb":{"anyOf":[{"type":"integer","maximum":8192.0,"minimum":128.0},{"type":"null"}],"title":"Memory Override Mb"},"auto_sleep_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Sleep Enabled"},"custom_domain":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Custom Domain"}},"type":"object","title":"EnvironmentUpdate"},"ExecRequest":{"properties":{"command":{"type":"string","minLength":1,"title":"Command","description":"Shell command to run"},"cwd":{"type":"string","title":"Cwd","description":"Working directory inside sandbox","default":"/workspace"},"env":{"additionalProperties":{"type":"string"},"type":"object","title":"Env","description":"Per-call env overrides"},"timeout_seconds":{"type":"integer","maximum":3600.0,"minimum":1.0,"title":"Timeout Seconds","default":60},"stream":{"type":"boolean","title":"Stream","description":"If true, response is SSE with one chunk per stdout/stderr burst. If false, response is the buffered result.","default":false}},"type":"object","required":["command"],"title":"ExecRequest"},"ExecResponse":{"properties":{"stdout":{"type":"string","title":"Stdout"},"stderr":{"type":"string","title":"Stderr"},"exit_code":{"type":"integer","title":"Exit Code"},"duration_ms":{"type":"integer","title":"Duration Ms"}},"type":"object","required":["stdout","stderr","exit_code","duration_ms"],"title":"ExecResponse","description":"Non-streaming exec response. Streaming exec returns SSE; see docs."},"FileBatchEntry":{"properties":{"path":{"type":"string","title":"Path","description":"Absolute path inside sandbox"},"content":{"type":"string","maxLength":16777216,"title":"Content","description":"Base64-encoded file content"},"mode":{"type":"integer","maximum":511.0,"minimum":256.0,"title":"Mode","description":"Unix mode bits (octal)","default":420}},"type":"object","required":["path","content"],"title":"FileBatchEntry"},"FileBatchError":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"FileBatchError"},"FileBatchResult":{"properties":{"path":{"type":"string","title":"Path"},"bytes_written":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bytes Written"},"error":{"anyOf":[{"$ref":"#/components/schemas/FileBatchError"},{"type":"null"}]}},"type":"object","required":["path"],"title":"FileBatchResult"},"FileBatchWriteRequest":{"properties":{"files":{"items":{"$ref":"#/components/schemas/FileBatchEntry"},"type":"array","maxItems":64,"minItems":1,"title":"Files","description":"Up to 64 files, written in order. Each file stays under the one-shot 16 MiB cap; use a pre-signed upload URL for anything bigger."}},"type":"object","required":["files"],"title":"FileBatchWriteRequest"},"FileBatchWriteResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/FileBatchResult"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"FileBatchWriteResponse","description":"Per-file outcomes, in request order. A failed file never aborts the\nrest of the batch - check each row's `error`."},"FileGetResponse":{"properties":{"path":{"type":"string","title":"Path"},"is_dir":{"type":"boolean","title":"Is Dir"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content","description":"Base64-encoded content (files only)"},"size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size","description":"Byte length (files only)"},"entries":{"anyOf":[{"items":{"$ref":"#/components/schemas/FileListEntry"},"type":"array"},{"type":"null"}],"title":"Entries","description":"Directory entries (directories only)"}},"type":"object","required":["path","is_dir"],"title":"FileGetResponse","description":"Single shape for both file-read and directory-list.\n\nWhen `is_dir` is False, `content` and `size` are populated.\nWhen `is_dir` is True, `entries` is populated.\nKept as one shape so the OpenAPI spec and SDK type signatures are flat."},"FileListEntry":{"properties":{"name":{"type":"string","title":"Name"},"is_dir":{"type":"boolean","title":"Is Dir"},"size":{"type":"integer","title":"Size"},"mode":{"type":"integer","title":"Mode"},"modified_at":{"type":"string","format":"date-time","title":"Modified At"}},"type":"object","required":["name","is_dir","size","mode","modified_at"],"title":"FileListEntry"},"FileStatResponse":{"properties":{"path":{"type":"string","title":"Path"},"exists":{"type":"boolean","title":"Exists"},"is_dir":{"type":"boolean","title":"Is Dir","default":false},"size":{"type":"integer","title":"Size","default":0},"mode":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Mode"},"modified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Modified At"}},"type":"object","required":["path","exists"],"title":"FileStatResponse","description":"stat / exists for one path (ORK-202). `exists=false` is a normal\nresult, not a 404 - use it as an existence check."},"FileWriteRequest":{"properties":{"path":{"type":"string","title":"Path","description":"Absolute path inside sandbox"},"content":{"type":"string","title":"Content","description":"Base64-encoded file content. SDKs hide this; raw API callers must base64.b64encode bytes before sending."},"mode":{"type":"integer","maximum":511.0,"minimum":256.0,"title":"Mode","description":"Unix mode bits (octal)","default":420}},"type":"object","required":["path","content"],"title":"FileWriteRequest"},"FunctionCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":2,"pattern":"^[a-z0-9][a-z0-9-]*$","title":"Name"},"display_name":{"type":"string","maxLength":255,"minLength":2,"title":"Display Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"runtime":{"type":"string","maxLength":20,"title":"Runtime"},"handler_code":{"type":"string","maxLength":100000,"minLength":1,"title":"Handler Code"},"dependencies":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Dependencies"},"auth_mode":{"type":"string","maxLength":20,"title":"Auth Mode","default":"public"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"idle_timeout_seconds":{"anyOf":[{"type":"integer","maximum":3600.0,"minimum":10.0},{"type":"null"}],"title":"Idle Timeout Seconds"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"}},"type":"object","required":["name","display_name","runtime","handler_code"],"title":"FunctionCreate"},"FunctionUpdate":{"properties":{"display_name":{"anyOf":[{"type":"string","maxLength":255,"minLength":2},{"type":"null"}],"title":"Display Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"handler_code":{"anyOf":[{"type":"string","maxLength":100000,"minLength":1},{"type":"null"}],"title":"Handler Code"},"dependencies":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Dependencies"},"auth_mode":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Auth Mode"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"idle_timeout_seconds":{"anyOf":[{"type":"integer","maximum":3600.0,"minimum":10.0},{"type":"null"}],"title":"Idle Timeout Seconds"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"}},"type":"object","title":"FunctionUpdate"},"GroupCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":2,"title":"Name"},"slug":{"type":"string","maxLength":100,"minLength":2,"pattern":"^[a-z0-9][a-z0-9-]*$","title":"Slug"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["name","slug"],"title":"GroupCreate"},"GroupUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":2},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","title":"GroupUpdate"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InvokeRequest":{"properties":{"method":{"type":"string","maxLength":10,"title":"Method","default":"POST"},"path":{"type":"string","maxLength":500,"title":"Path","default":"/"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"headers":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Headers"},"query":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Query"}},"type":"object","title":"InvokeRequest"},"MkdirRequest":{"properties":{"path":{"type":"string","title":"Path","description":"Absolute directory path to create."},"parents":{"type":"boolean","title":"Parents","description":"Create missing parent directories (mkdir -p). When false, the parent must already exist.","default":true}},"type":"object","required":["path"],"title":"MkdirRequest"},"MoveRequest":{"properties":{"source":{"type":"string","title":"Source","description":"Absolute path to move/rename from."},"destination":{"type":"string","title":"Destination","description":"Absolute path to move/rename to."}},"type":"object","required":["source","destination"],"title":"MoveRequest"},"NetworkMode":{"type":"string","enum":["off","restricted","open"],"title":"NetworkMode"},"OnTimeout":{"type":"string","enum":["kill","pause"],"title":"OnTimeout","description":"What happens when a sandbox's lifetime clock runs out (ORK-200)."},"PauseResponse":{"properties":{"sandbox_id":{"type":"string","title":"Sandbox Id"},"snapshot_id":{"type":"string","title":"Snapshot Id","description":"Opaque snapshot identifier. Pass to resume to restore. Snapshot retention is tier-capped (free: 1, payg: 10, enterprise: 50)."},"status":{"type":"string","const":"paused","title":"Status"},"snapshot_size_mb":{"type":"integer","title":"Snapshot Size Mb"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"paused_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paused Expires At"}},"type":"object","required":["sandbox_id","snapshot_id","status","snapshot_size_mb","created_at"],"title":"PauseResponse"},"PresignRequest":{"properties":{"path":{"type":"string","title":"Path","description":"Absolute path inside the sandbox."},"expires_in":{"type":"integer","maximum":3600.0,"minimum":60.0,"title":"Expires In","description":"Seconds until the URL stops working (60..3600). Within that window the URL is reusable, like an S3 pre-signed URL.","default":600}},"type":"object","required":["path"],"title":"PresignRequest"},"PresignResponse":{"properties":{"url":{"type":"string","title":"Url"},"method":{"type":"string","title":"Method","description":"HTTP method the URL is signed for"},"path":{"type":"string","title":"Path"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["url","method","path","expires_at"],"title":"PresignResponse","description":"An expiring signed URL that moves file bytes directly between the\nclient and the sandbox's host - no base64, no 16 MiB one-shot cap.\nUse `method` verbatim: GET streams the file down, PUT streams a raw\nrequest body up (Content-Length required)."},"ProjectCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":2,"pattern":"^[a-z0-9][a-z0-9-]*$","title":"Name"},"display_name":{"type":"string","maxLength":255,"minLength":2,"title":"Display Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"repo_url":{"type":"string","maxLength":500,"title":"Repo Url"},"repo_branch":{"type":"string","maxLength":100,"title":"Repo Branch","default":"main"},"build_context":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Build Context"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"resource_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resource Config"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"}},"type":"object","required":["name","display_name","repo_url"],"title":"ProjectCreate"},"ProjectListResponse":{"properties":{"projects":{"items":{"$ref":"#/components/schemas/ProjectResponse"},"type":"array","title":"Projects"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["projects","total"],"title":"ProjectListResponse"},"ProjectResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"repo_url":{"type":"string","title":"Repo Url"},"repo_branch":{"type":"string","title":"Repo Branch"},"framework":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Framework"},"has_dockerfile":{"type":"boolean","title":"Has Dockerfile"},"build_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Build Context"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"resource_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resource Config"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"},"group_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Group Id"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"},"effective_plan":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Effective Plan"},"created_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By User Id"},"created_by_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Username"},"status":{"type":"string","title":"Status"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","name","display_name","description","repo_url","repo_branch","framework","has_dockerfile","build_context","env_vars","resource_config","domain","group_id","status","created_at","updated_at"],"title":"ProjectResponse"},"ProjectUpdate":{"properties":{"display_name":{"anyOf":[{"type":"string","maxLength":255,"minLength":2},{"type":"null"}],"title":"Display Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"repo_branch":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Repo Branch"},"env_vars":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Env Vars"},"resource_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resource Config"},"domain":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Domain"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"}},"type":"object","title":"ProjectUpdate"},"RepoAnalysis":{"properties":{"framework":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Framework"},"runtime":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Runtime"},"has_dockerfile":{"type":"boolean","title":"Has Dockerfile","default":false},"detected_port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Detected Port"},"suggested_cpu":{"type":"number","title":"Suggested Cpu","default":0.25},"suggested_memory":{"type":"integer","title":"Suggested Memory","default":512},"dockerfile_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dockerfile Content"}},"type":"object","title":"RepoAnalysis"},"SandboxBillingResponse":{"properties":{"access_tier":{"type":"string","title":"Access Tier","description":"Sandbox access tier - free | payg | enterprise | unverified (ORK-162). PAYG billing applies to payg/enterprise (card on file)."},"plan":{"type":"string","title":"Plan","description":"DEPRECATED - platform plan, kept one release for back-compat. Use `access_tier`."},"payg_eligible":{"type":"boolean","title":"Payg Eligible","description":"Whether this plan can enter pay-as-you-go at all. False for free (trial-then-wall, no PAYG, no cap to set)."},"trial_exhausted":{"type":"boolean","title":"Trial Exhausted","description":"Whether the one-time compute trial is spent. PAYG (and thus the cap) only bites once this is true."},"spend_this_month_eur":{"type":"number","title":"Spend This Month Eur","description":"PAYG cost accrued since the start of the billing month, in EUR, at the public rates - compute plus billable held storage."},"cap_eur":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cap Eur","description":"The spend cap enforced this month, in EUR, or null when uncapped. At 100% new sandboxes are blocked and running ones are stopped; at 80% the caller is alerted."},"custom_cap_eur":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Custom Cap Eur","description":"The caller's explicitly-set cap, or null when they are on the platform default (default_cap_eur)."},"default_cap_eur":{"type":"number","title":"Default Cap Eur","description":"The platform default cap applied when the caller has not set their own and is not uncapped."},"uncapped":{"type":"boolean","title":"Uncapped","description":"Whether the caller has opted out of the cap entirely (unbounded PAYG). Mutually exclusive with an enforced cap_eur."},"cap_status":{"type":"string","title":"Cap Status","description":"Where spend sits versus the cap: 'uncapped' | 'ok' | 'alert' (>=80%) | 'exceeded' (>=100%)."},"alert_fraction":{"type":"number","title":"Alert Fraction","description":"The fraction of the cap at which the caller is alerted (0.80)."},"storage_gb_held":{"type":"number","title":"Storage Gb Held","description":"Persistent storage the account holds right now, in GB - paused-sandbox snapshots + ready custom-template images. A point-in-time figure for the storage card, not metered GB-hours."},"storage_free_gb":{"type":"number","title":"Storage Free Gb","description":"Free storage allowance in GB. Held storage up to this is free; only the excess is billable (per GB-month). Most accounts sit under it, so storage spend is 0."},"storage_gb_months_billed":{"type":"number","title":"Storage Gb Months Billed","description":"Billable held storage metered so far this billing month, in GB-months (already net of the free allowance). Folded into spend_this_month_eur at the per-GB-month rate; 0 while held storage stays under the allowance.","default":0.0},"accrued_balance_eur":{"type":"number","title":"Accrued Balance Eur","description":"Unbilled PAYG balance since the last invoice - carry-forward from prior months plus the current open month - in EUR. This is exactly what 'Pay Now' settles; the monthly invoice charges only the closed-month portion once it clears the floor. 0 for free plans.","default":0.0},"account_balance_eur":{"type":"number","title":"Account Balance Eur","description":"Whole-account amount owed right now - platform plan, seats, project overage AND sandbox PAYG combined - in EUR. This is what 'Pay Now' settles for consolidated (non-subscription) users. 0 for users on an active Mollie subscription (platform rides the sub) and free plans.","default":0.0},"compute_gib_hours_month":{"type":"number","title":"Compute Gib Hours Month","description":"Metered RAM compute this billing month, in GiB-hours. Drives the post-trial usage card (uncapped, PAYG) once the trial is spent.","default":0.0},"compute_vcpu_hours_month":{"type":"number","title":"Compute Vcpu Hours Month","description":"Metered CPU compute this billing month, in vCPU-hours. Drives the post-trial usage card once the trial is spent.","default":0.0}},"type":"object","required":["access_tier","plan","payg_eligible","trial_exhausted","spend_this_month_eur","default_cap_eur","uncapped","cap_status","alert_fraction","storage_gb_held","storage_free_gb"],"title":"SandboxBillingResponse","description":"The caller's PAYG spend picture for the current billing month.\n\nDrives the console's budget panel: this month's spend, the effective\ncap, and where spend sits against it. Compute is a one-time trial first\n(see SandboxLimitsResponse); PAYG and this cap only apply once a card is\non file (the `payg`/`enterprise` access tiers) and the trial is spent."},"SandboxCpuMetrics":{"properties":{"cores":{"type":"number","title":"Cores","description":"Allocated vCPU cores."},"usage_cores":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Usage Cores","description":"Cores in use at the latest sample (cores * percent)."},"usage_percent":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Usage Percent","description":"Latest CPU use as % of allocated cores - a 1-core sandbox fully pegged reads 100."}},"type":"object","required":["cores"],"title":"SandboxCpuMetrics","description":"Live CPU usage for a sandbox. Usage fields are null when no live\nsample exists (sandbox starting, paused, or terminated)."},"SandboxCreate":{"properties":{"template":{"anyOf":[{"$ref":"#/components/schemas/Template"},{"type":"string"},{"type":"null"}],"title":"Template","description":"Base image template (e.g. 'python-3.12'), or a custom template created via POST /v1/templates - by id (tmpl_..., pins that immutable build), by name (resolves the name's current 'default' tag), or as 'name:tag' (pins a tag). Required unless `snapshot` is given."},"timeout_seconds":{"type":"integer","maximum":86400.0,"minimum":10.0,"title":"Timeout Seconds","description":"Maximum sandbox lifetime in seconds before auto-termination (up to 24 h). The per-tier ceiling (max_timeout_seconds on GET /v1/sandboxes/limits) may be lower than this absolute bound. Extend a running sandbox with POST /v1/sandboxes/{id}/timeout.","default":600},"on_timeout":{"$ref":"#/components/schemas/OnTimeout","description":"What happens when the lifetime runs out. 'kill' (default) terminates the sandbox. 'pause' snapshots it instead, so a later resume picks up where it left off - useful for agent sessions that go idle. On a paid tier the pause always succeeds; on the free tier it falls back to terminate if you are already at your snapshot cap.","default":"kill"},"auto_resume":{"type":"boolean","title":"Auto Resume","description":"When true, running a command or file operation on this sandbox while it is paused resumes it automatically first, instead of returning 409 - and an HTTP request to one of its public preview URLs wakes it the same way. Pairs with on_timeout='pause': the sandbox parks at its deadline and wakes on next use. The implicit resume passes the same admission gates as an explicit resume.","default":false},"preview_auth":{"type":"boolean","title":"Preview Auth","description":"When true, this sandbox's public preview URLs require an access token: the response carries `preview_auth_token`, and a request to a preview URL must present it (header `X-Orkestr-Preview-Token`, cookie, or `?ork_preview_token=`) or gets a 401. Default false keeps previews public (the unguessable hostname is the only capability) so embedding stays header-free.","default":false},"size":{"$ref":"#/components/schemas/SandboxSize","description":"Sandbox size. 'small' = 1 vCPU / 1 GB, 'medium' = 2 vCPU / 4 GB, 'large' = 4 vCPU / 8 GB. Allowed sizes are tier-capped; GET /v1/sandboxes/limits lists the sizes available to you. Default 'small' - it fits every tier.","default":"small"},"network":{"$ref":"#/components/schemas/NetworkMode","description":"Egress policy. 'off': no network. 'restricted': egress only through a preconfigured HTTP/HTTPS proxy (HTTP_PROXY and HTTPS_PROXY are set inside the sandbox) that allows package registries, GitHub and major LLM APIs and blocks everything else - proxy-aware tools (pip, npm, curl, standard HTTP libraries) work as-is, but direct DNS and raw sockets do not. 'open': unrestricted egress. Default 'off'.","default":"off"},"env":{"additionalProperties":{"type":"string"},"type":"object","title":"Env","description":"Environment variables for the sandbox process. Persisted in memory only; not visible after termination."},"metadata":{"additionalProperties":{"type":"string"},"type":"object","title":"Metadata","description":"Caller-defined tags. Echoed back unchanged. Max 16 keys, 256 chars per value."},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region","description":"Region preference (e.g. 'fsn1'). The current region list comes from GET /sandboxes/limits (`regions`). If absent, the control plane picks the region with the most capacity."},"allow_domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allow Domains","description":"Custom egress allowlist for a 'restricted' sandbox. When set, these domains replace the platform default set entirely for this sandbox - still HTTPS only, still proxy-mediated. Bare hostnames only (subdomains are matched automatically). Ignored for 'off'/'open'. Omit to use the default allowlist."},"volume":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Volume","description":"Persistent volume to attach (ORK-155), by name or id (vol_...). Data written under /persist survives termination and re-attaches to a later sandbox that names the same volume. Created on first reference if it does not exist. A volume can only be attached to one running sandbox at a time, and pins the sandbox to the volume's host."},"snapshot":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Snapshot","description":"Fork from a named snapshot (ORK-208): boot a new sandbox from a snap_ id created via POST /v1/sandboxes/{id}/snapshots. The fork inherits the snapshot's template, size, and network - do not pass `template`, `size`, or `volume` with it. Mutually exclusive with `template`."}},"type":"object","title":"SandboxCreate"},"SandboxEndpoints":{"properties":{"exec":{"type":"string","title":"Exec"},"files":{"type":"string","title":"Files"},"pause":{"type":"string","title":"Pause"},"resume":{"type":"string","title":"Resume"}},"type":"object","required":["exec","files","pause","resume"],"title":"SandboxEndpoints"},"SandboxEventEntry":{"properties":{"id":{"type":"string","title":"Id"},"event_type":{"type":"string","title":"Event Type","description":"created | exec | file_write | file_read | file_delete | pause | resume | terminate"},"outcome":{"type":"string","title":"Outcome","description":"ok | error"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Command run or path touched (truncated)."},"exit_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exit Code"},"duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Ms"},"bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bytes","description":"Bytes written or read."},"detail":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Detail"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","event_type","outcome","created_at"],"title":"SandboxEventEntry","description":"One activity row: what happened in a sandbox and how it turned out.\n\nNot a log of output - `summary` is the command or path, the outcome\nfields carry exit code / bytes / duration, `detail` holds structured\nextras."},"SandboxEventsResponse":{"properties":{"events":{"items":{"$ref":"#/components/schemas/SandboxEventEntry"},"type":"array","title":"Events"},"next_before":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Before"}},"type":"object","required":["events"],"title":"SandboxEventsResponse","description":"A page of a sandbox's activity, newest first.\n\n`next_before` is the cursor for the following page: pass it back as the\n`before` query param. Null when there are no older events."},"SandboxHostResponse":{"properties":{"port":{"type":"integer","title":"Port","description":"The guest port being exposed."},"host":{"type":"string","title":"Host","description":"Public hostname, e.g. 3000-01hxyz....sbx.orkestr.run"},"url":{"type":"string","title":"Url","description":"Ready-to-embed https:// URL for the port."}},"type":"object","required":["port","host","url"],"title":"SandboxHostResponse","description":"A public preview endpoint for one sandbox port (ORK-174). `host` is the\nbare hostname, `url` the ready https:// form."},"SandboxLifetimeUsage":{"properties":{"cpu_seconds":{"type":"number","title":"Cpu Seconds","description":"On-CPU seconds since start."},"gb_seconds":{"type":"number","title":"Gb Seconds","description":"GB-seconds of provisioned RAM since start."}},"type":"object","required":["cpu_seconds","gb_seconds"],"title":"SandboxLifetimeUsage","description":"Compute a sandbox has consumed over its whole life (ORK-77).\n\nSourced from drained billing events plus the host's undrained\naccumulator while the sandbox is live, so it stays accurate to the\nsecond; from billing events alone when paused/terminated (trails by\nup to one 60s drain, which does not move for a stopped sandbox)."},"SandboxLimitsResponse":{"properties":{"access_tier":{"type":"string","title":"Access Tier","description":"Sandbox access tier - free | payg | enterprise | unverified (ORK-162). Independent of the platform plan: a sandbox-only user with a card on file is `payg` regardless of any PaaS subscription."},"plan":{"type":"string","title":"Plan","description":"DEPRECATED - the caller's platform plan, kept for one release for back-compat. Use `access_tier` for sandbox entitlements."},"enrolled":{"type":"boolean","title":"Enrolled","description":"Whether the caller has opted into the sandbox beta. Mutating routes (create / exec / files / pause / resume) are refused until the caller enrolls in the console."},"allowed_sizes":{"items":{"$ref":"#/components/schemas/SandboxSize"},"type":"array","title":"Allowed Sizes","description":"Sizes the caller may request - a flat list for a cheap membership check."},"sizes":{"items":{"$ref":"#/components/schemas/SandboxSizeInfo"},"type":"array","title":"Sizes","description":"The full size menu, each flagged with whether the caller's plan allows it (drives upgrade prompts)."},"regions":{"items":{"$ref":"#/components/schemas/SandboxRegionInfo"},"type":"array","title":"Regions","description":"Regions a create may pin right now, from the live host registry (every region with an active host, plus the default). Render this instead of a hardcoded list."},"max_concurrent_memory_mb":{"type":"integer","title":"Max Concurrent Memory Mb","description":"Per-customer concurrent RAM budget in MB. A create is refused once the sum of the caller's live (non-paused) sandbox memory plus the new box would exceed this. Paused sandboxes free their RAM."},"max_concurrent":{"type":"integer","title":"Max Concurrent","description":"The RAM budget expressed as a count of the smallest size (max_concurrent_memory_mb / small RAM) - a back-compat convenience; the real gate is max_concurrent_memory_mb."},"max_snapshots":{"type":"integer","title":"Max Snapshots","description":"Maximum paused sandboxes (snapshots) the caller may hold at once."},"max_named_snapshots":{"type":"integer","title":"Max Named Snapshots","description":"Maximum named, forkable snapshots the caller may hold at once (ORK-208). 0 means snapshot fork is not available on the tier.","default":0},"max_custom_templates":{"type":"integer","title":"Max Custom Templates","description":"Maximum custom templates the caller may keep. 0 means custom templates are not available on the caller's tier."},"max_volumes":{"type":"integer","title":"Max Volumes","description":"Maximum persistent volumes the caller may hold at once (ORK-155).","default":0},"max_volume_gb":{"type":"integer","title":"Max Volume Gb","description":"Maximum combined provisioned size of the caller's persistent volumes, in GB.","default":0},"max_volume_size_gb":{"type":"integer","title":"Max Volume Size Gb","description":"Largest size a SINGLE volume may be provisioned at, in GB. Distinct from max_volume_gb, which bounds the combined size of all of them. Clients should use this as the top of their size picker.","default":100},"default_volume_mb":{"type":"integer","title":"Default Volume Mb","description":"Size a volume gets when the caller does not ask for one - both an inline auto-create (naming a new volume on create_sandbox) and the size a client should pre-select. Per-account, so an account granted many small volumes defaults to a small one instead of the fleet 10 GB.","default":10240},"max_timeout_seconds":{"type":"integer","title":"Max Timeout Seconds","description":"Maximum sandbox lifetime the caller's plan allows, in seconds. A create with a higher timeout_seconds is refused."},"max_running_lifetime_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Running Lifetime Seconds","description":"Hard ceiling (seconds) on a single continuous RUNNING window - repeated keep-alive (set_timeout) calls cannot extend a box past this; once used up, set_timeout returns 409 and the box must be paused/resumed to start a fresh window (ORK-221). null = uncapped (carded tiers). Distinct from max_timeout_seconds, which is only the per-reset countdown length."},"custom_egress_allowlist":{"type":"boolean","title":"Custom Egress Allowlist","description":"Whether the caller's plan may declare a custom egress allowlist for restricted sandboxes (ORK-152). Available on every plan today.","default":false},"default_egress_domains":{"items":{"type":"string"},"type":"array","title":"Default Egress Domains","description":"The platform default restricted-egress allowlist. A custom allowlist replaces this set, so clients pre-fill an editable field with it so users start from a working baseline."},"trial_credit_eur":{"type":"number","title":"Trial Credit Eur","description":"The one-time compute trial credit, in EUR, for THIS caller - it varies by access tier (a card on file unlocks the larger one), so read it rather than assuming a fixed amount. Sandbox compute is metered at the public PAYG rates and drawn against this single credit - far clearer than separate GB-h/CPU-h buckets. The trial does not reset, and lapses at trial_expires_at even if unspent."},"trial_credit_used_eur":{"type":"number","title":"Trial Credit Used Eur","description":"EUR of the trial credit consumed so far (PAYG cost of all compute since the trial epoch). Creates are refused once this reaches trial_credit_eur; on free that is a hard wall (upgrade to continue), on paid it switches to pay-as-you-go."},"trial_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Trial Expires At","description":"When the free-tier trial credit lapses even if unspent, or null when there is no clock - a card on file (payg/enterprise) is never time-expired (it consumes the credit then meters PAYG), and null also when expiry is disabled. Past this, a free account hard-walls."},"trial_active":{"type":"boolean","title":"Trial Active","description":"Whether the one-time trial is still live - false once the credit is spent OR trial_expires_at has passed. The single signal clients should read; trial_credit_used_eur vs trial_credit_eur alone misses time expiry.","default":true}},"type":"object","required":["access_tier","plan","enrolled","allowed_sizes","sizes","max_concurrent_memory_mb","max_concurrent","max_snapshots","max_custom_templates","max_timeout_seconds","trial_credit_eur","trial_credit_used_eur"],"title":"SandboxLimitsResponse","description":"What the authenticated caller's sandbox access tier allows.\n\nLets SDK and MCP callers discover their envelope before a create,\nrather than learning it from a rejected request."},"SandboxListResponse":{"properties":{"sandboxes":{"items":{"$ref":"#/components/schemas/SandboxResponse"},"type":"array","title":"Sandboxes"},"total":{"type":"integer","title":"Total"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["sandboxes","total"],"title":"SandboxListResponse"},"SandboxLogRetentionResponse":{"properties":{"access_tier":{"type":"string","title":"Access Tier","description":"Sandbox access tier - free | payg | enterprise | unverified (ORK-162). Determines max_days."},"retention_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Retention Days","description":"The window this account chose, exactly as stored. Null means no choice has been made and nothing is ever deleted."},"effective_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Effective Days","description":"The window actually in force - retention_days clamped to max_days. Differs from retention_days only when the account dropped to a tier with a shorter ceiling. Null means events are kept for the life of the account."},"max_days":{"type":"integer","title":"Max Days","description":"Longest window this tier may choose. 0 means no ceiling."},"cutoff":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cutoff","description":"Events created before this instant are deleted by the next daily purge. Null when nothing is deleted."},"events_stored":{"type":"integer","title":"Events Stored","description":"Activity records currently held for this account."},"events_expiring":{"type":"integer","title":"Events Expiring","description":"How many of those the next purge would delete. 0 when no window is set."}},"type":"object","required":["access_tier","retention_days","effective_days","max_days","events_stored","events_expiring"],"title":"SandboxLogRetentionResponse","description":"How long this account keeps its sandbox activity records, and what the\nnext purge would remove.\n\n`cutoff` is the point of the contract: the deadline is readable BEFORE the\nnightly purge runs, so a deletion is never first discovered by finding\nevents missing."},"SandboxLogRetentionUpdateRequest":{"properties":{"retention_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Retention Days","description":"Days to keep sandbox activity records, or null to keep them indefinitely. Must not exceed the tier's max_days. The lower bound is 1 day - there is no 'delete everything now' setting."}},"type":"object","title":"SandboxLogRetentionUpdateRequest","description":"Set or clear the account's sandbox activity-log retention window.\n\nretention_days=<n>   -> keep events for n days; older ones are deleted by\n                        the next daily purge.\nretention_days=null  -> stop deleting; keep events for the life of the\n                        account (the default for an account that has never\n                        set this)."},"SandboxMemoryMetrics":{"properties":{"limit_bytes":{"type":"integer","title":"Limit Bytes","description":"Allocated memory ceiling, in bytes."},"usage_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Usage Bytes","description":"Working set at the latest sample, in bytes - memory.current minus reclaimable file cache, so it tracks pressure that can actually OOM."},"usage_percent":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Usage Percent","description":"Latest working set as % of limit_bytes."}},"type":"object","required":["limit_bytes"],"title":"SandboxMemoryMetrics","description":"Live memory usage for a sandbox. Usage fields are null when no live\nsample exists."},"SandboxMetricsResponse":{"properties":{"sandbox_id":{"type":"string","title":"Sandbox Id"},"sandbox_status":{"$ref":"#/components/schemas/SandboxStatus","description":"Echoed so a client knows when samples are stale because the sandbox is paused/terminated."},"as_of":{"type":"string","format":"date-time","title":"As Of","description":"When this response was assembled (UTC)."},"as_of_unix":{"type":"integer","title":"As Of Unix","description":"`as_of` as Unix seconds."},"sample_interval_seconds":{"type":"integer","title":"Sample Interval Seconds","description":"Seconds between samples - a sensible poll floor."},"window_seconds":{"type":"integer","title":"Window Seconds","description":"How far back `samples` reaches, in seconds."},"cpu":{"$ref":"#/components/schemas/SandboxCpuMetrics"},"memory":{"$ref":"#/components/schemas/SandboxMemoryMetrics"},"lifetime":{"$ref":"#/components/schemas/SandboxLifetimeUsage"},"samples":{"items":{"$ref":"#/components/schemas/SandboxMetricsSample"},"type":"array","title":"Samples","description":"Recent samples, oldest first. Empty when the sandbox has no live VM or has not been sampled yet."}},"type":"object","required":["sandbox_id","sandbox_status","as_of","as_of_unix","sample_interval_seconds","window_seconds","cpu","memory","lifetime","samples"],"title":"SandboxMetricsResponse","description":"Live per-sandbox CPU + memory metrics (ORK-77).\n\nA rolling window of recent samples plus the latest reading and the\nsandbox's lifetime totals. Telemetry, not a mutating call: a paused or\nterminated sandbox returns 200 with null live usage and an empty\n`samples` window - read `sandbox_status` to tell why - rather than an\nerror. Poll no faster than `sample_interval_seconds`; going faster\nreturns no new data."},"SandboxMetricsSample":{"properties":{"t":{"type":"string","format":"date-time","title":"T","description":"When the sample was taken (UTC)."},"cpu_percent":{"type":"number","title":"Cpu Percent","description":"CPU at this sample, as % of allocated cores."},"mem_bytes":{"type":"integer","title":"Mem Bytes","description":"Working-set memory at this sample, in bytes."}},"type":"object","required":["t","cpu_percent","mem_bytes"],"title":"SandboxMetricsSample","description":"One point in a sandbox's rolling live-metrics window (ORK-77)."},"SandboxRegionInfo":{"properties":{"id":{"type":"string","title":"Id","description":"Region code to pass as `region` on create, e.g. 'fsn1'."},"label":{"type":"string","title":"Label","description":"Human-readable location, e.g. 'Falkenstein, DE'. Falls back to the code for a location without a label yet."}},"type":"object","required":["id","label"],"title":"SandboxRegionInfo","description":"One region a create may pin, straight from the live host registry.\n\nClients render this list instead of hardcoding region names, so a newly\nenrolled host surfaces everywhere without a client release."},"SandboxResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Sandbox ID, format sbx_<ulid>"},"status":{"$ref":"#/components/schemas/SandboxStatus"},"template":{"anyOf":[{"$ref":"#/components/schemas/Template"},{"type":"string"}],"title":"Template"},"network":{"$ref":"#/components/schemas/NetworkMode"},"cpu":{"type":"number","title":"Cpu"},"memory_mb":{"type":"integer","title":"Memory Mb"},"region":{"type":"string","title":"Region"},"node_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"on_timeout":{"$ref":"#/components/schemas/OnTimeout","default":"kill"},"auto_resume":{"type":"boolean","title":"Auto Resume","default":false},"preview_auth":{"type":"boolean","title":"Preview Auth","default":false},"preview_auth_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preview Auth Token"},"paused_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paused Expires At"},"endpoints":{"$ref":"#/components/schemas/SandboxEndpoints"},"preview_host_base":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preview Host Base"},"allow_domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allow Domains"},"metadata":{"additionalProperties":{"type":"string"},"type":"object","title":"Metadata"},"volume":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Volume"},"start_command_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Command Id"}},"type":"object","required":["id","status","template","network","cpu","memory_mb","region","created_at","expires_at","endpoints"],"title":"SandboxResponse"},"SandboxSize":{"type":"string","enum":["small","medium","large"],"title":"SandboxSize","description":"Fixed sandbox size menu (ORK-62).\n\nA fixed menu replaces free-form cpu/memory_mb: it keeps capacity on\none box predictable and rules out pathological shapes. Allowed sizes\nare tier-capped (see SANDBOX_LIMITS in config.py)."},"SandboxSizeInfo":{"properties":{"size":{"$ref":"#/components/schemas/SandboxSize"},"cpu":{"type":"number","title":"Cpu"},"memory_mb":{"type":"integer","title":"Memory Mb"},"allowed":{"type":"boolean","title":"Allowed","description":"Whether the caller's plan may request this size."}},"type":"object","required":["size","cpu","memory_mb","allowed"],"title":"SandboxSizeInfo","description":"One entry of the sandbox size menu, with the caller's eligibility."},"SandboxStatus":{"type":"string","enum":["starting","running","pausing","paused","resuming","terminated","failed"],"title":"SandboxStatus"},"SandboxTimeoutRequest":{"properties":{"timeout_seconds":{"type":"integer","maximum":86400.0,"minimum":10.0,"title":"Timeout Seconds","description":"New lifetime in seconds, measured from now."}},"type":"object","required":["timeout_seconds"],"title":"SandboxTimeoutRequest","description":"Extend a running sandbox's lifetime (POST /v1/sandboxes/{id}/timeout).\nThe clock is reset to run this many seconds from now, capped by the tier's\nmax_timeout_seconds. The absolute bound matches create (10..86400)."},"SandboxUsageEntry":{"properties":{"gb_hours":{"type":"number","title":"Gb Hours","description":"GB-hours of provisioned RAM."},"cpu_hours":{"type":"number","title":"Cpu Hours","description":"CPU-hours of on-CPU time."}},"type":"object","required":["gb_hours","cpu_hours"],"title":"SandboxUsageEntry","description":"One sandbox's compute usage so far this billing month."},"SandboxUsageResponse":{"properties":{"usage":{"additionalProperties":{"$ref":"#/components/schemas/SandboxUsageEntry"},"type":"object","title":"Usage"}},"type":"object","required":["usage"],"title":"SandboxUsageResponse","description":"Per-sandbox usage this month, keyed by sandbox id. Sandboxes with no\nsamples yet are absent - treat missing as zero."},"SnapshotCreate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Name","description":"Optional human-friendly label for the snapshot."}},"type":"object","title":"SnapshotCreate","description":"Capture a named, forkable snapshot of a running sandbox."},"SnapshotList":{"properties":{"snapshots":{"items":{"$ref":"#/components/schemas/SnapshotResponse"},"type":"array","title":"Snapshots"}},"type":"object","required":["snapshots"],"title":"SnapshotList"},"SnapshotResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Snapshot id, format snap_<ulid>."},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status","description":"capturing | ready | failed."},"source_sandbox_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Sandbox Id"},"template":{"anyOf":[{"$ref":"#/components/schemas/Template"},{"type":"string"}],"title":"Template"},"cpu":{"type":"number","title":"Cpu"},"memory_mb":{"type":"integer","title":"Memory Mb"},"network":{"$ref":"#/components/schemas/NetworkMode"},"size_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Mb"},"node_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Id"},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"ready_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ready At"}},"type":"object","required":["id","status","template","cpu","memory_mb","network","created_at"],"title":"SnapshotResponse"},"SpendCapUpdateRequest":{"properties":{"cap_eur":{"anyOf":[{"type":"number","maximum":999999.99,"minimum":0.0},{"type":"null"}],"title":"Cap Eur","description":"Monthly cap in EUR. 0 means 'no PAYG spend' (stops at the trial). Null with uncapped=false resets to the platform default."},"uncapped":{"type":"boolean","title":"Uncapped","description":"Opt out of the cap entirely. When true, cap_eur is ignored.","default":false}},"type":"object","title":"SpendCapUpdateRequest","description":"Set or clear the caller's monthly sandbox spend cap (paid plans only).\n\nExactly one intent per call:\n- uncapped=true        -> opt out of the cap (unbounded PAYG).\n- cap_eur=<number>     -> enforce that cap (and clear any uncapped opt-out).\n- cap_eur=null,\n  uncapped=false       -> fall back to the platform default cap."},"Template":{"type":"string","enum":["python-3.12","python-3.12-bare","node-22","ubuntu-24.04","chromium","debian-12","code-interpreter"],"title":"Template"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VolumeCreate":{"properties":{"name":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z0-9][a-z0-9_-]{0,63}$","title":"Name","description":"Volume name, unique within your account. Re-used to re-attach the same data to a later sandbox."},"size_gb":{"type":"number","maximum":100.0,"minimum":0.125,"title":"Size Gb","description":"Provisioned capacity in GB (default 10). Fractional sizes are allowed down to 0.125 (128 MB) - many small volumes are cheaper than a few large ones, since billing is GB-month on the declared size for as long as the volume exists, whether or not it is full. Request what you need, not the max. Your tier may cap a single volume below 100 GB; see max_volume_size_gb on the limits response.","default":10},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region","description":"Region the volume must live in (e.g. \"rbx\"); sandboxes attaching it are placed there. Omit to let the volume follow the first sandbox that attaches it."},"max_lifetime_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Max Lifetime Days","description":"Auto-destroy: maximum lifetime in days, counted from creation. Past the deadline the platform deletes the volume and its data exactly like an explicit delete - useful for temporary, per-job volumes. While the volume is attached to a live sandbox the destroy is deferred until it detaches. Omit (the default) to keep the volume until you delete it."}},"type":"object","required":["name"],"title":"VolumeCreate"},"VolumeListResponse":{"properties":{"volumes":{"items":{"$ref":"#/components/schemas/VolumeResponse"},"type":"array","title":"Volumes"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["volumes","total"],"title":"VolumeListResponse"},"VolumeMove":{"properties":{"region":{"type":"string","title":"Region","description":"Target region (e.g. \"hel1\"). The volume's data is checkpointed to object storage and re-materializes in this region on its next attach."}},"type":"object","required":["region"],"title":"VolumeMove"},"VolumeResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Volume id, format vol_<ulid>"},"name":{"type":"string","title":"Name"},"size_mb":{"type":"integer","title":"Size Mb"},"status":{"type":"string","title":"Status","description":"creating | ready | attached | error"},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region","description":"Where the volume lives (or must live). Null until it is homed by its first attach, unless a region was chosen at create."},"node_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Id"},"attached_sandbox_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attached Sandbox Id"},"max_lifetime_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Lifetime Days","description":"Auto-destroy lifetime in days from creation, or null when the volume is kept until explicitly deleted."},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At","description":"When the volume will be auto-destroyed (created_at + max_lifetime_days), or null if it never expires."},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","size_mb","status","created_at"],"title":"VolumeResponse"},"VolumeUpdate":{"properties":{"max_lifetime_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":0.0},{"type":"null"}],"title":"Max Lifetime Days","description":"New maximum lifetime in days, counted from the volume's creation (not from this call). Null or 0 clears auto-destroy so the volume is kept until explicitly deleted."}},"type":"object","title":"VolumeUpdate","description":"PATCH body for a volume. The one mutable knob is the auto-destroy\nlifetime; the field must be present - null (or 0) clears it (keep\nforever)."},"WebhookCreate":{"properties":{"url":{"type":"string","maxLength":2048,"title":"Url","description":"Publicly reachable http(s) endpoint to POST deliveries to. URLs resolving to private addresses are rejected."},"event_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Event Types","description":"Event names to deliver. Supports exact names ('deploy.failed'), family wildcards ('deploy.*'), and '*' for every event the platform emits. Omit or null for the sandbox lifecycle family only; pass an empty list to pause deliveries without deleting the registration."}},"type":"object","required":["url"],"title":"WebhookCreate","description":"Register an endpoint for lifecycle notifications\n(POST /v1/sandboxes/webhooks)."},"WebhookListResponse":{"properties":{"webhooks":{"items":{"$ref":"#/components/schemas/WebhookResponse"},"type":"array","title":"Webhooks"}},"type":"object","required":["webhooks"],"title":"WebhookListResponse"},"WebhookResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Public id (whk_...)."},"url":{"type":"string","title":"Url"},"event_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Event Types"},"active":{"type":"boolean","title":"Active"},"consecutive_failures":{"type":"integer","title":"Consecutive Failures","default":0},"last_delivery_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Delivery At"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret","description":"Signing secret (whsec_...). Returned once, at registration, and never again."}},"type":"object","required":["id","url","active","created_at"],"title":"WebhookResponse","description":"One webhook registration. `secret` is present ONLY in the create\nresponse - store it then; it signs every delivery (X-Orkestr-Signature =\n'sha256=' + HMAC-SHA256 hex of the request body)."}},"securitySchemes":{"apiToken":{"type":"http","scheme":"bearer","description":"orkestr API token. Create one in the console under Settings -> API, then send it as `Authorization: Bearer <token>`."}}},"servers":[{"url":"https://api.orkestr.eu"}]}