xYago APIv1

Plantillas y botones

Las plantillas son los avisos que puedes enviar con POST /messages: textos por idioma con variables, hasta 3 botones y una revisión de xYago antes de usarlas en producción. Se crean en el panel (API Developer → Plantillas); por API solo se consultan (GET /templates).

Texto

Botones

Una plantilla puede tener hasta 3 botones, que aparecen bajo el mensaje en el mismo orden. Como el cuerpo, el texto del botón va por idioma (texts, con la misma forma que languages: p. ej. {"es": "Seguir pedido", "en": "Track order"}): uno por cada idioma de la plantilla, de máx. 20 caracteres, sin variables y distinto del de los demás botones. Cada mensaje muestra los botones en el mismo idioma que el cuerpo.

TipoCamposQué pasa al pulsarlo
quick_replytexts, payload (opcional, máx. 128, fijo en la plantilla)Recibes el webhook message.button_clicked con tu payload. No es un mensaje: el usuario no escribe nada y el payload nunca llega a su teléfono.
url (máx. 2)texts, urlSe abre el enlace (y recibes message.button_clicked con la URL final).

Reglas de la url: solo https://, con un nombre de dominio (no una IP), sin usuario ni contraseña y sin acortadores (bit.ly, tinyurl.com, t.co…). Puede llevar una variable {{1}} en la ruta o la query (nunca en el dominio), p. ej. https://tiendaexpress.example.com/pedidos/{{1}}. Su valor se envía en cada mensaje en button_variables, por índice del botón:

{"to": "+573005550123", "sender_id": "tiendaexpress", "template": "pedido_enviado",
 "variables": ["Valentina", "TE-48213"], "button_variables": {"0": "TE-48213"}}

El valor es texto (máx. 200 caracteres) y xYago lo codifica para la URL. Falta el valor de un botón con variable, sobra uno o no es válido → 422 invalid_button_variables.

Plantilla de ejemplo (GET /templates/{id}):

{
  "id": "d2f4a6c8-0e1b-4d3f-9a5c-7e9b1d3f5a70",
  "sender_id": "tiendaexpress",
  "name": "pedido_enviado",
  "category": "utility",
  "default_language": "es",
  "languages": {
    "es": "Hola {{1}}, tu pedido {{2}} va en camino.",
    "en": "Hi {{1}}, your order {{2}} is on its way."
  },
  "variables_count": 2,
  "buttons": [
    {
      "type": "url",
      "texts": {
        "es": "Seguir pedido",
        "en": "Track order"
      },
      "payload": null,
      "url": "https://tiendaexpress.example.com/pedidos/{{1}}"
    },
    {
      "type": "quick_reply",
      "texts": {
        "es": "No lo pedí",
        "en": "Not my order"
      },
      "payload": "order_not_mine",
      "url": null
    }
  ],
  "version": 1,
  "status": "approved",
  "review_flags": [],
  "rejection_reason": null,
  "created_at": "2026-11-03T10:00:00Z",
  "updated_at": "2026-11-03T16:45:00Z"
}

Revisión de xYago

  1. Creas la plantilla (draft) y la envías a revisión (pending_review). En sandbox ya puedes probar una en draft.
  2. Al enviarla se calculan avisos automáticos (review_flags) que ve quien la revisa y tú en el panel. No bloquean el envío a revisión, pero conviene corregirlos:
AvisoSignificado
marketing_wordsPalabras de publicidad (descuento, oferta, gratis, cupón…). Las plantillas son solo para avisos de servicio.
url_shortenerMenciona un acortador de enlaces.
too_many_variablesMás de 10 variables.
variables_adjacentDos variables seguidas sin texto entre ellas.
starts_or_ends_with_variableEl texto empieza o termina con una variable.
only_variablesEl texto es solo variables.

xYago la aprueba (approved) o la rechaza con un motivo (rejected; corrígela en el panel y vuelve a revisión). Cada paso queda en su historial en el panel y emite template.status_changed.

Versiones

Una plantilla aprobada no cambia. Si la editas se crea la versión siguiente (mismo name, version + 1) en revisión, y la aprobada se sigue usando en tus envíos hasta que xYago apruebe la nueva; entonces la anterior pasa a superseded. No hace falta cambiar nada en tu integración: envías por name.

Si xYago pausa una plantilla (p. ej. por quejas de los usuarios), los envíos con ella responden 409 template_paused hasta que la reactive.

Estados

EstadoSignificado
draftBorrador (solo sandbox).
pending_reviewEn revisión por xYago.
approvedSe puede usar en live y sandbox.
rejectedRechazada (ver rejection_reason).
pausedPausada por xYago: 409 template_paused.
supersededSustituida por una versión más nueva aprobada.

Webhook de clics

Suscríbete a message.button_clicked. Solo se avisa del primer clic de cada botón de cada mensaje. data lleva el mensaje (como en message.*, con tu reference), el botón y la hora del clic. El text del botón es el del idioma en que se envió el mensaje (button.language, igual que message.language):

{
  "created_at": "2026-03-02T15:00:04Z",
  "data": {
    "message": {
      "id": "7a1c9e35-2b4d-4f6a-8c0e-1d3f5a7b9c21",
      "status": "read",
      "to_masked": "+57 ••• ••• 0123",
      "sender_id": "tiendaexpress",
      "template": "pedido_enviado",
      "language": "es",
      "reference": "CLI-000123",
      "failure_code": null,
      "created_at": "2026-11-04T15:00:00Z",
      "sent_at": "2026-11-04T15:00:01Z",
      "delivered_at": "2026-11-04T15:02:10Z",
      "read_at": "2026-11-04T15:07:42Z",
      "expires_at": null
    },
    "button": {
      "index": 1,
      "id": "b1",
      "type": "quick_reply",
      "text": "No lo pedí",
      "language": "es",
      "payload": "order_not_mine",
      "url": null
    },
    "clicked_at": "2026-11-04T15:08:03Z"
  },
  "environment": "live",
  "id": "evt_4f9c2b7a1d3e4c5b8a6f0e1d2c3b4a59",
  "type": "message.button_clicked"
}