Pular para o conteúdo principal

SDK Java

Java 11+ nativo: SDK oficial com HttpClient, CompletableFuture e zero dependências externas

O SDK Java permite integrar a Notifica em qualquer aplicação Java com suporte a sync e async. Este guia cobre:

  • Instalação (Gradle & Maven)
  • Envio de notificações (email, SMS, WhatsApp, in-app, push)
  • Gerenciamento de subscribers, templates e workflows
  • Webhooks e analytics
  • Tratamento de erros

Instalação

Gradle

implementation 'com.notifica:notifica-java:1.0.0'

Gradle (Kotlin DSL)

implementation("com.notifica:notifica-java:1.0.0")

Maven

<dependency>
<groupId>com.notifica</groupId>
<artifactId>notifica-java</artifactId>
<version>1.0.0</version>
</dependency>

Requisitos: Java 11+ · Zero dependências externas (usa java.net.http.HttpClient)


Setup básico

Síncrono

import com.notifica.Notifica;
import com.notifica.models.*;

var notifica = new Notifica("nk_live_sua_chave");

var notification = notifica.notifications().send(new SendNotificationParams()
.channel("email")
.recipient("[email protected]")
.templateId("welcome")
.payload(Map.of("name", "Fernanda"))
);

System.out.println("Enviada: " + notification.id() + " — " + notification.status());

Assíncrono (CompletableFuture)

notifica.notifications().sendAsync(new SendNotificationParams()
.channel("email")
.recipient("[email protected]")
.templateId("welcome")
.payload(Map.of("name", "Fernanda"))
).thenAccept(n -> {
System.out.println("Enviada: " + n.id());
}).exceptionally(err -> {
System.err.println("Erro: " + err.getMessage());
return null;
});

Autenticação

// Chave de produção
var notifica = new Notifica("nk_live_sua_chave");

// Chave de sandbox (desenvolvimento)
var notifica = new Notifica("nk_test_sua_chave");
dica

Use variáveis de ambiente para não commitar chaves no código:

var notifica = new Notifica(System.getenv("NOTIFICA_API_KEY"));

Configuração avançada

var notifica = Notifica.builder("nk_live_...")
// URL customizada (self-hosted ou staging)
.baseUrl("https://api.staging.notifica.com.br")
// Timeout
.timeout(Duration.ofSeconds(60))
// Retry com backoff exponencial
.maxRetries(5)
// HTTP client customizado
.httpClient(HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build())
.build();
OpçãoPadrãoDescrição
baseUrlhttps://api.notifica.com.brURL base da API
timeout30sTimeout de requisições
maxRetries3Tentativas com backoff exponencial
httpClientHttpClient.newHttpClient()HTTP client customizado

Enviando notificações

Todas as notificações são assíncronas e retornam status accepted (202).

Email

var n = notifica.notifications().send(new SendNotificationParams()
.channel("email")
.recipient("[email protected]")
.templateId("order-confirmation")
.payload(Map.of(
"name", "Roberto",
"orderId", "ORD-12345"
))
);

WhatsApp

var n = notifica.notifications().send(new SendNotificationParams()
.channel("whatsapp")
.recipient("+5511998765432")
.templateId("welcome")
.payload(Map.of(
"customerName", "João",
"company", "Acme"
))
);

SMS

var n = notifica.notifications().send(new SendNotificationParams()
.channel("sms")
.recipient("+5511998765432")
.payload(Map.of("content", "Seu código é: 583921"))
);

In-App

var n = notifica.notifications().send(new SendNotificationParams()
.channel("in_app")
.recipient("subscriber-id-aqui")
.payload(Map.of(
"title", "Novo comentário",
"body", "Maria comentou na sua tarefa #123"
))
);

Com chave de idempotência

var n = notifica.notifications().send(new SendNotificationParams()
.channel("email")
.recipient("[email protected]")
.templateId("payment-receipt")
.payload(Map.of("amount", "R$ 99,90"))
.idempotencyKey("payment-12345")
);

Tracking de entrega

Ver status de uma notificação

var n = notifica.notifications().get("notification-id");
System.out.println(n.status()); // "delivered"
System.out.println(n.deliveredAt()); // 2024-01-15T14:30:05Z

Listar tentativas de entrega

var attempts = notifica.notifications().listAttempts("notification-id");
for (var a : attempts) {
System.out.printf("Tentativa %d: %s (%s)%n", a.attemptNumber(), a.status(), a.provider());
}

Listar notificações com filtros

var page = notifica.notifications().list(new ListNotificationsParams()
.status("failed")
.channel("email")
.limit(50)
);

for (var n : page.data()) {
System.out.println(n.id() + " " + n.status());
}

// Paginação via cursor
if (page.meta().hasMore()) {
var nextPage = notifica.notifications().list(new ListNotificationsParams()
.cursor(page.meta().cursor())
);
}

Subscribers (Assinantes)

Criar ou atualizar (upsert)

var sub = notifica.subscribers().create(new CreateSubscriberParams()
.externalId("user-123")
.email("[email protected]")
.phone("+5511999999999")
.name("Maria Silva")
.customProperties(Map.of("plan", "pro", "company", "Acme"))
);

Listar com busca

var page = notifica.subscribers().list(new ListSubscribersParams()
.search("maria")
.limit(20)
);
System.out.printf("Encontrados: %d subscribers%n", page.total());

Atualizar

var sub = notifica.subscribers().update("subscriber-id",
new UpdateSubscriberParams().name("Maria Santos")
);

Deletar (LGPD)

notifica.subscribers().delete("subscriber-id");

Preferências de notificação

// Consultar
var prefs = notifica.subscribers().getPreferences("subscriber-id");

// Atualizar
notifica.subscribers().setPreferences("subscriber-id", List.of(
new PreferenceInput("marketing", "email", false),
new PreferenceInput("transacional", "email", true)
));

Importação em massa

var result = notifica.subscribers().bulkImport(List.of(
new CreateSubscriberParams().externalId("user-1").email("[email protected]").name("Ana"),
new CreateSubscriberParams().externalId("user-2").email("[email protected]").name("Bruno")
));
System.out.printf("Importados: %d subscribers%n", result.imported());

Templates

Criar template

var tmpl = notifica.templates().create(new CreateTemplateParams()
.channel("email")
.slug("welcome")
.name("Email de Boas-vindas")
.content("Olá {{name}}, bem-vindo ao {{company}}!")
.status("published")
);

Preview com dados de exemplo

var result = notifica.templates().preview("template-id",
Map.of("name", "Maria", "company", "Acme")
);
System.out.println(result.output()); // "Olá Maria, bem-vindo ao Acme!"

Validar template

var result = notifica.templates().validate("template-id");
if (!result.valid()) {
System.out.println("Erros: " + result.errors());
}

Workflows

Criar e disparar workflow

// Criar
var wf = notifica.workflows().create(new CreateWorkflowParams()
.slug("onboarding")
.name("Onboarding do Usuário")
.steps(List.of(
Map.of("type", "send", "channel", "email", "template", "welcome"),
Map.of("type", "delay", "duration", "24h"),
Map.of("type", "send", "channel", "email", "template", "getting-started")
))
);

// Disparar
var run = notifica.workflows().trigger("onboarding", new TriggerWorkflowParams()
.recipient("user-123")
.data(Map.of("name", "João", "plan", "pro"))
);
System.out.println("Run: " + run.id() + " — " + run.status());

// Cancelar
notifica.workflows().cancelRun("run-id");

Webhooks

Criar webhook

var wh = notifica.webhooks().create(new CreateWebhookParams()
.url("https://api.empresa.com/webhooks/notifica")
.events(List.of("notification.sent", "notification.delivered", "notification.failed"))
);
System.out.println("Secret (guarde!): " + wh.secret());

Listar deliveries

var page = notifica.webhooks().listDeliveries("webhook-id", 50);
for (var d : page.data()) {
System.out.printf("Evento: %s, HTTP: %d%n", d.eventType(), d.responseStatus());
}

Domínios de envio

// Registrar
var domain = notifica.domains().create("mail.empresa.com.br");

// Verificar
domain = notifica.domains().verify(domain.id());

// Health check
var health = notifica.domains().checkHealth(domain.id());
System.out.printf("SPF: %s, DKIM: %s, DMARC: %s%n",
health.spf().status(), health.dkim().status(), health.dmarc().status());

Analytics

// Resumo
var overview = notifica.analytics().overview("7d");
System.out.printf("Enviados: %d, Entregues: %d, Falhas: %d%n",
overview.sent(), overview.delivered(), overview.failed());

// Por canal
var stats = notifica.analytics().byChannel("30d");
for (var s : stats) {
System.out.printf("%s: %d enviados%n", s.channel(), s.sent());
}

// Top templates
var top = notifica.analytics().topTemplates("30d", 5);

Audit Logs (Admin Only)

Autenticação Admin Necessária

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
import com.notifica.sdk.models.AuditLog;
import com.notifica.sdk.models.ListAuditLogsParams;
import com.notifica.sdk.models.common.PaginatedResponse;

// Listar logs recentes
PaginatedResponse<AuditLog> result = notifica.audit().list(
new ListAuditLogsParams().setLimit(50)
);
for (AuditLog log : result.getData()) {
System.out.printf("%s by %s at %s%n",
log.getAction(), log.getActor().getName(), log.getCreatedAt());
}

// Filtrar por tipo de ação
var apiKeyLogs = notifica.audit().list(
new ListAuditLogsParams()
.setAction("api_key.created")
.setLimit(20)
);

// Filtrar por tipo de recurso
var webhookLogs = notifica.audit().list(
new ListAuditLogsParams()
.setResourceType("webhook")
);

// Filtrar por período
var logs = notifica.audit().list(
new ListAuditLogsParams()
.setStartDate("2024-01-01T00:00:00Z")
.setEndDate("2024-01-31T23:59:59Z")
);

// Obter um audit log específico
AuditLog log = notifica.audit().get("audit_abc123");

// Async
notifica.audit().listAsync(new ListAuditLogsParams().setLimit(50))
.thenAccept(page -> {
for (AuditLog l : page.getData()) {
System.out.println(l.getAction());
}
});

Filtros disponíveis

ParâmetroTipoDescrição
actionStringFiltrar por ação (ex: api_key.created)
resourceTypeStringFiltrar por tipo de recurso (api_key, webhook, etc.)
resourceIdStringFiltrar por ID do recurso
actorTypeStringFiltrar por tipo de ator (user, api_key, system)
actorIdStringFiltrar por ID do ator
startDateStringData inicial (ISO 8601)
endDateStringData final (ISO 8601)

Tratamento de erros

import com.notifica.exceptions.*;

try {
notifica.notifications().send(params);
} catch (ValidationException e) {
// 422: Dados inválidos
System.out.println("Campos inválidos: " + e.details());
} catch (RateLimitException e) {
// 429: Limite excedido
System.out.println("Rate limited");
} catch (NotFoundException e) {
// 404: Recurso não encontrado
} catch (NotificaException e) {
// Qualquer erro da API
System.out.printf("HTTP %d | %s: %s%n", e.statusCode(), e.code(), e.message());
}
informação

O SDK faz retry automático com backoff exponencial para erros 429 e 5xx. Configure maxRetries(0) para desabilitar.


Integração com Spring Boot

@Configuration
public class NotificaConfig {
@Bean
public Notifica notificaClient(@Value("${notifica.api-key}") String apiKey) {
return new Notifica(apiKey);
}
}

@RestController
public class NotificationController {
@Autowired
private Notifica notifica;

@PostMapping("/send-welcome")
public ResponseEntity<?> sendWelcome(@RequestBody WelcomeRequest req) {
var n = notifica.notifications().send(new SendNotificationParams()
.channel("email")
.recipient(req.email())
.templateId("welcome")
.payload(Map.of("name", req.name()))
);
return ResponseEntity.ok(Map.of(
"notificationId", n.id(),
"status", n.status()
));
}
}
# application.yml
notifica:
api-key: ${NOTIFICA_API_KEY}

FAQ

Q: Qual a versão mínima do Java? A: Java 11+. O SDK usa java.net.http.HttpClient nativo.

Q: Preciso de alguma dependência externa? A: Não. Zero dependências. O SDK usa apenas a stdlib do Java.

Q: Como funciona o async? A: Todos os métodos possuem uma variante *Async() que retorna CompletableFuture<T>.

Q: Funciona com Kotlin? A: Sim. API fluida funciona naturalmente em Kotlin.

Q: O SDK é thread-safe? A: Sim. A instância de Notifica pode ser compartilhada entre threads.