Skip to content

Descoberta — avaliação, recomendados, buscas populares, pessoas e compartilhamento

ADR-0179 (descoberta) e ADR-0181 (prévia do link compartilhado).

Rotas /me/* e /search/popular, /people: Authorization: Bearer <JWT> (cliente ou admin). Avaliação e recomendação são por perfil: o header opcional X-Profile-Id escolhe o perfil; sem ele vale o perfil padrão (a conta); perfil de outra conta → 403 (perfis).


Avaliação (polegar)

Uma por perfil e vídeo: dislike, like ou love.

Método Rota Corpo Resposta
PUT /api/v1/me/ratings/{video_id} {"rating": "love"} 204; 404 se o vídeo não existe
DELETE /api/v1/me/ratings/{video_id} — 204
GET /api/v1/me/ratings — {"ratings": {"<video_id>": "like", ...}}
PUT /api/v1/me/ratings/507f1f77bcf86cd799439011
Authorization: Bearer <JWT>
X-Profile-Id: 6720a1b2c3d4e5f607182931
Content-Type: application/json

{"rating": "like"}

Recomendados — GET /api/v1/me/recommendations?limit=20

Ids de vídeos publicados, do mais para o menos indicado ao perfil. limit de 1 a 50 (padrão 20).

{"video_ids": ["507f1f77bcf86cd799439011", "507f1f77bcf86cd799439012"]}

Como é calculado (explicável, evolui depois):

  • cada categoria/tag dos vídeos que o perfil curtiu vale 2 pontos e dos que assistiu, 1;
  • cada vídeo publicado ganha a soma dos pontos das categorias/tags que tem;
  • ficam de fora o que o perfil já viu e o que levou dislike;
  • empate, ou falta de sinal, desempata pela data (os mais recentes primeiro).

O app busca os vídeos por id (GET /videos/{id}) — a rota devolve só os ids.


Buscas

POST /api/v1/me/search-log

204. Corpo {"query": "no diva"} (≤ 200 caracteres). O app chama quando a pessoa confirma a busca, não a cada tecla. O termo é guardado sem acento e em minúsculas, por 30 dias; menos de 2 caracteres não entra.

GET /api/v1/search/popular?limit=8

{"queries": ["no diva", "culto de domingo", "natal"]}
Regra Valor
Janela últimos 30 dias
Contagem pessoas distintas por termo (repetir o termo não sobe o ranking)
Mínimo termo só aparece com 5 ou mais pessoas
limit 1–20 (padrão 8)
Cache 5 minutos por réplica (um ranking de 20, fatiado pelo limit)

Rota fixa

/search/popular é registrada antes do /search/{collection} administrativo (Pesquisa Global), que capturaria "popular". Quem não é admin nunca cai lá.


Pessoas — GET /api/v1/people

Quem aparece nos vídeos publicados (people e cast), com quantos títulos — para os chips do filtro por pessoa. Sem foto nesta fase.

[{"name": "Ana Souza", "titles": 12}, {"name": "Pedro Lima", "titles": 7}]

Os campos people/cast são cadastrados no vídeo (ficha do título).


Compartilhamento — prévia do link (Open Graph)

WhatsApp, Instagram e Facebook leem og:* sem rodar JavaScript, e o app web é Flutter. Estas rotas públicas devolvem uma página HTML mínima com as metatags e mandam a pessoa para o app.

Rota Redireciona para
GET /api/v1/share/videos/{video_id} APP_PUBLIC_URL/watch/<id>
GET /api/v1/share/series/{season_id} APP_PUBLIC_URL/series/<id>
  • Resposta text/html com og:title, og:description (≤ 200 caracteres), og:image, og:url, twitter:card, <link rel="canonical"> e meta refresh para o app. Tudo escapado. Cache-Control: public, max-age=3600.
  • og:image é a capa horizontal (senão a vertical) por link assinado de 30 dias em /media/images/{id} (o WhatsApp guarda a prévia em cache).
  • Título desligado (enable=false), inexistente, ou série sem episódio publicado: prévia genérica do FD Play (200), sem dizer se o id existe.

Depende do front/infra

Só funciona se o link compartilhado (ou o proxy do domínio do app) chegar a estas rotas: a hospedagem do app (fallback de SPA, encaminhar robôs de link para /share/...) é do front/infra, não da API.


Erros

HTTP Quando
401 Sem login
403 X-Profile-Id de outra conta
404 PUT /me/ratings/{video_id} com vídeo inexistente
422 rating fora de dislike/like/love, limit fora da faixa, query > 200