Resend Email API Tutorial: El Único Setup que Necesitas en Producción
Complete Resend Email API tutorial in Spanish: setup, React Email templates, webhooks, and production best practices for Next.js developers.
La Mayoría de Developers Siguen Usando SMTP en 2026
SMTP es un protocolo de 1982.
Y todavía lo usas para enviar emails transaccionales en tu SaaS.
*La realidad:* tu sistema de emails se cae una vez al mes, tu tasa de entrega es un misterio, y no tienes ni un dashboard decente para ver qué está fallando.
Resend resuelve exactamente esto. Y con 15 líneas de código.
Este es el resend email api tutorial que ojalá hubiera existido cuando empecé.
Por Qué Resend y No SendGrid, Mailgun o AWS SES
La respuesta corta: la developer experience.
SendGrid tiene una API de 2011 envuelta en una UI de 2014. Mailgun es potente pero está documentado como si fuera para ingenieros de telecomunicaciones. AWS SES funciona, pero configurar DKIM, SPF y DMARC desde cero te cuesta medio día de trabajo.
Resend está construido específicamente para developers que usan Next.js, React y TypeScript.
Tiene:
→ SDK oficial para Node.js, Python, Go, Ruby y PHP
→ Integración nativa con React Email para plantillas
→ Webhooks con firma HMAC para eventos en tiempo real
→ Domain verification en menos de 10 minutos
→ Dashboard limpio con logs de entrega por mensaje
La API sigue el mismo patrón que Stripe: simple, predecible, documentada con ejemplos reales.
Setup Inicial: De Cero a Primer Email en 5 Minutos
Paso 1: Instalar el SDK
```bash
npm install resend
o con pnpm
pnpm add resend
```
Paso 2: Obtener tu API Key
Ve a resend.com, crea una cuenta, y en el dashboard genera tu primera API key.
Guárdala en tu `.env.local`:
```bash
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxx
```
Paso 3: Enviar tu Primer Email
Este es el código más básico posible. Funciona en Node.js, Next.js API Routes y cualquier entorno server-side:
```typescript
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
async function sendWelcomeEmail(userEmail: string, userName: string) {
const { data, error } = await resend.emails.send({
from: 'Tu App <hola@tudominio.com>',
to: [userEmail],
subject: `Bienvenido, ${userName}`,
html: `<h1>Hola ${userName}, gracias por registrarte.</h1>`,
});
if (error) {
console.error('Error enviando email:', error);
return null;
}
return data;
}
```
El objeto de respuesta tiene `data.id` — el ID único de ese email. Lo necesitas para rastrear entregas vía webhook.
El Patrón Real: React Email + Resend en Next.js
Enviar HTML crudo es el enfoque de 2015.
El patrón correcto en 2026 es React Email como sistema de plantillas con Resend como transporte. Separas el diseño del envío, y puedes previsualizar emails en el browser como si fueran componentes React.
Instalar React Email
```bash
npm install @react-email/components react-email
```
Crear una Plantilla
```tsx
// emails/WelcomeEmail.tsx
import {
Html,
Head,
Body,
Container,
Text,
Button,
Hr,
} from '@react-email/components';
import * as React from 'react';
interface WelcomeEmailProps {
userName: string;
confirmationUrl: string;
}
export function WelcomeEmail({ userName, confirmationUrl }: WelcomeEmailProps) {
return (
<Html lang="es">
<Head />
<Body style={{ fontFamily: 'sans-serif', backgroundColor: '#f4f4f4' }}>
<Container style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
<Text style={{ fontSize: '24px', fontWeight: 'bold' }}>
Bienvenido, {userName} 👋
</Text>
<Text style={{ color: '#666' }}>
Confirma tu cuenta para empezar a usar la app.
</Text>
<Hr />
<Button
href={confirmationUrl}
style={{
backgroundColor: '#000',
color: '#fff',
padding: '12px 24px',
borderRadius: '6px',
textDecoration: 'none',
}}
>
Confirmar cuenta
</Button>
</Container>
</Body>
</Html>
);
}
```
Enviar la Plantilla con Resend
```typescript
// app/api/send-welcome/route.ts (Next.js App Router)
import { Resend } from 'resend';
import { render } from '@react-email/render';
import { WelcomeEmail } from '@/emails/WelcomeEmail';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST(request: Request) {
const { email, name, confirmationUrl } = await request.json();
const emailHtml = await render(
<WelcomeEmail userName={name} confirmationUrl={confirmationUrl} />
);
const { data, error } = await resend.emails.send({
from: 'Mi App <noreply@miapp.com>',
to: [email],
subject: 'Confirma tu cuenta',
html: emailHtml,
});
if (error) {
return Response.json({ error }, { status: 400 });
}
return Response.json({ id: data?.id });
}
```
Este es el patrón de producción. Tus plantillas son testeables, versionables en Git, y reutilizables.
Webhooks: La Parte que Todos Ignoran
El error real no es en el resend email api tutorial. Es en no implementar webhooks.
*El verdadero problema no es enviar emails. Es saber cuáles llegaron.*
Resend emite eventos para: `email.sent`, `email.delivered`, `email.bounced`, `email.complained`, `email.opened`, `email.clicked`.
Sin webhooks, estás enviando emails a ciegas.
```typescript
// app/api/webhooks/resend/route.ts
import { headers } from 'next/headers';
import { Webhook } from 'svix';
const webhookSecret = process.env.RESEND_WEBHOOK_SECRET!;
export async function POST(request: Request) {
const headersList = headers();
const svixId = headersList.get('svix-id')!;
const svixTimestamp = headersList.get('svix-timestamp')!;
const svixSignature = headersList.get('svix-signature')!;
const body = await request.text();
const wh = new Webhook(webhookSecret);
let event: any;
try {
event = wh.verify(body, {
'svix-id': svixId,
'svix-timestamp': svixTimestamp,
'svix-signature': svixSignature,
});
} catch (err) {
return Response.json({ error: 'Invalid signature' }, { status: 400 });
}
// Manejar el evento
switch (event.type) {
case 'email.bounced':
// Marcar el email como inválido en tu BD
await markEmailAsBounced(event.data.email_id, event.data.to[0]);
break;
case 'email.complained':
// Desuscribir inmediatamente
await unsubscribeUser(event.data.to[0]);
break;
case 'email.delivered':
// Actualizar estado en tu dashboard
await updateEmailStatus(event.data.email_id, 'delivered');
break;
}
return Response.json({ received: true });
}
async function markEmailAsBounced(emailId: string, address: string) {
// Tu lógica de base de datos aquí
console.log(`Email ${emailId} bounced para ${address}`);
}
async function unsubscribeUser(address: string) {
console.log(`Desuscribiendo ${address} por complaint`);
}
async function updateEmailStatus(emailId: string, status: string) {
console.log(`Email ${emailId}: ${status}`);
}
```
Instala `svix` para verificar las firmas:
```bash
npm install svix
```
Errores Comunes en Producción
❌ Mal: Enviar desde un dominio no verificado
```
from: 'app@gmail.com'
```
Resend lo bloqueará. Gmail y los grandes ISPs rechazan emails transaccionales desde dominios personales.
✅ Bien: Dominio propio verificado con DNS
```
from: 'hola@tuproducto.com'
```
Verifica el dominio en el dashboard de Resend añadiendo los registros DKIM y SPF que te proporcionan. Tarda menos de 10 minutos.
---
❌ Mal: Hardcodear la API key en el código
```typescript
const resend = new Resend('re_abc123...'); // NUNCA hagas esto
```
✅ Bien: Variables de entorno siempre
```typescript
const resend = new Resend(process.env.RESEND_API_KEY);
```
---
❌ Mal: Ignorar errores del SDK
```typescript
const { data } = await resend.emails.send({...});
// Si hay error, data es null y tu app explota
```
✅ Bien: Desestructurar y manejar `error` siempre
```typescript
const { data, error } = await resend.emails.send({...});
if (error) {
// Log, alerta, reintento — no ignores esto
throw new Error(`Resend error: ${error.message}`);
}
```
Verifica Emails en Local con el CLI de React Email
Antes de hacer deploy, previsualiza tus plantillas en el browser:
```bash
npx react-email dev --dir emails --port 3001
```
Abres `localhost:3001` y ves todas tus plantillas renderizadas como si fueran páginas web. Cambias el componente, se recarga en tiempo real. *Es la mejor developer experience para email que existe ahora mismo.*
Cuándo No Usar Resend
Resend no es la solución para todo.
→ Si necesitas email marketing masivo con segmentación avanzada, listas y A/B testing → usa Loops.so o Brevo
→ Si ya tienes infraestructura en AWS y quieres coste mínimo → AWS SES sigue siendo válido
→ Si necesitas email bidireccional con parsing de respuestas → considera Postmark
Pero para emails transaccionales en un SaaS moderno — confirmaciones, resets de contraseña, notificaciones, facturas — Resend es la opción más rápida de implementar y mantener.
Takeaways Clave
→ Instala `resend` y `@react-email/components` juntos desde el primer día
→ Nunca envíes HTML crudo: usa React Email como sistema de plantillas
→ Implementa el webhook endpoint antes de ir a producción, no después
→ Verifica tu dominio con DKIM y SPF desde el dashboard de Resend
→ Maneja siempre `{ data, error }` — nunca asumas que el envío fue exitoso
→ Usa `svix` para verificar firmas de webhooks y evitar requests maliciosos
La infraestructura de email es la parte más ignorada del stack de cualquier SaaS. Con Resend y este setup, la conviertes en algo que funciona, es observable y no te da problemas a las 3 de la mañana.
Lee el artículo completo en brianmenagomez.com


