> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixroute.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# API Key 管理

> 透過系統 API 建立、搜尋、顯示、更新、停用、輪換和刪除 API Key。

## 概述

API Key 通過 `/api/token` 下的介面管理。這些介面使用[認證與額度](/zh-hant/api-reference/system-api/authentication-and-quota)中介紹的系統存取權杖。

<Warning>
  `PUT /api/token/` 是完整的可變設定更新，不是 JSON Merge Patch。請求中必須包含所有需要保留的設定。
</Warning>

## 可變欄位

| 欄位                     | 型別             | 說明                                 |
| ---------------------- | -------------- | ---------------------------------- |
| `id`                   | integer        | 更新時必填                              |
| `name`                 | string         | 顯示名稱，最多 50 個字元                     |
| `expired_time`         | integer        | Unix 秒級時間戳；`-1` 表示永不過期             |
| `remain_quota`         | integer        | 以內部單位表示的剩餘額度                       |
| `unlimited_quota`      | boolean        | 為 `true` 時取消 Key 級額度上限             |
| `model_limits_enabled` | boolean        | 是否啟用模型白名單                          |
| `model_limits`         | string         | 以逗號分隔的模型 ID                        |
| `allow_ips`            | string or null | 以換行分隔的 IP 或 CIDR；空字串或 `null` 表示不限制 |
| `group`                | string         | 路由與計費分組                            |
| `cross_group_retry`    | boolean        | 跨分組重試，僅對受支援的自動分組有效                 |
| `smart_routing`        | boolean        | 是否為智慧路由 Key                        |
| `smart_route_tiers`    | string         | JSON 字串形式的智慧路由層級設定                 |

## 建立一般 API Key

```bash theme={null}
curl -fsS -X POST "$BASE_URL/api/token/" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ci-deployment",
    "expired_time": -1,
    "remain_quota": 0,
    "unlimited_quota": true,
    "model_limits_enabled": false,
    "model_limits": "",
    "allow_ips": "",
    "group": "default",
    "cross_group_retry": false,
    "smart_routing": false,
    "smart_route_tiers": ""
  }' | jq
```

建立成功的回應不會傳回記錄 ID。請使用唯一名稱建立，再通過列表或搜尋介面定位新記錄。

## 列表與搜尋

一般 Key 列表預設排除智慧路由 Key：

```bash theme={null}
curl -fsS "$BASE_URL/api/token/?p=1&size=20" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" | jq
```

設定 `exclude_smart_routing=false` 可包含所有 Key：

```bash theme={null}
curl -fsS "$BASE_URL/api/token/?p=1&size=20&exclude_smart_routing=false" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" | jq
```

分頁大小參數支援 `size`、`page_size` 和 `ps`，每頁最多 100 條。

按名稱或已儲存的 Key 值搜尋：

```bash theme={null}
curl -fsS --get "$BASE_URL/api/token/search" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" \
  --data-urlencode "keyword=ci-deployment" \
  --data-urlencode "p=1" \
  --data-urlencode "size=20" | jq
```

可選的 `token` 查詢參數支援帶或不帶 `sk-` 字首的 Key。列表、搜尋和單條讀取回應中的 Key 始終經過掩碼處理。

## 讀取與顯示完整 Key

讀取掩碼記錄：

```bash theme={null}
curl -fsS "$BASE_URL/api/token/42" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" | jq
```

顯示完整儲存值：

```bash theme={null}
stored_key=$(curl -fsS -X POST "$BASE_URL/api/token/42/key" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" \
  | jq -er '.data.key')

api_key="sk-${stored_key#sk-}"
```

顯示介面返回的儲存值不會自動新增 `sk-`。請把回應直接寫入金鑰管理系統，不要列印到日誌。

一次最多顯示 100 個 Key：

```bash theme={null}
curl -fsS -X POST "$BASE_URL/api/token/batch/keys" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" \
  -H "Content-Type: application/json" \
  -d '{"ids":[42,43]}'
```

## 安全更新 Key

先讀取目前記錄，構造完整的可變欄位請求內容，然後只修改目標欄位：

```bash theme={null}
current=$(curl -fsS "$BASE_URL/api/token/42" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID")

payload=$(jq '.data | {
  id,
  name,
  expired_time,
  remain_quota,
  unlimited_quota,
  model_limits_enabled,
  model_limits,
  allow_ips,
  group,
  cross_group_retry,
  smart_routing,
  smart_route_tiers
} | .name = "ci-deployment-v2"' <<< "$current")

curl -fsS -X PUT "$BASE_URL/api/token/" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" \
  -H "Content-Type: application/json" \
  -d "$payload" | jq
```

該讀取、修改、寫回流程可以保留模型限制和智慧路由設定。

## 啟用或停用

僅更新狀態不會替換其他設定：

```bash theme={null}
curl -fsS -X PUT "$BASE_URL/api/token/?status_only=true" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" \
  -H "Content-Type: application/json" \
  -d '{"id":42,"status":2}' | jq
```

| 狀態  | 含義    |
| --- | ----- |
| `1` | 已啟用   |
| `2` | 手動停用  |
| `3` | 已過期   |
| `4` | 額度已耗盡 |

過期或額度耗盡的 Key 必須先修正過期時間或額度，之後才能重新啟用。

## 刪除 Key

刪除一個 Key：

```bash theme={null}
curl -fsS -X DELETE "$BASE_URL/api/token/42" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" | jq
```

批次刪除目前帳號擁有的 Key：

```bash theme={null}
curl -fsS -X POST "$BASE_URL/api/token/batch" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "New-Api-User: $USER_ID" \
  -H "Content-Type: application/json" \
  -d '{"ids":[42,43]}' | jq
```

批次回應的 `data` 是實際刪除的記錄數量。

## 完整生命週期腳本

以下指令碼建立一個有效期為一小時、使用美元金額換算額度的 Key，然後完成定位、讀取完整 Key、更新、停用和刪除。指令碼不會把完整 Key 列印到標準輸出。

```bash theme={null}
#!/usr/bin/env bash
set -euo pipefail

: "${BASE_URL:=https://api.mixroute.ai}"
: "${ACCESS_TOKEN:?Set ACCESS_TOKEN}"
: "${USER_ID:?Set USER_ID}"

auth=(
  -H "Authorization: Bearer $ACCESS_TOKEN"
  -H "New-Api-User: $USER_ID"
)

name="automation-$(date +%s)-$RANDOM"
token_id=""

delete_token() {
  local response
  response=$(curl -fsS -X DELETE "$BASE_URL/api/token/$token_id" \
    "${auth[@]}")
  jq -e '.success == true' <<< "$response" >/dev/null
}

cleanup() {
  if [[ -n "$token_id" ]]; then
    delete_token >/dev/null 2>&1 || true
  fi
}
trap cleanup EXIT

quota_per_unit=$(curl -fsS "$BASE_URL/api/status" | jq -er '.data.quota_per_unit')
expires_at=$(( $(date +%s) + 3600 ))
quota=$(( 5 * quota_per_unit ))

create_payload=$(jq -n \
  --arg name "$name" \
  --argjson expires "$expires_at" \
  --argjson quota "$quota" '{
    name: $name,
    expired_time: $expires,
    remain_quota: $quota,
    unlimited_quota: false,
    model_limits_enabled: false,
    model_limits: "",
    allow_ips: "",
    group: "default",
    cross_group_retry: false,
    smart_routing: false,
    smart_route_tiers: ""
  }')

created=$(curl -fsS -X POST "$BASE_URL/api/token/" \
  "${auth[@]}" -H "Content-Type: application/json" \
  -d "$create_payload")
jq -e '.success == true' <<< "$created" >/dev/null

found=$(curl -fsS --get "$BASE_URL/api/token/search" \
  "${auth[@]}" --data-urlencode "keyword=$name" \
  --data-urlencode "p=1" --data-urlencode "size=10")
token_id=$(jq -er --arg name "$name" '
  [.data.items[] | select(.name == $name)]
  | if length == 1 then .[0].id
    else error("expected exactly one matching API key")
    end
' <<< "$found")

stored_key=$(curl -fsS -X POST "$BASE_URL/api/token/$token_id/key" \
  "${auth[@]}" | jq -er '.data.key')
api_key="sk-${stored_key#sk-}"
# 將下一行空操作替換為金鑰管理系統命令。
: "$api_key"
unset stored_key api_key

current=$(curl -fsS "$BASE_URL/api/token/$token_id" "${auth[@]}")
update_payload=$(jq --argjson quota "$((10 * quota_per_unit))" '.data | {
  id, name, expired_time, remain_quota, unlimited_quota,
  model_limits_enabled, model_limits, allow_ips, group,
  cross_group_retry, smart_routing, smart_route_tiers
} | .remain_quota = $quota' <<< "$current")

curl -fsS -X PUT "$BASE_URL/api/token/" \
  "${auth[@]}" -H "Content-Type: application/json" \
  -d "$update_payload" | jq -e '.success == true' >/dev/null

curl -fsS -X PUT "$BASE_URL/api/token/?status_only=true" \
  "${auth[@]}" -H "Content-Type: application/json" \
  -d "{\"id\":$token_id,\"status\":2}" \
  | jq -e '.success == true' >/dev/null

delete_token
token_id=""
trap - EXIT
echo "API key lifecycle completed"
```
