# Migrar desde SendGrid

> Pasa de SendGrid a Emailit. Equivalencias de conceptos, campos de la API, configuración SMTP y nombres de eventos del Event Webhook, y cómo trasladar las direcciones bloqueadas, las plantillas dinámicas y los DNS.

Esta guía relaciona los conceptos, las llamadas a la API, los webhooks, las direcciones bloqueadas y las plantillas de SendGrid con sus equivalentes en Emailit. Lee primero [Migrar a Emailit](/es/docs/migrate/) para conocer el orden general y cómo usar los dos proveedores en paralelo.

## Conceptos

| SendGrid | Emailit |
| --- | --- |
| Cuenta y subusuarios (subusers) | Cuenta y [espacios de trabajo](/es/docs/workspaces/). Cada espacio de trabajo tiene sus propios dominios, claves, miembros y créditos. |
| Clave de API con permisos | [Clave de API](/es/docs/developers/api-keys/): **Full Access**, o **Sending Only** limitada opcionalmente a un dominio |
| Domain authentication | [Dominio de envío](/es/docs/domains/) con registros SPF, DKIM y return-path |
| Link branding | [Subdominio de seguimiento](/es/docs/tracking/), un CNAME como `go.acme.com` |
| Single sender verification | No disponible. Todas las direcciones del remitente deben pertenecer a un dominio verificado. |
| Dynamic templates | [Plantillas](/es/docs/templates/) con un alias y versiones, renderizadas con [Temple](/es/docs/templates/temple/) |
| Event Webhook | [Webhooks](/es/docs/webhooks/) |
| Inbound Parse | [Emails entrantes](/es/docs/inbound/) |
| Suppressions | [Direcciones bloqueadas](/es/docs/suppressions/) |
| Unsubscribe groups | No disponible. Usa [listas de contactos](/es/docs/audiences/) y los enlaces de baja de las campañas. |
| Contactos y listas de marketing | [Contactos](/es/docs/contacts/) y [listas de contactos](/es/docs/audiences/) |
| Single Sends | [Campañas](/es/docs/campaigns/) |
| Email Activity | **Email API → Emails** y **Email API → Logs** |
| Categories y custom args | `meta` |
| IP dedicadas y pools de IP | [IP dedicadas](/es/docs/deliverability/dedicated-ips/) bajo solicitud |
| Validación de direcciones de email | [Verificación de emails](/es/docs/email-verification/) |

## Actualizar las llamadas a la API

`POST /v3/mail/send` de SendGrid pasa a ser `POST /v2/emails`. La petición es más plana: no hay `personalizations` y las direcciones son cadenas simples.

```bash title="Antes: SendGrid"
curl https://api.sendgrid.com/v3/mail/send \
  -H "Authorization: Bearer $SENDGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [{ "to": [{ "email": "ada@example.com" }] }],
    "from": { "email": "hello@acme.com", "name": "Acme" },
    "subject": "Your receipt",
    "content": [
      { "type": "text/plain", "value": "Thanks for your order." },
      { "type": "text/html", "value": "<p>Thanks for your order.</p>" }
    ]
  }'
```

```bash title="Después: Emailit"
curl https://api.emailit.com/v2/emails \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@acme.com>",
    "to": "ada@example.com",
    "subject": "Your receipt",
    "text": "Thanks for your order.",
    "html": "<p>Thanks for your order.</p>"
  }'
```

| SendGrid | Emailit |
| --- | --- |
| `Authorization: Bearer SG.…` | `Authorization: Bearer secret_…` |
| `from: { email, name }` | `from: "Name "` |
| `personalizations[].to[]` | `to`, una cadena o un array de hasta 50 direcciones |
| `personalizations[].cc[]`, `bcc[]` | `cc`, `bcc` |
| `reply_to: { email }` | `reply_to` |
| `subject` | `subject` |
| `content[]` con `text/plain` y `text/html` | `text` y `html` |
| `template_id` | `template`, un ID o alias de plantilla |
| `personalizations[].dynamic_template_data` | `variables` |
| `attachments[]` con `content`, `filename`, `type`, `content_id` | `attachments[]` con `content`, `filename`, `content_type`, `content_id`, o una `url` en lugar de `content` |
| `headers` | `headers` |
| `custom_args`, `categories` | `meta`, un objeto de valores de cadena que se devuelve en los eventos de webhook |
| `send_at` (tiempo Unix) | `scheduled_at`, que acepta el mismo tiempo Unix, ISO 8601 o lenguaje natural en inglés |
| `tracking_settings.open_tracking` y `click_tracking` | `tracking: { "loads": true, "clicks": true }` |
| `asm` (unsubscribe groups) | No disponible |
| `202 Accepted` con una cabecera `X-Message-Id` | `200` con un cuerpo JSON: `id`, `status: "accepted"` e `ids` con un ID por destinatario |

Cada destinatario de una petición a Emailit se convierte en un email independiente con su propio ID. Para enviar variables distintas a personas distintas, que SendGrid hace con varios `personalizations`, envía una petición por destinatario. Añade una cabecera `Idempotency-Key` para que los reintentos sean seguros. Consulta [Enviar un email](/es/docs/email-api/send-email/).

## Cambiar la configuración SMTP

| Ajuste | SendGrid | Emailit |
| --- | --- | --- |
| Host | `smtp.sendgrid.net` | `smtp.emailit.com` |
| Puerto | `587`, `465`, `2525` o `25` | `587` (STARTTLS), `465` (TLS), `2525`, `2587` o `25` |
| Usuario | `apikey` | `emailit` |
| Contraseña | Tu clave de API de SendGrid | Tu clave de API de Emailit |

Emailit no lee la cabecera `X-SMTPAPI`. Elimínala y configura el seguimiento en el dominio. Consulta [Configuración SMTP](/es/docs/smtp/settings/).

## Equivalencias de los eventos de webhook

| Evento de SendGrid | Evento de Emailit |
| --- | --- |
| `processed` | `email.accepted` (solo API) |
| `deferred` | `email.attempted` |
| `delivered` | `email.delivered` |
| `bounce` | `email.bounced` |
| `dropped` | `email.suppressed` cuando el destinatario está en la lista de direcciones bloqueadas |
| `open` | `email.loaded` |
| `click` | `email.clicked` |
| `spamreport` | `email.complained` |
| `unsubscribe`, `group_unsubscribe` | `email.unsubscribed`, solo para los emails de campaña |
| POST de Inbound Parse | `email.received`; después, obtén el contenido con [`GET /emails/{id}`](/es/docs/api-reference/emails/get/) |

Igual que SendGrid, Emailit envía por POST un array JSON de eventos. Los campos son distintos:

- El nombre del evento está en `type` y el email, en `data.object`. Usa `data.object.id` (el ID `em_` de la respuesta de envío) en lugar de `sg_message_id`, y `data.object.to` en lugar de `email`.
- Tus valores de `meta` vuelven en `data.object.meta`.
- Emailit firma las peticiones con HMAC-SHA256 en lugar de con la clave pública ECDSA de SendGrid. Verifica `X-Emailit-Signature` con tu secreto `whsec_`. Consulta [Verificar las firmas de los webhooks](/es/docs/webhooks/request-signature/).

```javascript
for (const event of req.body) {
  const email = event.data.object;
  if (event.type === 'email.bounced') markBounced(email.to, email.id);
  if (event.type === 'email.complained') unsubscribe(email.to);
}
```

## Trasladar las direcciones bloqueadas

1. En SendGrid, exporta tus **Bounces**, **Spam Reports**, **Invalid Emails** y **Global Unsubscribes**, desde las páginas de Suppressions o con los endpoints `/v3/suppression/*` de la API. Los Blocks suelen ser temporales, así que puedes omitirlos.

2. Crea un único CSV con las columnas `email,type,reason`:

```csv
email,type,reason
old-address@example.com,recipient,sendgrid bounce
angry@example.com,recipient,sendgrid spam report
```

   Usa el tipo `recipient` para las direcciones que nunca deben recibir emails. Bloquea los envíos por API, por SMTP y de campañas. Los tipos `bounce`, `complaint` y `unsubscribe` solo detienen las campañas.

3. En **Email API → Suppressions**, selecciona **Import** y sube el archivo. Cada archivo puede tener hasta 10.000 filas y ocupar como máximo 8 MB, así que divide las listas más grandes. Los duplicados se omiten.

Para las bajas de grupos del email de marketing, importa a esas personas como contactos con **unsubscribed** activado, en lugar de bloquearlas para todos los emails. Consulta [Gestionar las direcciones bloqueadas](/es/docs/suppressions/manage/).

## Trasladar las plantillas

Exporta el HTML de cada plantilla dinámica de SendGrid y después impórtalo en **Email Marketing → Templates** o crea la plantilla con la [API de plantillas](/es/docs/api-reference/templates/create/). Asigna a cada plantilla un alias, como `receipt`, y envíala con `"template": "receipt"`.

Las dos usan dobles llaves, pero Temple es más reducido que Handlebars:

| SendGrid (Handlebars) | Emailit (Temple) |
| --- | --- |
| `{{first_name}}` | `{{first_name}}` |
| `{{{html_block}}}` | `{{html_block}}`. Temple nunca escapa el HTML, así que escapa tú los datos que introducen los usuarios. |
| `{{insert name "default=there"}}` | `{{name\|"there"}}` |
| `{{#if plan}}…{{else}}…{{/if}}` | Igual |
| `{{#each items}}…{{/each}}` | No compatible. Genera la lista en tu código y pásala como una sola variable. |
| `{{#equals plan "pro"}}…{{/equals}}` | No compatible. Pasa un booleano como `is_pro` y usa `{{#if is_pro}}`. |

Consulta [Lenguaje de plantillas Temple](/es/docs/templates/temple/) e [Importar, exportar y duplicar plantillas](/es/docs/templates/import-export/).

## Cambiar los DNS

Añade tu dominio en **Email API → Domains** y publica los registros de Emailit. Usan sus propios nombres (`emailit._domainkey`, `emailit.<domain>` y, opcionalmente, `go` e `inbound`), así que no entran en conflicto con los CNAME de domain authentication ni de link branding de SendGrid. Conserva tu registro DMARC. Después del cambio definitivo, elimina los CNAME de SendGrid. Consulta [Registros DNS de los dominios de envío](/es/docs/domains/dns-records/).

Si usabas Inbound Parse, haz que el registro MX de tu nombre de host de parse apunte a Emailit. Para conservar el mismo nombre de host, como `parse.acme.com`, establece el `inbound_key` del dominio en `parse` con la API. Consulta [Configurar el email entrante](/es/docs/inbound/set-up/).

## Próximos pasos

- [Lista de comprobación para pasar a producción](/es/docs/get-started/go-live/)
- [Configurar un webhook](/es/docs/webhooks/set-up/)
- [Migración prioritaria](/es/docs/programs/priority-migration/): deja que los ingenieros de Emailit hagan la migración contigo

---
Fuente: https://emailit.com/es/docs/migrate/sendgrid/
