API 參考
錯誤
了解所有 Kanorio API 回傳的統一錯誤格式、錯誤代碼與 HTTP 狀態碼的對應關係,以及如何處理重試機制。
Management API、Content Delivery API 及 Customer API 回傳的錯誤格式均一致。每個錯誤代碼在所有 API 中皆對應相同的 HTTP 狀態碼,因此您只需編寫一個錯誤處理器,即可應用於所有 API。
{ "error": { "code": "SLUG_TAKEN", "message": "Another post already uses this slug.", "details": { "slug": "how-we-feed-our-starter" } } }
| 欄位 | 類型 | 備註 |
|---|---|---|
error.code | string | 穩定且機器可讀。請根據此欄位進行分支處理。 |
error.message | string | 供日誌與開發者參考的英文句子。內容隨時可能變更,切勿依此進行比對。 |
error.details | object, optional | 代碼的結構化上下文,例如 retryAfter、availableAt、issues 或 requiredScope。 |
成功的回應絕不會包含 error 欄位,且 API 不會將成功回應包裹在 ok 旗標中。
錯誤代碼對應的 HTTP 狀態碼
每個錯誤代碼皆對應一個狀態碼。未來新增的代碼亦遵循相同規則,因此您可以根據狀態碼來處理尚未遇過的錯誤代碼。
| 狀態 | 含義 | 範例 |
|---|---|---|
400 | 請求格式錯誤或驗證失敗 | VALIDATION, INVALID_CURSOR, 以 INVALID_ 開頭的代碼 |
401 | 無憑證,或憑證無效、過期或已撤銷 | UNAUTHORIZED, UNAUTHENTICATED |
403 | 憑證有效但無權存取:權限、計劃、角色或模式不符 | FORBIDDEN, OWNER_REQUIRED, LIMIT_REACHED, LOCKED |
404 | 此網站上不存在該資源 | NOT_FOUND, 以 _NOT_FOUND 結尾的代碼 |
405 | 此路徑不支援該方法 | METHOD_NOT_ALLOWED |
409 | 與當前狀態衝突:過時的寫入、網址別名已被佔用、重複資料 | CONFLICT, SLUG_TAKEN, IDEMPOTENCY_CONFLICT |
413 | 上傳檔案過大 | FILE_TOO_LARGE |
422 | 輸入格式正確,但違反業務規則 | SITE_NOT_PUBLISHED, ASSET_IN_USE |
429 | 請求過多或後端繁忙;請稍後重試 | RATE_LIMITED, SEARCH_BUSY, ANALYTICS_BUSY |
500 | 未預期的伺服器錯誤 | INTERNAL |
502, 503 | 上游服務失敗或暫時無法使用 | UPLOAD_FAILED, SERVICE_UNAVAILABLE, SHARED_SENDER_PAUSED |
API 參考文件中的每項操作皆列出了其可能回傳的錯誤代碼及其含義。OpenAPI 文件中亦包含相同的列表,標記為 x-kanorio-errors。
驗證錯誤
VALIDATION 錯誤會在 details.issues 中列出所有驗證失敗的欄位。path 欄位使用點號(.)來表示巢狀結構。
{ "error": { "code": "VALIDATION", "message": "Input does not match the capability schema.", "details": { "issues": [ { "path": "title", "message": "Required", "code": "invalid_type" } ] } } }
Content Delivery API 的表單提交若有無效回答,會以相同方式回報,並將問題 ID 作為 path。
重試機制
- 針對
429、502及503錯誤,請使用退避演算法(backoff)進行重試。若回應中包含Retry-After標頭或details.retryAfter欄位,請至少等待該秒數後再重試。 - 請勿直接重試其他
4xx錯誤,應先修正請求內容。 - 若寫入操作出現
409 CONFLICT,代表資源在您讀取後已被他人修改。請重新讀取資源、合併變更,並使用新的時間戳記再次發送寫入請求。 - 請使用 冪等性鍵值 確保建立請求可安全重試。
權限錯誤
403 回應會在 details 中說明缺失的權限,例如權杖缺乏的 requiredScope,或是當服務帳戶呼叫帳戶層級操作時顯示 reason: "principal_not_allowed"。遇到此類錯誤時,請引導使用者進行修正,而非進行重試。
請求識別碼
Content Delivery API 及 Customer API 的回應皆包含 X-Request-Id 標頭。若需聯絡支援團隊查詢特定請求,請提供此識別碼。
錯誤代碼
下表列出了目前各 API 可能回傳的所有錯誤代碼,內容由 OpenAPI 文件自動產生。
Management API codes
| Code | HTTP status |
|---|---|
EMPTY_SLUG | 400 |
INVALID_BODY | 400 |
INVALID_CURSOR | 400 |
INVALID_EDITED_PATH | 400 |
INVALID_FORMAT | 400 |
INVALID_ORDER | 400 |
INVALID_SUBDOMAIN | 400 |
UNSUPPORTED_EDITED_PATH | 400 |
VALIDATION | 400 |
UNAUTHENTICATED | 401 |
UNAUTHORIZED | 401 |
CUSTOM_DOMAIN_CHANGE_FORBIDDEN | 403 |
CUSTOM_DOMAIN_LIMIT_REACHED | 403 |
FORBIDDEN | 403 |
LIMIT_REACHED | 403 |
MODERATION_LOCKED | 403 |
OWNER_REQUIRED | 403 |
PLAN_CANNOT_PUBLISH | 403 |
PRO_REQUIRED | 403 |
REDIRECT_LIMIT | 403 |
SUBDOMAIN_CHANGE_FORBIDDEN | 403 |
TOKEN_WEBSITE_SCOPED | 403 |
HEADER_NOT_FOUND | 404 |
HOME_PAGE_NOT_FOUND | 404 |
NOT_FOUND | 404 |
OWNER_NOT_FOUND | 404 |
PAGE_NOT_FOUND | 404 |
PARENT_NOT_FOUND | 404 |
PRODUCT_NOT_FOUND | 404 |
WEBSITE_NOT_FOUND | 404 |
METHOD_NOT_ALLOWED | 405 |
CONFLICT | 409 |
CUSTOM_DOMAIN_TAKEN | 409 |
HAS_CHILDREN | 409 |
HOSTED_ONLY | 409 |
HOSTNAME_CONFLICT | 409 |
IDEMPOTENCY_CONFLICT | 409 |
IDEMPOTENCY_IN_PROGRESS | 409 |
KEY_TAKEN | 409 |
PRIMARY_HEADER_PROTECTED | 409 |
READD_COOLDOWN | 409 |
REDIRECT_CONFLICT | 409 |
SLUG_TAKEN | 409 |
SUBDOMAIN_TAKEN | 409 |
TAKEN | 409 |
BLOCKED | 422 |
BREADCRUMB_PARENT_INVALID | 422 |
CONTENT_VALIDATION_FAILED | 422 |
CORE_SECTION_VIOLATION | 422 |
CUSTOM_DOMAIN_BLOCKED | 422 |
CUSTOM_DOMAIN_HIGH_RISK_TLD | 422 |
CUSTOM_DOMAIN_TOO_LONG | 422 |
DEPTH_EXCEEDED | 422 |
DNS_NOT_PROPAGATED | 422 |
DOMAIN_CHANGE_NOT_ALLOWED | 422 |
EMPTY_CONTENT | 422 |
FOREIGN_PAGE | 422 |
HIGH_RISK_TLD | 422 |
HOME_HAS_HIERARCHY | 422 |
HOME_NOT_CREATABLE | 422 |
HOME_NOT_DELETABLE | 422 |
HOME_NOT_SORTABLE | 422 |
HOME_SLUG_IMMUTABLE | 422 |
LINK_IN_BIO_DEDICATED_ENTRY | 422 |
LINK_IN_BIO_NOT_DUPLICABLE | 422 |
META_NOT_LIVE | 422 |
NO_PUBLIC_URL | 422 |
OWNERSHIP_REQUIRED | 422 |
PAGE_LIMIT_REACHED | 422 |
PARENT_NOT_ALLOWED | 422 |
RESERVED_SEGMENT | 422 |
RESERVED_SLUG | 422 |
RESERVED_SUBDOMAIN | 422 |
SANITIZE_FAILED | 422 |
SEARCH_CONSOLE_AUTH_EXPIRED | 422 |
SEARCH_CONSOLE_NOT_CONNECTED | 422 |
SEARCH_CONSOLE_PERMISSION_DENIED | 422 |
SEARCH_CONSOLE_PROPERTY_NOT_FOUND | 422 |
SEGMENT_TOO_LONG | 422 |
SITEMAP_NOT_REACHABLE | 422 |
SUBDOMAIN_MISSING | 422 |
SYSTEM_PAGE_LOCKED | 422 |
TEMPLATE_PRODUCT_LOCKED | 422 |
ANALYTICS_BUSY | 429 |
DAILY_LIMIT_REACHED | 429 |
RATE_LIMITED | 429 |
SEARCH_BUSY | 429 |
SEARCH_CONSOLE_QUOTA_EXCEEDED | 429 |
STOCK_BUSY | 429 |
INTERNAL | 500 |
SEARCH_CONSOLE_ERROR | 502 |
BUSY | 503 |
SEARCH_CONSOLE_UNAVAILABLE | 503 |
SERVICE_UNAVAILABLE | 503 |
WRITE_FROZEN | 503 |
Content Delivery API codes
| Code | HTTP status |
|---|---|
BAD_HOST | 400 |
FILE_TYPE_NOT_ALLOWED | 400 |
INVALID_ANSWERS | 400 |
INVALID_BODY | 400 |
INVALID_CURSOR | 400 |
INVALID_KIND | 400 |
INVALID_LIMIT | 400 |
INVALID_PATH | 400 |
INVALID_QUERY | 400 |
QUERY_REQUIRED | 400 |
QUERY_TOO_LONG | 400 |
QUERY_TOO_SHORT | 400 |
TOO_MANY_PARAMS | 400 |
UNKNOWN_BOT | 400 |
UNSUPPORTED_LOCALE | 400 |
VALIDATION | 400 |
VERIFICATION_EXPIRED | 400 |
NOT_PREVIEW | 403 |
COLLECTION_NOT_FOUND | 404 |
FORM_NOT_FOUND | 404 |
HEADER_NOT_FOUND | 404 |
ITEM_NOT_FOUND | 404 |
PAGE_NOT_FOUND | 404 |
PRODUCT_NOT_FOUND | 404 |
SITE_NOT_FOUND | 404 |
UNIT_NOT_FOUND | 404 |
DUPLICATE_SUBMISSION | 409 |
FILE_TOO_LARGE | 413 |
RATE_LIMITED | 429 |
SEARCH_BUSY | 429 |
QUERY_TIMEOUT | 503 |
UPLOAD_UNAVAILABLE | 503 |
UPSTREAM_UNAVAILABLE | 503 |
Customer API codes
| Code | HTTP status |
|---|---|
BAD_HOST | 400 |
INVALID_CODE | 400 |
INVALID_CURSOR | 400 |
INVALID_EMAIL | 400 |
INVALID_LIMIT | 400 |
VALIDATION | 400 |
UNAUTHENTICATED | 401 |
BOT_PROTECTION_FAILED | 403 |
DOWNLOAD_NOT_ALLOWED | 403 |
EXPIRED | 403 |
FORBIDDEN | 403 |
LIMIT_REACHED | 403 |
LOCKED | 403 |
NOT_RELEASED | 403 |
NO_ATTEMPTS_LEFT | 403 |
REVIEWS_DISABLED | 403 |
CERTIFICATE_DISABLED | 404 |
DELIVERABLE_NOT_FOUND | 404 |
NOT_FOUND | 404 |
NO_FILE | 404 |
NO_RECEIPT | 404 |
ORDER_NOT_FOUND | 404 |
SITE_NOT_FOUND | 404 |
UNIT_NOT_FOUND | 404 |
WEBSITE_NOT_FOUND | 404 |
METHOD_NOT_ALLOWED | 405 |
ALREADY_REVIEWED | 409 |
FILE_NOT_PROTECTED | 409 |
NOT_A_QUIZ | 409 |
QUIZ_NOT_READY | 409 |
ACCOUNT_BLOCKED | 422 |
ALREADY_REGISTERED | 422 |
CHALLENGE_EXPIRED | 422 |
EMAIL_NOT_VERIFIED | 422 |
METHOD_DISABLED | 422 |
VERIFY_FAILED | 422 |
RATE_LIMITED | 429 |
SHARED_SENDER_PAUSED | 503 |
SIGN_FAILED | 503 |
UPSTREAM_UNAVAILABLE | 503 |