---
title: "Update Plan"
method: PUT
path: "/admin/plans/{plan_id}"
---

# Update Plan

`PUT /admin/plans/{plan_id}`

## Request

- Base URL: `https://api.twtapi.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.twtapi.com/admin/plans/{plan_id}`
- Auth: none declared

Update an existing plan.

与创建的区别：credits 的换算带 fallback_credits=plan.credits，即当套餐不是
API 类型（不参与反推）时保留原有积分值，避免改个名字就把积分清零。

改完会调 _sync_plan_user_entitlements 给在期用户补差，让新额度立刻生效；
返回体里带 synced_users 告知运营影响了多少人。

副作用：写库 + 给用户补积分（会写 CreditLog）+ 清套餐缓存与相关用户缓存。
顺序上先 commit 套餐本身、再补用户权益，保证套餐改动不会被后面的失败带崩。

## Path parameters

- `plan_id` integer, required

## Request body

- AdminPlanUpsert: Create or update a plan row. 中文：后台套餐的新增/编辑入参（同一模型服务两个动作）。 注意这里没有 ``id``：更新时由路径参数指定目标，新增时不带 id。 字段与 models.Plan 一一对应，改动需两侧同步。
  - `plan_type` string
  - `name` string, required
  - `price` number
  - `subscription_price` number
  - `currency` string
  - `monthly_limit` integer
  - `rate_limit_per_second` integer, nullable
  - `rate_limit_per_hour` integer, nullable
  - `features` string[]
  - `is_popular` boolean
  - `button_text` string
  - `button_style` string
  - `billing_mode` string
  - `trial_period` string, nullable
  - `validity_period` string
  - `overage_price_per_call` number, nullable
  - `sort_order` integer
  - `is_active` boolean

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/twtapi/apis/twtapi-backend.md) · [All operations](https://skmtc.dev/twtapi/apis/twtapi-backend/llms.txt) · [OpenAPI document](https://skmtc.dev/twtapi/apis/twtapi-backend/revisions/5295976febaf?raw)
