{"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"}}],"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","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"}}],"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/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/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}":{"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/{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}/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/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"}}}}}}}},"components":{"schemas":{"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"},"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."}},"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"},"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"},"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"},"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."},"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"},"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"},"NetworkMode":{"type":"string","enum":["off","restricted","open"],"title":"NetworkMode"},"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"},"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"}],"title":"Template","description":"Base image template (e.g. 'python-3.12'), or a custom template id (tmpl_...) created via POST /v1/templates."},"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.","default":600},"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."}},"type":"object","required":["template"],"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_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_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."},"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, flat across plans. 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"}},"type":"object","required":["sandboxes","total"],"title":"SandboxListResponse"},"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"},"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"}},"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"},"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."},"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"],"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":"integer","maximum":100.0,"minimum":1.0,"title":"Size Gb","description":"Provisioned capacity in GB (default 10). Billed as GB-month at this size for as long as the volume exists, whether or not it is full - request what you need, not the max.","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."}},"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"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","size_mb","status","created_at"],"title":"VolumeResponse"}},"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"}]}