openapi: 3.0.0 info: contact: {} description: API for manipulating filesystem, processes and network. title: Sandbox API version: 0.0.1 paths: /archive/export: post: description: >- Archives everything the sandbox changed on top of its base image and streams it, uncompressed, to a presigned S3 PUT URL. The memory of the sandbox is not archived. The sandbox is quiesced first: the process list is saved (unless saveProcesses is false), every process is stopped, and the API then refuses the calls that would write to the filesystem. The freeze is not lifted afterwards, since an exported sandbox is meant to be restored elsewhere; call POST /archive/resume to lift it. Use dryRun to get the archive's content and exact size without stopping anything and without uploading. Set async to start the export and answer immediately, which is what archiving a large filesystem needs: the export then reports itself through GET /archive/status. requestBody: content: application/json: schema: $ref: "#/components/schemas/ExportOptions" description: Export options required: true responses: "200": description: Export result content: application/json: schema: $ref: "#/components/schemas/ExportResult" "202": description: The export was started and runs in the background content: application/json: schema: $ref: "#/components/schemas/ExportProgress" "400": description: Invalid request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "409": description: An export is already in progress content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Export failed content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Export the filesystem changes to a presigned URL tags: - archive /archive/resume: post: description: "Makes the API serve every route again after an export. The processes stopped for the export are not relaunched: this exists so a failed or aborted export does not leave the sandbox unusable." responses: "200": description: Archive status content: application/json: schema: $ref: "#/components/schemas/QuiesceStatus" "409": description: An export or a restore is in progress content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: The root filesystem could not be made writable again content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Lift the archive freeze tags: - archive /archive/status: get: description: Reports whether the sandbox is frozen for an archive export, and which processes were stopped for it. responses: "200": description: Archive status content: application/json: schema: $ref: "#/components/schemas/QuiesceStatus" summary: Get the archive status tags: - archive "/codegen/fastapply/{path}": put: description: >- Uses the configured LLM provider (Relace or Morph) to apply a code edit to the original content. To use this endpoint as an agent tool, follow these guidelines: Use this tool to make an edit to an existing file. This will be read by a less intelligent model, which will quickly apply the edit. You should make it clear what the edit is, while also minimizing the unchanged code you write. When writing the edit, you should specify each edit in sequence, with the special comment "// ... existing code ..." to represent unchanged code in between edited lines. Example format: // ... existing code ... FIRST_EDIT // ... existing code ... SECOND_EDIT // ... existing code ... THIRD_EDIT // ... existing code ... You should still bias towards repeating as few lines of the original file as possible to convey the change. But, each edit should contain minimally sufficient context of unchanged lines around the code you're editing to resolve ambiguity. DO NOT omit spans of pre-existing code (or comments) without using the "// ... existing code ..." comment to indicate its absence. If you omit the existing code comment, the model may inadvertently delete these lines. If you plan on deleting a section, you must provide context before and after to delete it. If the initial code is "Block 1\nBlock 2\nBlock 3", and you want to remove Block 2, you would output "// ... existing code ...\nBlock 1\nBlock 3\n// ... existing code ...". Make sure it is clear what the edit should be, and where it should be applied. Make edits to a file in a single edit_file call instead of multiple edit_file calls to the same file. The apply model can handle many distinct edits at once. parameters: - description: Path to the file to edit (relative to workspace) in: path name: path required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/ApplyEditRequest" description: Code edit request required: true responses: "200": description: Code edit applied successfully content: application/json: schema: $ref: "#/components/schemas/ApplyEditResponse" "400": description: Invalid request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity - failed to process the request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "503": description: Service unavailable - no provider configured content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Apply code edit tags: - fastapply "/codegen/reranking/{path}": get: description: >- Uses Relace's code reranking model to find the most relevant files for a given query. This is useful as a first pass in agentic exploration to narrow down the search space. Based on: https://docs.relace.ai/docs/code-reranker/agent Query Construction: The query can be a short question or a more detailed conversation with the user request included. For a first pass, use the full conversation; for subsequent calls, use more targeted questions. Token Limit and Score Threshold: For 200k token context models like Claude 4 Sonnet, recommended defaults are scoreThreshold=0.5 and tokenLimit=30000. The response will be a list of file paths and contents ordered from most relevant to least relevant. parameters: - description: Path to search in (relative to workspace) in: path name: path required: true schema: type: string - description: Natural language query to search for in: query name: query required: true schema: type: string - description: "Minimum relevance score (default: 0.5)" in: query name: scoreThreshold schema: type: number - description: "Maximum tokens to return (default: 30000)" in: query name: tokenLimit schema: type: integer - description: Regex pattern to filter files (e.g., .*\\.ts$ for TypeScript files) in: query name: filePattern schema: type: string responses: "200": description: Relevant files found content: application/json: schema: $ref: "#/components/schemas/RerankingResponse" "400": description: Invalid request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity - failed to process the request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "503": description: Service unavailable - Relace not configured content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Code reranking/semantic search tags: - codegen /drives/mount: get: description: Returns a list of all currently mounted drives managed by blfs responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/DriveListResponse" "500": description: Internal Server Error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" security: - BearerAuth: [] summary: List currently mounted drives tags: - drive post: description: Mounts an agent drive using the blfs binary to a local path, optionally mounting a subpath within the drive. Supports optional UID/GID mapping to remap file ownership between the local sandbox and the filer (always mapped to filer UID/GID 0). Mapping values can be set per-request via uidMap/gidMap fields, or globally via BLFS_UID_MAP/BLFS_GID_MAP environment variables (request values take precedence). requestBody: content: application/json: schema: $ref: "#/components/schemas/DriveMountRequest" description: Drive attachment parameters required: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/DriveMountResponse" "400": description: Bad Request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "403": description: Forbidden content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "409": description: Conflict content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal Server Error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" security: - BearerAuth: [] summary: Attach a drive to a local path tags: - drive "/drives/mount/{mountPath}": delete: description: Unmounts a previously mounted drive from the specified local path parameters: - description: Mount path to detach (must start with /, e.g. /mnt/test) in: path name: mountPath required: true schema: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/DriveUnmountResponse" "400": description: Bad Request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal Server Error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" security: - BearerAuth: [] summary: Detach a drive from a local path tags: - drive /environment/reload: post: description: Re-reads /bl/metadata and applies its environment to the sandbox-api process, so this process and every process started afterwards see the current values. Called by the guest init after an environment update; safe to call manually. responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/handler.ReloadResponse" "404": description: Not Found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal Server Error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Reload environment from guest metadata tags: - system "/filesystem-content-search/{path}": get: description: Searches for text content inside files using ripgrep. Returns matching lines with context. parameters: - description: Directory path to search in in: path name: path required: true schema: type: string - description: Text to search for in: query name: query required: true schema: type: string - description: "Case sensitive search (default: false)" in: query name: caseSensitive schema: type: boolean - description: "Maximum number of results to return (default: 100)" in: query name: maxResults schema: type: integer - description: File pattern to include (e.g., *.go) in: query name: filePattern schema: type: string - description: "Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage)" in: query name: excludeDirs schema: type: string responses: "200": description: Content search results content: application/json: schema: $ref: "#/components/schemas/ContentSearchResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Search for text content in files tags: - filesystem "/filesystem-find/{path}": get: description: Finds files and directories using the find command. parameters: - description: Path to search in (e.g., /home/user/projects) in: path name: path required: true schema: type: string - description: Type of search (file or directory) in: query name: type schema: type: string - description: Comma-separated file patterns to include (e.g., *.go,*.js) in: query name: patterns schema: type: string - description: "Maximum number of results to return (default: 20). If set to 0, all results will be returned." in: query name: maxResults schema: type: integer - description: "Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage). Use empty string to skip no directories." in: query name: excludeDirs schema: type: string - description: "Exclude hidden files and directories (default: true)" in: query name: excludeHidden schema: type: boolean responses: "200": description: Find results content: application/json: schema: $ref: "#/components/schemas/FindResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Find files and directories tags: - filesystem /filesystem-multipart: get: description: List all active multipart uploads responses: "200": description: List of active uploads content: application/json: schema: $ref: "#/components/schemas/MultipartListUploadsResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: List multipart uploads tags: - filesystem "/filesystem-multipart/{uploadId}/abort": delete: description: Abort a multipart upload and clean up all parts parameters: - description: Upload ID in: path name: uploadId required: true schema: type: string responses: "200": description: Upload aborted content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "404": description: Upload not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Abort multipart upload tags: - filesystem "/filesystem-multipart/{uploadId}/complete": post: description: Complete a multipart upload by assembling all parts parameters: - description: Upload ID in: path name: uploadId required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/MultipartCompleteRequest" description: List of parts required: true responses: "200": description: Upload completed content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "404": description: Upload not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Complete multipart upload tags: - filesystem "/filesystem-multipart/{uploadId}/part": put: description: Upload a single part of a multipart upload parameters: - description: Upload ID in: path name: uploadId required: true schema: type: string - description: Part number (1-10000) in: query name: partNumber required: true schema: type: integer requestBody: content: multipart/form-data: schema: type: object properties: file: description: Part data type: string format: binary required: - file required: true responses: "200": description: Part uploaded content: application/json: schema: $ref: "#/components/schemas/MultipartUploadPartResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "404": description: Upload not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Upload part tags: - filesystem "/filesystem-multipart/{uploadId}/parts": get: description: List all uploaded parts for a multipart upload parameters: - description: Upload ID in: path name: uploadId required: true schema: type: string responses: "200": description: List of parts content: application/json: schema: $ref: "#/components/schemas/MultipartListPartsResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "404": description: Upload not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: List parts tags: - filesystem "/filesystem-multipart/initiate/{path}": post: description: Initiate a multipart upload session for a file parameters: - description: File path in: path name: path required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/MultipartInitiateRequest" description: Optional permissions responses: "200": description: Upload session created content: application/json: schema: $ref: "#/components/schemas/MultipartInitiateResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Initiate multipart upload tags: - filesystem "/filesystem-search/{path}": get: description: Performs fuzzy search on filesystem paths using fuzzy matching algorithm. Optimized alternative to find and grep commands. parameters: - description: Path to search in (e.g., /home/user/projects) in: path name: path required: true schema: type: string - description: "Maximum number of results to return (default: 20)" in: query name: maxResults schema: type: integer - description: Comma-separated file patterns to include (e.g., *.go,*.js) in: query name: patterns schema: type: string - description: "Comma-separated directory names to skip (default: node_modules,vendor,.git,dist,build,target,__pycache__,.venv,.next,coverage). Use empty string to skip no directories." in: query name: excludeDirs schema: type: string - description: "Exclude hidden files and directories (default: true)" in: query name: excludeHidden schema: type: boolean responses: "200": description: Fuzzy search results content: application/json: schema: $ref: "#/components/schemas/FuzzySearchResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Fuzzy search for files and directories tags: - filesystem "/filesystem/{path}": delete: description: Delete a file or directory parameters: - description: File or directory path in: path name: path required: true schema: type: string - description: Delete directory recursively in: query name: recursive schema: type: boolean responses: "200": description: Success message content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "404": description: File or directory not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Delete file or directory tags: - filesystem get: description: Get content of a file or listing of a directory. Use Accept header to control response format for files. parameters: - description: File or directory path in: path name: path required: true schema: type: string - description: Force download mode for files in: query name: download schema: type: boolean responses: "200": description: Directory listing content: application/json: schema: oneOf: - $ref: "#/components/schemas/Directory" - $ref: "#/components/schemas/FileWithContent" - type: string format: binary application/octet-stream: schema: oneOf: - $ref: "#/components/schemas/Directory" - $ref: "#/components/schemas/FileWithContent" - type: string format: binary "404": description: File or directory not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" application/octet-stream: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" application/octet-stream: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" application/octet-stream: schema: $ref: "#/components/schemas/ErrorResponse" summary: Get file or directory information tags: - filesystem put: description: Create or update a file or directory parameters: - description: File or directory path in: path name: path required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/FileRequest" description: File or directory details required: true responses: "200": description: Success message content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Create or update a file or directory tags: - filesystem "/filesystem/tree/{path}": delete: description: Delete a directory tree recursively parameters: - description: Root directory path in: path name: path required: true schema: type: string - description: Delete directory recursively in: query name: recursive schema: type: boolean responses: "200": description: Directory deleted successfully content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Delete directory tree tags: - filesystem get: description: Get a recursive directory tree structure starting from the specified path parameters: - description: Root directory path in: path name: path required: true schema: type: string responses: "200": description: Directory tree content: application/json: schema: oneOf: - $ref: "#/components/schemas/Directory" - $ref: "#/components/schemas/FileWithContent" - type: string format: binary "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Get directory tree tags: - filesystem put: description: Create or update multiple files within a directory tree structure parameters: - description: Root directory path in: path name: path required: true schema: type: string requestBody: content: application/json: schema: $ref: "#/components/schemas/TreeRequest" description: Map of file paths to content required: true responses: "200": description: Updated directory tree content: application/json: schema: oneOf: - $ref: "#/components/schemas/Directory" - $ref: "#/components/schemas/FileWithContent" - type: string format: binary "400": description: Bad request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Create or update directory tree tags: - filesystem /health: get: description: >- Returns health status and system information including upgrade count and binary details Also includes last upgrade attempt status with detailed error information if available responses: "200": description: Health status content: application/json: schema: $ref: "#/components/schemas/HealthResponse" summary: Health check tags: - system "/network/process/{pid}/monitor": delete: description: Stop monitoring for new ports opened by a process parameters: - description: Process ID in: path name: pid required: true schema: type: integer responses: "200": description: Object containing PID and success message content: application/json: schema: additionalProperties: true type: object "400": description: Invalid process ID content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Stop monitoring ports for a process tags: - network post: description: Start monitoring for new ports opened by a process parameters: - description: Process ID in: path name: pid required: true schema: type: integer requestBody: content: application/json: schema: $ref: "#/components/schemas/PortMonitorRequest" description: Port monitor configuration required: true responses: "200": description: Object containing PID and success message content: application/json: schema: additionalProperties: true type: object "400": description: Invalid request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Start monitoring ports for a process tags: - network "/network/process/{pid}/ports": get: description: Get a list of all open ports for a process parameters: - description: Process ID in: path name: pid required: true schema: type: integer responses: "200": description: Object containing PID and array of network.PortInfo content: application/json: schema: additionalProperties: true type: object "400": description: Invalid process ID content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Get open ports for a process tags: - network /network/tunnel: delete: description: "Stop the network tunnel and restore the original network configuration. WARNING: After disconnecting, the sandbox will lose all outbound internet connectivity (no egress). Inbound connections to the sandbox will still work. Use PUT /network/tunnel/config to re-establish the tunnel." responses: "200": description: Tunnel disconnected content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "400": description: No tunnel is running content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Failed to stop tunnel content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Disconnect tunnel tags: - network /network/tunnel/config: put: description: Apply a new tunnel configuration on the fly. The existing tunnel is torn down and a new one is established. This endpoint is write-only; there is no corresponding GET to read the config back. requestBody: content: application/json: schema: $ref: "#/components/schemas/TunnelConfigRequest" description: Base64-encoded tunnel configuration required: true responses: "200": description: Configuration applied content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "400": description: Invalid request body content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Invalid tunnel configuration content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Failed to apply configuration content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Update tunnel configuration tags: - network /process: get: description: Get a list of all running and completed processes responses: "200": description: Process list content: application/json: schema: items: $ref: "#/components/schemas/ProcessResponse" type: array summary: List all processes tags: - process post: description: Execute a command and return process information. If Accept header is text/event-stream, streams logs in SSE format and returns the process response as a final event. requestBody: content: application/json: schema: $ref: "#/components/schemas/ProcessRequest" description: Process execution request required: true responses: "200": description: Process information content: application/json: schema: $ref: "#/components/schemas/ProcessResponse" text/event-stream: schema: $ref: "#/components/schemas/ProcessResponse" "400": description: Invalid request content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" text/event-stream: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" text/event-stream: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" text/event-stream: schema: $ref: "#/components/schemas/ErrorResponse" summary: Execute a command tags: - process "/process/{identifier}": delete: description: Gracefully stop a running process parameters: - description: Process identifier (PID or name) in: path name: identifier required: true schema: type: string responses: "200": description: Process stopped content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "404": description: Process not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Stop a process tags: - process get: description: Get information about a process by its PID or name parameters: - description: Process identifier (PID or name) in: path name: identifier required: true schema: type: string responses: "200": description: Process information content: application/json: schema: $ref: "#/components/schemas/ProcessResponse" "404": description: Process not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Get process by identifier tags: - process "/process/{identifier}/kill": delete: description: Forcefully kill a running process parameters: - description: Process identifier (PID or name) in: path name: identifier required: true schema: type: string responses: "200": description: Process killed content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "404": description: Process not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Kill a process tags: - process "/process/{identifier}/logs": get: description: Get the stdout and stderr output of a process parameters: - description: Process identifier (PID or name) in: path name: identifier required: true schema: type: string responses: "200": description: Process logs content: application/json: schema: $ref: "#/components/schemas/ProcessLogs" "404": description: Process not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Get process logs tags: - process "/process/{identifier}/logs/stream": get: description: Streams the stdout and stderr output of a process in real time, one line per log, prefixed with 'stdout:' or 'stderr:'. Closes when the process exits or the client disconnects. parameters: - description: Process identifier (PID or name) in: path name: identifier required: true schema: type: string responses: "200": description: Stream of process logs, one line per log (prefixed with stdout:/stderr:) content: text/plain: schema: type: string "404": description: Process not found content: text/plain: schema: $ref: "#/components/schemas/ErrorResponse" "422": description: Unprocessable entity content: text/plain: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: text/plain: schema: $ref: "#/components/schemas/ErrorResponse" summary: Stream process logs in real time tags: - process "/process/{identifier}/stdin": delete: description: Send EOF to the process by closing its stdin pipe. Idempotent. For stdio protocols such as MCP this is the clean shutdown path. parameters: - description: Process identifier (PID or name) in: path name: identifier required: true schema: type: string responses: "200": description: Stdin closed content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "404": description: Process not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "409": description: Process has no stdin content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Close a process's stdin tags: - process post: description: 'Write the raw request body to the stdin of a process started with "stdin": true. Bytes are forwarded verbatim, so include the trailing newline your protocol expects. Sequential requests keep their order; each body is written atomically with respect to other writers. The pipe does not survive a sandbox-api restart: once it is gone this returns 409 and the process must be restarted.' parameters: - description: Process identifier (PID or name) in: path name: identifier required: true schema: type: string requestBody: content: application/octet-stream: schema: type: string description: Raw bytes to write required: true responses: "200": description: Bytes written content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "404": description: Process not found content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "409": description: Process has no stdin, or stdin is closed content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "413": description: Body over 8 MiB content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Write failed content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" "503": description: Process stopped reading its stdin content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Write to a process's stdin tags: - process /upgrade: post: description: >- Triggers an upgrade of the sandbox-api process. Returns 200 immediately before upgrading. The upgrade will: download the specified binary from GitHub releases, validate it, and restart. All running processes will be preserved across the upgrade. Available versions: "latest" (default, most recent release), "develop", "main", or specific tag like "v1.0.0" You can also specify a custom baseUrl for forks (defaults to https://github.com/blaxel-ai/sandbox/releases) requestBody: content: application/json: schema: $ref: "#/components/schemas/UpgradeRequest" description: Upgrade options responses: "200": description: Upgrade initiated content: application/json: schema: $ref: "#/components/schemas/SuccessResponse" "500": description: Internal server error content: application/json: schema: $ref: "#/components/schemas/ErrorResponse" summary: Upgrade the sandbox-api tags: - system "/watch/filesystem/{path}": get: description: Streams the path of modified files (one per line) in the given directory. Closes when the client disconnects. parameters: - description: Ignore patterns (comma-separated) in: query name: ignore schema: type: string - description: Directory path to watch in: path name: path required: true schema: type: string responses: "200": description: Stream of modified file paths, one per line content: text/plain: schema: type: string "400": description: Invalid path content: text/plain: schema: $ref: "#/components/schemas/ErrorResponse" "500": description: Internal server error content: text/plain: schema: $ref: "#/components/schemas/ErrorResponse" summary: Stream file modification events in a directory tags: - filesystem servers: - url: https://sbx-{sandbox_id}-{workspace_id}.{region}.bl.run variables: sandbox_id: default: unknown workspace_id: default: unknown region: default: unknown components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT schemas: ApplyEditRequest: properties: codeEdit: example: |- // Add world parameter function hello(world) { console.log('Hello', world); } type: string model: example: relace-apply-3 type: string required: - codeEdit type: object ApplyEditResponse: properties: message: example: Code edit applied successfully type: string originalContent: example: |- function hello() { console.log('Hello'); } type: string path: example: src/main.js type: string provider: example: Relace type: string success: example: true type: boolean updatedContent: example: |- function hello(world) { console.log('Hello', world); } type: string type: object ArchiveManifest: properties: added: description: Added and Modified count the archive's payload members. example: 11 type: integer apiVersion: description: APIVersion is the sandbox-api build that produced the archive. example: v0.1.0 type: string createdAt: type: string deleted: description: >- Deleted are paths the image has and the sandbox deleted. Tar cannot carry a deletion, so import applies these from the manifest. items: type: string type: array excludes: description: Excludes are the paths left out of the comparison. items: type: string type: array imageDevice: description: >- ImageDevice is the device the pristine image was read from, for the record: it says where the sandbox that exported the archive found its image. example: /dev/vda type: string modified: example: 3 type: integer payloadBytes: description: PayloadBytes is the total content size of the payload members. example: 3073449 type: integer processes: description: Processes tells whether ProcessesName is present. example: true type: boolean root: description: Root is the directory the paths are relative to. example: / type: string version: example: 1 type: integer required: - createdAt - root - version type: object ContentSearchMatch: properties: column: example: 10 type: integer context: example: |- previous line current line next line type: string line: example: 42 type: integer path: example: src/main.go type: string text: example: const searchText = 'example' type: string required: - column - line - path - text type: object ContentSearchResponse: properties: matches: items: $ref: "#/components/schemas/ContentSearchMatch" type: array query: example: searchText type: string total: example: 5 type: integer required: - matches - query - total type: object Directory: properties: files: items: $ref: "#/components/schemas/File" type: array name: type: string path: type: string subdirectories: description: "@name Subdirectories" items: $ref: "#/components/schemas/Subdirectory" type: array required: - files - name - path - subdirectories type: object DriveListResponse: properties: mounts: items: $ref: "#/components/schemas/DriveMountInfo" type: array type: object DriveMountInfo: properties: driveName: type: string drivePath: type: string gidMap: description: The local GID used for this mount type: string mountPath: type: string readOnly: type: boolean uidMap: description: The local UID used for this mount type: string type: object DriveMountRequest: properties: driveName: type: string drivePath: description: Optional, defaults to "/" type: string gidMap: description: Optional, local GID to map (filer GID is always 0) type: string mountPath: type: string readOnly: description: Optional, defaults to false type: boolean uidMap: description: Optional, local UID to map (filer UID is always 0) type: string required: - driveName - mountPath type: object DriveMountResponse: properties: driveName: type: string drivePath: type: string gidMap: description: The local GID used for this mount type: string message: type: string mountPath: type: string readOnly: type: boolean success: type: boolean uidMap: description: The local UID used for this mount type: string type: object DriveUnmountResponse: properties: message: type: string mountPath: type: string success: type: boolean type: object ErrorResponse: properties: error: example: Error message type: string required: - error type: object ExportOptions: properties: async: description: >- Async starts the export and answers immediately, leaving it to run: an archive of a large filesystem takes longer than a request may be held open. Its progress is reported by /archive/status. example: false type: boolean dryRun: description: |- DryRun reports what would be archived, and its exact size, without stopping anything and without uploading. example: false type: boolean excludes: description: Excludes are added to the paths excluded by default. items: type: string type: array headers: additionalProperties: type: string description: >- Headers are sent with the upload request as given. A presigned URL only accepts the headers it was signed for, so these have to match what the caller signed: sending one that was not signed, or signing one that is not sent, is rejected as a signature mismatch. Typical use is a storage class, x-amz-storage-class: GLACIER_IR. type: object imageDevice: description: >- ImageDevice is the device holding the pristine image. It is found on its own, wherever the sandbox booted from attached it, and naming one here only overrides that. example: /dev/vda type: string imageMountPoint: description: >- ImageMountPoint is a directory where the pristine image is already mounted. When set the image device is neither mounted nor unmounted. example: /mnt/lower type: string multipart: allOf: - $ref: "#/components/schemas/MultipartUpload" description: >- Multipart uploads the archive part by part instead, which is how an archive larger than the 5 GB a single PUT accepts is stored. It takes precedence over URL. saveProcesses: description: |- SaveProcesses stores the process list in the archive so restore can relaunch the workload. Defaults to true; set it to false to archive storage only. example: true type: boolean stopTimeoutSeconds: description: StopTimeoutSeconds bounds the graceful stop of each process. example: 30 type: integer url: description: >- URL is a presigned S3 PUT URL the archive is streamed to. Empty is only valid with DryRun, or with Multipart. example: https://bucket.s3.amazonaws.com/key?... type: string type: object ExportProgress: properties: error: description: Error is why the export failed, without the presigned URL it used. type: string finishedAt: type: string size: description: Size is the archive's exact size, known once the filesystem is scanned. example: 3074211 type: integer startedAt: type: string state: allOf: - $ref: "#/components/schemas/archive.ExportState" example: running uploaded: description: Uploaded reports whether the storage holds the archive. example: false type: boolean type: object ExportResult: properties: changes: description: |- Changes lists every path in the archive. Only filled for a dry run, where it is the point of the call. items: $ref: "#/components/schemas/archive.Change" type: array duration: example: 4.2s type: string manifest: $ref: "#/components/schemas/ArchiveManifest" size: description: |- Size is the exact number of bytes uploaded, known before the upload starts since the archive is not compressed. example: 3074211 type: integer stoppedProcesses: description: StoppedProcesses are the processes stopped to freeze the filesystem. items: type: string type: array uploaded: description: Uploaded is false for a dry run. example: true type: boolean required: - manifest type: object File: properties: group: type: string lastModified: type: string name: type: string owner: type: string path: type: string permissions: type: string size: type: integer required: - group - lastModified - name - owner - path - permissions - size type: object FileRequest: properties: content: example: file contents here type: string isDirectory: example: false type: boolean permissions: example: "0644" type: string type: object FileWithContent: properties: content: type: string group: type: string lastModified: type: string name: type: string owner: type: string path: type: string permissions: type: string size: type: integer required: - content - group - lastModified - name - owner - path - permissions - size type: object FindMatch: properties: path: example: src/main.go type: string type: description: '"file" or "directory"' example: file type: string required: - path - type type: object FindResponse: properties: matches: items: $ref: "#/components/schemas/FindMatch" type: array total: example: 5 type: integer required: - matches - total type: object FuzzySearchMatch: properties: path: example: src/main.go type: string score: example: 100 type: integer type: description: '"file" or "directory"' example: file type: string required: - path - score - type type: object FuzzySearchResponse: properties: matches: items: $ref: "#/components/schemas/FuzzySearchMatch" type: array total: example: 5 type: integer required: - matches - total type: object HealthResponse: properties: arch: example: amd64 type: string buildTime: example: 2026-01-29T17:36:52Z type: string gitCommit: example: abc123 type: string goVersion: example: go1.25.0 type: string lastUpgrade: $ref: "#/components/schemas/UpgradeStatus" os: example: linux type: string startedAt: example: 2026-01-29T18:45:49Z type: string status: example: ok type: string upgradeCount: example: 0 type: integer uptime: example: 1h30m type: string uptimeSeconds: example: 5400.5 type: number version: example: v0.1.0 type: string required: - arch - buildTime - gitCommit - goVersion - lastUpgrade - os - startedAt - status - upgradeCount - uptime - uptimeSeconds - version type: object MultipartCompleteRequest: properties: parts: items: $ref: "#/components/schemas/MultipartPartInfo" type: array type: object MultipartInitiateRequest: properties: permissions: example: "0644" type: string type: object MultipartInitiateResponse: properties: path: example: /tmp/largefile.dat type: string uploadId: example: 550e8400-e29b-41d4-a716-446655440000 type: string type: object MultipartListPartsResponse: properties: parts: items: $ref: "#/components/schemas/filesystem.UploadedPart" type: array uploadId: example: 550e8400-e29b-41d4-a716-446655440000 type: string type: object MultipartListUploadsResponse: properties: uploads: items: $ref: "#/components/schemas/filesystem.MultipartUpload" type: array type: object MultipartPartInfo: properties: etag: example: 5d41402abc4b2a76b9719d911017c592 type: string partNumber: example: 1 type: integer type: object MultipartUpload: properties: abortUrl: description: >- AbortURL is a presigned DELETE URL that discards the parts already uploaded. Without it a failed export leaves them on the storage until a lifecycle rule removes them. type: string completeUrl: description: CompleteURL is a presigned POST URL that assembles the parts. type: string partSize: description: PartSize is the number of bytes sent to every part but the last. example: 536870912 type: integer partUrls: description: >- PartURLs are presigned PUT URLs, one per part, in order. Extra ones are left unused. items: type: string type: array type: object MultipartUploadPartResponse: properties: etag: example: 5d41402abc4b2a76b9719d911017c592 type: string partNumber: example: 1 type: integer size: example: 5242880 type: integer type: object PortMonitorRequest: properties: callback: description: URL to call when a new port is detected example: http://localhost:3000/callback type: string type: object ProcessLogs: properties: logs: example: logs output type: string stderr: example: stderr output type: string stdout: example: stdout output type: string required: - logs - stderr - stdout type: object ProcessRequest: properties: command: example: ls -la type: string env: additionalProperties: type: string example: "{\"PORT\"": ' "3000"}' type: object keepAlive: description: Disable scale-to-zero while process runs. Default timeout is 600s (10 minutes). Set timeout to 0 for infinite. example: false type: boolean maxRestarts: description: Maximum number of restarts on failure. Set to a negative value (e.g. -1) for unlimited restarts. example: 3 type: integer name: example: my-process type: string restartOnFailure: example: true type: boolean stdin: description: "Open a writable stdin pipe, fed via POST /process/{identifier}/stdin and closed via DELETE. The pipe does not survive a sandbox-api restart: the process then sees EOF." example: false type: boolean timeout: description: Timeout in seconds. When keepAlive is true, defaults to 600s (10 minutes). Set to 0 for infinite (no auto-kill). example: 30 type: integer waitForCompletion: example: false type: boolean waitForPorts: example: - 3000 - 8080 items: type: integer type: array workingDir: example: /home/user type: string required: - command type: object ProcessResponse: properties: command: example: ls -la type: string completedAt: example: Wed, 01 Jan 2023 12:01:00 GMT type: string exitCode: example: 0 type: integer keepAlive: description: Whether scale-to-zero is disabled for this process example: false type: boolean logs: example: logs output type: string maxRestarts: example: 3 type: integer name: example: my-process type: string pid: example: "1234" type: string restartCount: example: 2 type: integer restartOnFailure: example: true type: boolean startedAt: example: Wed, 01 Jan 2023 12:00:00 GMT type: string status: enum: - failed - killed - stopped - running - completed example: running type: string stderr: example: stderr output type: string stdin: description: Whether the process was started with a writable stdin pipe example: false type: boolean stdout: example: stdout output type: string workingDir: example: /home/user type: string required: - command - completedAt - exitCode - logs - name - pid - startedAt - status - stderr - stdout - workingDir type: object QuiesceStatus: properties: export: allOf: - $ref: "#/components/schemas/ExportProgress" description: >- Export reports the export started asynchronously, if there was one. It is how a caller that did not wait for the export learns that the archive is on the storage, or why it is not. readOnlyRoot: description: >- ReadOnlyRoot reports whether the root mount was remounted read-only, which is what actually stops writes; false means the freeze relies only on the API refusing calls, and the reason says why. example: true type: boolean reason: description: Reason is a human readable explanation of why the sandbox is frozen. example: archive export type: string restore: allOf: - $ref: "#/components/schemas/RestoreProgress" description: |- Restore reports the archive this sandbox was started from, if it was started from one: how far its restore has got, and how it ended. since: description: Since is when the sandbox left StateActive. type: string state: allOf: - $ref: "#/components/schemas/archive.QuiesceState" example: quiesced stoppedProcesses: description: StoppedProcesses are the process identifiers stopped while quiescing. items: type: string type: array required: - state type: object RankedFile: properties: content: type: string path: type: string score: type: number type: object RerankingResponse: properties: files: items: $ref: "#/components/schemas/RankedFile" type: array message: example: Found 5 relevant files type: string success: example: true type: boolean type: object RestoreProgress: properties: deleted: example: 3 type: integer downloaded: description: Downloaded is how much of the archive has been read so far. example: 1048576 type: integer error: description: Error is why the restore failed, without the presigned URL it used. type: string finishedAt: type: string restored: description: Restored and Deleted count what the archive changed on the filesystem. example: 1204 type: integer size: description: >- Size is the archive's size as the storage announced it, and zero when it announced none - a client showing a percentage has to allow for that. example: 3074211 type: integer startedAt: type: string state: allOf: - $ref: "#/components/schemas/archive.RestoreState" example: extracting type: object Subdirectory: properties: name: type: string path: type: string required: - name - path type: object SuccessResponse: properties: message: example: File created successfully type: string path: example: /path/to/file type: string required: - message type: object TreeRequest: properties: files: additionalProperties: type: string example: '"dir/file2.txt"': '"content2"}' "{\"file1.txt\"": '"content1"' type: object type: object TunnelConfigRequest: properties: config: description: Base64-encoded tunnel config JSON example: eyJsb2NhbF9pcCI6ICIxMC4wLjAuMS8zMiIsIC4uLn0= type: string required: - config type: object UpgradeRequest: properties: baseUrl: description: Base URL for releases (useful for forks) example: https://github.com/blaxel-ai/sandbox/releases type: string version: description: 'Version to upgrade to: "latest" (default), "develop", "main", or specific tag like "v1.0.0"' example: latest type: string type: object UpgradeStatus: properties: binaryPath: description: Path to downloaded binary example: /tmp/sandbox-api-new type: string bytesDownloaded: description: Bytes downloaded example: 25034936 type: integer downloadUrl: description: URL used for download example: https://github.com/... type: string error: description: Error message if failed example: Failed to download binary type: string lastAttempt: description: When the upgrade was attempted type: string status: allOf: - $ref: "#/components/schemas/process.UpgradeState" description: Current state (idle, running, completed, failed) example: running step: description: Current/last step (none, starting, download, validate, replace, completed, skipped) example: download type: string version: description: Version being upgraded to example: latest type: string required: - status - step - version type: object archive.Change: properties: kind: allOf: - $ref: "#/components/schemas/archive.ChangeKind" example: added path: description: Path is relative to the root, without a leading slash. example: usr/bin/curl type: string size: description: Size is the file content size in bytes, 0 for anything but a regular file. example: 256216 type: integer required: - kind - path type: object archive.ChangeKind: enum: - added - modified - deleted type: string x-enum-varnames: - ChangeAdded - ChangeModified - ChangeDeleted archive.ExportState: enum: - running - succeeded - failed type: string x-enum-varnames: - ExportRunning - ExportSucceeded - ExportFailed archive.QuiesceState: enum: - active - quiescing - quiesced - restoring type: string x-enum-varnames: - StateActive - StateQuiescing - StateQuiesced - StateRestoring archive.RestoreState: enum: - downloading - extracting - relaunching - succeeded - failed type: string x-enum-varnames: - RestoreDownloading - RestoreExtracting - RestoreRelaunching - RestoreSucceeded - RestoreFailed filesystem.MultipartUpload: properties: initiatedAt: type: string parts: additionalProperties: $ref: "#/components/schemas/filesystem.UploadedPart" type: object path: example: /tmp/largefile.dat type: string permissions: example: 420 type: integer uploadId: example: 550e8400-e29b-41d4-a716-446655440000 type: string type: object filesystem.UploadedPart: properties: etag: example: 5d41402abc4b2a76b9719d911017c592 type: string partNumber: example: 1 type: integer size: example: 5242880 type: integer uploadedAt: type: string type: object handler.ReloadResponse: properties: applied: type: integer generation: type: integer removed: type: integer type: object process.UpgradeState: enum: - idle - running - completed - failed type: string x-enum-comments: UpgradeStateCompleted: Upgrade completed successfully UpgradeStateFailed: Upgrade failed UpgradeStateIdle: No upgrade in progress UpgradeStateRunning: Upgrade is currently running x-enum-descriptions: - No upgrade in progress - Upgrade is currently running - Upgrade completed successfully - Upgrade failed x-enum-varnames: - UpgradeStateIdle - UpgradeStateRunning - UpgradeStateCompleted - UpgradeStateFailed security: - BearerAuth: []