El Envío de Email se Declaró "Resuelto" Hace una Década — Entonces ¿Por Qué una Startup de Y Combinator Construida Sobre un Solo POST /emails se Llevó a Toda una Generación de Desarrolladores?
Abre tu dashboard de SES. Mira la curva de aprendizaje. Ahora mira tu tiempo hasta el primer email enviado.
El consejo estándar lleva años siendo: "usa SES, es barato y es de Amazon". Infraestructura commodity. Entregabilidad como ventaja. Y sin embargo, en su primer año, Resend — una startup de Y Combinator Winter 2023 fundada por Zeno Rocha, el creador del tema Dracula — se convirtió en la opción por defecto para una nueva generación de desarrolladores.
*El producto que se vende no es infraestructura SMTP. Es experiencia de desarrollador. *
El mercado de APIs de email se reabre cada pocos años: un nuevo entrante re-platforma la misma infraestructura SMTP con mejor DX y gana a la siguiente generación de devs. Postmark lo hizo. Resend lo hizo después. Comparar proveedores por capacidad de relay es un error de categoría — la comparación que gana es tiempo hasta el primer email y workflow de plantillas.
En este tutorial te llevo de cero a producción con Resend en 5 pasos. Terminal en mano.
---
No Quieres Un Proveedor de Email. Quieres una API Minima
El bet de Resend es deliberadamente mínimo: enviar un email es una llamada REST con from/to/subject/body, envuelta por SDKs oficiales delgados.
Un solo endpoint. Sin dashboards gigantes, sin drag-and-drop, sin 40 SDKs pesados que te obligan a leer 200 páginas de docs antes de tu primer send.
La superficie pequeña tiene consecuencias directas: onboarding más rápido, menos bugs, menos docs que leer. Y porque los SDKs son wrappers delgados sobre REST plano, siempre puedes bajar a curl o a cualquier HTTP client. Esa transparencia es una señal de confianza en sí misma.
El primer email con el SDK de Node.js en menos de un minuto:
```js
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'you@yourdomain.com',
to: 'user@example.com',
subject: 'Hello',
html: '<p>Hello!</p>'
});
```
¿Ves la superficie completa? Eso es todo. Para probar que el SDK es un wrapper delgado y no una caja negra, aquí está la misma llamada en curl:
```bash
curl -X POST https://api.resend.com/emails \
-H 'Authorization: Bearer re_...' \
-H 'Content-Type: application/json' \
-d '{"from":"you@yourdomain.com","to":"user@example.com","subject":"Hello","html":"<p>Hello!</p>"}'
```
Si algo falla y necesitas depurar, no dependes del SDK. Tienes raw HTTP.
Y si tu equipo usa otro lenguaje, no hay problema: Resend tiene SDKs oficiales para Node.js/TypeScript, Python, Ruby, Go, Java, PHP, Elixir, .NET, Swift y Kotlin. No te fuerza a un solo ecosistema.
---
El Paso Que Todos los Tutoriales Omiten: DNS Antes que API
Ahora viene la verdad incómoda.
El onboarding real de Resend no es la llamada a la API. Es verificar tu dominio. Y aquí es donde empiezan el 80% de los problemas de entregabilidad.
La infraestructura SMTP está resuelta. Tu reputación de dominio — y si tu email llega a la bandeja de entrada o a spam — no lo está. Eso se decide con SPF, DKIM y DMARC antes de enviar ni un solo email.
Registra tu dominio vía la API:
```bash
curl -X POST https://api.resend.com/domains \
-H 'Authorization: Bearer re_...' \
-H 'Content-Type: application/json' \
-d '{"name":"yourdomain.com"}'
```
La respuesta te devuelve los registros DNS que tu proveedor de DNS necesita (SPF, DKIM, DMARC). Añádelos en tu proveedor, vuelve a verificar, y ya tienes un dominio verificado.
Este paso — no la llamada de send — es donde se pierde el tiempo y donde la entregabilidad se gana o se pierde. El producto real de Resend es empaquetar esas preocupaciones operativas detrás de una API limpia: verificación de dominio, webhooks para eventos de entrega y rebote, tracking de opens y clicks.
---
React Email: El Cambio de Workflow Que Redefine Qué es una "Plantilla"
Ahora llegamos al bet estratégico de Resend.
React Email deja que escribas tus emails como componentes React tipados que se renderizan a HTML. Tu plantilla de welcome se convierte en un fichero versionado en tu repo, revisable en un pull request, testeable como cualquier otro código.
El mito de que una plantilla de email tiene que vivirse en un dashboard de drag-and-drop se cae aquí. Para equipos que ya revisan código, el email se vuelve revisable como cualquier otra feature.
Un ejemplo de `WelcomeEmail.tsx`:
```tsx
import {
Body,
Button,
Container,
Heading,
Html,
Section,
Text
} from '@react-email/components';
const WelcomeEmail = ({ name }: { name: string }) => (
<Html>
<Body>
<Container>
<Heading>Bienvenido, {name}</Heading>
<Text>Tu cuenta está lista. Esto es todo lo que necesitas saber.</Text>
<Section>
<Button href="https://yourdomain.com/dashboard">
Ir al panel
</Button>
</Section>
</Container>
</Body>
</Html>
);
export default WelcomeEmail;
```
Y antes del send, lo renderizas a HTML:
```tsx
import { render } from '@react-email/render';
import WelcomeEmail from './WelcomeEmail';
const html = render(<WelcomeEmail name={user.name} />);
await resend.emails.send({
from: 'you@yourdomain.com',
to: user.email,
subject: 'Bienvenido',
html
});
```
Ya no hay strings HTML gigantes embebidos en tu código de envío. El email es código, versionado, tipado y testeable. Y al final del día, React Email produce HTML estándar — por eso son provider-agnostic. Si mañana cambias de proveedor, tus componentes se quedan.
---
El Patrón de la Campana de Experiencia: 5 Pasos de Resend
Aquí está el framework que he usado en producción con mis propios productos (conversoriaecnae.es, gestoriascercademi.com, findemergencyplumber.com). Le llamo el Patrón de la Campana de Experiencia, porque el valor no está en la campana (el relay) sino en la forma que la envuelve: la experiencia.
Paso 1: Cuenta + Verificación de Dominio
Crea la cuenta y verifica tu dominio primero. Añade SPF, DKIM y DMARC tal y como te los da tu proveedor de DNS. Este paso DNS — no la llamada a la API — es la fricción real del onboarding y donde empiezan la mayoría de los problemas de entregabilidad.
Paso 2: Primer Email desde un Script Local
Usa el SDK oficial de tu lenguaje y apunta a un time-to-first-email por debajo de 5 minutos. La superficie mínima de la API es el punto: si tardas más de 5 minutos en enviar tu primer email, el proveedor está haciendo algo mal.
Paso 3: Plantillas Como Código
Saca tu markup de los strings HTML inline y muévelo a componentes React Email tipados en tu repo. Versionado, testeable, reutilizable entre todos tus flujos transaccionales (welcome, password reset, invoice). Este es el cambio de workflow, no una feature.
Paso 4: Webhooks y Tracking
Conecta los webhooks para `email.delivered`, `email.opened` y `email.bounced`. Loggea lo que pasa después del send y construye un pequeño path de retry para rebotes y fallos de API. La observabilidad post-send es donde pierdes el tiempo de ingeniería que SES nunca te resolvió.
Un handler mínimo:
```ts
// webhook handler
export async function handleResendEvent(event: {
type: 'email.delivered' | 'email.bounced' | 'email.opened';
data: { email_id: string };
}) {
if (event.type === 'email.bounced') {
// retry con backoff o marca el contacto como inválido
await retryOrMarkInvalid(event.data.email_id);
}
logger.info('resend_event', event);
}
```
Paso 5: Adapter Provider-Agnóstico
Integra el envío detrás de una función adapter delgada y agnóstica al proveedor, para que Resend siga siendo swappable. La superficie de API es pequeña y los SDKs son wrappers delgados, así que la integración es barata de reemplazar. El bet queda reversible.
```ts
// email.ts — adapter
export async function sendEmail({
to,
subject,
html
}: {
to: string;
subject: string;
html: string;
}) {
return resend.emails.send({ from: 'you@yourdomain.com', to, subject, html });
}
```
Si mañana cambias de proveedor, cambias una función, no toda tu app.
---
Deliverability: El 80% Oculto de "Enviar Email"
La mayoría de los desarrolladores piensan que "enviar email" es la llamada a la API. En realidad, la llamada es el 20% visible. El 80% oculto es: reputación de dominio, alineación SPF/DKIM/DMARC, warm-up, manejo de rebotes.
Resend empaqueta toda esa pila operativa — dominios, webhooks, analytics de opens/clicks — detrás de una API limpia. Y además cubre casos operativos sin librerías extra: attachments y envíos programados.
```ts
await resend.emails.send({
from: 'you@yourdomain.com',
to: user.email,
subject: 'Tu factura',
html: invoiceHtml,
attachments: [
{ filename: 'factura.pdf', content: pdfBuffer }
],
send_at: futureIsoString // envío programado
});
```
Este tutorial te enseña que el trabajo real está en el DNS, no en el send. Esa es la lección que los tutoriales de SES nunca te dieron.
---
¿Y si Ya Uso SES o SendGrid?
La objeción más común: "ya uso Mailgun, ¿por qué migrar?"
La migración es en su mayoría cambiar una función de send por otra. Y las plantillas React Email son HTML provider-agnostic al final del día. La pregunta real es: ¿cuánto tiempo de workflow pierde tu equipo cada vez que toca un email?
¿Y el lock-in? La superficie de API es pequeña y los SDKs son wrappers delgados. El adapter agnóstico del Paso 5 lo convierte en un bet reversible. Vas a querer reemplazar una librería de 20 líneas, no un monolito.
---
Tiempo de Ejecución
El mercado de email se reabre cada pocos años con el mismo movimiento: la misma infraestructura bajo mejor DX gana a la siguiente generación de devs.
Resend es ese movimiento para esta generación. Un solo POST /emails, SDKs delgados, React Email como workflow, y la pila operativa de entregabilidad empaquetada detrás de la API.
El producto no es el relay. Es la campana de experiencia que lo envuelve.
El email dejó de ser un problema de infraestructura hace una década. Se convirtió en un problema de workflow — y Resend lo ganó en su primer año porque entendió exactamente eso.
Lee el artículo completo en brianmenagomez.com
Más sobre mis servicios en brianmenagomez.com
Herramientas: Conversor IAE CNAE · Gestorias cerca de ti · Calculadora IRPF

