Pular para o conteúdo

API de Análise Somente Leitura

A API HTTP api.jonot.io/v1/* permite consultar os dados de senhas e filas da organização com um bearer token. Não é preciso fazer login no Admin. Use a API para enviar dados a um data warehouse, uma ferramenta de BI ou um painel personalizado.

  1. Abra admin.jonot.io/settings/integrations.
  2. Clique na aba Tokens da API.
  3. Clique em Criar token, dê-lhe um nome (ex.: “Power BI”) e confirme.
  4. Copie o token imediatamente — é mostrado apenas uma vez e não pode ser recuperado. Se o perder, revogue-o e crie um novo.

Os tokens têm o prefixo jot_ e não expiram por si só; revogue-os na mesma aba quando deixarem de ser necessários.

Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EstadoSignificado
401Token em falta, malformado, desconhecido ou revogado.
402Token válido, mas a organização não tem a funcionalidade da API ativa.
429Limite de pedidos excedido — consulte Limites de pedidos abaixo.
400Parâmetros de consulta inválidos, ou um intervalo de datas superior a 90 dias.

Devolve os locais e filas da sua organização, sem filtragem nem paginação:

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"
}
]
}
]
}

Use os valores id devolvidos para filtrar /v1/tickets e a exportação CSV por queueId / locationId.

Leitura paginada de senhas, com escopo na sua organização.

ParâmetroObrigatórioRepetívelNotas
fromsimnãoISO-8601, limite inferior inclusivo em createdAt.
tosimnãoISO-8601, limite superior exclusivo. Intervalo máximo de 90 dias.
queueIdnãosimRepita o parâmetro para filtrar várias filas.
locationIdnãosimRepita o parâmetro para filtrar vários locais.
statusnãosimUm de WAITING, CALLED, COMPLETED, CANCELED, SKIPPED, NO_SHOW.
cursornãonãoValor opaco obtido do nextCursor da página anterior.
limitnãonãoPadrão 100, máximo 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…"
}

As linhas nunca incluem o hash de credencial da senha nem qualquer dado pessoal inserido pelo cliente (nome, notas, número de pessoas) — apenas identificadores, estado e os registros de data/hora do ciclo de vida.

Paginação: quando nextCursor não for nulo, passe-o como cursor no pedido seguinte para continuar de onde ficou (mesmos from/to/filtros). Um nextCursor null significa que chegou ao fim do intervalo.

Esse endpoint aceita os mesmos filtros de /v1/tickets: from e to são obrigatórios, e queueId, locationId e status podem se repetir. Ele não usa cursor nem limit. O servidor envia todo o intervalo em uma única resposta CSV, sem o limite de 500 linhas por página.

A ordem das colunas é estável, mas analise as colunas pelo nome do cabeçalho em vez da posição fixa. A linha de cabeçalho está sempre presente e corresponde exatamente a esta lista:

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

A resposta usa streaming (Transfer-Encoding: chunked). Assim, nem o servidor nem o cliente precisam manter toda uma exportação de 90 dias ou 100 mil linhas na memória. Grave o fluxo diretamente em um arquivo ou envie-o a um processador.

Todos os endpoints que recebem from/to rejeitam um intervalo superior a 90 dias com 400. Extraia dados de forma incremental (ex.: uma chamada por semana) se precisar de um histórico mais longo — os registros de data/hora do ciclo de vida da senha (calledAt, completedAt, …) permitem-lhe reconstruir durações de espera/atendimento sem voltar a obter as mesmas linhas duas vezes.

Cada token permite 60 solicitações por minuto. O limite acompanha o token, não o endereço IP. Todas as respostas incluem:

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

Um 429 inclui adicionalmente Retry-After (segundos). Aguarde e tente novamente após essa janela; uma sincronização agendada a cada poucos minutos permanece confortavelmente abaixo do limite.

Uma organização de demonstração tem acesso à mesma API, com uma cota adicional de 50 solicitações por dia acima do limite por minuto. Isso é suficiente para validar uma integração de ponta a ponta — listar as suas filas, obter algumas senhas e fazer uma exportação CSV — mas insuficiente de propósito para uso em produção. Ultrapassar essa cota retorna um 429 cujo corpo identifica a causa, em vez da resposta genérica habitual de limite de solicitações:

{
"error": "demo_quota_exceeded",
"limit": 50,
"resetAt": "2026-01-02T09:00:00.000Z"
}

As exportações CSV de demonstração também são identificadas, para que um arquivo exportado não possa ser confundido com dados de produção: o nome do arquivo tem o prefixo demo-, a resposta inclui o cabeçalho X-Jonot-Demo: 1, e uma coluna demo é acrescentada ao final do CSV. As exportações pagas não são afetadas — sem coluna extra, sem cabeçalho extra. Assinar um plano pago remove a cota diária e essas identificações.

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())

Ou leia diretamente a exportação CSV — o pandas trata a resposta em fluxo de forma transparente:

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. No Power BI Desktop: Obter Dados → Web.
  2. Escolha Avançado e construa o URL com o seu intervalo de datas, ex.: https://api.jonot.io/v1/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z.
  3. Em Parâmetros de cabeçalho de pedido HTTP, adicione um cabeçalho chamado Authorization com o valor Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
  4. Clique em OK — o Power BI detecta o CSV e abre a visualização da tabela.
  5. Clique em Carregar (ou primeiro em Transformar Dados se quiser definir os tipos de coluna — createdAt/calledAt/etc. são importados como texto; converta-os para Data/Hora no Power Query).
  6. Defina uma atualização agendada no serviço Power BI se estiver extraindo dados com regularidade; mantenha o intervalo confortavelmente abaixo de 90 dias por atualização.