{
  "openapi": "3.0.0",
  "info": {
    "version": "0.1.0",
    "title": "AgentBox API"
  },
  "servers": [
    {
      "url": "https://api.agentbox-runtime.ru"
    }
  ],
  "components": {
    "parameters": {
      "templateID": {
        "name": "templateID",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "buildID": {
        "name": "buildID",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "sandboxID": {
        "name": "sandboxID",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "teamID": {
        "name": "teamID",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "paginationLimit": {
        "name": "limit",
        "in": "query",
        "description": "Maximum number of items to return per page",
        "required": false,
        "schema": {
          "type": "integer",
          "format": "int32",
          "minimum": 1,
          "default": 100,
          "maximum": 100
        }
      },
      "paginationNextToken": {
        "name": "nextToken",
        "in": "query",
        "description": "Cursor to start the list from",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "XNextToken": {
        "description": "Cursor to fetch the next page of results, if more exist",
        "schema": {
          "type": "string"
        }
      },
      "XTotalRunning": {
        "description": "Number of running sandboxes matching the filters, before pagination is applied. Only present when running sandboxes were requested.\n",
        "schema": {
          "type": "integer",
          "format": "int32"
        }
      }
    },
    "responses": {
      "400": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "401": {
        "description": "Authentication error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "403": {
        "description": "Forbidden",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "404": {
        "description": "Not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "409": {
        "description": "Conflict",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "500": {
        "description": "Server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "TeamUser": {
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of the user"
          }
        }
      },
      "TemplateUpdateRequest": {
        "properties": {
          "public": {
            "type": "boolean",
            "description": "Whether the template is public or only accessible by the team"
          }
        }
      },
      "TemplateUpdateResponse": {
        "required": [
          "names"
        ],
        "properties": {
          "names": {
            "type": "array",
            "description": "Names of the template (namespace/alias format when namespaced)",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CPUCount": {
        "type": "integer",
        "format": "int32",
        "minimum": 1,
        "description": "CPU cores for the sandbox"
      },
      "MemoryMB": {
        "type": "integer",
        "format": "int32",
        "minimum": 128,
        "description": "Memory for the sandbox in MiB"
      },
      "DiskSizeMB": {
        "type": "integer",
        "format": "int32",
        "minimum": 0,
        "description": "Disk size for the sandbox in MiB"
      },
      "EnvdVersion": {
        "type": "string",
        "description": "Version of the envd running in the sandbox"
      },
      "SandboxMetadata": {
        "additionalProperties": {
          "type": "string",
          "description": "Metadata of the sandbox"
        }
      },
      "SandboxState": {
        "type": "string",
        "description": "State of the sandbox",
        "enum": [
          "running",
          "paused"
        ]
      },
      "SnapshotInfo": {
        "type": "object",
        "required": [
          "snapshotID",
          "names"
        ],
        "properties": {
          "snapshotID": {
            "type": "string",
            "description": "Identifier of the snapshot template including the tag. Uses namespace/alias when a name was provided (e.g. team-slug/my-snapshot:default), otherwise falls back to the raw template ID (e.g. abc123:default)."
          },
          "names": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Full names of the snapshot template including team namespace and tag (e.g. team-slug/my-snapshot:v2)"
          }
        }
      },
      "EnvVars": {
        "additionalProperties": {
          "type": "string",
          "description": "Environment variables for the sandbox"
        }
      },
      "SandboxNetworkConfig": {
        "type": "object",
        "properties": {
          "allowPublicTraffic": {
            "type": "boolean",
            "default": true,
            "description": "Specify if the sandbox URLs should be accessible only with authentication."
          },
          "allowOut": {
            "type": "array",
            "description": "List of allowed destinations for egress traffic. Each entry can be a CIDR block (e.g. \"8.8.8.8/32\"), a bare IP address (e.g. \"8.8.8.8\"), or a domain name (e.g. \"example.com\", \"*.example.com\"). Allowed entries always take precedence over denied entries.",
            "items": {
              "type": "string"
            }
          },
          "denyOut": {
            "type": "array",
            "description": "List of denied CIDR blocks or IP addresses for egress traffic. Domain names are not supported for deny rules.",
            "items": {
              "type": "string"
            }
          },
          "maskRequestHost": {
            "type": "string",
            "description": "Specify host mask which will be used for all sandbox requests"
          },
          "rules": {
            "type": "object",
            "description": "Per-domain transform rules applied to matching egress HTTP/HTTPS requests. Keys are domains (e.g. \"api.example.com\", \"example.com\"). A domain listed here is not automatically allowed - use allowOut to permit the traffic.\n",
            "additionalProperties": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/SandboxNetworkRule"
              }
            }
          }
        }
      },
      "SandboxNetworkUpdateConfig": {
        "type": "object",
        "description": "Network configuration update for a running sandbox. Replaces the current egress rules with the provided configuration. Omitting a field clears it.",
        "properties": {
          "allowOut": {
            "type": "array",
            "description": "List of allowed destinations for egress traffic. Each entry can be a CIDR block (e.g. \"8.8.8.8/32\"), a bare IP address (e.g. \"8.8.8.8\"), or a domain name (e.g. \"example.com\", \"*.example.com\"). Allowed entries always take precedence over denied entries.",
            "items": {
              "type": "string"
            }
          },
          "denyOut": {
            "type": "array",
            "description": "List of denied CIDR blocks or IP addresses for egress traffic. Domain names are not supported for deny rules.",
            "items": {
              "type": "string"
            }
          },
          "rules": {
            "type": "object",
            "description": "Per-domain transform rules. Replaces all existing rules when provided.",
            "additionalProperties": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/SandboxNetworkRule"
              }
            }
          },
          "allow_internet_access": {
            "type": "boolean",
            "description": "Allow sandbox to access the internet. When set to false, it behaves the same as specifying denyOut to 0.0.0.0/0 in the network config."
          }
        }
      },
      "SandboxNetworkRule": {
        "type": "object",
        "description": "Transform rule applied to egress requests matching a domain pattern.",
        "properties": {
          "transform": {
            "$ref": "#/components/schemas/SandboxNetworkTransform"
          }
        }
      },
      "SandboxNetworkTransform": {
        "type": "object",
        "description": "Transformations applied to matching egress requests before forwarding.",
        "properties": {
          "headers": {
            "type": "object",
            "description": "HTTP headers to inject or override in matching requests. An existing header with the same name is replaced. Values are plain strings; secret resolution happens client-side before sending to the API.\n",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "SandboxAutoResumeEnabled": {
        "type": "boolean",
        "description": "Auto-resume enabled flag for paused sandboxes. Default false.",
        "default": false
      },
      "SandboxAutoResumeConfig": {
        "type": "object",
        "description": "Auto-resume configuration for paused sandboxes.",
        "required": [
          "enabled"
        ],
        "properties": {
          "enabled": {
            "$ref": "#/components/schemas/SandboxAutoResumeEnabled"
          }
        }
      },
      "SandboxOnTimeout": {
        "type": "string",
        "description": "Action taken when the sandbox times out.",
        "enum": [
          "kill",
          "pause"
        ]
      },
      "SandboxLifecycle": {
        "type": "object",
        "description": "Sandbox lifecycle policy returned by sandbox info.",
        "required": [
          "autoResume",
          "onTimeout"
        ],
        "properties": {
          "autoResume": {
            "type": "boolean",
            "description": "Whether the sandbox can auto-resume."
          },
          "onTimeout": {
            "$ref": "#/components/schemas/SandboxOnTimeout"
          }
        }
      },
      "SandboxLogEntry": {
        "required": [
          "timestamp",
          "level",
          "message",
          "fields"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier used to reconcile overlapping live log pages"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of the log entry"
          },
          "message": {
            "type": "string",
            "description": "Log message content"
          },
          "level": {
            "$ref": "#/components/schemas/LogLevel"
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "SandboxLogsV2Response": {
        "required": [
          "logs"
        ],
        "properties": {
          "logs": {
            "default": [],
            "description": "Sandbox logs structured",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SandboxLogEntry"
            }
          },
          "nextCursor": {
            "type": "string",
            "description": "Opaque continuation cursor for the next page"
          }
        }
      },
      "SandboxMetric": {
        "description": "Metric entry with timestamp and line",
        "required": [
          "timestampUnix",
          "cpuCount",
          "cpuUsedPct",
          "memUsed",
          "memTotal",
          "memCache",
          "diskUsed",
          "diskTotal"
        ],
        "properties": {
          "timestampUnix": {
            "type": "integer",
            "format": "int64",
            "description": "Timestamp of the metric entry in Unix time (seconds since epoch)"
          },
          "cpuCount": {
            "type": "integer",
            "format": "int32",
            "description": "Number of CPU cores"
          },
          "cpuUsedPct": {
            "type": "number",
            "format": "float",
            "description": "CPU usage percentage"
          },
          "memUsed": {
            "type": "integer",
            "format": "int64",
            "description": "Memory used in bytes"
          },
          "memTotal": {
            "type": "integer",
            "format": "int64",
            "description": "Total memory in bytes"
          },
          "memCache": {
            "type": "integer",
            "format": "int64",
            "description": "Cached memory (page cache) in bytes"
          },
          "diskUsed": {
            "type": "integer",
            "format": "int64",
            "description": "Disk used in bytes"
          },
          "diskTotal": {
            "type": "integer",
            "format": "int64",
            "description": "Total disk space in bytes"
          }
        }
      },
      "Sandbox": {
        "required": [
          "templateID",
          "sandboxID",
          "envdVersion"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the template from which is the sandbox created"
          },
          "sandboxID": {
            "type": "string",
            "description": "Identifier of the sandbox"
          },
          "alias": {
            "type": "string",
            "description": "Alias of the template"
          },
          "envdVersion": {
            "$ref": "#/components/schemas/EnvdVersion"
          },
          "domain": {
            "type": "string",
            "nullable": true,
            "description": "Base domain where the sandbox traffic is accessible"
          }
        }
      },
      "SandboxDetail": {
        "required": [
          "templateID",
          "sandboxID",
          "startedAt",
          "cpuCount",
          "memoryMB",
          "diskSizeMB",
          "endAt",
          "state",
          "envdVersion"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the template from which is the sandbox created"
          },
          "alias": {
            "type": "string",
            "description": "Alias of the template"
          },
          "sandboxID": {
            "type": "string",
            "description": "Identifier of the sandbox"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the sandbox was started"
          },
          "endAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the sandbox will expire"
          },
          "envdVersion": {
            "$ref": "#/components/schemas/EnvdVersion"
          },
          "allowInternetAccess": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether internet access was explicitly enabled or disabled for the sandbox. Null means it was not explicitly set."
          },
          "domain": {
            "type": "string",
            "nullable": true,
            "description": "Base domain where the sandbox traffic is accessible"
          },
          "cpuCount": {
            "$ref": "#/components/schemas/CPUCount"
          },
          "memoryMB": {
            "$ref": "#/components/schemas/MemoryMB"
          },
          "diskSizeMB": {
            "$ref": "#/components/schemas/DiskSizeMB"
          },
          "metadata": {
            "$ref": "#/components/schemas/SandboxMetadata"
          },
          "state": {
            "$ref": "#/components/schemas/SandboxState"
          },
          "network": {
            "$ref": "#/components/schemas/SandboxNetworkConfig"
          },
          "lifecycle": {
            "$ref": "#/components/schemas/SandboxLifecycle"
          }
        }
      },
      "ListedSandbox": {
        "required": [
          "templateID",
          "sandboxID",
          "startedAt",
          "cpuCount",
          "memoryMB",
          "diskSizeMB",
          "endAt",
          "state",
          "envdVersion"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the template from which is the sandbox created"
          },
          "alias": {
            "type": "string",
            "description": "Alias of the template"
          },
          "sandboxID": {
            "type": "string",
            "description": "Identifier of the sandbox"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the sandbox was started"
          },
          "endAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the sandbox will expire"
          },
          "cpuCount": {
            "$ref": "#/components/schemas/CPUCount"
          },
          "memoryMB": {
            "$ref": "#/components/schemas/MemoryMB"
          },
          "diskSizeMB": {
            "$ref": "#/components/schemas/DiskSizeMB"
          },
          "metadata": {
            "$ref": "#/components/schemas/SandboxMetadata"
          },
          "state": {
            "$ref": "#/components/schemas/SandboxState"
          },
          "envdVersion": {
            "$ref": "#/components/schemas/EnvdVersion"
          }
        }
      },
      "SandboxesWithMetrics": {
        "required": [
          "sandboxes"
        ],
        "properties": {
          "sandboxes": {
            "additionalProperties": {
              "$ref": "#/components/schemas/SandboxMetric"
            }
          }
        }
      },
      "NewSandbox": {
        "required": [
          "templateID"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the required template"
          },
          "timeout": {
            "type": "integer",
            "format": "int32",
            "minimum": 0,
            "default": 15,
            "description": "Time to live for the sandbox in seconds."
          },
          "autoPause": {
            "type": "boolean",
            "default": false,
            "description": "Automatically pauses the sandbox after the timeout"
          },
          "autoPauseMemory": {
            "type": "boolean",
            "default": true,
            "description": "Controls the snapshot kind taken when the sandbox auto-pauses on timeout (only relevant when autoPause is true). When false, the auto-pause drops the in-memory state and persists only the filesystem (a filesystem-only snapshot); resuming it cold-boots (reboots) the sandbox from disk. Such a snapshot cannot be auto-resumed by traffic and must be resumed explicitly, so it cannot be combined with autoResume. Defaults to true (full memory snapshot)."
          },
          "autoResume": {
            "$ref": "#/components/schemas/SandboxAutoResumeConfig"
          },
          "secure": {
            "type": "boolean",
            "description": "Secure all system communication with sandbox"
          },
          "allow_internet_access": {
            "type": "boolean",
            "description": "Allow sandbox to access the internet. When set to false, it behaves the same as specifying denyOut to 0.0.0.0/0 in the network config."
          },
          "network": {
            "$ref": "#/components/schemas/SandboxNetworkConfig"
          },
          "metadata": {
            "$ref": "#/components/schemas/SandboxMetadata"
          },
          "envVars": {
            "$ref": "#/components/schemas/EnvVars"
          },
          "iam": {
            "$ref": "#/components/schemas/SandboxIam"
          }
        }
      },
      "SandboxIam": {
        "type": "object",
        "description": "Sandbox workload identity configuration. A non-empty, valid tokens map enables workload identity for the sandbox.",
        "properties": {
          "tokens": {
            "$ref": "#/components/schemas/SandboxIamTokens"
          }
        }
      },
      "SandboxIamTokens": {
        "type": "object",
        "description": "Named workload-token definitions, keyed by a caller-chosen token name.",
        "additionalProperties": {
          "$ref": "#/components/schemas/SandboxIamToken"
        }
      },
      "SandboxIamToken": {
        "type": "object",
        "required": [
          "audience",
          "tokenType"
        ],
        "properties": {
          "audience": {
            "type": "string",
            "description": "Audience of the workload token, stored exactly as provided."
          },
          "tokenType": {
            "type": "string",
            "description": "Workload token type."
          }
        }
      },
      "ConnectSandbox": {
        "type": "object",
        "required": [
          "timeout"
        ],
        "properties": {
          "timeout": {
            "description": "Timeout in seconds from the current time after which the sandbox should expire",
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "SandboxTimeoutRequest": {
        "type": "object",
        "required": [
          "timeout"
        ],
        "properties": {
          "timeout": {
            "description": "Timeout in seconds from the current time after which the sandbox should expire",
            "type": "integer",
            "format": "int32",
            "minimum": 0
          }
        }
      },
      "SandboxRefreshRequest": {
        "type": "object",
        "properties": {
          "duration": {
            "description": "Duration for which the sandbox should be kept alive in seconds",
            "type": "integer",
            "maximum": 3600,
            "minimum": 0
          }
        }
      },
      "SandboxSnapshotRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Optional name for the snapshot template. If a snapshot template with this name already exists, a new build will be assigned to the existing template instead of creating a new one."
          }
        }
      },
      "SandboxPauseRequest": {
        "type": "object",
        "properties": {
          "memory": {
            "type": "boolean",
            "default": true,
            "description": "Whether to capture a full memory snapshot. When false, only the filesystem is persisted and resuming the sandbox cold-boots (reboots) it from disk, losing in-memory state, running processes, and open connections. Resume it with an explicit request (connect or resume); auto-resume, which can be triggered by arbitrary traffic, refuses such a sandbox. Defaults to true."
          }
        }
      },
      "SandboxForkRequest": {
        "type": "object",
        "properties": {
          "timeout": {
            "type": "integer",
            "format": "int32",
            "minimum": 0,
            "default": 15,
            "description": "Time to live for the new forked sandboxes in seconds."
          },
          "count": {
            "type": "integer",
            "format": "int32",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "description": "Number of forked sandboxes to create. All forks boot from the same snapshot, so the snapshot is captured once regardless of count. Each fork succeeds or fails independently; the outcome of each is reported in its entry of the response list."
          }
        }
      },
      "SandboxForkResult": {
        "type": "object",
        "description": "Result of one requested fork. Exactly one of sandbox or error is set: sandbox when the fork started successfully, error when it failed to start.",
        "properties": {
          "sandbox": {
            "$ref": "#/components/schemas/Sandbox"
          },
          "error": {
            "$ref": "#/components/schemas/Error"
          }
        }
      },
      "TeamMetric": {
        "description": "Team metric with timestamp",
        "required": [
          "timestampUnix",
          "concurrentSandboxes",
          "sandboxStartRate"
        ],
        "properties": {
          "timestampUnix": {
            "type": "integer",
            "format": "int64",
            "description": "Timestamp of the metric entry in Unix time (seconds since epoch)"
          },
          "concurrentSandboxes": {
            "type": "integer",
            "format": "int32",
            "description": "The number of concurrent sandboxes for the team"
          },
          "sandboxStartRate": {
            "type": "number",
            "format": "float",
            "description": "Number of sandboxes started per second"
          }
        }
      },
      "MaxTeamMetric": {
        "description": "Team metric with timestamp",
        "required": [
          "timestampUnix",
          "value"
        ],
        "properties": {
          "timestampUnix": {
            "type": "integer",
            "format": "int64",
            "description": "Timestamp of the metric entry in Unix time (seconds since epoch)"
          },
          "value": {
            "type": "number",
            "description": "The maximum value of the requested metric in the given interval"
          }
        }
      },
      "Template": {
        "required": [
          "templateID",
          "buildID",
          "cpuCount",
          "memoryMB",
          "diskSizeMB",
          "public",
          "createdAt",
          "updatedAt",
          "createdBy",
          "lastSpawnedAt",
          "spawnCount",
          "buildCount",
          "envdVersion",
          "names",
          "buildStatus"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the template"
          },
          "buildID": {
            "type": "string",
            "description": "Identifier of the last successful build for given template"
          },
          "cpuCount": {
            "$ref": "#/components/schemas/CPUCount"
          },
          "memoryMB": {
            "$ref": "#/components/schemas/MemoryMB"
          },
          "diskSizeMB": {
            "$ref": "#/components/schemas/DiskSizeMB"
          },
          "public": {
            "type": "boolean",
            "description": "Whether the template is public or only accessible by the team"
          },
          "names": {
            "type": "array",
            "description": "Names of the template (namespace/alias format when namespaced)",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the template was created"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the template was last updated"
          },
          "createdBy": {
            "allOf": [
              {
                "$ref": "#/components/schemas/TeamUser"
              }
            ],
            "nullable": true
          },
          "lastSpawnedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Time when the template was last used"
          },
          "spawnCount": {
            "type": "integer",
            "format": "int64",
            "description": "Number of times the template was used"
          },
          "buildCount": {
            "type": "integer",
            "format": "int32",
            "description": "Number of times the template was built"
          },
          "envdVersion": {
            "$ref": "#/components/schemas/EnvdVersion"
          },
          "buildStatus": {
            "$ref": "#/components/schemas/TemplateBuildStatus"
          }
        }
      },
      "TemplateRequestResponseV3": {
        "required": [
          "templateID",
          "buildID",
          "public",
          "names",
          "tags"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the template"
          },
          "buildID": {
            "type": "string",
            "description": "Identifier of the last successful build for given template"
          },
          "public": {
            "type": "boolean",
            "description": "Whether the template is public or only accessible by the team"
          },
          "names": {
            "type": "array",
            "description": "Names of the template",
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "description": "Tags assigned to the template build",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "TemplateBuild": {
        "required": [
          "buildID",
          "status",
          "createdAt",
          "updatedAt",
          "cpuCount",
          "memoryMB"
        ],
        "properties": {
          "buildID": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of the build"
          },
          "status": {
            "$ref": "#/components/schemas/TemplateBuildStatus"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the build was created"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the build was last updated"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the build was finished"
          },
          "cpuCount": {
            "$ref": "#/components/schemas/CPUCount"
          },
          "memoryMB": {
            "$ref": "#/components/schemas/MemoryMB"
          },
          "diskSizeMB": {
            "$ref": "#/components/schemas/DiskSizeMB"
          },
          "envdVersion": {
            "$ref": "#/components/schemas/EnvdVersion"
          }
        }
      },
      "TemplateWithBuilds": {
        "required": [
          "templateID",
          "public",
          "names",
          "createdAt",
          "updatedAt",
          "lastSpawnedAt",
          "spawnCount",
          "builds"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the template"
          },
          "public": {
            "type": "boolean",
            "description": "Whether the template is public or only accessible by the team"
          },
          "names": {
            "type": "array",
            "description": "Names of the template (namespace/alias format when namespaced)",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the template was created"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the template was last updated"
          },
          "lastSpawnedAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Time when the template was last used"
          },
          "spawnCount": {
            "type": "integer",
            "format": "int64",
            "description": "Number of times the template was used"
          },
          "builds": {
            "type": "array",
            "description": "List of builds for the template",
            "items": {
              "$ref": "#/components/schemas/TemplateBuild"
            }
          }
        }
      },
      "TemplateAliasResponse": {
        "required": [
          "templateID",
          "public"
        ],
        "properties": {
          "templateID": {
            "type": "string",
            "description": "Identifier of the template"
          },
          "public": {
            "type": "boolean",
            "description": "Whether the template is public or only accessible by the team"
          }
        }
      },
      "TemplateStep": {
        "description": "Step in the template build process",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Type of the step"
          },
          "args": {
            "default": [],
            "type": "array",
            "description": "Arguments for the step",
            "items": {
              "type": "string"
            }
          },
          "filesHash": {
            "type": "string",
            "description": "Hash of the files used in the step"
          },
          "force": {
            "default": false,
            "type": "boolean",
            "description": "Whether the step should be forced to run regardless of the cache"
          }
        }
      },
      "TemplateBuildRequestV3": {
        "properties": {
          "name": {
            "description": "Name of the template. Can include a tag with colon separator (e.g. \"my-template\" or \"my-template:v1\"). If tag is included, it will be treated as if the tag was provided in the tags array.",
            "type": "string",
            "maxLength": 128
          },
          "tags": {
            "type": "array",
            "description": "Tags to assign to the template build",
            "items": {
              "type": "string"
            }
          },
          "cpuCount": {
            "$ref": "#/components/schemas/CPUCount"
          },
          "memoryMB": {
            "$ref": "#/components/schemas/MemoryMB"
          }
        }
      },
      "FromImageRegistry": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/AWSRegistry"
          },
          {
            "$ref": "#/components/schemas/GCPRegistry"
          },
          {
            "$ref": "#/components/schemas/GeneralRegistry"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "aws": "#/components/schemas/AWSRegistry",
            "gcp": "#/components/schemas/GCPRegistry",
            "registry": "#/components/schemas/GeneralRegistry"
          }
        }
      },
      "AWSRegistry": {
        "type": "object",
        "required": [
          "type",
          "awsAccessKeyId",
          "awsSecretAccessKey",
          "awsRegion"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "aws"
            ],
            "description": "Type of registry authentication"
          },
          "awsAccessKeyId": {
            "type": "string",
            "description": "AWS Access Key ID for ECR authentication"
          },
          "awsSecretAccessKey": {
            "type": "string",
            "description": "AWS Secret Access Key for ECR authentication"
          },
          "awsRegion": {
            "type": "string",
            "description": "AWS Region where the ECR registry is located"
          }
        }
      },
      "GCPRegistry": {
        "type": "object",
        "required": [
          "type",
          "serviceAccountJson"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "gcp"
            ],
            "description": "Type of registry authentication"
          },
          "serviceAccountJson": {
            "type": "string",
            "description": "Service Account JSON for GCP authentication"
          }
        }
      },
      "GeneralRegistry": {
        "type": "object",
        "required": [
          "type",
          "username",
          "password"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "registry"
            ],
            "description": "Type of registry authentication"
          },
          "username": {
            "type": "string",
            "description": "Username to use for the registry"
          },
          "password": {
            "type": "string",
            "description": "Password to use for the registry"
          }
        }
      },
      "TemplateBuildStartV2": {
        "type": "object",
        "properties": {
          "fromImage": {
            "type": "string",
            "description": "Image to use as a base for the template build"
          },
          "fromTemplate": {
            "type": "string",
            "description": "Template to use as a base for the template build"
          },
          "fromImageRegistry": {
            "$ref": "#/components/schemas/FromImageRegistry"
          },
          "force": {
            "default": false,
            "type": "boolean",
            "description": "Whether the whole build should be forced to run regardless of the cache"
          },
          "steps": {
            "default": [],
            "description": "List of steps to execute in the template build",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateStep"
            }
          },
          "startCmd": {
            "description": "Start command to execute in the template after the build",
            "type": "string"
          },
          "readyCmd": {
            "description": "Ready check command to execute in the template after the build",
            "type": "string"
          }
        }
      },
      "TemplateBuildFileUpload": {
        "required": [
          "present"
        ],
        "properties": {
          "present": {
            "type": "boolean",
            "description": "Whether the file is already present in the cache"
          },
          "url": {
            "description": "Url where the file should be uploaded to",
            "type": "string"
          }
        }
      },
      "LogLevel": {
        "type": "string",
        "description": "State of the sandbox",
        "enum": [
          "debug",
          "info",
          "warn",
          "error"
        ]
      },
      "BuildLogEntry": {
        "required": [
          "timestamp",
          "message",
          "level"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier used to reconcile overlapping live log pages"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of the log entry"
          },
          "message": {
            "type": "string",
            "description": "Log message content"
          },
          "level": {
            "$ref": "#/components/schemas/LogLevel"
          },
          "step": {
            "type": "string",
            "description": "Step in the build process related to the log entry"
          }
        }
      },
      "BuildStatusReason": {
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "description": "Message with the status reason, currently reporting only for error status"
          },
          "step": {
            "type": "string",
            "description": "Step that failed"
          },
          "logEntries": {
            "default": [],
            "description": "Log entries related to the status reason",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BuildLogEntry"
            }
          }
        }
      },
      "TemplateBuildStatus": {
        "type": "string",
        "description": "Status of the template build",
        "enum": [
          "building",
          "waiting",
          "ready",
          "error"
        ]
      },
      "TemplateBuildInfo": {
        "required": [
          "templateID",
          "buildID",
          "status",
          "logs",
          "logEntries"
        ],
        "properties": {
          "logs": {
            "default": [],
            "description": "Build logs",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "logEntries": {
            "default": [],
            "description": "Build logs structured",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BuildLogEntry"
            }
          },
          "templateID": {
            "type": "string",
            "description": "Identifier of the template"
          },
          "buildID": {
            "type": "string",
            "description": "Identifier of the build"
          },
          "status": {
            "$ref": "#/components/schemas/TemplateBuildStatus"
          },
          "reason": {
            "$ref": "#/components/schemas/BuildStatusReason"
          }
        }
      },
      "TemplateBuildLogsResponse": {
        "required": [
          "logs"
        ],
        "properties": {
          "logs": {
            "default": [],
            "description": "Build logs structured",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BuildLogEntry"
            }
          },
          "nextCursor": {
            "type": "string",
            "description": "Opaque continuation cursor for the next page"
          },
          "source": {
            "$ref": "#/components/schemas/LogsSource",
            "description": "Actual source used to serve this page"
          }
        }
      },
      "LogsDirection": {
        "type": "string",
        "description": "Direction of the logs that should be returned",
        "enum": [
          "forward",
          "backward"
        ]
      },
      "LogsSource": {
        "type": "string",
        "description": "Source of the logs that should be returned",
        "enum": [
          "temporary",
          "persistent"
        ]
      },
      "AssignedTemplateTags": {
        "required": [
          "tags",
          "buildID"
        ],
        "properties": {
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Assigned tags of the template"
          },
          "buildID": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of the build associated with these tags"
          }
        }
      },
      "TemplateTag": {
        "required": [
          "tag",
          "buildID",
          "createdAt"
        ],
        "properties": {
          "tag": {
            "type": "string",
            "description": "The tag name"
          },
          "buildID": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of the build associated with this tag"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time when the tag was assigned"
          }
        }
      },
      "AssignTemplateTagsRequest": {
        "required": [
          "target",
          "tags"
        ],
        "properties": {
          "target": {
            "type": "string",
            "description": "Target template in \"name:tag\" format"
          },
          "tags": {
            "description": "Tags to assign to the template",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "DeleteTemplateTagsRequest": {
        "required": [
          "name",
          "tags"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the template"
          },
          "tags": {
            "description": "Tags to delete",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Error": {
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "format": "int32",
            "description": "Error code"
          },
          "message": {
            "type": "string",
            "description": "Error"
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    }
  },
  "tags": [
    {
      "name": "sandboxes"
    },
    {
      "name": "snapshots"
    },
    {
      "name": "tags"
    },
    {
      "name": "team-metrics"
    },
    {
      "name": "templates"
    }
  ],
  "paths": {
    "/teams/{teamID}/metrics": {
      "get": {
        "summary": "Team metrics",
        "description": "Get metrics for the team",
        "tags": [
          "team-metrics"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/teamID"
          },
          {
            "in": "query",
            "name": "start",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            },
            "description": "Unix timestamp for the start of the interval, in seconds, for which the metrics"
          },
          {
            "in": "query",
            "name": "end",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0,
              "description": "Unix timestamp for the end of the interval, in seconds, for which the metrics"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the team metrics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TeamMetric"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getTeamMetrics",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/teams/{teamID}/metrics/max": {
      "get": {
        "summary": "Maximum team metrics",
        "description": "Get the maximum metrics for the team in the given interval",
        "tags": [
          "team-metrics"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/teamID"
          },
          {
            "in": "query",
            "name": "start",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            },
            "description": "Unix timestamp for the start of the interval, in seconds, for which the metrics"
          },
          {
            "in": "query",
            "name": "end",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0,
              "description": "Unix timestamp for the end of the interval, in seconds, for which the metrics"
            }
          },
          {
            "in": "query",
            "name": "metric",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "concurrent_sandboxes",
                "sandbox_start_rate"
              ]
            },
            "description": "Metric to retrieve the maximum value for"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the team metrics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaxTeamMetric"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getTeamMetricsMax",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes": {
      "post": {
        "summary": "Create sandbox",
        "description": "Create a sandbox from the template",
        "tags": [
          "sandboxes"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewSandbox"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The sandbox was created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sandbox"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "createSandbox",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v2/sandboxes": {
      "get": {
        "summary": "List sandboxes (v2)",
        "description": "List all sandboxes",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "name": "metadata",
            "in": "query",
            "description": "Metadata query used to filter the sandboxes (e.g. \"user=abc&app=prod\"). Each key and values must be URL encoded.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "Filter sandboxes by one or more states",
            "required": false,
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/SandboxState"
              }
            },
            "style": "form",
            "explode": false
          },
          {
            "$ref": "#/components/parameters/paginationNextToken"
          },
          {
            "$ref": "#/components/parameters/paginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned all running sandboxes",
            "headers": {
              "X-Next-Token": {
                "$ref": "#/components/headers/XNextToken"
              },
              "X-Total-Running": {
                "$ref": "#/components/headers/XTotalRunning"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ListedSandbox"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "listSandboxes",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/metrics": {
      "get": {
        "summary": "List sandbox metrics",
        "description": "List metrics for given sandboxes",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "name": "sandbox_ids",
            "in": "query",
            "required": true,
            "description": "Comma-separated list of sandbox IDs to get metrics for",
            "explode": false,
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "maxItems": 100,
              "uniqueItems": true
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned all running sandboxes with metrics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxesWithMetrics"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "listSandboxMetrics",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v2/sandboxes/{sandboxID}/logs": {
      "get": {
        "summary": "Sandbox logs (v2)",
        "description": "Get sandbox logs",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          },
          {
            "in": "query",
            "name": "pageCursor",
            "schema": {
              "type": "string",
              "maxLength": 512
            },
            "description": "Opaque continuation cursor returned as nextCursor by the previous page"
          },
          {
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            },
            "description": "Starting timestamp of the logs that should be returned in milliseconds"
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 1000,
              "type": "integer",
              "format": "int32",
              "minimum": 0,
              "maximum": 1000
            },
            "description": "Maximum number of logs that should be returned"
          },
          {
            "in": "query",
            "name": "direction",
            "schema": {
              "$ref": "#/components/schemas/LogsDirection"
            },
            "description": "Direction of the logs that should be returned"
          },
          {
            "in": "query",
            "name": "level",
            "schema": {
              "$ref": "#/components/schemas/LogLevel"
            },
            "description": "Minimum log level to return. Logs below this level are excluded"
          },
          {
            "in": "query",
            "name": "search",
            "schema": {
              "type": "string",
              "maxLength": 256
            },
            "description": "Case-sensitive substring match on log message content"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the sandbox logs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxLogsV2Response"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getSandboxLogs",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}": {
      "get": {
        "summary": "Sandbox",
        "description": "Get a sandbox by id",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the sandbox",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SandboxDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getSandbox",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Kill sandbox",
        "description": "Kill a sandbox",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "responses": {
          "204": {
            "description": "The sandbox was killed successfully"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "killSandbox",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/metrics": {
      "get": {
        "summary": "Sandbox metrics",
        "description": "Get sandbox metrics",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          },
          {
            "in": "query",
            "name": "start",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            },
            "description": "Unix timestamp for the start of the interval, in seconds, for which the metrics"
          },
          {
            "in": "query",
            "name": "end",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0,
              "description": "Unix timestamp for the end of the interval, in seconds, for which the metrics"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the sandbox metrics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SandboxMetric"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getSandboxMetrics",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/pause": {
      "post": {
        "summary": "Pause sandbox",
        "description": "Pause the sandbox",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxPauseRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "The sandbox was paused successfully and can be resumed"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "pauseSandbox",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/fork": {
      "post": {
        "summary": "Fork sandbox",
        "description": "Fork the sandbox: checkpoint the running sandbox in place (it is briefly paused, snapshotted with its full memory state, and resumed on its node, keeping its ID and expiration untouched) and create count new sandboxes from that snapshot. Returns one result per requested fork, each carrying either the created sandbox or the error that prevented it from starting. A non-201 status means the request failed before any fork was attempted.",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxForkRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The sandbox was snapshotted and the forks were attempted; each entry reports one fork's outcome",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SandboxForkResult"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "forkSandbox",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/connect": {
      "post": {
        "summary": "Connect sandbox",
        "description": "Returns sandbox details. If the sandbox is paused, it will be resumed. TTL is only extended.",
        "tags": [
          "sandboxes"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConnectSandbox"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The sandbox was already running",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sandbox"
                }
              }
            }
          },
          "201": {
            "description": "The sandbox was resumed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sandbox"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "connectSandbox",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/timeout": {
      "post": {
        "summary": "Set sandbox timeout",
        "description": "Set the timeout for the sandbox. The sandbox will expire x seconds from the time of the request. Calling this method multiple times overwrites the TTL, each time using the current timestamp as the starting point to measure the timeout duration.",
        "tags": [
          "sandboxes"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxTimeoutRequest"
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "responses": {
          "204": {
            "description": "Successfully set the sandbox timeout"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "setSandboxTimeout",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/network": {
      "put": {
        "summary": "Update sandbox network",
        "description": "Update the network configuration for a running sandbox. Replaces the current egress rules with the provided configuration. Omitting field clears it.",
        "tags": [
          "sandboxes"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxNetworkUpdateConfig"
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "responses": {
          "204": {
            "description": "Successfully updated the sandbox network configuration"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "updateSandboxNetwork",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/refreshes": {
      "post": {
        "summary": "Refresh sandbox",
        "description": "Refresh the sandbox extending its time to live",
        "tags": [
          "sandboxes"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxRefreshRequest"
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "responses": {
          "204": {
            "description": "Successfully refreshed the sandbox"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          }
        },
        "operationId": "refreshSandbox",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/sandboxes/{sandboxID}/snapshots": {
      "post": {
        "summary": "Create snapshot",
        "description": "Create a persistent snapshot from the sandbox's current state. Snapshots can be used to create new sandboxes and persist beyond the original sandbox's lifetime.",
        "tags": [
          "snapshots"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/sandboxID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SandboxSnapshotRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Snapshot created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotInfo"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "createSnapshot",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/snapshots": {
      "get": {
        "summary": "List snapshots",
        "description": "List all snapshots for the team",
        "tags": [
          "snapshots"
        ],
        "parameters": [
          {
            "name": "sandboxID",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter snapshots by source sandbox ID"
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Filter snapshots by name or ID, optionally tag-qualified (e.g. \"my-snapshot\", \"my-team/my-snapshot\" or \"my-snapshot:v1\").",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/paginationLimit"
          },
          {
            "$ref": "#/components/parameters/paginationNextToken"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned snapshots",
            "headers": {
              "X-Next-Token": {
                "$ref": "#/components/headers/XNextToken"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SnapshotInfo"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "listSnapshots",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v3/templates": {
      "post": {
        "summary": "Create template (v3)",
        "description": "Create a new template",
        "tags": [
          "templates"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateBuildRequestV3"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The build was requested successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateRequestResponseV3"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "createTemplate",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v2/templates": {
      "get": {
        "summary": "List templates (v2)",
        "description": "List all templates",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "in": "query",
            "required": false,
            "name": "teamID",
            "schema": {
              "type": "string",
              "description": "Identifier of the team"
            }
          },
          {
            "$ref": "#/components/parameters/paginationNextToken"
          },
          {
            "$ref": "#/components/parameters/paginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned all templates",
            "headers": {
              "X-Next-Token": {
                "$ref": "#/components/headers/XNextToken"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Template"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "listTemplates",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/templates/{templateID}/files/{hash}": {
      "get": {
        "summary": "Template build file upload URL",
        "description": "Get an upload link for a tar file containing build layer files",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          },
          {
            "in": "path",
            "name": "hash",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Hash of the files"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "The upload link where to upload the tar file",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateBuildFileUpload"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getTemplateUploadUrl",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/templates/{templateID}": {
      "get": {
        "summary": "List template builds",
        "description": "List all builds for a template",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          },
          {
            "$ref": "#/components/parameters/paginationNextToken"
          },
          {
            "$ref": "#/components/parameters/paginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the template with its builds",
            "headers": {
              "X-Next-Token": {
                "$ref": "#/components/headers/XNextToken"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateWithBuilds"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getTemplate",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Delete template",
        "description": "Delete a template",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          }
        ],
        "responses": {
          "204": {
            "description": "The template was deleted successfully"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "deleteTemplate",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v2/templates/{templateID}/builds/{buildID}": {
      "post": {
        "summary": "Start template build (v2)",
        "description": "Start the build",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          },
          {
            "$ref": "#/components/parameters/buildID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateBuildStartV2"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The build has started"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "startTemplateBuild",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/v2/templates/{templateID}": {
      "patch": {
        "summary": "Update template (v2)",
        "description": "Update template",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The template was updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateUpdateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "updateTemplate",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/templates/{templateID}/builds/{buildID}/status": {
      "get": {
        "summary": "Template build status",
        "description": "Get template build info",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          },
          {
            "$ref": "#/components/parameters/buildID"
          },
          {
            "in": "query",
            "name": "logsOffset",
            "schema": {
              "default": 0,
              "type": "integer",
              "format": "int32",
              "minimum": 0
            },
            "description": "Index of the starting build log that should be returned with the template"
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "type": "integer",
              "format": "int32",
              "minimum": 0,
              "maximum": 100
            },
            "description": "Maximum number of logs that should be returned"
          },
          {
            "in": "query",
            "name": "level",
            "schema": {
              "$ref": "#/components/schemas/LogLevel"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the template",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateBuildInfo"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getTemplateBuildStatus",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/templates/{templateID}/builds/{buildID}/logs": {
      "get": {
        "summary": "Template build logs",
        "description": "Get template build logs",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          },
          {
            "$ref": "#/components/parameters/buildID"
          },
          {
            "in": "query",
            "name": "pageCursor",
            "schema": {
              "type": "string",
              "maxLength": 512
            },
            "description": "Opaque continuation cursor returned as nextCursor by the previous page"
          },
          {
            "in": "query",
            "name": "cursor",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 0
            },
            "description": "Starting timestamp of the logs that should be returned in milliseconds"
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 100,
              "type": "integer",
              "format": "int32",
              "minimum": 0,
              "maximum": 100
            },
            "description": "Maximum number of logs that should be returned"
          },
          {
            "in": "query",
            "name": "direction",
            "schema": {
              "$ref": "#/components/schemas/LogsDirection"
            }
          },
          {
            "in": "query",
            "name": "level",
            "schema": {
              "$ref": "#/components/schemas/LogLevel"
            }
          },
          {
            "in": "query",
            "name": "source",
            "schema": {
              "$ref": "#/components/schemas/LogsSource"
            },
            "description": "Source of the logs that should be returned from"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the template build logs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateBuildLogsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getTemplateBuildLogs",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/templates/tags": {
      "post": {
        "summary": "Assign template tags",
        "description": "Assign tag(s) to a template build",
        "tags": [
          "tags"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AssignTemplateTagsRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tag assigned successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssignedTemplateTags"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "assignTemplateTags",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      },
      "delete": {
        "summary": "Delete template tags",
        "description": "Delete multiple tags from templates",
        "tags": [
          "tags"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteTemplateTagsRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Tags deleted successfully"
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "deleteTemplateTags",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/templates/{templateID}/tags": {
      "get": {
        "summary": "List template tags",
        "description": "List all tags for a template",
        "tags": [
          "tags"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/templateID"
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully returned the template tags",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TemplateTag"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "listTemplateTags",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    },
    "/templates/aliases/{alias}": {
      "get": {
        "summary": "Check template alias",
        "description": "Check if template with given alias exists",
        "tags": [
          "templates"
        ],
        "parameters": [
          {
            "name": "alias",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Template alias"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successfully queried template by alias",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateAliasResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "500": {
            "$ref": "#/components/responses/500"
          }
        },
        "operationId": "getTemplateByAlias",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ]
      }
    }
  }
}
