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

# 端点参考

> 开放 API 的全部资源——方法、路径、状态码、错误包络与限流规则。

所有路径都挂在 `$BASE/v1` 下,并要求 `Authorization: Bearer <secret>`。本页是地图,全集在两处:

* 本 tab 的\*\*「接口」\*\*分组逐一收录每个操作——完整的请求/响应结构、逐字段说明,并带 **Try it** 调试台,可以直接用你的密钥发起调用。
* API 也会自我描述:`GET $BASE/openapi.json` 是 OpenAPI 3.1 规范(可用于生成客户端),`$BASE/docs` 由你的部署直接提供同一份交互式文档。

## 活动

| 方法与路径                               | 作用                                                             |
| ----------------------------------- | -------------------------------------------------------------- |
| `GET /v1/events`                    | 列出业务单元的活动,含所有状态                                                |
| `POST /v1/events`                   | 创建(以**草稿**出生);`name`、`timezone`,可选 `startsAt`/`endsAt`         |
| `GET /v1/events/{eventId}`          | 单个活动                                                           |
| `PATCH /v1/events/{eventId}`        | 修改名称、日期、时区、`status`(`draft`/`published`/`archived`)、`currency` |
| `POST /v1/events/{eventId}/archive` | 归档——活动永不删除                                                     |

控制台的规则原样生效:发布需要开始时间(`400`);活动一旦产生过订单,**币种即锁定**(`412`);变更起始**日期**会清空议程——第一次尝试返回 `412`,带上 `"confirmAgendaReset": true` 重发才会执行。

## 票种

| 方法与路径                                      | 作用                                                                                                                          |
| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/ticket-types`    | 列表,含 `counts`(已确认/候补中)                                                                                                      |
| `POST …/ticket-types`                      | 创建(以**草稿**出生):`name`、`capacity`(null = 不限)、`priceAmount`、`allowWaitlist`、`isPublic`、`requiresApproval`、`opensAt`/`closesAt` |
| `GET …/ticket-types/{typeId}`              | 单个票种                                                                                                                        |
| `PATCH …/ticket-types/{typeId}`            | 以上任意字段,外加 `status` ——生命周期为 `draft → open ⇄ closed → archived`                                                               |
| `GET …/ticket-types/{typeId}/availability` | `{ capacity, confirmed, waitlisted, held, remaining }`                                                                      |

改价永远不会改写已售订单——订单上的金额是购买时刻的快照。权益绑定、报名表单与退款政策在控制台配置,不经 API。

## 报名

| 方法与路径                                    | 作用                                                   |
| ---------------------------------------- | ---------------------------------------------------- |
| `GET /v1/events/{eventId}/registrations` | 列表,最新在前;`?status=` 过滤                                |
| `POST …/registrations`                   | 录入:`email`,可选 `name`,`registrationTypeId`(活动启用票种时必填) |
| `GET …/registrations/{id}`               | 单条报名                                                 |
| `POST …/registrations/{id}/approve`      | 审批通过一条 `pending` 申请                                  |
| `POST …/registrations/{id}/reject`       | 驳回;可选 `reason`                                       |
| `POST …/registrations/{id}/cancel`       | 释放名额(若由兑换码入场,同时释放该次使用)                               |
| `GET …/registrations/{id}/perks`         | 此人的生效权益:票种 ∪ 兑换码 ∪ 个人授予                              |

需要为之设计的行为:

* **审批模式的票种,API 录入落在 `pending`** ——与控制台操作员不同,API 不代表准入决定,需显式审批。
* **票已满** → `412`(票种开候补则落 `waitlisted`)。
* **邮箱重复** → `200` 且 `"created": false`,返回已有报名——绝不重复,绝不报错。
* 审批/驳回只对 `pending` 生效;其余状态返回 `412`。
* 每条报名带 `checkinCode`(`CHK-…`)——签到用的胸卡凭证。

## 兑换码

| 方法与路径                                       | 作用                                                                                                    |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/redemption-codes` | 列表,含实时 `uses` 用量                                                                                      |
| `POST …/redemption-codes`                   | 生成:`registrationTypeId`,可选 `count`(批量)、`code`(自定义,强制单张)、`label`、`maxUses`(默认 1,null = 不限)、`expiresAt` |
| `GET …/redemption-codes/lookup?code=`       | 验码:买家输码后预览——解锁哪张票(含隐藏票)、这次入场附带的权益、折后价。一切无效形态都是同一个 404                                                 |
| `POST …/redemption-codes/{codeId}/disable`  | 禁用——兑换码永不删除                                                                                           |

自定义 `code` 与活动内已有的重复时返回 `409`。

## 加购与捆绑

| 方法与路径                                                              | 作用                                                                          |
| ------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| `GET/POST /v1/events/{eventId}/addons`,`GET/PATCH …/addons/{id}`   | 加购项配置;可售项生命周期(`draft → open ⇄ closed → archived`)                           |
| `GET/POST /v1/events/{eventId}/bundles`,`GET/PATCH …/bundles/{id}` | 捆绑配置                                                                        |
| `PUT …/bundles/{id}/items`                                         | 整体替换捆绑内容:`[{ itemType: "registration_type" \| "addon", itemId, quantity }]` |

捆绑内每个项目必须是同一活动中真实存在的票种或加购项(否则 `400`)。

## 订单与购买流

| 方法与路径                                 | 作用                                                                                                                                                      |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/orders`     | 列表,含订单行                                                                                                                                                 |
| `GET …/orders/{orderId}`              | 单条订单                                                                                                                                                    |
| `POST …/orders`                       | 下单:`email`,可选 `name`、`items`(`registration_type` / `addon` / `bundle`)、`redemptionCode`、`responses`。占位 15 分钟;已报名的买家返回 `alreadyRegistered: true`         |
| `POST …/orders/{orderNumber}/confirm` | 免费单 → 当场结清并履约(`status: "paid"`)。付费单 → `status: "awaiting_payment"` + `paymentUrl`(Stripe 托管页);必须携带 `successUrl`/`cancelUrl`(https;本地 localhost 允许 http) |
| `POST …/orders/{orderNumber}/cancel`  | 立即释放占位;幂等                                                                                                                                               |

付费单的结算由平台的 Stripe webhook 完成——轮询订单直到 `paid`。退款仍是控制台决定。端到端全流程见 [Headless 购买流](/zh/developers/checkout)。

## 签到

| 方法与路径                               | 作用                                                                                                                                                  |
| ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /v1/events/{eventId}/checkins` | 列表;过滤 `?subjectType=`、`?subjectId=`、`?registrationId=`                                                                                              |
| `POST …/checkins`                   | 记录:`registrationId` **或** `checkinCode`,加 `subjectType`(`event` / `session` / `venue`),session/venue 门需要 `subjectId`,可选 `method`(`scan` / `manual`) |

只有 `confirmed` 状态的报名能签到(`412`)。同一扇门第二次扫码返回 `200` 和 `"alreadyCheckedIn": true`。

## 议程、讲者与场地

| 方法与路径                               | 作用                                                      |
| ----------------------------------- | ------------------------------------------------------- |
| `GET /v1/events/{eventId}/sessions` | 议程,按时间排序:标题、起止、`venueId`,以及该场自己的权益门 `perkIds`(空 = 人人可入) |
| `GET /v1/events/{eventId}/speakers` | 讲者阵容:姓名、头衔、简介、`registrationId`、`sessionIds`             |
| `GET /v1/events/{eventId}/venues`   | 场地,各带自己的权益门 `perkIds` ——场次在自身的门之上继承其场地的门                |

## 参会者

| 方法与路径                                | 作用                      |
| ------------------------------------ | ----------------------- |
| `GET /v1/events/{eventId}/attendees` | 只读:每人一条,含其报名 ID 列表与当前状态 |

## 错误包络

所有错误,无论状态码,穿同一件外衣:

```json theme={null}
{
  "error": {
    "code": 404,
    "status": "NOT_FOUND",
    "message": "Event not found.",
    "details": []
  }
}
```

| HTTP | `status`              | 何时出现                                                  |
| ---- | --------------------- | ----------------------------------------------------- |
| 400  | `INVALID_ARGUMENT`    | 请求体或参数不合法;`details` 携带字段级问题                           |
| 401  | `UNAUTHENTICATED`     | 密钥缺失、未知、已吊销或已过期——刻意不可区分                               |
| 404  | `NOT_FOUND`           | 资源不在你密钥的业务单元内。别人的 id 与不存在的 id 回答完全一致——API 永远不确认别处存在什么 |
| 409  | `ALREADY_EXISTS`      | 自定义兑换码与已有的重复                                          |
| 412  | `FAILED_PRECONDITION` | 业务规则拦下了它:售罄、币种锁定、非 pending、非 confirmed、议程重置未确认        |
| 429  | `RESOURCE_EXHAUSTED`  | 触发限流——见下                                              |

## 限流与重试

每把密钥每分钟 **120 次请求**;超出后返回 `429`,直到窗口重置。集成里请对 `429` 做退避——并利用 API 的幂等行为(重复报名、重复扫码都以确认代替失败),让写操作的重试天然安全。

## 相关页面

<CardGroup cols={2}>
  <Card title="快速上手" icon="rocket" href="/zh/developers/quickstart">
    把这份参考端到端跑一遍。
  </Card>

  <Card title="订单" icon="receipt" href="/zh/ticketing/orders">
    你看到的只读订单究竟是什么。
  </Card>
</CardGroup>
