API para parceiros
Integre cronometragem, catracas, totens e sistemas próprios com os dados da sua organização. REST, JSON e versionada em /v1.
Visão geral
- Endereço base:
https://largavo.com/api/v1. Toda resposta é JSON (UTF-8), mesmo em caso de erro. - Cada token pertence a uma organização: só os eventos, inscrições e resultados dela são visíveis. Um slug de evento de outra organização responde
404. - Datas e horários são ISO 8601 em UTC (
2026-10-04T10:00:00+00:00); cada evento informa o própriotimezonepara exibição. - Valores monetários são inteiros em centavos (
price_cents). - Envie o corpo das requisições
POSTem JSON comContent-Type: application/json.
Autenticação
A API usa tokens Bearer. Para obter um token, um membro com permissão Gerenciar acesso de API (e autenticação em dois fatores ativa) acessa Painel → API, cria um cliente informando nome, escopos e limite por minuto e copia o token — ele é mostrado uma única vez. Tokens podem ser revogados a qualquer momento no mesmo lugar.
Inclua o token em todas as chamadas:
curl "https://largavo.com/api/v1/events" \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Accept: application/json"
Guarde o token como um segredo
Escopos
Cada token carrega apenas os escopos escolhidos na criação. Chamar um endpoint sem o escopo necessário responde 403.
| Escopo | Permite | Endpoints |
|---|---|---|
| events:read | Consultar eventos da organização | GET /events · GET /events/{event} |
| registrations:read | Consultar inscrições | GET /events/{event}/registrations |
| checkins:write | Registrar check-in | POST /events/{event}/checkins |
| results:write | Enviar resultados | POST /events/{event}/results |
Limites de uso
Cada cliente tem um limite de requisições por minuto definido na criação do token (padrão: 60/min). Toda resposta informa o consumo:
X-RateLimit-Limit— requisições permitidas por minuto.X-RateLimit-Remaining— quantas ainda cabem na janela atual.
Ao ultrapassar o limite a API responde 429 Too Many Requests com Retry-After (segundos) e X-RateLimit-Reset (timestamp Unix). Aguarde e repita a chamada; não faça novas tentativas em laço apertado.
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
{"message":"Limite de requisições excedido. Aguarde o tempo indicado em Retry-After e tente novamente.","errors":{}}
Paginação e filtros
Listagens são paginadas. Use page e per_page (padrão 25, máximo 100). A resposta traz data, links e meta:
{
"data": [ ... ],
"links": { "first": "…?page=1", "last": "…?page=4", "prev": null, "next": "…?page=2" },
"meta": { "current_page": 1, "from": 1, "last_page": 4, "per_page": 25, "to": 25, "total": 92 }
}
Para sincronizações incrementais de inscrições use updated_since com o instante da última sincronização e percorra todas as páginas.
Formato de erros
Erros sempre têm message (texto em português para exibir ou registrar) e errors (objeto campo → lista de mensagens; vazio quando não é erro de validação).
{
"message": "Os dados enviados são inválidos.",
"errors": {
"operation": ["O campo operation selecionado é inválido."]
}
}
| Código | Quando acontece |
|---|---|
| 200 | Sucesso. |
| 401 | Token ausente, inválido ou revogado. |
| 403 | Token sem o escopo necessário, ou organização suspensa. |
| 404 | Evento ou inscrição inexistente na sua organização. |
| 409 | Check-in ou kit já validado anteriormente (chamada repetida). |
| 422 | Dados inválidos ou validação recusada (QR inválido, inscrição não confirmada, outro evento). |
| 429 | Limite de requisições por minuto excedido. |
| 5xx | Falha interna. Repita a chamada depois de alguns segundos. |
GET /events
Escopo events:read. Lista os eventos da organização (todos os status), ordenados por data.
- status
- draft · published · paused · closed · cancelled
- from / to
- data de início do evento (YYYY-MM-DD, inclusivo)
- page / per_page
- paginação
curl "https://largavo.com/api/v1/events?status=published&from=2026-10-01&per_page=50" \
-H "Authorization: Bearer SEU_TOKEN" -H "Accept: application/json"
{
"data": [
{
"id": 12,
"slug": "meia-maratona-das-pontes",
"title": "Meia Maratona das Pontes",
"status": "published",
"modality": "Corrida de rua",
"timezone": "America/Sao_Paulo",
"starts_at": "2026-10-04T10:00:00+00:00",
"ends_at": "2026-10-04T14:00:00+00:00",
"registration_opens_at": "2026-08-01T03:00:00+00:00",
"registration_closes_at": "2026-10-01T02:59:00+00:00",
"venue_name": "Parque das Pontes",
"city": "Recife",
"state": "PE",
"availability": { "capacity": 3000, "sold": 1840, "reserved": 12, "remaining": 1148, "registrations_open": true },
"url": "https://largavo.com/eventos/meia-maratona-das-pontes",
"updated_at": "2026-09-10T18:22:41+00:00"
}
],
"links": { "first": "…", "last": "…", "prev": null, "next": null },
"meta": { "current_page": 1, "from": 1, "last_page": 1, "per_page": 50, "to": 1, "total": 1 }
}
GET /events/{event}
Escopo events:read. Detalhe do evento pelo slug, com categorias ativas, lote vigente de cada uma e disponibilidade. current_batch é null quando não há lote à venda.
curl "https://largavo.com/api/v1/events/meia-maratona-das-pontes" \
-H "Authorization: Bearer SEU_TOKEN" -H "Accept: application/json"
{
"data": {
"id": 12,
"slug": "meia-maratona-das-pontes",
"title": "Meia Maratona das Pontes",
"status": "published",
"availability": { "capacity": 3000, "sold": 1840, "reserved": 12, "remaining": 1148, "registrations_open": true },
"categories": [
{
"id": 31,
"name": "21 km",
"distance_meters": 21097,
"gender": "any",
"min_age": 18,
"max_age": null,
"availability": { "capacity": 2000, "sold": 1500, "reserved": 10, "remaining": 490 },
"current_batch": {
"id": 77, "name": "2º lote", "price_cents": 15900,
"starts_at": "2026-09-01T03:00:00+00:00", "ends_at": "2026-09-30T02:59:00+00:00",
"capacity": 800, "remaining": 212
}
}
],
"url": "https://largavo.com/eventos/meia-maratona-das-pontes"
}
}
GET /events/{event}/registrations
Escopo registrations:read. Inscrições do evento, ordenadas por criação. O documento sai sempre mascarado; e-mail e telefone não são expostos.
- status
- pending · confirmed · cancelled · expired · refunded
- category_id
- id da categoria (ver detalhe do evento)
- updated_since
- ISO 8601 — só inscrições alteradas a partir desse instante (sincronização incremental)
curl "https://largavo.com/api/v1/events/meia-maratona-das-pontes/registrations?status=confirmed&updated_since=2026-09-10T00:00:00Z" \
-H "Authorization: Bearer SEU_TOKEN" -H "Accept: application/json"
{
"data": [
{
"code": "K7PM2QX4",
"status": "confirmed",
"bib_number": "1042",
"is_courtesy": false,
"category": { "id": 31, "name": "21 km" },
"kit": { "id": 5, "name": "Kit completo", "items": "Camiseta — M" },
"participant": { "name": "Maria Souza", "document_type": "cpf", "document": "***.456.789-**", "gender": "F", "birth_date": "1990-05-10" },
"confirmed_at": "2026-09-02T14:03:10+00:00",
"checked_in_at": null,
"kit_picked_up_at": null,
"created_at": "2026-09-02T14:00:52+00:00",
"updated_at": "2026-09-02T14:03:10+00:00"
}
],
"links": { "first": "…", "last": "…", "prev": null, "next": "…?page=2" },
"meta": { "current_page": 1, "from": 1, "last_page": 74, "per_page": 25, "to": 25, "total": 1840 }
}
POST /events/{event}/checkins
Escopo checkins:write. Registra o check-in ou a entrega de kit (operações distintas, cada uma de uso único por inscrição). Identifique a inscrição pelo code ou pelo conteúdo lido do QR Code em qr_content.
- code
- código público da inscrição (obrigatório se não houver qr_content)
- qr_content
- texto completo do QR Code (obrigatório se não houver code)
- operation
checkinoukit
curl -X POST "https://largavo.com/api/v1/events/meia-maratona-das-pontes/checkins" \
-H "Authorization: Bearer SEU_TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{"code": "K7PM2QX4", "operation": "checkin"}'
200 — validado
{
"data": {
"ok": true,
"code": "ok",
"message": "Check-in confirmado.",
"used_by": null,
"used_at": null,
"registration": {
"code": "K7PM2QX4", "name": "Maria Souza", "document": "***.456.789-**",
"category": "21 km", "kit": "Kit completo", "kit_items": "Camiseta — M", "bib_number": "1042",
"checked_in": true, "kit_picked_up": false
}
}
}
409 — já validado (chamada repetida; segura para tratar como concluída)
{
"message": "Check-in já realizado em 04/10 às 07:12 por Catraca Norte.",
"errors": {},
"data": { "ok": false, "code": "already_used", "used_by": "Catraca Norte", "used_at": "2026-10-04T10:12:03+00:00", "registration": { ... } }
}
Outras recusas respondem 422 com data.code igual a invalid (QR não reconhecido), revoked (QR substituído após transferência), not_confirmed (inscrição sem pagamento, cancelada ou reembolsada) ou wrong_event. Um code inexistente no evento responde 404. Todas as tentativas ficam registradas no histórico de leituras do evento.
POST /events/{event}/results
Escopo results:write. Envia até 500 resultados por chamada. Cada item é validado individualmente; se qualquer item for inválido, nada é gravado e a resposta aponta o erro de cada um. Itens válidos são gravados por upsert (evento + número de peito): reenviar corrige sem duplicar. A classificação geral, por categoria e por sexo é recalculada a cada envio; resultados vinculados a uma inscrição pelo número de peito geram certificado.
- bib
- número de peito (obrigatório, até 12 caracteres, único na chamada)
- name
- nome do atleta (obrigatório)
- category
- nome da categoria (opcional; assume a da inscrição quando o número bate)
- gender
- M ou F (opcional)
- net_time
- tempo líquido HH:MM:SS ou HH:MM:SS.mmm (obrigatório para status finished)
- gross_time
- tempo bruto, mesmo formato (opcional)
- status
- finished (padrão) · dnf · dns · dsq
curl -X POST "https://largavo.com/api/v1/events/meia-maratona-das-pontes/results" \
-H "Authorization: Bearer SEU_TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" \
-d '{
"results": [
{"bib": "1042", "name": "Maria Souza", "category": "21 km", "gender": "F", "net_time": "01:38:12.450", "gross_time": "01:39:01"},
{"bib": "2210", "name": "João Lima", "category": "21 km", "gender": "M", "status": "dnf"}
]
}'
200 — gravado
{ "data": { "received": 2, "imported": 2, "matched_registrations": 1 } }
422 — item inválido (nada foi gravado)
{
"message": "1 item inválido. Nenhum resultado foi gravado — corrija e envie novamente.",
"errors": {
"results.1": ["Tempo líquido obrigatório para quem concluiu a prova (ou informe o status dnf, dns ou dsq)."]
}
}
Boas práticas
- Um token por integração (cronometragem, catraca, BI) com apenas os escopos necessários — fica mais fácil revogar sem derrubar as outras.
- Sincronize por
updated_sinceem vez de baixar tudo a cada minuto; respeiteRetry-Afterao receber 429. - Check-in é idempotente: trate 409 como "já feito" e siga em frente. Registre o
used_by/used_atpara conferência. - Resultados: envie em lotes de até 500, com o número de peito igual ao cadastrado nas inscrições para vincular certificados.
- Precisa de algo que não está aqui? Fale com o suporte pela sua organização no painel.