跳到內容
繁體中文

API 驗證與安全

以 Session、CSRF、租戶權限及請求去重保護每次操作。

連線與驗證

目前提供同來源工作台 API,尚未提供個人 API Token 或公開服務端 API Key。請先登入,並使用瀏覽器管理的 Session Cookie。

http
GET /api/v1/auth/csrf HTTP/1.1
Accept: application/json
json
{
  "token": "<csrf-token>"
}

修改請求需帶 X-CSRF-TOKEN 及 Idempotency-Key。登入、登出後重新取得 token;不要把 Cookie、密碼或 token 寫入日誌。

快速開始

javascript
// 在同一站點的瀏覽器環境執行;沿用 Session Cookie。
const base = '/api/v1';
const csrf = async () => {
  const res = await fetch(base + '/auth/csrf', {
    credentials: 'same-origin', headers: { Accept: 'application/json' }
  });
  if (!res.ok) throw new Error('無法取得 CSRF');
  return (await res.json()).token;
};
let token = await csrf();
const login = await fetch(base + '/customer/auth/login', {
  method: 'POST', credentials: 'same-origin',
  headers: {
    Accept: 'application/json', 'Content-Type': 'application/json',
    'X-CSRF-TOKEN': token, 'Idempotency-Key': crypto.randomUUID()
  },
  body: JSON.stringify({ login: '[email protected]', password: '<password>' })
});
if (!login.ok) throw new Error('登入失敗');
token = await csrf(); // 登入會更新 Session,重新取得 token。
const res = await fetch(base + '/customer/posts?page=1&per_page=10', {
  credentials: 'same-origin', headers: { Accept: 'application/json' }
});
if (!res.ok) throw new Error('查詢失敗');
const data = await res.json();

修改資料、版本與重試

每個新操作產生一個 UUID,同一操作的重試沿用相同 UUID 與相同內容。revision 使用讀取文章或排程時回傳的最新值;成功後採用回應的新 revision。

http
PATCH /api/v1/customer/posts/81 HTTP/1.1
Content-Type: application/json
Accept: application/json
X-CSRF-TOKEN: <csrf-token>
Idempotency-Key: 9c5a7a92-a62a-4ff9-921f-5806be34797f
Cookie: <session-cookie>
json
{
  "revision": 2,
  "title": "文章標題",
  "excerpt": "文章摘要",
  "content": "<h2>第一段</h2><p>文章內容。</p>"
}

API 根路徑為 /api/v1。多租戶帳戶可帶 X-Workspace-ID 指定租戶;它是帳戶租戶 ID,與發布工作空間 workspace_id 不同。伺服器仍會驗證 membership,不能藉此存取其他租戶資料。

上傳圖片

使用 FormData,讓瀏覽器自動加入 multipart boundary;不要手動填入 JSON Content-Type。

javascript
const body = new FormData();
body.append('file', fileInput.files[0]);
body.append('revision', String(post.revision));
const response = await fetch('/api/v1/customer/posts/' + post.id + '/images', {
  method: 'POST', credentials: 'same-origin',
  headers: { Accept: 'application/json', 'X-CSRF-TOKEN': token,
    'Idempotency-Key': crypto.randomUUID() },
  body
});

HTTP 狀態與錯誤

狀態碼含義處理方式
401登入狀態失效重新登入。
403權限不足確認帳戶與租戶權限。
404資料不存在或不可存取確認資料 ID 屬於目前租戶。
409版本衝突或操作衝突重新讀取資料;檢查是否已有執行中的任務。
419CSRF/Session 已更新重新取得 CSRF token 再操作。
422欄位驗證或業務條件不符合閱讀 message 與 errors,修正參數。
429請求過於頻繁依 Retry-After 等候後重試。
500 / 502 / 503服務或上游異常先查生成/發布狀態;同一操作沿用 UUID。
json · 422 example
{
  "message": "The title field is required.",
  "errors": {
    "title": [
      "The title field is required."
    ]
  }
}

欄位驗證失敗可能包含 errors;其他錯誤以 HTTP 狀態碼與 message 為準。

查看 API 端點參考 →
新文章AI