Saltar al contenido principal

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:read para leer, validar y previsualizar, y templates:write para crear, editar e importar. Los dos son independientes: una API key con templates:write y sin templates:read no puede leer plantillas.
  • Los ejemplos usan las variables $API_HOST, $API_KEY y $SLUG de la introducción de la API, y la herramienta jq para modificar el JSON.
  • Una plantilla nace en borrador, y solo un borrador se puede editar. Las respuestas de error siguen el formato application/problem+json descrito 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:

  1. Lea la plantilla con GET /v1/mail-templates/{template_id}.
  2. Modifique su config.
  3. 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/format devuelve 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 uuid de cada fila, columna y módulo que ya existe. Un bloque nuevo necesita un uuid propio, 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:

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: rawHtml es obligatorio, no puede pasar de 100 KB (template_html_too_large) y el documento no admite otra clave que mode, rawHtml y una page vacía.
  • La sintaxis del HTML se revisa con tres advertencias que nunca impiden guardar: tag-pair, tagname-lowercase y attr-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 config con PATCH /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": "[email protected]",
"to": [{ "email": "[email protected]" }],
"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 %}.

Importante

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.