预订
一条预订分两步创建:先在客人付款期间锁定库存,再把这次锁房确认成预订。这样拆开之后,客人一决定就立刻占住房量,而预订只有在收款成功后才最终生效。
预订的生命周期
POST /holds 创建一条暂定预订,把一间房锁住 15 分钟。POST /holds/{id}/confirm 把它变成已确认的预订,并记录付款。未被确认的锁房会自动过期,并把房量释放回去。
POST /holds权限范围: reservations:write · 支持 Idempotency-Key
创建一条暂定预订,按某个房价方案锁住某个房型的这段日期。这段住宿会被定价(房晚加适用税费)并入账到一张新账单上。在确认或 15 分钟窗口失效之前,这次锁房都会占用房量。
| 请求体字段 | 必填 | 说明 |
|---|---|---|
room_type_id | 是 | 必须属于这家酒店。 |
rate_plan_id | 是 | 该房型下启用的方案;它的可见性规则会被重新校验。 |
check_in | 是 | YYYY-MM-DD。 |
check_out | 是 | YYYY-MM-DD,晚于 check_in;最长 30 晚。 |
guest_id | 是 | 这次锁房是为哪位客人。 |
adults | 是 | 整数 1–20;人数必须装得进 max_occupancy。 |
children | 否 | 整数 0–20,默认 0。 |
child_ages | 否 | 儿童年龄数组(整数 ≥ 0)。一旦传了它,它就是准确的儿童人数,并据此按年龄段做加人计价。 |
bed_config | 否 | 客人选择的床型配置标签;必须是该房型提供的选项之一。会记在预订上供客房清洁使用。 |
add_ons | 否 | 客人选择的附加项数组(最多 10 个),在锁房时就逐项定价入账,因此都包含在收取的总额里。字段见下。 |
promo_code | 否 | 如果所选房价方案需要促销码,则必填。 |
add_ons 中的每一项都引用一个客人可预订的服务:
| 附加项字段 | 必填 | 说明 |
|---|---|---|
service_id | 是 | 要添加的服务。 |
modifier_values | 否 | 该服务信息采集字段的 { modifier_key: value } 对象。默认为 {}。 |
quantity | 否 | 附加项的数量(整数 1–99)。默认为 1。 |
curl -X POST "$VRDN_BASE/holds" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1d2c9a-8b3e-4a17-9c2f-1e5b7d0a4c83" \
-d '{
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02",
"check_in": "2026-08-01",
"check_out": "2026-08-04",
"guest_id": "3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34",
"adults": 2
}'{
"reservation_id": "7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27",
"folio_id": "1a6c3e9f-4d2b-4e8a-b5c7-9f0e6d4a2c81",
"hold_expires_at": "2026-06-19T08:45:00.000Z",
"total": "1260.00",
"currency": "USD",
"status": "tentative"
}| 错误 | 出现时机 |
|---|---|
409 no_availability | 该房型在这段日期已售罄。 |
404 rate_plan_not_found | 方案已停用,或它的可见性规则把这位客人/这个上下文排除在外。 |
400 party_too_large | adults + children 超过了该房型的 max_occupancy。 |
POST /holds/{id}/confirm权限范围: reservations:write · 支持 Idempotency-Key
在你自己的流程里收款,然后带上 payment_reference 确认这次锁房。Veridien 会重新校验房量(不把这次锁房自己算进去),把预订及其住宿单元标记为 confirmed,把付款记到账单上,并对以美元结算的住宿按房费收入发放会员积分。
方式 1 是基于信任的声明模型,请读这一段
这个接口是基于信任的。你的 payment_reference 是你已经收到钱的一个声明,是一种主张,绝不是证明。Veridien 不会核实这笔钱是否真的到账:你的酒店才是记录商户,资金、争议与退款都归你负责。因此:
- 每次预订都要发送一个真实且唯一的凭据。绝不要跨预订复用或改写同一个付款 id。
- 每一次确认都会作为付款声明写入审计日志(谁声明的、凭据是什么、金额多少)。
- 确认时的校验会挡掉明显错误的输入,但它无法验证钱是否真的易手。
如果你希望由 Veridien 自己核实付款(Stripe 托管、平台核实的收款),那属于托管式预订引擎(方式 2),不是这套 API。
| 请求体字段 | 必填 | 说明 |
|---|---|---|
payment_reference | 是 | 你的付款标识:一个未经核实的、声称你已收款的凭据。确认对这个值是幂等的。 |
payment_currency | 否 | 可选的 ISO-4217 币种,声明你实际收取的币种。与预订币种不一致会被拒绝。 |
payment_amount | 否 | 可选金额,声明你实际收取的数额。与账单总额不一致会被拒绝。 |
curl -X POST "$VRDN_BASE/holds/7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27/confirm" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9a2e7c10-4b3f-4d28-8c1f-2e6b8d0a5d94" \
-d '{ "payment_reference": "pay_abc123", "payment_currency": "USD", "payment_amount": 1260.00 }'{
"reservation_id": "7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27",
"status": "confirmed",
"check_in_date": "2026-08-01",
"check_out_date": "2026-08-04",
"currency": "USD",
"folio_balance": "0.00",
"already_confirmed": false
}| 错误 | 出现时机 |
|---|---|
409 hold_expired | 你确认之前,这次锁房的 15 分钟付款窗口已经过去。请重新创建一次锁房。 |
409 no_availability | 从锁房到确认之间,这次锁房丢掉了它占的房量。 |
409 not_confirmable | 这条预订不是一次可确认的暂定锁房(例如已经取消了)。 |
400 currency_mismatch | payment_currency 与预订币种不一致。 |
400 amount_mismatch | payment_amount 与账单总额不一致。 |
两种意义上的幂等
重复确认一条已确认的预订,或重放同一个 payment_reference,都会返回已有的确认结果并带上 "already_confirmed": true,不会有第二次付款,也不会有第二条预订(一个 (folio, reference) 唯一索引保证了并发安全)。再配合 Idempotency-Key,确认可以放心重试。
会员积分以美元计
会员积分按美元房费收入赚取。非美元的住宿不会悄悄地赚到零分;被跳过的这次赚取会被记录下来以便对账,直到多币种赚取功能上线。
GET /reservations权限范围: reservations:read
返回这家酒店的预订,按入住日期从早到晚排序,并带上每条预订未结清的账单余额。
| 查询参数 | 说明 |
|---|---|
guest_id | 只看某一位客人。 |
status | 按状态筛选:tentative、confirmed、checked_in、checked_out、cancelled、no_show。 |
limit | 每页条数,默认 25,最大 100。 |
offset | 跳过多少条记录。 |
curl "$VRDN_BASE/reservations?guest_id=3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34&limit=10" -H "Authorization: Bearer $VRDN_KEY"{
"has_more": false,
"data": [
{
"id": "7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27",
"status": "confirmed",
"guest_id": "3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34",
"check_in_date": "2026-08-01",
"check_out_date": "2026-08-04",
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"room_type_name": "Deluxe Ocean Villa",
"nightly_rate": "420.00",
"currency": "USD",
"folio_balance": "0.00",
"balances": []
}
]
}分页取数参见接口约定。
GET /reservations/{id}权限范围: reservations:read
返回单条预订,带上它的住宿单元(这次住宿按房间拆开的各段)和账单余额。
curl "$VRDN_BASE/reservations/7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27" -H "Authorization: Bearer $VRDN_KEY"{
"id": "7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27",
"status": "confirmed",
"guest_id": "3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34",
"check_in_date": "2026-08-01",
"check_out_date": "2026-08-04",
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"room_type_name": "Deluxe Ocean Villa",
"nightly_rate": "420.00",
"currency": "USD",
"adults": 2,
"children": 0,
"number_of_guests": 2,
"booking_source": "direct_web",
"special_notes": null,
"folio_id": "1a6c3e9f-4d2b-4e8a-b5c7-9f0e6d4a2c81",
"folio_balance": "0.00",
"balances": [{ "currency": "USD", "charges": "1310.40", "payments": "1310.40", "balance": "0.00" }],
"accommodations": [
{
"id": "2b9e6f4d-8a3c-4e1b-9d5f-7a0c4e8b2d63",
"room_id": null,
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"check_in_date": "2026-08-01",
"check_out_date": "2026-08-04",
"status": "confirmed",
"nightly_rate": "420.00"
}
]
}POST /reservations/{id}/cancel权限范围: reservations:write
取消一条 tentative 或 confirmed 的预订,并释放它占用的房量。已入住、已退房或已取消的预订无法通过 API 取消(409 not_cancellable)。账单与任何发票都会作废(保留以备审计),如果这条预订已付款,会在释放房量之前按政策发起退款。
| 请求体字段 | 必填 | 说明 |
|---|---|---|
reason | 否 | 作为取消原因保存下来。 |
curl -X POST "$VRDN_BASE/reservations/7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27/cancel" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Guest changed plans" }'{ "reservation_id": "7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27", "status": "cancelled", "refund_minor": 0, "refund_provider": null }| 字段 | 类型 | 说明 |
|---|---|---|
refund_minor | integer | 退款金额,以最小货币单位(分)计。预订未付款或政策不退款时为 0。 |
refund_provider | string | null | 处理这笔退款的服务方;没有退款时为 null。 |