{"openapi":"3.1.0","info":{"title":"PubPage Public API","version":"1.0.0","description":"Stable developer API for sites, templates and reviewed deployments. Deployments always pass through PubPage staging and review before publication."},"paths":{"/api/v1/sites":{"get":{"operationId":"listSites","summary":"List sites","security":[{"bearerAuth":[]}],"x-required-scope":"sites:read","responses":{"200":{"description":"Sites","content":{"application/json":{"schema":{"type":"object","required":["data","requestId"],"additionalProperties":false,"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Site"}},"requestId":{"type":"string"}}}}}},"default":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"createSite","summary":"Create a site","security":[{"bearerAuth":[]}],"x-required-scope":"sites:create","description":"A non-blank template also requires deployments:write because template bootstrap enters the normal reviewed deployment pipeline.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"slug":{"type":"string","minLength":3,"maxLength":63,"pattern":"^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])?$","description":"Lowercase hostname label. Reserved platform labels are rejected."},"templateKey":{"type":"string","enum":["blank","personal","showcase","resume","landing","ai-tool","links","event"],"default":"blank"}}}}}},"responses":{"201":{"description":"Site created","content":{"application/json":{"schema":{"type":"object","required":["data","requestId"],"additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/Site"},"requestId":{"type":"string"}}}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/templates":{"get":{"operationId":"listTemplates","summary":"List stable starter templates","security":[{"bearerAuth":[]}],"x-required-scope":"sites:read","responses":{"200":{"description":"Templates","content":{"application/json":{"schema":{"type":"object","required":["data","requestId"],"additionalProperties":false,"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Template"}},"requestId":{"type":"string"}}}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/sites/{siteId}/deployments":{"post":{"operationId":"createDeployment","summary":"Upload a deployment candidate","description":"The upload is staged privately and processed by the existing scanner, AI/risk review, release and publish pipeline. This endpoint cannot bypass review.","security":[{"bearerAuth":[]}],"x-required-scope":"deployments:write","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Retries with the same user, site and key return the same deployment without creating another candidate release.","schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"additionalProperties":false,"properties":{"file":{"type":"string","format":"binary"},"path":{"type":"string","maxLength":2048,"description":"Optional safe relative path for a single-file deployment."}}}}}},"responses":{"200":{"description":"Idempotent replay","headers":{"Idempotency-Replayed":{"schema":{"type":"string","enum":["true"]}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentEnvelope"}}}},"201":{"description":"Deployment candidate created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentEnvelope"}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/deployments/{deploymentId}":{"get":{"operationId":"getDeployment","summary":"Get deployment status","security":[{"bearerAuth":[]}],"x-required-scope":"deployments:read","parameters":[{"name":"deploymentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentEnvelope"}}}},"default":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"PubPage API token"}},"responses":{"Error":{"description":"Stable machine-readable API error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"}}}}},"schemas":{"Site":{"type":"object","required":["id","name","slug","hostname","url","status"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string","pattern":"^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])?$"},"hostname":{"type":"string"},"url":{"type":"string","format":"uri"},"status":{"type":"string"},"accessMode":{"type":"string","enum":["public","password"]},"storageBytes":{"type":"string","pattern":"^[0-9]+$"},"template":{"type":"object","required":["key","status","deploymentId"],"additionalProperties":false,"properties":{"key":{"type":"string","enum":["blank","personal","showcase","resume","landing","ai-tool","links","event"]},"status":{"type":"string","enum":["not_requested","queued","failed"]},"deploymentId":{"type":["string","null"],"format":"uuid"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Template":{"type":"object","required":["key","name","summary","tone"],"additionalProperties":false,"properties":{"key":{"type":"string","enum":["blank","personal","showcase","resume","landing","ai-tool","links","event"]},"name":{"type":"string"},"summary":{"type":"string"},"tone":{"type":"string"}}},"DeploymentEnvelope":{"type":"object","required":["data","requestId"],"additionalProperties":false,"properties":{"data":{"$ref":"#/components/schemas/Deployment"},"requestId":{"type":"string"}}},"Deployment":{"type":"object","required":["id","siteId","state","review","publish","finalUrl","createdAt"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid","description":"Stable public deployment ID. It is the underlying upload/candidate identity, available before publication."},"siteId":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["queued","reviewing","manual_review","rejected","published","failed"]},"review":{"type":"object","required":["status"],"additionalProperties":false,"properties":{"status":{"type":"string","enum":["pending","in_progress","approved","manual_review","rejected","not_started"]},"reason":{"$ref":"#/components/schemas/PublicReason"}}},"publish":{"type":"object","required":["status"],"additionalProperties":false,"properties":{"status":{"type":"string","enum":["pending","published","not_published","failed"]},"deploymentRecordId":{"type":["string","null"],"format":"uuid"}}},"finalUrl":{"type":["string","null"],"format":"uri"},"createdAt":{"type":"string","format":"date-time"},"error":{"$ref":"#/components/schemas/PublicReason"}}},"PublicReason":{"type":"object","required":["code","message"],"additionalProperties":false,"properties":{"code":{"type":"string"},"message":{"type":"string"}}},"PublicApiError":{"type":"object","required":["error","requestId"],"additionalProperties":false,"properties":{"error":{"$ref":"#/components/schemas/PublicReason"},"requestId":{"type":"string"}}}}}}