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

# 错误和限流

> 开放 API 的错误响应、requestId、rate limit headers 和 CORS 行为。

# 错误和限流

错误响应使用稳定 JSON 结构：

```json theme={null}
{
  "error": {
    "code": "invalid_subscription",
    "message": "Invalid option",
    "field": "period",
    "suggestedFix": "Use one of the supported billing periods: monthly, yearly, custom.",
    "allowedValues": ["monthly", "yearly", "custom"]
  },
  "requestId": "request-..."
}
```

当服务端能定位具体修复方式时，会返回 `field`、`suggestedFix`、`allowedValues` 或 `writableFields`。AI Agent 应优先使用这些字段修正请求，而不是自行猜测。

## 常见错误码

|   状态码 | Code                         | 说明                          |
| ----: | ---------------------------- | --------------------------- |
| `400` | `invalid_json`               | 请求体不是合法 JSON 对象             |
| `400` | `invalid_subscription`       | 订阅字段未通过校验                   |
| `400` | `invalid_subscription_field` | 请求尝试写入服务端管理字段               |
| `400` | `invalid_subscription_id`    | 订阅 ID 不是合法 UUID             |
| `400` | `invalid_pagination`         | `limit` 或 `offset` 查询参数超出范围 |
| `400` | `invalid_query`              | 过滤或 `sort` 查询参数非法           |
| `400` | `empty_patch`                | PATCH 请求体没有包含任何可写字段         |
| `401` | `authentication_required`    | 缺少 Bearer token             |
| `401` | `invalid_api_key`            | API Key 无效或已撤销              |
| `403` | `insufficient_scope`         | API Key 缺少该操作所需的 `write` 权限 |
| `404` | `subscription_not_found`     | 当前 API Key owner 下不存在该订阅    |
| `405` | `method_not_allowed`         | HTTP method 不支持             |
| `429` | `rate_limit_exceeded`        | 用户请求限额或无效认证限额已耗尽            |
| `500` | `internal_error`             | 未预期的服务端错误                   |

## 恢复字段

| 字段               | 含义                              |
| ---------------- | ------------------------------- |
| `field`          | 导致错误的请求字段                       |
| `suggestedFix`   | 人和 AI 都能读懂的修正建议                 |
| `allowedValues`  | `currency` 或 `period` 等枚举字段的合法值 |
| `writableFields` | 订阅 `POST` 和 `PATCH` 请求接受的可写字段   |

不可写字段示例：

```json theme={null}
{
  "error": {
    "code": "invalid_subscription_field",
    "message": "Field is not writable: nextPaymentDate",
    "field": "nextPaymentDate",
    "suggestedFix": "Remove server-managed fields such as id, nextPaymentDate, createdAt, and updatedAt before retrying.",
    "writableFields": [
      "amount",
      "category",
      "currency",
      "customDate",
      "lastPaymentDate",
      "name",
      "notificationEnabled",
      "period",
      "status"
    ]
  },
  "requestId": "request-..."
}
```

## 权限范围（Scopes）

API Key 带有 scopes。`read` Key 可以查询、读取订阅，并调用分析与审计端点；`write` Key 额外允许创建、更新、取消、暂停、恢复和删除。用只读 Key 执行写操作会返回 `403 insufficient_scope`，此时不要重试——需要换用带 `write` 权限的 Key。详见 [API 认证](/zh-CN/api/authentication#权限范围-scopes)。

## Rate limit headers

认证成功后的响应会包含：

```text theme={null}
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-Reset
```

`X-RateLimit-Reset` 是 Unix 秒级时间戳，表示当前固定窗口何时重置。

校验失败（`400`）会在扣减每小时限额之前被拒绝，因此不计入限额，也不带 rate limit headers。修正请求体后重试是「免费」的。

`429` 响应还会带 `Retry-After` header，表示需要等待多少秒后再重试。它同时适用于「用户请求限额」和「无效 API Key 尝试过多」两种封锁。

```text theme={null}
Retry-After: 2700
```

## CORS

订阅 API 支持浏览器预检请求：

```text theme={null}
OPTIONS /api/v1/subscriptions
OPTIONS /api/v1/subscriptions/{id}
```

允许的方法：

```text theme={null}
GET, POST, PATCH, DELETE, OPTIONS
```

允许的 headers：

```text theme={null}
Authorization, Content-Type
```

不要把 API Key 暴露在不可信浏览器环境里。CORS 主要用于开发者工具、内部面板或可信本地工作流。
