Endpoints de notificações
Notificações in-app para o usuário logado: revisões atribuídas, menções, publicações, etc. Disponíveis via REST clássico + Server-Sent Events para contagem em tempo real.
Tabela de endpoints
| Método | Caminho | Auth | Descrição |
|---|---|---|---|
| GET | /notifications | Sessão | Lista notificações e contagens. |
| POST | /notifications/mark-read | Sessão | Marca notificações como lidas. |
| GET | /notifications/stream | Sessão | SSE — contagem atualizada em tempo real. |
Escopo: estes endpoints usam sessão de usuário (JWT/cookie).
context.user_idecontext.organization_idprecisam estar preenchidos — API keys puras não suportam notificações.
GET /notifications
Retorna a lista de notificações do usuário para a organização ativa.
Query params:
limit— 1–200. Padrão 50.unread_only—trueretorna apenas não lidas. Padrãofalse.
Response 200 (NotificationListResponse):
{
"items": [
{
"id": "ntf_...",
"user_id": "usr_...",
"organization_id": "org_...",
"kind": "review.created",
"title": "Nova revisão em projeto Edge rules",
"body": "Ana solicitou sua revisão em 'Refactor sshd'",
"link": "/projects/prj_.../reviews/rev_...",
"read_at": null,
"created_at": "2026-04-24T14:00:00Z"
}
],
"total": 12,
"unread": 3
}
kind— tipo da notificação (review.created,review.approved,version.published,api.quota.warning, etc.).read_at—nullenquanto não lida; ISO 8601 após ser marcada.total— total no período retornado.unread— total não lidas.
POST /notifications/mark-read
Marca notificações específicas ou todas como lidas.
Request body (NotificationMarkReadRequest):
{ "ids": ["ntf_aaa", "ntf_bbb"] }
ids— lista de IDs. Se vazia/ausente, marca todas as não lidas do usuário na organização como lidas.
Response 200: NotificationListResponse atualizado (mesmo shape do GET /notifications).
GET /notifications/stream (SSE)
Stream em tempo real que emite a contagem de não lidas sempre que ela muda.
Headers de requisição:
Accept: text/event-stream
Authorization: Bearer <jwt>
(API keys não funcionam aqui — é um endpoint de sessão.)
Formato do stream:
event: unread
data: {"unread": 3}
: keep-alive
event: unread
data: {"unread": 4}
: keep-alive
- O primeiro
event: unreadchega imediatamente ao conectar (semeia o estado do cliente). : keep-aliveé um comentário SSE para evitar que proxies fechem a conexão.- A próxima linha
event: unreadsó aparece quando a contagem muda.
Limites
- Conexões simultâneas por usuário são limitadas. Se exceder,
429 sse_connection_limit_exceededcomRetry-After. Reuse a conexão aberta. - O servidor usa polling interno (5 s) para detectar mudanças — a latência máxima da notificação é ~5 s.
Exemplo (navegador)
const es = new EventSource("/api/v1/notifications/stream", { withCredentials: true })
es.addEventListener("unread", (ev) => {
const { unread } = JSON.parse(ev.data)
document.getElementById("badge").textContent = String(unread)
})
es.onerror = (err) => {
console.error("SSE falhou", err)
// browser EventSource faz reconnect automático; respeita Retry-After em 429.
}
Exemplo (curl)
curl -N "$RF_BASE/notifications/stream" \
-H "Accept: text/event-stream" \
-H "Authorization: Bearer $JWT"
(-N desabilita o buffer do curl para vermos os eventos chegando.)
Estruturas compartilhadas
NotificationRecord
{
"id": "string",
"user_id": "string",
"organization_id": "string",
"kind": "string",
"title": "string",
"body": "string",
"link": "string|null",
"read_at": "ISO 8601|null",
"created_at": "ISO 8601"
}
NotificationListResponse
{
"items": [ "NotificationRecord[]" ],
"total": 0,
"unread": 0
}