總覽
cairn 是多租戶旅行社營運平台。你用 bearer token 對租戶自己的網域呼叫 API 或 CLI,操作那個租戶——和租戶在後台做的事完全等價。
每個旅行社(租戶)有自己的網域與資料,彼此完全隔離。本篇建立四個基本概念:認證與租戶、權限、模組、錯誤格式;其餘各篇深入單一領域(訂單與金流、付款…)。
API 等同後台
凡是人在後台網頁能做的操作,API 與 CLI 都做得到——而且走相同的業務規則、相同的權限檢查、相同的稽核。API 不是另一條捷徑或子集,是後台的同義傳輸層。
CLI 只是 API 的命令列封裝;CLI 參考每個命令都標了它對應的 /api/v1 端點。
認證與租戶
- 每個請求帶
Authorization: Bearer <token>。 - 你打哪個租戶的網域,就操作哪個租戶。token 與工作階段隨租戶網域天然隔離;你無法用一個租戶的 token 存取另一個租戶。
- token 對應一個使用者與其角色,決定你能呼叫哪些端點。
curl https://your-tenant.example.com/api/v1/orders \
-H "Authorization: Bearer $CAIRN_TOKEN"
權限與角色
每個 token 屬於一個使用者,使用者有角色;角色決定授權範圍。
| 角色 | 典型範圍 |
|---|---|
admin | 全功能 + 使用者管理 |
sales | 自己經手的訂單與客戶 |
op | 出團作業、線控 |
accountant | 財務、核簽、報表 |
- API 參考每個端點都標了它要求的權限(如
order.read、order.write)。token 權限不足時回403 forbidden。 - 部分端點有 owner-scope:例如業務只看得到自己經手的訂單。範圍由伺服器依 token 的使用者重新判定,不接受用參數覆寫。
模組
部分進階功能屬可選模組,租戶可能未啟用:
| 模組 | 涵蓋 |
|---|---|
| 訂房(lodging) | 住宿庫存與直訂 |
| 進階會計(accounting) | 內外帳、損益、結算 |
| 登山(climbing) | 登山審核、裝備 |
| 海外(overseas) | 海外團 |
| 抽籤(lottery) | 名額抽籤 |
呼叫未啟用模組的端點會回 403 module_disabled。
錯誤格式
所有 /api/v1 回應都是統一信封。成功:
{ "ok": true, "data": { /* … */ } }
失敗:
{ "ok": false, "error": { "code": "validation", "message": "…", "issues": [ /* … */ ] } }
常見錯誤碼:
| code | HTTP | 意義 |
|---|---|---|
unauthorized | 401 | 無效或缺少 bearer token |
forbidden | 403 | 權限不足 |
module_disabled | 403 | 模組未啟用 |
not_found | 404 | 資源不存在,或不在你的可見範圍 |
conflict / invariant | 409 | 狀態衝突(如重複、座位不足) |
validation | 422 | 輸入未通過驗證(附 issues[] 逐欄說明) |
主要資源
| 領域 | 資源 |
|---|---|
| 銷售與出團 | trips、departures、orders |
| 客戶與名單 | members、travelers(掛在 order 下)、agencies |
| 金流 | payments、payment-requests、payouts |
| 出團作業 | guides、guide-roster、equipment |
| 財務會計 | pnl、internal-external-ledger、reconciliation |
| 設定 | settings、roles、discount-codes |