API y desarrolladores

Receta: Shopify (Flow)

Dispara el envío de plantilla desde Shopify Flow, sin código y sin un servidor propio.

Esta es la receta guiada del contrato genérico de Mensajes de Plantilla: el mismo POST, resuelto paso a paso desde Shopify.

Shopify no llama a esta API por su cuenta, pero Shopify Flow —la app oficial de automatización, gratuita— sí puede: se dispara con el carrito abandonado y hace el POST. Es el camino sin código y sin un servidor propio en medio.

Antes de empezar

Requisito Dónde se resuelve
Plantilla aprobada Con su nombre técnico y su language exactos — los lista GET /v1/templates.
API key Con alcance outbound:send para enviar, más outbound:read si vas a verificar el estado — ver Autenticación.
Teléfono exigido en el checkout Shopify → Settings → Checkout: Customer contact method en "Phone number or email", y Shipping address phone number en "Required". Sin teléfono en el carrito no hay a quién escribirle.
Email nativo de recuperación apagado Shopify → Marketing → Automations: si el WhatsApp toma el relevo, desactiva el "Abandoned checkout" nativo. Si no, el cliente recibe dos recordatorios del mismo carrito.

El workflow

  1. Trigger — Customer abandons checkout.
  2. Condition — abandonment.customer.defaultPhoneNumber is not empty. Un checkout sin teléfono no se puede enviar: cortarlo acá evita gastar la llamada en un 422.
  3. Action — Send HTTP request, con método POST, la URL https://api.ya.onl/v1/template-messages y dos headers: X-API-Key con tu key y Content-Type: application/json.

El cuerpo

{
  "event_id": "CART-{{ abandonment.id | split: '/' | last }}",
  "phone": "{{ abandonment.customer.defaultPhoneNumber.phoneNumber }}",
  "template": { "name": "TU_PLANTILLA", "language": "es" },
  "variables": {
    "1": "{{ abandonment.customer.firstName }}",
    "2": "{% for item in abandonment.abandonedCheckoutPayload.lineItems limit: 3 %}{{ item.quantity }}× {{ item.title | replace: '\"', '' }}{% unless forloop.last %}, {% endunless %}{% endfor %}"
  },
  "occurred_at": "{{ abandonment.createdAt }}"
}
Campo Qué hace esa línea
event_id Recorta el GID de Shopify (gid://shopify/Abandonment/774830424) a su último segmento, que respeta el charset del campo, y el prefijo CART- cubre el mínimo de 8 caracteres y da la idempotencia: si Flow reintenta, el cliente no recibe dos mensajes.
phone defaultPhoneNumber.phoneNumber ya viene en E.164 (+51987654321), que es exactamente lo que exige el campo.
template Objeto con el nombre y el idioma de tu plantilla, tal como están aprobados en Meta: reemplaza TU_PLANTILLA y ajusta language.
variables Por posición, en el orden de tu plantilla: "1" el nombre, "2" los primeros tres productos. Ajusta la cantidad a la que la plantilla exige — que falte una es un 422. El replace saca las comillas del título, que romperían el JSON.
occurred_at abandonment.createdAt ya trae offset, y es lo que activa la ventana de frescura: un abandono viejo vuelve discarded con motivo stale en vez de enviarse tarde.

La receta es genérica. El contrato es el mismo desde cualquier plataforma capaz de hacer un POST — otro ecommerce, tu propio backend o un automatizador tipo Zapier o Make. Shopify Flow es sólo el ejemplo guiado, porque resuelve el disparo del abandono sin escribir código.

Verificar que salió

curl https://api.ya.onl/v1/template-messages/CART-774830424 \
  -H "X-API-Key: yv_live_v1_tu_api_key"

Con la misma key —siempre que tenga outbound:read— y el mismo event_id que armó Flow. Un 404 significa que la llamada nunca llegó: revisa el historial de ejecuciones del workflow en Flow.

¿Necesitas ayuda?