From 85cf3ef816244618501d0ec3a0c3413c0d6533ef Mon Sep 17 00:00:00 2001 From: jae beller Date: Fri, 9 Oct 2026 12:08:33 -0400 Subject: [PATCH] Sort OpenAPI fields --- api/openapi.json | 1960 +++++++++++++++++++++++----------------------- 1 file changed, 980 insertions(+), 980 deletions(-) diff --git a/api/openapi.json b/api/openapi.json index 1f5cef7..b886dcc 100644 --- a/api/openapi.json +++ b/api/openapi.json @@ -1,8 +1,55 @@ { "components": { "schemas": { - "OAuthCallbackRequest": { - "description": "OAuth callback request", + "AccessPolicy": { + "description": "Connector access policy", + "properties": { + "allow_all": { + "description": "When true, all sprites in the organization may use this connector.", + "example": false, + "type": "boolean" + }, + "allowed_endpoints": { + "description": "Provider API paths the connector may call. Supports exact paths and trailing `*` prefix wildcards.", + "example": [ + "/chat.*" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "blocked_endpoints": { + "description": "Provider API paths the connector may not call. Block rules are checked before allow rules.", + "example": [ + "/admin.*" + ], + "items": { + "type": "string" + }, + "type": "array" + }, + "name_prefix": { + "description": "Sprite name prefix required to use this connector.", + "example": "prod-", + "type": "string" + }, + "sprite_labels": { + "description": "Labels the calling sprite must have. All listed labels are required.", + "example": [ + "api-access" + ], + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [], + "type": "object" + }, + "ApiKeyConnectionRequest": { + "description": "API-key connector request", "properties": { "access_policy": { "$ref": "#/components/schemas/AccessPolicy", @@ -11,46 +58,105 @@ "allow_all": true } }, - "code": { - "description": "Authorization code returned by the provider.", - "example": "oauth-code", + "api_key": { + "description": "Provider API key. Stored encrypted and never returned by the API.", + "example": "sk-or-...", "type": "string" }, - "redirect_uri": { - "description": "Redirect URI used to create the authorization URL.", - "example": "https://api.sprites.dev/v1/oauth/slack/callback", + "base_api_url": { + "description": "Required for Upstash Redis: immutable HTTPS database REST URL. Not used by fixed-host providers.", + "example": "https://your-database.upstash.io", "type": "string" }, - "state": { - "description": "State value from the authorize response.", - "example": "opaque-state", + "provider": { + "description": "API-key provider.", + "example": "openrouter", "type": "string" } }, "required": [ - "code" + "provider", + "api_key" ], "type": "object" }, - "CopyResponse": { + "CheckpointInfo": { + "example": { + "comment": "Before database migration", + "create_time": "2026-01-05T10:30:00Z", + "id": "v7" + }, "properties": { - "copied": { + "comment": { + "description": "User-provided description", + "type": "string" + }, + "create_time": { + "description": "When the checkpoint was created", + "format": "date-time", + "type": "string" + }, + "health": { + "description": "Health status (empty = healthy, \"mount_failed\" = unhealthy)", + "type": "string" + }, + "id": { + "description": "Checkpoint identifier (e.g., `v7`)", + "type": "string" + }, + "source_id": { + "description": "Parent checkpoint ID", + "type": "string" + } + }, + "required": [ + "id", + "create_time" + ], + "type": "object" + }, + "ChmodRequest": { + "properties": { + "asRoot": { + "type": "boolean" + }, + "mode": { + "type": "string" + }, + "path": { + "type": "string" + }, + "recursive": { + "type": "boolean" + }, + "workingDir": { + "type": "string" + } + }, + "required": [ + "path", + "workingDir", + "mode", + "recursive", + "asRoot" + ], + "type": "object" + }, + "ChmodResponse": { + "properties": { + "affected": { "items": { - "$ref": "#/components/schemas/CopyResult" + "$ref": "#/components/schemas/ChmodResult" }, "type": "array" }, "count": { "type": "integer" - }, - "totalBytes": { - "type": "integer" } }, "required": [ - "copied", - "count", - "totalBytes" + "affected", + "count" ], "type": "object" }, @@ -69,235 +175,298 @@ ], "type": "object" }, - "StreamCompleteEvent": { - "example": { - "data": "Checkpoint v3 created successfully", - "time": "2026-01-05T10:30:00Z", - "type": "complete" - }, + "ChownRequest": { "properties": { - "data": { - "description": "Completion message", - "type": "string" + "asRoot": { + "type": "boolean" }, - "time": { - "description": "Timestamp", - "format": "date-time", + "gid": { + "type": "object" + }, + "path": { "type": "string" }, - "type": { - "const": "complete", + "recursive": { + "type": "boolean" + }, + "uid": { + "type": "object" + }, + "workingDir": { "type": "string" } }, "required": [ - "type", - "data", - "time" + "path", + "workingDir", + "uid", + "gid", + "recursive", + "asRoot" ], "type": "object" }, - "ServiceLogCompleteEvent": { - "example": { - "log_files": { - "combined": "/.sprite/logs/services/webapp.log", - "stderr": "/.sprite/logs/services/webapp.log", - "stdout": "/.sprite/logs/services/webapp.log" - }, - "timestamp": 1767609000000, - "type": "complete" - }, + "ChownResponse": { "properties": { - "timestamp": { - "description": "Unix milliseconds", - "type": "integer" + "affected": { + "items": { + "$ref": "#/components/schemas/ChownResult" + }, + "type": "array" }, - "type": { - "const": "complete", - "type": "string" + "count": { + "type": "integer" } }, "required": [ - "type", - "timestamp" + "affected", + "count" ], "type": "object" }, - "ExecKillCompleteEvent": { - "example": { - "exit_code": 0, - "type": "complete" - }, + "ChownResult": { "properties": { - "exit_code": { - "description": "Process exit code", + "gid": { "type": "integer" }, - "type": { - "const": "complete", + "path": { "type": "string" + }, + "uid": { + "type": "integer" } }, "required": [ - "type", - "exit_code" + "path", + "uid", + "gid" ], "type": "object" }, - "ServiceRequest": { - "example": { - "args": [ - "-m", - "http.server", - "8000" - ], - "cmd": "python", - "http_port": 8000, - "needs": [ - "postgres" - ] - }, + "Connection": { + "description": "Connector", "properties": { - "args": { - "description": "Command arguments", - "items": { - "type": "string" - }, - "type": "array" - }, - "cmd": { - "description": "Command to execute", - "type": "string" + "access_policy": { + "$ref": "#/components/schemas/AccessPolicy", + "description": "Policy controlling which sprites and provider endpoints may use this connector.", + "example": { + "allow_all": true, + "allowed_endpoints": [ + "/*" + ] + } }, - "dir": { - "description": "Working directory for the service", + "connection_type": { + "description": "How the connector was created.", + "enum": [ + "oauth", + "api_key", + "provisioned", + "internal" + ], + "example": "oauth", "type": "string" }, - "env": { - "description": "Environment variables to add to the base service environment", - "type": "object" + "id": { + "description": "Connector ID used in gateway URLs.", + "example": "conn_abc123", + "type": "string" }, - "http_port": { - "description": "HTTP port for proxy routing", - "type": [ - "integer", - "null" - ] + "inserted_at": { + "description": "When the connector was created.", + "example": "2026-04-28T12:00:00Z", + "format": "date-time", + "type": "string" }, - "needs": { - "description": "Service dependencies (started first)", + "notes": { + "description": "Provider notes about this connection, derived from its saved settings. Each has a nullable `title` and a `body`; backticks mark inline code.", + "example": [ + { + "body": "Full-access key.", + "title": null + } + ], "items": { - "type": "string" + "type": "object" }, "type": "array" + }, + "provider": { + "description": "Provider key. See https://fly.io/sprites/ecosystem/ for current connectors.", + "example": "slack", + "type": "string" + }, + "provider_account_id": { + "description": "Provider account, workspace, or key identifier.", + "example": "T12345", + "type": "string" + }, + "provider_account_name": { + "description": "Human-readable provider account name.", + "example": "Example Workspace", + "type": "string" + }, + "provider_info": { + "description": "Provider-specific metadata such as workspace URLs, custom API base URLs, or icon references.", + "example": { + "team_domain": "example" + }, + "type": "object" + }, + "scopes": { + "description": "Comma-separated OAuth scopes granted to the connector.", + "example": "chat:write,channels:read", + "type": "string" + }, + "token_expires_at": { + "description": "When the stored token expires, if the provider issues expiring tokens.", + "example": "2026-04-29T12:00:00Z", + "format": "date-time", + "type": "string" + }, + "updated_at": { + "description": "When the connector was last updated.", + "example": "2026-04-29T12:00:00Z", + "format": "date-time", + "type": "string" + }, + "usage_snippet": { + "description": "Provider-specific curl snippet showing how to call the connector through the gateway.", + "example": "curl https://api.sprites.dev/v1/gateway/slack/conn_abc123/auth.test", + "type": "string" + }, + "user_id": { + "description": "Sprites user ID that created or owns the connector.", + "example": "user_abc123", + "type": "string" } }, "required": [ - "cmd", - "args", - "needs" + "id", + "provider", + "provider_account_id" ], "type": "object" }, - "ServiceLogStdoutEvent": { - "example": { - "data": "Server listening on port 3000\n", - "timestamp": 1767609000000, - "type": "stdout" - }, + "ConnectionListResponse": { + "description": "Connector list response", "properties": { - "data": { - "description": "Log line content", - "type": "string" - }, - "timestamp": { - "description": "Unix milliseconds", - "type": "integer" - }, - "type": { - "const": "stdout", - "type": "string" + "connections": { + "description": "Connectors configured for the organization.", + "example": [ + { + "id": "conn_abc123", + "provider": "slack" + } + ], + "items": { + "$ref": "#/components/schemas/Connection" + }, + "type": "array" } }, "required": [ - "type", - "data", - "timestamp" + "connections" ], "type": "object" }, - "UpdateSpriteRequest": { - "description": "Update sprite request", + "ConnectionResponse": { + "description": "Connector response", "properties": { - "url_settings": { - "$ref": "#/components/schemas/UrlSettingsRequest", - "description": "URL access configuration to update", + "connection": { + "$ref": "#/components/schemas/Connection", + "description": "Sanitized connector. Secrets and encrypted token fields are never returned.", "example": { - "auth": "public" + "id": "conn_abc123", + "provider": "slack" } } }, "required": [ - "url_settings" + "connection" ], "type": "object" }, - "ServiceState": { - "example": { - "name": "webapp", - "pid": 1567, - "started_at": "2026-01-05T08:01:00Z", - "status": "running" - }, + "CopyRequest": { "properties": { - "error": { - "description": "Error message if failed", - "type": "string" + "asRoot": { + "type": "boolean" }, - "name": { - "description": "Service name", + "dest": { "type": "string" }, - "pid": { - "description": "Process ID when running", - "type": "integer" + "preserveAttrs": { + "type": "boolean" }, - "started_at": { - "description": "ISO 8601 timestamp", + "recursive": { + "type": "boolean" + }, + "source": { "type": "string" }, - "status": { - "description": "`stopped`, `starting`, `running`, `stopping`, or `failed`", + "workingDir": { "type": "string" } }, "required": [ - "name", - "status" + "source", + "dest", + "workingDir", + "recursive", + "preserveAttrs", + "asRoot" ], "type": "object" }, - "UpdateConnectionRequest": { - "description": "Update connector request", + "CopyResponse": { "properties": { - "access_policy": { - "$ref": "#/components/schemas/AccessPolicy", - "description": "Replacement access policy.", - "example": { - "sprite_labels": [ - "api-access" - ], - "allowed_endpoints": [ - "/chat.*" - ] - } + "copied": { + "items": { + "$ref": "#/components/schemas/CopyResult" + }, + "type": "array" + }, + "count": { + "type": "integer" + }, + "totalBytes": { + "type": "integer" } }, "required": [ - "access_policy" + "copied", + "count", + "totalBytes" + ], + "type": "object" + }, + "CopyResult": { + "properties": { + "dest": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "required": [ + "source", + "dest" ], "type": "object" }, + "CreateCheckpointRequest": { + "example": { + "comment": "Before deploying v2.0" + }, + "properties": { + "comment": { + "type": "string" + } + }, + "required": [], + "type": "object" + }, "CreateSpriteRequest": { "description": "Create sprite request", "properties": { @@ -319,92 +488,7 @@ ], "type": "object" }, - "ServiceLogErrorEvent": { - "example": { - "data": "Failed to start service: command not found", - "timestamp": 1767609000000, - "type": "error" - }, - "properties": { - "data": { - "description": "Error message", - "type": "string" - }, - "timestamp": { - "description": "Unix milliseconds", - "type": "integer" - }, - "type": { - "const": "error", - "type": "string" - } - }, - "required": [ - "type", - "data", - "timestamp" - ], - "type": "object" - }, - "ServiceLogExitEvent": { - "example": { - "exit_code": 0, - "timestamp": 1767609000000, - "type": "exit" - }, - "properties": { - "exit_code": { - "description": "Process exit code", - "type": "integer" - }, - "timestamp": { - "description": "Unix milliseconds", - "type": "integer" - }, - "type": { - "const": "exit", - "type": "string" - } - }, - "required": [ - "type", - "exit_code", - "timestamp" - ], - "type": "object" - }, - "ChownRequest": { - "properties": { - "asRoot": { - "type": "boolean" - }, - "gid": { - "type": "object" - }, - "path": { - "type": "string" - }, - "recursive": { - "type": "boolean" - }, - "uid": { - "type": "object" - }, - "workingDir": { - "type": "string" - } - }, - "required": [ - "path", - "workingDir", - "uid", - "gid", - "recursive", - "asRoot" - ], - "type": "object" - }, - "DeleteRequest": { + "DeleteRequest": { "properties": { "asRoot": { "type": "boolean" @@ -427,180 +511,24 @@ ], "type": "object" }, - "ConnectionResponse": { - "description": "Connector response", - "properties": { - "connection": { - "$ref": "#/components/schemas/Connection", - "description": "Sanitized connector. Secrets and encrypted token fields are never returned.", - "example": { - "id": "conn_abc123", - "provider": "slack" - } - } - }, - "required": [ - "connection" - ], - "type": "object" - }, - "ChownResponse": { + "DeleteResponse": { "properties": { - "affected": { - "items": { - "$ref": "#/components/schemas/ChownResult" - }, - "type": "array" - }, "count": { "type": "integer" - } - }, - "required": [ - "affected", - "count" - ], - "type": "object" - }, - "SpriteListResponse": { - "description": "Paginated sprite list", - "properties": { - "cold": { - "description": "Number of returned sprites currently cold.", - "example": 3, - "type": "integer" - }, - "has_more": { - "description": "Whether more results are available", - "example": true, - "type": "boolean" - }, - "name": { - "description": "Organization slug.", - "example": "my-org", - "type": "string" - }, - "next_continuation_token": { - "description": "Token for fetching the next page of results", - "example": "eyJsYXN0IjoibXktZGV2LXNwcml0ZSJ9", - "type": "string" - }, - "running": { - "description": "Number of returned sprites currently running.", - "example": 1, - "type": "integer" - }, - "running_limit": { - "description": "Organization-wide active sprite limit.", - "example": 10, - "type": "integer" }, - "sprites": { - "description": "List of sprite resources", - "example": [ - { - "id": "sprite-abc123", - "name": "my-dev-sprite", - "status": "running" - } - ], + "deleted": { "items": { - "$ref": "#/components/schemas/SpriteResponse" + "type": "string" }, "type": "array" - }, - "warm": { - "description": "Number of returned sprites currently warm.", - "example": 2, - "type": "integer" - }, - "warm_limit": { - "description": "Organization-wide warm sprite limit.", - "example": 10, - "type": "integer" - } - }, - "required": [ - "sprites", - "has_more", - "running", - "warm", - "cold", - "name" - ], - "type": "object" - }, - "ListConnectionsRequest": { - "description": "List connectors query parameters", - "properties": { - "provider": { - "description": "Optional provider filter.", - "example": "slack", - "type": "string" - } - }, - "required": [], - "type": "object" - }, - "ApiKeyConnectionRequest": { - "description": "API-key connector request", - "properties": { - "access_policy": { - "$ref": "#/components/schemas/AccessPolicy", - "description": "Initial access policy. Empty or missing policies deny sprite use until updated.", - "example": { - "allow_all": true - } - }, - "api_key": { - "description": "Provider API key. Stored encrypted and never returned by the API.", - "example": "sk-or-...", - "type": "string" - }, - "base_api_url": { - "description": "Required for Upstash Redis: immutable HTTPS database REST URL. Not used by fixed-host providers.", - "example": "https://your-database.upstash.io", - "type": "string" - }, - "provider": { - "description": "API-key provider.", - "example": "openrouter", - "type": "string" } }, "required": [ - "provider", - "api_key" + "deleted", + "count" ], "type": "object" }, - "OAuthAuthorizeRequest": { - "description": "OAuth authorize query parameters", - "properties": { - "add_scopes": { - "description": "Comma-separated scopes to add to any scopes already granted for this provider.", - "example": "reactions:write,files:read", - "type": "string" - }, - "redirect_uri": { - "description": "OAuth callback URI. Defaults to the Sprites API callback for the provider.", - "example": "https://api.sprites.dev/v1/oauth/slack/callback", - "type": "string" - }, - "scopes": { - "description": "Comma-separated scopes to request. Replaces the default scope set for this authorization URL.", - "example": "chat:write,channels:read", - "type": "string" - }, - "state": { - "description": "Optional state value. If omitted, Sprites generates one that ties the callback to the organization.", - "example": "opaque-state", - "type": "string" - } - }, - "required": [], - "type": "object" - }, "Entry": { "properties": { "isDir": { @@ -637,165 +565,120 @@ ], "type": "object" }, - "ServiceLogStoppedEvent": { + "ExecKillCompleteEvent": { "example": { "exit_code": 0, - "timestamp": 1767609000000, - "type": "stopped" + "type": "complete" }, "properties": { "exit_code": { "description": "Process exit code", "type": "integer" }, - "timestamp": { - "description": "Unix milliseconds", - "type": "integer" - }, "type": { - "const": "stopped", + "const": "complete", "type": "string" } }, "required": [ "type", - "exit_code", - "timestamp" - ], - "type": "object" - }, - "ConnectionListResponse": { - "description": "Connector list response", - "properties": { - "connections": { - "description": "Connectors configured for the organization.", - "example": [ - { - "id": "conn_abc123", - "provider": "slack" - } - ], - "items": { - "$ref": "#/components/schemas/Connection" - }, - "type": "array" - } - }, - "required": [ - "connections" + "exit_code" ], "type": "object" }, - "StreamInfoEvent": { + "ExecKillErrorEvent": { "example": { - "data": "Creating checkpoint...", - "time": "2026-01-05T10:30:00Z", - "type": "info" + "message": "Warning: process may not have terminated", + "type": "error" }, "properties": { - "data": { - "description": "Status message", - "type": "string" - }, - "time": { - "description": "Timestamp", - "format": "date-time", + "message": { + "description": "Error message", "type": "string" }, "type": { - "const": "info", + "const": "error", "type": "string" } }, "required": [ "type", - "data", - "time" + "message" ], "type": "object" }, - "NetworkPolicyRequest": { + "ExecKillExitedEvent": { "example": { - "rules": [ - { - "action": "allow", - "domain": "github.com" - }, - { - "action": "allow", - "domain": "*.npmjs.org" - } - ] + "message": "Process exited", + "type": "exited" }, "properties": { - "rules": { - "description": "List of network policy rules", - "items": { - "$ref": "#/components/schemas/NetworkPolicyRule" - }, - "type": "array" + "message": { + "description": "Status message", + "type": "string" + }, + "type": { + "const": "exited", + "type": "string" } }, "required": [ - "rules" + "type", + "message" ], "type": "object" }, - "NetworkPolicyRule": { + "ExecKillKilledEvent": { "example": { - "action": "allow", - "domain": "*.github.com" - }, - "properties": { - "action": { - "description": "`allow` or `deny`", - "type": "string" - }, - "domain": { - "description": "Domain pattern (e.g., `*.github.com`)", - "type": "string" - }, - "include": { - "description": "Include rules from preset", - "type": "string" - } + "message": "Process killed", + "type": "killed" }, - "required": [], - "type": "object" - }, - "RenameResponse": { "properties": { - "dest": { + "message": { + "description": "Status message", "type": "string" }, - "source": { + "type": { + "const": "killed", "type": "string" } }, "required": [ - "source", - "dest" + "type", + "message" ], "type": "object" }, - "ExecKillKilledEvent": { + "ExecKillSignalEvent": { "example": { - "message": "Process killed", - "type": "killed" + "message": "Signaling SIGTERM to process group 1847", + "pid": 1847, + "signal": "SIGTERM", + "type": "signal" }, "properties": { "message": { "description": "Status message", "type": "string" }, + "pid": { + "description": "Target process ID", + "type": "integer" + }, + "signal": { + "description": "Signal name (e.g., `SIGTERM`)", + "type": "string" + }, "type": { - "const": "killed", + "const": "signal", "type": "string" } }, "required": [ "type", - "message" + "message", + "signal", + "pid" ], "type": "object" }, @@ -820,470 +703,356 @@ ], "type": "object" }, - "ServiceLogStartedEvent": { - "example": { - "timestamp": 1767609000000, - "type": "started" + "ListConnectionsRequest": { + "description": "List connectors query parameters", + "properties": { + "provider": { + "description": "Optional provider filter.", + "example": "slack", + "type": "string" + } }, + "required": [], + "type": "object" + }, + "ListResponse": { "properties": { - "timestamp": { - "description": "Unix milliseconds", + "count": { "type": "integer" }, - "type": { - "const": "started", + "entries": { + "items": { + "$ref": "#/components/schemas/Entry" + }, + "type": "array" + }, + "path": { "type": "string" } }, "required": [ - "type", - "timestamp" + "path", + "entries", + "count" ], "type": "object" }, - "CopyRequest": { + "ListSpritesRequest": { + "description": "List sprites query parameters", "properties": { - "asRoot": { - "type": "boolean" - }, - "dest": { + "continuation_token": { + "description": "Token from previous response for pagination", + "example": "eyJsYXN0IjoibXktc3ByaXRlIn0=", "type": "string" }, - "preserveAttrs": { - "type": "boolean" - }, - "recursive": { - "type": "boolean" - }, - "source": { - "type": "string" + "max_results": { + "description": "Maximum number of results (1-500, default: 50)", + "example": 50, + "type": "integer" }, - "workingDir": { + "prefix": { + "description": "Filter sprites by name prefix", + "example": "dev-", "type": "string" } }, - "required": [ - "source", - "dest", - "workingDir", - "recursive", - "preserveAttrs", - "asRoot" - ], + "required": [], "type": "object" }, - "ExecKillExitedEvent": { + "NetworkPolicyRequest": { "example": { - "message": "Process exited", - "type": "exited" + "rules": [ + { + "action": "allow", + "domain": "github.com" + }, + { + "action": "allow", + "domain": "*.npmjs.org" + } + ] }, "properties": { - "message": { - "description": "Status message", - "type": "string" - }, - "type": { - "const": "exited", - "type": "string" + "rules": { + "description": "List of network policy rules", + "items": { + "$ref": "#/components/schemas/NetworkPolicyRule" + }, + "type": "array" } }, "required": [ - "type", - "message" + "rules" ], "type": "object" }, - "ChmodRequest": { + "NetworkPolicyRule": { + "example": { + "action": "allow", + "domain": "*.github.com" + }, "properties": { - "asRoot": { - "type": "boolean" - }, - "mode": { + "action": { + "description": "`allow` or `deny`", "type": "string" }, - "path": { + "domain": { + "description": "Domain pattern (e.g., `*.github.com`)", "type": "string" }, - "recursive": { - "type": "boolean" - }, - "workingDir": { - "type": "string" - } - }, - "required": [ - "path", - "workingDir", - "mode", - "recursive", - "asRoot" - ], - "type": "object" - }, - "UrlSettingsRequest": { - "description": "URL settings request", - "properties": { - "auth": { - "description": "Authentication type (default: sprite)", - "enum": [ - "sprite", - "public" - ], - "example": "sprite", + "include": { + "description": "Include rules from preset", "type": "string" } }, "required": [], "type": "object" }, - "ServiceResponse": { - "example": { - "args": [ - "-m", - "http.server", - "8000" - ], - "cmd": "python", - "http_port": 8000, - "name": "webapp", - "needs": [ - "postgres" - ], - "state": { - "name": "webapp", - "pid": 1567, - "started_at": "2026-01-05T08:01:00Z", - "status": "running" - } - }, + "OAuthAuthorizeRequest": { + "description": "OAuth authorize query parameters", "properties": { - "args": { - "description": "Command arguments", - "items": { - "type": "string" - }, - "type": "array" - }, - "cmd": { - "description": "Command to execute", + "add_scopes": { + "description": "Comma-separated scopes to add to any scopes already granted for this provider.", + "example": "reactions:write,files:read", "type": "string" }, - "http_port": { - "description": "HTTP port for proxy routing", - "type": [ - "integer", - "null" - ] - }, - "name": { - "description": "Service name", + "redirect_uri": { + "description": "OAuth callback URI. Defaults to the Sprites API callback for the provider.", + "example": "https://api.sprites.dev/v1/oauth/slack/callback", "type": "string" }, - "needs": { - "description": "Service dependencies", - "items": { - "type": "string" - }, - "type": "array" - }, - "state": { - "description": "Current runtime state", - "oneOf": [ - { - "$ref": "#/components/schemas/ServiceState" - }, - { - "type": "null" - } - ] - } - }, - "required": [ - "name", - "cmd", - "args", - "needs" - ], - "type": "object" - }, - "ListSpritesRequest": { - "description": "List sprites query parameters", - "properties": { - "continuation_token": { - "description": "Token from previous response for pagination", - "example": "eyJsYXN0IjoibXktc3ByaXRlIn0=", + "scopes": { + "description": "Comma-separated scopes to request. Replaces the default scope set for this authorization URL.", + "example": "chat:write,channels:read", "type": "string" }, - "max_results": { - "description": "Maximum number of results (1-500, default: 50)", - "example": 50, - "type": "integer" - }, - "prefix": { - "description": "Filter sprites by name prefix", - "example": "dev-", + "state": { + "description": "Optional state value. If omitted, Sprites generates one that ties the callback to the organization.", + "example": "opaque-state", "type": "string" } }, "required": [], "type": "object" }, - "ChmodResponse": { + "OAuthAuthorizeResponse": { + "description": "OAuth authorization response", "properties": { - "affected": { - "items": { - "$ref": "#/components/schemas/ChmodResult" - }, - "type": "array" + "authorize_url": { + "description": "Provider URL where the user grants access.", + "example": "https://slack.com/oauth/v2/authorize?client_id=...", + "type": "string" }, - "count": { - "type": "integer" + "state": { + "description": "State value that must be sent back to the callback.", + "example": "opaque-state", + "type": "string" } }, "required": [ - "affected", - "count" + "authorize_url", + "state" ], "type": "object" }, - "DeleteResponse": { + "OAuthCallbackRequest": { + "description": "OAuth callback request", "properties": { - "count": { - "type": "integer" + "access_policy": { + "$ref": "#/components/schemas/AccessPolicy", + "description": "Initial access policy. Empty or missing policies deny sprite use until updated.", + "example": { + "allow_all": true + } }, - "deleted": { - "items": { - "type": "string" - }, - "type": "array" + "code": { + "description": "Authorization code returned by the provider.", + "example": "oauth-code", + "type": "string" + }, + "redirect_uri": { + "description": "Redirect URI used to create the authorization URL.", + "example": "https://api.sprites.dev/v1/oauth/slack/callback", + "type": "string" + }, + "state": { + "description": "State value from the authorize response.", + "example": "opaque-state", + "type": "string" } }, "required": [ - "deleted", - "count" + "code" ], "type": "object" }, - "ExecKillSignalEvent": { - "example": { - "message": "Signaling SIGTERM to process group 1847", - "pid": 1847, - "signal": "SIGTERM", - "type": "signal" - }, + "PortNotificationMessage": { "properties": { - "message": { - "description": "Status message", + "address": { + "description": "Proxy URL for accessing the port", "type": "string" }, "pid": { - "description": "Target process ID", + "description": "Process ID that opened/closed the port", "type": "integer" }, - "signal": { - "description": "Signal name (e.g., `SIGTERM`)", - "type": "string" + "port": { + "description": "Port number", + "type": "integer" }, "type": { - "const": "signal", + "description": "Notification type", + "enum": [ + "port_opened", + "port_closed" + ], "type": "string" } }, "required": [ "type", - "message", - "signal", + "port", + "address", "pid" ], "type": "object" }, - "AccessPolicy": { - "description": "Connector access policy", + "ProvisionConnectionRequest": { + "description": "Provision connector request", "properties": { - "allow_all": { - "description": "When true, all sprites in the organization may use this connector.", - "example": false, - "type": "boolean" - }, - "allowed_endpoints": { - "description": "Provider API paths the connector may call. Supports exact paths and trailing `*` prefix wildcards.", - "example": [ - "/chat.*" - ], - "items": { - "type": "string" - }, - "type": "array" - }, - "blocked_endpoints": { - "description": "Provider API paths the connector may not call. Block rules are checked before allow rules.", - "example": [ - "/admin.*" - ], - "items": { - "type": "string" - }, - "type": "array" - }, - "name_prefix": { - "description": "Sprite name prefix required to use this connector.", - "example": "prod-", + "provider": { + "description": "Provider to provision.", + "example": "openrouter", "type": "string" - }, - "sprite_labels": { - "description": "Labels the calling sprite must have. All listed labels are required.", - "example": [ - "api-access" - ], - "items": { - "type": "string" - }, - "type": "array" } }, - "required": [], + "required": [ + "provider" + ], "type": "object" }, - "Connection": { - "description": "Connector", + "RenameRequest": { "properties": { - "access_policy": { - "$ref": "#/components/schemas/AccessPolicy", - "description": "Policy controlling which sprites and provider endpoints may use this connector.", - "example": { - "allow_all": true, - "allowed_endpoints": [ - "/*" - ] - } - }, - "connection_type": { - "description": "How the connector was created.", - "enum": [ - "oauth", - "api_key", - "provisioned", - "internal" - ], - "example": "oauth", - "type": "string" - }, - "id": { - "description": "Connector ID used in gateway URLs.", - "example": "conn_abc123", - "type": "string" - }, - "inserted_at": { - "description": "When the connector was created.", - "example": "2026-04-28T12:00:00Z", - "format": "date-time", - "type": "string" - }, - "notes": { - "description": "Provider notes about this connection, derived from its saved settings. Each has a nullable `title` and a `body`; backticks mark inline code.", - "example": [ - { - "title": null, - "body": "Full-access key." - } - ], - "items": { - "type": "object" - }, - "type": "array" - }, - "provider": { - "description": "Provider key. See https://fly.io/sprites/ecosystem/ for current connectors.", - "example": "slack", - "type": "string" + "asRoot": { + "type": "boolean" }, - "provider_account_id": { - "description": "Provider account, workspace, or key identifier.", - "example": "T12345", + "dest": { "type": "string" }, - "provider_account_name": { - "description": "Human-readable provider account name.", - "example": "Example Workspace", + "source": { "type": "string" }, - "provider_info": { - "description": "Provider-specific metadata such as workspace URLs, custom API base URLs, or icon references.", - "example": { - "team_domain": "example" - }, - "type": "object" - }, - "scopes": { - "description": "Comma-separated OAuth scopes granted to the connector.", - "example": "chat:write,channels:read", + "workingDir": { "type": "string" - }, - "token_expires_at": { - "description": "When the stored token expires, if the provider issues expiring tokens.", - "example": "2026-04-29T12:00:00Z", - "format": "date-time", + } + }, + "required": [ + "source", + "dest", + "workingDir", + "asRoot" + ], + "type": "object" + }, + "RenameResponse": { + "properties": { + "dest": { "type": "string" }, - "updated_at": { - "description": "When the connector was last updated.", - "example": "2026-04-29T12:00:00Z", - "format": "date-time", + "source": { "type": "string" + } + }, + "required": [ + "source", + "dest" + ], + "type": "object" + }, + "ServiceLogCompleteEvent": { + "example": { + "log_files": { + "combined": "/.sprite/logs/services/webapp.log", + "stderr": "/.sprite/logs/services/webapp.log", + "stdout": "/.sprite/logs/services/webapp.log" }, - "usage_snippet": { - "description": "Provider-specific curl snippet showing how to call the connector through the gateway.", - "example": "curl https://api.sprites.dev/v1/gateway/slack/conn_abc123/auth.test", - "type": "string" + "timestamp": 1767609000000, + "type": "complete" + }, + "properties": { + "timestamp": { + "description": "Unix milliseconds", + "type": "integer" }, - "user_id": { - "description": "Sprites user ID that created or owns the connector.", - "example": "user_abc123", + "type": { + "const": "complete", "type": "string" } }, "required": [ - "id", - "provider", - "provider_account_id" + "type", + "timestamp" ], "type": "object" }, - "ChownResult": { + "ServiceLogErrorEvent": { + "example": { + "data": "Failed to start service: command not found", + "timestamp": 1767609000000, + "type": "error" + }, "properties": { - "gid": { - "type": "integer" - }, - "path": { + "data": { + "description": "Error message", "type": "string" }, - "uid": { + "timestamp": { + "description": "Unix milliseconds", "type": "integer" + }, + "type": { + "const": "error", + "type": "string" } }, "required": [ - "path", - "uid", - "gid" + "type", + "data", + "timestamp" ], "type": "object" }, - "CreateCheckpointRequest": { + "ServiceLogExitEvent": { "example": { - "comment": "Before deploying v2.0" + "exit_code": 0, + "timestamp": 1767609000000, + "type": "exit" }, "properties": { - "comment": { + "exit_code": { + "description": "Process exit code", + "type": "integer" + }, + "timestamp": { + "description": "Unix milliseconds", + "type": "integer" + }, + "type": { + "const": "exit", "type": "string" } }, - "required": [], + "required": [ + "type", + "exit_code", + "timestamp" + ], "type": "object" }, - "ServiceLogStoppingEvent": { + "ServiceLogStartedEvent": { "example": { "timestamp": 1767609000000, - "type": "stopping" + "type": "started" }, "properties": { "timestamp": { @@ -1291,7 +1060,7 @@ "type": "integer" }, "type": { - "const": "stopping", + "const": "started", "type": "string" } }, @@ -1301,209 +1070,333 @@ ], "type": "object" }, - "RenameRequest": { + "ServiceLogStderrEvent": { + "example": { + "data": "Warning: deprecated API usage\n", + "timestamp": 1767609000000, + "type": "stderr" + }, "properties": { - "asRoot": { - "type": "boolean" - }, - "dest": { + "data": { + "description": "Log line content", "type": "string" }, - "source": { - "type": "string" + "timestamp": { + "description": "Unix milliseconds", + "type": "integer" }, - "workingDir": { + "type": { + "const": "stderr", "type": "string" } }, "required": [ - "source", - "dest", - "workingDir", - "asRoot" + "type", + "data", + "timestamp" ], "type": "object" }, - "PortNotificationMessage": { + "ServiceLogStdoutEvent": { + "example": { + "data": "Server listening on port 3000\n", + "timestamp": 1767609000000, + "type": "stdout" + }, "properties": { - "address": { - "description": "Proxy URL for accessing the port", + "data": { + "description": "Log line content", "type": "string" }, - "pid": { - "description": "Process ID that opened/closed the port", - "type": "integer" - }, - "port": { - "description": "Port number", + "timestamp": { + "description": "Unix milliseconds", "type": "integer" }, "type": { - "description": "Notification type", - "enum": [ - "port_opened", - "port_closed" - ], + "const": "stdout", "type": "string" } }, "required": [ "type", - "port", - "address", - "pid" + "data", + "timestamp" ], "type": "object" }, - "ServiceLogStderrEvent": { + "ServiceLogStoppedEvent": { "example": { - "data": "Warning: deprecated API usage\n", + "exit_code": 0, "timestamp": 1767609000000, - "type": "stderr" + "type": "stopped" }, "properties": { - "data": { - "description": "Log line content", - "type": "string" + "exit_code": { + "description": "Process exit code", + "type": "integer" }, "timestamp": { "description": "Unix milliseconds", "type": "integer" }, "type": { - "const": "stderr", + "const": "stopped", "type": "string" } }, "required": [ "type", - "data", + "exit_code", "timestamp" ], "type": "object" }, - "CopyResult": { + "ServiceLogStoppingEvent": { + "example": { + "timestamp": 1767609000000, + "type": "stopping" + }, "properties": { - "dest": { - "type": "string" + "timestamp": { + "description": "Unix milliseconds", + "type": "integer" }, - "source": { + "type": { + "const": "stopping", "type": "string" } }, "required": [ - "source", - "dest" + "type", + "timestamp" ], "type": "object" }, - "WriteResponse": { + "ServiceRequest": { + "example": { + "args": [ + "-m", + "http.server", + "8000" + ], + "cmd": "python", + "http_port": 8000, + "needs": [ + "postgres" + ] + }, "properties": { - "mode": { + "args": { + "description": "Command arguments", + "items": { + "type": "string" + }, + "type": "array" + }, + "cmd": { + "description": "Command to execute", "type": "string" }, - "path": { + "dir": { + "description": "Working directory for the service", "type": "string" }, - "size": { - "type": "integer" + "env": { + "description": "Environment variables to add to the base service environment", + "type": "object" + }, + "http_port": { + "description": "HTTP port for proxy routing", + "type": [ + "integer", + "null" + ] + }, + "needs": { + "description": "Service dependencies (started first)", + "items": { + "type": "string" + }, + "type": "array" } }, "required": [ - "path", - "size", - "mode" + "cmd", + "args", + "needs" ], "type": "object" }, - "StreamErrorEvent": { + "ServiceResponse": { "example": { - "error": "Checkpoint failed: disk full", - "time": "2026-01-05T10:30:00Z", - "type": "error" + "args": [ + "-m", + "http.server", + "8000" + ], + "cmd": "python", + "http_port": 8000, + "name": "webapp", + "needs": [ + "postgres" + ], + "state": { + "name": "webapp", + "pid": 1567, + "started_at": "2026-01-05T08:01:00Z", + "status": "running" + } }, "properties": { - "error": { - "description": "Error description", - "type": "string" + "args": { + "description": "Command arguments", + "items": { + "type": "string" + }, + "type": "array" }, - "time": { - "description": "Timestamp", - "format": "date-time", + "cmd": { + "description": "Command to execute", "type": "string" }, - "type": { - "const": "error", + "http_port": { + "description": "HTTP port for proxy routing", + "type": [ + "integer", + "null" + ] + }, + "name": { + "description": "Service name", "type": "string" + }, + "needs": { + "description": "Service dependencies", + "items": { + "type": "string" + }, + "type": "array" + }, + "state": { + "description": "Current runtime state", + "oneOf": [ + { + "$ref": "#/components/schemas/ServiceState" + }, + { + "type": "null" + } + ] } }, "required": [ - "type", - "error", - "time" + "name", + "cmd", + "args", + "needs" ], "type": "object" }, - "ProvisionConnectionRequest": { - "description": "Provision connector request", - "properties": { - "provider": { - "description": "Provider to provision.", - "example": "openrouter", - "type": "string" - } + "ServiceState": { + "example": { + "name": "webapp", + "pid": 1567, + "started_at": "2026-01-05T08:01:00Z", + "status": "running" }, - "required": [ - "provider" - ], - "type": "object" - }, - "UrlSettings": { - "description": "URL access settings", "properties": { - "auth": { - "description": "Authentication type", - "enum": [ - "sprite", - "public" - ], - "example": "sprite", + "error": { + "description": "Error message if failed", + "type": "string" + }, + "name": { + "description": "Service name", "type": "string" }, - "private_access": { - "description": "Who may access a sprite-authenticated URL.", - "enum": [ - "admins", - "organization" - ], - "example": "admins", + "pid": { + "description": "Process ID when running", + "type": "integer" + }, + "started_at": { + "description": "ISO 8601 timestamp", + "type": "string" + }, + "status": { + "description": "`stopped`, `starting`, `running`, `stopping`, or `failed`", "type": "string" } }, "required": [ - "auth" + "name", + "status" ], "type": "object" }, - "ListResponse": { + "SpriteListResponse": { + "description": "Paginated sprite list", "properties": { - "count": { + "cold": { + "description": "Number of returned sprites currently cold.", + "example": 3, "type": "integer" }, - "entries": { + "has_more": { + "description": "Whether more results are available", + "example": true, + "type": "boolean" + }, + "name": { + "description": "Organization slug.", + "example": "my-org", + "type": "string" + }, + "next_continuation_token": { + "description": "Token for fetching the next page of results", + "example": "eyJsYXN0IjoibXktZGV2LXNwcml0ZSJ9", + "type": "string" + }, + "running": { + "description": "Number of returned sprites currently running.", + "example": 1, + "type": "integer" + }, + "running_limit": { + "description": "Organization-wide active sprite limit.", + "example": 10, + "type": "integer" + }, + "sprites": { + "description": "List of sprite resources", + "example": [ + { + "id": "sprite-abc123", + "name": "my-dev-sprite", + "status": "running" + } + ], "items": { - "$ref": "#/components/schemas/Entry" + "$ref": "#/components/schemas/SpriteResponse" }, "type": "array" }, - "path": { - "type": "string" + "warm": { + "description": "Number of returned sprites currently warm.", + "example": 2, + "type": "integer" + }, + "warm_limit": { + "description": "Organization-wide warm sprite limit.", + "example": 10, + "type": "integer" } }, "required": [ - "path", - "entries", - "count" + "sprites", + "has_more", + "running", + "warm", + "cold", + "name" ], "type": "object" }, @@ -1622,34 +1515,48 @@ ], "type": "object" }, - "OAuthAuthorizeResponse": { - "description": "OAuth authorization response", + "StreamCompleteEvent": { + "example": { + "data": "Checkpoint v3 created successfully", + "time": "2026-01-05T10:30:00Z", + "type": "complete" + }, "properties": { - "authorize_url": { - "description": "Provider URL where the user grants access.", - "example": "https://slack.com/oauth/v2/authorize?client_id=...", + "data": { + "description": "Completion message", "type": "string" }, - "state": { - "description": "State value that must be sent back to the callback.", - "example": "opaque-state", + "time": { + "description": "Timestamp", + "format": "date-time", + "type": "string" + }, + "type": { + "const": "complete", "type": "string" } }, "required": [ - "authorize_url", - "state" + "type", + "data", + "time" ], "type": "object" }, - "ExecKillErrorEvent": { + "StreamErrorEvent": { "example": { - "message": "Warning: process may not have terminated", + "error": "Checkpoint failed: disk full", + "time": "2026-01-05T10:30:00Z", "type": "error" }, "properties": { - "message": { - "description": "Error message", + "error": { + "description": "Error description", + "type": "string" + }, + "time": { + "description": "Timestamp", + "format": "date-time", "type": "string" }, "type": { @@ -1659,42 +1566,135 @@ }, "required": [ "type", - "message" + "error", + "time" ], "type": "object" }, - "CheckpointInfo": { + "StreamInfoEvent": { "example": { - "comment": "Before database migration", - "create_time": "2026-01-05T10:30:00Z", - "id": "v7" + "data": "Creating checkpoint...", + "time": "2026-01-05T10:30:00Z", + "type": "info" }, "properties": { - "comment": { - "description": "User-provided description", + "data": { + "description": "Status message", "type": "string" }, - "create_time": { - "description": "When the checkpoint was created", + "time": { + "description": "Timestamp", "format": "date-time", "type": "string" }, - "health": { - "description": "Health status (empty = healthy, \"mount_failed\" = unhealthy)", + "type": { + "const": "info", + "type": "string" + } + }, + "required": [ + "type", + "data", + "time" + ], + "type": "object" + }, + "UpdateConnectionRequest": { + "description": "Update connector request", + "properties": { + "access_policy": { + "$ref": "#/components/schemas/AccessPolicy", + "description": "Replacement access policy.", + "example": { + "allowed_endpoints": [ + "/chat.*" + ], + "sprite_labels": [ + "api-access" + ] + } + } + }, + "required": [ + "access_policy" + ], + "type": "object" + }, + "UpdateSpriteRequest": { + "description": "Update sprite request", + "properties": { + "url_settings": { + "$ref": "#/components/schemas/UrlSettingsRequest", + "description": "URL access configuration to update", + "example": { + "auth": "public" + } + } + }, + "required": [ + "url_settings" + ], + "type": "object" + }, + "UrlSettings": { + "description": "URL access settings", + "properties": { + "auth": { + "description": "Authentication type", + "enum": [ + "sprite", + "public" + ], + "example": "sprite", "type": "string" }, - "id": { - "description": "Checkpoint identifier (e.g., `v7`)", + "private_access": { + "description": "Who may access a sprite-authenticated URL.", + "enum": [ + "admins", + "organization" + ], + "example": "admins", + "type": "string" + } + }, + "required": [ + "auth" + ], + "type": "object" + }, + "UrlSettingsRequest": { + "description": "URL settings request", + "properties": { + "auth": { + "description": "Authentication type (default: sprite)", + "enum": [ + "sprite", + "public" + ], + "example": "sprite", + "type": "string" + } + }, + "required": [], + "type": "object" + }, + "WriteResponse": { + "properties": { + "mode": { "type": "string" }, - "source_id": { - "description": "Parent checkpoint ID", + "path": { "type": "string" + }, + "size": { + "type": "integer" } }, "required": [ - "id", - "create_time" + "path", + "size", + "mode" ], "type": "object" }