Pular para o conteúdo principal

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

PrefixoTipoUso
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/notifications
  • POST /v1/channels
  • POST /v1/templates
  • POST /v1/workflows
  • POST /v1/workflows/:slug/trigger
  • POST /v1/subscribers
  • POST /v1/webhooks
  • POST /v1/api-keys
  • POST /v1/domains

Autenticação por Tipo de Key

Dependendo do tipo de API key, o comportamento da API muda:

TipoAcessoValidação extra
Secret (nk_*)Todos os endpointsNenhuma
Public (pk_*)Somente subscriber-scoped (in-app)Header Origin validado contra allowed origins
Dashboard (sessão)Todos os endpointsCookie 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

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"
}
}
CampoObrigatórioDescrição
channelSimCanal: email, whatsapp, sms, in_app, push
to / recipientSimEndereço destino (email, telefone E.164, etc.)
template / template_idNãoSlug do template para renderizar
data / payloadNãoVariáveis para o template ou conteúdo raw
metadataNãoMetadados 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âmetroTipoDescrição
limitintMáximo por página (default: 20, max: 100)
cursorstringCursor de paginação
statusstringFiltrar por status
channelstringFiltrar 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"
}
CampoObrigatórioDescrição
channelSimCanal alvo
slugSimIdentificador URL-safe
nameSimNome legível
contentSimConteúdo com {{variáveis}}
variablesNãoLista de variáveis (auto-extraída se omitida)
variantsNãoVariantes por canal (subject, html_body, etc.)
languageNãoIdioma (default: pt_BR)
statusNãodraft ou active (default: draft)
metadataNãoMetadados extras
provider_template_idNãoReferê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âmetroTipoDescrição
channelstringFiltrar por canal
statusstringFiltrar 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"
}
}
CampoObrigatórioDescrição
external_idSimSeu identificador do usuário (upsert key)
emailNãoEmail do subscriber
phoneNãoTelefone E.164 (ex: +5511999998888)
nameNãoNome de exibição
localeNãoLocale preferido
timezoneNãoTimezone preferida
custom_propertiesNãoDados customizados (key-value)
informação

LGPD: O Notifica registra automaticamente consentimento (timestamp, IP, método) em toda criação de subscriber via API.

Listar Subscribers

GET /v1/subscribers
ParâmetroTipoDescrição
limitintMáximo por página (default: 20, max: 100)
offsetintOffset de paginação
searchstringBusca 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)
aviso

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âmetroTipoDescrição
limitintMáximo por página
offsetintOffset
unread_onlyboolApenas 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"
}
}
informação

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..."
}
}
aviso

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âmetroTipoDescrição
limitintMáximo de resultados (default: 20, max: 100)

Analytics — Métricas e Dashboards

Overview

GET /v1/analytics/overview
ParâmetroTipoDescrição
periodstring1h, 24h, 7d, 30d (default: 24h)

Por Canal

GET /v1/analytics/channels
ParâmetroTipoDescrição
periodstring1h, 24h, 7d, 30d (default: 24h)

Time Series

GET /v1/analytics/timeseries
ParâmetroTipoDescrição
periodstring24h, 7d, 30d (default: 24h)
granularitystringhour ou day (auto-detectado se omitido)

Top Templates

GET /v1/analytics/templates
ParâmetroTipoDescrição
periodstring1h, 24h, 7d, 30d (default: 24h)
limitintMá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..."
}
}
aviso

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.

informação

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
}
CampoTipoDescrição
developer_modeboolQuando true, aceita automaticamente requests de localhost e 127.0.0.1 em qualquer porta
aviso

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"
}
CampoObrigatórioDescrição
originSimURL de origem com scheme e host (sem trailing slash). Ex: https://meuapp.com.br

Validação:

  • Deve incluir scheme (http:// ou https://)
  • 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:

  1. Extrai o header Origin da request
  2. Se developer mode está ativo e o origin é localhost ou 127.0.0.1permite
  3. Compara o origin com a lista de allowed origins do tenant
  4. 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"
}
}
informação

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 HTTPSignificado
400Bad Request — parâmetros inválidos
401Unauthorized — API key ausente ou inválida
403Forbidden — sem permissão para o recurso
404Not Found — recurso não encontrado
409Conflict — operação conflitante (ex: cancelar run já completado)
422Unprocessable Entity — validação falhou
429Too Many Requests — rate limit excedido
500Internal Server Error

Formato de erro padrão:

{
"error": {
"code": "validation_failed",
"message": "Descrição do erro",
"details": {
"field": ["mensagem de erro"]
}
}
}

Referências