SDK Python
🐍 Sync + async: SDK oficial com type hints completos, compatível com Django, Flask e FastAPI
O SDK Python permite integrar a Notifica em qualquer aplicação Python com suporte a sync e async. Este guia cobre:
- Instalação e setup
- Envio de notificações (email, SMS, WhatsApp, in-app, push)
- Gerenciamento de subscribers, templates e workflows
- Webhooks e analytics
- Tratamento de erros
Instalação
pip install notifica
Ou com poetry:
poetry add notifica
Requisitos: Python 3.8+ · Sem dependências obrigatórias (usa httpx opcionalmente para async)
Setup básico
Síncrono
from notifica import Notifica
client = Notifica("nk_live_sua_chave")
notification = client.notifications.send(
channel="email",
recipient="[email protected]",
template_id="welcome",
payload={"name": "Fernanda"},
)
print(f"Enviada: {notification.id} — {notification.status}")
Assíncrono (httpx)
from notifica import AsyncNotifica
client = AsyncNotifica("nk_live_sua_chave")
notification = await client.notifications.send(
channel="email",
recipient="[email protected]",
template_id="welcome",
payload={"name": "Fernanda"},
)
Autenticação
# Chave de produção
client = Notifica("nk_live_sua_chave")
# Chave de sandbox (desenvolvimento)
client = Notifica("nk_test_sua_chave")
Use variáveis de ambiente para não commitar chaves no código:
import os
client = Notifica(os.environ["NOTIFICA_API_KEY"])
Configuração avançada
client = Notifica(
"nk_live_...",
# URL customizada (self-hosted ou staging)
base_url="https://api.staging.notifica.com.br",
# Timeout em segundos
timeout=60,
# Retry com backoff exponencial
max_retries=5,
)
| Opção | Padrão | Descrição |
|---|---|---|
base_url | https://api.notifica.com.br | URL base da API |
timeout | 30 | Timeout em segundos |
max_retries | 3 | Tentativas com backoff exponencial |
Enviando notificações
Todas as notificações são assíncronas e retornam status accepted (202).
Email
n = client.notifications.send(
channel="email",
recipient="[email protected]",
template_id="order-confirmation",
payload={
"name": "Roberto",
"order_id": "ORD-12345",
},
)
WhatsApp
n = client.notifications.send(
channel="whatsapp",
recipient="+5511998765432",
template_id="welcome",
payload={
"customer_name": "João",
"company": "Acme",
},
)
SMS
n = client.notifications.send(
channel="sms",
recipient="+5511998765432",
payload={"content": "Seu código de verificação é: 583921"},
)
In-App
n = client.notifications.send(
channel="in_app",
recipient="subscriber-id-aqui",
payload={
"title": "Novo comentário",
"body": "Maria comentou na sua tarefa #123",
},
)
Com chave de idempotência
Para evitar duplicatas em retries:
n = client.notifications.send(
channel="email",
recipient="[email protected]",
template_id="payment-receipt",
payload={"amount": "R$ 99,90"},
idempotency_key="payment-12345", # Use ID do seu sistema
)
Tracking de entrega
Ver status de uma notificação
n = client.notifications.get("notification-id")
print(n.status) # "delivered"
print(n.delivered_at) # 2024-01-15T14:30:05Z
Listar tentativas de entrega
attempts = client.notifications.list_attempts("notification-id")
for a in attempts:
print(f"Tentativa {a.attempt_number}: {a.status} ({a.provider})")
Listar notificações com filtros
page = client.notifications.list(
status="failed",
channel="email",
limit=50,
)
for n in page.data:
print(n.id, n.status)
# Paginação via cursor
if page.meta.has_more:
next_page = client.notifications.list(cursor=page.meta.cursor)
Subscribers (Assinantes)
Criar ou atualizar (upsert)
sub = client.subscribers.create(
external_id="user-123",
email="[email protected]",
phone="+5511999999999",
name="Maria Silva",
custom_properties={
"plan": "pro",
"company": "Acme",
},
)
Se o external_id já existir, o subscriber é atualizado automaticamente.
Listar com busca
page = client.subscribers.list(search="maria", limit=20)
print(f"Encontrados: {page.total} subscribers")
Atualizar
sub = client.subscribers.update("subscriber-id", name="Maria Santos")
Deletar (LGPD)
Soft delete com nullificação de PII:
client.subscribers.delete("subscriber-id")
Preferências de notificação
# Consultar
prefs = client.subscribers.get_preferences("subscriber-id")
# Atualizar
prefs = client.subscribers.set_preferences("subscriber-id", preferences=[
{"category": "marketing", "channel": "email", "enabled": False},
{"category": "transacional", "channel": "email", "enabled": True},
])
Importação em massa
result = client.subscribers.bulk_import(subscribers=[
{"external_id": "user-1", "email": "[email protected]", "name": "Ana"},
{"external_id": "user-2", "email": "[email protected]", "name": "Bruno"},
])
print(f"Importados: {result.imported} subscribers")
Templates
Criar template
tmpl = client.templates.create(
channel="email",
slug="welcome",
name="Email de Boas-vindas",
content="Olá {{name}}, bem-vindo ao {{company}}!",
status="published",
)
Listar por canal
templates = client.templates.list(channel="email", status="published")
Preview com dados de exemplo
result = client.templates.preview("template-id", variables={
"name": "Maria",
"company": "Acme",
})
print(result.output) # "Olá Maria, bem-vindo ao Acme!"
Validar template
result = client.templates.validate("template-id")
if not result.valid:
print("Erros:", result.errors)
Workflows
Criar workflow
wf = client.workflows.create(
slug="onboarding",
name="Onboarding do Usuário",
steps=[
{"type": "send", "channel": "email", "template": "welcome"},
{"type": "delay", "duration": "24h"},
{"type": "send", "channel": "email", "template": "getting-started"},
{"type": "delay", "duration": "72h"},
{"type": "send", "channel": "whatsapp", "template": "check-in"},
],
)
Disparar workflow
run = client.workflows.trigger("onboarding",
recipient="user-123",
data={"name": "João", "plan": "pro"},
)
print(f"Workflow run: {run.id} — {run.status}")
Cancelar workflow em execução
run = client.workflows.cancel_run("run-id")
Webhooks
Criar webhook
O signing secret só é retornado na criação — guarde-o!
wh = client.webhooks.create(
url="https://api.empresa.com/webhooks/notifica",
events=["notification.sent", "notification.delivered", "notification.failed"],
)
print(f"Secret (guarde!): {wh.secret}")
Listar deliveries
page = client.webhooks.list_deliveries("webhook-id", limit=50)
for d in page.data:
print(f"Evento: {d.event_type}, Status HTTP: {d.response_status}")
Domínios de envio
# Registrar
domain = client.domains.create(domain="mail.empresa.com.br")
# Verificar DNS
domain = client.domains.verify(domain.id)
if domain.status == "verified":
print("Domínio verificado!")
# Health check
health = client.domains.check_health(domain.id)
print(f"SPF: {health.spf.status}, DKIM: {health.dkim.status}")
Analytics
# Resumo dos últimos 7 dias
overview = client.analytics.overview("7d")
print(f"Enviados: {overview.sent}, Entregues: {overview.delivered}")
# Por canal
stats = client.analytics.by_channel("30d")
for s in stats:
print(f"{s.channel}: {s.sent} enviados")
# Timeseries
points = client.analytics.timeseries(period="7d", granularity="day")
# Top templates
top = client.analytics.top_templates(period="30d", limit=5)
Notificações In-App
# Listar não-lidas
notifications = client.in_app.list("subscriber-id", unread_only=True, limit=20)
# Contagem
count = client.in_app.get_unread_count("subscriber-id")
print(f"{count} notificações não lidas")
# Marcar como lida
client.in_app.mark_read("subscriber-id", "notification-id")
# Marcar todas como lidas
client.in_app.mark_all_read("subscriber-id")
Audit Logs (Admin Only)
Audit logs requerem autenticação admin (Bearer token do backoffice). Não estão disponíveis com API keys regulares (nk_live_... ou nk_test_...).
Rastreie ações sensíveis na sua organização:
- API Keys: created, rotated, revoked
- Team Members: invited, removed, role_changed
- Subscriptions: created, plan_changed, cancelled, payment_failed
- Domains: added, verified, removed
- Webhooks: created, updated, deleted
# Listar logs recentes
result = client.audit.list({"limit": 50})
for log in result["data"]:
print(f"{log['action']} por {log['actor']['name']} em {log['created_at']}")
# Filtrar por tipo de ação
api_key_logs = client.audit.list({
"action": "api_key.created",
"limit": 20,
})
# Filtrar por tipo de recurso
webhook_logs = client.audit.list({
"resource_type": "webhook",
})
# Filtrar por período
logs = client.audit.list({
"start_date": "2024-01-01T00:00:00Z",
"end_date": "2024-01-31T23:59:59Z",
})
# Obter um audit log específico
log = client.audit.get("audit_abc123")
# Auto-paginar por todos os logs
for log in client.audit.list_auto({"resource_type": "api_key"}):
print(log["action"], log["resource_id"])
Filtros disponíveis
| Parâmetro | Tipo | Descrição |
|---|---|---|
action | string | Filtrar por ação (ex: api_key.created) |
resource_type | string | Filtrar por tipo de recurso (api_key, webhook, etc.) |
resource_id | string | Filtrar por ID do recurso |
actor_type | string | Filtrar por tipo de ator (user, api_key, system) |
actor_id | string | Filtrar por ID do ator |
start_date | string | Data inicial (ISO 8601) |
end_date | string | Data final (ISO 8601) |
Tratamento de erros
from notifica import Notifica, NotificaError, ValidationError, RateLimitError
try:
client.notifications.send(...)
except ValidationError as e:
# 422: Dados inválidos
print(f"Campos inválidos: {e.details}")
except RateLimitError as e:
# 429: Limite excedido
print("Rate limited, tente novamente")
except NotificaError as e:
# Qualquer erro da API
print(f"HTTP {e.status_code} | {e.code}: {e.message}")
O SDK faz retry automático com backoff exponencial para erros 429 e 5xx. Configure max_retries=0 para desabilitar.
Integração com frameworks
FastAPI
from fastapi import FastAPI
from notifica import AsyncNotifica
app = FastAPI()
client = AsyncNotifica(os.environ["NOTIFICA_API_KEY"])
@app.post("/send-welcome")
async def send_welcome(email: str, name: str):
n = await client.notifications.send(
channel="email",
recipient=email,
template_id="welcome",
payload={"name": name},
)
return {"notification_id": n.id, "status": n.status}
Django
# settings.py
NOTIFICA_API_KEY = os.environ["NOTIFICA_API_KEY"]
# views.py
from notifica import Notifica
from django.conf import settings
client = Notifica(settings.NOTIFICA_API_KEY)
def send_welcome(request):
n = client.notifications.send(
channel="email",
recipient=request.POST["email"],
template_id="welcome",
payload={"name": request.POST["name"]},
)
return JsonResponse({"notification_id": n.id})
Flask
from flask import Flask, request, jsonify
from notifica import Notifica
app = Flask(__name__)
client = Notifica(os.environ["NOTIFICA_API_KEY"])
@app.post("/send-welcome")
def send_welcome():
data = request.json
n = client.notifications.send(
channel="email",
recipient=data["email"],
template_id="welcome",
payload={"name": data["name"]},
)
return jsonify(notification_id=n.id, status=n.status)
FAQ
Q: Preciso do httpx para o modo síncrono?
A: Não. O modo síncrono usa urllib3 ou requests (se disponível). O httpx é necessário apenas para AsyncNotifica.
Q: Como funciona o retry automático? A: O SDK retenta automaticamente em erros 429 (rate limit) e 5xx (servidor) com backoff exponencial: 1s, 2s, 4s...
Q: Os type hints são completos? A: Sim. O SDK é totalmente tipado e compatível com mypy em modo strict.
Q: Qual a versão mínima do Python? A: Python 3.8+. Recomendamos 3.10+ para melhor suporte a type hints.
Links
- PyPI: pypi.org/project/notifica
- GitHub: github.com/notifica-tech/notifica-python
- API Reference: API Reference
- Templates: Email Templates
- Webhooks: Webhooks