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

# 订阅 CRUD

> 通过开放 API 创建、读取、更新和删除订阅，并提供适合 AI Agent 的任务语义。

# 订阅 CRUD

订阅 API 使用 camelCase 字段。服务端管理字段会在响应中返回，但不能出现在写请求里。

## 操作语义

| 操作 | 适用场景 | 风险 | AI 是否需要确认 |
| - | - | - | - |
| `GET /api/v1/subscriptions` | 查询、搜索、汇总、分析或识别订阅 | 低 | 不需要 |
| `GET /api/v1/subscriptions/{id}` | 已知 UUID，读取单条订阅 | 低 | 不需要 |
| `POST /api/v1/subscriptions` | 记录一个新的订阅 | 中 | 需要 |
| `PATCH /api/v1/subscriptions/{id}` | 修改可写字段 | 中 | 需要 |
| `DELETE /api/v1/subscriptions/{id}` | 永久删除本地追踪记录 | 高 | 需要 |

AI 集成在更新或删除前，应该先查询并确认目标订阅；除非用户已经提供了准确的订阅 UUID。写操作需要带 `write` 权限的 API Key；只读 Key 会收到 `403 insufficient_scope`。

## 分页

`GET /api/v1/subscriptions` 按创建时间倒序返回，支持两个可选查询参数：

| 参数 | 默认值 | 规则 |
| - | - | - |
| `limit` | `50` | 每页数量，范围 1 到 100 |
| `offset` | `0` | 从开头跳过的记录数 |

响应中包含 `pagination` 对象。当 `hasMore` 为 `true` 时，用 `offset + limit` 获取下一页。

```json theme={null}
{
  "data": [ /* ... */ ],
  "pagination": { "limit": 50, "offset": 0, "hasMore": false },
  "requestId": "request-..."
}
```

```bash theme={null}
curl -H "Authorization: Bearer $SUBSCRIPTION_MANAGER_API_KEY" \
  "https://your-site.example/api/v1/subscriptions?limit=50&offset=50"
```

超出范围的取值会返回 `400 invalid_pagination`。

## 过滤与排序

`GET /api/v1/subscriptions` 在分页之外，还支持以下可选过滤器和排序：

| 参数 | 规则 |
| - | - |
| `status` | `active`、`paused`、`cancelled` 之一 |
| `category` | 分类精确匹配，如 `Streaming` |
| `period` | `monthly`、`yearly`、`custom` 之一 |
| `q` | 对订阅名称不区分大小写搜索 |
| `expiringBefore` | `YYYY-MM-DD`；返回 `nextPaymentDate` 在该日期当天或之前的记录 |
| `sort` | `createdAt`、`-createdAt`、`nextPaymentDate`、`-nextPaymentDate`、`amount`、`-amount`、`name`、`-name` 之一（默认 `-createdAt`，前缀 `-` 表示降序） |

将 `status=active` 与 `expiringBefore` 组合即可回答「哪些即将续费」。非法取值返回 `400 invalid_query`，并带 `field` 与 `suggestedFix`。

```bash theme={null}
curl -H "Authorization: Bearer $SUBSCRIPTION_MANAGER_API_KEY" \
  "https://your-site.example/api/v1/subscriptions?status=active&expiringBefore=2026-07-01&sort=nextPaymentDate"
```

响应会回显实际生效的查询，便于 Agent 确认结果来源：

```json theme={null}
{
  "data": [ /* ... */ ],
  "pagination": { "limit": 50, "offset": 0, "hasMore": false },
  "query": { "sort": "nextPaymentDate", "filters": { "status": "active", "expiringBefore": "2026-07-01" } },
  "requestId": "request-..."
}
```

## 订阅对象

```json theme={null}
{
  "id": "33333333-3333-4333-8333-333333333333",
  "name": "Netflix",
  "category": "Streaming",
  "amount": 15.99,
  "currency": "USD",
  "period": "monthly",
  "lastPaymentDate": "2026-06-01",
  "nextPaymentDate": "2026-07-01",
  "billingAnchorDay": 1,
  "notificationEnabled": true,
  "status": "active",
  "createdAt": "2026-06-16T00:00:00.000Z",
  "updatedAt": "2026-06-16T00:00:00.000Z"
}
```

## 可写字段

```json theme={null}
{
  "name": "Netflix",
  "category": "Streaming",
  "amount": 15.99,
  "currency": "USD",
  "period": "monthly",
  "nextPaymentDate": "2026-07-01",
  "billingAnchorDay": 1,
  "customDate": null,
  "notificationEnabled": true,
  "status": "active"
}
```

服务端管理这些字段：

* `id`
* `createdAt`
* `updatedAt`

不要在 `POST` 或 `PATCH` 请求里发送服务端管理字段。

## 字段规则

| 字段 | 规则 |
| - | - |
| `name` | 必填，1-120 个字符 |
| `category` | 必填，1-80 个字符 |
| `amount` | 必填数字，范围 0 到 999999.99，最多 2 位小数 |
| `currency` | 必填，可选 `CNY`、`USD`、`EUR`、`JPY`、`GBP`、`AUD`、`CAD`、`CHF`、`HKD`、`SGD` |
| `period` | 必填，可选 `monthly`、`yearly`、`custom` |
| `nextPaymentDate` | 必填，下次续费日期，格式为 `YYYY-MM-DD` |
| `billingAnchorDay` | 月付订阅可选，范围 1-31；通常根据 `nextPaymentDate` 自动推断 |
| `lastPaymentDate` | 已弃用的兼容输入；未提供 `nextPaymentDate` 时会转换为下次续费日期 |
| `customDate` | 仅当 `period` 为 `custom` 时必填；表示间隔天数，需为正整数字符串 |
| `notificationEnabled` | 可选布尔值，默认 `true` |

`nextPaymentDate` 是权威的订阅计划日期。月付订阅通过 `billingAnchorDay` 保留原始日历日期，短月份只会临时落到月末，例如：1 月 31 日 → 2 月 28/29 日 → 3 月 31 日。如果服务是固定每 30 天扣费，而不是每月固定日期，请使用 `period: "custom"` 和 `customDate: "30"`。响应中的 `lastPaymentDate` 只是反推得到的兼容字段，新集成不应再依赖它。

## 状态 vs 删除

响应中会返回只读的 `status`（`active`、`paused`、`cancelled`），列表查询也可以按它过滤。公开 API **不能** 通过写入 `status` 来取消、暂停或恢复订阅。需要移除追踪记录时使用 `DELETE`。

在[分析](/docs/zh-CN/api/analytics)端点中，只有 `active` 订阅计入活跃支出。

## 自然语言示例

### 新增订阅

用户意图：

```text theme={null}
帮我记录 ChatGPT Plus，每月 20 美元，下次续费是 2026-07-17。
```

API 调用：

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer $SUBSCRIPTION_MANAGER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"ChatGPT Plus","category":"AI","amount":20,"currency":"USD","period":"monthly","nextPaymentDate":"2026-07-17","notificationEnabled":true}' \
  https://your-site.example/api/v1/subscriptions
```

### 修改计费周期

用户意图：

```text theme={null}
把 Netflix 改成年付。
```

Agent 流程：

1. 调用 `GET /api/v1/subscriptions` 找到 Netflix 记录。
2. 向用户确认具体记录和修改内容。
3. 调用 `PATCH /api/v1/subscriptions/{id}`。

```bash theme={null}
curl -X PATCH \
  -H "Authorization: Bearer $SUBSCRIPTION_MANAGER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"period":"yearly"}' \
  https://your-site.example/api/v1/subscriptions/33333333-3333-4333-8333-333333333333
```

### 删除重复记录

用户意图：

```text theme={null}
删除重复的 Netflix 订阅。
```

Agent 流程：

1. 调用 `GET /api/v1/subscriptions` 找到重复候选。
2. 向用户确认订阅名称和 id。
3. 调用 `DELETE /api/v1/subscriptions/{id}`。

```bash theme={null}
curl -X DELETE \
  -H "Authorization: Bearer $SUBSCRIPTION_MANAGER_API_KEY" \
  https://your-site.example/api/v1/subscriptions/33333333-3333-4333-8333-333333333333
```

## 自定义计费周期

如果不是月付或年付，把 `period` 设为 `custom`，并把 `customDate` 设为表示天数的正整数字符串。

```json theme={null}
{
  "name": "Domain renewal",
  "category": "Infrastructure",
  "amount": 12,
  "currency": "USD",
  "period": "custom",
  "nextPaymentDate": "2026-07-16",
  "customDate": "45"
}
```

固定每 30 天续费时，把 `customDate` 设为 `"30"`；不要选择 `monthly`。

从 `custom` 改回 `monthly` 或 `yearly` 时，省略 `customDate`。服务端会清理旧的自定义计费数据。

## AI tool schema

使用 [ai-tools.json](/docs/api/ai-tools.json) 获取 tool/function 定义、风险等级和确认提示。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.