Skip to content

Notificações — sino, push, "Lembrar-me" e e-mail semanal

ADR-0178. O sino passa a ser calculado no servidor (o contador é o mesmo em todos os aparelhos da conta), há push por FCM, "Lembrar-me" e um e-mail semanal de novidades.

Todas as rotas /me/* são do cliente ou admin logado (Authorization: Bearer <JWT>). O descadastro do e-mail é público: a credencial é o link assinado do e-mail.


Como funciona

Peça Regra
Aviso do sino Expira em 90 dias. Vale para todos (audience=all) ou para uma conta. Aviso "para todos" anterior ao cadastro da conta não aparece
Tipos (type) new_title · new_episode · reminder · live
Quem é avisado Título novo → todos. Episódio → quem tem histórico ou Minha Lista na série. Lembrete → quem ligou o "Lembrar-me"
Quando Rotina novidades do worker (a cada 15 min): estreia (availability_start_date, senão release_date) nas últimas 24 h, uma vez por vídeo
Push Firebase Cloud Messaging (HTTP v1). Sem credencial no servidor, só o sino. Token morto sai sozinho. O tipo live existe nas preferências (lives), mas a rotina de estreias não o gera (live não tem entidade no catálogo)
Tokens de push Até 10 por conta; sem ser visto por 120 dias, sai
Preferências Valem para push e e-mail; o sino mostra tudo da conta
E-mail semanal Domingo 04:00; desligado até PUT /admin/config/weekly-email; só e-mail verificado

Push

Método Rota Corpo Resposta
POST /api/v1/me/push-tokens {token, platform, app_version?} 204
DELETE /api/v1/me/push-tokens/{token} — 204 sempre (sair duas vezes não é erro)
{"token": "fcm-token-do-aparelho...", "platform": "android", "app_version": "2.3.0"}
Campo Regra
token 10–4096 caracteres (token do FCM; iOS pelo APNs via FCM)
platform android | ios | web
app_version ≤ 20 caracteres, opcional

Chamar POST a cada abertura do app: o mesmo token só atualiza. Se outra conta entrar no aparelho, o token passa para ela. Chamar DELETE no logout.


"Lembrar-me"

Método Rota Resposta
PUT /api/v1/me/reminders/{video_id} 204; idempotente; 404 se o vídeo não existe
DELETE /api/v1/me/reminders/{video_id} 204
GET /api/v1/me/reminders {"video_ids": ["..."]} — os que ainda não estrearam, para o botão aceso

Na estreia, a pessoa recebe um aviso reminder no sino e o push.


Sino

GET /api/v1/me/notifications?limit=30

limit de 1 a 100 (padrão 30). Do mais novo para o mais antigo.

{
  "notifications": [
    {
      "id": "6720a1b2c3d4e5f607182970",
      "type": "new_episode",
      "title": "Novo episódio de No Divã",
      "body": "Episódio 4 já está disponível.",
      "image_url": "https://fdplay-api.infraifd.com/api/v1/media/images/6720...?expires=1730000000&sig=...",
      "link": "/watch/507f1f77bcf86cd799439011",
      "created_at": "2026-10-23T12:00:00Z",
      "read": false
    }
  ],
  "unread_count": 3
}
Campo Descrição
link Deep link do app: /watch/<videoId> ou /series/<seasonId>
image_url Imagem por link assinado de 7 dias, ou null
unread_count Contador do sino (o mesmo em todos os aparelhos)

POST /api/v1/me/notifications/read

204. Corpo {"ids": ["..."]} (até 100) marca só esses; {} (sem ids) marca todas até agora. Id que não é de aviso nenhum é ignorado.


Preferências

GET e PUT /api/v1/me/notification-preferences. As cinco chaves nascem ligadas.

{"new_titles": true, "new_episodes": true, "lives": true, "reminders": true, "weekly_email": true}

PUT aceita qualquer subconjunto das chaves (só as enviadas mudam) e devolve o conjunto completo.


Descadastro do e-mail semanal (público)

O link do e-mail é assinado (60 dias) e leva u, expires e sig na query.

Método Rota Efeito
GET /api/v1/notifications/unsubscribe?u=&expires=&sig= Página HTML com o botão "Descadastrar". Não descadastra: leitores de e-mail que abrem links sozinhos (Safe Links) não podem desligar ninguém
POST /api/v1/notifications/unsubscribe?u=&expires=&sig= Desliga weekly_email e mostra a confirmação. É também o alvo do one-click (List-Unsubscribe-Post, RFC 8058)

Link vencido ou adulterado: 403 com página HTML ("Este link venceu. Desligue o e-mail em Conta > Notificações, no app.").


Ligar o e-mail semanal (admin)

Método Rota Auth
GET /api/v1/config/weekly-email Público — {"enabled": false}
PUT /api/v1/admin/config/weekly-email Admin — corpo {"enabled": true}

Ligar manda e-mail de verdade

Nasce desligado. Ligado, o worker envia no domingo às 04:00 para cada cliente com e-mail verificado que não se descadastrou: milhares de e-mails reais, pelo mesmo provedor da verificação de e-mail e da recuperação de senha.


Erros

HTTP Quando
401 Sem login
403 Link de descadastro vencido/adulterado
404 PUT /me/reminders/{video_id} com vídeo inexistente ou id inválido
422 Corpo inválido (token curto demais, platform fora da lista, limit fora de 1–100)

Limite conhecido

Falha no meio de um aviso perde o resto dele em vez de repetir (o vídeo é reivindicado antes de avisar, para nunca avisar duas vezes).