# Spike — Fonte de calendário e placar (football-data.org)

**Data:** 03/08/2026 · **Escopo:** os 2 itens pendentes registrados em
`docs/prd/palpite-e-prazo.md`

> **Limite deste spike:** o tier Free exige um token que só é emitido por
> cadastro com e-mail. Não criei conta em nome do Igor. Portanto o que segue é
> **verificação documental + endpoint público**, não teste empírico com dados
> ao vivo. O que ficou sem verificar está marcado como tal.

---

## Veredito

**O tier Free não atende ao produto que foi especificado.** O plano de €12/mês
("Free w/ Livescores") é o mínimo viável. A alternativa é revisar a métrica
aceita na seção 2 do PRD.

## ✅ Decisão (03/08/2026): fica no tier Free

**É uma PoC e não haverá investimento neste momento.** Consequências aceitas:

- **A métrica "ponto logo após o apito" foi revisada** no PRD de _Palpite e
  prazo_. O placar chega com atraso e a PoC não demonstra esse momento.
- **`PP-6` fica com confiabilidade desconhecida** — o atraso de _schedule_ do
  tier Free não é documentado. Numa PoC curta o risco é baixo, porque adiamento
  de jogo é evento raro na janela de teste. **Recomendo despriorizar `PP-6` para
  fora da PoC** em vez de entregá-la sem poder confiar nela.
- **Licença de uso comercial fica em aberto**, e isso é aceitável **enquanto a
  PoC não for publicada nem movimentar dinheiro**. Precisa ser resolvido antes
  de ir para as lojas.
- **Ainda é necessário registrar-se** em `football-data.org/client/register`
  para obter o token. É gratuito, mas depende de ação do Igor — sem token,
  `CC-1` não sai do papel.

---

## Item 1 — A fonte informa mudança de horário? ✅ com ressalva

**Sim, tecnicamente é viável.** O recurso `Match` da API v4 expõe:

- **`status`** com o enum completo: `SCHEDULED | LIVE | IN_PLAY | PAUSED |
  FINISHED | POSTPONED | SUSPENDED | CANCELLED`
- **`utcDate`** — o horário agendado do jogo, que passa a refletir a nova data
  quando o jogo é remarcado
- **`lastUpdated`** — timestamp de quando o registro mudou, o que permite
  detectar alteração sem comparar campo a campo
- Filtros `status` e `dateFrom`/`dateTo` em `/competitions/{id}/matches`

Isso é suficiente para `PP-6`: o backend faz polling, compara `utcDate` com o
valor armazenado e reabre o palpite quando muda. **Não existe webhook** — a
detecção é por comparação no nosso lado, como já estava previsto.

**⚠️ Ressalva não resolvida:** o tier Free entrega **"schedules delayed"**,
não só scores. Quanto tempo esse atraso representa **não está documentado em
nenhum lugar público**. Se for grande, `PP-6` detecta o adiamento tarde e o
prazo fecha na hora errada — exatamente a falha que a story existe para evitar.

## Item 2 — Qual o atraso do placar? ❌ reprovado para o tier Free

**O tier Free tem placar atrasado por design.** Live scores começam no plano de
**€12/mês**. A duração exata do atraso não é publicada.

Isso **contraria diretamente a métrica aceita** no PRD de _Palpite e prazo_ e a
necessidade levantada na Fase 1 pelo participante casual: *"preciso ver o
resultado e o meu ponto logo depois do apito, não no dia seguinte."*

Também afeta `PR-1` (cálculo do ponto) e `PP-7` (o sigilo só libera quando o
jogo termina — com placar atrasado, os palpites ficam escondidos por mais tempo
do que o previsto).

---

## Achados adicionais, não previstos no spike

### A API distingue CANCELLED de POSTPONED — e nós decidimos ignorar

A decisão de 03/08 foi tratar **todo** jogo não realizado como adiado. Mas a
fonte informa `CANCELLED` explicitamente. Consequência concreta: um jogo
cancelado ficaria aguardando nova data **para sempre**, mantendo o bolão aberto
(`CV-1`), enquanto a API está dizendo que ele não vai acontecer.

A saída prevista é o admin encerrar antecipadamente (`CV-3`) ou lançar placar à
mão (`PR-10`). **Vale reconsiderar:** tratar `CANCELLED` de forma diferente
custa pouco, já que o dado vem de graça.

### Só o Brasileirão Série A é gratuito

Consultando o endpoint público `/v4/competitions` (não exige token):

| Competição | Código | Plano |
| ---------- | ------ | ----- |
| Campeonato Brasileiro Série A | `BSA` | **TIER_ONE** (gratuito) |
| Campeonato Brasileiro Série B | `BSB` | TIER_THREE (pago) |
| Copa do Brasil | `CDB` | TIER_FOUR (pago) |
| Série C / Série D | — | TIER_FOUR (pago) |

Coerente com a decisão de fazer só o Brasileirão. Mas **expandir depois custa
plano**, não só código.

Temporada atual de `BSA` confirmada pela API: **28/01/2026 a 02/12/2026**,
rodada corrente **22**.

### O rate limit de 10 req/min não é problema

A leitura de que "poucos usuários atualizando a tela esgotam o limite" só vale
para app que chama a API direto. **Nossa arquitetura não faz isso:** o backend
faz polling, armazena, e o app consome o nosso banco. Pollar a rodada inteira
de hora em hora custa ~24 requests/dia — folgado dentro de 10/min.

### Licença de uso comercial: não documentado ⚠️

A página `/terms` retorna **404**, e nem o site nem a documentação declaram se o
tier gratuito permite uso comercial, nem se exige atribuição. Para um app que
pode passar a movimentar dinheiro, isso é risco a resolver **antes** de
publicar — e só se resolve escrevendo para `daniel@football-data.org`.

---

## O que ainda exige teste empírico (precisa de token)

1. **Quantos minutos/horas de atraso** o tier Free aplica a placar e a schedule.
2. **Quanto tempo a fonte leva** para refletir um adiamento real do Brasileirão.
3. Se `lastUpdated` muda de forma confiável quando só o `utcDate` é alterado.

Para isso é preciso registrar em `football-data.org/client/register` e obter o
token — ação que depende do Igor.

---

## Recomendação

1. **Subir para o plano de €12/mês** ("Free w/ Livescores", 20 req/min). É o
   mínimo que sustenta a métrica aceita, e o custo é baixo o suficiente para não
   valer a discussão.
2. Se a preferência for continuar no gratuito, **revisar a métrica** do PRD e
   avisar o usuário na interface de que o resultado tem atraso — o que enfraquece
   a proposta contra o grupo do WhatsApp, onde o placar chega na hora.
3. **Escrever para o mantenedor** sobre uso comercial, independentemente do
   plano escolhido.
4. **Reconsiderar tratar `CANCELLED` separadamente**, já que o dado existe.
