From 1277c7baf3d4bfc69d9ea8e997418026513c2c84 Mon Sep 17 00:00:00 2001 From: Tomas Beran Date: Mon, 2 Feb 2026 16:59:06 -0800 Subject: [PATCH 1/6] Add REST API reference using OpenAPI spec from infra repo Adds a new "REST API" navigation anchor that uses Mintlify's native OpenAPI support to auto-generate interactive API documentation from the E2B infra repository's OpenAPI spec. --- docs.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs.json b/docs.json index d89e016..6798e65 100644 --- a/docs.json +++ b/docs.json @@ -212,6 +212,14 @@ "anchor": "SDK Reference", "icon": "brackets-curly", "href": "https://e2b.dev/docs/sdk-reference" + }, + { + "anchor": "REST API", + "icon": "code", + "openapi": { + "source": "https://raw.githubusercontent.com/e2b-dev/infra/main/spec/openapi.yml", + "directory": "docs/api-reference" + } } ], "global": {} From fcb373155338ecb69351555452ef259541c4ad2c Mon Sep 17 00:00:00 2001 From: Tomas Beran Date: Wed, 4 Feb 2026 18:04:00 -0800 Subject: [PATCH 2/6] Add Sandbox API reference and automated spec sync - Add Sandbox API OpenAPI spec with filesystem and process endpoints - Filter REST API spec to only include user-facing endpoints (ApiKeyAuth) - Remove admin/internal endpoints (Supabase-only, AccessToken-only) - Add sync script to fetch and transform specs from infra repo - Add GitHub Actions workflow for scheduled sync every 6 hours - Fix OpenAPI 3.0 compatibility issues in generated specs --- .github/workflows/sync-openapi.yml | 61 + .gitignore | 2 + docs.json | 10 +- openapi-public.yml | 2424 ++++++++++++++++++++++++++++ openapi-sandbox.yml | 1683 +++++++++++++++++++ package.json | 12 + scripts/sync-openapi.js | 484 ++++++ 7 files changed, 4675 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/sync-openapi.yml create mode 100644 openapi-public.yml create mode 100644 openapi-sandbox.yml create mode 100644 package.json create mode 100644 scripts/sync-openapi.js diff --git a/.github/workflows/sync-openapi.yml b/.github/workflows/sync-openapi.yml new file mode 100644 index 0000000..3a705d3 --- /dev/null +++ b/.github/workflows/sync-openapi.yml @@ -0,0 +1,61 @@ +name: Sync OpenAPI Specs + +on: + # Run every 6 hours + schedule: + - cron: '0 */6 * * *' + # Allow manual trigger + workflow_dispatch: + # Re-run if sync script changes + push: + branches: [main] + paths: + - 'scripts/sync-openapi.js' + +jobs: + sync: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: npm install + + - name: Setup buf (for proto generation) + uses: bufbuild/buf-setup-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install protoc-gen-connect-openapi + run: | + go install github.com/sudorandom/protoc-gen-connect-openapi@latest + echo "$HOME/go/bin" >> $GITHUB_PATH + + - name: Sync OpenAPI specs + run: node scripts/sync-openapi.js + + - name: Validate specs + run: | + npx mintlify openapi-check openapi-public.yml + npx mintlify openapi-check openapi-sandbox.yml + + - name: Commit and push changes + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add openapi-public.yml openapi-sandbox.yml + if git diff --staged --quiet; then + echo "No changes to commit" + else + git commit -m "chore: sync OpenAPI specs from infra" + git push + fi diff --git a/.gitignore b/.gitignore index 090a1f0..0f7e488 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea .DS_Store +node_modules/ +package-lock.json diff --git a/docs.json b/docs.json index 6798e65..ff6852e 100644 --- a/docs.json +++ b/docs.json @@ -217,9 +217,17 @@ "anchor": "REST API", "icon": "code", "openapi": { - "source": "https://raw.githubusercontent.com/e2b-dev/infra/main/spec/openapi.yml", + "source": "openapi-public.yml", "directory": "docs/api-reference" } + }, + { + "anchor": "Sandbox API", + "icon": "server", + "openapi": { + "source": "openapi-sandbox.yml", + "directory": "docs/sandbox-api" + } } ], "global": {} diff --git a/openapi-public.yml b/openapi-public.yml new file mode 100644 index 0000000..2d0a96b --- /dev/null +++ b/openapi-public.yml @@ -0,0 +1,2424 @@ +openapi: 3.0.0 +info: + version: 0.1.0 + title: E2B REST API + description: | + REST API for managing E2B sandboxes and templates. + + ## Authentication + All endpoints require authentication via API key passed in the `X-API-Key` header. + Get your API key from the [E2B Dashboard](https://e2b.dev/dashboard?tab=keys). + + ## Base URL + ``` + https://api.e2b.app + ``` +servers: + - url: https://api.e2b.app +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: X-API-Key + 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 + nodeID: + name: nodeID + in: path + required: true + schema: + type: string + apiKeyID: + name: apiKeyID + in: path + required: true + schema: + type: string + accessTokenID: + name: accessTokenID + in: path + required: true + schema: + type: string + tag: + name: tag + in: path + required: true + schema: + type: string + description: Tag name + 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 + 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: + Team: + required: + - teamID + - name + - apiKey + - isDefault + properties: + teamID: + type: string + description: Identifier of the team + name: + type: string + description: Name of the team + apiKey: + type: string + description: API key for the team + isDefault: + type: boolean + description: Whether the team is the default team + TeamUser: + required: + - id + - email + properties: + id: + type: string + format: uuid + description: Identifier of the user + email: + type: string + description: Email 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 + EnvVars: + additionalProperties: + type: string + description: Environment variables for the sandbox + Mcp: + type: object + description: MCP configuration for the sandbox + additionalProperties: {} + nullable: true + 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 CIDR blocks or IP addresses for egress traffic. Allowed addresses always take precedence over blocked addresses. + items: + type: string + denyOut: + type: array + description: List of denied CIDR blocks or IP addresses for egress traffic + items: + type: string + maskRequestHost: + type: string + description: Specify host mask which will be used for all sandbox requests + SandboxLog: + description: Log entry with timestamp and line + required: + - timestamp + - line + properties: + timestamp: + type: string + format: date-time + description: Timestamp of the log entry + line: + type: string + description: Log line content + SandboxLogEntry: + required: + - timestamp + - level + - message + - fields + properties: + 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 + SandboxLogs: + required: + - logs + - logEntries + properties: + logs: + description: Logs of the sandbox + type: array + items: + $ref: '#/components/schemas/SandboxLog' + logEntries: + description: Structured logs of the sandbox + type: array + items: + $ref: '#/components/schemas/SandboxLogEntry' + SandboxMetric: + description: Metric entry with timestamp and line + required: + - timestamp + - timestampUnix + - cpuCount + - cpuUsedPct + - memUsed + - memTotal + - diskUsed + - diskTotal + properties: + timestamp: + type: string + format: date-time + deprecated: true + description: Timestamp of the metric entry + 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 + 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 + - clientID + - 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 + clientID: + type: string + deprecated: true + description: Identifier of the client + envdVersion: + $ref: '#/components/schemas/EnvdVersion' + envdAccessToken: + type: string + description: Access token used for envd communication + trafficAccessToken: + type: string + nullable: true + description: Token required for accessing sandbox via proxy. + domain: + type: string + nullable: true + description: Base domain where the sandbox traffic is accessible + SandboxDetail: + required: + - templateID + - sandboxID + - clientID + - 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 + clientID: + type: string + deprecated: true + description: Identifier of the client + 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' + envdAccessToken: + type: string + description: Access token used for envd communication + 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' + ListedSandbox: + required: + - templateID + - sandboxID + - clientID + - 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 + clientID: + type: string + deprecated: true + description: Identifier of the client + 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 + 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' + mcp: + $ref: '#/components/schemas/Mcp' + ResumedSandbox: + properties: + timeout: + type: integer + format: int32 + minimum: 0 + default: 15 + description: Time to live for the sandbox in seconds. + autoPause: + type: boolean + deprecated: true + description: Automatically pauses the sandbox after the timeout + 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 + TeamMetric: + description: Team metric with timestamp + required: + - timestamp + - timestampUnix + - concurrentSandboxes + - sandboxStartRate + properties: + timestamp: + type: string + format: date-time + deprecated: true + description: Timestamp of the metric entry + 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: + - timestamp + - timestampUnix + - value + properties: + timestamp: + type: string + format: date-time + deprecated: true + description: Timestamp of the metric entry + 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 + AdminSandboxKillResult: + required: + - killedCount + - failedCount + properties: + killedCount: + type: integer + description: Number of sandboxes successfully killed + failedCount: + type: integer + description: Number of sandboxes that failed to kill + Template: + required: + - templateID + - buildID + - cpuCount + - memoryMB + - diskSizeMB + - public + - createdAt + - updatedAt + - createdBy + - lastSpawnedAt + - spawnCount + - buildCount + - envdVersion + - aliases + - 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 + aliases: + type: array + description: Aliases of the template + deprecated: true + items: + type: string + 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 + - aliases + - 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 + aliases: + type: array + description: Aliases of the template + deprecated: true + items: + type: string + TemplateLegacy: + required: + - templateID + - buildID + - cpuCount + - memoryMB + - diskSizeMB + - public + - createdAt + - updatedAt + - createdBy + - lastSpawnedAt + - spawnCount + - buildCount + - envdVersion + - aliases + 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 + aliases: + type: array + description: Aliases of the template + 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' + 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 + - aliases + - 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 + aliases: + type: array + description: Aliases of the template + deprecated: true + items: + type: string + 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 + TemplateBuildRequest: + required: + - dockerfile + properties: + alias: + description: Alias of the template + type: string + dockerfile: + description: Dockerfile for the template + type: string + teamID: + type: string + description: Identifier of the team + 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 + cpuCount: + $ref: '#/components/schemas/CPUCount' + memoryMB: + $ref: '#/components/schemas/MemoryMB' + 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 + tags: + type: array + description: Tags to assign to the template build + items: + type: string + alias: + description: Alias of the template. Deprecated, use name instead. + type: string + deprecated: true + teamID: + deprecated: true + type: string + description: Identifier of the team + cpuCount: + $ref: '#/components/schemas/CPUCount' + memoryMB: + $ref: '#/components/schemas/MemoryMB' + TemplateBuildRequestV2: + required: + - alias + properties: + alias: + description: Alias of the template + type: string + teamID: + deprecated: true + type: string + description: Identifier of the team + 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: + 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' + LogsDirection: + type: string + description: Direction of the logs that should be returned + enum: + - forward + - backward + x-enum-varnames: + - LogsDirectionForward + - LogsDirectionBackward + LogsSource: + type: string + description: Source of the logs that should be returned + enum: + - temporary + - persistent + x-enum-varnames: + - LogsSourceTemporary + - LogsSourcePersistent + NodeStatus: + type: string + description: Status of the node + enum: + - ready + - draining + - connecting + - unhealthy + x-enum-varnames: + - NodeStatusReady + - NodeStatusDraining + - NodeStatusConnecting + - NodeStatusUnhealthy + NodeStatusChange: + required: + - status + properties: + clusterID: + type: string + format: uuid + description: Identifier of the cluster + status: + $ref: '#/components/schemas/NodeStatus' + DiskMetrics: + required: + - mountPoint + - device + - filesystemType + - usedBytes + - totalBytes + properties: + mountPoint: + type: string + description: Mount point of the disk + device: + type: string + description: Device name + filesystemType: + type: string + description: Filesystem type (e.g., ext4, xfs) + usedBytes: + type: integer + format: uint64 + description: Used space in bytes + totalBytes: + type: integer + format: uint64 + description: Total space in bytes + NodeMetrics: + description: Node metrics + required: + - allocatedCPU + - allocatedMemoryBytes + - cpuPercent + - memoryUsedBytes + - cpuCount + - memoryTotalBytes + - disks + properties: + allocatedCPU: + type: integer + format: uint32 + description: Number of allocated CPU cores + cpuPercent: + type: integer + format: uint32 + description: Node CPU usage percentage + cpuCount: + type: integer + format: uint32 + description: Total number of CPU cores on the node + allocatedMemoryBytes: + type: integer + format: uint64 + description: Amount of allocated memory in bytes + memoryUsedBytes: + type: integer + format: uint64 + description: Node memory used in bytes + memoryTotalBytes: + type: integer + format: uint64 + description: Total node memory in bytes + disks: + type: array + description: Detailed metrics for each disk/mount point + items: + $ref: '#/components/schemas/DiskMetrics' + MachineInfo: + required: + - cpuFamily + - cpuModel + - cpuModelName + - cpuArchitecture + properties: + cpuFamily: + type: string + description: CPU family of the node + cpuModel: + type: string + description: CPU model of the node + cpuModelName: + type: string + description: CPU model name of the node + cpuArchitecture: + type: string + description: CPU architecture of the node + Node: + required: + - nodeID + - id + - serviceInstanceID + - clusterID + - status + - sandboxCount + - metrics + - createSuccesses + - createFails + - sandboxStartingCount + - version + - commit + - machineInfo + properties: + version: + type: string + description: Version of the orchestrator + commit: + type: string + description: Commit of the orchestrator + nodeID: + type: string + deprecated: true + description: Identifier of the nomad node + id: + type: string + description: Identifier of the node + serviceInstanceID: + type: string + description: Service instance identifier of the node + clusterID: + type: string + description: Identifier of the cluster + machineInfo: + $ref: '#/components/schemas/MachineInfo' + status: + $ref: '#/components/schemas/NodeStatus' + sandboxCount: + type: integer + format: uint32 + description: Number of sandboxes running on the node + metrics: + $ref: '#/components/schemas/NodeMetrics' + createSuccesses: + type: integer + format: uint64 + description: Number of sandbox create successes + createFails: + type: integer + format: uint64 + description: Number of sandbox create fails + sandboxStartingCount: + type: integer + format: int + description: Number of starting Sandboxes + NodeDetail: + required: + - nodeID + - id + - serviceInstanceID + - clusterID + - status + - sandboxes + - cachedBuilds + - createSuccesses + - createFails + - version + - commit + - metrics + - machineInfo + properties: + clusterID: + type: string + description: Identifier of the cluster + version: + type: string + description: Version of the orchestrator + commit: + type: string + description: Commit of the orchestrator + id: + type: string + description: Identifier of the node + serviceInstanceID: + type: string + description: Service instance identifier of the node + nodeID: + type: string + deprecated: true + description: Identifier of the nomad node + machineInfo: + $ref: '#/components/schemas/MachineInfo' + status: + $ref: '#/components/schemas/NodeStatus' + sandboxes: + type: array + description: List of sandboxes running on the node + items: + $ref: '#/components/schemas/ListedSandbox' + metrics: + $ref: '#/components/schemas/NodeMetrics' + cachedBuilds: + type: array + description: List of cached builds id on the node + items: + type: string + createSuccesses: + type: integer + format: uint64 + description: Number of sandbox create successes + createFails: + type: integer + format: uint64 + description: Number of sandbox create fails + CreatedAccessToken: + required: + - id + - name + - token + - mask + - createdAt + properties: + id: + type: string + format: uuid + description: Identifier of the access token + name: + type: string + description: Name of the access token + token: + type: string + description: The fully created access token + mask: + $ref: '#/components/schemas/IdentifierMaskingDetails' + createdAt: + type: string + format: date-time + description: Timestamp of access token creation + NewAccessToken: + required: + - name + properties: + name: + type: string + description: Name of the access token + TeamAPIKey: + required: + - id + - name + - mask + - createdAt + properties: + id: + type: string + format: uuid + description: Identifier of the API key + name: + type: string + description: Name of the API key + mask: + $ref: '#/components/schemas/IdentifierMaskingDetails' + createdAt: + type: string + format: date-time + description: Timestamp of API key creation + createdBy: + allOf: + - $ref: '#/components/schemas/TeamUser' + nullable: true + lastUsed: + type: string + format: date-time + description: Last time this API key was used + nullable: true + CreatedTeamAPIKey: + required: + - id + - key + - mask + - name + - createdAt + properties: + id: + type: string + format: uuid + description: Identifier of the API key + key: + type: string + description: Raw value of the API key + mask: + $ref: '#/components/schemas/IdentifierMaskingDetails' + name: + type: string + description: Name of the API key + createdAt: + type: string + format: date-time + description: Timestamp of API key creation + createdBy: + allOf: + - $ref: '#/components/schemas/TeamUser' + nullable: true + lastUsed: + type: string + format: date-time + description: Last time this API key was used + nullable: true + NewTeamAPIKey: + required: + - name + properties: + name: + type: string + description: Name of the API key + UpdateTeamAPIKey: + required: + - name + properties: + name: + type: string + description: New name for the API key + 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 + 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 + IdentifierMaskingDetails: + required: + - prefix + - valueLength + - maskedValuePrefix + - maskedValueSuffix + properties: + prefix: + type: string + description: Prefix that identifies the token or key type + valueLength: + type: integer + description: Length of the token or key + maskedValuePrefix: + type: string + description: Prefix used in masked version of the token or key + maskedValueSuffix: + type: string + description: Suffix used in masked version of the token or key +tags: + - name: templates + - name: sandboxes + - name: auth + - name: access-tokens + - name: api-keys + - name: tags +paths: + /health: + get: + description: Health check + responses: + '200': + description: Request was successful + '401': + $ref: '#/components/responses/401' + /teams/{teamID}/metrics: + get: + description: Get metrics for the team + tags: + - auth + security: + - ApiKeyAuth: [] + 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' + /teams/{teamID}/metrics/max: + get: + description: Get the maximum metrics for the team in the given interval + tags: + - auth + security: + - ApiKeyAuth: [] + 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' + /sandboxes: + get: + description: List all running sandboxes + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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 + responses: + '200': + description: Successfully returned all running sandboxes + content: + application/json: + schema: + type: array + items: + allOf: + - $ref: '#/components/schemas/ListedSandbox' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '500': + $ref: '#/components/responses/500' + post: + description: Create a sandbox from the template + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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' + /v2/sandboxes: + get: + description: List all sandboxes + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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 + content: + application/json: + schema: + type: array + items: + allOf: + - $ref: '#/components/schemas/ListedSandbox' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '500': + $ref: '#/components/responses/500' + /sandboxes/metrics: + get: + description: List metrics for given sandboxes + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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' + /sandboxes/{sandboxID}/logs: + get: + description: Get sandbox logs + tags: + - sandboxes + security: + - ApiKeyAuth: [] + parameters: + - $ref: '#/components/parameters/sandboxID' + - in: query + name: start + 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 + format: int32 + minimum: 0 + type: integer + description: Maximum number of logs that should be returned + responses: + '200': + description: Successfully returned the sandbox logs + content: + application/json: + schema: + $ref: '#/components/schemas/SandboxLogs' + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + '500': + $ref: '#/components/responses/500' + /sandboxes/{sandboxID}: + get: + description: Get a sandbox by id + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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' + delete: + description: Kill a sandbox + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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' + /sandboxes/{sandboxID}/metrics: + get: + description: Get sandbox metrics + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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' + /sandboxes/{sandboxID}/pause: + post: + description: Pause the sandbox + tags: + - sandboxes + security: + - ApiKeyAuth: [] + parameters: + - $ref: '#/components/parameters/sandboxID' + 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' + /sandboxes/{sandboxID}/resume: + post: + deprecated: true + description: Resume the sandbox + tags: + - sandboxes + security: + - ApiKeyAuth: [] + parameters: + - $ref: '#/components/parameters/sandboxID' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ResumedSandbox' + responses: + '201': + description: The sandbox was resumed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Sandbox' + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + '409': + $ref: '#/components/responses/409' + '500': + $ref: '#/components/responses/500' + /sandboxes/{sandboxID}/connect: + post: + description: Returns sandbox details. If the sandbox is paused, it will be resumed. TTL is only extended. + tags: + - sandboxes + security: + - ApiKeyAuth: [] + 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' + /sandboxes/{sandboxID}/timeout: + post: + 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. + security: + - ApiKeyAuth: [] + tags: + - sandboxes + requestBody: + content: + application/json: + schema: + 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 + 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' + /sandboxes/{sandboxID}/refreshes: + post: + description: Refresh the sandbox extending its time to live + security: + - ApiKeyAuth: [] + tags: + - sandboxes + requestBody: + content: + application/json: + schema: + type: object + properties: + duration: + description: Duration for which the sandbox should be kept alive in seconds + type: integer + maximum: 3600 + minimum: 0 + parameters: + - $ref: '#/components/parameters/sandboxID' + responses: + '204': + description: Successfully refreshed the sandbox + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + /v3/templates: + post: + description: Create a new template + tags: + - templates + security: + - ApiKeyAuth: [] + 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' + '500': + $ref: '#/components/responses/500' + /v2/templates: + post: + description: Create a new template + deprecated: true + tags: + - templates + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TemplateBuildRequestV2' + responses: + '202': + description: The build was requested successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TemplateLegacy' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '500': + $ref: '#/components/responses/500' + /templates/{templateID}/files/{hash}: + get: + description: Get an upload link for a tar file containing build layer files + tags: + - templates + security: + - ApiKeyAuth: [] + 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' + /templates: + get: + description: List all templates + tags: + - templates + security: + - ApiKeyAuth: [] + parameters: + - in: query + required: false + name: teamID + schema: + type: string + description: Identifier of the team + responses: + '200': + description: Successfully returned all templates + content: + application/json: + schema: + type: array + items: + allOf: + - $ref: '#/components/schemas/Template' + '401': + $ref: '#/components/responses/401' + '500': + $ref: '#/components/responses/500' + /templates/{templateID}: + get: + description: List all builds for a template + tags: + - templates + security: + - ApiKeyAuth: [] + parameters: + - $ref: '#/components/parameters/templateID' + - $ref: '#/components/parameters/paginationNextToken' + - $ref: '#/components/parameters/paginationLimit' + responses: + '200': + description: Successfully returned the template with its builds + content: + application/json: + schema: + $ref: '#/components/schemas/TemplateWithBuilds' + '401': + $ref: '#/components/responses/401' + '500': + $ref: '#/components/responses/500' + delete: + description: Delete a template + tags: + - templates + security: + - ApiKeyAuth: [] + parameters: + - $ref: '#/components/parameters/templateID' + responses: + '204': + description: The template was deleted successfully + '401': + $ref: '#/components/responses/401' + '500': + $ref: '#/components/responses/500' + patch: + description: Update template + deprecated: true + tags: + - templates + security: + - ApiKeyAuth: [] + parameters: + - $ref: '#/components/parameters/templateID' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TemplateUpdateRequest' + responses: + '200': + description: The template was updated successfully + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '500': + $ref: '#/components/responses/500' + /v2/templates/{templateID}/builds/{buildID}: + post: + description: Start the build + tags: + - templates + security: + - ApiKeyAuth: [] + 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' + /v2/templates/{templateID}: + patch: + description: Update template + tags: + - templates + security: + - ApiKeyAuth: [] + 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' + /templates/{templateID}/builds/{buildID}/status: + get: + description: Get template build info + tags: + - templates + security: + - ApiKeyAuth: [] + 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' + /templates/{templateID}/builds/{buildID}/logs: + get: + description: Get template build logs + tags: + - templates + security: + - ApiKeyAuth: [] + parameters: + - $ref: '#/components/parameters/templateID' + - $ref: '#/components/parameters/buildID' + - 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' + /templates/tags: + post: + description: Assign tag(s) to a template build + tags: + - tags + security: + - ApiKeyAuth: [] + 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' + delete: + description: Delete multiple tags from templates + tags: + - tags + security: + - ApiKeyAuth: [] + 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' + /templates/aliases/{alias}: + get: + description: Check if template with given alias exists + tags: + - templates + security: + - ApiKeyAuth: [] + 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' diff --git a/openapi-sandbox.yml b/openapi-sandbox.yml new file mode 100644 index 0000000..3ed7e1f --- /dev/null +++ b/openapi-sandbox.yml @@ -0,0 +1,1683 @@ +openapi: 3.0.0 +info: + title: E2B Sandbox API + version: 0.1.1 + description: | + API for interacting with files and processes inside E2B sandboxes. + + ## Authentication + All endpoints require the `X-Access-Token` header with the access token received when creating a sandbox. + + ## Base URL + ``` + https://{sandboxID}.e2b.app + ``` + + ## Getting the Access Token + 1. Create a sandbox via REST API: `POST https://api.e2b.app/sandboxes` + 2. Response includes `sandboxID` and `envdAccessToken` + 3. Use `envdAccessToken` as `X-Access-Token` header for all Sandbox API calls +tags: + - name: files + - name: filesystem.Filesystem + - name: process.Process +paths: + /health: + get: + summary: Check the health of the service + responses: + '204': + description: The service is healthy + /metrics: + get: + summary: Get the stats of the service + security: + - AccessTokenAuth: [] + - {} + responses: + '200': + description: The resource usage metrics of the service + content: + application/json: + schema: + $ref: '#/components/schemas/Metrics' + /init: + post: + summary: Set initial vars, ensure the time and metadata is synced with the host + security: + - AccessTokenAuth: [] + - {} + requestBody: + content: + application/json: + schema: + type: object + properties: + hyperloopIP: + type: string + description: IP address of the hyperloop server to connect to + envVars: + $ref: '#/components/schemas/EnvVars' + accessToken: + type: string + description: Access token for secure access to envd service + x-go-type: SecureToken + timestamp: + type: string + format: date-time + description: The current timestamp in RFC3339 format + defaultUser: + type: string + description: The default user to use for operations + defaultWorkdir: + type: string + description: The default working directory to use for operations + responses: + '204': + description: Env vars set, the time and metadata is synced with the host + /envs: + get: + summary: Get the environment variables + security: + - AccessTokenAuth: [] + - {} + responses: + '200': + description: Environment variables + content: + application/json: + schema: + $ref: '#/components/schemas/EnvVars' + /files: + get: + summary: Download a file + tags: + - files + security: + - AccessTokenAuth: [] + - {} + parameters: + - $ref: '#/components/parameters/FilePath' + - $ref: '#/components/parameters/User' + - $ref: '#/components/parameters/Signature' + - $ref: '#/components/parameters/SignatureExpiration' + responses: + '200': + $ref: '#/components/responses/DownloadSuccess' + '400': + $ref: '#/components/responses/InvalidPath' + '401': + $ref: '#/components/responses/InvalidUser' + '404': + $ref: '#/components/responses/FileNotFound' + '500': + $ref: '#/components/responses/InternalServerError' + post: + summary: Upload a file and ensure the parent directories exist. If the file exists, it will be overwritten. + tags: + - files + security: + - AccessTokenAuth: [] + - {} + parameters: + - $ref: '#/components/parameters/FilePath' + - $ref: '#/components/parameters/User' + - $ref: '#/components/parameters/Signature' + - $ref: '#/components/parameters/SignatureExpiration' + requestBody: + $ref: '#/components/requestBodies/File' + responses: + '200': + $ref: '#/components/responses/UploadSuccess' + '400': + $ref: '#/components/responses/InvalidPath' + '401': + $ref: '#/components/responses/InvalidUser' + '500': + $ref: '#/components/responses/InternalServerError' + '507': + $ref: '#/components/responses/NotEnoughDiskSpace' + /filesystem.Filesystem/CreateWatcher: + post: + tags: + - filesystem.Filesystem + summary: CreateWatcher + description: Non-streaming versions of WatchDir + operationId: filesystem.Filesystem.CreateWatcher + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.CreateWatcherRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.CreateWatcherResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/GetWatcherEvents: + post: + tags: + - filesystem.Filesystem + summary: GetWatcherEvents + operationId: filesystem.Filesystem.GetWatcherEvents + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.GetWatcherEventsRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.GetWatcherEventsResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/ListDir: + post: + tags: + - filesystem.Filesystem + summary: ListDir + operationId: filesystem.Filesystem.ListDir + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.ListDirRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.ListDirResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/MakeDir: + post: + tags: + - filesystem.Filesystem + summary: MakeDir + operationId: filesystem.Filesystem.MakeDir + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MakeDirRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MakeDirResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/Move: + post: + tags: + - filesystem.Filesystem + summary: Move + operationId: filesystem.Filesystem.Move + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MoveRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MoveResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/Remove: + post: + tags: + - filesystem.Filesystem + summary: Remove + operationId: filesystem.Filesystem.Remove + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/RemoveWatcher: + post: + tags: + - filesystem.Filesystem + summary: RemoveWatcher + operationId: filesystem.Filesystem.RemoveWatcher + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveWatcherRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveWatcherResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/Stat: + post: + tags: + - filesystem.Filesystem + summary: Stat + operationId: filesystem.Filesystem.Stat + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.StatRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.StatResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/WatchDir: + post: + tags: + - filesystem.Filesystem + summary: WatchDir + operationId: filesystem.Filesystem.WatchDir + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/Connect: + post: + tags: + - process.Process + summary: Connect + operationId: process.Process.Connect + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/List: + post: + tags: + - process.Process + summary: List + operationId: process.Process.List + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.ListRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.ListResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /process.Process/SendInput: + post: + tags: + - process.Process + summary: SendInput + operationId: process.Process.SendInput + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendInputRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendInputResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /process.Process/SendSignal: + post: + tags: + - process.Process + summary: SendSignal + operationId: process.Process.SendSignal + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendSignalRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendSignalResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /process.Process/Start: + post: + tags: + - process.Process + summary: Start + operationId: process.Process.Start + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StartRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StartResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/StreamInput: + post: + tags: + - process.Process + summary: StreamInput + description: Client input stream ensures ordering of messages + operationId: process.Process.StreamInput + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/Update: + post: + tags: + - process.Process + summary: Update + operationId: process.Process.Update + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.UpdateRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.UpdateResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' +components: + securitySchemes: + AccessTokenAuth: + type: apiKey + in: header + name: X-Access-Token + description: Access token received when creating a sandbox + parameters: + FilePath: + name: path + in: query + required: false + description: Path to the file, URL encoded. Can be relative to user's home directory. + schema: + type: string + User: + name: username + in: query + required: false + description: User used for setting the owner, or resolving relative paths. + schema: + type: string + Signature: + name: signature + in: query + required: false + description: Signature used for file access permission verification. + schema: + type: string + SignatureExpiration: + name: signature_expiration + in: query + required: false + description: Signature expiration used for defining the expiration time of the signature. + schema: + type: integer + requestBodies: + File: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + UploadSuccess: + description: The file was uploaded successfully. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/EntryInfo' + DownloadSuccess: + description: Entire file downloaded successfully. + content: + application/octet-stream: + schema: + type: string + format: binary + description: The file content + InvalidPath: + description: Invalid path + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + InternalServerError: + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + FileNotFound: + description: File not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + InvalidUser: + description: Invalid user + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + NotEnoughDiskSpace: + description: Not enough disk space + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + schemas: + Error: + required: + - message + - code + properties: + message: + type: string + description: Error message + code: + type: integer + description: Error code + EntryInfo: + required: + - path + - name + - type + properties: + path: + type: string + description: Path to the file + name: + type: string + description: Name of the file + type: + type: string + description: Type of the file + enum: + - file + EnvVars: + type: object + description: Environment variables to set + additionalProperties: + type: string + Metrics: + type: object + description: Resource usage metrics + properties: + ts: + type: integer + format: int64 + description: Unix timestamp in UTC for current sandbox time + cpu_count: + type: integer + description: Number of CPU cores + cpu_used_pct: + type: number + format: float + description: CPU usage percentage + mem_total: + type: integer + description: Total virtual memory in bytes + mem_used: + type: integer + description: Used virtual memory in bytes + disk_used: + type: integer + description: Used disk space in bytes + disk_total: + type: integer + description: Total disk space in bytes + connect.error_details.Any: + type: object + properties: + type: + type: string + description: 'A URL that acts as a globally unique identifier for the type of the serialized message. For example: `type.googleapis.com/google.rpc.ErrorInfo`. This is used to determine the schema of the data in the `value` field and is the discriminator for the `debug` field.' + value: + type: string + format: binary + description: The Protobuf message, serialized as bytes and base64-encoded. The specific message type is identified by the `type` field. + debug: + oneOf: + - type: object + title: Any + additionalProperties: true + description: Detailed error information. + discriminator: + propertyName: type + title: Debug + description: Deserialized error detail payload. The 'type' field indicates the schema. This field is for easier debugging and should not be relied upon for application logic. + additionalProperties: true + description: Contains an arbitrary serialized message along with a @type that describes the type of the serialized message, with an additional debug field for ConnectRPC error details. + filesystem.CreateWatcherRequest: + type: object + properties: + path: + type: string + title: path + recursive: + type: boolean + title: recursive + title: CreateWatcherRequest + additionalProperties: false + filesystem.CreateWatcherResponse: + type: object + properties: + watcherId: + type: string + title: watcher_id + title: CreateWatcherResponse + additionalProperties: false + filesystem.EntryInfo: + type: object + properties: + name: + type: string + title: name + type: + title: type + $ref: '#/components/schemas/filesystem.FileType' + path: + type: string + title: path + size: + type: integer + title: size + format: int64 + mode: + type: integer + title: mode + permissions: + type: string + title: permissions + owner: + type: string + title: owner + group: + type: string + title: group + modifiedTime: + title: modified_time + $ref: '#/components/schemas/google.protobuf.Timestamp' + symlinkTarget: + type: string + title: symlink_target + description: If the entry is a symlink, this field contains the target of the symlink. + title: EntryInfo + additionalProperties: false + filesystem.EventType: + type: string + title: EventType + enum: + - EVENT_TYPE_UNSPECIFIED + - EVENT_TYPE_CREATE + - EVENT_TYPE_WRITE + - EVENT_TYPE_REMOVE + - EVENT_TYPE_RENAME + - EVENT_TYPE_CHMOD + filesystem.FileType: + type: string + title: FileType + enum: + - FILE_TYPE_UNSPECIFIED + - FILE_TYPE_FILE + - FILE_TYPE_DIRECTORY + filesystem.FilesystemEvent: + type: object + properties: + name: + type: string + title: name + type: + title: type + $ref: '#/components/schemas/filesystem.EventType' + title: FilesystemEvent + additionalProperties: false + filesystem.GetWatcherEventsRequest: + type: object + properties: + watcherId: + type: string + title: watcher_id + title: GetWatcherEventsRequest + additionalProperties: false + filesystem.GetWatcherEventsResponse: + type: object + properties: + events: + type: array + items: + $ref: '#/components/schemas/filesystem.FilesystemEvent' + title: events + title: GetWatcherEventsResponse + additionalProperties: false + filesystem.ListDirRequest: + type: object + properties: + path: + type: string + title: path + depth: + type: integer + title: depth + title: ListDirRequest + additionalProperties: false + filesystem.ListDirResponse: + type: object + properties: + entries: + type: array + items: + $ref: '#/components/schemas/filesystem.EntryInfo' + title: entries + title: ListDirResponse + additionalProperties: false + filesystem.MakeDirRequest: + type: object + properties: + path: + type: string + title: path + title: MakeDirRequest + additionalProperties: false + filesystem.MakeDirResponse: + type: object + properties: + entry: + title: entry + $ref: '#/components/schemas/filesystem.EntryInfo' + title: MakeDirResponse + additionalProperties: false + filesystem.MoveRequest: + type: object + properties: + source: + type: string + title: source + destination: + type: string + title: destination + title: MoveRequest + additionalProperties: false + filesystem.MoveResponse: + type: object + properties: + entry: + title: entry + $ref: '#/components/schemas/filesystem.EntryInfo' + title: MoveResponse + additionalProperties: false + filesystem.RemoveRequest: + type: object + properties: + path: + type: string + title: path + title: RemoveRequest + additionalProperties: false + filesystem.RemoveResponse: + type: object + title: RemoveResponse + additionalProperties: false + filesystem.RemoveWatcherRequest: + type: object + properties: + watcherId: + type: string + title: watcher_id + title: RemoveWatcherRequest + additionalProperties: false + filesystem.RemoveWatcherResponse: + type: object + title: RemoveWatcherResponse + additionalProperties: false + filesystem.StatRequest: + type: object + properties: + path: + type: string + title: path + title: StatRequest + additionalProperties: false + filesystem.StatResponse: + type: object + properties: + entry: + title: entry + $ref: '#/components/schemas/filesystem.EntryInfo' + title: StatResponse + additionalProperties: false + filesystem.WatchDirRequest: + type: object + properties: + path: + type: string + title: path + recursive: + type: boolean + title: recursive + title: WatchDirRequest + additionalProperties: false + filesystem.WatchDirResponse: + type: object + oneOf: + - properties: + filesystem: + title: filesystem + $ref: '#/components/schemas/filesystem.FilesystemEvent' + title: filesystem + required: + - filesystem + - properties: + keepalive: + title: keepalive + $ref: '#/components/schemas/filesystem.WatchDirResponse.KeepAlive' + title: keepalive + required: + - keepalive + - properties: + start: + title: start + $ref: '#/components/schemas/filesystem.WatchDirResponse.StartEvent' + title: start + required: + - start + title: WatchDirResponse + additionalProperties: false + filesystem.WatchDirResponse.KeepAlive: + type: object + title: KeepAlive + additionalProperties: false + filesystem.WatchDirResponse.StartEvent: + type: object + title: StartEvent + additionalProperties: false + google.protobuf.Timestamp: + type: string + format: date-time + description: |- + A Timestamp represents a point in time independent of any time zone or local + calendar, encoded as a count of seconds and fractions of seconds at + nanosecond resolution. The count is relative to an epoch at UTC midnight on + January 1, 1970, in the proleptic Gregorian calendar which extends the + Gregorian calendar backwards to year one. + + All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + second table is needed for interpretation, using a [24-hour linear + smear](https://developers.google.com/time/smear). + + The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + restricting to that range, we ensure that we can convert to and from [RFC + 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + + # Examples + + Example 1: Compute Timestamp from POSIX `time()`. + + Timestamp timestamp; + timestamp.set_seconds(time(NULL)); + timestamp.set_nanos(0); + + Example 2: Compute Timestamp from POSIX `gettimeofday()`. + + struct timeval tv; + gettimeofday(&tv, NULL); + + Timestamp timestamp; + timestamp.set_seconds(tv.tv_sec); + timestamp.set_nanos(tv.tv_usec * 1000); + + Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + + // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + Timestamp timestamp; + timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + + Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + + long millis = System.currentTimeMillis(); + + Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + .setNanos((int) ((millis % 1000) * 1000000)).build(); + + Example 5: Compute Timestamp from Java `Instant.now()`. + + Instant now = Instant.now(); + + Timestamp timestamp = + Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + .setNanos(now.getNano()).build(); + + Example 6: Compute Timestamp from current time in Python. + + timestamp = Timestamp() + timestamp.GetCurrentTime() + + # JSON Mapping + + In JSON format, the Timestamp type is encoded as a string in the + [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + where {year} is always expressed using four digits while {month}, {day}, + {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + is required. A proto3 JSON serializer should always use UTC (as indicated by + "Z") when printing the Timestamp type and a proto3 JSON parser should be + able to accept both UTC and other timezones (as indicated by an offset). + + For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + 01:30 UTC on January 15, 2017. + + In JavaScript, one can convert a Date object to this format using the + standard + [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + method. In Python, a standard `datetime.datetime` object can be converted + to this format using + [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + the Joda Time's [`ISODateTimeFormat.dateTime()`]( + http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() + ) to obtain a formatter capable of generating timestamps in this format. + example: '2023-01-15T01:30:15.01Z' + process.ConnectRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + title: ConnectRequest + additionalProperties: false + process.ConnectResponse: + type: object + properties: + event: + title: event + $ref: '#/components/schemas/process.ProcessEvent' + title: ConnectResponse + additionalProperties: false + process.ListRequest: + type: object + title: ListRequest + additionalProperties: false + process.ListResponse: + type: object + properties: + processes: + type: array + items: + $ref: '#/components/schemas/process.ProcessInfo' + title: processes + title: ListResponse + additionalProperties: false + process.PTY: + type: object + properties: + size: + title: size + $ref: '#/components/schemas/process.PTY.Size' + title: PTY + additionalProperties: false + process.PTY.Size: + type: object + properties: + cols: + type: integer + title: cols + rows: + type: integer + title: rows + title: Size + additionalProperties: false + process.ProcessConfig: + type: object + properties: + cmd: + type: string + title: cmd + args: + type: array + items: + type: string + title: args + envs: + type: object + title: envs + additionalProperties: + type: string + title: value + cwd: + type: string + title: cwd + title: ProcessConfig + additionalProperties: false + process.ProcessConfig.EnvsEntry: + type: object + properties: + key: + type: string + title: key + value: + type: string + title: value + title: EnvsEntry + additionalProperties: false + process.ProcessEvent: + type: object + oneOf: + - properties: + data: + title: data + $ref: '#/components/schemas/process.ProcessEvent.DataEvent' + title: data + required: + - data + - properties: + end: + title: end + $ref: '#/components/schemas/process.ProcessEvent.EndEvent' + title: end + required: + - end + - properties: + keepalive: + title: keepalive + $ref: '#/components/schemas/process.ProcessEvent.KeepAlive' + title: keepalive + required: + - keepalive + - properties: + start: + title: start + $ref: '#/components/schemas/process.ProcessEvent.StartEvent' + title: start + required: + - start + title: ProcessEvent + additionalProperties: false + process.ProcessEvent.DataEvent: + type: object + oneOf: + - properties: + pty: + type: string + title: pty + format: byte + title: pty + required: + - pty + - properties: + stderr: + type: string + title: stderr + format: byte + title: stderr + required: + - stderr + - properties: + stdout: + type: string + title: stdout + format: byte + title: stdout + required: + - stdout + title: DataEvent + additionalProperties: false + process.ProcessEvent.EndEvent: + type: object + properties: + exitCode: + type: integer + title: exit_code + format: int32 + exited: + type: boolean + title: exited + status: + type: string + title: status + error: + type: string + title: error + title: EndEvent + additionalProperties: false + process.ProcessEvent.KeepAlive: + type: object + title: KeepAlive + additionalProperties: false + process.ProcessEvent.StartEvent: + type: object + properties: + pid: + type: integer + title: pid + title: StartEvent + additionalProperties: false + process.ProcessInfo: + type: object + properties: + config: + title: config + $ref: '#/components/schemas/process.ProcessConfig' + pid: + type: integer + title: pid + tag: + type: string + title: tag + title: ProcessInfo + additionalProperties: false + process.ProcessInput: + type: object + oneOf: + - properties: + pty: + type: string + title: pty + format: byte + title: pty + required: + - pty + - properties: + stdin: + type: string + title: stdin + format: byte + title: stdin + required: + - stdin + title: ProcessInput + additionalProperties: false + process.ProcessSelector: + type: object + oneOf: + - properties: + pid: + type: integer + title: pid + title: pid + required: + - pid + - properties: + tag: + type: string + title: tag + title: tag + required: + - tag + title: ProcessSelector + additionalProperties: false + process.SendInputRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + input: + title: input + $ref: '#/components/schemas/process.ProcessInput' + title: SendInputRequest + additionalProperties: false + process.SendInputResponse: + type: object + title: SendInputResponse + additionalProperties: false + process.SendSignalRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + signal: + title: signal + $ref: '#/components/schemas/process.Signal' + title: SendSignalRequest + additionalProperties: false + process.SendSignalResponse: + type: object + title: SendSignalResponse + additionalProperties: false + process.Signal: + type: string + title: Signal + enum: + - SIGNAL_UNSPECIFIED + - SIGNAL_SIGTERM + - SIGNAL_SIGKILL + process.StartRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessConfig' + pty: + title: pty + nullable: true + $ref: '#/components/schemas/process.PTY' + tag: + type: string + title: tag + stdin: + type: boolean + title: stdin + description: |- + This is optional for backwards compatibility. + We default to true. New SDK versions will set this to false by default. + title: StartRequest + additionalProperties: false + process.StartResponse: + type: object + properties: + event: + title: event + $ref: '#/components/schemas/process.ProcessEvent' + title: StartResponse + additionalProperties: false + process.StreamInputRequest: + type: object + oneOf: + - properties: + data: + title: data + $ref: '#/components/schemas/process.StreamInputRequest.DataEvent' + title: data + required: + - data + - properties: + keepalive: + title: keepalive + $ref: '#/components/schemas/process.StreamInputRequest.KeepAlive' + title: keepalive + required: + - keepalive + - properties: + start: + title: start + $ref: '#/components/schemas/process.StreamInputRequest.StartEvent' + title: start + required: + - start + title: StreamInputRequest + additionalProperties: false + process.StreamInputRequest.DataEvent: + type: object + properties: + input: + title: input + $ref: '#/components/schemas/process.ProcessInput' + title: DataEvent + additionalProperties: false + process.StreamInputRequest.KeepAlive: + type: object + title: KeepAlive + additionalProperties: false + process.StreamInputRequest.StartEvent: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + title: StartEvent + additionalProperties: false + process.StreamInputResponse: + type: object + title: StreamInputResponse + additionalProperties: false + process.UpdateRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + pty: + title: pty + nullable: true + $ref: '#/components/schemas/process.PTY' + title: UpdateRequest + additionalProperties: false + process.UpdateResponse: + type: object + title: UpdateResponse + additionalProperties: false diff --git a/package.json b/package.json new file mode 100644 index 0000000..1cdb7ee --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "e2b-docs", + "version": "1.0.0", + "private": true, + "description": "E2B Documentation", + "scripts": { + "sync-openapi": "node scripts/sync-openapi.js" + }, + "dependencies": { + "js-yaml": "^4.1.0" + } +} diff --git a/scripts/sync-openapi.js b/scripts/sync-openapi.js new file mode 100644 index 0000000..217b272 --- /dev/null +++ b/scripts/sync-openapi.js @@ -0,0 +1,484 @@ +#!/usr/bin/env node + +/** + * OpenAPI Spec Sync Script + * + * Fetches OpenAPI specs from e2b-dev/infra repository, transforms them + * for public documentation, and saves them to the docs repo. + * + * Usage: node scripts/sync-openapi.js + */ + +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +// Try to load js-yaml, install if not available +let yaml; +try { + yaml = require('js-yaml'); +} catch (e) { + console.log('Installing js-yaml...'); + execSync('npm install js-yaml', { stdio: 'inherit' }); + yaml = require('js-yaml'); +} + +const INFRA_RAW_BASE = 'https://raw.githubusercontent.com/e2b-dev/infra/main'; + +// === CONFIGURATION === + +const REST_API_CONFIG = { + source: `${INFRA_RAW_BASE}/spec/openapi.yml`, + output: 'openapi-public.yml', + excludePaths: [ + '/access-tokens', + '/access-tokens/{accessTokenID}', + '/admin/teams/{teamID}/sandboxes/kill', + '/api-keys', + '/api-keys/{apiKeyID}', + '/nodes', + '/nodes/{nodeID}', + '/teams', + ], + // Security schemes to remove from endpoints (keep only ApiKeyAuth) + removeSecuritySchemes: [ + 'Supabase1TokenAuth', + 'Supabase2TeamAuth', + 'AccessTokenAuth', + 'AdminTokenAuth', + ], + info: { + title: 'E2B REST API', + description: `REST API for managing E2B sandboxes and templates. + +## Authentication +All endpoints require authentication via API key passed in the \`X-API-Key\` header. +Get your API key from the [E2B Dashboard](https://e2b.dev/dashboard?tab=keys). + +## Base URL +\`\`\` +https://api.e2b.app +\`\`\` +` + } +}; + +const SANDBOX_API_CONFIG = { + envdSource: `${INFRA_RAW_BASE}/packages/envd/spec/envd.yaml`, + filesystemProto: `${INFRA_RAW_BASE}/packages/envd/spec/filesystem/filesystem.proto`, + processProto: `${INFRA_RAW_BASE}/packages/envd/spec/process/process.proto`, + output: 'openapi-sandbox.yml', + info: { + title: 'E2B Sandbox API', + description: `API for interacting with files and processes inside E2B sandboxes. + +## Authentication +All endpoints require the \`X-Access-Token\` header with the access token received when creating a sandbox. + +## Base URL +\`\`\` +https://{sandboxID}.e2b.app +\`\`\` + +## Getting the Access Token +1. Create a sandbox via REST API: \`POST https://api.e2b.app/sandboxes\` +2. Response includes \`sandboxID\` and \`envdAccessToken\` +3. Use \`envdAccessToken\` as \`X-Access-Token\` header for all Sandbox API calls +` + }, + // Connect RPC schemas to remove (protocol-level, not user-facing) + removeSchemas: [ + 'connect-protocol-version', + 'connect-timeout-header', + 'connect.error' + ], + // Connect headers to remove from endpoint parameters + removeHeaders: [ + 'Connect-Protocol-Version', + 'Connect-Timeout-Ms' + ] +}; + +// === UTILITY FUNCTIONS === + +async function fetchYaml(url) { + console.log(`Fetching: ${url}`); + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch ${url}: ${response.status}`); + } + const text = await response.text(); + return yaml.load(text); +} + +async function fetchText(url) { + console.log(`Fetching: ${url}`); + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to fetch ${url}: ${response.status}`); + } + return response.text(); +} + +function saveYaml(filename, data) { + const outputPath = path.join(process.cwd(), filename); + fs.writeFileSync(outputPath, yaml.dump(data, { lineWidth: -1, noRefs: true })); + console.log(`Saved: ${outputPath}`); +} + +// === REST API SPEC GENERATION === + +async function generateRestApiSpec() { + console.log('\n=== Generating REST API Spec ===\n'); + + const spec = await fetchYaml(REST_API_CONFIG.source); + + // Filter out excluded paths AND endpoints that only use Supabase tokens + const filteredPaths = {}; + for (const [path, methods] of Object.entries(spec.paths || {})) { + // Skip explicitly excluded paths + if (REST_API_CONFIG.excludePaths.includes(path)) { + continue; + } + + // Check each method in this path + const filteredMethods = {}; + for (const [method, operation] of Object.entries(methods)) { + // Skip non-operation properties like 'parameters' + if (!operation.security && !operation.responses) { + filteredMethods[method] = operation; + continue; + } + + // Check if this endpoint has ApiKeyAuth + const hasApiKeyAuth = operation.security?.some(secObj => + Object.keys(secObj).includes('ApiKeyAuth') + ); + + // Keep endpoint only if it has ApiKeyAuth (or no security = public) + if (hasApiKeyAuth || !operation.security) { + filteredMethods[method] = operation; + } + } + + // Only add path if it has any methods left + if (Object.keys(filteredMethods).length > 0) { + filteredPaths[path] = filteredMethods; + } + } + spec.paths = filteredPaths; + console.log(`Filtered paths: ${Object.keys(filteredPaths).length} remaining`); + + // Keep only ApiKeyAuth security scheme + if (spec.components?.securitySchemes?.ApiKeyAuth) { + spec.components.securitySchemes = { + ApiKeyAuth: spec.components.securitySchemes.ApiKeyAuth + }; + } + + // Clean up security references in endpoints - remove Supabase/AccessToken refs + for (const [path, methods] of Object.entries(spec.paths || {})) { + for (const [method, operation] of Object.entries(methods)) { + if (operation.security) { + // Filter out security schemes we don't want + operation.security = operation.security.filter(secObj => { + const schemes = Object.keys(secObj); + // Keep only if it has ApiKeyAuth or is empty (public endpoint) + return schemes.length === 0 || schemes.includes('ApiKeyAuth'); + }); + // If no security left, remove the property (makes it use global security) + if (operation.security.length === 0) { + delete operation.security; + } + } + } + } + + // Update info section + spec.info.title = REST_API_CONFIG.info.title; + spec.info.description = REST_API_CONFIG.info.description; + + saveYaml(REST_API_CONFIG.output, spec); + return spec; +} + +// === SANDBOX API SPEC GENERATION === + +async function generateSandboxApiSpec() { + console.log('\n=== Generating Sandbox API Spec ===\n'); + + // Fetch base envd.yaml + const spec = await fetchYaml(SANDBOX_API_CONFIG.envdSource); + + // Fix security scheme (scheme: header -> in: header) + if (spec.components?.securitySchemes?.AccessTokenAuth) { + spec.components.securitySchemes.AccessTokenAuth = { + type: 'apiKey', + in: 'header', + name: 'X-Access-Token', + description: 'Access token received when creating a sandbox' + }; + } + + // Update info section + spec.info.title = SANDBOX_API_CONFIG.info.title; + spec.info.description = SANDBOX_API_CONFIG.info.description; + + // Try to generate and merge proto-based specs + try { + await mergeProtoSpecs(spec); + } catch (e) { + console.warn(`Warning: Could not generate proto specs: ${e.message}`); + console.warn('Sandbox API will only include REST endpoints (/files, /health, etc.)'); + } + + // Apply fixes + applySchemaFixes(spec); + + saveYaml(SANDBOX_API_CONFIG.output, spec); + return spec; +} + +async function mergeProtoSpecs(spec) { + // Check if buf and protoc-gen-connect-openapi are available + try { + execSync('which buf', { stdio: 'pipe' }); + execSync('which protoc-gen-connect-openapi', { stdio: 'pipe' }); + } catch (e) { + throw new Error('buf or protoc-gen-connect-openapi not installed'); + } + + // Create temp directory for proto generation + const tempDir = fs.mkdtempSync(path.join(require('os').tmpdir(), 'openapi-')); + console.log(`Using temp directory: ${tempDir}`); + + try { + // Fetch proto files + const filesystemProto = await fetchText(SANDBOX_API_CONFIG.filesystemProto); + const processProto = await fetchText(SANDBOX_API_CONFIG.processProto); + + // Write proto files + fs.mkdirSync(path.join(tempDir, 'filesystem'), { recursive: true }); + fs.mkdirSync(path.join(tempDir, 'process'), { recursive: true }); + fs.writeFileSync(path.join(tempDir, 'filesystem', 'filesystem.proto'), filesystemProto); + fs.writeFileSync(path.join(tempDir, 'process', 'process.proto'), processProto); + + // Write buf.yaml + fs.writeFileSync(path.join(tempDir, 'buf.yaml'), 'version: v1\n'); + + // Write buf.gen.yaml for OpenAPI generation + const bufGenYaml = `version: v2 +plugins: + - local: protoc-gen-connect-openapi + out: . + opt: + - with-streaming +`; + fs.writeFileSync(path.join(tempDir, 'buf.gen.yaml'), bufGenYaml); + + // Run buf generate + console.log('Running buf generate...'); + execSync('buf generate', { cwd: tempDir, stdio: 'pipe' }); + + // Load generated specs + const filesystemSpecPath = path.join(tempDir, 'filesystem', 'filesystem.openapi.yaml'); + const processSpecPath = path.join(tempDir, 'process', 'process.openapi.yaml'); + + if (fs.existsSync(filesystemSpecPath)) { + const filesystemSpec = yaml.load(fs.readFileSync(filesystemSpecPath, 'utf8')); + mergeSpec(spec, filesystemSpec, '/filesystem.'); + } + + if (fs.existsSync(processSpecPath)) { + const processSpec = yaml.load(fs.readFileSync(processSpecPath, 'utf8')); + mergeSpec(spec, processSpec, '/process.'); + } + + console.log('Merged filesystem and process endpoints'); + + } finally { + // Cleanup temp directory + fs.rmSync(tempDir, { recursive: true, force: true }); + } +} + +function fixInvalidTypeArrays(schemas) { + // Recursively fix type arrays in schemas (OpenAPI 3.0 doesn't support type arrays) + for (const [name, schema] of Object.entries(schemas)) { + fixTypeArraysRecursive(schema); + } +} + +function fixTypeArraysRecursive(obj) { + if (!obj || typeof obj !== 'object') return; + + // Fix type arrays - convert to first type (usually the main type) + if (Array.isArray(obj.type)) { + // Use the first non-null type + const mainType = obj.type.find(t => t !== 'null') || obj.type[0]; + obj.type = mainType; + } + + // Fix examples -> example (OpenAPI 3.0 uses singular for schemas) + if (obj.examples && !obj.example) { + obj.example = Array.isArray(obj.examples) ? obj.examples[0] : obj.examples; + delete obj.examples; + } + + // Fix oneOf with type: 'null' -> nullable: true (OpenAPI 3.0 style) + if (Array.isArray(obj.oneOf)) { + const nullIndex = obj.oneOf.findIndex(item => item.type === 'null'); + if (nullIndex !== -1) { + // Remove the null type from oneOf + obj.oneOf.splice(nullIndex, 1); + obj.nullable = true; + // If only one item left, unwrap the oneOf + if (obj.oneOf.length === 1) { + const remaining = obj.oneOf[0]; + delete obj.oneOf; + Object.assign(obj, remaining); + } else if (obj.oneOf.length === 0) { + delete obj.oneOf; + } + } + } + + // Recurse into properties + if (obj.properties) { + for (const prop of Object.values(obj.properties)) { + fixTypeArraysRecursive(prop); + } + } + + // Recurse into items (for arrays) + if (obj.items) { + fixTypeArraysRecursive(obj.items); + } + + // Recurse into additionalProperties + if (obj.additionalProperties && typeof obj.additionalProperties === 'object') { + fixTypeArraysRecursive(obj.additionalProperties); + } + + // Recurse into allOf/oneOf/anyOf + for (const key of ['allOf', 'oneOf', 'anyOf']) { + if (Array.isArray(obj[key])) { + for (const item of obj[key]) { + fixTypeArraysRecursive(item); + } + } + } +} + +function mergeSpec(target, source, pathPrefix) { + // Merge paths + for (const [path, methods] of Object.entries(source.paths || {})) { + if (path.startsWith(pathPrefix)) { + target.paths[path] = methods; + } + } + + // Merge schemas + if (source.components?.schemas) { + target.components = target.components || {}; + target.components.schemas = target.components.schemas || {}; + Object.assign(target.components.schemas, source.components.schemas); + } + + // Merge tags + if (source.tags) { + target.tags = target.tags || []; + const existingTags = new Set(target.tags.map(t => t.name)); + for (const tag of source.tags) { + if (!existingTags.has(tag.name)) { + target.tags.push(tag); + } + } + } +} + +function applySchemaFixes(spec) { + // Remove Connect protocol schemas + if (spec.components?.schemas) { + for (const schemaName of SANDBOX_API_CONFIG.removeSchemas) { + if (spec.components.schemas[schemaName]) { + delete spec.components.schemas[schemaName]; + console.log(`Removed schema: ${schemaName}`); + } + } + + // Fix invalid type arrays (e.g., type: [integer, string] -> oneOf) + fixInvalidTypeArrays(spec.components.schemas); + } + + // Remove Connect headers from endpoint parameters + for (const [path, methods] of Object.entries(spec.paths || {})) { + for (const [method, operation] of Object.entries(methods)) { + if (operation.parameters) { + const filtered = operation.parameters.filter(p => + !SANDBOX_API_CONFIG.removeHeaders.includes(p.name) + ); + if (filtered.length !== operation.parameters.length) { + operation.parameters = filtered; + } + } + + // Replace connect.error references with standard Error + if (operation.responses) { + for (const [code, response] of Object.entries(operation.responses)) { + if (response.content?.['application/json']?.schema?.$ref === '#/components/schemas/connect.error') { + response.content['application/json'].schema.$ref = '#/components/schemas/Error'; + } + } + } + } + } +} + +// === VALIDATION === + +function validateSpec(filename) { + try { + execSync(`mintlify openapi-check ${filename}`, { stdio: 'pipe' }); + console.log(`✓ ${filename} is valid`); + return true; + } catch (e) { + const output = e.stdout?.toString() || e.stderr?.toString() || e.message; + console.error(`✗ ${filename} validation failed:\n${output}`); + return false; + } +} + +// === MAIN === + +async function main() { + console.log('OpenAPI Spec Sync Script'); + console.log('========================\n'); + + try { + // Generate REST API spec + await generateRestApiSpec(); + + // Generate Sandbox API spec + await generateSandboxApiSpec(); + + console.log('\n=== Validation ===\n'); + + // Validate if mintlify is available + try { + execSync('which mintlify', { stdio: 'pipe' }); + validateSpec(REST_API_CONFIG.output); + validateSpec(SANDBOX_API_CONFIG.output); + } catch (e) { + console.log('mintlify CLI not available, skipping validation'); + } + + console.log('\n✓ Done!\n'); + + } catch (error) { + console.error(`\n✗ Error: ${error.message}\n`); + process.exit(1); + } +} + +main(); From d28a1b08e6cf052d882606481945ff8f7b0a41c4 Mon Sep 17 00:00:00 2001 From: Tomas Beran Date: Wed, 4 Feb 2026 18:15:25 -0800 Subject: [PATCH 3/6] Remove automated sync workflow and exclude internal endpoints - Remove GitHub Actions workflow (sync will be done manually) - Exclude /init and /metrics from Sandbox API (internal SDK endpoints) --- .github/workflows/sync-openapi.yml | 61 -- openapi-sandbox.yml | 1438 ---------------------------- scripts/sync-openapi.js | 14 + 3 files changed, 14 insertions(+), 1499 deletions(-) delete mode 100644 .github/workflows/sync-openapi.yml diff --git a/.github/workflows/sync-openapi.yml b/.github/workflows/sync-openapi.yml deleted file mode 100644 index 3a705d3..0000000 --- a/.github/workflows/sync-openapi.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Sync OpenAPI Specs - -on: - # Run every 6 hours - schedule: - - cron: '0 */6 * * *' - # Allow manual trigger - workflow_dispatch: - # Re-run if sync script changes - push: - branches: [main] - paths: - - 'scripts/sync-openapi.js' - -jobs: - sync: - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Install dependencies - run: npm install - - - name: Setup buf (for proto generation) - uses: bufbuild/buf-setup-action@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install protoc-gen-connect-openapi - run: | - go install github.com/sudorandom/protoc-gen-connect-openapi@latest - echo "$HOME/go/bin" >> $GITHUB_PATH - - - name: Sync OpenAPI specs - run: node scripts/sync-openapi.js - - - name: Validate specs - run: | - npx mintlify openapi-check openapi-public.yml - npx mintlify openapi-check openapi-sandbox.yml - - - name: Commit and push changes - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add openapi-public.yml openapi-sandbox.yml - if git diff --staged --quiet; then - echo "No changes to commit" - else - git commit -m "chore: sync OpenAPI specs from infra" - git push - fi diff --git a/openapi-sandbox.yml b/openapi-sandbox.yml index 3ed7e1f..9ed976a 100644 --- a/openapi-sandbox.yml +++ b/openapi-sandbox.yml @@ -19,8 +19,6 @@ info: 3. Use `envdAccessToken` as `X-Access-Token` header for all Sandbox API calls tags: - name: files - - name: filesystem.Filesystem - - name: process.Process paths: /health: get: @@ -28,53 +26,6 @@ paths: responses: '204': description: The service is healthy - /metrics: - get: - summary: Get the stats of the service - security: - - AccessTokenAuth: [] - - {} - responses: - '200': - description: The resource usage metrics of the service - content: - application/json: - schema: - $ref: '#/components/schemas/Metrics' - /init: - post: - summary: Set initial vars, ensure the time and metadata is synced with the host - security: - - AccessTokenAuth: [] - - {} - requestBody: - content: - application/json: - schema: - type: object - properties: - hyperloopIP: - type: string - description: IP address of the hyperloop server to connect to - envVars: - $ref: '#/components/schemas/EnvVars' - accessToken: - type: string - description: Access token for secure access to envd service - x-go-type: SecureToken - timestamp: - type: string - format: date-time - description: The current timestamp in RFC3339 format - defaultUser: - type: string - description: The default user to use for operations - defaultWorkdir: - type: string - description: The default working directory to use for operations - responses: - '204': - description: Env vars set, the time and metadata is synced with the host /envs: get: summary: Get the environment variables @@ -137,676 +88,6 @@ paths: $ref: '#/components/responses/InternalServerError' '507': $ref: '#/components/responses/NotEnoughDiskSpace' - /filesystem.Filesystem/CreateWatcher: - post: - tags: - - filesystem.Filesystem - summary: CreateWatcher - description: Non-streaming versions of WatchDir - operationId: filesystem.Filesystem.CreateWatcher - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.CreateWatcherRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.CreateWatcherResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/GetWatcherEvents: - post: - tags: - - filesystem.Filesystem - summary: GetWatcherEvents - operationId: filesystem.Filesystem.GetWatcherEvents - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.GetWatcherEventsRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.GetWatcherEventsResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/ListDir: - post: - tags: - - filesystem.Filesystem - summary: ListDir - operationId: filesystem.Filesystem.ListDir - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.ListDirRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.ListDirResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/MakeDir: - post: - tags: - - filesystem.Filesystem - summary: MakeDir - operationId: filesystem.Filesystem.MakeDir - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.MakeDirRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.MakeDirResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/Move: - post: - tags: - - filesystem.Filesystem - summary: Move - operationId: filesystem.Filesystem.Move - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.MoveRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.MoveResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/Remove: - post: - tags: - - filesystem.Filesystem - summary: Remove - operationId: filesystem.Filesystem.Remove - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.RemoveRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.RemoveResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/RemoveWatcher: - post: - tags: - - filesystem.Filesystem - summary: RemoveWatcher - operationId: filesystem.Filesystem.RemoveWatcher - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.RemoveWatcherRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.RemoveWatcherResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/Stat: - post: - tags: - - filesystem.Filesystem - summary: Stat - operationId: filesystem.Filesystem.Stat - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.StatRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/filesystem.StatResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /filesystem.Filesystem/WatchDir: - post: - tags: - - filesystem.Filesystem - summary: WatchDir - operationId: filesystem.Filesystem.WatchDir - parameters: [] - requestBody: - content: - application/connect+json: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - application/connect+proto: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - application/grpc: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - application/grpc+proto: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - application/grpc+json: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - application/grpc-web: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/filesystem.WatchDirRequest' - required: true - responses: - '200': - description: Success - content: - application/connect+json: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - application/connect+proto: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - application/grpc: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - application/grpc+proto: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - application/grpc+json: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - application/grpc-web: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/filesystem.WatchDirResponse' - default: - description: Error - content: - application/connect+json: - schema: - $ref: '#/components/schemas/connect.error' - application/connect+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+json: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/connect.error' - /process.Process/Connect: - post: - tags: - - process.Process - summary: Connect - operationId: process.Process.Connect - parameters: [] - requestBody: - content: - application/connect+json: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - application/connect+proto: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - application/grpc: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - application/grpc+proto: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - application/grpc+json: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - application/grpc-web: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/process.ConnectRequest' - required: true - responses: - '200': - description: Success - content: - application/connect+json: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - application/connect+proto: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - application/grpc: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - application/grpc+proto: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - application/grpc+json: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - application/grpc-web: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/process.ConnectResponse' - default: - description: Error - content: - application/connect+json: - schema: - $ref: '#/components/schemas/connect.error' - application/connect+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+json: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/connect.error' - /process.Process/List: - post: - tags: - - process.Process - summary: List - operationId: process.Process.List - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/process.ListRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/process.ListResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /process.Process/SendInput: - post: - tags: - - process.Process - summary: SendInput - operationId: process.Process.SendInput - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/process.SendInputRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/process.SendInputResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /process.Process/SendSignal: - post: - tags: - - process.Process - summary: SendSignal - operationId: process.Process.SendSignal - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/process.SendSignalRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/process.SendSignalResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - /process.Process/Start: - post: - tags: - - process.Process - summary: Start - operationId: process.Process.Start - parameters: [] - requestBody: - content: - application/connect+json: - schema: - $ref: '#/components/schemas/process.StartRequest' - application/connect+proto: - schema: - $ref: '#/components/schemas/process.StartRequest' - application/grpc: - schema: - $ref: '#/components/schemas/process.StartRequest' - application/grpc+proto: - schema: - $ref: '#/components/schemas/process.StartRequest' - application/grpc+json: - schema: - $ref: '#/components/schemas/process.StartRequest' - application/grpc-web: - schema: - $ref: '#/components/schemas/process.StartRequest' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/process.StartRequest' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/process.StartRequest' - required: true - responses: - '200': - description: Success - content: - application/connect+json: - schema: - $ref: '#/components/schemas/process.StartResponse' - application/connect+proto: - schema: - $ref: '#/components/schemas/process.StartResponse' - application/grpc: - schema: - $ref: '#/components/schemas/process.StartResponse' - application/grpc+proto: - schema: - $ref: '#/components/schemas/process.StartResponse' - application/grpc+json: - schema: - $ref: '#/components/schemas/process.StartResponse' - application/grpc-web: - schema: - $ref: '#/components/schemas/process.StartResponse' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/process.StartResponse' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/process.StartResponse' - default: - description: Error - content: - application/connect+json: - schema: - $ref: '#/components/schemas/connect.error' - application/connect+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+json: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/connect.error' - /process.Process/StreamInput: - post: - tags: - - process.Process - summary: StreamInput - description: Client input stream ensures ordering of messages - operationId: process.Process.StreamInput - parameters: [] - requestBody: - content: - application/connect+json: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - application/connect+proto: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - application/grpc: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - application/grpc+proto: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - application/grpc+json: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - application/grpc-web: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/process.StreamInputRequest' - required: true - responses: - '200': - description: Success - content: - application/connect+json: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - application/connect+proto: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - application/grpc: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - application/grpc+proto: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - application/grpc+json: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - application/grpc-web: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/process.StreamInputResponse' - default: - description: Error - content: - application/connect+json: - schema: - $ref: '#/components/schemas/connect.error' - application/connect+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc+json: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+proto: - schema: - $ref: '#/components/schemas/connect.error' - application/grpc-web+json: - schema: - $ref: '#/components/schemas/connect.error' - /process.Process/Update: - post: - tags: - - process.Process - summary: Update - operationId: process.Process.Update - parameters: [] - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/process.UpdateRequest' - required: true - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/process.UpdateResponse' - default: - description: Error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' components: securitySchemes: AccessTokenAuth: @@ -962,722 +243,3 @@ components: disk_total: type: integer description: Total disk space in bytes - connect.error_details.Any: - type: object - properties: - type: - type: string - description: 'A URL that acts as a globally unique identifier for the type of the serialized message. For example: `type.googleapis.com/google.rpc.ErrorInfo`. This is used to determine the schema of the data in the `value` field and is the discriminator for the `debug` field.' - value: - type: string - format: binary - description: The Protobuf message, serialized as bytes and base64-encoded. The specific message type is identified by the `type` field. - debug: - oneOf: - - type: object - title: Any - additionalProperties: true - description: Detailed error information. - discriminator: - propertyName: type - title: Debug - description: Deserialized error detail payload. The 'type' field indicates the schema. This field is for easier debugging and should not be relied upon for application logic. - additionalProperties: true - description: Contains an arbitrary serialized message along with a @type that describes the type of the serialized message, with an additional debug field for ConnectRPC error details. - filesystem.CreateWatcherRequest: - type: object - properties: - path: - type: string - title: path - recursive: - type: boolean - title: recursive - title: CreateWatcherRequest - additionalProperties: false - filesystem.CreateWatcherResponse: - type: object - properties: - watcherId: - type: string - title: watcher_id - title: CreateWatcherResponse - additionalProperties: false - filesystem.EntryInfo: - type: object - properties: - name: - type: string - title: name - type: - title: type - $ref: '#/components/schemas/filesystem.FileType' - path: - type: string - title: path - size: - type: integer - title: size - format: int64 - mode: - type: integer - title: mode - permissions: - type: string - title: permissions - owner: - type: string - title: owner - group: - type: string - title: group - modifiedTime: - title: modified_time - $ref: '#/components/schemas/google.protobuf.Timestamp' - symlinkTarget: - type: string - title: symlink_target - description: If the entry is a symlink, this field contains the target of the symlink. - title: EntryInfo - additionalProperties: false - filesystem.EventType: - type: string - title: EventType - enum: - - EVENT_TYPE_UNSPECIFIED - - EVENT_TYPE_CREATE - - EVENT_TYPE_WRITE - - EVENT_TYPE_REMOVE - - EVENT_TYPE_RENAME - - EVENT_TYPE_CHMOD - filesystem.FileType: - type: string - title: FileType - enum: - - FILE_TYPE_UNSPECIFIED - - FILE_TYPE_FILE - - FILE_TYPE_DIRECTORY - filesystem.FilesystemEvent: - type: object - properties: - name: - type: string - title: name - type: - title: type - $ref: '#/components/schemas/filesystem.EventType' - title: FilesystemEvent - additionalProperties: false - filesystem.GetWatcherEventsRequest: - type: object - properties: - watcherId: - type: string - title: watcher_id - title: GetWatcherEventsRequest - additionalProperties: false - filesystem.GetWatcherEventsResponse: - type: object - properties: - events: - type: array - items: - $ref: '#/components/schemas/filesystem.FilesystemEvent' - title: events - title: GetWatcherEventsResponse - additionalProperties: false - filesystem.ListDirRequest: - type: object - properties: - path: - type: string - title: path - depth: - type: integer - title: depth - title: ListDirRequest - additionalProperties: false - filesystem.ListDirResponse: - type: object - properties: - entries: - type: array - items: - $ref: '#/components/schemas/filesystem.EntryInfo' - title: entries - title: ListDirResponse - additionalProperties: false - filesystem.MakeDirRequest: - type: object - properties: - path: - type: string - title: path - title: MakeDirRequest - additionalProperties: false - filesystem.MakeDirResponse: - type: object - properties: - entry: - title: entry - $ref: '#/components/schemas/filesystem.EntryInfo' - title: MakeDirResponse - additionalProperties: false - filesystem.MoveRequest: - type: object - properties: - source: - type: string - title: source - destination: - type: string - title: destination - title: MoveRequest - additionalProperties: false - filesystem.MoveResponse: - type: object - properties: - entry: - title: entry - $ref: '#/components/schemas/filesystem.EntryInfo' - title: MoveResponse - additionalProperties: false - filesystem.RemoveRequest: - type: object - properties: - path: - type: string - title: path - title: RemoveRequest - additionalProperties: false - filesystem.RemoveResponse: - type: object - title: RemoveResponse - additionalProperties: false - filesystem.RemoveWatcherRequest: - type: object - properties: - watcherId: - type: string - title: watcher_id - title: RemoveWatcherRequest - additionalProperties: false - filesystem.RemoveWatcherResponse: - type: object - title: RemoveWatcherResponse - additionalProperties: false - filesystem.StatRequest: - type: object - properties: - path: - type: string - title: path - title: StatRequest - additionalProperties: false - filesystem.StatResponse: - type: object - properties: - entry: - title: entry - $ref: '#/components/schemas/filesystem.EntryInfo' - title: StatResponse - additionalProperties: false - filesystem.WatchDirRequest: - type: object - properties: - path: - type: string - title: path - recursive: - type: boolean - title: recursive - title: WatchDirRequest - additionalProperties: false - filesystem.WatchDirResponse: - type: object - oneOf: - - properties: - filesystem: - title: filesystem - $ref: '#/components/schemas/filesystem.FilesystemEvent' - title: filesystem - required: - - filesystem - - properties: - keepalive: - title: keepalive - $ref: '#/components/schemas/filesystem.WatchDirResponse.KeepAlive' - title: keepalive - required: - - keepalive - - properties: - start: - title: start - $ref: '#/components/schemas/filesystem.WatchDirResponse.StartEvent' - title: start - required: - - start - title: WatchDirResponse - additionalProperties: false - filesystem.WatchDirResponse.KeepAlive: - type: object - title: KeepAlive - additionalProperties: false - filesystem.WatchDirResponse.StartEvent: - type: object - title: StartEvent - additionalProperties: false - google.protobuf.Timestamp: - type: string - format: date-time - description: |- - A Timestamp represents a point in time independent of any time zone or local - calendar, encoded as a count of seconds and fractions of seconds at - nanosecond resolution. The count is relative to an epoch at UTC midnight on - January 1, 1970, in the proleptic Gregorian calendar which extends the - Gregorian calendar backwards to year one. - - All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap - second table is needed for interpretation, using a [24-hour linear - smear](https://developers.google.com/time/smear). - - The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By - restricting to that range, we ensure that we can convert to and from [RFC - 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. - - # Examples - - Example 1: Compute Timestamp from POSIX `time()`. - - Timestamp timestamp; - timestamp.set_seconds(time(NULL)); - timestamp.set_nanos(0); - - Example 2: Compute Timestamp from POSIX `gettimeofday()`. - - struct timeval tv; - gettimeofday(&tv, NULL); - - Timestamp timestamp; - timestamp.set_seconds(tv.tv_sec); - timestamp.set_nanos(tv.tv_usec * 1000); - - Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. - - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; - - // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z - // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. - Timestamp timestamp; - timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); - timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); - - Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. - - long millis = System.currentTimeMillis(); - - Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) - .setNanos((int) ((millis % 1000) * 1000000)).build(); - - Example 5: Compute Timestamp from Java `Instant.now()`. - - Instant now = Instant.now(); - - Timestamp timestamp = - Timestamp.newBuilder().setSeconds(now.getEpochSecond()) - .setNanos(now.getNano()).build(); - - Example 6: Compute Timestamp from current time in Python. - - timestamp = Timestamp() - timestamp.GetCurrentTime() - - # JSON Mapping - - In JSON format, the Timestamp type is encoded as a string in the - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the - format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" - where {year} is always expressed using four digits while {month}, {day}, - {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional - seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), - are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone - is required. A proto3 JSON serializer should always use UTC (as indicated by - "Z") when printing the Timestamp type and a proto3 JSON parser should be - able to accept both UTC and other timezones (as indicated by an offset). - - For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past - 01:30 UTC on January 15, 2017. - - In JavaScript, one can convert a Date object to this format using the - standard - [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) - method. In Python, a standard `datetime.datetime` object can be converted - to this format using - [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with - the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use - the Joda Time's [`ISODateTimeFormat.dateTime()`]( - http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() - ) to obtain a formatter capable of generating timestamps in this format. - example: '2023-01-15T01:30:15.01Z' - process.ConnectRequest: - type: object - properties: - process: - title: process - $ref: '#/components/schemas/process.ProcessSelector' - title: ConnectRequest - additionalProperties: false - process.ConnectResponse: - type: object - properties: - event: - title: event - $ref: '#/components/schemas/process.ProcessEvent' - title: ConnectResponse - additionalProperties: false - process.ListRequest: - type: object - title: ListRequest - additionalProperties: false - process.ListResponse: - type: object - properties: - processes: - type: array - items: - $ref: '#/components/schemas/process.ProcessInfo' - title: processes - title: ListResponse - additionalProperties: false - process.PTY: - type: object - properties: - size: - title: size - $ref: '#/components/schemas/process.PTY.Size' - title: PTY - additionalProperties: false - process.PTY.Size: - type: object - properties: - cols: - type: integer - title: cols - rows: - type: integer - title: rows - title: Size - additionalProperties: false - process.ProcessConfig: - type: object - properties: - cmd: - type: string - title: cmd - args: - type: array - items: - type: string - title: args - envs: - type: object - title: envs - additionalProperties: - type: string - title: value - cwd: - type: string - title: cwd - title: ProcessConfig - additionalProperties: false - process.ProcessConfig.EnvsEntry: - type: object - properties: - key: - type: string - title: key - value: - type: string - title: value - title: EnvsEntry - additionalProperties: false - process.ProcessEvent: - type: object - oneOf: - - properties: - data: - title: data - $ref: '#/components/schemas/process.ProcessEvent.DataEvent' - title: data - required: - - data - - properties: - end: - title: end - $ref: '#/components/schemas/process.ProcessEvent.EndEvent' - title: end - required: - - end - - properties: - keepalive: - title: keepalive - $ref: '#/components/schemas/process.ProcessEvent.KeepAlive' - title: keepalive - required: - - keepalive - - properties: - start: - title: start - $ref: '#/components/schemas/process.ProcessEvent.StartEvent' - title: start - required: - - start - title: ProcessEvent - additionalProperties: false - process.ProcessEvent.DataEvent: - type: object - oneOf: - - properties: - pty: - type: string - title: pty - format: byte - title: pty - required: - - pty - - properties: - stderr: - type: string - title: stderr - format: byte - title: stderr - required: - - stderr - - properties: - stdout: - type: string - title: stdout - format: byte - title: stdout - required: - - stdout - title: DataEvent - additionalProperties: false - process.ProcessEvent.EndEvent: - type: object - properties: - exitCode: - type: integer - title: exit_code - format: int32 - exited: - type: boolean - title: exited - status: - type: string - title: status - error: - type: string - title: error - title: EndEvent - additionalProperties: false - process.ProcessEvent.KeepAlive: - type: object - title: KeepAlive - additionalProperties: false - process.ProcessEvent.StartEvent: - type: object - properties: - pid: - type: integer - title: pid - title: StartEvent - additionalProperties: false - process.ProcessInfo: - type: object - properties: - config: - title: config - $ref: '#/components/schemas/process.ProcessConfig' - pid: - type: integer - title: pid - tag: - type: string - title: tag - title: ProcessInfo - additionalProperties: false - process.ProcessInput: - type: object - oneOf: - - properties: - pty: - type: string - title: pty - format: byte - title: pty - required: - - pty - - properties: - stdin: - type: string - title: stdin - format: byte - title: stdin - required: - - stdin - title: ProcessInput - additionalProperties: false - process.ProcessSelector: - type: object - oneOf: - - properties: - pid: - type: integer - title: pid - title: pid - required: - - pid - - properties: - tag: - type: string - title: tag - title: tag - required: - - tag - title: ProcessSelector - additionalProperties: false - process.SendInputRequest: - type: object - properties: - process: - title: process - $ref: '#/components/schemas/process.ProcessSelector' - input: - title: input - $ref: '#/components/schemas/process.ProcessInput' - title: SendInputRequest - additionalProperties: false - process.SendInputResponse: - type: object - title: SendInputResponse - additionalProperties: false - process.SendSignalRequest: - type: object - properties: - process: - title: process - $ref: '#/components/schemas/process.ProcessSelector' - signal: - title: signal - $ref: '#/components/schemas/process.Signal' - title: SendSignalRequest - additionalProperties: false - process.SendSignalResponse: - type: object - title: SendSignalResponse - additionalProperties: false - process.Signal: - type: string - title: Signal - enum: - - SIGNAL_UNSPECIFIED - - SIGNAL_SIGTERM - - SIGNAL_SIGKILL - process.StartRequest: - type: object - properties: - process: - title: process - $ref: '#/components/schemas/process.ProcessConfig' - pty: - title: pty - nullable: true - $ref: '#/components/schemas/process.PTY' - tag: - type: string - title: tag - stdin: - type: boolean - title: stdin - description: |- - This is optional for backwards compatibility. - We default to true. New SDK versions will set this to false by default. - title: StartRequest - additionalProperties: false - process.StartResponse: - type: object - properties: - event: - title: event - $ref: '#/components/schemas/process.ProcessEvent' - title: StartResponse - additionalProperties: false - process.StreamInputRequest: - type: object - oneOf: - - properties: - data: - title: data - $ref: '#/components/schemas/process.StreamInputRequest.DataEvent' - title: data - required: - - data - - properties: - keepalive: - title: keepalive - $ref: '#/components/schemas/process.StreamInputRequest.KeepAlive' - title: keepalive - required: - - keepalive - - properties: - start: - title: start - $ref: '#/components/schemas/process.StreamInputRequest.StartEvent' - title: start - required: - - start - title: StreamInputRequest - additionalProperties: false - process.StreamInputRequest.DataEvent: - type: object - properties: - input: - title: input - $ref: '#/components/schemas/process.ProcessInput' - title: DataEvent - additionalProperties: false - process.StreamInputRequest.KeepAlive: - type: object - title: KeepAlive - additionalProperties: false - process.StreamInputRequest.StartEvent: - type: object - properties: - process: - title: process - $ref: '#/components/schemas/process.ProcessSelector' - title: StartEvent - additionalProperties: false - process.StreamInputResponse: - type: object - title: StreamInputResponse - additionalProperties: false - process.UpdateRequest: - type: object - properties: - process: - title: process - $ref: '#/components/schemas/process.ProcessSelector' - pty: - title: pty - nullable: true - $ref: '#/components/schemas/process.PTY' - title: UpdateRequest - additionalProperties: false - process.UpdateResponse: - type: object - title: UpdateResponse - additionalProperties: false diff --git a/scripts/sync-openapi.js b/scripts/sync-openapi.js index 217b272..dbdb23e 100644 --- a/scripts/sync-openapi.js +++ b/scripts/sync-openapi.js @@ -86,6 +86,11 @@ https://{sandboxID}.e2b.app 3. Use \`envdAccessToken\` as \`X-Access-Token\` header for all Sandbox API calls ` }, + // Internal endpoints to exclude (SDK initialization, not user-facing) + excludePaths: [ + '/init', + '/metrics' + ], // Connect RPC schemas to remove (protocol-level, not user-facing) removeSchemas: [ 'connect-protocol-version', @@ -232,6 +237,15 @@ async function generateSandboxApiSpec() { console.warn('Sandbox API will only include REST endpoints (/files, /health, etc.)'); } + // Filter out internal endpoints + const excludePaths = SANDBOX_API_CONFIG.excludePaths || []; + for (const excludePath of excludePaths) { + if (spec.paths[excludePath]) { + delete spec.paths[excludePath]; + console.log(`Excluded internal endpoint: ${excludePath}`); + } + } + // Apply fixes applySchemaFixes(spec); From 6197c239a1d16013dfeb738a7d1c39e19da84277 Mon Sep 17 00:00:00 2001 From: Tomas Beran Date: Wed, 4 Feb 2026 18:20:17 -0800 Subject: [PATCH 4/6] Regenerate Sandbox API spec with filesystem and process endpoints Include proto-generated endpoints: - filesystem.Filesystem: ListDir, MakeDir, Move, Remove, Stat, watchers - process.Process: Start, List, Connect, SendInput, SendSignal, Update --- openapi-sandbox.yml | 1391 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1391 insertions(+) diff --git a/openapi-sandbox.yml b/openapi-sandbox.yml index 9ed976a..22d2933 100644 --- a/openapi-sandbox.yml +++ b/openapi-sandbox.yml @@ -19,6 +19,8 @@ info: 3. Use `envdAccessToken` as `X-Access-Token` header for all Sandbox API calls tags: - name: files + - name: filesystem.Filesystem + - name: process.Process paths: /health: get: @@ -88,6 +90,676 @@ paths: $ref: '#/components/responses/InternalServerError' '507': $ref: '#/components/responses/NotEnoughDiskSpace' + /filesystem.Filesystem/CreateWatcher: + post: + tags: + - filesystem.Filesystem + summary: CreateWatcher + description: Non-streaming versions of WatchDir + operationId: filesystem.Filesystem.CreateWatcher + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.CreateWatcherRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.CreateWatcherResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/GetWatcherEvents: + post: + tags: + - filesystem.Filesystem + summary: GetWatcherEvents + operationId: filesystem.Filesystem.GetWatcherEvents + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.GetWatcherEventsRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.GetWatcherEventsResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/ListDir: + post: + tags: + - filesystem.Filesystem + summary: ListDir + operationId: filesystem.Filesystem.ListDir + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.ListDirRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.ListDirResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/MakeDir: + post: + tags: + - filesystem.Filesystem + summary: MakeDir + operationId: filesystem.Filesystem.MakeDir + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MakeDirRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MakeDirResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/Move: + post: + tags: + - filesystem.Filesystem + summary: Move + operationId: filesystem.Filesystem.Move + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MoveRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.MoveResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/Remove: + post: + tags: + - filesystem.Filesystem + summary: Remove + operationId: filesystem.Filesystem.Remove + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/RemoveWatcher: + post: + tags: + - filesystem.Filesystem + summary: RemoveWatcher + operationId: filesystem.Filesystem.RemoveWatcher + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveWatcherRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.RemoveWatcherResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/Stat: + post: + tags: + - filesystem.Filesystem + summary: Stat + operationId: filesystem.Filesystem.Stat + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.StatRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/filesystem.StatResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /filesystem.Filesystem/WatchDir: + post: + tags: + - filesystem.Filesystem + summary: WatchDir + operationId: filesystem.Filesystem.WatchDir + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/filesystem.WatchDirResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/Connect: + post: + tags: + - process.Process + summary: Connect + operationId: process.Process.Connect + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.ConnectRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.ConnectResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/List: + post: + tags: + - process.Process + summary: List + operationId: process.Process.List + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.ListRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.ListResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /process.Process/SendInput: + post: + tags: + - process.Process + summary: SendInput + operationId: process.Process.SendInput + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendInputRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendInputResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /process.Process/SendSignal: + post: + tags: + - process.Process + summary: SendSignal + operationId: process.Process.SendSignal + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendSignalRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.SendSignalResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /process.Process/Start: + post: + tags: + - process.Process + summary: Start + operationId: process.Process.Start + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StartRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StartRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StartResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StartResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/StreamInput: + post: + tags: + - process.Process + summary: StreamInput + description: Client input stream ensures ordering of messages + operationId: process.Process.StreamInput + parameters: [] + requestBody: + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StreamInputRequest' + required: true + responses: + '200': + description: Success + content: + application/connect+json: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/connect+proto: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc+proto: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc+json: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc-web: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/process.StreamInputResponse' + default: + description: Error + content: + application/connect+json: + schema: + $ref: '#/components/schemas/connect.error' + application/connect+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc+json: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+proto: + schema: + $ref: '#/components/schemas/connect.error' + application/grpc-web+json: + schema: + $ref: '#/components/schemas/connect.error' + /process.Process/Update: + post: + tags: + - process.Process + summary: Update + operationId: process.Process.Update + parameters: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/process.UpdateRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/process.UpdateResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' components: securitySchemes: AccessTokenAuth: @@ -243,3 +915,722 @@ components: disk_total: type: integer description: Total disk space in bytes + connect.error_details.Any: + type: object + properties: + type: + type: string + description: 'A URL that acts as a globally unique identifier for the type of the serialized message. For example: `type.googleapis.com/google.rpc.ErrorInfo`. This is used to determine the schema of the data in the `value` field and is the discriminator for the `debug` field.' + value: + type: string + format: binary + description: The Protobuf message, serialized as bytes and base64-encoded. The specific message type is identified by the `type` field. + debug: + oneOf: + - type: object + title: Any + additionalProperties: true + description: Detailed error information. + discriminator: + propertyName: type + title: Debug + description: Deserialized error detail payload. The 'type' field indicates the schema. This field is for easier debugging and should not be relied upon for application logic. + additionalProperties: true + description: Contains an arbitrary serialized message along with a @type that describes the type of the serialized message, with an additional debug field for ConnectRPC error details. + filesystem.CreateWatcherRequest: + type: object + properties: + path: + type: string + title: path + recursive: + type: boolean + title: recursive + title: CreateWatcherRequest + additionalProperties: false + filesystem.CreateWatcherResponse: + type: object + properties: + watcherId: + type: string + title: watcher_id + title: CreateWatcherResponse + additionalProperties: false + filesystem.EntryInfo: + type: object + properties: + name: + type: string + title: name + type: + title: type + $ref: '#/components/schemas/filesystem.FileType' + path: + type: string + title: path + size: + type: integer + title: size + format: int64 + mode: + type: integer + title: mode + permissions: + type: string + title: permissions + owner: + type: string + title: owner + group: + type: string + title: group + modifiedTime: + title: modified_time + $ref: '#/components/schemas/google.protobuf.Timestamp' + symlinkTarget: + type: string + title: symlink_target + description: If the entry is a symlink, this field contains the target of the symlink. + title: EntryInfo + additionalProperties: false + filesystem.EventType: + type: string + title: EventType + enum: + - EVENT_TYPE_UNSPECIFIED + - EVENT_TYPE_CREATE + - EVENT_TYPE_WRITE + - EVENT_TYPE_REMOVE + - EVENT_TYPE_RENAME + - EVENT_TYPE_CHMOD + filesystem.FileType: + type: string + title: FileType + enum: + - FILE_TYPE_UNSPECIFIED + - FILE_TYPE_FILE + - FILE_TYPE_DIRECTORY + filesystem.FilesystemEvent: + type: object + properties: + name: + type: string + title: name + type: + title: type + $ref: '#/components/schemas/filesystem.EventType' + title: FilesystemEvent + additionalProperties: false + filesystem.GetWatcherEventsRequest: + type: object + properties: + watcherId: + type: string + title: watcher_id + title: GetWatcherEventsRequest + additionalProperties: false + filesystem.GetWatcherEventsResponse: + type: object + properties: + events: + type: array + items: + $ref: '#/components/schemas/filesystem.FilesystemEvent' + title: events + title: GetWatcherEventsResponse + additionalProperties: false + filesystem.ListDirRequest: + type: object + properties: + path: + type: string + title: path + depth: + type: integer + title: depth + title: ListDirRequest + additionalProperties: false + filesystem.ListDirResponse: + type: object + properties: + entries: + type: array + items: + $ref: '#/components/schemas/filesystem.EntryInfo' + title: entries + title: ListDirResponse + additionalProperties: false + filesystem.MakeDirRequest: + type: object + properties: + path: + type: string + title: path + title: MakeDirRequest + additionalProperties: false + filesystem.MakeDirResponse: + type: object + properties: + entry: + title: entry + $ref: '#/components/schemas/filesystem.EntryInfo' + title: MakeDirResponse + additionalProperties: false + filesystem.MoveRequest: + type: object + properties: + source: + type: string + title: source + destination: + type: string + title: destination + title: MoveRequest + additionalProperties: false + filesystem.MoveResponse: + type: object + properties: + entry: + title: entry + $ref: '#/components/schemas/filesystem.EntryInfo' + title: MoveResponse + additionalProperties: false + filesystem.RemoveRequest: + type: object + properties: + path: + type: string + title: path + title: RemoveRequest + additionalProperties: false + filesystem.RemoveResponse: + type: object + title: RemoveResponse + additionalProperties: false + filesystem.RemoveWatcherRequest: + type: object + properties: + watcherId: + type: string + title: watcher_id + title: RemoveWatcherRequest + additionalProperties: false + filesystem.RemoveWatcherResponse: + type: object + title: RemoveWatcherResponse + additionalProperties: false + filesystem.StatRequest: + type: object + properties: + path: + type: string + title: path + title: StatRequest + additionalProperties: false + filesystem.StatResponse: + type: object + properties: + entry: + title: entry + $ref: '#/components/schemas/filesystem.EntryInfo' + title: StatResponse + additionalProperties: false + filesystem.WatchDirRequest: + type: object + properties: + path: + type: string + title: path + recursive: + type: boolean + title: recursive + title: WatchDirRequest + additionalProperties: false + filesystem.WatchDirResponse: + type: object + oneOf: + - properties: + filesystem: + title: filesystem + $ref: '#/components/schemas/filesystem.FilesystemEvent' + title: filesystem + required: + - filesystem + - properties: + keepalive: + title: keepalive + $ref: '#/components/schemas/filesystem.WatchDirResponse.KeepAlive' + title: keepalive + required: + - keepalive + - properties: + start: + title: start + $ref: '#/components/schemas/filesystem.WatchDirResponse.StartEvent' + title: start + required: + - start + title: WatchDirResponse + additionalProperties: false + filesystem.WatchDirResponse.KeepAlive: + type: object + title: KeepAlive + additionalProperties: false + filesystem.WatchDirResponse.StartEvent: + type: object + title: StartEvent + additionalProperties: false + google.protobuf.Timestamp: + type: string + format: date-time + description: |- + A Timestamp represents a point in time independent of any time zone or local + calendar, encoded as a count of seconds and fractions of seconds at + nanosecond resolution. The count is relative to an epoch at UTC midnight on + January 1, 1970, in the proleptic Gregorian calendar which extends the + Gregorian calendar backwards to year one. + + All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap + second table is needed for interpretation, using a [24-hour linear + smear](https://developers.google.com/time/smear). + + The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By + restricting to that range, we ensure that we can convert to and from [RFC + 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. + + # Examples + + Example 1: Compute Timestamp from POSIX `time()`. + + Timestamp timestamp; + timestamp.set_seconds(time(NULL)); + timestamp.set_nanos(0); + + Example 2: Compute Timestamp from POSIX `gettimeofday()`. + + struct timeval tv; + gettimeofday(&tv, NULL); + + Timestamp timestamp; + timestamp.set_seconds(tv.tv_sec); + timestamp.set_nanos(tv.tv_usec * 1000); + + Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. + + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + + // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z + // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. + Timestamp timestamp; + timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); + timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); + + Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. + + long millis = System.currentTimeMillis(); + + Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) + .setNanos((int) ((millis % 1000) * 1000000)).build(); + + Example 5: Compute Timestamp from Java `Instant.now()`. + + Instant now = Instant.now(); + + Timestamp timestamp = + Timestamp.newBuilder().setSeconds(now.getEpochSecond()) + .setNanos(now.getNano()).build(); + + Example 6: Compute Timestamp from current time in Python. + + timestamp = Timestamp() + timestamp.GetCurrentTime() + + # JSON Mapping + + In JSON format, the Timestamp type is encoded as a string in the + [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the + format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" + where {year} is always expressed using four digits while {month}, {day}, + {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional + seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), + are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone + is required. A proto3 JSON serializer should always use UTC (as indicated by + "Z") when printing the Timestamp type and a proto3 JSON parser should be + able to accept both UTC and other timezones (as indicated by an offset). + + For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past + 01:30 UTC on January 15, 2017. + + In JavaScript, one can convert a Date object to this format using the + standard + [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) + method. In Python, a standard `datetime.datetime` object can be converted + to this format using + [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with + the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use + the Joda Time's [`ISODateTimeFormat.dateTime()`]( + http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime() + ) to obtain a formatter capable of generating timestamps in this format. + example: '2023-01-15T01:30:15.01Z' + process.ConnectRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + title: ConnectRequest + additionalProperties: false + process.ConnectResponse: + type: object + properties: + event: + title: event + $ref: '#/components/schemas/process.ProcessEvent' + title: ConnectResponse + additionalProperties: false + process.ListRequest: + type: object + title: ListRequest + additionalProperties: false + process.ListResponse: + type: object + properties: + processes: + type: array + items: + $ref: '#/components/schemas/process.ProcessInfo' + title: processes + title: ListResponse + additionalProperties: false + process.PTY: + type: object + properties: + size: + title: size + $ref: '#/components/schemas/process.PTY.Size' + title: PTY + additionalProperties: false + process.PTY.Size: + type: object + properties: + cols: + type: integer + title: cols + rows: + type: integer + title: rows + title: Size + additionalProperties: false + process.ProcessConfig: + type: object + properties: + cmd: + type: string + title: cmd + args: + type: array + items: + type: string + title: args + envs: + type: object + title: envs + additionalProperties: + type: string + title: value + cwd: + type: string + title: cwd + title: ProcessConfig + additionalProperties: false + process.ProcessConfig.EnvsEntry: + type: object + properties: + key: + type: string + title: key + value: + type: string + title: value + title: EnvsEntry + additionalProperties: false + process.ProcessEvent: + type: object + oneOf: + - properties: + data: + title: data + $ref: '#/components/schemas/process.ProcessEvent.DataEvent' + title: data + required: + - data + - properties: + end: + title: end + $ref: '#/components/schemas/process.ProcessEvent.EndEvent' + title: end + required: + - end + - properties: + keepalive: + title: keepalive + $ref: '#/components/schemas/process.ProcessEvent.KeepAlive' + title: keepalive + required: + - keepalive + - properties: + start: + title: start + $ref: '#/components/schemas/process.ProcessEvent.StartEvent' + title: start + required: + - start + title: ProcessEvent + additionalProperties: false + process.ProcessEvent.DataEvent: + type: object + oneOf: + - properties: + pty: + type: string + title: pty + format: byte + title: pty + required: + - pty + - properties: + stderr: + type: string + title: stderr + format: byte + title: stderr + required: + - stderr + - properties: + stdout: + type: string + title: stdout + format: byte + title: stdout + required: + - stdout + title: DataEvent + additionalProperties: false + process.ProcessEvent.EndEvent: + type: object + properties: + exitCode: + type: integer + title: exit_code + format: int32 + exited: + type: boolean + title: exited + status: + type: string + title: status + error: + type: string + title: error + title: EndEvent + additionalProperties: false + process.ProcessEvent.KeepAlive: + type: object + title: KeepAlive + additionalProperties: false + process.ProcessEvent.StartEvent: + type: object + properties: + pid: + type: integer + title: pid + title: StartEvent + additionalProperties: false + process.ProcessInfo: + type: object + properties: + config: + title: config + $ref: '#/components/schemas/process.ProcessConfig' + pid: + type: integer + title: pid + tag: + type: string + title: tag + title: ProcessInfo + additionalProperties: false + process.ProcessInput: + type: object + oneOf: + - properties: + pty: + type: string + title: pty + format: byte + title: pty + required: + - pty + - properties: + stdin: + type: string + title: stdin + format: byte + title: stdin + required: + - stdin + title: ProcessInput + additionalProperties: false + process.ProcessSelector: + type: object + oneOf: + - properties: + pid: + type: integer + title: pid + title: pid + required: + - pid + - properties: + tag: + type: string + title: tag + title: tag + required: + - tag + title: ProcessSelector + additionalProperties: false + process.SendInputRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + input: + title: input + $ref: '#/components/schemas/process.ProcessInput' + title: SendInputRequest + additionalProperties: false + process.SendInputResponse: + type: object + title: SendInputResponse + additionalProperties: false + process.SendSignalRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + signal: + title: signal + $ref: '#/components/schemas/process.Signal' + title: SendSignalRequest + additionalProperties: false + process.SendSignalResponse: + type: object + title: SendSignalResponse + additionalProperties: false + process.Signal: + type: string + title: Signal + enum: + - SIGNAL_UNSPECIFIED + - SIGNAL_SIGTERM + - SIGNAL_SIGKILL + process.StartRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessConfig' + pty: + title: pty + nullable: true + $ref: '#/components/schemas/process.PTY' + tag: + type: string + title: tag + stdin: + type: boolean + title: stdin + description: |- + This is optional for backwards compatibility. + We default to true. New SDK versions will set this to false by default. + title: StartRequest + additionalProperties: false + process.StartResponse: + type: object + properties: + event: + title: event + $ref: '#/components/schemas/process.ProcessEvent' + title: StartResponse + additionalProperties: false + process.StreamInputRequest: + type: object + oneOf: + - properties: + data: + title: data + $ref: '#/components/schemas/process.StreamInputRequest.DataEvent' + title: data + required: + - data + - properties: + keepalive: + title: keepalive + $ref: '#/components/schemas/process.StreamInputRequest.KeepAlive' + title: keepalive + required: + - keepalive + - properties: + start: + title: start + $ref: '#/components/schemas/process.StreamInputRequest.StartEvent' + title: start + required: + - start + title: StreamInputRequest + additionalProperties: false + process.StreamInputRequest.DataEvent: + type: object + properties: + input: + title: input + $ref: '#/components/schemas/process.ProcessInput' + title: DataEvent + additionalProperties: false + process.StreamInputRequest.KeepAlive: + type: object + title: KeepAlive + additionalProperties: false + process.StreamInputRequest.StartEvent: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + title: StartEvent + additionalProperties: false + process.StreamInputResponse: + type: object + title: StreamInputResponse + additionalProperties: false + process.UpdateRequest: + type: object + properties: + process: + title: process + $ref: '#/components/schemas/process.ProcessSelector' + pty: + title: pty + nullable: true + $ref: '#/components/schemas/process.PTY' + title: UpdateRequest + additionalProperties: false + process.UpdateResponse: + type: object + title: UpdateResponse + additionalProperties: false From 0ddbe34c981cd00e20db950a6336fda61f286c22 Mon Sep 17 00:00:00 2001 From: Tomas Beran Date: Wed, 4 Feb 2026 18:25:15 -0800 Subject: [PATCH 5/6] Exclude /envs endpoint from Sandbox API --- openapi-sandbox.yml | 13 ------------- scripts/sync-openapi.js | 3 ++- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/openapi-sandbox.yml b/openapi-sandbox.yml index 22d2933..da29fea 100644 --- a/openapi-sandbox.yml +++ b/openapi-sandbox.yml @@ -28,19 +28,6 @@ paths: responses: '204': description: The service is healthy - /envs: - get: - summary: Get the environment variables - security: - - AccessTokenAuth: [] - - {} - responses: - '200': - description: Environment variables - content: - application/json: - schema: - $ref: '#/components/schemas/EnvVars' /files: get: summary: Download a file diff --git a/scripts/sync-openapi.js b/scripts/sync-openapi.js index dbdb23e..22b7244 100644 --- a/scripts/sync-openapi.js +++ b/scripts/sync-openapi.js @@ -89,7 +89,8 @@ https://{sandboxID}.e2b.app // Internal endpoints to exclude (SDK initialization, not user-facing) excludePaths: [ '/init', - '/metrics' + '/metrics', + '/envs' ], // Connect RPC schemas to remove (protocol-level, not user-facing) removeSchemas: [ From 102ac12c2543a6f9398b7e2e4eabb6f73fee376c Mon Sep 17 00:00:00 2001 From: Tomas Beran Date: Wed, 4 Feb 2026 18:33:51 -0800 Subject: [PATCH 6/6] Improve Sandbox API section names and exclude /health - Rename tags: filesystem.Filesystem -> Filesystem, process.Process -> Process - Add descriptions to tag sections - Exclude /health endpoint (internal) --- openapi-sandbox.yml | 51 +++++++++++++++++++---------------------- scripts/sync-openapi.js | 26 ++++++++++++++++++++- 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/openapi-sandbox.yml b/openapi-sandbox.yml index da29fea..c25c692 100644 --- a/openapi-sandbox.yml +++ b/openapi-sandbox.yml @@ -18,21 +18,18 @@ info: 2. Response includes `sandboxID` and `envdAccessToken` 3. Use `envdAccessToken` as `X-Access-Token` header for all Sandbox API calls tags: - - name: files - - name: filesystem.Filesystem - - name: process.Process + - name: Files + description: Upload and download files + - name: Filesystem + description: Filesystem operations (list, create, move, delete) + - name: Process + description: Process management (start, stop, send input) paths: - /health: - get: - summary: Check the health of the service - responses: - '204': - description: The service is healthy /files: get: summary: Download a file tags: - - files + - Files security: - AccessTokenAuth: [] - {} @@ -55,7 +52,7 @@ paths: post: summary: Upload a file and ensure the parent directories exist. If the file exists, it will be overwritten. tags: - - files + - Files security: - AccessTokenAuth: [] - {} @@ -80,7 +77,7 @@ paths: /filesystem.Filesystem/CreateWatcher: post: tags: - - filesystem.Filesystem + - Filesystem summary: CreateWatcher description: Non-streaming versions of WatchDir operationId: filesystem.Filesystem.CreateWatcher @@ -107,7 +104,7 @@ paths: /filesystem.Filesystem/GetWatcherEvents: post: tags: - - filesystem.Filesystem + - Filesystem summary: GetWatcherEvents operationId: filesystem.Filesystem.GetWatcherEvents parameters: [] @@ -133,7 +130,7 @@ paths: /filesystem.Filesystem/ListDir: post: tags: - - filesystem.Filesystem + - Filesystem summary: ListDir operationId: filesystem.Filesystem.ListDir parameters: [] @@ -159,7 +156,7 @@ paths: /filesystem.Filesystem/MakeDir: post: tags: - - filesystem.Filesystem + - Filesystem summary: MakeDir operationId: filesystem.Filesystem.MakeDir parameters: [] @@ -185,7 +182,7 @@ paths: /filesystem.Filesystem/Move: post: tags: - - filesystem.Filesystem + - Filesystem summary: Move operationId: filesystem.Filesystem.Move parameters: [] @@ -211,7 +208,7 @@ paths: /filesystem.Filesystem/Remove: post: tags: - - filesystem.Filesystem + - Filesystem summary: Remove operationId: filesystem.Filesystem.Remove parameters: [] @@ -237,7 +234,7 @@ paths: /filesystem.Filesystem/RemoveWatcher: post: tags: - - filesystem.Filesystem + - Filesystem summary: RemoveWatcher operationId: filesystem.Filesystem.RemoveWatcher parameters: [] @@ -263,7 +260,7 @@ paths: /filesystem.Filesystem/Stat: post: tags: - - filesystem.Filesystem + - Filesystem summary: Stat operationId: filesystem.Filesystem.Stat parameters: [] @@ -289,7 +286,7 @@ paths: /filesystem.Filesystem/WatchDir: post: tags: - - filesystem.Filesystem + - Filesystem summary: WatchDir operationId: filesystem.Filesystem.WatchDir parameters: [] @@ -378,7 +375,7 @@ paths: /process.Process/Connect: post: tags: - - process.Process + - Process summary: Connect operationId: process.Process.Connect parameters: [] @@ -467,7 +464,7 @@ paths: /process.Process/List: post: tags: - - process.Process + - Process summary: List operationId: process.Process.List parameters: [] @@ -493,7 +490,7 @@ paths: /process.Process/SendInput: post: tags: - - process.Process + - Process summary: SendInput operationId: process.Process.SendInput parameters: [] @@ -519,7 +516,7 @@ paths: /process.Process/SendSignal: post: tags: - - process.Process + - Process summary: SendSignal operationId: process.Process.SendSignal parameters: [] @@ -545,7 +542,7 @@ paths: /process.Process/Start: post: tags: - - process.Process + - Process summary: Start operationId: process.Process.Start parameters: [] @@ -634,7 +631,7 @@ paths: /process.Process/StreamInput: post: tags: - - process.Process + - Process summary: StreamInput description: Client input stream ensures ordering of messages operationId: process.Process.StreamInput @@ -724,7 +721,7 @@ paths: /process.Process/Update: post: tags: - - process.Process + - Process summary: Update operationId: process.Process.Update parameters: [] diff --git a/scripts/sync-openapi.js b/scripts/sync-openapi.js index 22b7244..e5b0be9 100644 --- a/scripts/sync-openapi.js +++ b/scripts/sync-openapi.js @@ -90,7 +90,8 @@ https://{sandboxID}.e2b.app excludePaths: [ '/init', '/metrics', - '/envs' + '/envs', + '/health' ], // Connect RPC schemas to remove (protocol-level, not user-facing) removeSchemas: [ @@ -247,6 +248,29 @@ async function generateSandboxApiSpec() { } } + // Clean up tags - rename to user-friendly names + const tagRenames = { + 'filesystem.Filesystem': 'Filesystem', + 'process.Process': 'Process', + 'files': 'Files' + }; + + // Update tags in paths + for (const [path, methods] of Object.entries(spec.paths || {})) { + for (const [method, operation] of Object.entries(methods)) { + if (operation.tags) { + operation.tags = operation.tags.map(tag => tagRenames[tag] || tag); + } + } + } + + // Update top-level tags list + spec.tags = [ + { name: 'Files', description: 'Upload and download files' }, + { name: 'Filesystem', description: 'Filesystem operations (list, create, move, delete)' }, + { name: 'Process', description: 'Process management (start, stop, send input)' } + ]; + // Apply fixes applySchemaFixes(spec);