Campañas
Cree, programe y envíe campañas de email marketing con seguimiento y analíticas
Cree y gestione campañas de email marketing. MailLand se encarga de la selección de destinatarios, el envío, el seguimiento de entrega y las analíticas de interacción para cada campaña.
Ciclo de vida de una campaña
Cada campaña pasa por un flujo de estados definido:
| Estado | Valor | Descripción |
|---|---|---|
Draft | 0 | Estado inicial: editable, aún no enviada |
Scheduled | 1 | En cola para entrega futura |
Sending | 2 | Actualmente enviándose a los destinatarios |
Sent | 3 | Todos los destinatarios procesados |
Paused | 4 | Envío pausado durante la ejecución |
Cancelled | 5 | Envío cancelado |
Failed | 6 | Error del sistema durante el envío |
Transiciones permitidas:
Draft→Scheduled(programar) oSending(enviar de inmediato) oCancelled(cancelar)Scheduled→SendingoCancelled: no se admite reprogramar una campañaScheduledSending→Sent,Paused,CancelledoFailedPaused→Sending(reanudar)SentoCancelled→ archivada
Tipos de campaña
| Tipo | Valor | Descripción |
|---|---|---|
Regular | 0 | Campaña estándar de una sola vez |
Automated | 1 | Activada por automatizaciones |
ABTest | 2 | Campaña de prueba A/B |
Personalización
Los asuntos y el contenido de las campañas admiten etiquetas de fusión {{variable}}, sustituidas por destinatario a partir del propio registro de ese suscriptor.
| Etiqueta | Valor |
|---|---|
{{firstName}} | Nombre del suscriptor |
{{lastName}} | Apellido del suscriptor |
{{fullName}} | Nombre y apellido unidos |
{{email}} | Dirección de correo del suscriptor |
{{subscriberId}} | Identificador opaco del suscriptor |
{{custom_<field>}} | Cualquier campo personalizado del suscriptor, también disponible como {{<field>}} |
<p>Hi {{firstName}}, here's what's new this month.</p>Una etiqueta sin valor se deja exactamente como está escrita: {{firstName}} para un suscriptor sin nombre permanece como {{firstName}} en el correo entregado en lugar de convertirse en un espacio vacío. Escriba contenido que se lea correctamente en ambos casos, por ejemplo Hi there{{firstName}} es poco adecuado pero "Your account" es seguro. Use un saludo alternativo cuando no esté seguro de que todos los suscriptores tengan el campo.
Los valores se escapan según la parte en la que caen: el contenido HTML se escapa como HTML (de modo que un nombre con & o < no puede romper su marcado), mientras que el asunto y el cuerpo en texto plano nunca se escapan, Ben & Jerry's permanece exactamente así.
Las grafías antiguas en snake_case ({{first_name}}, {{last_name}}, {{full_name}}, {{subscriber_id}}) siguen funcionando como alias.
Crear una campaña
El workspace debe estar Business Verified antes de poder crear o actualizar una campaña: una verificación anterior y separada de la comprobación de fromEmail de abajo. Si no lo está, la solicitud falla con 400 INVALID_REQUEST ("Marketing campaigns require Business Verified status…").
El dominio de fromEmail debe estar ya agregado y completamente verificado (SPF + DKIM + DMARC) en el momento de crear y actualizar, o la solicitud es rechazada (400/404). Esta comprobación ocurre aquí, no al enviar, vea Enviar de inmediato.
POST https://api.mail.land/v1/marketing/campaigns{
"name": "February Newsletter",
"subject": "What's new in February",
"previewText": "Product updates and tips",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"replyTo": "[email protected]",
"htmlContent": "<html>...</html>",
"textContent": "Plain text version...",
"type": 0,
"mailingListId": "ddv6ou6kz4wbto",
"segmentId": "x4xa3ep1zmqq0b"
}| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | string | Sí | Nombre de la campaña |
subject | string | Sí | Asunto del correo |
previewText | string | No | Texto de vista previa en la bandeja de entrada |
fromName | string | Sí | Nombre para mostrar del remitente |
fromEmail | string | Sí | Dirección de correo del remitente |
replyTo | string | No | Dirección de respuesta |
htmlContent | string | Sí | Cuerpo del correo en HTML |
textContent | string | No | Versión en texto plano |
templateId | string | No | ID de plantilla a utilizar |
type | int | No | Tipo de campaña (predeterminado: 0 Regular) |
mailingListId | string | No* | Lista de correo de destino |
segmentId | string | No* | Segmento de destino |
* Proporcione mailingListId o segmentId: uno de los dos es obligatorio a menos que se establezca templateId.
curl -X POST https://api.mail.land/v1/marketing/campaigns \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "February Newsletter",
"subject": "What'\''s new in February",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"htmlContent": "<html><body><h1>Hello!</h1></body></html>",
"mailingListId": "ddv6ou6kz4wbto"
}'Respuesta
{
"id": "uivozyvucowj9w",
"name": "February Newsletter",
"subject": "What's new in February",
"previewText": "Product updates and tips",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"status": "draft",
"statusName": "Draft",
"type": 0,
"typeName": "Regular",
"mailingListId": "ddv6ou6kz4wbto",
"mailingListName": "Main Newsletter",
"segmentId": null,
"segmentName": null,
"createdAt": "2026-02-17T12:00:00Z",
"updatedAt": "2026-02-17T12:00:00Z"
}Listar campañas
GET https://api.mail.land/v1/marketing/campaigns| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
cursor | string | - | Cursor opaco del nextCursor de la página anterior. Omitir para la primera página. |
limit | int | 20 | Elementos por página (máx. 100) |
search | string | - | Buscar por nombre |
status | int | - | Filtrar por CampaignStatus |
type | int | - | Filtrar por CampaignType |
mailingListId | string | - | Filtrar por lista de correo |
sortBy | string | - | Campo de ordenamiento |
sortDesc | bool | false | Orden descendente |
includeArchived | bool | false | Incluir campañas archivadas |
curl "https://api.mail.land/v1/marketing/campaigns?limit=20&status=3" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"items": [
{
"id": "uivozyvucowj9w",
"name": "February Newsletter",
"subject": "What's new in February",
"status": "sent",
"statusName": "Sent",
"type": 0,
"typeName": "Regular",
"mailingListId": "ddv6ou6kz4wbto",
"mailingListName": "Main Newsletter",
"totalRecipients": 5000,
"totalSent": 4980,
"totalDelivered": 4900,
"totalOpened": 1520,
"totalClicked": 195,
"totalBounced": 45,
"totalUnsubscribed": 12,
"sentAt": "2026-02-15T10:00:00Z",
"completedAt": "2026-02-15T10:35:00Z",
"createdAt": "2026-02-14T08:00:00Z"
}
],
"nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
"hasMore": true
}Obtener detalles de una campaña
GET https://api.mail.land/v1/marketing/campaigns/{id}Devuelve el CampaignDetailDto completo, incluyendo el contenido HTML, todas las estadísticas y las tasas de interacción calculadas:
curl https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"id": "uivozyvucowj9w",
"name": "February Newsletter",
"subject": "What's new in February",
"previewText": "Product updates and tips",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"replyTo": "[email protected]",
"status": "sent",
"statusName": "Sent",
"type": 0,
"typeName": "Regular",
"htmlContent": "<html>...</html>",
"textContent": "Plain text...",
"mailingListId": "ddv6ou6kz4wbto",
"mailingListName": "Main Newsletter",
"totalRecipients": 5000,
"totalSent": 4980,
"totalDelivered": 4900,
"totalOpened": 1520,
"totalClicked": 195,
"totalBounced": 45,
"totalUnsubscribed": 12,
"totalComplaints": 2,
"deliveryRate": 98.39,
"openRate": 31.02,
"clickRate": 3.98,
"clickToOpenRate": 12.83,
"bounceRate": 0.9,
"unsubscribeRate": 0.24,
"openTrackingEnabled": true,
"clickTrackingEnabled": true,
"sentAt": "2026-02-15T10:00:00Z",
"completedAt": "2026-02-15T10:35:00Z",
"createdAt": "2026-02-14T08:00:00Z",
"updatedAt": "2026-02-15T10:35:00Z"
}Tasas de interacción
| Tasa | Fórmula |
|---|---|
deliveryRate | totalDelivered / totalSent * 100 |
openRate | totalOpened / totalDelivered * 100 |
clickRate | totalClicked / totalDelivered * 100 |
clickToOpenRate | totalClicked / totalOpened * 100 |
bounceRate | totalBounced / totalSent * 100 |
unsubscribeRate | totalUnsubscribed / totalDelivered * 100 |
Las tasas se calculan en el servidor a partir de los contadores en bruto (las aperturas y los clics son únicos por destinatario). deliveryRate y bounceRate son tasas sobre lo enviado; openRate, clickRate y unsubscribeRate son tasas sobre lo entregado; clickToOpenRate (CTOR) es clics sobre aperturas y es una métrica distinta de clickRate. Una tasa es un porcentaje sin tope (clickToOpenRate puede superar 100) y es null, nunca 0, cuando no está disponible: su denominador es 0 o la cuenta tiene desactivado el seguimiento necesario (openTrackingEnabled / clickTrackingEnabled muestran el ajuste actual). Para combinar campañas, sume los contadores y divida una sola vez; no promedie porcentajes. La lista devuelve los mismos campos para cada campaña.
Actualizar una campaña
PUT https://api.mail.land/v1/marketing/campaigns/{id}Solo se pueden actualizar las campañas en estado Draft o Scheduled. El cuerpo de la solicitud coincide con el de creación, excepto type, que no se puede cambiar.
| Estado | Código | Descripción |
|---|---|---|
200 | - | Campaña actualizada |
400 | INVALID_REQUEST | Solo se pueden editar campañas en borrador |
404 | RESOURCE_NOT_FOUND | Campaña no encontrada |
curl -X PUT https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "February Newsletter (Updated)",
"subject": "What'\''s new in February - updated",
"fromName": "MailLand Team",
"fromEmail": "[email protected]",
"htmlContent": "<html><body><h1>Updated!</h1></body></html>",
"mailingListId": "ddv6ou6kz4wbto"
}'Programar una campaña
POST https://api.mail.land/v1/marketing/campaigns/{id}/schedule{
"scheduledAt": "2026-02-20T14:00:00Z"
}El tiempo scheduledAt debe ser en el futuro. El estado de la campaña cambia a Scheduled y el CampaignWorker la procesa a la hora programada.
La programación solo está permitida desde el estado Draft: una campaña que ya está Scheduled no se puede reprogramar mediante este endpoint.
| Estado | Código | Descripción |
|---|---|---|
200 | - | Campaña programada |
400 | VALIDATION_FAILED | La hora programada debe ser en el futuro |
404 | RESOURCE_NOT_FOUND | Campaña no encontrada o no se puede programar |
403 | MARKETING_NOT_YET_ALLOWED | El marketing aún no está abierto para la cuenta (consulte Códigos de error); /send también lo devuelve |
403 | MARKETING_SUSPENDED | El marketing no está disponible en toda la plataforma; /send también lo devuelve |
422 | CAMPAIGN_LINK_BLOCKED | Un enlace de la campaña apunta a un destino marcado como inseguro; /send también lo devuelve. No se programa ni se envía nada |
curl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/schedule \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{ "scheduledAt": "2026-02-20T14:00:00Z" }'Enviar inmediatamente
POST https://api.mail.land/v1/marketing/campaigns/{id}/sendEnvía la campaña de inmediato. El estado de la campaña pasa a Sending y el CampaignWorker comienza a procesar los destinatarios.
/send en sí no comprueba la verificación del dominio: esa comprobación ocurre al crear/actualizar (vea Crear una campaña). /send devuelve 422 CAMPAIGN_NO_ELIGIBLE_RECIPIENTS si nadie en la lista/segmento de destino es elegible para recibir la campaña (por ejemplo, si todos están suprimidos o dados de baja).
curl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/send \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Pausar y reanudar
Pausar una campaña que se está enviando:
POST https://api.mail.land/v1/marketing/campaigns/{id}/pausecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/pause \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Reanudar una campaña pausada:
POST https://api.mail.land/v1/marketing/campaigns/{id}/resumecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/resume \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Pausar detiene el procesamiento de destinatarios restantes por el CampaignWorker. Los correos ya enviados no se ven afectados. Al reanudar, el proceso continúa desde donde se dejó.
Cancelar una campaña
POST https://api.mail.land/v1/marketing/campaigns/{id}/cancelCancela una campaña en estado Draft, Scheduled o Sending. Los correos ya enviados no se recuperan.
curl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/cancel \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Duplicar una campaña
POST https://api.mail.land/v1/marketing/campaigns/{id}/duplicate?name=Copy%20of%20NewsletterCrea una nueva campaña en estado Draft con todos los ajustes copiados del original. El parámetro de consulta name es opcional.
curl -X POST "https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/duplicate?name=Copy%20of%20Newsletter" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Archivar y desarchivar
Archivar una campaña en estado Sent o Cancelled:
POST https://api.mail.land/v1/marketing/campaigns/{id}/archivecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/archive \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Desarchivar una campaña archivada:
POST https://api.mail.land/v1/marketing/campaigns/{id}/unarchivecurl -X POST https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/unarchive \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Las campañas archivadas se ocultan de la vista de lista predeterminada a menos que se pase includeArchived=true.
Destinatarios de la campaña
Obtener destinatarios paginados con estado de entrega para una campaña:
GET https://api.mail.land/v1/marketing/campaigns/{id}/recipients| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
cursor | string | - | Cursor opaco del nextCursor de la página anterior. Omitir para la primera página. |
limit | int | 20 | Elementos por página (máx. 100) |
status | string | - | Filtrar por estado del destinatario |
search | string | - | Buscar por correo electrónico |
curl "https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w/recipients?limit=20" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."{
"items": [
{
"email": "[email protected]",
"status": "Opened",
"sentAt": "2026-02-15T10:00:30Z",
"deliveredAt": "2026-02-15T10:00:32Z",
"openedAt": "2026-02-15T11:15:00Z",
"clickedAt": "2026-02-15T11:16:30Z",
"bouncedAt": null,
"complainedAt": null,
"unsubscribedAt": null,
"openCount": 2,
"clickCount": 1,
"bounceReason": null
}
],
"nextCursor": "eyJ2IjoxLCJzIjoiY3JlYXRlZGF0OmRlc2MiLCJrIjoi...",
"hasMore": true
}Estados de los destinatarios
| Estado | Valor | Descripción |
|---|---|---|
Pending | 0 | En cola, aún no enviado |
Sent | 1 | Aceptado por el MTA |
Delivered | 2 | Entregado al destinatario |
Opened | 3 | El destinatario lo abrió |
Clicked | 4 | El destinatario hizo clic en un enlace |
Bounced | 5 | Rebote permanente |
Unsubscribed | 6 | El destinatario se dio de baja |
Complained | 7 | Queja de spam |
Failed | 8 | Entrega fallida |
openedAt/openCount y clickedAt/clickCount incluyen actividad de máquinas, la precarga de Apple Mail Privacy Protection y los escáneres de enlaces de seguridad, que MailLand no filtra hoy. Trate las tasas derivadas de aperturas/clics como un límite superior, no como una cifra precisa de interacción humana.
Eliminar una campaña
DELETE https://api.mail.land/v1/marketing/campaigns/{id}Elimina permanentemente una campaña y sus datos de destinatarios. Solo se pueden eliminar campañas en estado Draft o Scheduled; eliminar cualquier otro estado devuelve 404: archive una campaña enviada en su lugar.
curl -X DELETE https://api.mail.land/v1/marketing/campaigns/uivozyvucowj9w \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Respuestas de error
| Estado | Código | Descripción |
|---|---|---|
400 | VALIDATION_FAILED | Campos requeridos faltantes |
400 | INVALID_REQUEST | Solo se pueden editar campañas en borrador |
403 | FORBIDDEN | Permisos insuficientes |
404 | RESOURCE_NOT_FOUND | Campaña no encontrada |
Próximos pasos
- Suscriptores: gestione sus contactos suscriptores
- Listas: organice suscriptores en listas de correo
- Segmentos: dirija campañas con segmentos dinámicos
- Automatizaciones: configure secuencias de correo basadas en disparadores