接口文档
概览
开放接口提供两套机制:①拉取——第三方主动调用 HTTP 接口,按条件拉取预约数据;②推送——新预约产生时,系统主动向你配置的通知地址推送 appointment.created 事件。两者共用同一套 HMAC-SHA256 签名。凭据分两部分:API Key 用于标识身份,随请求头明文传递;API Secret 用于计算签名,永不出现在请求报文中。重置密钥时只更换 API Secret,API Key 保持不变。
拉取接口
GET https://phone-api.bookmi.ai/api/open/v1/appointments
请求头
| 名称 | 说明 |
|---|---|
| X-Api-Key | 身份标识 API Key(ak_ 开头) |
| X-Timestamp | Unix 秒级时间戳(字符串),须在服务器时间 ±300 秒内 |
| X-Signature | 本次请求的 HMAC-SHA256 签名(小写十六进制) |
签名算法
待签串由四行拼成、以换行符连接:第 1 行为时间戳,第 2 行为 HTTP 方法(GET),第 3 行为请求路径 /api/open/v1/appointments,第 4 行为 query string。query string 须与实际发出的完全逐字一致,不重排、不重新编码;无参数时为空串。以 API Secret 为密钥对该串做 HMAC-SHA256,取小写十六进制作为 X-Signature。时间戳须为 Unix 秒且在服务器时间 ±300 秒内,否则视为过期。
查询参数
| 名称 | 说明 |
|---|---|
| updated_since | 只返回该时间之后有更新的预约(ISO 8601) |
| scheduled_from | 预约时间下界(ISO 8601) |
| scheduled_to | 预约时间上界(ISO 8601) |
| status | 按状态过滤:pending / confirmed / cancelled |
| page | 页码,从 1 起(默认 1) |
| page_size | 每页条数,1-200(默认 50) |
响应示例
{
"code": 0,
"message": "ok",
"data": {
"total": 128,
"items": [
{
"id": 1024,
"scheduled_at": "2026-07-20T10:00:00+09:00",
"party_size": 2,
"contact_name": "山田太郎",
"contact_phone": "+819012345678",
"subject": "カット予約",
"note": null,
"status": "confirmed",
"outside_slot": false,
"item_name": "カット",
"item_external_id": "svc_001",
"created_at": "2026-07-16T12:34:56+09:00",
"updated_at": "2026-07-16T12:34:56+09:00"
}
]
}
}字段说明
| 字段 | 说明 |
|---|---|
| id | 预约主键 |
| scheduled_at | 预约时间(可为空) |
| party_size | 人数 / 数量(可为空) |
| contact_name | 联系人姓名(可为空) |
| contact_phone | 联系电话(可为空) |
| subject | 预约用件 |
| note | 备注(可为空) |
| status | 状态:pending / confirmed / cancelled |
| outside_slot | 是否落在不可约时段(定休 / 时段外 / 满员) |
| item_name | 商品名快照(可为空) |
| item_external_id | 第三方商品 ID 快照,仅精确命中商户商品时才有值(可为空) |
| created_at | 创建时间 |
| updated_at | 更新时间 |
推送通知
配置通知地址后,每当有新预约创建(AI 抽取或人工录入),系统会向该地址发起一次 POST 请求,请求体为下方 JSON。
推送请求体示例
{
"event": "appointment.created",
"delivery_id": 8801,
"timestamp": 1752633600,
"data": {
"id": 1024,
"scheduled_at": "2026-07-20T10:00:00+09:00",
"party_size": 2,
"contact_name": "山田太郎",
"contact_phone": "+819012345678",
"subject": "カット予約",
"note": null,
"status": "pending",
"outside_slot": false,
"item_name": "カット",
"item_external_id": "svc_001",
"created_at": "2026-07-16T12:34:56+09:00",
"updated_at": "2026-07-16T12:34:56+09:00"
}
}推送签名
推送请求头带 X-Timestamp 与 X-Signature:待签串为「时间戳 + 半角句点 + 请求体原始字节」,以 API Secret 为密钥做 HMAC-SHA256。你的服务收到后应重算签名比对,一致才处理。返回 2xx 即视为投递成功。
重试与幂等
投递失败(非 2xx 或超时)会自动重试,间隔依次为 1 分钟、5 分钟、30 分钟、2 小时、6 小时,含首次共尝试 6 次,全部失败后置为终态、不再投递。同一预约的多次投递携带相同 delivery_id,请据此去重以保证幂等。首次配置测试推送时,会先发一条 event 为 webhook.test 的探测事件,data 为空对象。
错误码
业务错误除 HTTP 状态码外,还会在响应体的 code 字段返回下列业务码。
| 业务码 | HTTP | 含义 |
|---|---|---|
| 1801 | 403 | 开放接口功能未开启 |
| 1802 | 401 | API Key 无效 |
| 1803 | 401 | 签名无效或时间戳过期 |
| 1804 | 400 | 通知地址非法 |
| 1805 | 400 | 请先生成凭据并配置通知地址 |
代码示例
拉取(curl)
# 拉取预约(签名 = HMAC-SHA256(secret, ts + "\n" + "GET" + "\n" + path + "\n" + query))
TS=$(date +%s)
QUERY="page=1&page_size=50"
SIG=$(printf '%s\nGET\n/api/open/v1/appointments\n%s' "$TS" "$QUERY" \
| openssl dgst -sha256 -hmac "$API_SECRET" -hex | awk '{print $NF}')
curl "https://phone-api.bookmi.ai/api/open/v1/appointments?$QUERY" \
-H "X-Api-Key: ak_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -H "X-Timestamp: $TS" -H "X-Signature: $SIG"推送验签(Python)
# 推送验签(收到 POST 时)
import hashlib, hmac
def verify(secret: str, timestamp: str, body: bytes, signature: str) -> bool:
expected = hmac.new(secret.encode(), timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)