# CathyColor API 串接指南（離線版）

本指南供現有客戶管理 API 金鑰並從伺服器端呼叫。新 API 銷售與新客戶帳戶開通目前暫停；現有客戶可繼續使用有效金鑰，續訂與支援服務持續。正式 API 網址為
`https://api.chinesecoloratlas.com`，可使用 161 種中國色。API 不提供完整色庫下載；瀏覽器也不能直接呼叫，因為不支援 CORS。

## 服務狀態與用量

- 新 API 銷售與新客戶帳戶開通目前暫停。現有客戶可繼續使用 API 和有效金鑰；續訂與支援服務持續。
- 現有帳戶每個 UTC 月包含 2,000 個顏色比對輸入（每個 RGB 顏色計一次）和 1,000 次文字搜尋。第一個額度週期可能不足一個月。額度於每個 UTC 月第一天重設，不會累積；達到硬性上限後會拒絕後續請求，不會自動加購或收取超額費用。本服務不提供服務水準協議（SLA）。

以下指令使用 POSIX 相容終端機，例如 macOS 或 Linux 終端機；尚未驗證 Windows 原生指令。需要 Node.js 20 或更新版本、`unzip` 和 `curl`。工具包沒有第三方相依套件，不需要執行 `npm install`。

## 1. 下載並解壓縮工具

請從線上 API 串接指南下載 `key-delivery-tools.zip`。將 ZIP 存到「下載項目」資料夾，解壓縮到私人工作資料夾，再於該資料夾執行指令。如果瀏覽器將 ZIP 存到其他位置，請修改 `unzip` 指令中的路徑。

```sh
mkdir -p ~/cathycolor-api
unzip ~/Downloads/key-delivery-tools.zip -d ~/cathycolor-api
cd ~/cathycolor-api
node --version
```

確認 Node.js 版本為 20 或更新版本。指令位於 `tools/api-key-delivery/`。工作資料夾請放在網站公開目錄和 Git 原始碼目錄之外。

## 2. 產生公鑰檔與私鑰檔

如現有帳戶需要支援團隊協助進行金鑰變更，公鑰 JWK 檔可讓 CathyColor 加密 API 金鑰，只有配對的私鑰能解開。僅在支援人員提出要求時提供公鑰檔；私鑰留在自己掌控的裝置上。JWK 是一種 JSON 金鑰檔格式。工具會產生所需的 3072-bit RSA-OAEP (SHA-256) 金鑰組，兩個檔案的權限皆為 `0600`，也不會覆寫已存在的檔案。

```sh
umask 077
node tools/api-key-delivery/generate-keypair.mjs \
  --public-out ./customer.public.jwk \
  --private-out ./customer.private.jwk
ls -l ./customer.public.jwk ./customer.private.jwk
```

請妥善保管 `customer.private.jwk`，絕不要透過電子郵件或其他方式傳給支援團隊。

## 3. 現有客戶金鑰支援

新 API 銷售與新客戶帳戶開通目前暫停。現有客戶可繼續使用有效金鑰，續訂與支援服務持續。如需現有帳戶協助，請使用帳戶電子郵件地址寄信至 [support@chinesecoloratlas.com](mailto:support@chinesecoloratlas.com)。僅在支援人員為現有帳戶金鑰變更提出要求時，才提供公鑰 JWK。

建議郵件主旨：`CathyColor API 支援`。

請勿附上 `customer.private.jwk`、API 金鑰、完整 `Authorization` 標頭或付款卡資料。請勿在公開議題或聊天中貼上任何金鑰。

## 4. 讀取加密金鑰回執

如支援團隊為現有帳戶金鑰變更提供加密回執，請將檔案存成 `provisioning-receipt.json`，放在私人工作資料夾中。回執中的 API 金鑰是加密資料，不是可直接讀取的明文。請勿修改檔案，並妥善保管。

```sh
umask 077
node tools/api-key-delivery/decrypt-envelope.mjs \
  --envelope ./provisioning-receipt.json \
  --private-key ./customer.private.jwk \
  --key-out ./cathycolor.api-key \
  --purpose cathycolor_api_key_provisioning
```

工具會驗證回執，並以 `0600` 權限將 API 金鑰寫入 `cathycolor.api-key`。它不會印出金鑰，也不會覆寫已存在的輸出檔。請將金鑰存入密鑰管理工具；不要在終端機錄影中顯示，也不要傳給支援團隊。

## 5. 驗證金鑰（執行一次）

請只使用發給你帳戶的有效金鑰。驗證會讀取 `/v1/library`（不消耗額度），並送出一次 `/v1/search` 請求（消耗 1 次搜尋額度）。重複執行會繼續消耗搜尋額度。

```sh
node tools/api-key-delivery/verify-key.mjs \
  --key-file ./cathycolor.api-key \
  --base-url https://api.chinesecoloratlas.com \
  --query red
```

成功時，`library.status` 和 `search.status` 都會顯示 HTTP `200`。工具會捨棄回應本文，只顯示狀態和非敏感用量資訊。如狀態不同，請保留請求資訊並聯絡支援團隊，不要傳送金鑰。

## 6. 呼叫 API

請在自己的後端環境執行以下範例。讀取金鑰時請關閉 Shell 追蹤；`API_KEY` 僅留在目前 Shell 中，不要匯出。

```sh
set +x
API_BASE_URL="https://api.chinesecoloratlas.com"
API_KEY_FILE="./cathycolor.api-key"
API_KEY="$(tr -d '\n' < "$API_KEY_FILE")"
```

### 讀取色庫資訊 — `GET /v1/library`

此免額度端點只回傳發佈版本資訊，不會回傳顏色資料。

```sh
curl --silent --show-error --include \
  --header "Authorization: Bearer $API_KEY" \
  "$API_BASE_URL/v1/library"
```

### 讀取目前用量 — `GET /v1/usage`

此免額度端點會回傳目前 UTC 月份的兩種用量。

```sh
curl --silent --show-error --include \
  --header "Authorization: Bearer $API_KEY" \
  "$API_BASE_URL/v1/usage"
```

### 比對 RGB 顏色 — `POST /v1/match`

一次傳送 1–5 個 RGB 顏色。每個輸入顏色消耗 1 次比對額度；選用參數 `top` 的範圍為 1–3。每個新的邏輯請求都要使用不同的冪等鍵。

```sh
MATCH_IDEMPOTENCY_KEY="match-$(node -e 'process.stdout.write(require("node:crypto").randomUUID())')"

curl --silent --show-error --include \
  --header "Authorization: Bearer $API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: $MATCH_IDEMPOTENCY_KEY" \
  --data '{"colors":[{"r":12,"g":34,"b":56}],"top":2}' \
  "$API_BASE_URL/v1/match"
```

### 搜尋色名 — `GET /v1/search`

每次搜尋消耗 1 次搜尋額度。去除前後空白後，`q` 必須為 2–64 個字元；`limit` 上限為 10。

```sh
SEARCH_IDEMPOTENCY_KEY="search-$(node -e 'process.stdout.write(require("node:crypto").randomUUID())')"

curl --silent --show-error --include \
  --header "Authorization: Bearer $API_KEY" \
  --header "Idempotency-Key: $SEARCH_IDEMPOTENCY_KEY" \
  "$API_BASE_URL/v1/search?q=black&limit=3"

unset API_KEY
```

API 只回傳有限的顏色資料，沒有可列出或下載完整色庫的客戶端端點。

## 7. 安全重試計量請求

`POST /v1/match` 和 `GET /v1/search` 必須帶上 `Idempotency-Key`。內容須為 8–128 個 ASCII 英文字母、數字或 `.`, `_`, `:`、`-`。每個新的邏輯請求都產生一組鍵。請求逾時、回傳 5xx 或 `409 request_in_progress` 時，使用同一組鍵重試完全相同的請求。成功重播不會再次扣量。同一組鍵搭配不同請求資料會回傳 `409 idempotency_conflict`；只有真正要送出新請求時才使用新鍵。

每個回應都包含 `X-Request-Id`。需要支援協助時，請將它與不含敏感資訊的請求紀錄一起提供。

## 8. 常見錯誤

| 狀態碼 | 含義與處理方式 |
| --- | --- |
| `400` | 計量請求缺少有效的 `Idempotency-Key`；請補上冪等鍵。 |
| `401` | API 金鑰遺漏、無效、已撤銷或過期。檢查金鑰檔與 `Authorization` 標頭，絕不要把金鑰傳給支援團隊。 |
| `403` | `account_unavailable`：停止重試，聯絡支援團隊並提供請求 ID 和錯誤資訊。 |
| `409` | `idempotency_conflict`：冪等鍵已用於不同請求；`request_in_progress`：使用同一組鍵重試完全相同的請求。 |
| `422` | 修正無效輸入，例如 RGB 色值超出 0–255、比對數量超出 1–5，或搜尋詞長度不在 2–64 個字元範圍內。 |
| `429` | `rate_limited` 表示觸發濫用防護，請遵循 `Retry-After`（通常為 60 秒）。`quota_exceeded` 表示月度硬性額度已用完，請遵循重試提示（通常為 86,400 秒）；這不代表額度會在那時重設。只有額度錯誤會附上用量標頭。 |
| `500` 或 `503` | 若計量請求結果不確定，請用相同冪等鍵重試完全相同的請求，並逐步拉長重試間隔。 |

請勿平行重試，也不要透過增加請求來繞過速率或額度限制。

## 9. 金鑰安全與支援

- 將私鑰 JWK、加密回執和 API 金鑰保存在私密位置；不要放入原始碼管理、工單、聊天、Shell 歷史、CI 日誌或終端機錄影。
- 如需計畫內輪替金鑰，請用訂閱電子郵件聯絡支援團隊，並且只附上新產生的公鑰 JWK。解密輪替回執時使用用途 `cathycolor_api_key_rotation`。
- 若懷疑金鑰外洩，請停止使用並聯絡支援團隊。不要附上私鑰 JWK、API 金鑰或完整 Authorization 標頭。
- 聯絡支援時，請提供訂閱電子郵件、請求路徑、UTC 時間、HTTP 狀態碼、錯誤碼和 `X-Request-Id`。不要傳送請求本文、RGB 數值、搜尋詞或任何憑證。

支援信箱：[support@chinesecoloratlas.com](mailto:support@chinesecoloratlas.com)

## 10. 資料範圍與署名

API 只提供目前 161 種顏色的商用資料。`/v1/library` 只回傳發佈資訊；比對與搜尋只回傳有限結果，不會列出完整顏色資料。請勿使用 API 重建、抓取、鏡像或再散布完整色庫。展示或衍生 API 回傳的顏色時，請保留版本或合約提供的 CathyColor / Chinese Color Atlas 署名，以及上游 MIT 署名。

`reliability` 表示來源可信度（`verified`、`attributed` 或 `disputed`），不代表每個現代 HEX 色值都是官方歷史標準。
