平台 API 慣例¶
本頁定義 NextPDF SaaS Foundation 的 API 設計標準。所有基於 NextPDF 構建的 SaaS 平台應遵循這些慣例,確保 API 的一致性、可預測性與安全性。
認證與授權(Auth / RBAC)¶
認證方式¶
所有 API 請求必須包含以下其中一種認證標頭:
# Bearer Token(API Key)
Authorization: Bearer npro_sk_live_abc123def456...
# Bearer JWT(短效)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
API Key 格式規範¶
格式:{prefix}_{environment}_{random64chars}
範例:
npro_sk_live_8f4a2b1c...(生產環境,Secret Key)
npro_sk_test_7e3d9a0f...(測試環境)
npro_pk_live_1a2b3c4d...(公開金鑰,用於前端)
前綴說明:
npro_sk_live 生產環境 Secret Key(服務端)
npro_sk_test 測試環境 Secret Key
npro_pk_live 生產環境 Publishable Key(客戶端可見)
npro_wh_live Webhook 簽名密鑰
RBAC 角色定義¶
| 角色 | 說明 | 可執行操作 |
|---|---|---|
owner | 帳號擁有者 | 所有操作 + 帳單管理 + 成員管理 |
admin | 管理員 | 所有操作(除帳單)+ 成員管理 |
developer | 開發者 | API 操作 + 設定讀取 |
analyst | 分析師 | 唯讀(文件、報告、指標) |
viewer | 觀看者 | 唯讀(指定資源) |
service_account | 服務帳號 | 依授予的特定 Scopes |
權限 Scope 設計¶
格式:{resource}:{action}
範例:
pdf:generate 生成 PDF
pdf:parse 解析 PDF
pdf:sign 數位簽章
pdf:delete 刪除 PDF
rag:embed 向量索引
rag:search 語意搜尋
members:read 讀取成員列表
members:write 管理成員
billing:read 查看帳單
audit:read 查看審計日誌
settings:write 修改平台設定
RBAC 請求範例¶
POST /v1/pdf/generate HTTP/1.1
Authorization: Bearer npro_sk_live_...
X-Organization-ID: org-abc123
Content-Type: application/json
# 系統自動驗證:
# 1. Token 有效性
# 2. Token 對應的 tenant_id
# 3. 角色是否具有 pdf:generate 權限
# 4. 是否超過 plan 的使用配額
速率限制¶
標頭規範¶
每個 API 回應均包含速率限制標頭:
HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1740000060
X-RateLimit-Policy: 60;w=60;comment="per-minute"
超過限制回應¶
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1740000090
{
"type": "https://docs.yourpdf.com/errors/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "You have exceeded 60 requests per minute for operation 'pdf.generate'.",
"instance": "/v1/pdf/generate",
"retry_after": 30,
"limit": 60,
"window": "1m"
}
各方案速率限制¶
| 方案 | pdf.generate | pdf.parse | rag.embed | rag.search |
|---|---|---|---|---|
| Free | 10/分鐘 | 10/分鐘 | — | — |
| Pro | 300/分鐘 | 300/分鐘 | 100/小時 | 1,000/小時 |
| Enterprise | 自定義 | 自定義 | 自定義 | 自定義 |
冪等性¶
所有具副作用的 API 端點(POST、DELETE)支援冪等性保護。
使用方式¶
POST /v1/pdf/generate HTTP/1.1
Authorization: Bearer npro_sk_live_...
Idempotency-Key: idem_550e8400e29b41d4a716446655440000
Content-Type: application/json
{"html": "<h1>Report</h1>"}
規範¶
Idempotency-Key必須是唯一字串,建議使用 UUID v4- 相同的 Key 在 24 小時內重複請求將返回快取回應
- Key 不可重複使用於不同的請求體
- 快取命中時,回應標頭包含
X-Idempotency-Cache: hit - 冪等性不適用於
GET和HEAD請求(這些操作天然冪等)
最佳實踐¶
// 基於業務邏輯生成確定性 Key(推薦)
$key = hash('sha256', "tenant:{$tenantId}:generate:{$documentId}:attempt:1");
// 而非每次隨機生成(不推薦,失去冪等性保護)
$key = Uuid::uuid4(); // 重試時會是新 Key
Webhook¶
事件推送設計¶
Webhook 以 HTTPS POST 推送事件,保證至少一次(At-Least-Once)交付。
請求格式¶
POST https://your-endpoint.com/webhooks/nextpdf HTTP/1.1
Content-Type: application/json
X-NextPDF-Webhook-ID: wh_550e8400e29b41d4
X-NextPDF-Webhook-Timestamp: 1740000000
X-NextPDF-Webhook-Signature: v1=8f4a2b1c...
X-NextPDF-Webhook-Version: 1
{
"id": "evt_abc123",
"type": "pdf.generated",
"created_at": "2026-03-04T10:30:00Z",
"tenant_id": "tenant-abc123",
"data": {
"document_id": "doc-001",
"pages": 10,
"size_bytes": 524288,
"duration_ms": 1234
}
}
簽名驗證¶
function verifyWebhookSignature(
string $payload,
string $timestamp,
string $signature,
string $secret,
): bool {
// 防重放攻擊:拒絕超過 5 分鐘的請求
if (abs(time() - (int)$timestamp) > 300) {
return false;
}
$expectedSignature = 'v1=' . hash_hmac(
'sha256',
"{$timestamp}.{$payload}",
$secret
);
return hash_equals($expectedSignature, $signature);
}
重試策略¶
| 重試次數 | 等待時間 |
|---|---|
| 第 1 次 | 立即 |
| 第 2 次 | 5 分鐘後 |
| 第 3 次 | 30 分鐘後 |
| 第 4 次 | 2 小時後 |
| 第 5 次 | 12 小時後 |
| 放棄 | 72 小時後 |
事件類型清單¶
| 事件類型 | 說明 |
|---|---|
pdf.generated | PDF 生成完成 |
pdf.generation_failed | PDF 生成失敗 |
pdf.signed | 數位簽章完成 |
batch.completed | 批次任務完成 |
rag.index_completed | 向量索引完成 |
tenant.quota_warning | 配額使用達 80% |
tenant.quota_exceeded | 配額已用盡 |
data_purge.completed | GDPR 資料清除完成 |
審計事件¶
所有操作均產生不可變的審計事件(詳見 合規套件)。
查詢審計日誌¶
GET /v1/audit-log HTTP/1.1
Authorization: Bearer npro_sk_live_...
# 查詢參數
?tenant_id=tenant-abc123 # 必填(admin 以上才能跨租戶查詢)
&operation=pdf.sign # 可選:按操作類型過濾
&user_id=user-456 # 可選:按使用者過濾
&from=2026-01-01T00:00:00Z # 可選:起始時間(ISO 8601)
&to=2026-03-31T23:59:59Z # 可選:結束時間
&cursor=evt_abc123 # 可選:游標分頁
&per_page=50 # 可選:每頁筆數(max: 100)
RFC 9457 錯誤格式¶
所有 API 錯誤均遵循 RFC 9457(Problem Details for HTTP APIs) 格式。
標準錯誤格式¶
{
"type": "https://docs.yourpdf.com/errors/{error-slug}",
"title": "Human-readable error title",
"status": 422,
"detail": "Detailed explanation of what went wrong.",
"instance": "/v1/pdf/generate/req-abc123",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"documentation_url": "https://docs.yourpdf.com/errors/{error-slug}"
}
標準錯誤代碼¶
| HTTP 狀態 | 錯誤 Slug | 說明 |
|---|---|---|
| 400 | bad-request | 請求格式錯誤 |
| 401 | authentication-required | 未提供認證憑據 |
| 401 | invalid-credentials | 認證失敗 |
| 403 | insufficient-permissions | 無操作權限 |
| 404 | resource-not-found | 資源不存在 |
| 409 | conflict | 資源衝突(如重複建立) |
| 413 | payload-too-large | 請求體超過限制 |
| 422 | invalid-pdf | PDF 格式無效 |
| 422 | malicious-content | 偵測到惡意內容 |
| 429 | rate-limit-exceeded | 超過速率限制 |
| 503 | service-unavailable | 服務暫時不可用 |
驗證錯誤格式(含欄位詳情)¶
{
"type": "https://docs.yourpdf.com/errors/validation-error",
"title": "Validation Error",
"status": 422,
"detail": "The request contains invalid fields.",
"instance": "/v1/pdf/generate",
"errors": [
{
"field": "options.page_size",
"message": "Must be one of: A4, A3, Letter, Legal",
"value": "A0",
"code": "invalid_enum_value"
},
{
"field": "html",
"message": "Cannot be empty",
"code": "required"
}
]
}
資料生命週期¶
資源狀態轉換¶
軟刪除設計¶
所有資源採用軟刪除,提供 30 天的誤刪恢復視窗:
# 刪除(軟刪除,30 天內可恢復)
DELETE /v1/documents/{id}
→ 202 Accepted, {deleted_at: "...", purge_at: "...+30days"}
# 恢復(30 天內)
POST /v1/documents/{id}/restore
→ 200 OK
# 永久刪除(立即,30 天後自動觸發)
DELETE /v1/documents/{id}?permanent=true
→ 202 Accepted
分頁¶
所有列表端點使用游標分頁(Cursor-Based Pagination),不使用頁碼分頁(避免大資料集的 OFFSET 效能問題):
回應格式¶
{
"data": [...],
"pagination": {
"has_more": true,
"next_cursor": "eyJpZCI6ImRvYy0wMDUwIiwiY3JlYXRlZF9hdCI6MTc0MDAwMDAwMH0",
"prev_cursor": "eyJpZCI6ImRvYy0wMDAxIiwiY3JlYXRlZF9hdCI6MTczOTk5OTkwMH0",
"per_page": 20,
"total_estimate": 342
},
"meta": {
"request_id": "550e8400-...",
"duration_ms": 45
}
}
分頁請求¶
API 版本控制¶
URL 路徑版本控制:/v1/、/v2/
版本生命週期:
- 新版本釋出後,舊版本至少維護 12 個月
- 棄用通知:棄用標頭 + 電子郵件通知
- 棄用標頭:Deprecation: "2027-03-01"; Sunset: "2027-09-01"
參見¶
- API Gateway — 速率限制與冪等性的技術實作
- 合規套件 — 審計日誌與 GDPR 清除
- 計費指標 — 操作計量與 Prometheus 匯出