# List sandboxes

Source: https://docs.recoupable.dev/api-reference/sandboxes/list

List all sandboxes associated with the authenticated account and their current statuses.

## GET /api/sandboxes

Full OpenAPI specification: https://docs.recoupable.dev/spec/content.json

## Authentication

The supplied specification does not declare an OpenAPI security object for this operation. Its declared headers and parameters still apply. Consult the authentication guide and the full specification before calling it.

[Authentication guide](https://docs.recoupable.dev/authentication)

## Operation and referenced schemas

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Recoup API - Content",
    "description": "API documentation for the Recoup platform - an AI agent platform for the music industry",
    "license": {
      "name": "MIT"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.recoupable.dev"
    }
  ],
  "paths": {
    "/api/sandboxes": {
      "get": {
        "operationId": "getSandboxes",
        "description": "List all sandboxes associated with the authenticated account and their current statuses. Returns sandbox details including lifecycle state, timeout remaining, and creation timestamp. Authentication is handled via the x-api-key header or Authorization Bearer token.\n\nSet `metadata_only=true` when you only need the existing saved metadata. This skips live sandbox status lookups and returns an empty `sandboxes` array alongside `snapshot_id`, `github_repo` and `filetree`, preserving their existing nullable behavior. Stored metadata reads and the optional GitHub filetree lookup still run. The empty array in this mode does not establish whether any sandbox is running.\n\nOmitting `metadata_only` or sending literal `false` preserves normal live-status behavior. Authentication, account access checks and sandbox filters remain the same in either mode. Supplied values must be literal lowercase `true` or `false`; other values, including an empty value, return 400 through query validation.\n\nOmit `account_id` to read the authenticated account. An explicit UUID must pass the existing account-access policy: the caller itself, an organization the caller belongs to, a shared-organization account, or existing Recoup administrative access. Invalid UUIDs return 400; denied targets return 403 before snapshot or repository lookup. A target read never falls back to the caller's repository. Successful explicit-target reads echo `account_id`; omitted-target responses do not add that field. This delegates reads only, not upload, replacement or deletion rights.",
        "parameters": [
          {
            "name": "sandbox_id",
            "in": "query",
            "required": false,
            "description": "Filter by a specific sandbox ID. When provided, returns only the sandbox matching this ID. Must be a sandbox that your account or organization is an admin of.",
            "schema": {
              "type": "string",
              "example": "sbx_abc123def456"
            }
          },
          {
            "name": "account_id",
            "in": "query",
            "description": "Optional target account UUID authorized by the existing account-access policy. Omit for the authenticated account. Successful explicit-target reads echo this value as account_id; this does not grant file-write access.",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "11111111-1111-4111-8111-111111111111"
          },
          {
            "name": "metadata_only",
            "in": "query",
            "required": false,
            "description": "Send literal lowercase true to skip live sandbox status lookups and return the existing metadata with an empty sandboxes array. Omitted or false retains live-status lookups. Database metadata reads and optional GitHub filetree retrieval still run; authentication, access checks and sandbox filters are unchanged. Other supplied values, including an empty value, return 400.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sandboxes retrieved successfully. In metadata_only mode, sandboxes is empty while the existing saved metadata fields are retained. Explicit authorized account_id requests echo that account_id; omitted-target requests keep the existing response shape.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxesResponse"
                },
                "examples": {
                  "ownMetadata": {
                    "summary": "Authenticated account metadata (metadata_only=true)",
                    "value": {
                      "status": "success",
                      "sandboxes": [],
                      "snapshot_id": null,
                      "github_repo": null,
                      "filetree": null
                    }
                  },
                  "targetMetadata": {
                    "summary": "Authorized explicit account metadata (account_id and metadata_only=true)",
                    "value": {
                      "status": "success",
                      "sandboxes": [],
                      "snapshot_id": null,
                      "github_repo": null,
                      "filetree": null,
                      "account_id": "11111111-1111-4111-8111-111111111111"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters, including an invalid account_id UUID or a supplied metadata_only value other than literal lowercase true or false.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Access denied to the explicit account_id. No target snapshot/repository lookup or fallback to the caller's repository occurs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "SandboxesResponse": {
        "type": "object",
        "required": [
          "status",
          "sandboxes"
        ],
        "description": "Response containing sandbox information",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error"
            ],
            "description": "Status of the request"
          },
          "sandboxes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Sandbox"
            },
            "description": "Array of sandbox objects"
          },
          "snapshot_id": {
            "type": "string",
            "description": "The account's saved snapshot ID used for creating new sandboxes. Null if no snapshot has been saved.",
            "example": "snap_abc123def456",
            "nullable": true
          },
          "github_repo": {
            "type": "string",
            "description": "The GitHub repository URL associated with the account's sandbox environment. Used as the filesystem source when restoring sandboxes.",
            "example": "https://github.com/username/repo",
            "nullable": true
          },
          "filetree": {
            "type": "array",
            "nullable": true,
            "description": "The recursive file tree of the account's GitHub repository. Null if no github_repo is set or if the fetch fails.",
            "items": {
              "$ref": "#/components/schemas/FileTreeEntry"
            }
          },
          "error": {
            "type": "string",
            "description": "Error message (only present if status is error)"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "description": "On successful GET reads only: the explicitly requested, authorized target account UUID. Present even for an explicit self target; absent when account_id was omitted. This is read scope, not write authorization.",
            "example": "11111111-1111-4111-8111-111111111111"
          }
        }
      },
      "SandboxErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Error message describing what went wrong",
            "example": "Failed to create sandbox"
          }
        }
      },
      "Sandbox": {
        "type": "object",
        "required": [
          "sandboxId",
          "sandboxStatus",
          "timeout",
          "createdAt"
        ],
        "description": "A sandbox environment instance",
        "properties": {
          "sandboxId": {
            "type": "string",
            "description": "Unique identifier for the sandbox",
            "example": "sbx_abc123def456"
          },
          "sandboxStatus": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "stopping",
              "stopped",
              "failed"
            ],
            "description": "Current lifecycle state of the sandbox",
            "example": "running"
          },
          "timeout": {
            "type": "integer",
            "description": "Milliseconds remaining before the sandbox stops automatically",
            "example": 300000
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp when the sandbox was created",
            "example": "2024-01-15T10:30:00.000Z"
          },
          "runId": {
            "type": "string",
            "description": "Unique identifier for the command execution run. Only present if a command was provided when creating the sandbox. Use this with [GET /api/tasks/runs](/api-reference/tasks/runs) to check the status and retrieve results.",
            "example": "run_xyz789abc123"
          }
        }
      },
      "FileTreeEntry": {
        "type": "object",
        "required": [
          "path",
          "type",
          "sha"
        ],
        "description": "A single entry in a GitHub repository file tree",
        "properties": {
          "path": {
            "type": "string",
            "description": "The file or directory path relative to the repository root",
            "example": "src/index.ts"
          },
          "type": {
            "type": "string",
            "enum": [
              "blob",
              "tree"
            ],
            "description": "The type of entry: blob for files, tree for directories"
          },
          "sha": {
            "type": "string",
            "description": "The SHA hash of the entry",
            "example": "abc123def456"
          },
          "size": {
            "type": "integer",
            "description": "The size of the file in bytes. Only present for blob entries.",
            "example": 1024
          }
        }
      }
    }
  }
}
```
