{"openapi":"3.1.0","info":{"title":"OpenQuick API","version":"0.1.1","description":"Public discovery and authenticated atomic deploys for static sites."},"servers":[{"url":"https://open-quick-production.up.railway.app"}],"paths":{"/healthz":{"get":{"operationId":"getHealth","summary":"Check service health","responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/.well-known/openquick-release.json":{"get":{"operationId":"getOpenQuickRelease","summary":"Public production revision attestation","description":"Credential-free attestation of the exact Space-main revision this process was built to serve. Values are injected at authorized build/deploy. Cache-Control: no-store. Production processes refuse to listen without valid metadata.","responses":{"200":{"description":"Pinned production revision","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenQuickRelease"}}}},"404":{"description":"Attestation not configured (non-production only)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteNotFoundError"}}}}}}},"/api/v1/me":{"get":{"operationId":"getMe","summary":"Current human console session (public fields only)","responses":{"200":{"description":"Authenticated human identity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicIdentity"}}}},"401":{"description":"No valid session cookie","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/identity":{"get":{"operationId":"getSiteIdentity","summary":"Public publisher identity for a site","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Public identity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicIdentity"}}}},"404":{"description":"Site or identity not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteNotFoundError"}}}}}}},"/api/v1/sites":{"get":{"operationId":"listSites","summary":"List deployed sites","responses":{"200":{"description":"Site list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteListResponse"}}}}}},"post":{"operationId":"writeSitesCollection","summary":"Unauthenticated collection writes fail closed","description":"Console/collection writes require the existing agent-connection or operator bearer. Missing or invalid credentials return 401 and never redirect. Production returns documented 403 when a local auth bypass or insecure cookie mode is enabled.","security":[{"bearerAuth":[]}],"responses":{"401":{"description":"Missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Production refuses writes while a local auth bypass or insecure cookie mode is enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Authenticated collection POST has no create resource; use /api/v1/sites/{slug}/deploy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteNotFoundError"}}}}}}},"/api/v1/sites/{slug}":{"get":{"operationId":"getSite","summary":"Get site metadata","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"responses":{"200":{"description":"Site metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteDetailResponse"}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteNotFoundError"}}}}}}},"/api/v1/agent-connections":{"get":{"operationId":"listAgentCredentials","summary":"List credentials belonging to the authenticated handle","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Secret-free credential lifecycle metadata","content":{"application/json":{"schema":{"type":"object","required":["handle","credentials"],"properties":{"handle":{"type":"string"},"credentials":{"type":"array","items":{"$ref":"#/components/schemas/AgentCredential"}}}}}}},"401":{"description":"Missing, invalid, or revoked token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"post":{"operationId":"startAgentConnection","summary":"Start a browser-mediated agent connection","description":"Approval creates an independent handle-bound credential with no expiry. Pending approval defaults to 60 minutes (OPENQUICK_APPROVAL_WINDOW_MS, max 24h). Optional scope is a literal site-slug prefix. Optional notifyCommonsHandle is forwarded only to the secret-free operator notifier.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["handle","privateSink"],"properties":{"handle":{"type":"string"},"privateSink":{"type":"boolean"},"scope":{"anyOf":[{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,61}$"},{"type":"null"}]},"notifyCommonsHandle":{"type":"string","pattern":"^[a-z][a-z0-9-]{1,61}$"}}}}}},"responses":{"201":{"description":"Pending connection with approval URL, expiresAt, pollIntervalSeconds, humanMessage, private poll secret, and approvalCode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectionStart"}}}},"400":{"description":"Missing private sink, invalid handle, or invalid scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/agent-connections/{id}":{"delete":{"operationId":"revokeAgentCredential","summary":"Immediately revoke a credential owned by the authenticated handle","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{32}$"}}],"responses":{"204":{"description":"Credential revoked"},"401":{"description":"Missing, invalid, or revoked token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Credential not found for this handle"}}}},"/api/v1/agent-connections/{id}/approve":{"post":{"operationId":"approveAgentConnection","summary":"Human approval of a pending connection","description":"Requires the requester six-digit approvalCode. URL possession alone cannot approve.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["approvalCode"],"properties":{"approvalCode":{"type":"string","pattern":"^[0-9]{6}$"}}}}}},"responses":{"200":{"description":"Approved; deploy token is not returned here"},"401":{"description":"Invalid approval code"},"409":{"description":"Replay"},"410":{"description":"Expired"}}}},"/api/v1/agent-connections/{id}/revive":{"post":{"operationId":"reviveAgentConnection","summary":"Re-arm an expired pending connection with the same id and handle","description":"Proves ownership with the current clientSecret, then issues a new clientSecret and approvalCode bound to the same id/handle/approval URL. Old secrets fail closed.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{32}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["clientSecret"],"properties":{"clientSecret":{"type":"string"},"notifyCommonsHandle":{"type":"string","pattern":"^[a-z][a-z0-9-]{1,61}$"}}}}}},"responses":{"200":{"description":"Revived pending connection with new clientSecret, approvalCode, expiresAt, and humanMessage"},"401":{"description":"Bad client secret"},"409":{"description":"Not expired or no longer pending"}}}},"/api/v1/agent-connections/{id}/poll":{"post":{"operationId":"pollAgentConnection","summary":"Privately poll for a one-time deploy credential","description":"Pending responses include Retry-After matching pollIntervalSeconds from the start/revive body. The approved token is delivered once.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-f0-9]{32}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectionPollRequest"}}}},"responses":{"200":{"description":"Pending status or one-time approved token","headers":{"Retry-After":{"description":"Seconds to wait before the next pending poll. Present when status is pending.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConnectionPollResponse"}}}},"401":{"description":"Bad client secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Already delivered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/ai/chat":{"post":{"operationId":"aiChat","summary":"Guardrailed AI chat (stream or JSON)","description":"Server-held provider proxy. Browser/SDK never see provider keys or raw upstream errors. Default stream=true returns text/event-stream with data: {delta|done|error}. Requires deploy/operator bearer. Models allowlisted via OPENQUICK_AI_MODELS.","security":[{"bearerAuth":[]}],"parameters":[{"name":"X-OpenQuick-Site","in":"header","required":false,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"},"description":"Optional site attribution for per-site quota (must match credential scope when scoped)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiChatRequest"}}}},"responses":{"200":{"description":"SSE stream (default) or JSON completion when stream=false","content":{"text/event-stream":{"schema":{"type":"string","description":"SSE frames: data: {delta}|{done,message,usage}|{error}"}},"application/json":{"schema":{"$ref":"#/components/schemas/AiChatCompletion"}}}},"400":{"description":"invalid_request or unsupported_model","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}},"401":{"description":"Missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}},"429":{"description":"Per-user or per-site quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}},"499":{"description":"Client cancellation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}},"502":{"description":"Provider failure (raw upstream text never forwarded)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}},"504":{"description":"Request timeout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}}}}},"/api/v1/ai/images":{"post":{"operationId":"aiImages","summary":"Image generation (not enabled)","description":"Always returns typed not_enabled. Image generation is out of scope for this release.","security":[{"bearerAuth":[]}],"responses":{"401":{"description":"Missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}},"501":{"description":"not_enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/db/{collection}":{"post":{"operationId":"createDocument","summary":"Create a JSON document in a site collection","description":"Site namespace is the path slug only. Body/query/header site selectors are rejected (site_override_forbidden). See docs/DOCUMENTS.md.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"collection","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentCreateRequest"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonDocument"}}}},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"409":{"description":"version_conflict (id exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"422":{"description":"invalid collection/id/payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}}}},"get":{"operationId":"listDocuments","summary":"List documents with stable cursor pagination","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"collection","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentListResponse"}}}},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"422":{"description":"invalid_cursor or invalid_limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/db/{collection}/{id}":{"get":{"operationId":"getDocument","summary":"Get one document","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"collection","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"}}],"responses":{"200":{"description":"Document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonDocument"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}}}},"put":{"operationId":"updateDocument","summary":"Update a document with optimistic versioning","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"collection","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentUpdateRequest"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonDocument"}}}},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"409":{"description":"version_conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"422":{"description":"invalid_payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}}}},"delete":{"operationId":"deleteDocument","summary":"Delete a document","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"collection","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"}},{"name":"version","in":"query","required":false,"schema":{"type":"integer","minimum":1},"description":"Optional optimistic version"}],"responses":{"204":{"description":"Deleted"},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}},"409":{"description":"version_conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/files":{"post":{"operationId":"uploadFile","summary":"Upload a private site file","description":"Authenticated proxy upload. Site namespace is the path slug only. See docs/FILES.md.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"X-OpenQuick-Filename","in":"header","required":false,"schema":{"type":"string"},"description":"Display filename for raw body uploads"}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"filename":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileRecord"}}}},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"409":{"description":"too_many_files","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"422":{"description":"invalid_filename / content_type_not_allowed / invalid_payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}}}},"get":{"operationId":"listFiles","summary":"List private files for a site","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"responses":{"200":{"description":"File list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileListResponse"}}}},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/files/{id}":{"get":{"operationId":"getFileMetadata","summary":"Get private file metadata","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"}}],"responses":{"200":{"description":"Metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileRecord"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}}}},"delete":{"operationId":"deleteFile","summary":"Idempotently delete a private file","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"}}],"responses":{"204":{"description":"Deleted (or already absent)"},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/files/{id}/content":{"get":{"operationId":"getFileContent","summary":"Download private file bytes (bearer or signed URL)","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"}},{"name":"expires","in":"query","required":false,"schema":{"type":"integer"},"description":"Unix seconds expiry for signed retrieve"},{"name":"sig","in":"query","required":false,"schema":{"type":"string"},"description":"HMAC signature for signed retrieve"}],"responses":{"200":{"description":"Raw bytes"},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"403":{"description":"expired or invalid_signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/files/{id}/url":{"post":{"operationId":"mintFileRetrieveUrl","summary":"Mint a short-lived HMAC signed retrieve URL","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUrlRequest"}}}},"responses":{"200":{"description":"Signed URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileSignedUrlResponse"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}},"404":{"description":"not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/realtime":{"get":{"operationId":"subscribeRealtime","summary":"Open a site realtime SSE stream","description":"Single-process SSE fan-out for document commits and ephemeral channels. Not multi-instance. See docs/REALTIME.md.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"responses":{"200":{"description":"text/event-stream of RealtimeEvent JSON data frames"},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}}}},"post":{"operationId":"realtimeControl","summary":"Send a realtime control frame","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeControlRequest"}}}},"responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeControlResponse"}}}},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"404":{"description":"client not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"422":{"description":"invalid_frame","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/channels/{channel}":{"post":{"operationId":"publishChannel","summary":"Publish an ephemeral site channel message","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"channel","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelPublishRequest"}}}},"responses":{"202":{"description":"Accepted for fan-out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelRealtimeEvent"}}}},"400":{"description":"site_override_forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"401":{"description":"unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"413":{"description":"payload_too_large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}},"422":{"description":"invalid_channel or invalid_payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeErrorEnvelope"}}}}}}},"/sites/{slug}/":{"get":{"operationId":"getCurrentSite","summary":"Serve the mutable current release","description":"Mutable site URL. Nested assets live under this prefix. Redeploys update this URL in place.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"responses":{"200":{"description":"Current-release asset"},"404":{"description":"Site or asset not found"}}}},"/sites/{slug}/releases/{releaseId}/":{"get":{"operationId":"getReleasePermalink","summary":"Serve an immutable release permalink","description":"Canonical entry URL for an exact release. Nested assets live under this prefix. Unknown, malformed, cross-site, or traversal release IDs return 404 and never fall back to the current release.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}},{"name":"releaseId","in":"path","required":true,"schema":{"type":"string","minLength":1}}],"responses":{"200":{"description":"Byte-stable release asset with immutable caching"},"308":{"description":"Redirect to the trailing-slash permalink when the slash is omitted"},"404":{"description":"Unknown, malformed, cross-site, or traversal release; never the current release"}}}},"/api/v1/sites/{slug}/releases":{"get":{"operationId":"getSiteReleaseHistory","summary":"Get current site pointer and ordered release history","description":"Public metadata-only history. Does not copy or return release asset bytes. Releases are newest-first by deploy timestamp.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"responses":{"200":{"description":"Current URL/release, file/byte totals, and ordered history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteHistoryResponse"}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteNotFoundError"}}}}}}},"/api/v1/sites/{slug}/rollback":{"post":{"operationId":"rollbackSite","summary":"Atomically activate a prior immutable release","description":"Guarded rollback: points current.json at an existing release directory without copying files. Unknown or malformed release IDs fail closed. Repeating the same target is idempotent.","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollbackRequest"}}}},"responses":{"200":{"description":"Active release after rollback (or unchanged when already active)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployReceipt"}}}},"401":{"description":"Missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Production refuses writes while a local auth bypass or insecure cookie mode is enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Site not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteNotFoundError"}}}},"422":{"description":"Unknown or malformed release id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/sites/{slug}/deploy":{"post":{"operationId":"deploySite","summary":"Atomically deploy a static site","security":[{"bearerAuth":[]}],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"type":"object","required":["path","content"],"properties":{"path":{"type":"string"},"content":{"type":"string","contentEncoding":"base64"}}}}}}}}},"responses":{"201":{"description":"Deployment created. url is the mutable current-site URL; releaseUrl is the immutable permalink for this exact release.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployReceipt"}}}},"401":{"description":"Missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Production refuses writes while a local auth bypass or insecure cookie mode is enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Slug owned by a different handle","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"413":{"description":"Request too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Typed deploy validation failure (invalid_slug, reserved_slug, path_traversal, size/count limits, missing_index, invalid_payload)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"AgentConnectionStart":{"type":"object","additionalProperties":false,"required":["id","handle","status","scope","approvalUrl","pollUrl","expiresAt","pollIntervalSeconds","clientSecret","approvalCode","humanMessage"],"properties":{"id":{"type":"string","pattern":"^[a-f0-9]{32}$"},"handle":{"type":"string","pattern":"^[a-z][a-z0-9-]{1,61}$"},"status":{"type":"string","const":"pending"},"scope":{"anyOf":[{"type":"string"},{"type":"null"}]},"approvalUrl":{"type":"string","format":"uri"},"pollUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"},"pollIntervalSeconds":{"type":"integer","minimum":1,"description":"Suggested seconds between pending polls; matches Retry-After."},"clientSecret":{"type":"string","minLength":1,"description":"Private poll secret. Never log or paste into chat."},"approvalCode":{"type":"string","pattern":"^[0-9]{6}$","description":"Six-digit code the human enters on approvalUrl."},"humanMessage":{"type":"string","minLength":1}}},"AgentConnectionPollRequest":{"type":"object","additionalProperties":false,"required":["clientSecret"],"properties":{"clientSecret":{"type":"string","minLength":1}}},"AgentConnectionPollPending":{"type":"object","additionalProperties":false,"required":["status","handle","expiresAt"],"properties":{"status":{"type":"string","const":"pending"},"handle":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}}},"AgentConnectionPollApproved":{"type":"object","additionalProperties":false,"required":["status","handle","expiresAt","token"],"properties":{"status":{"type":"string","const":"approved"},"handle":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"token":{"type":"string","minLength":1,"description":"One-time deploy credential. Store privately; never log."}}},"AgentConnectionPollResponse":{"oneOf":[{"$ref":"#/components/schemas/AgentConnectionPollPending"},{"$ref":"#/components/schemas/AgentConnectionPollApproved"}]},"AgentCredential":{"type":"object","additionalProperties":false,"required":["id","scope","created_at","last_used_at","revoked_at"],"properties":{"id":{"type":"string","pattern":"^[a-f0-9]{32}$","description":"Random credential identifier; not derived from the token."},"scope":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Literal site-slug prefix, or null for unrestricted."},"created_at":{"type":"string","format":"date-time"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]}}},"PublicIdentity":{"type":"object","additionalProperties":false,"required":["id","name","avatar","handle"],"properties":{"id":{"type":"string","minLength":1,"description":"Stable public id (GitHub user id or publisher handle)."},"name":{"type":"string","description":"Display name."},"avatar":{"type":"string","description":"Avatar URL when known; empty string otherwise."},"handle":{"type":"string","minLength":1,"description":"Public handle / GitHub login."}}},"HealthResponse":{"type":"object","additionalProperties":false,"required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},"OpenQuickRelease":{"type":"object","additionalProperties":false,"required":["schema","service","sourceRevision","builtAt","deploymentId"],"properties":{"schema":{"type":"string","const":"openquick-release/v1"},"service":{"type":"string","const":"openquick","description":"Stable application identity."},"sourceRevision":{"type":"string","pattern":"^[0-9a-f]{40}$","description":"Exact 40-character lowercase git SHA of the promoted Space-main commit. Injected at authorized build/deploy; never derived from a request or hosted file."},"builtAt":{"type":"string","format":"date-time","description":"RFC 3339 UTC timestamp of the authorized build."},"deploymentId":{"type":"string","minLength":1,"pattern":"^\\S{1,256}$","description":"Opaque operator-supplied Railway deployment or release identifier. Not a secret."}}},"SiteRecord":{"type":"object","additionalProperties":false,"required":["slug","releaseId","fileCount","totalBytes","createdAt","updatedAt"],"properties":{"slug":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"},"releaseId":{"type":"string","minLength":1},"fileCount":{"type":"integer","minimum":1},"totalBytes":{"type":"integer","minimum":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"deployedBy":{"type":"string","minLength":1,"description":"Public agent handle when known. Never the deploy secret. Optional on older public-read records."}}},"SiteListResponse":{"type":"object","additionalProperties":false,"required":["sites"],"properties":{"sites":{"type":"array","items":{"$ref":"#/components/schemas/SiteRecord"}}}},"SiteDetailResponse":{"type":"object","additionalProperties":false,"required":["site"],"properties":{"site":{"$ref":"#/components/schemas/SiteRecord"}}},"SiteHistoryResponse":{"type":"object","additionalProperties":false,"required":["site","url","releaseUrl","fileCount","totalBytes","releases"],"properties":{"site":{"$ref":"#/components/schemas/SiteRecord"},"url":{"type":"string","format":"uri","description":"Mutable current-site URL: {origin}/sites/{slug}/"},"releaseUrl":{"type":"string","format":"uri","description":"Immutable canonical URL for the active release"},"fileCount":{"type":"integer","minimum":1},"totalBytes":{"type":"integer","minimum":0},"releases":{"type":"array","items":{"$ref":"#/components/schemas/SiteRecord"},"description":"Newest-first metadata for each immutable release. No asset bytes."}}},"RollbackRequest":{"type":"object","additionalProperties":false,"required":["releaseId"],"properties":{"releaseId":{"type":"string","minLength":1}}},"SiteNotFoundError":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"string","minLength":1,"description":"Stable public-read not-found message. No code field on this path."}}},"DeployReceipt":{"type":"object","additionalProperties":false,"required":["site","url","releaseUrl"],"properties":{"site":{"$ref":"#/components/schemas/SiteRecord"},"url":{"type":"string","format":"uri","description":"Mutable current-site URL: {origin}/sites/{slug}/"},"releaseUrl":{"type":"string","format":"uri","description":"Immutable canonical URL for this exact release: {origin}/sites/{slug}/releases/{releaseId}/"}}},"AiChatRequest":{"type":"object","additionalProperties":false,"required":["model","messages"],"properties":{"model":{"type":"string","minLength":1},"messages":{"type":"array","minItems":1,"items":{"type":"object","additionalProperties":false,"required":["role","content"],"properties":{"role":{"type":"string","enum":["system","user","assistant"]},"content":{"type":"string"}}}},"site":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$"},"stream":{"type":"boolean","default":true},"max_tokens":{"type":"integer","minimum":1}}},"AiChatCompletion":{"type":"object","additionalProperties":false,"required":["model","message","usage"],"properties":{"model":{"type":"string"},"message":{"type":"object","additionalProperties":false,"required":["role","content"],"properties":{"role":{"type":"string","enum":["assistant"]},"content":{"type":"string"}}},"usage":{"type":"object","additionalProperties":false,"required":["inputTokens","outputTokens"],"properties":{"inputTokens":{"type":"integer","minimum":0},"outputTokens":{"type":"integer","minimum":0}}}}},"FileRecord":{"type":"object","additionalProperties":false,"required":["id","filename","contentType","size","createdAt"],"properties":{"id":{"type":"string"},"filename":{"type":"string"},"contentType":{"type":"string"},"size":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"}}},"FileListResponse":{"type":"object","additionalProperties":false,"required":["files"],"properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/FileRecord"}}}},"FileUrlRequest":{"type":"object","additionalProperties":false,"properties":{"ttlMs":{"type":"integer","minimum":1}}},"FileSignedUrlResponse":{"type":"object","additionalProperties":false,"required":["url","expiresAt"],"properties":{"url":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}}},"FileErrorEnvelope":{"type":"object","additionalProperties":false,"required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string","enum":["not_found","invalid_filename","invalid_payload","payload_too_large","too_many_files","content_type_not_allowed","expired","invalid_signature","site_override_forbidden","unauthorized"]}}},"DocumentCreateRequest":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"id":{"type":"string","pattern":"^[a-zA-Z0-9_-]{1,128}$"},"data":{}}},"DocumentUpdateRequest":{"type":"object","additionalProperties":false,"required":["data","version"],"properties":{"data":{},"version":{"type":"integer","minimum":1}}},"JsonDocument":{"type":"object","additionalProperties":false,"required":["id","collection","data","version","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"collection":{"type":"string"},"data":{},"version":{"type":"integer","minimum":1},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"DocumentListResponse":{"type":"object","additionalProperties":false,"required":["documents","nextCursor"],"properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/JsonDocument"}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}}},"ChannelPublishRequest":{"type":"object","additionalProperties":false,"required":["payload"],"properties":{"payload":{}}},"ChannelRealtimeEvent":{"type":"object","additionalProperties":false,"required":["type","channel","payload","at"],"properties":{"type":{"type":"string","const":"channel"},"channel":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"payload":{},"at":{"type":"string","format":"date-time"}}},"RealtimeControlRequest":{"type":"object","additionalProperties":true,"required":["clientId","op"],"properties":{"clientId":{"type":"string","minLength":1},"op":{"type":"string","enum":["subscribe","unsubscribe","ping","pong","channel"]},"collection":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"channel":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,63}$"},"payload":{}}},"RealtimeControlResponse":{"type":"object","additionalProperties":false,"required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},"RealtimeErrorEnvelope":{"type":"object","additionalProperties":false,"required":["error","code"],"properties":{"error":{"type":"string","minLength":1},"code":{"type":"string","enum":["unauthorized","site_override_forbidden","invalid_collection","invalid_channel","invalid_frame","payload_too_large","rate_limited","not_found","invalid_payload"]}}},"DocumentErrorEnvelope":{"type":"object","additionalProperties":false,"required":["error","code"],"properties":{"error":{"type":"string","minLength":1},"code":{"type":"string","enum":["not_found","invalid_collection","invalid_id","invalid_payload","payload_too_large","version_conflict","invalid_cursor","invalid_limit","site_override_forbidden","unauthorized"]}}},"AiErrorEnvelope":{"type":"object","additionalProperties":false,"required":["error","code"],"properties":{"error":{"type":"string","minLength":1},"code":{"type":"string","enum":["quota","unsupported_model","timeout","cancellation","provider_failure","not_enabled","unauthorized","invalid_request"]}}},"ErrorEnvelope":{"type":"object","additionalProperties":false,"required":["error","code"],"properties":{"error":{"type":"string","minLength":1},"code":{"type":"string","enum":["unauthorized","insecure_mode","payload_too_large","invalid_deployment","invalid_release","scope_denied","no_private_sink","invalid_slug","file_size_limit","deploy_size_limit","file_count_limit","path_traversal","missing_index","invalid_payload","conflict","reserved_slug"]}}}}}}