Email API · REST + GraphQL · SDKs típados · Webhooks HMAC · Idempotency Stripe-style

Una API que respeta tu tiempo de developer.

REST para acciones puntuales, GraphQL para queries complejas, SDKs nativos típados en TypeScript, Python, Go, PHP y Ruby. Idempotency keys siguiendo la convención que Stripe popularizó para retries seguros sin duplicar envíos. Webhooks firmados con HMAC SHA-256 con verificación built-in en cada SDK. No escribes el código de validación de signatures. Documentación con ejemplos copy-paste para los casos comunes (envío simple, templates, attachments, batch hasta 1,000 destinatarios, manejo de eventos). Production-grade desde día uno. Misma infraestructura subyacente que Email Transaccional + SMTP Relay, mismo pool dedicado separado del marketing, mismo P95 156ms medido sobre los últimos 90 días en producción real. La diferencia es la interface: si tu app habla HTTP/JSON, esta es tu página. Si tu app habla SMTP estándar, mira Email Transaccional + SMTP Relay. Setup técnico de desarrollo $290 one-time con endpoint aislado y onboarding 60 minutos, producción desde $99 mensuales.

Setup desarrollo$290
Producción desde$99/mes
SDKs5típados
P95156ms
REST vs GraphQL · cuándo usar cuál

Dos interfaces. Una infraestructura. Tu elección.

El debate REST vs GraphQL no es ganador-pierde, es contexto-dependiente. La mayoría de equipos termina usando ambas: REST para sending (acciones puntuales con resource-action mapping natural) y GraphQL para reporting (queries flexibles que combinan métricas en una request). Algunos prefieren solo REST. Otros solo GraphQL. Ambas posiciones son válidas. EMP soporta las dos para que decidas según tu stack y patrones existentes, sin obligarte a una arquitectura que no te calza. Este es el desglose honesto de cuándo cada una rinde mejor.

CASO 1 · ACCIONES TRANSACCIONALES

REST para sending

Enviar email, crear template, suspender suscriptor, marcar bounce como soft. Acciones puntuales con resource-action clarísima: POST /v1/emails para enviar, GET /v1/emails/{id} para consultar estado, DELETE /v1/templates/{id} para eliminar. Predecible, fácil de cachear cuando aplica, soporta CDNs como CloudFront, ecosistema enorme de tooling (Postman, curl, httpie, los SDKs de cualquier lenguaje). Si tu equipo viene de APIs HTTP tradicionales, REST es match natural sin curva de aprendizaje.

→ Cuando: sending puntual, retries simples, integración rápida
CASO 2 · QUERIES Y REPORTING

GraphQL para fetching

Dashboards que necesitan métricas combinadas: envíos del último día más bounces por dominio más tasa de apertura por template más eventos del último webhook recibido. Con REST tradicional son cuatro requests separadas. Con GraphQL pides exactamente los campos que necesitas en una sola query. Reduce overfetching (no traes campos que no usas) y elimina N+1 problems (no haces un request por entidad relacionada). También facilita versionado evolutivo porque agregas campos sin romper clientes existentes que no los consultan.

→ Cuando: dashboards, analytics, métricas combinadas
CASO 3 · EVENTOS TIEMPO REAL

GraphQL Subscriptions

WebSocket subscriptions para eventos en tiempo real sin polling. Plan Empresa. Subscribes a un filtro (subscription EmailEvents { emailEvent(filter: {status: BOUNCED}) }) y recibes bounces conforme suceden. Útil para dashboards en vivo, alertas instantáneas, sistemas de monitoring custom que necesitan stream continuo. Conexión persistente con auto-reconnect, heartbeats cada 30 segundos. Para notificaciones puntuales sin mantener conexión persistente, los webhooks HMAC tradicionales son más eficientes y escalan mejor.

→ Cuando: monitoring tiempo real, alerting instantáneo
REST+ GraphQL ambas disponibles
REST en /v1/emails, /v1/templates, /v1/contacts. GraphQL en /graphql con introspection habilitada en dev
5SDKs oficiales típados
TypeScript, Python, Go, PHP, Ruby · open source MIT en GitHub · type hints completos en cada uno
156ms P95 medido producción
Misma infraestructura que Email Transaccional + SMTP Relay · medido continuo sobre clientes activos
HMACSHA-256 webhooks built-in
Verificación de signatures en cada SDK · no escribes código de validación · headers documentados
API Playground · simulación request/response sin enviar emails reales

Probá la API antes de instalar el SDK en tu IDE.

Selector interactivo de método HTTP, endpoint y body de request. Genera la response simulada con headers correctos, status code apropiado y tiempo de respuesta indicativo. Útil para entender la forma de la API antes de comprometer tiempo de integración. Los datos son demostrativos pero la estructura es exactamente la que recibes en producción.

Interface
Operación
Request POST · /v1/emails
curl -X POST https://api.emp.pa/v1/emails \
  -H "Authorization: Bearer emp_live_xxx" \
  -H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "[email protected]",
    "to": ["[email protected]"],
    "subject": "Tu OTP es 482937",
    "text": "Tu código expira en 5 minutos.",
    "tags": ["otp", "auth"]
  }'
Response 202 · 156ms
{
  "id": "em_2gWpQjK4xMnRz8VLb3oXdY",
  "status": "queued",
  "from": "[email protected]",
  "to": ["[email protected]"],
  "subject": "Tu OTP es 482937",
  "created_at": "2026-05-09T03:42:18.527Z",
  "tags": ["otp", "auth"],
  "tracking": {
    "opens": true,
    "clicks": true
  },
  "_links": {
    "self": "/v1/emails/em_2gWpQjK4xMnRz8VLb3oXdY",
    "events": "/v1/emails/em_2gWpQjK4xMnRz8VLb3oXdY/events"
  }
}
Notas técnicas: Status 202 (Accepted) indica que el email fue encolado para envío, no que ya llegó al destinatario. Los SDKs convierten esto en una promise resuelta. Header Idempotency-Key garantiza que retries con la misma key retornen la respuesta cacheada (24h) sin duplicar envío. Para tracking del lifecycle completo (delivered, opened, clicked, bounced, complained) configuras webhook endpoint o consultas vía /v1/emails/{id}/events o GraphQL subscription.

Datos del playground son demostrativos. Estructura, headers y status codes son exactamente los de producción. Documentación completa con todos los endpoints, parámetros opcionales, error codes y rate limit headers en /docs cuando se provisiona el entorno de desarrollo. Provisionar entorno trae sesión 60 minutos con engineering para revisar tu integración específica.

SDKs nativos · type hints completos · open source MIT

Cinco SDKs mantenidos por engineering EMP.

Cada SDK trae verificación HMAC built-in para webhooks (no escribes el código de validación de signatures), retry logic con exponential backoff configurable, idempotency keys auto-generadas si no las pasas, y circuit breaker pattern para degradación elegante cuando hay incidentes upstream. Battle-tested en producción de 22 SaaS regionales activos. Cubre los edge cases que aprendimos a las malas. Source code abierto en GitHub bajo licencia MIT. Auditable, forkeable, contribuíble. Versionado semver estricto, breaking changes solo en major bumps con migration guide documentada.

TypeScript / Node

v3.4.2
npm install @emp/sdk
  • Tipos completos REST + GraphQL
  • Autocomplete VS Code y Cursor
  • Validación compile-time
  • React Email integration opcional
  • Bundler-friendly (ESM + CJS)

Python

v2.8.0
pip install emp-sdk
  • Type hints PEP 484 completos
  • mypy strict mode compatible
  • async/await con httpx
  • Compatible 3.9+
  • Pydantic models para responses

Go

v1.6.1
go get github.com/emp-pa/sdk-go
  • Structs generadas, sin reflection
  • context.Context propagation
  • Cero dependencias externas
  • Compatible Go 1.21+
  • Fuzz tests en CI

PHP

v2.3.0
composer require emp/sdk
  • PHP 8.1+ con enums y readonly
  • PSR-18 HTTP client compatible
  • Laravel + Symfony bridges
  • PHPStan level 9
  • Compatible PHP 8.4

Ruby

v1.9.3
gem install emp-sdk
  • dry-types validation
  • Rails ActiveJob integration
  • Sorbet sigs incluidas
  • Compatible Ruby 3.0+
  • Faraday HTTP por debajo

¿Otro lenguaje?

REST + GraphQL
curl + cualquier cliente HTTP
  • Rust, Java, .NET, Elixir, etc.
  • OpenAPI 3.1 spec descargable
  • GraphQL schema introspectable
  • Generadores OpenAPI funcionan
  • Templates community en GitHub
Webhooks + Idempotency · primitives críticas para production

Las dos cosas que separan production de demo.

Una API que solo envía emails no sirve para production. Necesitas dos primitives operacionales adicionales para no estar despierto a las 3 AM debugueando duplicados o eventos perdidos. Webhooks firmados con HMAC para que tu app reciba notificaciones de delivery, bounce, complaint, open y click sin polling. Idempotency keys siguiendo el patrón Stripe para que retries (timeouts, errores de red, queue retries) no produzcan envíos duplicados. EMP implementa ambas primitives correctamente desde día uno. Verificación HMAC built-in en cada SDK. Caching idempotente de respuestas por 24 horas.

PRIMITIVE 1 · WEBHOOKS HMAC

Eventos firmados sin polling

Cada evento (queued, sent, delivered, opened, clicked, bounced, complained) genera POST a tu webhook URL configurado. Body JSON con el evento, header X-EMP-Signature con HMAC-SHA256 del body usando tu webhook secret. Los SDKs traen función verify(body, signature) que valida la signature en una línea. Sin verificación, cualquiera puede simular eventos hacia tu endpoint. Tu handler debería responder 200 al recibir el evento, EMP reintentará con exponential backoff si recibe 5xx o no responde en 10 segundos. Idempotente del lado tuyo (mismo evento puede llegar 2 veces si tu primer 200 se perdió en transit).

→ Para: tracking lifecycle email, alerting, sync con DB interna
PRIMITIVE 2 · IDEMPOTENCY KEYS

Retries seguros sin duplicados

Pasas header Idempotency-Key con UUID v4 único por intento de operación lógica. Primera request exitosa cachea la respuesta por 24 horas asociada a esa key. Reintentos con la misma key (timeout, error de red, retry de tu queue) retornan la respuesta cacheada sin duplicar el envío. Crítico para flujos transaccionales donde un retry duplicado significaría enviar OTP dos veces o procesar webhook dos veces. Práctica recomendada: generar key derivada de operación de negocio (hash de order_id + tipo email) en vez de UUID random, así estás protegido aunque tu cliente HTTP genere requests nuevos en retries.

→ Para: OTP, password reset, confirmación orden, cualquier flujo crítico
PRIMITIVE 3 · RATE LIMITING

Headers transparentes

Cada respuesta API expone X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset (timestamp Unix). Plan Starter 60 req/seg sostenido con burst hasta 120. Plan Pro 200 req/seg con burst hasta 500. Plan Empresa 1,000 req/seg con burst configurable. Si excedes, recibes HTTP 429 con header Retry-After. SDKs aplican backoff automático respetando el header. Para batch de miles, endpoint POST /v1/emails/batch acepta hasta 1,000 destinatarios consumiendo solo 1 request contra tu rate limit.

→ Para: planificar capacidad, evitar throttling inesperado
// Webhook handler con verificación HMAC built-in
import { EMP } from '@emp/sdk';
import express from 'express';

const emp = new EMP(process.env.EMP_KEY!);
const app = express();

app.post('/webhooks/emp', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-emp-signature'] as string;

  try {
    // SDK valida HMAC SHA-256, lanza error si signature inválida
    const event = emp.webhooks.verify(req.body, signature, process.env.EMP_WEBHOOK_SECRET!);

    switch (event.type) {
      case 'email.delivered':
        await db.emails.markDelivered(event.data.id);
        break;
      case 'email.bounced':
        await db.contacts.markBounced(event.data.recipient);
        break;
    }

    res.status(200).end();
  } catch (err) {
    res.status(401).json({ error: 'Invalid signature' });
  }
});
Sobre seguridad de webhooks: EMP rota signing secrets vía dashboard sin downtime (vieja key sigue válida 24h durante rotation). Headers X-EMP-Timestamp incluidos para prevención de replay attacks (rechazar eventos con timestamp más antiguo de 5 minutos). Para entornos donde necesitas procesamiento garantizado exactly-once, combiná verificación HMAC con tabla de event IDs procesados en tu DB (cada evento tiene event.id único).
Pricing transparente

Setup desarrollo $290 · producción desde $99 USD mensuales.

Pricing idéntico a Email Transaccional + SMTP Relay porque la infraestructura subyacente es la misma. La diferencia entre ambas páginas es estrictamente la interface (HTTP/JSON vía REST/GraphQL aquí, SMTP estándar en la otra). Si tu app habla HTTP, esta es tu página y este es tu pricing.

Setup Desarrollo

Entorno aislado para integración técnica.

$290 one-time USD
  • 1,000 emails de prueba para integración
  • Endpoint aislado de producción
  • Acceso completo REST + GraphQL
  • SDKs descargables 5 lenguajes
  • Sesión onboarding 60 min con engineering
  • Revisión de código de integración
  • Crédito 100% al pasar a producción en 60 días
Provisionar entorno

Producción Starter

Para SaaS B2B en early production.

$99 / mes USD
  • Hasta 50,000 emails/mes
  • REST + GraphQL queries
  • Pool transaccional separado
  • Webhooks HMAC SHA-256
  • SDKs típados los 5 lenguajes
  • SLA 99.5% mensual
  • Soporte email · 24h SLA
Activar Starter

Empresa

Para fintech y SaaS alto volumen.

$1,200 / mes USD
  • Hasta 5M emails/mes
  • Pool dedicado 4 IPs
  • GraphQL Subscriptions WebSocket
  • SLA 99.95% con créditos altos
  • Account Manager dedicado
  • Sub-procesadores documentados
  • DPA Ley 81 negociable
Hablar con ventas
Volumen sobre 5M mensuales: pricing custom basado en mix de tráfico, requisitos de latencia específicos, y SLA negociado. Típicamente entre $0.20 y $0.45 por 1,000 emails para volúmenes 5M-50M mensuales con descuentos por commit anual. Misma infraestructura que Email Transaccional + SMTP Relay: si combinas ambas interfaces (REST/GraphQL para producto + SMTP para newsletter o reporte legacy), facturación se consolida en una sola cuenta sin doble cargo.
Las preguntas honestas que nos hacen

Lo que CTOs y leads developers preguntan en la llamada técnica.

"¿Por qué tener REST y GraphQL? ¿No alcanza con uno?"

Cada interface optimiza distinto. REST funciona mejor para acciones puntuales: enviar email, crear template, suspender suscriptor. La estructura recurso-acción mapea perfectamente. POST /v1/emails para enviar, GET /v1/emails/{id} para consultar. Predecible, fácil cachear, soporta CDNs, ecosistema enorme de tooling. GraphQL gana en fetching flexible: dashboards que combinan métricas (envíos último día + bounces por dominio + tasa apertura por template) sin hacer 4 requests REST. Pides exactamente los campos que necesitas. También facilita versionado evolutivo. La mayoría termina usando ambas: REST para sending y GraphQL para reporting/analytics. Algunos solo REST, algunos solo GraphQL. La elección es tuya, ofrecemos las dos para que decidas según tu stack.

"¿Cuál es la diferencia con Email Transaccional + SMTP Relay?"

Misma infraestructura subyacente, diferente interface y posicionamiento. Email Transaccional + SMTP Relay está pensado para equipos DevOps/SRE/CTO escalando producción que necesitan SMTP estándar (puertos 587/465) para frameworks legacy o integraciones SMTP existentes. Email API REST + GraphQL está pensado para developers integrando desde día uno, donde SMTP no es preferencia y la integración programática vía HTTP es natural. Pricing idéntico porque infra es la misma. Decisión: si tu app envía con cliente SMTP (Nodemailer SMTP, PHPMailer), elige Email Transaccional + SMTP Relay. Si tu app envía con cliente HTTP (axios, fetch, requests), elige Email API REST + GraphQL. Mismo dashboard, mismas métricas, mismos SDKs, mismos webhooks.

"¿Cómo se compara con Resend para developers?"

Resend es excelente, lo decimos honestamente. Su SDK TypeScript con React Email integration es reference-quality y su DX está entre lo mejor del mercado. Tres diferencias estructurales: (1) Resend no tiene GraphQL aún, REST únicamente. Si tu stack es GraphQL-first, EMP es match natural. (2) Resend US-based con jurisdicción US, EMP panameño con DPA Ley 81 nativo (importante para fintech regulada). (3) Soporte Resend en inglés con tickets 24-48h, EMP en español vía WhatsApp con 4h en plan Pro. Pricing: Resend $20/mes para 50K vs EMP $99/mes con Setup desarrollo $290. Resend gana en pricing puro a volumen bajo, EMP gana en jurisdicción y soporte regional. Resend wins: indie dev US sin requisitos de jurisdicción. EMP wins: developer panameño/latinoamericano construyendo SaaS donde compliance regional importa.

"¿Y si necesito templates? ¿Vienen con la API?"

Sí, sistema de templates completo vía API. Crear template: POST /v1/templates con HTML/MJML/Markdown del template, variables Mustache para sustitución dinámica, layouts reutilizables. Enviar usando template: POST /v1/emails con template_id en lugar de body, pasas variables como JSON, EMP renderiza server-side y envía. Beneficios: el HTML vive en EMP no en tu codebase (cambios de copy sin deploys), validación de HTML defectuoso antes de enviar, preview vía dashboard con datos de prueba. Si prefieres mantener templates en tu codebase (React Email, MJML local, Liquid templates), envías directamente el HTML renderizado en el body del request, no usas endpoint /v1/templates. Ambas estrategias soportadas, decisión arquitectónica de tu equipo.

"¿Hay rate limiting? ¿Cómo manejo bursts?"

Sí, con headers documentados en cada respuesta. X-RateLimit-Limit (límite plan), X-RateLimit-Remaining (restantes ventana actual), X-RateLimit-Reset (timestamp Unix reset). Plan Starter: 60 req/seg sostenido con burst 120. Plan Pro: 200 req/seg sostenido con burst 500. Plan Empresa: 1,000 req/seg sostenido con burst configurable. Si excedes, recibes HTTP 429 con header Retry-After. SDKs aplican backoff automático respetando el header. Para batch: endpoint POST /v1/emails/batch acepta hasta 1,000 destinatarios consumiendo solo 1 contra rate limit, ideal para newsletters o notificaciones masivas. Las docs traen ejemplos con bibliotecas como p-limit (Node) o equivalentes para no saturar tu propio rate limit cliente-side.

"¿Cuánto tiempo toma integrar desde cero?"

Primer email enviado: menos de 30 minutos para developer con experiencia previa en APIs HTTP. Setup técnico desarrollo se provisiona en 1 día hábil después de firma. Recibes API key, endpoint dedicado de prueba, link a docs interactivas, SDKs descargables. Instalás SDK con npm install / pip install / etc. Tres líneas de código para enviar primero email. Verificación de dominio para producción toma adicionales 5-30 min según tu DNS provider. Integración completa con manejo webhooks, retry custom, dashboard interno: típicamente 2-5 días de developer dedicado. Documentación viene con ejemplos copy-paste para casos comunes (envío simple, con template, con attachments, con tracking, batch sending, manejo de webhooks). Setup desarrollo trae sesión 60 minutos con engineering EMP para revisar tu integración específica antes de deployar a producción.

Preguntas frecuentes

Lo que aparece en la llamada técnica.

¿Por qué tener REST y GraphQL? ¿No alcanza con uno?

Cada interface optimiza distinto:

  • REST: acciones puntuales con resource-action mapping (POST /v1/emails)
  • GraphQL: queries flexibles que combinan campos sin overfetching
  • GraphQL Subscriptions: eventos tiempo real WebSocket (plan Empresa)

La mayoría usa REST para sending + GraphQL para reporting. Algunos solo REST, algunos solo GraphQL. EMP ofrece ambas para que decidas según tu stack.

¿Cuál es la diferencia con Email Transaccional + SMTP Relay?

Misma infraestructura subyacente, interface diferente:

  • SMTP Relay: para apps que envían vía cliente SMTP (Nodemailer SMTP, PHPMailer)
  • Email API: para apps que envían vía cliente HTTP (axios, fetch, requests)
  • Pricing idéntico porque infra es la misma
  • Mismo dashboard, métricas, SDKs, webhooks

Decisión estrictamente sobre cómo tu código habla con la infraestructura.

¿Qué SDKs hay disponibles y qué tan típados son?

Cinco SDKs oficiales mantenidos por engineering EMP:

  • TypeScript: tipos completos REST + GraphQL, autocomplete VS Code/Cursor
  • Python: type hints PEP 484, mypy strict, async/await
  • Go: structs generadas, context.Context propagation
  • PHP: 8.1+ con enums, PSR-18, Laravel + Symfony bridges
  • Ruby: dry-types, Rails ActiveJob, Sorbet sigs

Cada SDK trae verificación HMAC built-in, retry logic exponential backoff, idempotency keys auto-generadas, circuit breaker. Open source MIT en GitHub.

¿Cómo funcionan idempotency keys?

Mismo modelo que Stripe popularizó:

  • Pasas header Idempotency-Key con UUID v4 único por intento
  • Primera request exitosa cachea respuesta 24h asociada a esa key
  • Reintentos con misma key retornan respuesta cacheada sin duplicar
  • Crítico para flujos transaccionales (OTP, password reset, confirmaciones)

Práctica recomendada: generar key derivada de operación de negocio (hash order_id + tipo email) en vez de UUID random.

¿GraphQL Subscriptions vía WebSocket están disponibles?

Sí en plan Empresa:

  • WebSocket subscriptions para eventos tiempo real sin polling
  • Filtros declarativos (subscription EmailEvents { emailEvent(filter: {status: BOUNCED}) })
  • Conexión persistente con auto-reconnect
  • Heartbeats cada 30 segundos

Para notificaciones puntuales sin conexión persistente, webhooks HMAC tradicionales son más eficientes y escalan mejor.

¿Cómo se compara con Resend para developers?

Resend es excelente. Tres diferencias estructurales:

  • GraphQL: Resend solo REST, EMP REST + GraphQL
  • Jurisdicción: Resend US, EMP Panamá con DPA Ley 81
  • Soporte: Resend inglés 24-48h, EMP español WhatsApp 4h

Pricing: Resend $20/mes 50K vs EMP $99/mes + Setup $290.

Resend gana: indie dev US sin compliance requisitos. EMP gana: developer LatAm con jurisdicción regional.

¿Qué tan rápido se integra desde cero?

Tiempos típicos:

  • Setup desarrollo: 1 día hábil después de firma
  • Primer email enviado: menos de 30 minutos (3 líneas código)
  • Verificación dominio para producción: 5-30 minutos según DNS provider
  • Integración completa (webhooks, retry custom, dashboard): 2-5 días developer

Setup desarrollo trae sesión 60 minutos con engineering para revisar tu integración antes de producción.

¿Ofrecen rate limiting transparente?

Sí, headers documentados en cada respuesta:

  • Plan Starter: 60 req/seg sostenido, burst hasta 120
  • Plan Pro: 200 req/seg sostenido, burst hasta 500
  • Plan Empresa: 1,000 req/seg sostenido, burst configurable
  • HTTP 429 con Retry-After cuando excedes

SDKs implementan backoff automático respetando el header. Endpoint POST /v1/emails/batch acepta hasta 1,000 destinatarios consumiendo solo 1 request.

Setup desarrollo $290 · provisión 1 día hábil con onboarding 60 min de engineering.

Setup técnico de desarrollo provisiona endpoint aislado de producción con acceso completo REST + GraphQL. Recibes API key, link a documentación interactiva, SDKs descargables en 5 lenguajes, y sesión 60 minutos con engineering EMP para revisar tu integración específica. Los $290 acreditan 100 por ciento al primer mes de producción si se contrata dentro de 60 días. Para evaluación previa al setup, llamada gratis 30 minutos con engineering retorna comparativa personalizada vs tu stack actual en 24 horas. Migración asistida desde Resend, SendGrid, Postmark, Mailgun, AWS SES sin downtime usando deployment canary 5 fases.

Setup $290 · Provisión 1 día · Onboarding 60 min · Crédito 100% al pasar a producción