Integre pelo SDK oficial no servidor
O @mandai/sdk é tipado, não possui dependências de runtime e mantém as decisões críticas explícitas: ambiente, idempotência e verificação de webhooks.
Instalação
Use o SDK somente em um ambiente confiável no servidor. Nunca entregue uma chave Mandaí ao navegador, aplicativo distribuído ou repositório.
npm install @mandai/sdkEnvie a primeira mensagem
O cliente escolhe automaticamente a origem correta para Sandbox ou Produção. A criação não é repetida automaticamente: se o resultado de rede for ambíguo, reutilize a mesma Idempotency-Key.
import { MandaiClient, createIdempotencyKey } from '@mandai/sdk';
const mandai = new MandaiClient({
apiKey: process.env.MANDAI_API_KEY!,
environment: 'sandbox',
});
const { data: message } = await mandai.messages.create(
{
to: '+5511000000001',
body: 'Mandai sandbox ready',
metadata: { order_id: 'BR-1842' },
},
{ idempotencyKey: createIdempotencyKey('order-BR-1842') },
);
console.log(message.message_id);Superfícies disponíveis
Crie públicos e adicione destinatários
Pela API, use POST /v1/groups e POST /v1/groups/{group_id}/members. A chave precisa das capacidades groups:read e groups:write.
const { data: group } = await mandai.groups.create({
name: 'Clientes ativos',
purpose: 'Alertas operacionais',
});
await mandai.groups.addMembers(group.group_id, [
{ to: '+5511000000001', variables: { nome: 'Ana' } },
]);Publique modelos versionados
Pela API, use POST /v1/templates para criar e POST /v1/templates/{template_id}/versions para publicar outra versão. Agendas existentes preservam a versão fixada na criação.
const { data: template } = await mandai.templates.create({
name: 'Alerta de incidente',
body: 'Ola {{nome}}, identificamos uma indisponibilidade.',
});
await mandai.templates.publishVersion(
template.template_id,
'Ola {{nome}}, o servico voltou ao normal.',
);Agende um envio
Pela API, use POST /v1/schedules com Idempotency-Key. O público, sua revisão e a versão do modelo são fixados quando a agenda é criada.
// Capture uma vez por intencao e preserve em qualquer retry.
const scheduledFor = new Date(Date.now() + 60 * 60_000).toISOString();
const scheduleKey = createIdempotencyKey('maintenance');
const { data: schedule } = await mandai.schedules.create(
{
name: 'Aviso de manutencao',
group_id: group.group_id,
template_id: template.template_id,
scheduled_for: scheduledFor,
},
{ idempotencyKey: scheduleKey },
);
console.log(schedule.schedule_id);Valide webhooks com o mesmo pacote
Leia o corpo bruto uma única vez e passe os headers recebidos ao helper. A tolerância padrão de timestamp é de cinco minutos.
import { verifyWebhookSignature } from '@mandai/sdk';
const rawBody = await request.text();
const valid = await verifyWebhookSignature({
secret: process.env.MANDAI_WEBHOOK_SECRET!,
timestamp: request.headers.get('mandai-timestamp') ?? '',
signature: request.headers.get('mandai-signature') ?? '',
rawBody,
});
if (!valid) return new Response('Invalid signature', { status: 401 });