只读分析 API
api.jonot.io/v1/* HTTP API 提供对您组织排队号和队列数据的只读访问——无需管理后台登录,只需一个 Bearer 令牌。用它将数据拉入数据仓库、BI 工具或自定义仪表盘。
- 打开 admin.jonot.io/settings/integrations。
- 点击 API 令牌 选项卡。
- 点击创建令牌,给它一个名称(例如 “Power BI”),并确认。
- 立即复制令牌——它只显示一次,无法找回。 如果丢失,请吊销它并创建新的。
令牌以 jot_ 为前缀,且不会自行过期;不再需要时,从同一选项卡吊销。
Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| 状态 | 含义 |
|---|---|
401 | 令牌缺失、格式错误、未知或已吊销。 |
402 | 令牌有效,但组织未启用 API 功能。 |
429 | 超过速率限制——参见下文速率限制。 |
400 | 查询参数无效,或日期范围超过 90 天。 |
GET /v1/queues
Section titled “GET /v1/queues”返回您组织的门店和队列,无过滤、无分页:
curl https://api.jonot.io/v1/queues \ -H "Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{ "locations": [ { "id": "loc_…", "name": "Downtown", "slug": "downtown", "queues": [ { "id": "q_…", "name": "Main Queue", "slug": "main-queue", "status": "ACTIVE" } ] } ]}使用返回的 id 值按 queueId / locationId 过滤 /v1/tickets 和 CSV 导出。
GET /v1/tickets
Section titled “GET /v1/tickets”分页的排队号读取,作用域限定为您的组织。
| 参数 | 必填 | 可重复 | 说明 |
|---|---|---|---|
from | 是 | 否 | ISO-8601,createdAt 的包含下限。 |
to | 是 | 否 | ISO-8601,排除上限。最大跨度 90 天。 |
queueId | 否 | 是 | 重复该参数以过滤多个队列。 |
locationId | 否 | 是 | 重复该参数以过滤多个门店。 |
status | 否 | 是 | WAITING、CALLED、COMPLETED、CANCELED、SKIPPED、NO_SHOW 之一。 |
cursor | 否 | 否 | 来自上一页 nextCursor 的不透明值。 |
limit | 否 | 否 | 默认 100,最大 500。 |
curl "https://api.jonot.io/v1/tickets?from=2026-06-01T00:00:00Z&to=2026-06-08T00:00:00Z&status=COMPLETED" \ -H "Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{ "items": [ { "id": "tkt_…", "number": 42, "queueId": "q_…", "locationId": "loc_…", "status": "COMPLETED", "createdAt": "2026-06-01T09:14:02.000Z", "calledAt": "2026-06-01T09:20:11.000Z", "completedAt": "2026-06-01T09:24:47.000Z", "cancelledAt": null, "skippedAt": null, "noShowAt": null, "calledByDeviceSessionId": "dev_…" } ], "nextCursor": "eyJjcmVhdGVkQXQi…"}行中绝不包含排队号的持有哈希或任何顾客输入的 PII(姓名、备注、人数)——只有 id、状态和生命周期时间戳。
分页:当 nextCursor 非空时,在下一个请求中将其作为 cursor 传入,即可从上次中断处继续(from/to/过滤器相同)。nextCursor 为 null 表示您已到达范围末尾。
GET /v1/exports/tickets.csv
Section titled “GET /v1/exports/tickets.csv”与 /v1/tickets 相同的过滤器(from/to 必填,queueId/locationId/status 可重复),但不含 cursor/limit——整个匹配范围作为一个 CSV 响应流式返回,因此批量拉取时无需绕过 500 行的分页上限。
列顺序是稳定的,但请按表头名称而非固定位置解析列。表头行始终存在,且与此列表完全一致:
id,number,queueId,locationId,status,createdAt,calledAt,completedAt,cancelledAt,skippedAt,noShowAt,calledByDeviceSessionIdcurl "https://api.jonot.io/v1/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z" \ -H "Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -o tickets.csv响应是流式的(Transfer-Encoding: chunked),因此 90 天/10 万行的导出在两端都无需在内存中缓冲——直接管道到文件或解析器。
90 天范围上限
Section titled “90 天范围上限”所有接受 from/to 的端点都会以 400 拒绝超过 90 天的跨度。如需更长的历史,请增量拉取数据(例如每周一次调用)——排队号生命周期时间戳(calledAt、completedAt 等)让您无需重复获取相同行即可重建等待/服务时长。
每个令牌 60 次请求/分钟(不是按 IP——预算跟随令牌)。每个响应都携带:
X-RateLimit-Remaining: 42X-RateLimit-Reset: 1751328000000429 还额外携带 Retry-After(秒数)。在该窗口过后退避重试;每隔几分钟的定时同步可轻松保持在限制之内。
演示组织获得相同的 API,并在每分钟限制之外额外享有每天 50 次请求。这足以端到端验证一个集成——列出队列、拉取一些排队号、做一次 CSV 导出——但有意不足以在生产环境运行。超过它返回的 429 会在响应体中指明原因,而非通常的裸速率限制响应:
{ "error": "demo_quota_exceeded", "limit": 50, "resetAt": "2026-01-02T09:00:00.000Z"}演示的 CSV 导出也被标记,以免导出文件被误认为生产数据:文件名带 demo- 前缀,响应携带 X-Jonot-Demo: 1,CSV 末尾追加一列 demo。付费导出保持不变——没有额外列,没有额外请求头。订阅付费套餐会解除每日配额并移除这些标记。
Python + pandas
Section titled “Python + pandas”import requestsimport pandas as pd
TOKEN = "jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"BASE = "https://api.jonot.io/v1"HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def fetch_tickets(frm: str, to: str) -> pd.DataFrame: rows = [] cursor = None while True: params = {"from": frm, "to": to, "limit": 500} if cursor: params["cursor"] = cursor res = requests.get(f"{BASE}/tickets", headers=HEADERS, params=params, timeout=30) res.raise_for_status() body = res.json() rows.extend(body["items"]) cursor = body["nextCursor"] if not cursor: break return pd.DataFrame(rows)
df = fetch_tickets("2026-06-01T00:00:00Z", "2026-07-01T00:00:00Z")df["waitSeconds"] = ( pd.to_datetime(df["calledAt"]) - pd.to_datetime(df["createdAt"])).dt.total_seconds()print(df.groupby("queueId")["waitSeconds"].mean())或者直接读取 CSV 导出——pandas 会透明地处理流式响应:
df = pd.read_csv( f"{BASE}/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z", storage_options={"Authorization": f"Bearer {TOKEN}"},)Power BI(Web 连接器)
Section titled “Power BI(Web 连接器)”- 在 Power BI Desktop 中:Get Data → Web。
- 选择 Advanced,用您的日期范围构造 URL,例如
https://api.jonot.io/v1/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z。 - 在 HTTP request header parameters 下,添加一个名为
Authorization、值为Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx的请求头。 - 点击 OK——Power BI 会检测到 CSV 并打开 Table Preview。
- 点击 Load(如果想先设置列类型,可先点击 Transform Data——
createdAt/calledAt等按文本导入;在 Power Query 中将它们转换为Date/Time)。 - 如果按固定节奏拉取,请在 Power BI 服务中设置计划刷新;每次刷新的范围保持在 90 天以内。