Pular para o conteúdo
Largavo

API para parceiros

Integre cronometragem, catracas, totens e sistemas próprios com os dados da sua organização. REST, JSON e versionada em /v1.

v1 Base: https://largavo.com/api/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óprio timezone para exibição.
  • Valores monetários são inteiros em centavos (price_cents).
  • Envie o corpo das requisições POST em JSON com Content-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"

Escopos

Cada token carrega apenas os escopos escolhidos na criação. Chamar um endpoint sem o escopo necessário responde 403.

EscopoPermiteEndpoints
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ódigoQuando acontece
200Sucesso.
401Token ausente, inválido ou revogado.
403Token sem o escopo necessário, ou organização suspensa.
404Evento ou inscrição inexistente na sua organização.
409Check-in ou kit já validado anteriormente (chamada repetida).
422Dados inválidos ou validação recusada (QR inválido, inscrição não confirmada, outro evento).
429Limite de requisições por minuto excedido.
5xxFalha 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
checkin ou kit
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_since em vez de baixar tudo a cada minuto; respeite Retry-After ao receber 429.
  • Check-in é idempotente: trate 409 como "já feito" e siga em frente. Registre o used_by/used_at para 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.