{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Square Cloud API","version":"10.3.3","description":"Public REST API for the Square Cloud platform.","contact":{"email":"support@squarecloud.app"},"license":{"name":"MIT"}},"servers":[{"url":"https://api.squarecloud.app","description":"Production"}],"tags":[{"name":"Account","description":"The authenticated user's account: profile, plan, owned resources, locale, username, API key, downgrade and personal snapshots."},{"name":"Lifecycle","description":"Application lifecycle and runtime: create, delete, info, status, logs, metrics, actions, realtime."},{"name":"File Manager","description":"Read, upload, rename and delete files in a running application's filesystem."},{"name":"Environment Variables","description":"Manage the application's environment variables (read, merge, replace, remove)."},{"name":"Network","description":"Custom domains, edge cache, DNS configuration and traffic analytics."},{"name":"Deployments","description":"Manual and Git-based deploy pipelines, GitHub App installation, commit uploads, deploy history."},{"name":"Snapshots","description":"Create, restore, list and download application snapshots."},{"name":"DB Lifecycle","description":"Database lifecycle and runtime: create, delete, info, status, metrics, start/stop, update."},{"name":"Credentials","description":"Rotate database access password and read the TLS certificate."},{"name":"Database Snapshots","description":"Create, restore and list database snapshots."},{"name":"Workspaces","description":"Multi-user collaboration: workspaces, members, app sharing and role-based permissions."},{"name":"Service","description":"Platform-wide read-only endpoints (status, schema)."},{"name":"Webhooks","description":"Public webhook receivers (Git providers). Authenticated by route-specific signatures."}],"x-tagGroups":[{"name":"Profile","tags":["Account"]},{"name":"Applications","tags":["Lifecycle","File Manager","Environment Variables","Network","Deployments","Snapshots"]},{"name":"Databases","tags":["DB Lifecycle","Credentials","Database Snapshots"]},{"name":"Collaboration","tags":["Workspaces"]},{"name":"Platform","tags":["Service","Webhooks"]}],"security":[{"apiKey":[]}],"components":{"schemas":{"ErrorBody":{"type":"object","required":["status"],"properties":{"status":{"type":"string","const":"error"},"code":{"type":"string","pattern":"^[A-Z][A-Z0-9_]+$"},"message":{"type":"string"}}}},"responses":{"InternalServerError":{"description":"An unexpected error occurred while processing the request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INTERNAL_SERVER_ERROR"}}}},"AccessDenied":{"description":"The Authorization header is missing, malformed, or the credentials are not valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"ACCESS_DENIED"}}}},"SessionRequired":{"description":"This endpoint requires a session token (JWT). API keys are not accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"ACCESS_DENIED","message":"You need to use a session token to access this route."}}}},"RateLimited":{"description":"The authenticated user or API key exceeded the global request budget.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RATE_LIMIT"}}}},"RateLimitedSpecific":{"description":"The endpoint enforces its own rate limit and the caller hit the cooldown.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"KEEP_CALM"}}}},"PayloadTooLarge":{"description":"The request body is larger than the maximum allowed size (100MB).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"PAYLOAD_TOO_LARGE"}}}},"InvalidJsonBody":{"description":"The request body could not be parsed as JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_JSON_BODY"}}}},"AppNotFound":{"description":"The target application could not be found, or the caller is not a member of the workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"APP_NOT_FOUND"}}}},"PermissionDenied":{"description":"The workspace member does not have the required permission for this endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"PERMISSION_DENIED"}}}}},"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"Authorization","description":"User API token or JWT session token. Length 64-1024 chars."}}},"paths":{"/v2/account/apikey":{"get":{"operationId":"getAccountApikey","tags":["Account"],"summary":"Rotate the authenticated user's API key","description":"Generates a new API key for the authenticated user and invalidates the previous one. The returned `apiKey` is in the format `<userId>-<encryptedSecret>` and is shown only once — store it securely.\n\nRequires a session token. Rate limited to 2 rotations per minute, with a 5 minute cooldown on the third attempt.","responses":{"200":{"description":"A fresh API key was generated and persisted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"apiKey":{"type":"string"}},"required":["apiKey"]}},"required":["status","response"]},"example":{"status":"success","response":{"apiKey":"1234567890-abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/account/downgrade":{"post":{"operationId":"postAccountDowngrade","tags":["Account"],"summary":"Downgrade the authenticated user's plan","description":"Moves the authenticated user to the next lower plan tier. The flow is two-step: the first call (no `confirmCode` in the body) emails an 8-character code; the second call must echo it back in `confirmCode` to apply the downgrade.\n\nThe downgrade is rejected when current memory usage exceeds the lower plan's allowance, when the user is already on `hobby-1`, or when standard→hobby would violate workspace/custom-domain entitlements.\n\nRequires a session token. Limited to 4 attempts per 5 minutes with a 24h block after the cap.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"confirmCode":{"type":"string","minLength":8,"maxLength":8,"description":"Code sent by email in the first call."}}}}}},"responses":{"200":{"description":"Either the confirmation code was sent or the downgrade was applied.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"code":{"type":"string"}},"required":["status","code"]},"examples":{"code_sent":{"value":{"status":"success","code":"CONFIRM_CODE_SENT"}},"downgrade_applied":{"value":{"status":"success","code":"CONFIRM_CODE_VALIDATED"}}}}}},"400":{"description":"The submitted `confirmCode` is missing, wrong length, or does not match the code on file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"CONFIRM_CODE_INVALID"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"The downgrade is not allowed (insufficient capacity on the lower plan, free-tier user, or unsupported workspace/custom domain state).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DOWNGRADE_NOT_ALLOWED"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"description":"A confirmation code was already sent recently and is still valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"CONFIRM_CODE_SENT"}}}},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/account/locale":{"patch":{"operationId":"patchAccountLocale","tags":["Account"],"summary":"Update the authenticated user's interface locale","description":"Updates the locale tag used by the platform UI and outgoing email notifications. Allowed values are `pt-BR`, `en-US`, `es-ES`, `zh-CN`.\n\nRequires a session token. Limited to 4 changes per minute with a 5 minute block on the cap.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["locale"],"properties":{"locale":{"type":"string","enum":["pt-BR","en-US","es-ES","zh-CN"]}}}}}},"responses":{"200":{"description":"Locale updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"locale":{"type":"object","properties":{"old":{"type":"string"},"new":{"type":"string"}},"required":["old","new"]}},"required":["locale"]}},"required":["status","response"]},"example":{"status":"success","response":{"locale":{"old":"en-US","new":"pt-BR"}}}}}},"400":{"description":"The submitted locale is missing, unknown, or identical to the current locale.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"invalid":{"value":{"status":"error","code":"INVALID_LOCALE","message":"Locale must be one of: pt-BR, en-US, es-ES, zh-CN"}},"same":{"value":{"status":"error","code":"SAME_LOCALE"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/account/username":{"patch":{"operationId":"patchAccountUsername","tags":["Account"],"summary":"Update the authenticated user's display name","description":"Updates the display name used across the platform and the workspace membership cache.\n\nThe name must be 1-24 characters and may contain letters (including accented), numbers and single spaces between words.\n\nRequires a session token. Limited to 3 changes per 24 hours per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username"],"properties":{"username":{"type":"string","minLength":1,"maxLength":24}}}}}},"responses":{"200":{"description":"Username updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"username":{"type":"object","properties":{"old":{"type":"string"},"new":{"type":"string"}},"required":["old","new"]}},"required":["username"]}},"required":["status","response"]},"example":{"status":"success","response":{"username":{"old":"John","new":"John Doe"}}}}}},"400":{"description":"The submitted username failed validation or matches the current value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"invalid":{"value":{"status":"error","code":"INVALID_USERNAME","message":"Username must contain 1-24 characters (letters, numbers, spaces)"}},"same":{"value":{"status":"error","code":"SAME_USERNAME"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps":{"post":{"operationId":"postApps","tags":["Lifecycle","Deployments"],"summary":"Create a new application from an uploaded zip","description":"Accepts a `multipart/form-data` upload containing a single zip archive and starts the application. The response payload depends on the application language.\n\nThe caller must have at least 256 MB of available memory on their plan. Rate limited to 1 upload every 3 seconds per user.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"Zip archive containing the application source."}}}}}},"responses":{"200":{"description":"Upload accepted. The payload depends on the application language.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"lang":{"type":"string"},"ram":{"type":"integer"}},"required":["id","name","lang","ram"]}},"required":["status","response"]},"example":{"status":"success","response":{"id":"abc123def456abc123def456","name":"my-app","lang":"nodejs","ram":512}}}}},"400":{"description":"The upload was rejected by validation or storage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"no_file":{"value":{"status":"error","code":"INVALID_FILE"}},"bad_filename":{"value":{"status":"error","code":"INVALID_FILENAME"}},"few_memory":{"value":{"status":"error","code":"FEW_MEMORY"}},"upload_aborted":{"value":{"status":"error","code":"UPLOAD_ABORTED"}},"upload_failed":{"value":{"status":"error","code":"FAILED_UPLOAD_DATA","message":"Upload failed due to a third-party error. Please try again later."}},"cluster_selection":{"value":{"status":"error","code":"FAILED_CLUSTER_SELECTION"}},"empty_response":{"value":{"status":"error","code":"EMPTY_RESPONSE"}},"generic":{"value":{"status":"error","code":"FAILED_UPLOAD"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"413":{"description":"Upload exceeded the 100 MB per-file limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"FILE_TOO_LARGE"}}}},"415":{"description":"The request does not use `multipart/form-data`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_CONTENT_TYPE"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"},"503":{"description":"Application provisioning is temporarily unavailable due to maintenance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"CLUSTER_MAINTENANCE_TRY_LATER"}}}}}}},"/v2/apps/status":{"get":{"operationId":"getAppsStatus","tags":["Lifecycle"],"summary":"List runtime stats for every application","description":"Returns live runtime stats (CPU, RAM, network, uptime) for every application owned by the caller, or scoped to the workspace passed via `workspaceId`.\n\nRate limited to 15 requests per 60s per user.","parameters":[{"name":"workspaceId","in":"query","required":false,"description":"Limit the listing to applications shared in this workspace (collection endpoint only).","schema":{"type":"string","pattern":"^([a-f0-9]{40}|[a-f0-9]{12}4[a-f0-9]{3}[89ab][a-f0-9]{3}[a-f0-9]{12})$"}},{"name":"rawData","in":"query","required":false,"description":"Return the raw stats payload without post-processing.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Runtime stats for the requested scope.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"cpu":{"type":"string"},"ram":{"type":"string"},"network":{"type":"object","properties":{"total":{"type":"string"},"now":{"type":"string"}},"required":["total","now"]},"uptime":{"type":"integer"},"running":{"type":"boolean"}},"required":["cpu","ram","network","uptime","running"]}},"required":["status","response"]},"example":{"status":"success","response":{"cpu":"0.50%","ram":"120/512MB","network":{"total":"12MB","now":"0KB"},"uptime":1716000000000,"running":true}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"Application or workspace not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"app":{"value":{"status":"error","code":"APP_NOT_FOUND"}},"workspace":{"value":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps/{appId}":{"get":{"operationId":"getAppByAppId","tags":["Lifecycle"],"summary":"Get application information","description":"Returns the application's identity, plan, region, language, and DNS configuration. The response is scoped to the caller; access to workspace-shared applications is granted automatically when the caller is a member of the owning workspace.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Application metadata.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","required":["id","name","owner","cluster","ram","language","domain","custom","created_at"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"desc":{"type":"string","description":"Optional. Omitted when not set."},"owner":{"type":"string"},"cluster":{"type":"string"},"ram":{"type":"integer"},"language":{"type":"string"},"domain":{"type":["string","null"]},"custom":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}}}}},"example":{"status":"success","response":{"id":"abc123def456abc123def456","name":"my-app","owner":"1234567890","cluster":"dragon-cluster","ram":512,"language":"nodejs","domain":"my-app.squareweb.app","custom":null,"created_at":"2024-05-01T12:00:00.000Z"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"delete":{"operationId":"deleteAppByAppId","tags":["Lifecycle"],"summary":"Delete an application","description":"Removes the application, releases any custom domain, and invalidates the caller's project and workspace caches. The operation is rejected while a snapshot restore is in progress.\n\nRate limited to 1 request every 3 seconds per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Application deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"A snapshot restore is currently running for this application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RESTORE_IN_PROGRESS","message":"A restore operation is currently in progress for this app."}}}},"404":{"description":"Application not found or the delete operation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"not_found":{"value":{"status":"error","code":"APP_NOT_FOUND"}},"cluster_error":{"value":{"status":"error","code":"DELETE_ERROR"}}}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps/{appId}/commit":{"post":{"operationId":"postAppCommitByAppId","tags":["Deployments","Lifecycle"],"summary":"Upload a file or zip to an application as a commit","description":"Streams a `multipart/form-data` file to the application. A `.zip` is unpacked at the destination; other files are placed at `path/name`. The optional `path` query parameter controls the destination directory inside the application.\n\nFile names that look like path traversal, control characters, or `.`/`..` are rejected. Content-Type is derived server-side from the extension.\n\nRequires the `commit` permission when called against a workspace-shared application. Rate limits: 1 commit per 2s per user (global) and 1 commit per 5s per (user, application).","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}},{"name":"path","in":"query","required":false,"description":"Destination directory inside the application (no traversal, no shell metacharacters).","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Commit accepted and applied.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"The upload was rejected by validation or storage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"no_file":{"value":{"status":"error","code":"INVALID_FILE"}},"bad_filename":{"value":{"status":"error","code":"INVALID_FILENAME"}},"invalid_path":{"value":{"status":"error","code":"INVALID_PATH"}},"upload_aborted":{"value":{"status":"error","code":"UPLOAD_ABORTED"}},"upload_failed":{"value":{"status":"error","code":"FAILED_UPLOAD_DATA","message":"Upload failed due to a third-party error. Please try again later."}},"generic":{"value":{"status":"error","code":"COMMIT_ERROR"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"description":"Upload exceeded the 100 MB per-file limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"FILE_TOO_LARGE"}}}},"415":{"description":"Request is not `multipart/form-data`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_CONTENT_TYPE"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"commit"}},"/v2/apps/{appId}/deploy/github-app":{"delete":{"operationId":"deleteAppDeployGithubAppByAppId","tags":["Deployments"],"summary":"Unlink the GitHub App repository from an application","description":"Removes the GitHub App repository linkage created via `POST /v2/apps/:appId/deploy/github-app`. Returns 400 if no GitHub App link is configured.\n\nRequires a session token. Rate limited to 3 calls per 60s per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"GitHub App linkage removed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"The application has no GitHub App repository configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"GIT_NOT_CONFIGURED"}}}},"401":{"$ref":"#/components/responses/SessionRequired"},"404":{"description":"The application does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"APP_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"post":{"operationId":"postAppDeployGithubAppByAppId","tags":["Deployments"],"summary":"Link a GitHub repository via the Square Cloud GitHub App","description":"Associates the application with a GitHub repository + branch installed through the Square Cloud GitHub App. The branch must be ≤256 chars and the (repository, branch) pair must not already be linked to another application owned by the caller.\n\nRequires a session token. Rate limited to 3 calls per 60s per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["repositoryName","repositoryBranch"],"properties":{"repositoryName":{"type":"string","description":"Full repository name (e.g. `octocat/hello-world`)."},"repositoryBranch":{"type":"string","maxLength":256}}}}}},"responses":{"200":{"description":"Repository linked.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"repository":{"type":"object","properties":{"id":{"type":"integer"},"full_name":{"type":"string"},"branch":{"type":"string"}},"required":["id","full_name","branch"]}},"required":["repository"]}},"required":["status","response"]},"example":{"status":"success","response":{"repository":{"id":1234567,"full_name":"octocat/hello-world","branch":"main"}}}}}},"400":{"description":"The request failed validation or the application already has a Git repository configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"missing":{"value":{"status":"error","code":"MISSING_REQUIRED_FIELDS","message":"repositoryName and repositoryBranch are required"}},"branch_too_long":{"value":{"status":"error","code":"INVALID_BRANCH_LENGTH","message":"Branch name is too long. Max 256 characters"}},"already":{"value":{"status":"error","code":"GIT_ALREADY_CONFIGURED"}}}}}},"401":{"$ref":"#/components/responses/SessionRequired"},"404":{"description":"The application does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"APP_NOT_FOUND"}}}},"409":{"description":"Another application already links the same (repository, branch) pair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"REPOSITORY_BRANCH_ALREADY_CONFIGURED","message":"This repository + branch combination is already configured on another app (abc123)"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"description":"Repository validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"VALIDATION_FAILED","message":"Failed to validate repository"}}}}}}},"/v2/apps/{appId}/deploy/webhook":{"post":{"operationId":"postAppDeployWebhookByAppId","tags":["Deployments"],"summary":"Configure or remove the Git deploy webhook","description":"Configures the application to deploy on push from a Git provider. Passing `access_token: \"@\"` removes the webhook; passing a GitHub personal access token (`ghp_*` / `github_pat_*`) enrolls the application and returns its webhook URL.\n\nRequires the `configure_deploy_webhook` permission when called against a workspace-shared application. Rate limited to 5 calls per 60s per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["access_token"],"properties":{"access_token":{"type":"string","description":"GitHub personal access token (`ghp_*` / `github_pat_*`), or `@` to remove the existing webhook."}}}}}},"responses":{"200":{"description":"Webhook configured (with `response.webhook`) or removed.","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","required":["webhook"],"properties":{"webhook":{"type":"string","format":"uri"}},"description":"Present when configuring; absent when removing."}}},"examples":{"configured":{"value":{"status":"success","response":{"webhook":"https://api.squarecloud.app/v2/git/webhook/0123456789abcdef..."}}},"removed":{"value":{"status":"success"}}}}}},"400":{"description":"`access_token` does not match the accepted format.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_ACCESS_TOKEN"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"configure_deploy_webhook"}},"/v2/apps/{appId}/deployments":{"get":{"operationId":"getAppDeploymentsByAppId","tags":["Deployments"],"summary":"List recent deploys for an application","description":"Returns the deploy log for the application (timestamps, source, success/failure). Empty array when no deploys have been recorded.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Recent deploys.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string"},"date":{"type":"string","format":"date-time"},"source":{"type":"string"}},"required":["id","state","date","source"]}}},"required":["status","response"]},"example":{"status":"success","response":[{"id":"deploy_abc","state":"success","date":"2025-12-01T12:00:00.000Z","source":"git"}]}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps/{appId}/deployments/current":{"get":{"operationId":"getAppDeploymentsCurrentByAppId","tags":["Deployments"],"summary":"Get current Git deploy configuration","description":"Returns the GitHub App repository linkage and the deploy webhook URL configured for the application. The response is cached for 5 minutes per (owner, application).\n\nRequires the `view_deployment_info` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Current Git deploy configuration. Either `app` (GitHub App), `webhook`, or both may be present.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"app":{"type":"object","required":["id","name","branch"],"properties":{"id":{"type":["integer","null"]},"name":{"type":["string","null"]},"branch":{"type":["string","null"]}}},"webhook":{"type":"string","format":"uri"}}}}},"example":{"status":"success","response":{"app":{"id":1234567,"name":"octocat/hello-world","branch":"main"},"webhook":"https://api.squarecloud.app/v2/git/webhook/0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"view_deployment_info"}},"/v2/apps/{appId}/envs":{"delete":{"operationId":"deleteAppEnvsByAppId","tags":["Environment Variables"],"summary":"Remove specific environment variables","description":"Removes the given keys from the application's environment variables. Unknown keys are silently ignored.\n\nRequires the `manage_envs` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["envs"],"properties":{"envs":{"type":"array","items":{"type":"string","maxLength":1024},"description":"Variable names to remove."}}}}}},"responses":{"200":{"description":"Remaining environment variables after removal.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","additionalProperties":{"type":"string"}}}},"example":{"status":"success","response":{"DATABASE_URL":"postgres://localhost"}}}}},"400":{"description":"The request failed validation or the environment variables could not be persisted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"static":{"value":{"status":"error","code":"STATIC_APP_ENV_NOT_SUPPORTED","message":"Static apps do not support environment variables."}},"invalid":{"value":{"status":"error","code":"INVALID_ENV_CONTENT"}},"name_too_long":{"value":{"status":"error","code":"ENV_NAME_TOO_LONG"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_envs"},"get":{"operationId":"getAppEnvsByAppId","tags":["Environment Variables"],"summary":"Get the application's environment variables","description":"Returns the application's environment variables as a `{ key: value }` JSON object. Static applications do not support environment variables and return 400.\n\nRequires the `manage_envs` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Environment variables as a `{ key: value }` map.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","additionalProperties":{"type":"string"}}}},"example":{"status":"success","response":{"DATABASE_URL":"postgres://localhost","API_KEY":"secret"}}}}},"400":{"description":"The application is static, or the environment variables could not be loaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"static":{"value":{"status":"error","code":"STATIC_APP_ENV_NOT_SUPPORTED","message":"Static apps do not support environment variables."}},"cluster_error":{"value":{"status":"error","code":"FAILED_READ"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_envs"},"post":{"operationId":"postAppEnvsByAppId","tags":["Environment Variables"],"summary":"Merge new environment variables into the existing set","description":"Adds or updates environment variables. Existing variables not present in the request body are preserved. Up to 256 variables per application; each key max 1024 chars; each value max 4096 chars.\n\nRequires the `manage_envs` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["envs"],"properties":{"envs":{"type":"object","additionalProperties":{"type":"string"},"description":"Variables to merge into the existing set."}}}}}},"responses":{"200":{"description":"Updated environment variables.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","additionalProperties":{"type":"string"}}}},"example":{"status":"success","response":{"DATABASE_URL":"postgres://localhost","API_KEY":"secret"}}}}},"400":{"description":"The request failed validation or the environment variables could not be persisted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"static":{"value":{"status":"error","code":"STATIC_APP_ENV_NOT_SUPPORTED","message":"Static apps do not support environment variables."}},"invalid":{"value":{"status":"error","code":"INVALID_ENV_CONTENT"}},"too_many":{"value":{"status":"error","code":"TOO_MANY_ENV_VARS","message":"You can only have up to 256 environment variables."}},"name_too_long":{"value":{"status":"error","code":"ENV_NAME_TOO_LONG"}},"content_too_long":{"value":{"status":"error","code":"ENV_CONTENT_TOO_LONG"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_envs"},"put":{"operationId":"putAppEnvsByAppId","tags":["Environment Variables"],"summary":"Replace the entire set of environment variables","description":"Replaces the application's environment variables with exactly the set provided in the request body. Variables not listed are removed; pass an empty object to wipe all of them.\n\nLimits: up to 256 variables, each key max 1024 chars, each value max 4096 chars.\n\nRequires the `manage_envs` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["envs"],"properties":{"envs":{"type":"object","additionalProperties":{"type":"string"},"description":"Complete env set. Replaces all existing variables."}}}}}},"responses":{"200":{"description":"Environment variables replaced.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","additionalProperties":{"type":"string"}}}},"example":{"status":"success","response":{"DATABASE_URL":"postgres://localhost"}}}}},"400":{"description":"The request failed validation or the environment variables could not be persisted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"static":{"value":{"status":"error","code":"STATIC_APP_ENV_NOT_SUPPORTED","message":"Static apps do not support environment variables."}},"invalid":{"value":{"status":"error","code":"INVALID_ENV_CONTENT"}},"too_many":{"value":{"status":"error","code":"TOO_MANY_ENV_VARS","message":"You can only have up to 256 environment variables."}},"name_too_long":{"value":{"status":"error","code":"ENV_NAME_TOO_LONG"}},"content_too_long":{"value":{"status":"error","code":"ENV_CONTENT_TOO_LONG"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_envs"}},"/v2/apps/{appId}/files":{"put":{"operationId":"putAppFilesByAppId","tags":["File Manager"],"summary":"Create or replace a file in an application","description":"Writes the provided content to the given path. Writes to `squarecloud.app` / `squarecloud.config` are parsed as platform config (display name, description, memory, autorestart, subdomain) and trigger plan/quota validation.\n\nWorkspace members without `access_restricted_files` cannot write `.env`, `.env.production`, `squarecloud.app`, or `squarecloud.config`.\n\nRequires the `manage_files` permission when called against a workspace-shared application. Config rewrites are rate limited to 1 request every 15 seconds per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["path","content"],"properties":{"path":{"type":"string","description":"Absolute path to write inside the application."},"content":{"type":"string","format":"byte","description":"File content as a base64 or Buffer-compatible payload."}}}}}},"responses":{"200":{"description":"File written. The underlying write response is passed through in `response`.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"written":{"type":"boolean"}},"required":["written"]}},"required":["status","response"]},"example":{"status":"success","response":{"written":true}}}}},"400":{"description":"The path or content failed validation, or a parsed config field was rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"invalid_content":{"value":{"status":"error","code":"INVALID_CONTENT"}},"invalid_path":{"value":{"status":"error","code":"INVALID_PATH"}},"invalid_display_name":{"value":{"status":"error","code":"INVALID_DISPLAY_NAME"}},"invalid_description":{"value":{"status":"error","code":"INVALID_DESCRIPTION"}},"invalid_memory":{"value":{"status":"error","code":"INVALID_MEMORY"}},"invalid_autorestart":{"value":{"status":"error","code":"INVALID_AUTORESTART"}},"invalid_subdomain":{"value":{"status":"error","code":"INVALID_SUBDOMAIN"}},"cannot_set_subdomain":{"value":{"status":"error","code":"CAN_NOT_SET_SUBDOMAIN"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"The workspace member cannot write a restricted file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"BLOCKED_PATH","message":"This route is blocked based on your workspace settings permissions."}}}},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"description":"Config rewrite cooldown is active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"KEEP_CALM"}}}},"500":{"description":"Persisting the parsed config update failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"FAILED_TO_SAVE"}}}}},"x-workspace-permission":"manage_files"},"delete":{"operationId":"deleteAppFilesByAppId","tags":["File Manager"],"summary":"Delete a file from an application","description":"Removes the file at the given `path`.\n\nWorkspace members without `access_restricted_files` cannot delete `.env`, `.env.production`, `squarecloud.app`, or `squarecloud.config` — the 403 returned in that case has the same code (`PERMISSION_DENIED`) as the generic workspace-permission denial.\n\nRequires the `manage_files` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["path"],"properties":{"path":{"type":"string","description":"Absolute path of the file to delete."}}}}}},"responses":{"200":{"description":"File deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"Path validation failed or the file could not be deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"invalid":{"value":{"status":"error","code":"INVALID_PATH"}},"cluster_error":{"value":{"status":"error","code":"FAILED_DELETE"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_files"},"get":{"operationId":"getAppFilesByAppId","tags":["File Manager"],"summary":"List files in an application directory","description":"Lists files and directories at the requested `path`. Defaults to the application root when no `path` is given.\n\nWorkspace members without `access_restricted_files` cannot see `.env` and `.env.production` entries.\n\nRequires the `manage_files` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}},{"name":"path","in":"query","required":false,"description":"Directory inside the application to list. Defaults to `/`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Directory listing.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"size":{"type":"integer"},"lastModified":{"type":"string","format":"date-time"}},"required":["name","type","size","lastModified"]}}},"required":["status","response"]},"example":{"status":"success","response":[{"name":"index.js","type":"file","size":1024,"lastModified":"2025-12-01T12:00:00.000Z"},{"name":"node_modules","type":"directory","size":0,"lastModified":"2025-12-01T12:00:00.000Z"}]}}}},"400":{"description":"Path validation failed or the directory could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"invalid":{"value":{"status":"error","code":"INVALID_PATH"}},"blocked":{"value":{"status":"error","code":"BLOCKED_PATH"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_files"},"patch":{"operationId":"patchAppFilesByAppId","tags":["File Manager"],"summary":"Rename or move a file within an application","description":"Renames the file at `path` to `to`. Both paths must be valid and distinct.\n\nWorkspace members without `access_restricted_files` cannot rename `.env`, `.env.production`, `squarecloud.app`, or `squarecloud.config` — the 403 returned in that case has the same code (`PERMISSION_DENIED`) as the generic workspace-permission denial.\n\nRequires the `manage_files` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["path","to"],"properties":{"path":{"type":"string","description":"Absolute path of the source file."},"to":{"type":"string","description":"Absolute path of the destination file."}}}}}},"responses":{"200":{"description":"File renamed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"Path validation failed or the rename operation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"invalid":{"value":{"status":"error","code":"INVALID_PATH"}},"same":{"value":{"status":"error","code":"INVALID_PATH"}},"cluster_error":{"value":{"status":"error","code":"FAILED_RENAME"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_files"}},"/v2/apps/{appId}/files/content":{"get":{"operationId":"getAppFilesContentByAppId","tags":["File Manager"],"summary":"Read a file from an application","description":"Returns the file at the given `path` as a JSON object `{ type: \"Buffer\", data: number[] }` where `data` is the raw byte array. Clients reconstruct the file by reading the `data` array.\n\nWorkspace members without `access_restricted_files` cannot read `.env` and `.env.production`.\n\nRequires the `manage_files` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}},{"name":"path","in":"query","required":true,"description":"Absolute path to the file inside the application.","schema":{"type":"string"}}],"responses":{"200":{"description":"File content as a byte-array JSON object.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","required":["type","data"],"properties":{"type":{"type":"string","const":"Buffer"},"data":{"type":"array","items":{"type":"integer","minimum":0,"maximum":255},"description":"File bytes as integers in [0, 255]."}}}}},"example":{"status":"success","response":{"type":"Buffer","data":[99,111,110,115,116,32,120]}}}}},"400":{"description":"Path validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_PATH"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"The file does not exist at the given path.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"FILE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_files"}},"/v2/apps/{appId}/logs":{"get":{"operationId":"getAppLogsByAppId","tags":["Lifecycle"],"summary":"Get the most recent application logs","description":"Fetches the application's stdout/stderr buffer from its cluster. The buffer is short-lived; for streaming logs, use the realtime endpoint instead.\n\nRate limited to 1 request per 3s per (user, application).","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Concatenated log buffer.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"logs":{"type":"string"}},"required":["logs"]}},"required":["status","response"]},"example":{"status":"success","response":{"logs":"Server listening on :3000\nRequest received\n"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"Cluster could not return logs (application offline, not deployed yet, or transient error).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps/{appId}/metrics":{"get":{"operationId":"getAppMetricsByAppId","tags":["Lifecycle"],"summary":"Get the last 24h of application metrics","description":"Returns up to 288 points (24h sampled every 5 minutes) of CPU, RAM and network usage. Cached for 2.5 minutes per (owner, application).\n\nAvailable only for applications with at least 512 MB of RAM. Rate limited to 10 requests per 5s per user, with a 60s block on the cap.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Array of metric points. Empty array when the application has no recent data.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date-time"},"cpu":{"type":"number"},"ram":{"type":"number"},"net":{"type":"array","items":{"type":"integer"}}},"required":["date","cpu","ram","net"]}}},"required":["status","response"]},"example":{"status":"success","response":[{"date":"2025-12-01T12:00:00.000Z","cpu":0.5,"ram":120.4,"net":[0,0]}]}}}},"400":{"description":"The application has less than 512 MB of RAM and cannot collect metrics.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_APP"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps/{appId}/network/analytics":{"get":{"operationId":"getAppNetworkAnalyticsByAppId","tags":["Network"],"summary":"Get edge analytics for the application's domains","description":"Returns aggregated edge analytics (requests, bandwidth, status codes, etc.) for the application's primary domain and any configured custom domain. Maximum retention window is 7 days.\n\nUse `start`/`end` (ISO timestamps) for a custom window, or `range=weekly` for the last 168 hours. Defaults to the last 24 hours.\n\nResults are cached per bucket; on cache miss rate-limited to 10 calls per 60s per owner.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}},{"name":"start","in":"query","required":false,"description":"ISO 8601 start timestamp.","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","required":false,"description":"ISO 8601 end timestamp.","schema":{"type":"string","format":"date-time"}},{"name":"range","in":"query","required":false,"description":"Preset window. Currently supports `weekly` (last 168h).","schema":{"type":"string","enum":["weekly"]}}],"responses":{"200":{"description":"Aggregated analytics. Empty object when the requested window is before the application's creation date.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"requests":{"type":"object","properties":{"total":{"type":"integer"}},"required":["total"]},"bandwidth":{"type":"object","properties":{"total":{"type":"integer"}},"required":["total"]}},"required":["requests","bandwidth"]}},"required":["status","response"]},"example":{"status":"success","response":{"requests":{"total":12345},"bandwidth":{"total":67890}}}}}},"400":{"description":"`start`/`end` are missing, malformed, or invert the time range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_TIME_RANGE"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"description":"Cache miss rate limit exceeded (10 per 60s per owner).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RATE_LIMIT_EXCEEDED"}}}},"500":{"description":"Failed to fetch analytics from the edge provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNABLE_TO_FETCH_ANALYTICS"}}}}}}},"/v2/apps/{appId}/network/custom":{"post":{"operationId":"postAppNetworkCustomByAppId","tags":["Network"],"summary":"Set or remove the application's custom domain","description":"Sets or removes the application's custom domain. Pass `custom: \"@\"` to remove the existing custom domain. Replacing an existing domain releases the previous one before attaching the new one.\n\nAvailable only on Standard, Pro, and Enterprise plans. The new domain must be a fully qualified domain name and not already attached to another application.\n\nRequires the `manage_custom_domain` permission when called against a workspace-shared application. Rate limited to 10 changes per 5 minutes per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["custom"],"properties":{"custom":{"type":"string","description":"Fully qualified domain to attach, or `@` to remove."}}}}}},"responses":{"200":{"description":"Custom domain set or removed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"Domain did not match the validation regex.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"REGEX_VALIDATION"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"The active plan does not include custom domains. Upgrade to Standard, Pro, or Enterprise.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UPGRADE_REQUIRED","message":"Custom domains are available for Standard, Pro, and Enterprise plans only."}}}},"404":{"$ref":"#/components/responses/AppNotFound"},"409":{"description":"The domain is already attached to another application.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DOMAIN_ALREADY_EXISTS"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"},"502":{"description":"Domain attachment failed at the edge provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DNS_FAILED"}}}}},"x-workspace-permission":"manage_custom_domain"}},"/v2/apps/{appId}/network/dns":{"get":{"operationId":"getAppNetworkDnsByAppId","tags":["Network"],"summary":"Get the DNS records required to attach the custom domain","description":"Returns the DNS records that the user must configure on their domain registrar so the edge provider can validate ownership and issue SSL. Cached for 30s per (owner, application).\n\nRequires a custom domain to be attached. Requires the `manage_dns` permission when called against a workspace-shared application. Rate limited to 3 calls per 10s per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"DNS records the user must configure plus the current SSL status.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"ownership":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"},"value":{"type":"string"}},"required":["type","name","value"]},"ssl":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]}},"required":["ownership","ssl"]}},"required":["status","response"]},"example":{"status":"success","response":{"ownership":{"type":"TXT","name":"_validation.example.com","value":"abc123..."},"ssl":{"status":"pending_validation"}}}}}},"400":{"description":"The application does not have a custom domain attached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"NO_CUSTOM_DOMAIN"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_dns"}},"/v2/apps/{appId}/network/logs":{"get":{"operationId":"getAppNetworkLogsByAppId","tags":["Network"],"summary":"Get per-request edge logs for the application's domains","description":"Returns per-request edge logs (HTTP, country, status, bytes) for the application's primary domain and any configured custom domain.\n\nRequires both `start` and `end` ISO timestamps. Maximum retention window is 7 days; the start is clamped to the application's creation date.\n\nResults cached per bucket; on cache miss rate-limited to 10 calls per 60s per owner. Available only on Pro and Enterprise plans.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}},{"name":"start","in":"query","required":true,"description":"ISO 8601 start timestamp.","schema":{"type":"string","format":"date-time"}},{"name":"end","in":"query","required":true,"description":"ISO 8601 end timestamp.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Per-request edge log entries.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","required":["timestamp","client","request","response"],"properties":{"timestamp":{"type":"string","format":"date-time"},"client":{"type":"object","required":["ip","country","location","asn","agent","category"],"properties":{"ip":{"type":["string","null"]},"country":{"type":["string","null"]},"location":{"type":["string","null"]},"asn":{"type":"string"},"agent":{"type":["string","null"]},"category":{"type":["string","null"]}}},"request":{"type":"object","required":["mitigated","method","host","path","query","protocol","referer"],"properties":{"mitigated":{"type":"boolean"},"method":{"type":"string"},"host":{"type":"string"},"path":{"type":"string"},"query":{"type":["string","null"]},"protocol":{"type":"string"},"referer":{"type":["string","null"]}}},"response":{"type":"object","required":["status","contentType","cache"],"properties":{"status":{"type":"integer"},"contentType":{"type":["string","null"]},"cache":{"type":["string","null"]}}}}}}}},"example":{"status":"success","response":[{"timestamp":"2025-12-01T12:00:00.000Z","client":{"ip":"203.0.113.45","country":"BR","location":"São Paulo","asn":"12345 - Example ISP","agent":"Mozilla/5.0","category":null},"request":{"mitigated":false,"method":"GET","host":"my-app.squareweb.app","path":"/api/users","query":"?limit=10","protocol":"HTTP/2","referer":null},"response":{"status":200,"contentType":"application/json","cache":"MISS"}}]}}}},"400":{"description":"`start`/`end` are missing, malformed, or invert the time range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_TIME_RANGE","message":"Start and end dates are required."}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"The active plan does not include analytics logs. Upgrade to Pro or Enterprise.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UPGRADE_REQUIRED","message":"Analytics logs are available for Pro and Enterprise plans only."}}}},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"description":"Cache miss rate limit exceeded (10 per 60s per owner).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RATE_LIMIT_EXCEEDED"}}}},"500":{"description":"Failed to fetch logs from the edge provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNABLE_TO_FETCH_ANALYTICS"}}}}}}},"/v2/apps/{appId}/network/purge_cache":{"post":{"operationId":"postAppNetworkPurgeCacheByAppId","tags":["Network"],"summary":"Purge the edge cache for the application's domains","description":"Purges the cached responses held at the edge for the application's primary domain and any configured custom domain.\n\nRequires the `purge_cache` permission when called against a workspace-shared application. Rate limited to 1 request per 60s per owner.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Cache purge submitted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"description":"Edge cache purge failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error"}}}}},"x-workspace-permission":"purge_cache"}},"/v2/apps/{appId}/realtime":{"get":{"operationId":"getAppRealtimeByAppId","tags":["Lifecycle"],"summary":"Open a Server-Sent Events stream of realtime application events","description":"Opens an SSE connection that proxies the application cluster's realtime feed (deploy progress, status changes, log lines) for up to 10 minutes per connection. Each user is limited to 10 concurrent realtime connections.\n\nThe stream emits `system` events for protocol-level signals (`REALTIME_CONNECTING`, `REALTIME_TIMEOUT`, `REALTIME_DISCONNECTED`, `REALTIME_RECONNECT`, `REALTIME_ERROR`) and `message` events with the cluster's payload.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"SSE stream established. Content type is `text/event-stream`.","content":{"text/event-stream":{"example":"event: system\ndata: REALTIME_CONNECTING | abc123-1716000000000-deadbeef\n\nevent: message\ndata: {\"status\":\"running\"}\n\n"}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"description":"The user already has 10 concurrent realtime connections open.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"REALTIME_MAX_CONNECTIONS","message":"The maximum number of realtime connections (10) for this account has been reached."}}}},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps/{appId}/restart":{"post":{"operationId":"postAppRestartByAppId","tags":["Lifecycle"],"summary":"Restart an application","description":"Restarts an application — equivalent to stop+start, performed atomically.\n\nRequires the `control_app_actions` permission when called against a workspace-shared application. Rate limited to 1 restart per 3s per app and to 20 actions per 15s per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Action dispatched. Payload reflects the underlying operation result.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"409":{"description":"The action was rejected (application already running/stopped, mid-deploy, etc).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"ACTION_FAILED"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"control_app_actions"}},"/v2/apps/{appId}/snapshots":{"get":{"operationId":"getAppSnapshotsByAppId","tags":["Snapshots"],"summary":"List snapshots for an application","description":"Lists the application's stored snapshots. The result is cached for 15 minutes per (owner, application).\n\nRequires the `manage_snapshots` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Snapshot list for the application.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","required":["name","size","modified","key"],"properties":{"name":{"type":"string","description":"Snapshot identifier (zip name without extension)."},"size":{"type":"integer","description":"Snapshot size in bytes."},"modified":{"type":"string","format":"date-time"},"key":{"type":"string","description":"Signed query string for the snapshot download URL."}}}}}},"example":{"status":"success","response":[{"name":"abc123","size":12345678,"modified":"2025-12-01T00:00:00.000Z","key":"AWSAccessKeyId=...&Expires=...&Signature=...&versionId=..."}]}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_snapshots"},"post":{"operationId":"postAppSnapshotsByAppId","tags":["Snapshots"],"summary":"Create a new snapshot of an application","description":"Captures a snapshot of the application and returns a signed download URL valid for 30 days.\n\nRate limits: 1 snapshot per 5s per user, 1 snapshot per 60s per application, and the plan's daily snapshot quota per owner.\n\nRequires the `manage_snapshots` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Snapshot created. The `url` is a signed download URL valid for 30 days.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"key":{"type":"string"}},"required":["url","key"]}},"required":["status","response"]},"example":{"status":"success","response":{"url":"https://snapshots.squarecloud.app/...","key":"<signed-query-string>"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Cluster snapshot failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"SNAPSHOT_FAILED"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_snapshots"}},"/v2/apps/{appId}/snapshots/restore":{"post":{"operationId":"postAppSnapshotsRestoreByAppId","tags":["Snapshots"],"summary":"Restore an application snapshot","description":"Restores the application to a previous snapshot identified by `snapshotId` (UUID v4) and `versionId` (snapshot version identifier from the snapshot listing).\n\nRate limits: 1 restore per 60s per user (`snapshot:restore`) and 1 restore per 120s per application (`snapshot:restore:<appId>`).\n\nRequires the `manage_snapshots` permission when called against a workspace-shared application.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["snapshotId","versionId"],"properties":{"snapshotId":{"type":"string","format":"uuid"},"versionId":{"type":"string","pattern":"^[A-Za-z0-9+/=_-]{24,96}$"}}}}}},"responses":{"200":{"description":"Restore dispatched.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"One of `snapshotId` or `versionId` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"missing":{"value":{"status":"error","code":"MISSING_PARAMETERS"}},"invalid_snapshot":{"value":{"status":"error","code":"INVALID_SNAPSHOT_ID"}},"invalid_version":{"value":{"status":"error","code":"INVALID_VERSION_ID"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Snapshot not found or the restore could not be dispatched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"snapshot":{"value":{"status":"error","code":"SNAPSHOT_NOT_FOUND"}},"cluster":{"value":{"status":"error","code":"SNAPSHOT_RESTORE_FAILED"}}}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"manage_snapshots"}},"/v2/apps/{appId}/start":{"post":{"operationId":"postAppStartByAppId","tags":["Lifecycle"],"summary":"Start an application","description":"Starts a stopped application. No-op if the application is already running.\n\nRequires the `control_app_actions` permission when called against a workspace-shared application. Rate limited to 1 start per 3s per app and to 20 actions per 15s per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Action dispatched. Payload reflects the underlying operation result.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"409":{"description":"The action was rejected (application already running/stopped, mid-deploy, etc).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"ACTION_FAILED"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"control_app_actions"}},"/v2/apps/{appId}/status":{"get":{"operationId":"getAppStatusByAppId","tags":["Lifecycle"],"summary":"Get runtime stats for an application","description":"Returns live runtime stats (CPU, RAM, network, uptime) for a single application. Append `?rawData=true` to skip post-processing.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}},{"name":"workspaceId","in":"query","required":false,"description":"Limit the listing to applications shared in this workspace (collection endpoint only).","schema":{"type":"string","pattern":"^([a-f0-9]{40}|[a-f0-9]{12}4[a-f0-9]{3}[89ab][a-f0-9]{3}[a-f0-9]{12})$"}},{"name":"rawData","in":"query","required":false,"description":"Return the raw stats payload without post-processing.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Runtime stats for the requested scope.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"cpu":{"type":"string"},"ram":{"type":"string"},"network":{"type":"object","properties":{"total":{"type":"string"},"now":{"type":"string"}},"required":["total","now"]},"uptime":{"type":"integer"},"running":{"type":"boolean"}},"required":["cpu","ram","network","uptime","running"]}},"required":["status","response"]},"example":{"status":"success","response":{"cpu":"0.50%","ram":"120/512MB","network":{"total":"12MB","now":"0KB"},"uptime":1716000000000,"running":true}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"Application or workspace not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"app":{"value":{"status":"error","code":"APP_NOT_FOUND"}},"workspace":{"value":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/apps/{appId}/stop":{"post":{"operationId":"postAppStopByAppId","tags":["Lifecycle"],"summary":"Stop an application","description":"Stops a running application. No-op if the application is already stopped.\n\nRequires the `control_app_actions` permission when called against a workspace-shared application. Rate limited to 1 stop per 3s per app and to 20 actions per 15s per user.","parameters":[{"name":"appId","in":"path","required":true,"description":"Application identifier. Optionally suffixed with -<workspaceId> to act on a workspace-shared application.","schema":{"type":"string","pattern":"^[a-f0-9]{24}(?:-[a-f0-9-]+)?$"}}],"responses":{"200":{"description":"Action dispatched. Payload reflects the underlying operation result.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"$ref":"#/components/responses/AppNotFound"},"409":{"description":"The action was rejected (application already running/stopped, mid-deploy, etc).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"ACTION_FAILED"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"x-workspace-permission":"control_app_actions"}},"/v2/databases":{"post":{"operationId":"postDatabases","tags":["DB Lifecycle"],"summary":"Create a new database","description":"Provisions a database (MongoDB, MySQL, Redis, Postgres, etc.), allocates a public DNS record (`square-cloud-db-<id>.squareweb.app`) pointing to it, and returns the connection URL once.\n\nAvailable only on Standard, Pro, and Enterprise plans. Memory must be at least the minimum required by the database type and not exceed the caller's available memory.\n\nRate limited to 1 creation every 3 seconds per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","memory","type","version"],"properties":{"name":{"type":"string","minLength":1,"maxLength":32,"description":"Display name (1-32 chars, letters/numbers/space/hyphen/underscore)."},"memory":{"type":"integer","description":"Allocated memory in MB."},"type":{"type":"string","description":"Database type (e.g. `mongodb`, `mysql`, `redis`)."},"version":{"type":"string","description":"Version key supported for the chosen type."}}}}}},"responses":{"200":{"description":"Database created. The returned `password` and `certificate` are shown only once — store them securely.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"memory":{"type":"integer"},"cpu":{"type":"number"},"type":{"type":"string"},"password":{"type":"string"},"certificate":{"type":"string"},"connection_url":{"type":"string"},"cluster":{"type":"string"}},"required":["id","name","memory","cpu","type","password","certificate","connection_url","cluster"]}},"required":["status","response"]},"example":{"status":"success","response":{"id":"abc123def456abc123def456","name":"my-db","memory":512,"cpu":0.5,"type":"mongodb","password":"<one-time secret>","certificate":"<base64 PEM, when applicable>","connection_url":"mongodb://user:<password>@square-cloud-db-abc123.squareweb.app:27017","cluster":"dragon-cluster"}}}}},"400":{"description":"The request failed input validation, the user has insufficient memory, or the database could not be provisioned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"name":{"value":{"status":"error","code":"NAME_INVALID"}},"bad_type":{"value":{"status":"error","code":"DATABASE_TYPE_INVALID"}},"bad_version":{"value":{"status":"error","code":"DATABASE_VERSION_INVALID"}},"few_memory":{"value":{"status":"error","code":"FEW_MEMORY"}},"cluster":{"value":{"status":"error","code":"FAILED_CLUSTER_SELECTION"}},"creation":{"value":{"status":"error","code":"FAILED_DATABASE_CREATION"}},"dns":{"value":{"status":"error","code":"FAILED_DATABASE_CREATION","message":"Failed to create DNS record for the database."}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"The active plan does not include databases. Upgrade to Standard, Pro, or Enterprise.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UPGRADE_REQUIRED","message":"Database hosting is available for Standard, Pro, and Enterprise plans only."}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"description":"Provisioning returned an incomplete response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"FAILED_DATABASE_CREATION","message":"Incomplete database creation response. Can you try again?"}}}},"503":{"description":"Database provisioning is temporarily unavailable due to maintenance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"CLUSTER_MAINTENANCE_TRY_LATER"}}}}}}},"/v2/databases/status":{"get":{"operationId":"getDatabasesStatus","tags":["DB Lifecycle"],"summary":"List runtime stats for every database","description":"Returns live runtime stats (CPU, RAM, network, uptime) for every database owned by the caller.\n\nRate limited to 15 requests per 60s per user.","parameters":[{"name":"rawData","in":"query","required":false,"description":"Return the raw stats payload without post-processing.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Runtime stats for the requested scope.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"cpu":{"type":"string"},"ram":{"type":"string"},"network":{"type":"object","properties":{"total":{"type":"string"},"now":{"type":"string"}},"required":["total","now"]},"uptime":{"type":"integer"},"running":{"type":"boolean"}},"required":["cpu","ram","network","uptime","running"]}},"required":["status","response"]},"example":{"status":"success","response":{"cpu":"0.50%","ram":"120/512MB","network":{"total":"12MB","now":"0KB"},"uptime":1716000000000,"running":true}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/databases/{databaseId}":{"delete":{"operationId":"deleteDatabaseByDatabaseId","tags":["DB Lifecycle"],"summary":"Delete a database","description":"Removes the database and releases the public DNS record. Rejected while a snapshot restore is in progress.\n\nRate limited to 1 deletion every 3 seconds per user.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Database deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"A snapshot restore is currently in progress for this database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RESTORE_IN_PROGRESS","message":"A restore operation is currently in progress for this database."}}}},"404":{"description":"The database does not exist, is not owned by the caller, or the delete operation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"not_found":{"value":{"status":"error","code":"DATABASE_NOT_FOUND"}},"cluster_error":{"value":{"status":"error","code":"DELETE_ERROR"}}}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"get":{"operationId":"getDatabaseByDatabaseId","tags":["DB Lifecycle"],"summary":"Get database information","description":"Returns the database identity, region, type, allocated memory, and connection port.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Database metadata.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"owner":{"type":"string"},"cluster":{"type":"string"},"ram":{"type":"integer"},"type":{"type":"string"},"port":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}},"required":["id","name","owner","cluster","ram","type","port","created_at"]}},"required":["status","response"]},"example":{"status":"success","response":{"id":"abc123def456abc123def456","name":"my-db","owner":"1234567890","cluster":"dragon-cluster","ram":512,"type":"mongodb","port":27017,"created_at":"2024-05-01T12:00:00.000Z"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"patch":{"operationId":"patchDatabaseByDatabaseId","tags":["DB Lifecycle"],"summary":"Update a database's name or memory","description":"Updates the database's display name or allocated memory. At least one of `name` or `ram` must be present in the request body.\n\nRate limited to 1 update every 5 seconds per user.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":32,"description":"Display name (1-32 chars, letters/numbers/space/hyphen/underscore)."},"ram":{"type":"integer","description":"Allocated memory in MB."}}}}}},"responses":{"200":{"description":"Database updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"No fields were provided, or the new value failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"empty":{"value":{"status":"error","code":"NO_UPDATE_DATA","message":"No data provided for update."}},"name":{"value":{"status":"error","code":"NAME_INVALID"}},"memory":{"value":{"status":"error","code":"MEMORY_INVALID"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"description":"Cluster memory update failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INTERNAL_ERROR"}}}}}}},"/v2/databases/{databaseId}/credentials/certificate":{"get":{"operationId":"getDatabaseCredentialsCertificateByDatabaseId","tags":["Credentials"],"summary":"Download the TLS certificate for the database","description":"Returns the TLS certificate used by the database, base64-encoded. The database must be running.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Base64-encoded TLS certificate (PEM).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"certificate":{"type":"string"}},"required":["certificate"]}},"required":["status","response"]},"example":{"status":"success","response":{"certificate":"LS0tLS1CRUdJTi..."}}}}},"400":{"description":"Database is not running, or the certificate could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"not_running":{"value":{"status":"error","code":"DATABASE_NOT_RUNNING"}},"cluster_error":{"value":{"status":"error","code":"FAILED_READ"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/databases/{databaseId}/credentials/reset":{"post":{"operationId":"postDatabaseCredentialsResetByDatabaseId","tags":["Credentials"],"summary":"Reset the database password or TLS certificate","description":"Rotates either the access password or the TLS certificate of the database. The database must be running.\n\nResetting `password` returns the new password once; resetting `certificate` returns success and the new certificate is fetched separately via `/credentials/certificate`.\n\nRate limited to 1 reset every 3 seconds per user.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reset"],"properties":{"reset":{"type":"string","enum":["certificate","password"]}}}}}},"responses":{"200":{"description":"Reset completed.","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","required":["password"],"properties":{"password":{"type":"string","description":"Shown only once for password resets."}},"description":"Present when `reset: password`; absent when `reset: certificate`."}}},"examples":{"password":{"value":{"status":"success","response":{"password":"<one-time secret>"}}},"certificate":{"value":{"status":"success"}}}}}},"400":{"description":"Invalid reset type or the database is not running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"invalid":{"value":{"status":"error","code":"INVALID_RESET_TYPE"}},"not_running":{"value":{"status":"error","code":"DATABASE_NOT_RUNNING"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"description":"The credential rotation was rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"FAILED_RESET"}}}}}}},"/v2/databases/{databaseId}/metrics":{"get":{"operationId":"getDatabaseMetricsByDatabaseId","tags":["DB Lifecycle"],"summary":"Get the last 24h of database metrics","description":"Returns up to 288 points (24h sampled every 5 minutes) of CPU, RAM and network usage for the database. Cached for 2.5 minutes per (user, database).\n\nRate limited to 10 requests per 5s per user, with a 60s block on the cap.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Array of metric points. Empty when the database has no recent data.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date-time"},"cpu":{"type":"number"},"ram":{"type":"number"},"net":{"type":"array","items":{"type":"integer"}}},"required":["date","cpu","ram","net"]}}},"required":["status","response"]},"example":{"status":"success","response":[{"date":"2025-12-01T12:00:00.000Z","cpu":0.5,"ram":120.4,"net":[0,0]}]}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/databases/{databaseId}/snapshots":{"get":{"operationId":"getDatabaseSnapshotsByDatabaseId","tags":["Database Snapshots"],"summary":"List snapshots for a database","description":"Lists the stored snapshots for the given database. Cached for 15 minutes per (user, database).","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Snapshot list.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","required":["name","size","modified","key"],"properties":{"name":{"type":"string","description":"Snapshot identifier (zip name without extension)."},"size":{"type":"integer","description":"Snapshot size in bytes."},"modified":{"type":"string","format":"date-time"},"key":{"type":"string","description":"Signed query string for the snapshot download URL."}}}}}},"example":{"status":"success","response":[{"name":"abc123_mongodb","size":12345678,"modified":"2025-12-01T00:00:00.000Z","key":"AWSAccessKeyId=...&Expires=...&Signature=...&versionId=..."}]}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"post":{"operationId":"postDatabaseSnapshotsByDatabaseId","tags":["Database Snapshots"],"summary":"Create a new snapshot of a database","description":"Captures a snapshot of the database and returns a signed download URL valid for 30 days.\n\nRate limits: 1 snapshot per 5s per user, 1 snapshot per 60s per database, and the plan's daily snapshot quota per user.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Snapshot created. The `url` is a signed download URL valid for 30 days.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"key":{"type":"string"}},"required":["url","key"]}},"required":["status","response"]},"example":{"status":"success","response":{"url":"https://snapshots.squarecloud.app/...","key":"<signed-query-string>"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database is not owned by the caller, or the snapshot could not be captured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"database":{"value":{"status":"error","code":"DATABASE_NOT_FOUND"}},"cluster":{"value":{"status":"error","code":"SNAPSHOT_FAILED"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/databases/{databaseId}/snapshots/restore":{"post":{"operationId":"postDatabaseSnapshotsRestoreByDatabaseId","tags":["Database Snapshots"],"summary":"Restore a database from a snapshot","description":"Restores the database from a previous snapshot identified by `snapshotId` and `versionId`. The snapshot's database type must match the target database type (the `mongodb`/`mongo` pair is accepted as compatible).\n\nRate limits: 1 restore per 60s per user (`snapshot:restore`) and 1 restore per 120s per database (`snapshot:restore:<databaseId>`).","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["snapshotId","versionId"],"properties":{"snapshotId":{"type":"string","description":"Snapshot identifier (UUID v4, optionally suffixed with `_<type>`)."},"versionId":{"type":"string","pattern":"^[A-Za-z0-9+/=_-]{24,96}$"}}}}}},"responses":{"200":{"description":"Restore dispatched.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"Snapshot restore input validation failed or the snapshot type does not match the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"missing":{"value":{"status":"error","code":"MISSING_PARAMETERS"}},"invalid_snapshot":{"value":{"status":"error","code":"INVALID_SNAPSHOT_ID"}},"invalid_version":{"value":{"status":"error","code":"INVALID_VERSION_ID"}},"mismatch":{"value":{"status":"error","code":"SNAPSHOT_DATABASE_MISMATCH"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The snapshot does not exist, the database is not owned by the caller, or the restore was rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"snapshot":{"value":{"status":"error","code":"SNAPSHOT_NOT_FOUND"}},"database":{"value":{"status":"error","code":"DATABASE_NOT_FOUND"}},"cluster":{"value":{"status":"error","code":"SNAPSHOT_RESTORE_FAILED"}}}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/databases/{databaseId}/start":{"post":{"operationId":"postDatabaseStartByDatabaseId","tags":["DB Lifecycle"],"summary":"Start a database","description":"Starts a stopped database. Rejected while a snapshot restore is in progress. Rate limited to 1 start per 3s per user.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Action dispatched. Payload reflects the underlying operation result.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"A snapshot restore is currently in progress for this database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RESTORE_IN_PROGRESS","message":"A restore operation is currently in progress for this database."}}}},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/databases/{databaseId}/status":{"get":{"operationId":"getDatabaseStatusByDatabaseId","tags":["DB Lifecycle"],"summary":"Get runtime stats for a database","description":"Returns live runtime stats (CPU, RAM, network, uptime) for a single database. Append `?rawData=true` to skip post-processing.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}},{"name":"rawData","in":"query","required":false,"description":"Return the raw stats payload without post-processing.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Runtime stats for the requested scope.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"cpu":{"type":"string"},"ram":{"type":"string"},"network":{"type":"object","properties":{"total":{"type":"string"},"now":{"type":"string"}},"required":["total","now"]},"uptime":{"type":"integer"},"running":{"type":"boolean"}},"required":["cpu","ram","network","uptime","running"]}},"required":["status","response"]},"example":{"status":"success","response":{"cpu":"0.50%","ram":"120/512MB","network":{"total":"12MB","now":"0KB"},"uptime":1716000000000,"running":true}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/databases/{databaseId}/stop":{"post":{"operationId":"postDatabaseStopByDatabaseId","tags":["DB Lifecycle"],"summary":"Stop a database","description":"Stops a running database. Rejected while a snapshot restore is in progress. Rate limited to 1 stop per 3s per user.","parameters":[{"name":"databaseId","in":"path","required":true,"description":"Database identifier.","schema":{"type":"string","pattern":"^[a-f0-9]{24}$"}}],"responses":{"200":{"description":"Action dispatched. Payload reflects the underlying operation result.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"A snapshot restore is currently in progress for this database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RESTORE_IN_PROGRESS","message":"A restore operation is currently in progress for this database."}}}},"404":{"description":"The database does not exist or is not owned by the caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"DATABASE_NOT_FOUND"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/git/webhook/{webhook}":{"post":{"operationId":"postGitWebhookByWebhook","tags":["Webhooks"],"summary":"Receive a Git provider push webhook","description":"Public endpoint that receives a `push` event from a Git provider (typically GitHub). The webhook token in the URL path (`:webhook`) authenticates the call; no Authorization header is sent.\n\nAccepts `application/json` only. The optional `branch` query parameter filters which branch triggers a deploy — if present and `body.ref` does not match `refs/heads/<branch>`, the request is accepted with 202 but no deploy is queued. The optional `restart` query parameter (`?restart=false`) skips the post-deploy application restart.\n\nResponses are `text/plain`. Rate limited to 1 push per 15 seconds per webhook token.","parameters":[{"name":"webhook","in":"path","required":true,"description":"Per-application Git webhook token (64 hex chars).","schema":{"type":"string","pattern":"^[a-f0-9]{64}$"}},{"name":"branch","in":"query","required":false,"description":"Lowercase branch name (≤256 chars). When provided, only matching pushes trigger a deploy.","schema":{"type":"string","maxLength":256}},{"name":"restart","in":"query","required":false,"description":"Pass `false` to skip the post-deploy application restart.","schema":{"type":"string","enum":["true","false"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["repository","ref"],"properties":{"repository":{"type":"object","required":["clone_url"],"properties":{"clone_url":{"type":"string"}}},"ref":{"type":"string","description":"`refs/heads/<branch>` for push events."}},"additionalProperties":true}}}},"responses":{"200":{"description":"Webhook received and the deploy job was queued.","content":{"text/plain":{"example":"Request received! Your deployment will be processed shortly."}}},"202":{"description":"Accepted but ignored because the pushed branch does not match the configured `branch`.","content":{"text/plain":{"example":"Branch name does not match."}}},"400":{"description":"Payload validation failed.","content":{"text/plain":{"examples":{"missing_id":{"value":"OOOPS! This webhook ID does not exist or missing data."},"invalid_id":{"value":"OOOPS! This webhook ID format is invalid."},"no_repository":{"value":"OOOPS! Missing repository data."},"no_ref":{"value":"OOOPS! Missing 'ref' data."},"branch_long":{"value":"Branch name is too long. Max 256 characters."}}}}},"404":{"description":"Webhook ID is not associated with any application.","content":{"text/plain":{"example":"OOOPS! This webhook ID does not exist or is not valid."}}},"415":{"description":"Content-Type is not `application/json`.","content":{"text/plain":{"example":"OOOPS! Invalid Content-Type. Use application/json instead."}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}},"security":[],"x-webhook":true}},"/v2/openapi.json":{"get":{"operationId":"getOpenapi.json","tags":["Service"],"summary":"Get the OpenAPI 3.1 schema for this API","description":"Returns the auto-generated OpenAPI 3.1 schema describing every public endpoint, parameter, request body and response shape. The schema is frozen at boot time and served as a pre-encoded UTF-8 buffer.","responses":{"200":{"description":"OpenAPI 3.1 document for this API.","content":{"application/json":{"schema":{"type":"object","description":"OpenAPI 3.1 document."}}}},"304":{"description":"The cached copy held by the client is still current."},"500":{"$ref":"#/components/responses/InternalServerError"}},"security":[]}},"/v2/service/status":{"get":{"operationId":"getServiceStatus","tags":["Service"],"summary":"Get the aggregate platform status","description":"Returns the latest cached status of the Square Cloud platform. The payload mirrors the public status page and is intended for lightweight health probes and dashboards.","responses":{"200":{"description":"Current status payload. Shape may include status, message, components, or incidents.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"message":{"type":"string"}},"required":["status","message"]},"example":{"status":"operational","message":"All systems are operating normally."}}}},"500":{"$ref":"#/components/responses/InternalServerError"}},"security":[]}},"/v2/users/me":{"get":{"operationId":"getUsersMe","tags":["Account"],"summary":"Get the authenticated user's profile and resources","description":"Returns the authenticated user, the memory allocated to their plan, and the aggregate list of applications and databases they own. The response is scoped to the caller; there is no path parameter to target another user.","responses":{"200":{"description":"User profile, plan, memory budget, and the user's applications and databases.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","required":["user","applications","databases"],"properties":{"user":{"type":"object","required":["id","name","email","locale","plan","created_at"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string","format":"email"},"locale":{"type":"string"},"plan":{"type":"object","required":["name","memory","duration"],"properties":{"name":{"type":"string"},"memory":{"type":"object","required":["available","total"],"properties":{"available":{"type":"integer"},"total":{"type":"integer"}}},"duration":{"type":"integer"}}},"created_at":{"type":"string","format":"date-time"}}},"applications":{"type":"array","items":{"type":"object","required":["id","name","ram","lang","domain","custom","cluster","created_at"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"desc":{"type":"string","description":"Optional. Omitted when not set."},"ram":{"type":"integer"},"lang":{"type":"string"},"domain":{"type":["string","null"]},"custom":{"type":["string","null"]},"cluster":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}},"databases":{"type":"array","items":{"type":"object","required":["id","name","ram","type","cluster","created_at"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"ram":{"type":"integer"},"type":{"type":"string"},"cluster":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}}}},"example":{"status":"success","response":{"user":{"id":"1234567890","name":"John Doe","email":"john@example.com","locale":"en-US","plan":{"name":"pro","memory":{"available":4096,"total":8192},"duration":2592000},"created_at":"2024-05-01T12:00:00.000Z"},"applications":[{"id":"abc123def456abc123def456","name":"my-app","ram":512,"lang":"nodejs","domain":"my-app.squareweb.app","custom":null,"cluster":"dragon-cluster","created_at":"2024-05-01T12:00:00.000Z"}],"databases":[{"id":"db_abc123def456abc123def4","name":"my-db","ram":256,"type":"mongodb","cluster":"dragon-cluster","created_at":"2024-05-01T12:00:00.000Z"}]}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/users/snapshots":{"get":{"operationId":"getUsersSnapshots","tags":["Snapshots"],"summary":"List the authenticated user's snapshots","description":"Lists application or database snapshots owned by the authenticated user. The result is cached for 30 minutes; on cache miss the endpoint enforces a stricter rate limit (3 calls per 60s, blocking 5 minutes) and requires a paid plan.\n\nUse the `scope` query parameter to switch between `applications` (default) and `databases`.","parameters":[{"name":"scope","in":"query","required":false,"description":"Snapshot domain to list. Defaults to `applications`.","schema":{"type":"string","enum":["applications","databases"]}}],"responses":{"200":{"description":"Snapshot list for the requested scope.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","required":["name","size","modified","key"],"properties":{"name":{"type":"string","description":"Snapshot identifier (zip name without extension)."},"size":{"type":"integer","description":"Snapshot size in bytes."},"modified":{"type":"string","format":"date-time"},"key":{"type":"string","description":"Signed query string for the snapshot download URL."}}}}}},"example":{"status":"success","response":[{"name":"abc123","size":12345678,"modified":"2025-12-01T00:00:00.000Z","key":"AWSAccessKeyId=...&Expires=...&Signature=...&versionId=..."}]}}}},"400":{"description":"The `scope` query parameter is not one of the allowed values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INVALID_SCOPE"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"402":{"description":"Listing snapshots requires a paid subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"SUBSCRIPTION_REQUIRED"}}}},"429":{"description":"The user exceeded the cache-miss rate limit (3 calls per 60s).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"RATE_LIMIT_EXCEEDED"}}}},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/workspaces":{"post":{"operationId":"postWorkspaces","tags":["Workspaces"],"summary":"Create a new workspace","description":"Creates a workspace owned by the authenticated user. Available only on Standard, Pro, and Enterprise plans, up to the plan's maximum workspace count.\n\nThe name must be 1-32 characters (letters, numbers, space, hyphen, or underscore). Rate limited to 1 creation every 10s per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":32}}}}}},"responses":{"200":{"description":"Workspace created.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}},"required":["status","response"]},"example":{"status":"success","response":{"id":"abcdef0123456789abcdef0123456789abcdef01","name":"Acme"}}}}},"400":{"description":"The name failed validation, the workspace quota was reached, or the workspace could not be created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"name":{"value":{"status":"error","code":"NAME_INVALID"}},"limit":{"value":{"status":"error","code":"WORKSPACE_LIMIT_REACHED"}},"creation":{"value":{"status":"error","code":"FAILED_WORKSPACE_CREATION"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"403":{"description":"The active plan does not include workspaces. Upgrade to Standard, Pro, or Enterprise.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UPGRADE_REQUIRED"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"delete":{"operationId":"deleteWorkspaces","tags":["Workspaces"],"summary":"Delete a workspace owned by the authenticated user","description":"Deletes the workspace identified by `workspaceId`. Only the owner can delete a workspace.\n\nRate limited to 1 deletion every 10 seconds per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspaceId"],"properties":{"workspaceId":{"type":"string"}}}}}},"responses":{"200":{"description":"Workspace deleted.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"The user is not the owner or the delete operation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error"}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The `workspaceId` body field is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"get":{"operationId":"getWorkspaces","tags":["Workspaces"],"summary":"List workspaces the authenticated user owns or belongs to","description":"Returns every workspace where the authenticated user is either the owner or a member, hydrated with members and shared applications.","responses":{"200":{"description":"Workspace list. Empty array when the user has no workspaces.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"array","items":{"type":"object","required":["id","name","owner","members","applications","createdAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"owner":{"type":"string"},"members":{"type":"array","items":{"type":"object","required":["id","name","group"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"group":{"type":"string"}}}},"applications":{"type":"array","items":{"type":"object","required":["id","name","desc","ram","lang","domain","custom"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"desc":{"type":["string","null"]},"ram":{"type":"integer"},"lang":{"type":"string"},"domain":{"type":["string","null"]},"custom":{"type":["string","null"]}}}},"createdAt":{"type":"string","format":"date-time"}}}}}},"example":{"status":"success","response":[{"id":"abcdef0123456789abcdef0123456789abcdef01","name":"Acme","owner":"1234567890","members":[{"id":"1234567890","name":"John Doe","group":"owner"}],"applications":[{"id":"abc123def456abc123def456","name":"my-app","desc":null,"ram":512,"lang":"nodejs","domain":"my-app.squareweb.app","custom":null}],"createdAt":"2025-12-01T00:00:00.000Z"}]}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/workspaces/applications":{"post":{"operationId":"postWorkspacesApplications","tags":["Workspaces"],"summary":"Share an application into a workspace","description":"Adds an application owned by the authenticated user to a workspace they own. Up to 100 applications per workspace. The same application cannot be shared twice.\n\nRate limited to 10 additions per 30s per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspaceId","appId"],"properties":{"workspaceId":{"type":"string"},"appId":{"type":"string","pattern":"^[a-f0-9]{24}$"}}}}}},"responses":{"200":{"description":"Application shared into the workspace.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"Application limit reached or already shared into this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"already":{"value":{"status":"error","code":"APP_ALREADY_IN_WORKSPACE"}},"limit":{"value":{"status":"error","code":"MAX_APPLICATIONS_REACHED"}},"missing_app":{"value":{"status":"error","code":"APP_NOT_FOUND"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"Workspace or application not found, or the caller is not the workspace owner.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"workspace":{"value":{"status":"error","code":"UNKNOWN_WORKSPACE"}},"app":{"value":{"status":"error","code":"APP_NOT_FOUND"}}}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"delete":{"operationId":"deleteWorkspacesApplications","tags":["Workspaces"],"summary":"Remove a shared application from a workspace","description":"Unshares an application from a workspace. Only the workspace owner can remove a shared application.\n\nRate limited to 10 removals per 30s per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspaceId","appId"],"properties":{"workspaceId":{"type":"string"},"appId":{"type":"string","pattern":"^[a-f0-9]{24}$"}}}}}},"responses":{"200":{"description":"Application removed from the workspace.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"App ID missing, app is not in the workspace, or the remove operation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"missing":{"value":{"status":"error","code":"APP_NOT_FOUND"}},"generic":{"value":{"status":"error"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"Workspace ID missing or workspace does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/workspaces/leave":{"delete":{"operationId":"deleteWorkspacesLeave","tags":["Workspaces"],"summary":"Leave a workspace the authenticated user belongs to","description":"Removes the authenticated user from the workspace's member list. The owner cannot leave their own workspace — use `DELETE /v2/workspaces` to delete it instead.\n\nRate limited to 1 leave every 5 seconds per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspaceId"],"properties":{"workspaceId":{"type":"string"}}}}}},"responses":{"200":{"description":"Membership removed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"The `workspaceId` is missing or the caller is the workspace owner.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"missing":{"value":{"status":"error","code":"ID_INVALID"}},"owner":{"value":{"status":"error","code":"CANNOT_LEAVE_OWNER"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The workspace does not exist or the caller is not a member.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/workspaces/members":{"post":{"operationId":"postWorkspacesMembers","tags":["Workspaces"],"summary":"Add a member to a workspace using an invite code","description":"Adds a member to the workspace using a short-lived invite code generated by `GET /v2/workspaces/members/code`. The invited user is identified by the user ID embedded in the code; the caller specifies the member's role (`view`, `manager`, `maintain`, `admin`).\n\nUp to the plan's per-workspace member cap. The workspace owner cannot be invited to their own workspace.\n\nRate limited to 1 addition every 5s per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspaceId","code","group"],"properties":{"workspaceId":{"type":"string"},"code":{"type":"string","description":"Invite code (UUID v4 without hyphens) from `/v2/workspaces/members/code`."},"group":{"type":"string","enum":["view","manager","maintain","admin"]}}}}}},"responses":{"200":{"description":"Member added.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"The invite code is invalid, the role is invalid, the workspace's member quota has been reached, or the member is already in the workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"code":{"value":{"status":"error","code":"CODE_INVALID"}},"owner":{"value":{"status":"error","code":"CANNOT_INVITE_OWNER"}},"group":{"value":{"status":"error","code":"INVALID_GROUP"}},"max":{"value":{"status":"error","code":"MAX_MEMBERS_REACHED"}},"duplicate":{"value":{"status":"error","code":"MEMBER_ALREADY_ADDED"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The workspace does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"patch":{"operationId":"patchWorkspacesMembers","tags":["Workspaces"],"summary":"Change a member's role in a workspace","description":"Changes the role of an existing workspace member. Allowed roles: `view`, `manager`, `maintain`, `admin`. The workspace owner cannot edit themselves.\n\nRate limited to 3 edits per 15 seconds per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspaceId","memberId","group"],"properties":{"workspaceId":{"type":"string"},"memberId":{"type":"string"},"group":{"type":"string","enum":["view","manager","maintain","admin"]}}}}}},"responses":{"200":{"description":"Member role updated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"The member does not belong to the workspace, the role is invalid, or the caller tried to edit themselves.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"member":{"value":{"status":"error","code":"UNKNOWN_MEMBER"}},"owner":{"value":{"status":"error","code":"CANNOT_EDIT_OWNER"}},"group":{"value":{"status":"error","code":"INVALID_GROUP"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The workspace does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"delete":{"operationId":"deleteWorkspacesMembers","tags":["Workspaces"],"summary":"Remove a member from a workspace","description":"Removes a member from a workspace. Only the workspace owner can call this endpoint.\n\nRate limited to 5 removals per 30s per user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["workspaceId","memberId"],"properties":{"workspaceId":{"type":"string"},"memberId":{"type":"string"}}}}}},"responses":{"200":{"description":"Member removed.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"}},"required":["status"]},"example":{"status":"success"}}}},"400":{"description":"The `memberId` is missing or the workspace write failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"examples":{"member":{"value":{"status":"error","code":"UNKNOWN_MEMBER"}},"generic":{"value":{"status":"error"}}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The `workspaceId` body field is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/v2/workspaces/members/code":{"get":{"operationId":"getWorkspacesMembersCode","tags":["Workspaces"],"summary":"Generate an invite code for the authenticated user","description":"Generates a short-lived (5 minutes) invite code bound to the authenticated user's identity. A workspace owner can then call `POST /v2/workspaces/members` with this code to add the user as a member.\n\nRate limited to 1 code every 5 minutes per user.","responses":{"200":{"description":"Invite code generated.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","properties":{"code":{"type":"string"}},"required":["code"]}},"required":["status","response"]},"example":{"status":"success","response":{"code":"abcdef0123456789abcdef0123456789"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"description":"Persisting the code in cache failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"INTERNAL_SERVER_ERROR"}}}}}}},"/v2/workspaces/{workspaceId}":{"get":{"operationId":"getWorkspaceByWorkspaceId","tags":["Workspaces"],"summary":"Get a single workspace","description":"Returns the workspace identified by `workspaceId`. The authenticated user must be the owner or a member.\n\nRate limited to 30 requests per 60s per user.","parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace identifier (40 hex chars or a UUIDv4 without hyphens).","schema":{"type":"string","pattern":"^([a-f0-9]{40}|[a-f0-9]{12}4[a-f0-9]{3}[89ab][a-f0-9]{3}[a-f0-9]{12})$"}}],"responses":{"200":{"description":"Workspace details.","content":{"application/json":{"schema":{"type":"object","required":["status","response"],"properties":{"status":{"type":"string","const":"success"},"response":{"type":"object","required":["id","name","owner","members","applications","createdAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"owner":{"type":"string"},"members":{"type":"array","items":{"type":"object","required":["id","name","group"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"group":{"type":"string"}}}},"applications":{"type":"array","items":{"type":"object","required":["id","name","desc","ram","lang","domain","custom"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"desc":{"type":["string","null"]},"ram":{"type":"integer"},"lang":{"type":"string"},"domain":{"type":["string","null"]},"custom":{"type":["string","null"]}}}},"createdAt":{"type":"string","format":"date-time"}}}}},"example":{"status":"success","response":{"id":"abcdef0123456789abcdef0123456789abcdef01","name":"Acme","owner":"1234567890","members":[{"id":"1234567890","name":"John Doe","group":"owner"}],"applications":[{"id":"abc123def456abc123def456","name":"my-app","desc":null,"ram":512,"lang":"nodejs","domain":"my-app.squareweb.app","custom":null}],"createdAt":"2025-12-01T00:00:00.000Z"}}}}},"401":{"$ref":"#/components/responses/AccessDenied"},"404":{"description":"The workspace does not exist or the caller is not a member.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"},"example":{"status":"error","code":"UNKNOWN_WORKSPACE"}}}},"429":{"$ref":"#/components/responses/RateLimitedSpecific"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}