Resend Email API Tutorial 2026: React Email + SDK en 5 Pasos para Dejar de Escribir HTML en Strings
Tutorial práctico de Resend Email API 2026. Aprende a integrar React Email + SDK de Resend en 5 pasos. TypeScript, webhooks, componentes versionables. Olvida los templates HTML en string.
El 90% de los que Usáis SendGrid Tenéis Templates que No Podéis Migrar
Abre tu dashboard de SendGrid. Mira cualquiera de tus templates activos.
*No puedes mover esa plantilla a Mailgun sin reescribirla desde cero. *
No es culpa tuya. Es el modelo de negocio. SendGrid, Mailgun, SES — todos os atan a su formato de plantillas porque la retención es más rentable que la calidad. Los proveedores legacy no compiten en experiencia de desarrollo: compiten en no dejaros ir.
El resultado es que tu código de email es el monolito más infravalorado de tu stack.
Miles de líneas de HTML inline, CSS manual, y strings concatenados que viven en un dashboard al que solo accedes desde el navegador. Sin Git. Sin CI. Sin tipos.
*El email transaccional no debería ser diferente al resto de tu frontend. *
Y aquí es donde entra Resend.
---
❌ Lo que Crees que Sabes sobre APIs de Email
La mayoría de los desarrolladores asumís que las APIs de email son un problema resuelto y commoditizado. Coges cualquiera, los resultados son los mismos.
*La realidad es que la mayoría de las APIs de email se diseñaron en los 2010s. *
Interfaces REST-first con respuestas sin tipar. Templates HTML que mezclan lógica y presentación en strings. Y una experiencia de depuración que consiste en "envía y reza".
Mirad lo que pasa cuando enviáis un email con SendGrid:
```typescript
// ❌ SendGrid — 2020 vibes
import sgMail from '@sendgrid/mail';
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
to: 'user@example.com',
from: 'noreply@tuapp.com',
subject: 'Bienvenido',
html: '<h1 style="color:red">Bienvenido</h1><p>Gracias por registrarte</p>',
};
await sgMail.send(msg);
```
Fijaos en lo que está pasando aquí:
El HTML es un string. No hay tipos. No hay autocompletado. No hay preview.
La respuesta de `send()` no está tipada. Si falla, parseas el error a mano.
El template vive en tu código, no en un dashboard. Esto es bueno, pero estás manteniendo HTML inline como en 2005.
El problema no es SendGrid. Es que toda la categoría aceptó que el email se escribe en strings.
Resend dijo: "¿Y si tratamos el email como un componente de React?"
---
✅ Lo que Resend Hace Diferente (y por Qué Importa)
Resend no inventó el envío de email. Resend inventó *cómo se escribe* el email.
Tres diferencias que cambian todo:
1. TypeScript nativo desde el día 1 — SDKs tipados, errores tipados, respuestas tipadas. Nada de adivinar qué devuelve la API.
2. React Email como estándar — Escribes componentes React, no strings HTML. Preview local, Git diff, CI testing.
3. Webhooks con firma HMAC-SHA256 — Eventos tipados, verificación de firma, suscripción por tipo de evento. No más payloads inconsistentes.
Mirad el mismo envío con Resend y React Email:
```typescript
// ✅ Resend + React Email — 2026 vibes
import { Resend } from 'resend';
import { WelcomeEmail } from '@/emails/welcome';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send({
from: 'noreply@tuapp.com',
to: 'user@example.com',
subject: 'Bienvenido',
react: WelcomeEmail({ name: 'Ana', plan: 'Pro' }),
});
```
¿Veis la diferencia?
`WelcomeEmail` es un componente React. Tiene props tipadas. Puedes hacer preview en local con `npx react-email dev`.
La respuesta `{ data, error }` está tipada. TypeScript te dice qué hay dentro.
El componente se versiona con Git. Haces `git diff` en el PR. Code review sobre el HTML del email.
*Eso no es una feature. Es un cambio de paradigma. *
---
El Problema Real: El Email no es un Problema de Entrega. Es un Problema de Mantenimiento
Aquí va la verdad incómoda que ningún proveedor legacy quiere que sepas:
Todos usáis la misma infraestructura de entrega.
Resend usa AWS SES por debajo. SendGrid también. Mailgun también. La diferencia no está en si el email llega — está en cuánto tiempo pierdes manteniendo el código que lo envía.
El coste real del email transaccional no está en la API. Está en el developer experience.
Cada vez que un diseñador os pide cambiar el color de un botón en un email de bienvenida:
❌ SendGrid/Mailgun: Abres el dashboard en el navegador, buscas la template, editas HTML inline con un editor web cutre, guardas, pruebas enviándote un email a ti mismo, ves que se ve mal en Outlook, repites.
✅ Resend + React Email: Abres `WelcomeEmail.tsx` en VS Code, cambias `className=\"bg-blue-500\"`, ves el preview en tu navegador local con hot reload, haces commit, tu CI corre tests visuales, despliegas.
*El segundo flujo es el mismo que usas para el resto de tu frontend. *
Ahí está el truco. Resend no compite en infraestructura. Compite en que tu workflow de email sea indistinguible del de tu app.
---
El Marco de 5 Capas para Email como Código
Después de enviar este tutorial a producción en varios proyectos — desde gestorías hasta módulos fiscales — he destilado el proceso en un marco que llamo "El Marco de 5 Capas para Email como Código".
Cada capa resuelve un problema específico del pipeline de email transaccional. Sáltate una y volverás a escribir HTML en strings.
Capa 1: Componentes React con React Email
```bash
npm install @react-email/components react-email
```
Cread `emails/WelcomeEmail.tsx`:
```typescript
import {
Body, Container, Head, Heading, Html,
Preview, Section, Text, Button,
} from '@react-email/components';
interface WelcomeEmailProps {
name: string;
plan: string;
}
export const WelcomeEmail = ({ name, plan }: WelcomeEmailProps) => (
<Html>
<Head />
<Preview>Bienvenido a {plan}, {name}</Preview>
<Body style={{ fontFamily: 'Arial', backgroundColor: '#f6f9fc' }}>
<Container>
<Heading>Bienvenido, {name}</Heading>
<Text>Gracias por unirte al plan {plan}.</Text>
<Section>
<Button href="https://tuapp.com/dashboard">
Ir al Dashboard
</Button>
</Section>
</Container>
</Body>
</Html>
);
```
Pro tip: Ejecutad `npx react-email dev` para ver el preview en vivo. Hot reload incluido. Esto solo ya os ahorra horas de "envía y comprueba en Gmail".
Capa 2: SDK de Resend con Tipado Estricto
```bash
npm install resend
```
Cread `lib/resend.ts`:
```typescript
import { Resend } from 'resend';
if (!process.env.RESEND_API_KEY) {
throw new Error('RESEND_API_KEY no está definida');
}
export const resend = new Resend(process.env.RESEND_API_KEY);
```
La clave aquí es que *el propio SDK lanza el error si la API key falta*. Nada de fallos silenciosos en producción.
Capa 3: Endpoint de API con Validación
En Next.js App Router:
```typescript
// app/api/send-welcome/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { resend } from '@/lib/resend';
import { WelcomeEmail } from '@/emails/welcome';
export async function POST(request: NextRequest) {
const body = await request.json();
const { name, email, plan } = body;
if (!name || !email || !plan) {
return NextResponse.json(
{ error: 'Faltan campos requeridos' },
{ status: 400 }
);
}
const { data, error } = await resend.emails.send({
from: 'onboarding@tuapp.com',
to: email,
subject: `Bienvenido a ${plan}`,
react: WelcomeEmail({ name, plan }),
});
if (error) {
return NextResponse.json({ error }, { status: 500 });
}
return NextResponse.json({ data });
}
```
Observad: validación manual antes de llamar a Resend. Tipado estricto en toda la cadena. Si la API key falla, el error es capturable.
Capa 4: Webhooks con Verificación de Firma
Resend firma cada webhook con HMAC-SHA256. No os saltéis la verificación.
```typescript
// app/api/webhooks/resend/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { createHmac } from 'crypto';
const WEBHOOK_SECRET = process.env.RESEND_WEBHOOK_SECRET!;
export async function POST(request: NextRequest) {
const signature = request.headers.get('resend-signature');
const body = await request.text();
// Verificar firma
const expectedSig = createHmac('sha256', WEBHOOK_SECRET)
.update(body)
.digest('hex');
if (signature !== expectedSig) {
return NextResponse.json({ error: 'Firma inválida' }, { status: 401 });
}
const event = JSON.parse(body);
switch (event.type) {
case 'email.delivered':
console.log(`Email entregado: ${event.data.email_id}`);
break;
case 'email.bounced':
console.log(`Email rebotado: ${event.data.email_id}`);
// Marcar usuario como hard bounce en tu BD
break;
case 'email.opened':
console.log(`Email abierto: ${event.data.email_id}`);
break;
case 'email.complained':
console.log(`Reclamación de spam: ${event.data.email_id}`);
break;
}
return NextResponse.json({ received: true });
}
```
*Sin verificación de firma, cualquiera puede llamar a tu webhook y falsear eventos. *
Capa 5: Batch Sending con Personalización
```typescript
const { data, error } = await resend.batch.send([
{
from: 'noreply@tuapp.com',
to: 'ana@example.com',
subject: 'Tu informe semanal',
react: WeeklyReport({ name: 'Ana', stats: { orders: 12, revenue: 340 } }),
},
{
from: 'noreply@tuapp.com',
to: 'juan@example.com',
subject: 'Tu informe semanal',
react: WeeklyReport({ name: 'Juan', stats: { orders: 8, revenue: 210 } }),
},
]);
```
Batch endpoint con tipado completo. Cada email puede tener datos dinámicos. Resend maneja la cola y los reintentos.
---
¿Y Si Resend Desaparece? El Riesgo Realista
Vale. Os oigo.
"¿Confiar el email de mi negocio a una startup de 2023?"
Es una pregunta legítima. Os diré cómo lo gestiono yo:
1. Resend es una capa fina sobre AWS SES. Si mañana cierran, migrar a SES directo es cambiar 3 líneas de código. El vendor lock-in es mínimo.
2. Tus templates son componentes React. No hay formato propietario. Te los llevas a cualquier proveedor que acepte HTML.
3. Ten un fallback configurado. En producción, envolved la llamada a Resend en un try-catch con un fallback a SES directo o Mailgun. Son 15 minutos de código.
*Switching cost bajo + templates portables + proof of concept en minutos. *
Esa ecuación no existía antes de Resend.
---
Lo Que Nadie os Cuenta: El Free Tier es un Funnel de Adopción, no un Descuento
Resend os da 100 emails gratis al día sin tarjeta de crédito.
No es "generosidad". Es estrategia.
El free tier os permite integrar Resend en un side project, amarlo por la DX, y luego abogar por él en vuestro trabajo del día. Es el mismo playbook que Stripe usó en 2011: haz que los desarrolladores se enamoren del tool, y ellos lo llevarán a la empresa.
*El free tier no es para ahorraros dinero. Es para que no podáis dejar de usarlo. *
---
Resumen: Por Qué Empezar Hoy
| Lo Que Hacíais Antes | Lo Que Haréis con Resend |
|---|---|
| HTML en strings | Componentes React con tipos |
| Dashboards externos para templates | Git + CI + code review |
| Depuración por "envía y reza" | Preview local con hot reload |
| Webhooks sin verificar | Firma HMAC-SHA256 |
| Respuestas sin tipar | TypeScript end-to-end |
| Vendor lock-in profundo | Capa fina sobre SES |
El email transaccional en 2026 no es un problema de infraestructura. Es un problema de mantenimiento.
Resend no os da mejor entrega. Os da un workflow que no odiáis.
*Y eso, para un equipo pequeño, vale más que diez funciones extra de SendGrid. *
Dejad de escribir HTML en strings. Instalad React Email. Cread un componente. Enviadlo con Resend.
El primer email os llevará 10 minutos. El resto, el tiempo de escribir un componente React.
Empezad hoy. Vuestro yo del futuro — y vuestro equipo — os lo agradecerán.
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

