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) |
| 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.
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).