Saltar al contenido principal
Documentación

Webhooks firmados

Recibe eventos en tiempo real en tu servidor, con validación HMAC SHA-256 contra falsificaciones.

Eventos disponibles

Recibe eventos en tiempo real en tu servidor, con validación HMAC SHA-256 contra falsificaciones.

CampoTipoDescripción
email.senteventEmail aceptado por el MTA y entregado al proveedor de destino.
email.deliveredeventEl proveedor de destino confirmó la entrega en la bandeja.
email.bouncedeventRebote permanente destinatario inexistente o política del proveedor.
email.complainedeventEl destinatario marcó el email como spam. Añade a supresión automáticamente.
email.openedeventEmail abierto por el destinatario (pixel tracking).
email.clickedeventEnlace clicado (tracking).
email.failedeventFallo definitivo tras reintentos.
email.suppressedeventEmail bloqueado por la lista de supresión.
email.delivery_delayedeventEntrega retrasada (greylisting / rate limit del destino).

1. Registra el endpoint

Proporciona una URL HTTPS válida y la lista de eventos que quieres recibir. Recomendamos encarecidamente registrar un secret.

curl
curl -X POST https://api.coffeemail.com.br/v1/product/webhooks \  -H "Authorization: Bearer $COFFEEMAIL_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "url": "https://sua-api.com.br/webhooks/coffeemail",    "events": ["email.delivered", "email.bounced", "email.complained"],    "secret": "whsec_meusegredocompartilhado"  }'

2. Valida la firma HMAC

Cada petición llega con el header X-CoffeeMail-Signature que contiene HMAC SHA-256 del cuerpo crudo. Usa coffeemail.webhooks.verifySignature() en tu handler.

handler.ts
import { Webhook } from '@coffeemail/node';import http from 'node:http'; const wh = new Webhook(process.env.COFFEEMAIL_WEBHOOK_SECRET!); http.createServer(async (req, res) => {  const signature = req.headers['x-coffeemail-signature'] as string;  const raw = await readBody(req);   try {    wh.verify(raw, signature);  } catch (err) {    res.statusCode = 401;    return res.end('Invalid signature');  }   const event = JSON.parse(raw.toString('utf-8'));  res.statusCode = 202;  res.end('OK');}).listen(3000);

3. Responde en < 5s

Responde 200 OK rápido. Si necesitas procesar de forma asíncrona, encola localmente y devuelve 202. Las cargas lentas disparan reintentos exponenciales.

4. Implementa idempotencia

Cada payload incluye un event id único. Persístelo en tu base para descartar duplicados. Usa upsert por id.

idempotency.ts
const event = JSON.parse(raw.toString('utf-8'));const eventId = event.id; await db.processedEvents.upsert({  where: { id: eventId },  create: {    id: eventId,    type: event.type,    payload: event,    receivedAt: new Date(),  },  update: {},});

5. Prueba el endpoint

Usa POST /v1/product/webhooks/:id/test para disparar un evento simulado. El endpoint recibe un payload ficticio con firma válida.

test-webhook.ts
const { data } = await coffeemail.webhooks.test('wh_123');console.log('Status recebido:', data.statusCode);
Utilice siempre tls: true en su manejador. Las direcciones HTTP simples (puerto 80) no son aceptadas — CoffeeMail requiere HTTPS válido con certificado de confianza.