Comece grátis, sem cartão de crédito. Ver os planos →

Para quem constrói

API

Tudo que é público no site, em JSON. Sem cadastro, sem chave, sem limite de uso razoável.

Para que serve

A pelada vive no grupo do WhatsApp, e a gente sabe disso. Esta API existe para você levar os dados até lá: um bot que responde “quem confirmou pra quinta?”, um placar no site do time, uma planilha que se atualiza sozinha. Você não precisa da nossa permissão nem avisar ninguém — é público do mesmo jeito que a página é.

E ela responde dois tipos de pergunta bem diferentes. Uma é sobre uma organização que você já conhece — o elenco, a agenda, a súmula de sábado. A outra é sobre o que existe por aí: onde tem jogo aberto neste fim de semana, quais goleiros estão disponíveis na cidade. As duas estão abaixo, nessa ordem invertida — a segunda vem primeiro porque é a que serve a quem ainda não conhece pelada nenhuma.

O básico

  • Base: https://gestao.semfirula.com/api/v1
  • Só GET. Não existe escrita — veja o porquê no fim.
  • Resposta em JSON, UTF-8. Datas em ISO 8601, sempre em UTC (terminam em Z).
  • Dinheiro em centavos inteiros: 2000 é R$ 20,00.
  • Organização inexistente responde 404.
  • Organização com a página oculta responde 404 também — e de propósito: a API devolve o que a página pública mostra, e uma página que ninguém vê não mostra nada.
  • Limite de 120 chamadas por minuto por IP. Passou disso, 429.
  • CORS liberado: dá para chamar direto do navegador, de qualquer site.
  • Resposta cacheada por 60 segundos na borda. Perguntar de dez em dez segundos não traz nada mais novo.

Toda lista diz quanto ela cortou

As rotas que devolvem lista trazem três campos junto: total (quantos existem no banco), limite (quantos couberam nesta resposta) e truncado (true se ficou coisa de fora). Peça mais com ?limite= — o teto é 200. Um valor inválido vira o padrão em vez de erro; você quer uma lista, não uma bronca.

Isso existe porque cortar em silêncio é pior que cortar: sem total, “vieram 50” e “existem 50” são a mesma resposta, e quem consome publica um elenco pela metade sem saber.

As rotas de relance

RotaO que devolve
/jogos Jogos abertos da vitrine, por cidade — o que serve a quem não conhece pelada nenhuma
/goleiros Goleiros disponíveis e convocações abertas, os dois lados na mesma resposta
/goleiros/{slug} Um goleiro: cidade, dias, cachê e reputação
/mapa Onde há jogo aberto e onde há organização — duas perguntas diferentes
/jogador/{slug} O perfil da pessoa, atravessando organizações. Opt-in
/esportes O que a súmula de cada esporte coleta. Leia antes de pedir partida
/planos Preço, teto de jogadores e comissão de cada plano
/org/{slug} Nome, cores, esporte e os rankings já prontos
/org/{slug}/jogadores O elenco ativo com a estatística de cada um
/org/{slug}/jogador/{slug} Um jogador daquela organização
/org/{slug}/eventos A agenda. ?passados=1 traz os que já aconteceram
/org/{slug}/evento/{slug} Um evento com quem confirmou — a pergunta do grupo
/org/{slug}/partidas As últimas partidas com placar e escalação
/org/{slug}/partida/{codigo} A súmula de uma partida
/org/{slug}/destaques Sequências, duplas, efeito e o artilheiro do mês
POST /org/{slug}/jogadores Escrita. Cadastra um jogador no elenco
POST /org/{slug}/eventos Escrita. Cria um evento na agenda
POST /org/{slug}/evento/{slug}/inscricoes Escrita. Confirma a presença de quem é do elenco
DELETE /org/{slug}/evento/{slug}/inscricoes/{slug} Escrita. Tira alguém da lista e promove a espera

Descobrir: o que existe por aí

/jogos

Os jogos abertos da vitrine — os que qualquer pessoa pode ver e entrar. É o endpoint para responder “tem jogo sábado aqui perto?” sem conhecer organização nenhuma.

Filtros: ?cidade= com o slug do município (santos-sp) e ?goleiro=1 para só o que está procurando goleiro. Cidade que não existe no catálogo do IBGE devolve a lista inteira, e não uma lista vazia — o erro aí é de digitação, não de dado. A resposta traz também cidades, com a contagem por município, que é o que alimenta um filtro do seu lado.

Cada jogo vem com vagas completo: o máximo de linha e de goleiro e quantas já foram ocupadas — “restam quantas?” é a pergunta, e devolver só o máximo obrigaria você a somar inscrição por conta própria. Não aparecem aqui: evento privado, jogo que começa em menos de 30 minutos, e organização com página oculta ou fora do ar.

/goleiros

O mercado de goleiros, os dois lados na mesma resposta: goleiros (quem está disponível, melhor avaliado primeiro) e convocacoes (as vagas abertas de jogos que ainda vão acontecer, com cachê e recado). Aceita ?cidade=.

Telefone não sai daqui, como não sai da página. O contato só faz sentido depois de um combinado entre as duas partes; publicá-lo transformaria isto num catálogo de telefones de gente que só queria jogar — e numa API isso é raspável em um comando.

/goleiros/{slug}

Um goleiro: cidade, dias em que joga, cachê e reputação (nota, avaliacoes, jogos). A nota é reconstruída de todas as avaliações, nunca incrementada. Perfil desativado responde 404.

/mapa

Onde há pelada, em duas listas: com_jogo_aberto (cidades com jogo na vitrine agora) e com_organizacao (cidades onde existe time cadastrado). São perguntas diferentes de propósito — uma cidade com dez peladas e nenhum jogo aberto some da primeira lista e continua na segunda, e é justamente ela que interessa a quem for decidir onde divulgar.

/jogador/{slug}

O perfil da pessoa, atravessando organizações: onde ela joga e como vai em cada esporte.

É opt-in: sem o perfil público ligado pela própria pessoa, responde 404. Organização de página oculta nunca aparece na lista — senão a privacidade de um time cairia pela porta do perfil de um jogador dele. E o agregado é por esporte, nunca somado: aces existe no vôlei e no tênis significando coisas diferentes.

/esportes

Os cinco esportes e o que a súmula de cada um coleta: posições, tipos de vaga, as colunas de estatística (com a sigla, se é rankeável e se é avançada) e o placar explicado em português. Sai do catálogo do código, não do banco.

Vale ler antes de pedir qualquer partida: é o que permite montar a tabela certa sem chutar nomes de campo. As marcadas avancada só são coletadas no plano Liga — se vierem zeradas, pode ser o plano, e não o jogador.

/planos

Nome, preço em centavos, teto de jogadores e comissão de cada plano. Deriva do mesmo arquivo que a página de preços e a cobrança de verdade usam — então copiar os números daqui é melhor que copiar da landing, que um dia muda.

Uma organização

/org/{slug}

O cartão da organização: nome, descrição, cores, se a inscrição é aberta, o esporte (com as chaves de estatística que ele usa) e os rankings já prontos — artilharia, assistências, aproveitamento, o que existir naquele esporte.

É a primeira chamada de quase toda integração: os rankings aqui poupam você de baixar o elenco inteiro e somar do seu lado.

/org/{slug}/jogadores

O elenco ativo, cada um com estatisticas: partidas, vitórias, empates, derrotas, aproveitamento, e os totais/por_partida por chave do esporte. Aceita ?limite=.

/org/{slug}/jogador/{slug}

Um jogador daquela organização, no mesmo formato do item da lista. O slug é o mesmo que aparece na URL da página dele.

/org/{slug}/eventos

A agenda. O padrão é o que vem pela frente, que é a pergunta que alguém faz num grupo; ?passados=1 traz também os que já aconteceram, do mais recente para o mais antigo.

situacao é o estado gravado (scheduled, open, finished, cancelled) e não manda sozinho na inscrição: a janela é regra de data, então um evento pode dizer open e já não aceitar ninguém porque o dia passou.

/org/{slug}/evento/{slug}

Um evento com quem confirmou — a pergunta do grupo. Cada inscrito traz nome, apelido, a vaga (line ou goalkeeper) e a situacao (confirmed ou waitlist), e o campo confirmados já vem contado.

Não traz telefone, e-mail nem se a pessoa pagou. Quem deve para a organização é assunto entre ela e quem organiza.

/org/{slug}/partidas

As últimas partidas com placar, times e escalação. Cada linha da súmula traz o jogador, o time e numeros — um dicionário com as chaves de estatística daquele esporte. Aceita ?limite=.

/org/{slug}/partida/{codigo}

Uma súmula pelo código curto que aparece na URL da partida. O código não é secreto (a página é pública) — ele só é estável e não sequencial.

/org/{slug}/destaques

Os números que rendem conversa: sequência de vitórias (atual e recorde), a dupla que mais joga do mesmo lado, o efeito de cada jogador — quanto o time rende com ele, relativo à média da própria organização — e o artilheiro do mês, que é a única versão do ranking que alguém que começou este ano pode ganhar.

A resposta traz minimos junto, e vale usar: sem saber que “dupla” exige um número mínimo de jogos juntos, não dá para distinguir “ninguém alcançou” de “não há dado” — e um quadro vazio publicado como resultado é pior que quadro nenhum.

Escrever

Ler é público. Escrever exige um token, criado pelo dono da organização em /org/{slug}/api — e ele decide, na hora de criar, o que aquele token pode fazer.

Como autenticar

curl -X POST https://gestao.semfirula.com/api/v1/org/pelada-do-ze/jogadores \
  -H "Authorization: Bearer gf_seu_token_aqui" \
  -H "Content-Type: application/json" \
  -d '{"nome": "João Silva", "apelido": "Jhow", "camisa": 10}'

Só o cabeçalho Authorization. Token na query string não funciona de propósito: o servidor registra o caminho inteiro de cada requisição, e um ?token= viraria segredo em texto puro num log — e ainda viajaria no Referer de qualquer link seguido a partir dali.

O token aparece uma única vez, na tela em que você o cria. Guardamos só um resumo criptográfico dele, então nem nós conseguimos mostrá-lo de novo: perdeu, revogue e crie outro.

Permissões

Um token nasce podendo nada, e cada permissão é uma caixa que você marca:

  • jogadores — cadastrar jogador no elenco
  • eventos — criar evento na agenda
  • inscricoes — confirmar e cancelar presença de quem já é do elenco

Faça um token por integração, com o mínimo que ela precisa. O bot do grupo que só confirma presença não deveria conseguir cadastrar ninguém — e se um dia o servidor dele vazar, a diferença entre esses dois tokens é a diferença entre um susto e um elenco reescrito.

Erros

  • 401 — token ausente, inválido ou revogado. Gere outro.
  • 403 — o token é válido mas não tem aquela permissão, ou é de outra organização. A resposta diz qual escopo falta.
  • 400 — falta um campo obrigatório, ou a data não está em ISO 8601.
  • 404 — evento ou jogador não existe naquela organização.
  • 409 — a regra do produto recusou: teto de jogadores do plano, evento encerrado ou cancelado.
  • 429 — mais de 60 escritas por minuto.

Todo uso fica registrado — inclusive o recusado — e o dono da organização vê a lista na mesma tela dos tokens. Não é vigilância: mil recusas no mesmo minuto é como um token vazado aparece.

POST /org/{slug}/jogadores

Cadastra um jogador. Escopo jogadores. Corpo: nome (obrigatório), apelido, posicoes (lista) e camisa. Responde 201 com o jogador no mesmo formato da leitura.

Passa pelo mesmo caminho da tela, então o teto de jogadores do seu plano vale aqui igual — estourou, é 409 com a frase explicando. Uma API que furasse o teto seria plano pago de graça para quem sabe programar.

POST /org/{slug}/eventos

Cria um evento. Escopo eventos. Corpo: nome e comeca_em (obrigatórios), local e preco_centavos.

comeca_em é ISO 8601 em UTC (2026-08-20T23:00:00Z), o mesmo formato que a leitura devolve. Não aceitamos hora local porque isso obrigaria a adivinhar o seu fuso — e um palpite errado marca o jogo três horas antes.

POST /org/{slug}/evento/{slug}/inscricoes

Confirma a presença de quem já é do elenco. Escopo inscricoes. Corpo: {"jogador": "slug-do-jogador"}. É o endpoint do bot no grupo.

Vaga cheia responde 201 com "situacao": "waitlist" — e não um erro: é o que a tela faz, e transformar em erro faria o bot mentir para quem chegou por último. Jogador que não existe responde 404 pedindo que você o cadastre antes; um evento não é porta de entrada para o elenco, nem pela API. Evento encerrado ou cancelado responde 409: quem tem o token administra, mas “encerrado” precisa querer dizer alguma coisa.

DELETE /org/{slug}/evento/{slug}/inscricoes/{slug}

Tira alguém da lista. Escopo inscricoes. A resposta traz promovido com o slug de quem subiu da espera no lugar — mesmo tipo de vaga, como na tela.

Esse campo existe para o seu bot avisar a pessoa certa: sem ele, o cancelamento aparece no grupo e a promoção não, que é justamente a metade que interessa a quem estava esperando.

Um exemplo

curl https://gestao.semfirula.com/api/v1/jogos?cidade=santos-sp
{
  "total": 3,
  "limite": 50,
  "truncado": false,
  "jogos": [
    {
      "organizacao": "pelada-do-ze",
      "organizacao_nome": "Pelada do Zé",
      "esporte": "futebol",
      "slug": "pelada-de-quinta",
      "nome": "Pelada de quinta",
      "local": "Quadra do Parque",
      "cidade": { "slug": "santos-sp", "name": "Santos", "uf": "SP" },
      "comeca_em": "2026-08-20T23:00:00Z",
      "preco_centavos": 2000,
      "vagas": {
        "linha": 20, "goleiro": 2,
        "linha_ocupadas": 17, "goleiro_ocupadas": 1
      }
    }
  ],
  "cidades": [ { "slug": "santos-sp", "name": "Santos", "uf": "SP", "total": 3 } ]
}

Cada esporte tem os seus números

Um jogador de vôlei tem aces onde o de futebol tem goals — e nenhum dos dois carrega o campo do outro. Em vez de chutar os nomes, leia esporte.estatisticas em /org/{slug}, ou o catálogo inteiro em /esportes. Num esporte cooperativo, como o frescobol, tem_vencedor vem false e o placar é null — porque ali ninguém ganha, e inventar um vencedor seria pior que não ter.

O que ela não faz, e por quê

A escrita cobre elenco, agenda e presença — e para por aí. Não dá para lançar gol na súmula, mexer em dinheiro, editar as configurações da organização nem apagar nada. Não é falta de tempo: cada uma dessas exige uma conversa própria sobre o que acontece quando um token vaza, e a súmula ainda tem o cronômetro do jogo ao vivo no meio. Elas chegam quando essa conversa acontecer, uma de cada vez.

A escrita que existe só existe porque as quatro coisas que a tornam defensável existem juntas: token por organização, escopo, revogação pela tela do dono e registro de uso. Meia disso seria pior que nenhuma.

E ela não devolve nada privado. Nem telefone, nem e-mail, nem quem está devendo, nem as anotações do administrador. Cada resposta é montada campo a campo a partir das mesmas funções que desenham a página pública — nada fica exposto só por existir uma API.

Construiu alguma coisa com isto? Conta pra gente em gestao@semfirula.com — dá vontade de ver.