API Reference — Notifica v1
Referência completa da API REST do Notifica. Todos os endpoints são prefixados com /v1 e requerem autenticação (exceto onde indicado).
Base URL: https://app.usenotifica.com.br
Autenticação
Todos os endpoints /v1/* requerem autenticação via API key no header Authorization:
Authorization: Bearer nk_live_aBcDeFgHiJkLmNoPqRsTuVwXyZ...
Tipos de API Key
| Prefixo | Tipo | Uso |
|---|---|---|
nk_live_ | Secret (produção) | Backend — acesso total |
nk_test_ | Secret (sandbox) | Backend — ambiente de teste |
pk_live_ | Public (produção) | Frontend — acesso limitado (in-app, subscriber) |
pk_test_ | Public (sandbox) | Frontend — ambiente de teste |
Headers Comuns
Idempotência
Endpoints POST que suportam idempotência aceitam o header:
Idempotency-Key: seu-identificador-unico
Se uma request com a mesma chave já foi processada, a resposta original é retornada sem reprocessar. Chaves expiram após 24 horas.
Endpoints com suporte a idempotência:
POST /v1/notificationsPOST /v1/channelsPOST /v1/templatesPOST /v1/workflowsPOST /v1/workflows/:slug/triggerPOST /v1/subscribersPOST /v1/webhooksPOST /v1/api-keysPOST /v1/domains
Autenticação por Tipo de Key
Dependendo do tipo de API key, o comportamento da API muda:
| Tipo | Acesso | Validação extra |
|---|---|---|
Secret (nk_*) | Todos os endpoints | Nenhuma |
Public (pk_*) | Somente subscriber-scoped (in-app) | Header Origin validado contra allowed origins |
| Dashboard (sessão) | Todos os endpoints | Cookie de sessão |
Requests com publishable keys que vêm de um origin não permitido recebem 403 Forbidden. Veja Inbox Embed — Allowed Origins para configuração.
Rate Limiting
Todas as requests autenticadas passam por rate limiting. Headers de resposta:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1706961600
Quando excedido, retorna 429 Too Many Requests.
Paginação (Cursor-Based)
Endpoints de listagem suportam paginação baseada em cursor:
GET /v1/notifications?limit=20&cursor=eyJpZCI6Ii4uLiJ9
A resposta inclui:
{
"data": [...],
"meta": {
"cursor": "eyJpZCI6Ii4uLiJ9",
"has_more": true
}
}
Passe o cursor retornado como parâmetro na próxima request para obter a próxima página.
Rotas Públicas (Sem Autenticação)
Health Check
GET /health
Retorna status do serviço. Usado para monitoring/uptime checks.
Unsubscribe (LGPD)
GET /unsubscribe/:token
POST /unsubscribe/:token
Link de descadastro em um clique. Não requer autenticação — o token é auto-contido e seguro. Usado em emails para conformidade com LGPD.
Auth — Login no Dashboard
Magic Link (Passwordless)
POST /auth/magic-link
Solicita envio de magic link por email para login no dashboard.
Body:
{"email": "[email protected]"}
GET /auth/magic-link/verify?token=...
Verifica o magic link e estabelece sessão (redirect para dashboard).
OAuth
GET /auth/:provider → Inicia fluxo OAuth (google, github)
GET /auth/:provider/callback → Callback do provider OAuth
DELETE /auth/logout → Encerra sessão
Notifications — Envio e Consulta
Enviar Notificação
POST /v1/notifications
Cria e enfileira uma notificação para entrega assíncrona.
Headers: Idempotency-Key (recomendado)
Body:
{
"channel": "email",
"to": "[email protected]",
"template": "welcome-email",
"data": {
"name": "João",
"company": "Empresa Ltda"
},
"metadata": {
"source": "signup-flow"
}
}
| Campo | Obrigatório | Descrição |
|---|---|---|
channel | Sim | Canal: email, whatsapp, sms, in_app, push |
to / recipient | Sim | Endereço destino (email, telefone E.164, etc.) |
template / template_id | Não | Slug do template para renderizar |
data / payload | Não | Variáveis para o template ou conteúdo raw |
metadata | Não | Metadados arbitrários (não processados) |
Resposta (202 Accepted):
{
"data": {
"id": "notif-uuid",
"channel": "email",
"recipient": "[email protected]",
"status": "pending",
"created_at": "2025-02-03T10:00:00Z"
}
}
Listar Notificações
GET /v1/notifications
| Parâmetro | Tipo | Descrição |
|---|---|---|
limit | int | Máximo por página (default: 20, max: 100) |
cursor | string | Cursor de paginação |
status | string | Filtrar por status |
channel | string | Filtrar por canal |
Resposta (200 OK):
{
"data": [
{
"id": "notif-uuid",
"channel": "email",
"recipient": "[email protected]",
"status": "delivered",
"template_id": "welcome-email",
"created_at": "2025-02-03T10:00:00Z"
}
],
"meta": {
"cursor": "...",
"has_more": true
}
}
Obter Notificação
GET /v1/notifications/:id
Retorna detalhes da notificação com tentativas de entrega (preloaded).
Listar Tentativas de Entrega
GET /v1/notifications/:notification_id/attempts
Retorna as tentativas de entrega para uma notificação específica, ordenadas por número da tentativa.
Resposta (200 OK):
{
"data": [
{
"id": "attempt-uuid",
"attempt_number": 1,
"status": "success",
"provider_response": {...},
"created_at": "2025-02-03T10:00:01Z"
}
]
}
Templates — Gerenciamento de Templates
Criar Template
POST /v1/templates
Headers: Idempotency-Key (recomendado)
Body:
{
"channel": "email",
"slug": "welcome-email",
"name": "Email de Boas-Vindas",
"content": "Olá {{name}}, bem-vindo ao {{company}}!",
"variables": ["name", "company"],
"variants": {
"subject": "Bem-vindo, {{name}}!",
"html_body": "<h1>Olá {{name}}</h1><p>Bem-vindo ao {{company}}!</p>"
},
"language": "pt_BR",
"status": "active"
}
| Campo | Obrigatório | Descrição |
|---|---|---|
channel | Sim | Canal alvo |
slug | Sim | Identificador URL-safe |
name | Sim | Nome legível |
content | Sim | Conteúdo com {{variáveis}} |
variables | Não | Lista de variáveis (auto-extraída se omitida) |
variants | Não | Variantes por canal (subject, html_body, etc.) |
language | Não | Idioma (default: pt_BR) |
status | Não | draft ou active (default: draft) |
metadata | Não | Metadados extras |
provider_template_id | Não | Referência a template externo |
Resposta (201 Created):
{
"data": {
"id": "tpl-uuid",
"slug": "welcome-email",
"name": "Email de Boas-Vindas",
"channel": "email",
"content": "Olá {{name}}, bem-vindo ao {{company}}!",
"variables": ["name", "company"],
"status": "active"
}
}
Listar Templates
GET /v1/templates
| Parâmetro | Tipo | Descrição |
|---|---|---|
channel | string | Filtrar por canal |
status | string | Filtrar por status (draft, active) |
Obter Template
GET /v1/templates/:id
Atualizar Template
PUT /v1/templates/:id
Deletar Template
DELETE /v1/templates/:id
Retorna 204 No Content.
Preview de Template (Salvo)
POST /v1/templates/:id/preview
Body:
{
"variables": {
"name": "João",
"company": "Empresa Ltda"
}
}
Resposta (200 OK):
{
"data": {
"rendered": {
"body": "Olá João, bem-vindo ao Empresa Ltda!",
"subject": "Bem-vindo, João!",
"html_body": "<h1>Olá João</h1><p>Bem-vindo ao Empresa Ltda!</p>"
},
"variables": ["name", "company"],
"validation": {
"valid": true,
"errors": [],
"warnings": []
}
}
}
Preview de Conteúdo Arbitrário
POST /v1/templates/preview
Útil para preview em tempo real no editor de templates.
Body:
{
"content": "Olá {{name}}!",
"channel": "email",
"variables": {"name": "Maria"},
"variants": {"subject": "Oi {{name}}"}
}
Validar Template (Salvo)
POST /v1/templates/:id/validate
Resposta (200 OK):
{
"data": {
"valid": true,
"errors": [],
"warnings": ["Email templates should include a 'subject' in variants."],
"variables": ["name", "order_id"]
}
}
Validar Conteúdo Arbitrário
POST /v1/templates/validate
Body:
{
"content": "Olá {{name}}!",
"channel": "email",
"variants": {}
}
Workflows — Orquestração
Veja Workflows — Documentação Completa para guia detalhado.
CRUD
POST /v1/workflows → Criar workflow (idempotent)
GET /v1/workflows → Listar workflows
GET /v1/workflows/:id → Obter workflow
PUT /v1/workflows/:id → Atualizar (cria nova versão)
DELETE /v1/workflows/:id → Soft delete
Trigger
POST /v1/workflows/:slug/trigger
Body:
{
"recipient": "[email protected]",
"data": {"name": "João", "plan": "pro"}
}
Resposta (202 Accepted) — Retorna o workflow run criado.
Workflow Runs
GET /v1/workflow-runs → Listar execuções
GET /v1/workflow-runs/:id → Detalhes (com step_results)
POST /v1/workflow-runs/:id/cancel → Cancelar execução em andamento
Subscribers — Gerenciamento de Destinatários
Criar/Upsert Subscriber
POST /v1/subscribers
Headers: Idempotency-Key (recomendado)
Body:
{
"external_id": "user-123",
"email": "[email protected]",
"phone": "+5511999998888",
"name": "João Silva",
"locale": "pt_BR",
"timezone": "America/Sao_Paulo",
"custom_properties": {
"plan": "pro",
"signup_date": "2025-01-15"
}
}
| Campo | Obrigatório | Descrição |
|---|---|---|
external_id | Sim | Seu identificador do usuário (upsert key) |
email | Não | Email do subscriber |
phone | Não | Telefone E.164 (ex: +5511999998888) |
name | Não | Nome de exibição |
locale | Não | Locale preferido |
timezone | Não | Timezone preferida |
custom_properties | Não | Dados customizados (key-value) |
LGPD: O Notifica registra automaticamente consentimento (timestamp, IP, método) em toda criação de subscriber via API.
Listar Subscribers
GET /v1/subscribers
| Parâmetro | Tipo | Descrição |
|---|---|---|
limit | int | Máximo por página (default: 20, max: 100) |
offset | int | Offset de paginação |
search | string | Busca por email, nome ou external_id |
Obter / Atualizar / Deletar
GET /v1/subscribers/:id → Detalhes
PUT /v1/subscribers/:id → Atualizar
DELETE /v1/subscribers/:id → Soft delete (nullifica PII — LGPD)
DELETE executa soft delete com nullificação de PII: email, telefone e nome são removidos para conformidade com LGPD. Esta operação é irreversível.
Preferências de Notificação
GET /v1/subscribers/:id/preferences
PUT /v1/subscribers/:id/preferences
Body (PUT):
{
"preferences": [
{"category": "marketing", "channel": "email", "enabled": false},
{"category": "transactional", "channel": "whatsapp", "enabled": true}
]
}
Import em Lote
POST /v1/subscribers/import
Body:
{
"subscribers": [
{"external_id": "user-1", "email": "[email protected]", "name": "Ana"},
{"external_id": "user-2", "email": "[email protected]", "name": "Bruno"}
]
}
Upsert transacional — se um subscriber falhar validação, todo o lote é revertido.
Resposta (200 OK):
{
"data": {
"imported": 2,
"subscribers": [...]
}
}
Erro (422): Retorna o índice do subscriber que falhou.
Notificações In-App
GET /v1/subscribers/:id/notifications → Listar notificações in-app
POST /v1/subscribers/:id/notifications/:notif_id/read → Marcar como lida
POST /v1/subscribers/:id/notifications/read-all → Marcar todas como lidas
GET /v1/subscribers/:id/notifications/unread-count → Contagem de não lidas
| Parâmetro | Tipo | Descrição |
|---|---|---|
limit | int | Máximo por página |
offset | int | Offset |
unread_only | bool | Apenas não lidas |
Channels — Configuração de Canais
CRUD de Configuração
POST /v1/channels → Criar (idempotent)
GET /v1/channels → Listar
GET /v1/channels/:channel → Obter (por nome do canal)
PUT /v1/channels/:channel → Atualizar
DELETE /v1/channels/:channel → Deletar
Body (POST/PUT):
{
"channel": "email",
"provider": "aws_ses",
"credentials": {
"access_key_id": "AKIA...",
"secret_access_key": "...",
"region": "us-east-1"
},
"settings": {
"from_address": "[email protected]",
"from_name": "Empresa"
}
}
Credenciais são criptografadas em repouso e nunca retornadas nas respostas da API.
Testar Canal
POST /v1/channels/:channel/test
Envia uma notificação de teste usando a configuração atual do canal.
Resposta (200 OK):
{
"data": {
"success": true,
"message": "Test notification enqueued for email channel"
}
}
Domains — Domínios de Envio
CRUD
POST /v1/domains → Registrar domínio (idempotent)
GET /v1/domains → Listar domínios
GET /v1/domains/:id → Detalhes do domínio
POST /v1/domains/:id/verify → Verificar DNS
DELETE /v1/domains/:id → Remover domínio
Body (POST):
{"domain": "suaempresa.com.br"}
Resposta (201 Created):
{
"data": {
"id": "dom_abc123",
"domain": "suaempresa.com.br",
"status": "pending",
"dns_records": {
"txt": {
"name": "suaempresa.com.br",
"type": "TXT",
"value": "notifica-verification=aBcDeFg..."
}
}
}
}
Veja: Configuração de Domínio | DKIM | Dashboard
Health Check
GET /v1/domains/:id/health → Status de saúde do domínio
POST /v1/domains/:id/health/check → Forçar verificação (1/min rate limit)
Alertas
GET /v1/domains/alerts → Listar alertas de domínio
Veja: Monitoramento de Saúde
Webhooks — Eventos Outbound
CRUD
POST /v1/webhooks → Criar webhook (idempotent)
GET /v1/webhooks → Listar webhooks
GET /v1/webhooks/:id → Obter webhook
PUT /v1/webhooks/:id → Atualizar webhook
DELETE /v1/webhooks/:id → Deletar webhook
Body (POST):
{
"url": "https://meuapp.com.br/webhooks/notifica",
"events": ["notification.delivered", "notification.failed", "notification.bounced"]
}
Resposta (201 Created): Inclui o signing_secret (retornado apenas na criação).
{
"data": {
"id": "wh-uuid",
"url": "https://meuapp.com.br/webhooks/notifica",
"events": ["notification.delivered", "notification.failed"],
"active": true,
"signing_secret": "whsec_aBcDeFgHiJkLmN..."
}
}
O signing_secret é exibido apenas uma vez (na criação). Salve-o em local seguro. Use-o para verificar a assinatura HMAC dos payloads recebidos.
Testar Webhook
POST /v1/webhooks/:id/test
Envia um evento notification.test para o webhook configurado.
Listar Entregas
GET /v1/webhooks/:id/deliveries
| Parâmetro | Tipo | Descrição |
|---|---|---|
limit | int | Máximo de resultados (default: 20, max: 100) |
Analytics — Métricas e Dashboards
Overview
GET /v1/analytics/overview
| Parâmetro | Tipo | Descrição |
|---|---|---|
period | string | 1h, 24h, 7d, 30d (default: 24h) |
Por Canal
GET /v1/analytics/channels
| Parâmetro | Tipo | Descrição |
|---|---|---|
period | string | 1h, 24h, 7d, 30d (default: 24h) |
Time Series
GET /v1/analytics/timeseries
| Parâmetro | Tipo | Descrição |
|---|---|---|
period | string | 24h, 7d, 30d (default: 24h) |
granularity | string | hour ou day (auto-detectado se omitido) |
Top Templates
GET /v1/analytics/templates
| Parâmetro | Tipo | Descrição |
|---|---|---|
period | string | 1h, 24h, 7d, 30d (default: 24h) |
limit | int | Máximo de templates (default: 10, max: 100) |
API Keys — Gerenciamento de Chaves
GET /v1/api-keys → Listar chaves (sem raw key)
POST /v1/api-keys → Criar chave (retorna raw key uma vez)
DELETE /v1/api-keys/:id → Revogar chave
Body (POST):
{
"key_type": "secret",
"label": "Backend Production",
"environment": "production"
}
Resposta (201 Created):
{
"data": {
"id": "key-uuid",
"key_type": "secret",
"label": "Backend Production",
"prefix": "nk_live_",
"raw_key": "nk_live_aBcDeFgHiJkLmNoPqRsT..."
}
}
A raw_key é exibida apenas uma vez. Salve-a imediatamente em um gerenciador de segredos. Se perder, será necessário gerar uma nova.
Sessão — Usuário Atual
GET /v1/me
Retorna informações do usuário autenticado na sessão do dashboard.
Inbox Embed — Allowed Origins
Endpoints para gerenciar a lista de origins permitidos para requests feitas com publishable keys (pk_*) no frontend. Essas configurações protegem sua key contra uso não autorizado em domínios de terceiros.
Esses endpoints requerem autenticação com secret key (nk_*). Publishable keys não têm permissão para alterar configurações de segurança.
Settings do Inbox Embed
GET /v1/inbox-embed/settings
PUT /v1/inbox-embed/settings
Resposta (GET 200 OK):
{
"data": {
"developer_mode": true,
"allowed_origins_count": 3
}
}
Body (PUT):
{
"developer_mode": false
}
| Campo | Tipo | Descrição |
|---|---|---|
developer_mode | bool | Quando true, aceita automaticamente requests de localhost e 127.0.0.1 em qualquer porta |
Desative developer_mode em produção. Ele permite qualquer request de localhost, o que é conveniente para desenvolvimento mas inseguro em produção.
Listar Allowed Origins
GET /v1/inbox-embed/allowed-origins
Resposta (200 OK):
{
"data": [
{
"id": "ao_abc123",
"origin": "https://meuapp.com.br",
"created_at": "2025-02-01T10:00:00Z"
},
{
"id": "ao_def456",
"origin": "https://staging.meuapp.com.br",
"created_at": "2025-02-01T10:05:00Z"
}
]
}
Adicionar Allowed Origin
POST /v1/inbox-embed/allowed-origins
Body:
{
"origin": "https://meuapp.com.br"
}
| Campo | Obrigatório | Descrição |
|---|---|---|
origin | Sim | URL de origem com scheme e host (sem trailing slash). Ex: https://meuapp.com.br |
Validação:
- Deve incluir scheme (
http://ouhttps://) - Não pode ter trailing slash ou path
- Wildcards (
*) não são suportados - Máximo de 20 origins por tenant
Resposta (201 Created):
{
"data": {
"id": "ao_ghi789",
"origin": "https://meuapp.com.br",
"created_at": "2025-02-03T14:30:00Z"
}
}
Remover Allowed Origin
DELETE /v1/inbox-embed/allowed-origins/:id
Retorna 204 No Content.
Validação de Origin (como funciona)
Quando uma request chega com uma publishable key (pk_*), a API:
- Extrai o header
Originda request - Se developer mode está ativo e o origin é
localhostou127.0.0.1→ permite - Compara o origin com a lista de allowed origins do tenant
- Se não há match → retorna 403 Forbidden:
{
"error": {
"code": "origin_not_allowed",
"message": "Origin 'https://outro-site.com' is not in the allowed origins list"
}
}
Requests com secret keys (nk_*) não passam por validação de origin — elas são feitas server-side onde o header Origin não existe.
Admin — Domínios Bloqueados
Endpoints administrativos para gerenciar a blocklist de domínios de email descartáveis.
GET /v1/admin/blocked-domains → Listar domínios bloqueados
GET /v1/admin/blocked-domains/check → Verificar se email é bloqueado
POST /v1/admin/blocked-domains → Bloquear domínio
DELETE /v1/admin/blocked-domains/:domain → Desbloquear domínio
Check (GET):
curl "https://app.usenotifica.com.br/v1/admin/blocked-domains/[email protected]" \
-H "Authorization: Bearer YOUR_API_KEY"
Resposta:
{
"data": {"email": "[email protected]", "blocked": true}
}
Webhooks Inbound (Sem Autenticação)
WhatsApp (Meta)
GET /webhooks/whatsapp → Verificação do webhook (Meta challenge)
POST /webhooks/whatsapp → Receber eventos do WhatsApp
Verificados pela assinatura do Meta, não por API key.
Códigos de Erro
| Código HTTP | Significado |
|---|---|
400 | Bad Request — parâmetros inválidos |
401 | Unauthorized — API key ausente ou inválida |
403 | Forbidden — sem permissão para o recurso |
404 | Not Found — recurso não encontrado |
409 | Conflict — operação conflitante (ex: cancelar run já completado) |
422 | Unprocessable Entity — validação falhou |
429 | Too Many Requests — rate limit excedido |
500 | Internal Server Error |
Formato de erro padrão:
{
"error": {
"code": "validation_failed",
"message": "Descrição do erro",
"details": {
"field": ["mensagem de erro"]
}
}
}
Referências
- In-App Inbox — Guia completo do SDK React e inbox embed
- Workflows — Guia completo do motor de workflows
- Configuração de Domínio — Setup de domínio de envio
- DKIM — Autenticação de email customizada
- Templates de Email — Criação de templates
- Quickstart — Primeiros passos