API de pedidos (conexión genérica)

El endpoint HTTP que registra un pedido —o un carrito que alguien empieza a pagar— desde cualquier herramienta. Contrato exacto, referencia de campos, respuestas, catálogo de errores 422 y qué nivel de contacto crea cada payload.

Ver .md Actualizado 2026-09-11
En esta página

La conexión genérica es un solo endpoint HTTP que convierte un pedido de cualquier herramienta —Zapier, Make, un módulo de webhooks o tu propio código— en una conversión registrada y, cuando el teléfono es reconocible, en un contacto con su nivel de consentimiento.

Encontrarás tu URL exacta en la app, en Ajustes → Integraciones → Conexión genérica.

El endpoint

POST https://app.konverda.com/webhooks/orders/<tu-token>
Content-Type: application/json

Payload

Solo order_ref es obligatorio. Todo lo demás es opcional y mejora lo que la plataforma puede hacer con el pedido.

{
  "order_ref": "pedido-1234",
  "status": "paid",
  "occurred_at": "2026-07-12T10:00:00Z",
  "total": 49.9,
  "currency": "EUR",
  "customer": {
    "phone": "+34 612 345 678",
    "name": "Ana Pérez",
    "email": "ana@example.com"
  },
  "consent": true,
  "items": [
    { "id": "SKU-9", "name": "Curso X", "quantity": 1, "total": 49.9 }
  ],
  "tags": ["cliente"]
}

Referencia de campos

CampoTipoDescripción
order_reftexto o número · obligatorioReferencia única del pedido en tu plataforma (máx. 120 caracteres). Es la clave de deduplicación: reenviar el mismo order_ref nunca duplica la venta.
status'paid' | 'refunded'Por defecto 'paid'. 'refunded' registra un reembolso del mismo pedido.
occurred_atfecha ISO 8601 · opcionalCuándo ocurrió. Sin él se usa el momento de recepción.
totalnúmero · opcionalImporte total del pedido. Acepta también texto numérico ("49.90").
currency3 letras · opcionalPor defecto EUR.
customerobjeto · opcionalContenedor de los datos del cliente: phone, name, email.
customer.phonetexto · opcionalTeléfono WhatsApp del cliente. Sin él (o si no es reconocible) la venta se registra igualmente, pero SIN contacto — aparece en «Conversiones sin contacto».
customer.nametexto · opcionalNombre del cliente.
customer.emailtexto · opcionalSe acepta pero NUNCA se guarda — el email vive en tu herramienta de email. Se borra también del registro técnico de la petición.
consentbooleano estricto (true / false) · opcionalLa casilla de consentimiento de tu checkout. DECIDE EL NIVEL DEL CONTACTO — ver Consentimiento. Ojo: aquí NO se acepta "true" entre comillas ni 1; un valor que no sea booleano devuelve 422 bad_consent.
items[]lista · opcionalMáx. 100 artículos: { id, name, quantity, total }. Cada uno necesita al menos id o name. Alimentan el Catálogo y las automatizaciones por producto.
tags[]lista de texto · opcionalMáx. 20 etiquetas a aplicar al contacto.
tokentexto · opcionalEl parámetro wtk que los enlaces enviados añaden a la URL de destino (máx. 64 caracteres). Si el pedido no trae teléfono utilizable pero sí este token, la venta se vincula al contacto que recibió el enlace (aparece como «vía enlace»).
cart_reftexto o número · opcionalEn un pedido: el carrito que este pago cierra (máx. 120 caracteres), el mismo cart_ref que enviaste al empezar el pago. Sin él, el pedido cierra igualmente los carritos abiertos de ese contacto. En un carrito es obligatorio — ver Carritos.
event'checkout.started' · opcionalSin él, el payload es un pedido. Con "checkout.started" es un carrito que alguien ha empezado a pagar — ver Carritos. Cualquier otro valor devuelve 422 bad_event.
recovery_urlURL https o http · solo en carritosEl enlace que reabre ese carrito en tu tienda. En un pedido se ignora.

Probarlo con curl

curl -X POST 'https://app.konverda.com/webhooks/orders/<tu-token>' \
  -H 'Content-Type: application/json' \
  -d '{
    "order_ref": "prueba-1",
    "total": 49.9,
    "customer": { "phone": "+34612345678", "name": "Ana Pérez" },
    "consent": true,
    "items": [{ "id": "SKU-9", "name": "Curso X", "quantity": 1, "total": 49.9 }]
  }'

Una respuesta correcta es {"ok":true,"matched":true}. La venta aparece en Ajustes → Integraciones → Catálogo y, si el teléfono es reconocible, en la ficha del contacto.

Respuestas

CódigoCuerpoSignificado
200{"ok":true,"matched":true}Registrado y vinculado a un contacto.
200{"ok":true,"matched":false}Registrado SIN contacto (teléfono ausente o irreconocible) — visible en «Conversiones sin contacto».
200{"ok":true,"duplicate":true}Ese order_ref ya estaba registrado. Reenviar es seguro.
200{"ok":true,"recorded":false,"reason":"no_consent"}consent:false y el teléfono no corresponde a un contacto ya dado de alta — no se crea ningún perfil. Es un 200 a propósito: reintentar nunca cambiaría el resultado.
404{"error":"not_found"}URL desconocida o conexión desactivada. Ambas responden igual: un 404 no revela si el token existe.
422{"error":"invalid_payload","details":[…]}Payload inválido; details lleva los códigos de error por campo.
429{"error":"rate_limited"}Más de 60 peticiones por minuto y por IP — espera y reintenta.
500{"error":"ingest_error"}Error interno; reintenta más tarde (la deduplicación por order_ref hace el reintento seguro).

Catálogo de errores del 422

details es una lista de códigos, uno por problema encontrado. La petición se rechaza entera: no se registra nada parcialmente.

CódigoQué lo provoca
missing_order_refFalta order_ref (o llega null).
bad_order_reforder_ref no es texto ni número, está vacío o pasa de 120 caracteres.
bad_statusstatus no es 'paid' ni 'refunded'.
bad_occurred_atoccurred_at no es texto o no es una fecha interpretable.
bad_totaltotal no se puede leer como número.
bad_currencycurrency no son exactamente 3 letras.
bad_customercustomer no es un objeto (llegó como texto o como lista).
bad_consentconsent no es booleano. "true", "1" y 1 se rechazan aquí a propósito: el consentimiento no se adivina.
bad_itemsitems no es una lista, pasa de 100, o algún artículo no trae ni id ni name (o trae quantity/total no numéricos).
bad_tagstags no es una lista de textos o pasa de 20.
bad_tokentoken no es texto o pasa de 64 caracteres.

Consentimiento: qué nivel de contacto crea cada payload

Desde el 25 de agosto de 2026 un contacto tiene DOS niveles posibles, y el campo consent de tu payload decide cuál.

  • «Marketing» = aceptó recibir envíos: campañas, oleadas, automatizaciones proactivas y plantillas 1
    .
  • «No» = solo podemos responderle cuando escribe él.

No es un matiz de informe: un contacto de nivel «No» no recibe NINGÚN mensaje que iniciemos nosotros — ni siquiera una plantilla de utilidad, ni la automatización de bienvenida. El intento queda registrado como not_marketing y no se envía.

Lo que envíasBase registradaOpt-in resultanteQué puede recibir
consent: truecheckboxMarketingTodo: campañas, oleadas, automatizaciones proactivas (order.paid incluida) y plantillas 1
. Además, al ser un acto explícito del propio cliente, levanta una baja anterior.
consent ausentepurchaseNoSolo respuestas cuando la persona escribe. La automatización de order.paid NO se envía. Una baja anterior se respeta siempre.
consent: false— (no se registra alta)Sin cambiosLa venta se registra SOLO si el teléfono ya era un contacto dado de alta; si no, no se crea ningún perfil y la respuesta lo dice (recorded:false).

Carritos: checkout.started

La misma URL registra también un carrito: el momento en que alguien empieza a pagar en tu tienda. Si no termina la compra en el tiempo que marques en Ajustes → Reglas (45 minutos si no lo cambias), Konverda lo da por abandonado y se inicia el flujo que tengas con el disparador Carrito abandonado. Lo que ve el cliente, el consentimiento que exige y las protecciones están en Carrito abandonado.

{
  "event": "checkout.started",
  "cart_ref": "carrito-5678",
  "recovery_url": "https://tu-tienda.com/carrito/recuperar/5678",
  "occurred_at": "2026-09-11T10:00:00Z",
  "total": 79.9,
  "currency": "EUR",
  "customer": {
    "phone": "+34 612 345 678",
    "email": "ana@example.com"
  },
  "items": [
    { "id": "SKU-9", "name": "Curso X", "quantity": 1, "total": 49.9 },
    { "id": "SKU-12", "name": "Libro del curso", "quantity": 1, "total": 30 }
  ]
}

Campos del carrito

CampoTipoDescripción
event'checkout.started' · obligatorioLo que convierte el payload en un carrito.
cart_reftexto o número · obligatorioEl identificador del carrito en tu tienda (máx. 120 caracteres). Reenviar el mismo cart_ref actualiza ese carrito y vuelve a empezar su cuenta atrás: nunca crea un segundo carrito ni un segundo aviso.
recovery_urlURL https o http · obligatorioEl enlace que reabre el carrito (máx. 2048 caracteres). Konverda nunca lo envía tal cual: lo convierte en un enlace con seguimiento, con sus UTM.
customer.phonetexto · opcionalPara encontrar al contacto. Mismo formato que en los pedidos.
customer.emailtexto · opcionalPara encontrar al contacto si el teléfono no basta. En un carrito sin contacto se guarda solo mientras el carrito está abierto —la casilla puede llegar un instante después— y se borra en cuanto se cierra.
items[]lista · opcionalComo en los pedidos. El primer artículo con nombre y el número de unidades se pueden poner en el mensaje.
totalnúmero · opcionalEl importe del carrito. Se puede poner en el mensaje con el formato de tu moneda («79,90 €»).
currency3 letras · opcionalPor defecto EUR.
occurred_atfecha ISO 8601 · opcionalCuándo empezó el pago. La cuenta atrás empieza al recibirlo, no en esta fecha.

status, consent, token y tags se ignoran en un carrito.

Respuestas del carrito

CódigoCuerpoSignificado
200{"ok":true,"matched":true,"armed":true}Carrito registrado, contacto encontrado, cuenta atrás en marcha.
200{"ok":true,"matched":false,"armed":true}Registrado sin contacto todavía. Se vuelve a buscar cuando termina la cuenta atrás; si sigue sin haber nadie, el carrito se cierra sin mensaje.
200{"ok":true,"matched":…,"armed":false}Ese carrito ya estaba cerrado (comprado, recordado o descartado). El reenvío no cambia nada.

404, 429 y 500 significan lo mismo que en los pedidos.

Errores del carrito

CódigoQué lo provoca
bad_eventevent trae un valor que no es "checkout.started".
missing_cart_refFalta cart_ref.
bad_cart_refcart_ref no es texto ni número, está vacío o pasa de 120 caracteres.
missing_recovery_urlFalta recovery_url.
bad_recovery_urlrecovery_url no es una dirección https/http válida o pasa de 2048 caracteres.
bad_occurred_atoccurred_at no es una fecha interpretable.
bad_totaltotal no se puede leer como número.
bad_currencycurrency no son exactamente 3 letras.
bad_customercustomer no es un objeto.
bad_itemsitems no es una lista válida (mismas reglas que en los pedidos).

Cerrar el carrito al pagar

Cuando la compra se completa, envía el pedido normal a esta misma URL. Si lleva el cart_ref del carrito, cierra ese carrito exactamente; si no, cierra los carritos abiertos de ese contacto. Además, justo antes de enviar el recordatorio, Konverda comprueba si esa persona ha comprado desde que empezó el carrito —por cualquier conexión, también Stripe o WooCommerce—, y si ha comprado no envía nada.

Seguir leyendo

¿No lo has resuelto? Contactar soporte