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
404també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
| Rota | O 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 elencoeventos— criar evento na agendainscricoes— 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.