Plantillas por API
Para desarrolladores
Con una API key se puede crear una plantilla, cambiar su diseño, validarlo y ver el correo que resultaría, sin abrir el panel. Es el camino de una integración que arma o ajusta sus correos por su cuenta.
Esta página recorre ese trabajo de principio a fin. Cada endpoint tiene su ficha con todos los campos y errores, y la estructura del documento de una plantilla está en Formato de plantillas. Para que un asistente de IA edite plantillas, vea Plantillas con un asistente de IA.
Antes de empezar
- La API key necesita el scope
templates:readpara leer, validar y previsualizar, ytemplates:writepara crear, editar e importar. Los dos son independientes: una API key contemplates:writey sintemplates:readno puede leer plantillas. - Los ejemplos usan las variables
$API_HOST,$API_KEYy$SLUGde la introducción de la API, y la herramientajqpara modificar el JSON. - Una plantilla nace en borrador, y solo un borrador se puede editar. Las respuestas de error siguen el formato
application/problem+jsondescrito en Errores.
El ciclo de edición
El diseño de una plantilla es un documento JSON que la API devuelve en el campo config. Se trabaja siempre completo, en tres pasos:
- Lea la plantilla con
GET /v1/mail-templates/{template_id}. - Modifique su
config. - Envíe el documento completo con
PATCH /v1/mail-templates/{template_id}.
El documento se envía tal como lo devolvió la lectura, con sus cambios. Un campo que se omite no conserva su valor anterior: se guarda con su valor por defecto, el que declara el schema de GET /v1/mail-templates/format. Por eso el ciclo parte siempre de la lectura: así conserva lo que no quiere cambiar.
Una propiedad que hereda (el color de un texto, la fuente) y que el documento omite sigue heredando de su fila o de la página.
Para una plantilla nueva, el punto de partida es una plantilla de la biblioteca, una propia o un HTML importado.
Conocer el documento
La especificación del documento está publicada en Formato de plantillas, y la API la entrega con dos consultas de solo lectura:
GET /v1/mail-templates/formatdevuelve la especificación (format), su JSON Schema (schema) con el tipo y el valor por defecto de cada campo, y la lista de tipos de módulo. A pedido (include=skeleton) suma un ejemplo del anidamiento.GET /v1/mail-templates/format/modules/{kind}devuelve el formato de un tipo de módulo, con un módulo completo de ejemplo, para armar o cambiar un bloque.
Para ver un documento completo real, GET /v1/template-catalog/{category}/{name} devuelve una plantilla de la biblioteca sin copiarla.
curl "https://$API_HOST/v1/mail-templates/format/modules/button" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG"
Crear una plantilla
POST /v1/mail-templates recibe el nombre y, opcionalmente, el asunto, el preheader y el diseño. El diseño puede venir de tres lugares:
- La biblioteca, con
catalog_slug. Es el punto de partida más simple; ver Partir de la biblioteca. - Un documento completo, en
config, por ejemplo el de otra plantilla que ya leyó. - Ninguno: la plantilla se crea solo con el nombre y el diseño se agrega después.
La respuesta es 201 Created, con la plantilla en borrador, su id y el header Location. Un documento con errores responde 422 con todos los errores a la vez, cada uno con su puntero.
Partir de la biblioteca
GET /v1/template-catalog lista las plantillas de la biblioteca, cada una con su identificador (slug) y su miniatura, y GET /v1/template-catalog/{category}/{name} muestra el documento completo de una sin copiarla. Para crear una plantilla a partir de una, envíe su identificador en catalog_slug:
curl -X POST "https://$API_HOST/v1/mail-templates" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
-H "Content-Type: application/json" \
-d '{"name": "Black Friday 2026", "subject": "Ofertas de fin de semana", "catalog_slug": "holidays/black-friday"}'
La copia es suya y se edita como cualquier otra plantilla. Revise los findings de la respuesta: una plantilla de la biblioteca puede traer advertencias, por ejemplo un botón sin enlace, que se resuelven con los datos de su campaña.
Leer y modificar el documento
GET /v1/mail-templates/{template_id} devuelve la plantilla con su diseño en config. Guárdelo en un archivo para modificarlo:
curl -s "https://$API_HOST/v1/mail-templates/41" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
| jq '.config' > config.json
El documento está formado por filas, columnas y módulos, cada uno con su uuid; la estructura y las propiedades de cada tipo de módulo están en Formato de plantillas y en GET /v1/mail-templates/format/modules/{kind}. Por ejemplo, para cambiar el texto del primer botón del documento:
jq '(first(.. | objects | select(.type? == "fidelizador-modules-button")) | .descriptor.button.label) = "Entrar a mi cuenta"' \
config.json > config-nuevo.json
- Conserve el
uuidde cada fila, columna y módulo que ya existe. Un bloque nuevo necesita unuuidpropio, distinto de todos los demás del documento, y al copiar un bloque la copia y todo lo que contiene necesitan identificadores nuevos. - Cambie solo lo necesario y deje el resto del documento como lo devolvió la lectura.
Validar y previsualizar
Dos endpoints revisan un documento completo sin guardar nada y sin que exista una plantilla:
POST /v1/mail-templates/validatedevuelve si el documento es válido y cada hallazgo, con su nivel (errorowarning), su ubicación y cómo corregirlo.POST /v1/mail-templates/previewdevuelve el HTML que recibiría el destinatario. Un documento con errores responde422.
jq '{config: .}' config-nuevo.json \
| curl -X POST "https://$API_HOST/v1/mail-templates/validate" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
-H "Content-Type: application/json" \
--data-binary @-
Si al documento le faltan los enlaces especiales que todo correo lleva, la respuesta lo advierte (abreviada a una advertencia):
{
"valid": true,
"findings": [
{
"level": "warning",
"code": "missing_special_link",
"message": "The email has no `fide:unsubscribe` link.",
"path": "/page",
"fix": "Add a link to `fide:unsubscribe`, usually in the footer.",
"uuid": null,
"line": null,
"column": null
}
]
}
Un error impide guardar; una advertencia no. Las advertencias también llegan en el campo findings de la respuesta al guardar. message y fix vienen en inglés.
Enviar el documento completo
PATCH /v1/mail-templates/{template_id} reemplaza el diseño entero cuando recibe config, y cambia además el nombre, el asunto, el preheader o la descripción que vengan en el cuerpo. Solo cambian los campos enviados.
jq '{config: .}' config-nuevo.json \
| curl -X PATCH "https://$API_HOST/v1/mail-templates/41" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
-H "Content-Type: application/json" \
--data-binary @-
La respuesta trae la plantilla guardada, con el HTML que se generó a partir del documento y las advertencias en findings. El cuerpo puede incluir también los campos que devolvió la lectura, como id o status: se ignoran.
El campo essential no se acepta en ningún cuerpo de esta API: una petición que lo trae responde 422 con el código essential_not_supported.
Importar HTML
POST /v1/mail-templates/html-import convierte el HTML de una campaña en un documento editable por bloques, sin guardar nada. El resultado viene en config, con los valores por defecto escritos, junto con:
- el preheader que se detectó;
- lo que se descartó: manejadores de eventos, enlaces que ejecutan código y elementos que los clientes de correo no muestran;
- lo que la validación dice del documento resultante (
findings).
La conversión es aproximada: revise el resultado con la vista previa antes de guardarlo. Para guardarlo, envíe ese config a POST /v1/mail-templates y el preheader en preheader, si lo quiere conservar.
Modo HTML crudo
Para conservar un HTML exactamente como está, créelo en modo HTML crudo, en config:
curl -X POST "https://$API_HOST/v1/mail-templates" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
-H "Content-Type: application/json" \
-d '{"name": "Mi HTML", "config": {"mode": "html", "rawHtml": "<html><body><p>Hola</p><a href=\"fide:unsubscribe\">Darse de baja</a></body></html>", "page": {"rows": []}}}'
- El HTML se guarda tal cual, salvo el preheader, que se inserta o se reemplaza.
- Se revisa su forma, y un error en ella impide guardar:
rawHtmles obligatorio, no puede pasar de 100 KB (template_html_too_large) y el documento no admite otra clave quemode,rawHtmly unapagevacía. - La sintaxis del HTML se revisa con tres advertencias que nunca impiden guardar:
tag-pair,tagname-lowercaseyattr-no-duplication, cada una con su línea y columna. - El contenido no se revisa: es responsabilidad de quien lo escribe.
- Para cambiarlo, envíe el HTML completo en
configconPATCH /v1/mail-templates/{template_id}. En el panel no se abre en el editor visual.
Personalizar un envío
Una plantilla puede llevar etiquetas {{CLAVE}} y {{ CLAVE | default: "respaldo" }} en el asunto, en sus textos y en sus enlaces, incluso como dirección completa, además de bloques {% if %} y {% for %} y filtros de formato como currency. El lenguaje es Liquid, y su sintaxis está en Formato de plantillas.
Una plantilla que no es Liquid válido no se guarda: la respuesta es 422 con template_syntax_error.
Para ver cómo queda con unos valores, envíelos en vars a POST /v1/mail-templates/preview, o guárdelos en sampleValues y omita vars.
Un bloque que cubre una fila entera del diseño se escribe en la propia fila: "if": "PUNTOS > 1000" la muestra solo cuando se cumple la condición, y "for": "item in PEDIDO.items" la repite por cada elemento. Una fila del módulo tabla también acepta for, para un comprobante con un ítem por fila.
Al enviar la plantilla, el campo vars de POST /v1/mails/send trae los valores, iguales para todos los destinatarios del mensaje:
{
"sender_email": "citas@example.com",
"to": [{ "email": "ana@example.com" }],
"template_id": 42,
"vars": {
"NOMBRE": "Ana",
"HORA": "jueves 23 de octubre, 10:30",
"SERVICIOS": [{ "nombre": "Control", "precio": 15990 }]
}
}
Un valor puede ser texto, número, booleano, lista u objeto. Una lista se recorre con {% for servicio in SERVICIOS %}.
Envíe los números como números. Las comparaciones son las de Liquid: un número que llega como texto ("1500") no se compara con un número, y ese destinatario no recibe el correo.
Una etiqueta sin valor toma su respaldo o queda vacía, y {{EMAIL}} es la dirección de quien recibe. Para que cada persona reciba sus propios datos, envíe un mensaje por persona.
Lo que se hace desde el panel
Publicar, despublicar y eliminar una plantilla se hace desde el panel. Una plantilla publicada se usa en un envío indicando su template_id en POST /v1/mails/send. Una plantilla publicada no se puede editar por API: para cambiarla, despublíquela primero.