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
| Objeto | Cómo la escribes |
|---|---|
| Cliente | POST /v1/customers · PATCH /v1/customers/{id} |
| Suscripción | PATCH /v1/subscriptions/{id} |
| Factura | PATCH /v1/invoices/{id} |
| Payment link | POST /v1/payment-links · PATCH /v1/payment-links/{id} |
| Sesión de checkout | POST /v1/checkout/sessions |
| Pago | PATCH /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:
| Mandas | Qué 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ímite | Valor |
|---|---|
| Claves por objeto | 50 |
| Longitud de una clave | 40 caracteres |
| Longitud de un valor | 500 caracteres |
| Total de todas las claves y valores | 27.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.
| Escribes | Encuentra |
|---|---|
A-2291 | Clientes con "A-2291" en su nombre, email, documento, empresa o en algún valor de su metadata |
mariana sal | Todas las palabras dentro de un mismo dato: "Mariana Salazar", pero no un Pedro Salazar que tenga "Mariana" en su metadata |
pedi | Clientes con alguna clave que empieza con "pedi" (pedido, pedido ab…), desde 3 letras |
pedido:A-2291 | La clave pedido con un valor que contiene "A-2291" |
vendedor:Ana Pérez | El 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:whatsapp | Cualquier clave cuyo valor contenga "whatsapp" |
metadata:canal=whatsapp | La forma larga de canal:whatsapp |
name:ana · email:gmail | Solo en el nombre, o solo en el email |
-canal:email | Excluye 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:
perezencuentra a "Pérez", lañcuenta comon, ycanal:encuentra la claveCanal. Si tienes dos claves que solo se diferencian en eso (Pedidoypedido), 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:pedroo2fa: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 checkout | Sí |
| La pantalla de pago que ve tu cliente | No |
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:
checkoutModesubscriptionIdobInvoiceIdbilling_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 connull; 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.
{
"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
PATCHlo 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,
billingCyclesse 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_cyclesde 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.
Del payment link a la sesión
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.
{
"plan": "574f56ed-...",
"metadata": { "vendedor": "Ana Pérez", "pedido": "A-2291" }
}{
"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.