# 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 值都是官方历史标准。
