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

# 接受预订

> 发现门店、搜索可用时段、保留容量，并创建或更改预订。

预订使用您应用的**门店授权（location grants）**，而不是其 POS 连接。预订集成可以与在同一门店接收订单的其他应用并存。该功能按门店逐步开放；请先让 Maple 为您的测试门店启用。

将 `MAPLE_BASE` 设置为您所在环境的基础 URL（包含 `/v1`），并将 `MAPLE_KEY` 设置为匹配的凭证。请参阅[环境](/zh/developer-api/concepts/environments)。发现和读取需要 `bookings:read`，保留时段和顾客侧写入需要 `bookings:write`。

## 1. 读取预订配置

```bash theme={null}
curl "$MAPLE_BASE/locations/$LOCATION_ID/booking_profile" \
  -H "Authorization: Bearer $MAPLE_KEY"
```

检查 `enabled`、`provider` 和 `capabilities`。Maple 原生门店的 `hold_ttl_seconds` 默认为 300。由第三方提供商管理的门店会返回 `null`，因为过期由提供商负责；请始终使用保留记录（hold）的 `expires_at`。

## 2. 搜索可用时段

`start` 和 `end` 是场所本地的挂钟时间，而不是 UTC 时刻。请选择未来且不超过 31 天的时间窗口：

```bash theme={null}
curl --get "$MAPLE_BASE/locations/$LOCATION_ID/booking_availability" \
  -H "Authorization: Bearer $MAPLE_KEY" \
  --data-urlencode 'party_size=2' \
  --data-urlencode "start=${BOOKING_DATE}T18:00" \
  --data-urlencode "end=${BOOKING_DATE}T21:00"
```

每个 `data` 条目包含一个不透明的 `slot_token`、UTC 时间的 `starts_at`、`starts_at_local`，以及报价的取消政策（如有）。令牌在 15 分钟后过期。请原样保存所选令牌；切勿根据显示的时间重新构造。

`422` 是业务结果，而不是空结果：请检查 `code` 和 `details`，了解人数上下限、预订窗口限制，或大型聚会咨询的联系方式。

### 特色体验

部分场所提供特色体验：固定套餐、品鉴或需购票的席位。如果门店支持（`booking_profile.capabilities.experiences`），可用时段中会按开始时间顺序，将这些时段与标准时段一并列出。体验时段会给出其 `experience`：`id`、`name`、`description` 和 `prepayment_required`。标准时段的 `experience` 为 `null`。

要显示某项体验的时间，请传入其 id：

```bash theme={null}
curl --get "$MAPLE_BASE/locations/$LOCATION_ID/booking_availability" \
  -H "Authorization: Bearer $MAPLE_KEY" \
  --data-urlencode 'party_size=2' \
  --data-urlencode "start=${BOOKING_DATE}T18:00" \
  --data-urlencode "end=${BOOKING_DATE}T21:00" \
  --data-urlencode 'experience_id=1771'
```

预订体验时段与预订其他时段相同：其 `slot_token` 绑定到该体验，因此保留和预订都针对该体验，预订的 `experience` 会指明它。OpenTable 可以将体验预订改到同一体验的另一个时间，但不能改到其他体验或标准餐桌：此类更改会返回 `422 capability_unsupported`，因此请取消后再预订新的时段。Maple 目前无法收取付款，因此保留 `prepayment_required: true` 的体验时段会返回 `422 payment_instrument_required`。请展示这些体验，但提供标准时段供预订。Maple 原生门店目前不提供体验：`capabilities.experiences` 为 `false`，`experience_id` 会返回 `422 capability_unsupported`。

## 3. 保留时段

```http theme={null}
POST /v1/booking_holds
Content-Type: application/json

{ "slot_token": "<selected slot_token>" }
```

将 `id` 保存为保留 ID。保留会占用容量，直到 `expires_at`；请在此之前创建预订。如果顾客放弃流程，请使用 `DELETE /v1/booking_holds/{holdId}` 释放原生保留。已被使用的保留会返回 `409 hold_consumed`，而不是报告其容量已释放。

每个应用在**每个门店最多可有十个有效保留**，在并发请求间以原子方式强制执行。原生保留和提供商保留都计入，包括仍在等待结果的提供商获取操作。其他应用无法释放或使用您的保留，即使两个应用都被授予该门店；此类请求会返回 `404`。

如果提供商保留的响应丢失，其配额预留会在最后一次可能的提供商尝试之后保守地隔离 24 小时。超过该期限后，它不再占用配额。原始操作仍保持记录，且在其重放窗口之后无法重新开始；这不会清除不确定的预订创建/更改/取消操作。

所有合作伙伴保留 ID 均使用 `bkh_…`。重复提交相同的 `slot_token` 会重放您当前有效的保留，而不是获取另一个锁。OpenTable 的释放仍是空操作：提供商的锁及其配额占用会保留到过期或被使用。在承诺提前释放之前，请检查 `booking_profile.capabilities.hold_release`。

## 4. 创建预订

```http theme={null}
POST /v1/bookings
Content-Type: application/json

{
  "hold_id": "<hold id>",
  "guest": {
    "first_name": "Alex",
    "last_name": "Quinn",
    "phone": "+12125551234",
    "email": "alex@example.com"
  },
  "notes": "Window table if possible",
  "idempotency_key": "<unique key for this write>"
}
```

响应是完整的 `booking` 资源。在原生门店，其初始状态为 `confirmed` 或 `requested`，取决于场所的接受政策。请保存其 `id` 和 `version`。顾客电话为必填；当前服务接受可拨打的北美号码。

已保存的保留为原生预订和提供商管理的预订提供权威报价。您可以省略 `slot_token`；为兼容现有集成，它仍作为可选字段被接受。

<Warning>
  超时或 `409 operation_in_progress` 并不意味着提供商拒绝了预订。请使用**相同的密钥和请求体**重试，切勿使用新密钥。Maple 会在提供商 I/O 之前记录待处理的命令，并使用相同的提供商请求标识来核对不确定的结果。如果 `details.reason` 为 `replay_window_expired`，请停止自动重试，并携带 `details.operation_id` 联系 Maple。请参阅[重放安全](/zh/developer-api/concepts/idempotency)。
</Warning>

## 5. 更改或取消

对于原生更改，请使用 `changing_booking_id=<booking id>` 再次搜索。这会排除该预订当前占用的容量。将选定的令牌发送到 `POST /v1/bookings/{id}/change`，并附上新的 `idempotency_key`，以及可选的 `expected_version`。

提供商管理的门店会以 `422 capability_unsupported` 拒绝 `changing_booking_id`。它们的直接更改路径使用普通可用时段搜索中的令牌。OpenTable 支持时间/人数更改和 `notes`，后者会替换预订的特殊要求。如果 OpenTable 未确认备注，更改会返回 `422 capability_unsupported`，而不是报告已保存；随之发送的时间或人数更改可能已生效，因此请重新读取预订。OpenTable 不接受结构化的 `intake_answers`；它们会返回 `422 capability_unsupported`，而不是被静默丢弃。

如果只更改顾客的备注，请发送 `notes` 而不带 `slot_token`。预订保持其时间、人数和餐桌，因此无需报价，改期截止时间或之后对当天设置的停订也不会阻止它。`""` 表示清除备注。预订开始后，顾客侧的备注更改会被拒绝。在 OpenTable，备注就是预订的特殊要求。如果既不发送 `slot_token` 也不发送 `notes`，会返回 `400 change_required`。

```http theme={null}
POST /v1/bookings/{bookingId}/change
Content-Type: application/json

{ "notes": "High chair, please", "expected_version": 1, "idempotency_key": "<unique change key>" }
```

```http theme={null}
POST /v1/bookings/{bookingId}/cancel
Content-Type: application/json

{ "expected_version": 0, "idempotency_key": "<unique cancellation key>" }
```

合作伙伴取消的预订状态为 `cancelled_by_guest`；拥有 `bookings:manage` 的前台应用则改用 `POST /v1/bookings/{id}/venue_cancel` 代表场所取消（请参阅[以场所身份取消](/zh/developer-api/concepts/booking-lifecycle)）。版本过期会返回 `409 stale_version`，并附带 `details.expected` 和 `details.actual`。由提供商支持的写入会在提供商 I/O 之前占用镜像的预订；在该占用有效期间，竞争的写入可能返回 `409 operation_in_progress`。成功的重放会先于版本检查运行，因此其原始 `expected_version` 不会阻止重放。

在决定是否提交不同的更改之前，请再次读取预订。取消和改期政策的拒绝会在 `details` 中包含 `reason`。版本声明会使通过 Maple 的写入串行化；它们无法阻止直接在提供商自有工具中所做的更改。

## 查找顾客的预订

当顾客来电或发短信询问其预订时，请使用其预订时的电话或所获得的确认码查找，而不是逐页翻看当天的预订：

```http theme={null}
GET /v1/bookings?location_id={locationId}&phone=(415)%20555-0142
GET /v1/bookings?location_id={locationId}&confirmation_code=4815162
```

电话号码在匹配前会被规范化；不带 `start`/`end` 的查找会匹配任意时间的预订，并按时段开始时间排序。它返回普通的 `booking` 资源，可直接用于更改或取消。`location_id` 为必填。请参阅[列出预订](/zh/developer-api/api-reference)。

在提供商管理的门店（OpenTable），包含 `phone` 的查找会先询问提供商，因此也能找到顾客直接通过 OpenTable 所做的预订。OpenTable 仅按电话查找预订：仅使用 `confirmation_code` 的查找只能找到 Maple 已知的提供商预订，因此如有电话请一并提供。

## 请求限制

每个应用、每个环境的默认预算为**每分钟 60 次可用时段搜索**和**每分钟 300 次其他预订请求**。两项预算相互独立，并适用于所有已授权的门店。现有的订单/菜单路由不计入。`429` 会同时包含 `Retry-After` 标头和 JSON 响应体中的 `retry_after`；请等待后再重试。Maple 可以调整这些部署级预算。

## 跟踪变更

订阅[预订 webhook](/zh/developer-api/webhook-events)。使用 `GET /v1/bookings/{id}` 获取当前状态，或使用[增量列表](/zh/developer-api/api-reference)在停机后追赶数据。场所操作和实时楼面读取请参阅[预订生命周期](/zh/developer-api/concepts/booking-lifecycle)。


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