Venflow API

Metadata

Metadata

Casi todos los objetos de la API tienen un campo metadata: un espacio donde guardas tu propia información, con las claves y los valores que tú decidas.

Sirve para atar un objeto de Venflow con algo de tu sistema. El número de pedido de tu tienda, el identificador del cliente en tu CRM, el vendedor que cerró la venta, la sucursal.

{
  "metadata": {
    "pedido": "A-2291",
    "vendedor": "Ana Pérez",
    "sucursal": "Maracay"
  }
}

Cuando después leas ese cliente, esa suscripción o esa factura, la metadata vuelve exactamente como la guardaste.

Qué NO hace

Esto es tan importante como lo anterior:

  • Venflow no la interpreta. No cambia ningún comportamiento. Guardar {"descuento": "50"} no aplica ningún descuento.
  • No la valida. Si escribes mal una clave, se guarda mal escrita.
  • Casi nunca la copia entre objetos. La metadata de una sesión de checkout no pasa a la suscripción ni a la factura que nazcan de ella. Cada objeto lleva la suya. La única excepción es el payment link, y está explicada abajo en Del payment link a la sesión.
  • No se puede buscar ni filtrar por ella desde la API. En el dashboard, la lista de clientes sí la busca. Ver Buscar por metadata.

En qué objetos vive

ObjetoCómo la escribes
ClientePOST /v1/customers · PATCH /v1/customers/{id}
SuscripciónPATCH /v1/subscriptions/{id}
FacturaPATCH /v1/invoices/{id}
Payment linkPOST /v1/payment-links · PATCH /v1/payment-links/{id}
Sesión de checkoutPOST /v1/checkout/sessions
PagoPATCH /v1/payments/{id}

La suscripción, la factura y el pago no se crean por API: nacen del checkout y del motor de cobros. Por eso solo tienen PATCH.

El PATCH de una factura y el de un pago solo tocan su metadata. Los importes, el estado y el calendario de cobro los gobierna el motor y no se editan desde la API.

Cómo se escribe: se combina, no se reemplaza

Un PATCH fusiona lo que mandas con lo que ya estaba guardado. Las claves que no menciones se quedan como estaban.

Partiendo de esto:

{ "pedido": "A-2291", "vendedor": "Ana Pérez" }

Mandas:

{ "metadata": { "vendedor": "Luis Salazar", "sucursal": "Maracay" } }

Y queda:

{ "pedido": "A-2291", "vendedor": "Luis Salazar", "sucursal": "Maracay" }

pedido sigue ahí aunque no lo mencionaste. vendedor se actualizó. sucursal es nueva.

Si no mandas el campo metadata en absoluto, la metadata no se toca.

Cómo se borra

Hay dos formas, y hacen cosas distintas:

MandasQué pasa
{"metadata": {"vendedor": null}}Borra esa clave. El resto se queda.
{"metadata": {}}Borra todas las claves.
(no mandas metadata)No se toca nada.

Ojo con la diferencia entre las dos primeras: {} no significa "no cambies nada", significa "déjalo vacío".

Para borrar un valor no mandes cadena vacía. {"vendedor": ""} guarda una clave con valor vacío; {"vendedor": null} la elimina.

Los límites

LímiteValor
Claves por objeto50
Longitud de una clave40 caracteres
Longitud de un valor500 caracteres
Total de todas las claves y valores27.000 caracteres

Los cuatro se cuentan en caracteres, no en bytes: una "ñ" o una tilde cuentan igual que cualquier otra letra.

Los límites se comprueban sobre el resultado, no sobre lo que mandas. Si ya tienes 50 claves guardadas, un PATCH que añada una más se rechaza aunque el cuerpo del PATCH traiga una sola.

Reglas de las claves y los valores

  • Los valores son texto. Nada de números, booleanos, listas ni objetos anidados. Si necesitas guardar un número, mándalo como texto: "cantidad": "3".
  • Las claves no pueden llevar corchetes ([ ni ]).

Buscar por metadata

Desde la API: no

La API no busca ni filtra por metadata. No existe algo como GET /v1/customers?metadata[pedido]=A-2291.

Si tu integración necesita encontrar un objeto a partir de un dato tuyo, guarda tú la relación en tu sistema: cuando crees el cliente en Venflow, apunta su id junto a tu número de pedido. Desde la API, la metadata sirve para leer tu dato cuando ya tienes el objeto, no para llegar hasta él.

En el dashboard: la lista de clientes

El buscador de la lista de Clientes también busca en la metadata de cada cliente, sin dejar de buscar por nombre, email, documento y empresa. Usa la misma forma de escribir que el buscador de Stripe. Por ahora es solo la lista de clientes: las de suscripciones, facturas, pagos y enlaces de pago no buscan en la metadata.

EscribesEncuentra
A-2291Clientes con "A-2291" en su nombre, email, documento, empresa o en algún valor de su metadata
mariana salTodas las palabras dentro de un mismo dato: "Mariana Salazar", pero no un Pedro Salazar que tenga "Mariana" en su metadata
pediClientes con alguna clave que empieza con "pedi" (pedido, pedido ab…), desde 3 letras
pedido:A-2291La clave pedido con un valor que contiene "A-2291"
vendedor:Ana PérezEl valor puede llevar espacios sin comillas: llega hasta el siguiente filtro. Sus palabras valen en cualquier orden
vendedor:"Ana Pérez"Con comillas, las palabras juntas y en ese orden
vendedor:Clientes que tienen la clave vendedor, con cualquier valor
vendedor:""Clientes que tienen la clave vendedor vacía
metadata:whatsappCualquier clave cuyo valor contenga "whatsapp"
metadata:canal=whatsappLa forma larga de canal:whatsapp
name:ana · email:gmailSolo en el nombre, o solo en el email
-canal:emailExcluye a los clientes que cumplen el filtro
"ana pérez"La frase tal cual, con las palabras juntas y en ese orden

Cómo se comporta:

  • Mayúsculas y tildes: no importan, ni en los valores ni en el nombre de la clave: perez encuentra a "Pérez", la ñ cuenta como n, y canal: encuentra la clave Canal. Si tienes dos claves que solo se diferencian en eso (Pedido y pedido), escríbela exactamente igual para elegir una.
  • Palabras cortas: si buscas una sola palabra de menos de 3 letras, no se busca dentro de los valores de metadata, porque está en casi todos. Sí se busca en el nombre, el email y el documento. Junto a otras palabras sí cuenta.
  • Comillas sin cerrar: si las comillas no cuadran, se ignoran todas y se busca lo demás.
  • Orden: primero salen los clientes cuyo nombre tiene lo que escribiste, y después los que coinciden por email, documento o metadata.
  • Hasta 10 filtros por búsqueda. Cuenta como filtro lo que lleva dos puntos (vendedor:ana) o empieza con guion (-canal:email). Las palabras sueltas no cuentan, así que puedes escribir un nombre largo sin problema.
  • No corrige errores de escritura, igual que Stripe: "Marianna" no encuentra a Mariana.
  • Claves con espacios, o que no empiezan por letra: escríbelas tal cual, como vendedor local:pedro o 2fa:si. El buscador las reconoce porque conoce las claves que tienen tus clientes.
  • Clave mal escrita o incompleta: si escribes una clave que no existe pero se parece a una que sí (vendedr:ana) o es su comienzo (pedi:A-2291), debajo del buscador aparece "¿Quisiste decir vendedor?", y un clic la corrige. Nunca se corrige sola.

Datos sensibles: no guardes nada aquí

La metadata no está cifrada y vuelve completa en cada lectura del objeto.

No guardes ahí números de tarjeta, contraseñas, cédulas, direcciones de casa ni nada que no quieras ver en un registro.

Dónde aparece y dónde no:

Dónde¿Aparece?
Tus lecturas autenticadas (GET /v1/...)Sí, completa
Los eventos de webhook de la sesión de checkoutSí
La pantalla de pago que ve tu clienteNo

Esa última fila es deliberada: la metadata es tuya, y quien paga es otra persona. El checkout nunca la recibe.

Nombres de clave reservados

Cuatro nombres los usa Venflow, y se rechazan si los mandas:

  • checkoutMode
  • subscriptionId
  • obInvoiceId
  • billing_cycles: es el nombre del campo del API con el total de cuotas. Una clave tuya con ese nombre se leería como un segundo total que contradice al real. Si ya la tenías guardada, puedes seguir editando el resto y borrarla con null; lo que se rechaza es escribirla.

Si usas uno, la petición falla con un mensaje que nombra la clave y te sugiere otra. No se guarda nada a medias.

{
  "code": "invalid_argument",
  "message": "Metadata key \"subscriptionId\" is reserved by Venflow and cannot be used. Choose another name, for example \"externalId\" or \"orderRef\"."
}

Se rechazan en todos los objetos, no solo en las sesiones de checkout. Es a propósito: la metadata de un payment link viaja a la sesión que crea (ver abajo), así que una clave reservada aceptada en el link acabaría en la sesión de todos modos.

Solo se rechazan esos cuatro nombres exactos, y distinguen mayúsculas de minúsculas. subscriptionRef, mySubscriptionId o checkout funcionan sin problema.

Cuotas de una suscripción: billingCycles

Cuando el plan de una suscripción tiene cuotas, Venflow guarda el total en su metadata con la clave billingCycles. Siempre aparece de primera y, como todo en la metadata, es texto. Si necesitas hacer cuentas con él, usa el campo billing_cycles de la suscripción, que es un número.

GET /v1/subscriptions/{id}
{
  "id": "8c1d...",
  "billing_cycles": 12,
  "billing_cycles_completed": 3,
  "metadata": { "billingCycles": "12", "vendedor": "Ana Pérez" }
}

Es un dato de Venflow y es de solo lectura:

  • Se conserva siempre. Ningún PATCH lo borra, tampoco {}, que vacía todas tus claves.
  • Puedes reenviarlo sin cambios. Si lees la metadata completa, cambias tus claves y mandas todo de vuelta, billingCycles se ignora y el resto se guarda.
  • Cambiarlo o borrarlo se rechaza. Si mandas otro valor o null, la petición falla y no se guarda nada:
{
  "code": "invalid_argument",
  "message": "Metadata key \"billingCycles\" is managed by Venflow and is read-only. Leave it out of the request, or send it back unchanged."
}
  • No cuenta para tus límites. Sigues teniendo tus 50 claves.
  • Sigue al plan. Si la suscripción cambia de plan, el valor pasa a ser el del plan nuevo.
  • Puede no estar. Las suscripciones de cobro externo nunca la tienen, y algunas creadas fuera del checkout antes de este cambio (importación o panel) tampoco. El campo billing_cycles de la suscripción siempre está.

En el dashboard se ve en la sección de metadata con un candado, y no aparece en el editor.

Solo en suscripciones. En clientes, facturas, payment links y transacciones, billingCycles es un nombre de clave como cualquier otro.

La metadata que le pongas a un payment link viaja a la sesión de checkout que se crea cuando alguien lo abre.

Es la única vez que un dato tuyo pasa de un objeto a otro, y existe por un motivo concreto: el evento de webhook del pago incluye session.metadata, así que es lo que te permite reconocer de qué link vino un cobro sin guardar tú la relación.

Etiquetas el link…
{
  "plan": "574f56ed-...",
  "metadata": { "vendedor": "Ana Pérez", "pedido": "A-2291" }
}
…y te vuelve en el webhook del pago
{
  "eventType": "PAYMENT_SUCCESS_EVENT",
  "session": {
    "id": "2b7ac02a-...",
    "metadata": { "vendedor": "Ana Pérez", "pedido": "A-2291" }
  }
}

Tres detalles que conviene saber:

  • Es una copia, tomada al abrirse el link. Si después editas la metadata del link, las sesiones ya creadas se quedan con lo que tenían.
  • No sigue más allá. La suscripción y la factura que nazcan de esa sesión arrancan con la metadata vacía. Si las quieres etiquetar, hazlo con su PATCH.
  • Tu cliente no la ve. La pantalla de pago nunca recibe la metadata, aunque la sesión la lleve.

Preguntas frecuentes

¿Qué devuelve un objeto que nunca tuvo metadata? Un objeto vacío, {}. Nunca null, así que puedes leerlo sin comprobar antes.

¿Distingue mayúsculas de minúsculas? Sí. Pedido y pedido son dos claves distintas.

¿Puedo mandar una clave repetida? En JSON no existen las claves repetidas: gana la última.

¿La metadata de un payment link pasa a las sesiones que genera? Sí, y es la única vez que un dato tuyo pasa de un objeto a otro. La sesión nace con una copia de la del link; desde ahí cada una va por su lado. Ver Del payment link a la sesión.