PUBLIC API · V1

用一条清晰的 API 路径,发布静态站点。

从 Site 到 Deployment,字段、Scope、请求与响应都以 /openapi.json 为准。这里提供最短上手路径和必要的安全边界。

01 · OVERVIEW

一条部署链,所有入口共用

网页上传、Public API 与 PubPage CLI V1 共用同一审核与发布流程。仓库已提供项目自有的 PubPage AI Skill 源文件 skills/pubpage/SKILL.md,用于指导 Agent 通过安全登录与官方 CLI 自动发布;外部 Skill registry/distribution 发布单独跟踪。

01Upload02Staging03Scan04Review05Release06Publish
02 · QUICK START

完成第一次 Public API 调用

API origin 使用控制面地址 https://www.pubpage.top。先把 Token 放进受保护的环境变量,再用最小 scope 调用接口。

Shell environment
export PUBPAGE_ORIGIN='https://www.pubpage.top'
export PUBPAGE_TOKEN='pp_live_...'

1. 列出 Sites

GET/api/v1/sitessites:read
curl
curl --fail-with-body -H "Authorization: Bearer $PUBPAGE_TOKEN" "$PUBPAGE_ORIGIN/api/v1/sites"

2. 创建一个空白 Site

POST/api/v1/sitessites:create
curl
curl --fail-with-body -H "Authorization: Bearer $PUBPAGE_TOKEN" -H 'Content-Type: application/json' --data '{"name":"My site","slug":"my-site","templateKey":"blank"}' "$PUBPAGE_ORIGIN/api/v1/sites"

3. 上传 deployment candidate

POST/api/v1/sites/{siteId}/deploymentsdeployments:write
multipart/form-data
SITE_ID='00000000-0000-4000-8000-000000000000'
IDEMPOTENCY_KEY='deploy-20260829-001'

curl --fail-with-body -H "Authorization: Bearer $PUBPAGE_TOKEN" -H "Idempotency-Key: $IDEMPOTENCY_KEY" -F 'file=@./index.html;type=text/html' -F 'path=index.html' "$PUBPAGE_ORIGIN/api/v1/sites/$SITE_ID/deployments"

4. 查询审核与发布状态

GET/api/v1/deployments/{deploymentId}deployments:read
poll deployment
DEPLOYMENT_ID='00000000-0000-4000-8000-000000000000'

curl --fail-with-body -H "Authorization: Bearer $PUBPAGE_TOKEN" "$PUBPAGE_ORIGIN/api/v1/deployments/$DEPLOYMENT_ID"
03 · AUTHENTICATION

API Token 只放在可信服务端

Public API 使用 Authorization: Bearer <token>。Token 与网页登录 Session 是两套凭据,不能互换。

通过 Developer Console 获取 Token

登录 PubPage 后前往 Developer Console 创建、查看状态和撤销 API Token。Token 管理使用网页登录 Session 与 same-origin/CSRF 保护,不属于 Public API。

创建成功时完整明文只显示一次;之后列表只返回 prefix、scopes、过期/撤销时间和最后使用时间等非敏感 metadata。丢失完整 Token 时应撤销并重新创建。

安全保存

优先使用 secret manager、CI secret 或本机受保护环境变量。按 integration 分开创建 Token,并只授予需要的 scope。

禁止放进 HTML、浏览器 JavaScript、公开 Git、前端 bundle、普通日志、截图或上传到 Site 的文件,也不要把 Token 共享给不受信任的第三方。

Scopes

sites:readGET /api/v1/sites
sites:createPOST /api/v1/sites
sites:readGET /api/v1/templates
deployments:writePOST /api/v1/sites/{siteId}/deployments
deployments:readGET /api/v1/deployments/{deploymentId}

同一个 scope 可能服务多个 operation。创建非 blank template 的 Site 还需要 deployments:write,因为模板 bootstrap 会创建普通 deployment candidate。

04 · SITES

列出和创建 Sites

GET/api/v1/sitessites:read

列表只返回当前 Token 所属用户拥有的 Sites。响应 envelope 包含 data 与 requestId;字段定义见下方 OpenAPI-derived Reference。

POST/api/v1/sitessites:create

name 必填;slug 与 templateKey 的约束直接来自 OpenAPI。不要在客户端复制 slug 正则或 template enum 作为长期权威值。

05 · TEMPLATES

模板只是普通静态文件的起点

GET/api/v1/templatessites:read

运行时通过这个 endpoint 发现 template key、名称、摘要和 tone。不要把模板目录复制进 SDK。

选择非 blank 模板后,服务器生成普通静态文件,再调用现有上传服务;状态通过 Site 响应里的 template.status 与 template.deploymentId 跟踪。模板不能绕过 Scan 或 Review。

06 · DEPLOYMENTS

上传 file,必要时指定 path

POST/api/v1/sites/{siteId}/deploymentsdeployments:write

请求是 multipart/form-data。OpenAPI 当前要求一个 file 字段,并允许一个可选 path 字段。单文件部署可用 path 指定安全的站内相对路径;多文件站点应打包为受支持 archive 后作为 file 上传。

上传仍受 transport safety cap、账户 storage/file-count 配额、archive/path/MIME 安全规则、上传限流和 review quota 约束。传输安全上限不是套餐“单文件空间”。

07 · LIFECYCLE

只依赖公开 deployment state

不要解析内部 Prisma status。Public API 把内部 Upload / Release / Deployment 投影成下面这些稳定状态;枚举直接读取 OpenAPI。

queued

已接收,等待现有审核工作流处理。

reviewing

扫描、审核、批准或发布正在进行。

manual_review

等待人工审核决定。

rejected

内容未通过审核,不会成为当前公开版本。

published

批准的 Release 已成为 Site 当前公开版本。

failed

上传接收或发布没有完成。

进一步判断时读取 review.status、publish.status、finalUrl 和有界的 reason/error。只有 published 才表示批准的 Release 已成为当前公开版本。

08 · ERRORS & LIMITS

按 error.code 分支,保留 requestId

stable error envelope
{
  "error": {
    "code": "invalid_request",
    "message": "The request is invalid."
  },
  "requestId": "..."
}

每个稳定 V1 JSON 响应都有 x-request-id header,JSON envelope 也包含 requestId。日志和工单应保存 requestId,但不要记录 Authorization header。

当前 runtime 会返回的常见 machine codes 包括 invalid_api_token、token_expired、token_revoked、insufficient_scope、invalid_request、invalid_idempotency_key、not_found、site_limit_reached、storage_quota_exceeded、file_quota_exceeded、upload_too_large、upload_rejected、rate_limited 和 service_unavailable。

429 / rate limit

Public API runtime 会执行账户级请求限流;deployment 上传还有独立上传限流,并继续受 plan、storage、file-count 与 review quotas 约束。遇到 429 时停止突发请求并做有界退避,不要把某个客户端写死的请求频率当成 contract。

09 · PASSWORD SITE

访问保护不等于审核豁免

Password Site 是 control-plane + wildcard UGC access-layer 能力,不是 Public API 认证模式。目前没有稳定的 /api/v1 密码管理 endpoint。

符合套餐条件的 Site 可在控制面启用密码保护。密码使用服务端 Argon2id 哈希;访问凭据绑定 Site 和 session version,生产 Cookie 为 Secure、HttpOnly、Host-only,受保护资源返回 private/no-store。HTML、CSS、JavaScript、图片、JSON、PDF 等资源都在同一访问边界后。

Operator validation pending:生产环境相关 DNS/TLS、CDN/cache、CAPTCHA、真实 PUBLIC/PASSWORD 站点与公网 E2E 仍需按独立验收清单验证。本页不把这些生产验收项描述为已完成。

10 · CLI & AI

CLI V1 与 PubPage AI Skill

PubPage CLI V1

CLI 是受审核发布 API 的普通外部客户端,不访问数据库、内部 Worker、UGC auth 或 published storage。现在支持 login、logout、whoami、sites、create、deploy 和 status。

pubpage login 使用浏览器中的现有 PubPage Session 与 127.0.0.1 loopback callback 完成授权;Token 明文不会要求用户复制到 AI 对话或终端输出。凭据保存在本机受限文件中,但不是 OS keychain。

项目自有 AI Skill

仓库内的 canonical instruction source 是 skills/pubpage/SKILL.md。Skill 优先调用官方 CLI;只有 CLI 不可用时才按 /openapi.json 回退 REST。仓库 artifact 已可用于 Agent onboarding,但这不等于已发布到外部 Skill registry。

Agent 不应读取或泄露 secret,不应把 Token 写进 prompt、网站文件或日志,也不会删除用户文件、绕过 Review,或在 rejected 后自动循环修改重投。

AI/CLI happy path
pubpage whoami
# 如果尚未登录:
pubpage login
# 当前目录必须是带根 index.html 的静态输出:
pubpage deploy .
  1. Agent 先读取 PubPage Skill,并用 pubpage whoami 检查身份;未登录时启动 browser login,不要求用户粘贴 API Token。
  2. 确定用户要求发布的目录。目录发布必须有 regular root index.html;CLI 不会修改或删除源码。
  3. 未传 --site 时,只有恰好一个 Site 才自动选择。没有 Site 时必须先询问用户是否创建;多个 Site 时先 pubpage sites,由用户选择。
  4. pubpage deploy . 自动打包、上传 candidate 并进行有界轮询;仍保留 idempotency 与完整 Review pipeline。
  5. manual_review、rejected、failed 都停止当前自动流程;特别是 rejected 后不能自动改写并重投。
  6. 仅在 state 为 published 时返回成功,并输出 API 提供的 finalUrl;polling 达到边界时报告现状,不进入无限循环。
11 · API REFERENCE

Reference 直接绑定 /openapi.json

下面的 endpoint、scope、parameter、request field、response 与 component schema 都由服务端同一份 publicOpenApiDocument 渲染。它不是第二份 contract。

GET/api/v1/sitessites:read

List sites

listSites

Responses

200Sitesobject
defaultStable machine-readable API errorPublicApiError
POST/api/v1/sitessites:create

Create a site

createSite

A non-blank template also requires deployments:write because template bootstrap enters the normal reviewed deployment pipeline.

Request · application/json

窄屏可左右滚动查看完整表格。

createSite application/json 请求字段
FieldTypeRequiredContract detail
namestringyesminLength 1 · maxLength 120
slugstringnoLowercase hostname label. Reserved platform labels are rejected. · minLength 3 · maxLength 63 · pattern ^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])?$
templateKeystringnoenum blank | personal | showcase | resume | landing | ai-tool | links | event

Responses

201Site createdobject
defaultStable machine-readable API errorPublicApiError
GET/api/v1/templatessites:read

List stable starter templates

listTemplates

Responses

200Templatesobject
defaultStable machine-readable API errorPublicApiError
POST/api/v1/sites/{siteId}/deploymentsdeployments:write

Upload a deployment candidate

createDeployment

The upload is staged privately and processed by the existing scanner, AI/risk review, release and publish pipeline. This endpoint cannot bypass review.

Parameters

siteIdpath · string · uuid · required
Idempotency-Keyheader · string · required

Retries with the same user, site and key return the same deployment without creating another candidate release.

minLength 1 · maxLength 128 · pattern ^[A-Za-z0-9._:-]+$

Request · multipart/form-data

窄屏可左右滚动查看完整表格。

createDeployment multipart/form-data 请求字段
FieldTypeRequiredContract detail
filestring · binaryyes—
pathstringnoOptional safe relative path for a single-file deployment. · maxLength 2048

Responses

200Idempotent replayDeploymentEnvelopeheaders: Idempotency-Replayed
201Deployment candidate createdDeploymentEnvelope
defaultStable machine-readable API errorPublicApiError
GET/api/v1/deployments/{deploymentId}deployments:read

Get deployment status

getDeployment

Parameters

deploymentIdpath · string · uuid · required

Responses

200DeploymentDeploymentEnvelope
defaultStable machine-readable API errorPublicApiError

Component schemas

Site14 fields

窄屏可左右滚动查看完整表格。

Site 字段
FieldTypeRequiredContract detail
idstring · uuidyes—
namestringyes—
slugstringyespattern ^[a-z0-9](?:[a-z0-9-]{1,61}[a-z0-9])?$
hostnamestringyes—
urlstring · uriyes—
statusstringyes—
accessModestringnoenum public | password
storageBytesstringnopattern ^[0-9]+$
templateobjectno—
template.keystringyesenum blank | personal | showcase | resume | landing | ai-tool | links | event
template.statusstringyesenum not_requested | queued | failed
template.deploymentIdstring | null · uuidyes—
createdAtstring · date-timeno—
updatedAtstring · date-timeno—
Template4 fields

窄屏可左右滚动查看完整表格。

Template 字段
FieldTypeRequiredContract detail
keystringyesenum blank | personal | showcase | resume | landing | ai-tool | links | event
namestringyes—
summarystringyes—
tonestringyes—
DeploymentEnvelope2 fields

窄屏可左右滚动查看完整表格。

DeploymentEnvelope 字段
FieldTypeRequiredContract detail
dataDeploymentyes—
requestIdstringyes—
Deployment12 fields

窄屏可左右滚动查看完整表格。

Deployment 字段
FieldTypeRequiredContract detail
idstring · uuidyesStable public deployment ID. It is the underlying upload/candidate identity, available before publication.
siteIdstring · uuidyes—
statestringyesenum queued | reviewing | manual_review | rejected | published | failed
reviewobjectyes—
review.statusstringyesenum pending | in_progress | approved | manual_review | rejected | not_started
review.reasonPublicReasonno—
publishobjectyes—
publish.statusstringyesenum pending | published | not_published | failed
publish.deploymentRecordIdstring | null · uuidno—
finalUrlstring | null · uriyes—
createdAtstring · date-timeyes—
errorPublicReasonno—
PublicReason2 fields

窄屏可左右滚动查看完整表格。

PublicReason 字段
FieldTypeRequiredContract detail
codestringyes—
messagestringyes—
PublicApiError2 fields

窄屏可左右滚动查看完整表格。

PublicApiError 字段
FieldTypeRequiredContract detail
errorPublicReasonyes—
requestIdstringyes—
Machine-readable source/openapi.json
打开原始 OpenAPI ↗