콘텐츠로 이동

읽기 전용 분석 API

api.jonot.io/v1/* HTTP API는 관리자 로그인 없이 bearer 토큰만으로 조직의 번호표 및 대기열 데이터에 읽기 전용으로 접근할 수 있게 해줍니다. 데이터 웨어하우스, BI 도구, 또는 커스텀 대시보드로 데이터를 가져올 때 사용하세요.

  1. admin.jonot.io/settings/integrations를 엽니다.
  2. API 토큰 탭을 클릭합니다.
  3. 토큰 생성을 클릭하고 이름을 입력한 뒤(예: “Power BI”) 확인합니다.
  4. 토큰을 즉시 복사해 두세요 — 한 번만 표시되며 다시 복구할 수 없습니다. 분실한 경우 해당 토큰을 폐기하고 새로 생성하세요.

토큰은 jot_ 접두사가 붙으며 자체적으로 만료되지 않습니다. 더 이상 필요하지 않으면 동일한 탭에서 폐기하세요.

Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
상태 코드의미
401토큰이 없거나, 형식이 잘못되었거나, 알 수 없거나, 폐기된 토큰입니다.
402유효한 토큰이지만 조직에서 API 기능이 활성화되어 있지 않습니다.
429요청 한도를 초과했습니다 — 아래 요청 한도를 참고하세요.
400쿼리 매개변수가 잘못되었거나, 날짜 범위가 90일을 초과합니다.

조직의 지점과 대기열을 필터링이나 페이지네이션 없이 반환합니다:

Terminal window
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 값을 사용하여 /v1/tickets와 CSV 내보내기를 queueId / locationId로 필터링할 수 있습니다.

조직 범위로 제한된 페이지네이션 방식의 번호표 조회입니다.

매개변수필수 여부반복 가능설명
from아니오ISO-8601, createdAt 기준 포함 하한값.
to아니오ISO-8601, 제외 상한값. 최대 90일 범위.
queueId아니오여러 대기열을 필터링하려면 매개변수를 반복하세요.
locationId아니오여러 지점을 필터링하려면 매개변수를 반복하세요.
status아니오WAITING, CALLED, COMPLETED, CANCELED, SKIPPED, NO_SHOW 중 하나.
cursor아니오아니오이전 페이지의 nextCursor에서 받은 불투명 값.
limit아니오아니오기본값 100, 최대 500.
Terminal window
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…"
}

각 행에는 번호표의 bearer 해시나 고객이 입력한 개인정보(이름, 메모, 인원 수)가 절대 포함되지 않으며 — id, 상태, 생애주기 타임스탬프만 포함됩니다.

페이지네이션: nextCursor가 null이 아니면, 다음 요청에서 cursor로 전달하여 이전에 멈춘 지점부터 이어서 조회하세요(동일한 from/to/필터 사용). nextCursornull이면 범위의 끝에 도달했다는 의미입니다.

/v1/tickets와 동일한 필터(from/to 필수, queueId/locationId/status 반복 가능)를 사용하지만 cursor/limit는 없습니다 — 일치하는 전체 범위가 하나의 CSV 응답으로 스트리밍되므로, 대량 조회 시 500행 페이지 제한을 우회할 필요가 없습니다.

열 순서는 고정되어 있지만, 고정 위치가 아닌 헤더 이름으로 열을 파싱하세요. 헤더 행은 항상 존재하며 아래 목록과 정확히 일치합니다:

id,number,queueId,locationId,status,createdAt,calledAt,completedAt,cancelledAt,skippedAt,noShowAt,calledByDeviceSessionId
Terminal window
curl "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만 행 규모의 내보내기도 양쪽 어디에서든 메모리에 버퍼링할 필요가 없습니다 — 파일이나 파서로 바로 파이프하면 됩니다.

from/to를 받는 모든 엔드포인트는 90일을 초과하는 범위를 400으로 거부합니다. 더 긴 기간의 데이터가 필요하면 (예: 주 1회 호출로) 나누어 가져오세요 — 번호표 생애주기 타임스탬프(calledAt, completedAt 등)를 이용하면 동일한 행을 다시 가져오지 않고도 대기/처리 시간을 재구성할 수 있습니다.

토큰당 분당 60회 요청(IP 기준이 아니라 — 한도는 토큰에 귀속됩니다). 모든 응답에는 다음이 포함됩니다:

X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1751328000000

429에는 추가로 Retry-After(초 단위)가 포함됩니다. 해당 시간만큼 대기한 뒤 재시도하세요. 몇 분 간격의 예약 동기화라면 여유 있게 한도 이내로 유지됩니다.

import requests
import 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}"},
)
  1. Power BI Desktop에서: 데이터 가져오기 → 웹.
  2. 고급을 선택하고, 원하는 날짜 범위로 URL을 구성합니다. 예: https://api.jonot.io/v1/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z.
  3. HTTP 요청 헤더 매개변수에서 이름이 Authorization이고 값이 Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx인 헤더를 추가합니다.
  4. 확인을 클릭하면 — Power BI가 CSV를 인식하고 테이블 미리보기를 엽니다.
  5. 로드를 클릭합니다(열 형식을 지정하려면 먼저 데이터 변환을 클릭하세요 — createdAt/calledAt 등은 텍스트로 가져와지므로 Power Query에서 날짜/시간으로 변환하세요).
  6. 주기적으로 데이터를 가져온다면 Power BI 서비스에서 예약 새로 고침을 설정하세요. 새로 고침당 범위는 90일보다 여유 있게 짧게 유지하세요.