功能
等待提醒
当某个地点的实时等待降到你的阈值以下时,Waity 会调用你的 Webhook,智能体无需反复查询。所有套餐都有,包括 Free。
工作方式
为一个地点创建提醒,设置以分钟为单位的阈值和一个 https Webhook。每分钟数据摄取完成后,Waity 会检查刚收到新读数的地点,当等待等于或低于阈值时,向你的 Webhook POST 一个已签名的 JSON 正文。
提醒读取的实时回答与 GET /v1/places/{id} 相同,因此绝不会与 API 不一致。只有当 now.usable 为 true、单位是分钟且 now.value 不超过 under 时才会触发。下限值(“超过 60”)、过时或暂停的数字、已关闭的地点或没有数据,都不会触发。
创建提醒
使用 API 密钥和 JSON 正文调用 POST /v1/alerts。响应即该提醒,包含其 id 和签名密钥。签名密钥只显示一次:请把它存放在你的 Webhook 能读取的地方。
| 字段 | 取值 |
|---|---|
place_id | 一个地点、通道或科室。机场、边境口岸或医院院区没有单一的等待时间,因此其 id 会被拒绝,并附上其通道或科室的 id。 |
under | 整数分钟,从 1 到 600。 |
webhook_url | Waity POST 的目标地址。仅限 https;见下方规则。 |
repeat | false(默认)只触发一次,之后提醒变为 fired。true 会在等待升到阈值加 5 分钟以上之后再次触发,最多每 30 分钟一次。 |
expires_at | 可选,ISO 8601。默认为从现在起 24 小时,最长 30 天。 |
curl -X POST "https://api.waity.ai/v1/alerts" \
-H "X-Api-Key: $WAITY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"place_id":"pl_nvk0wkb3ps","under":30,"webhook_url":"https://example.com/waity/webhook"}'
201响应
{
"id": "al_3k9qx2m7t4p8w1za",
"place": {
"id": "pl_nvk0wkb3ps",
"name": "Ysleta Passenger Vehicles, Standard",
"category": "border"
},
"under": 30,
"unit": "min",
"repeat": false,
"webhook_url": "https://example.com/waity/webhook",
"status": "armed",
"created_at": "2026-10-31T19:02:11Z",
"expires_at": "2026-11-01T19:02:11Z",
Webhook URL 规则
为防止提醒到达私有网络,Waity 会拒绝符合以下情况的 Webhook URL:
- 未在默认端口(443)上使用 https,或包含用户名或密码;
- 使用 IP 地址而不是主机名,因此私有、环回、链路本地和云元数据地址都会被拒绝;
- 使用 localhost、单标签名称,或 .local、.internal、.lan、.home.arpa 等私有或保留名称;
- 指向 Waity 本身。
Waity 自己不解析任何名称,也从不跟随重定向:3xx 响应算作投递失败。
列出、读取和删除
GET /v1/alerts 返回你的提醒,最新的在前,附带状态和最近一次投递。同一账户的密钥共用一个列表;没有账户的密钥有自己的列表。GET /v1/alerts/{id} 读取一个提醒,DELETE /v1/alerts/{id} 删除它并停止其投递。
curl
curl "https://api.waity.ai/v1/alerts" \
-H "X-Api-Key: $WAITY_API_KEY"
curl -X DELETE "https://api.waity.ai/v1/alerts/al_3k9qx2m7t4p8w1za" \
-H "X-Api-Key: $WAITY_API_KEY"
| 状态 | 取值 |
|---|---|
armed | 正在等候等待时间降到阈值以下。 |
fired | 已触发的一次性提醒。 |
expired | 已过 expires_at 且未触发。 |
failing | 最近一次投递尝试失败;见 last_delivery。只要还有剩余次数,就会继续重试。 |
disabled | 连续 20 次投递尝试失败。Webhook 恢复正常后,请新建一个提醒。 |
Webhook
每次投递都是一个带 JSON 正文的 POST。先向用户读出 warnings,再读 summary。now.value 在 now.usable_until 之前有效;之后请重新请求 GET /v1/places/{id}。
POST
{
"type": "wait.under",
"alert": {
"id": "al_3k9qx2m7t4p8w1za",
"under": 30
},
"place": {
"id": "pl_nvk0wkb3ps",
"name": "Ysleta Passenger Vehicles, Standard",
"category": "border",
"url": "https://waity.ai/places/ysleta-passenger-vehicles-standard-kb3ps"
},
"now": {
"value": 25,
"unit": "min",
"measured_at": "2026-10-31T13:58:00-06:00",
"usable_until": "2026-10-31T15:28:00-06:00",
"basis": "estimate"
},
"summary": "About 25 min to enter the US, estimated by the border agency, updated 2 min ago.",
"warnings": [],
"links": {
"place": "https://api.waity.ai/v1/places/pl_nvk0wkb3ps",
"page": "https://waity.ai/places/ysleta-passenger-vehicles-standard-kb3ps",
"alert": "https://api.waity.ai/v1/alerts/al_3k9qx2m7t4p8w1za",
"docs": "https://waity.ai/docs/alerts"
}
}
每个请求都带有以下请求头:
Waity-Signature: t=<unix>,v1=<hex>:t是签名时间,以 unix 秒计;v1是由t、一个点和原始正文拼成的字符串的 HMAC-SHA256,以提醒的完整签名密钥为密钥。Waity-Alert: 提醒的 id。Waity-Delivery: 投递的 id,每次重试都相同,便于你丢弃重复项。
验证签名
在解析 JSON 之前,基于原始字节检查签名,用常量时间比较,并拒绝超过 5 分钟的 t。
import crypto from "node:crypto";
import express from "express";
const app = express();
const secret = process.env.WAITY_ALERT_SECRET; // whsec_…
// The raw body: the signature covers the exact bytes Waity sent.
app.post("/waity/webhook", express.raw({ type: "application/json" }), (req, res) => {
const parts = Object.fromEntries(
(req.get("Waity-Signature") ?? "").split(",").map((p) => p.split("=", 2)),
);
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${req.body}`)
.digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= 300;
const ok =
fresh &&
typeof parts.v1 === "string" &&
parts.v1.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));
if (!ok) return res.status(400).end();
const event = JSON.parse(req.body);
// Read event.warnings first, then event.summary.
res.status(204).end();
});
app.listen(3000);
重试
请在 10 秒内以任意 2xx 响应。其他任何响应都算一次失败尝试,约 1, 5, 25 分钟后重试。连续 20 次尝试失败后,提醒会被停用。
各套餐的限制
每个套餐同时可保有一定数量的有效提醒。再多一个会返回 409 alert_limit,消息中会写明你套餐的上限。每个提醒请求计为一次调用;投递从不计数。没有账户的密钥按 Free 计。
| 套餐 | 有效提醒 |
|---|---|
| Free | 1 |
| Plus | 10 |
| Pro | 100 |
| Team | 1,000 |
急诊室和紧急护理
对于急诊室和紧急护理的提醒,每次投递的 warnings[0] 都是 911 提示,只说一次,与每个急诊室回答一样。