Esta especificación está sujeta a cambios. El estándar colombiano EASPBV está evolucionando para soportar las capacidades de la red Bre-B. Passport colabora activamente con entidades del sector para definir un modelo robusto y flexible de integración de códigos QR para pagos en tiempo real.
Visión General
Este endpoint permite crear un Código QR compatible con Bre-B utilizando la API de la Plataforma PaaS de Passport. El código QR codifica información de pago y metadatos contextuales de acuerdo con el estándar colombiano EASPBV, devolviendo un identificador único del QR y los detalles asociados.
Tipos de QR
Bre-B maneja 3 tipos funcionales:
Estático (STATIC):
- No lleva valor (sin
amount).
- No lleva valor (sin
Dinámico (DYNAMIC)
- Siempre lleva valor (con
amount). - No existe QR dinámico sin valor.
- Siempre lleva valor (con
Híbrido (HYBRID):
- Es un QR estático al que se le incluye un valor.
- En la API se representa como
type: STATIC+amountpresente.
QRs dinámicos, “valor” (sin el objeto amount definido) no es válido.
Detalles del Endpoint
| Parámetro | Descripción |
|---|---|
| Endpoint | https://api.paas.sandbox.co.passportfintech.com/v1/qrcodes |
| Método | POST |
| Encabezados | Content-Type: application/json, Authorization |
| Autenticación | Token de Acceso (Bearer Token) |
Reglas de Importe (Tag 54)
El Tag 54 (amount.value) es el único valor monetario que Bre-B utiliza para procesar el pago.
- El importe que se envía en
amount.valuedebe incluir ya sumado cualquier:TIPINCVAT
Cuerpo de la Solicitud
| Parámetro | Tipo | Cardinalidad | Descripción |
|---|---|---|---|
| key_id | String | Obligatorio | ID único de la llave Bre-B asociada a la cuenta del comercio. |
| customer_id | String | Obligatorio | ID único del cliente (comercio) que inicia la transacción. |
| type | ENUM | Obligatorio | Tipo de código QR: STATIC o DYNAMIC. |
| channel | ENUM | Obligatorio | Canal en el cual se presentará el QR:
MAN, POS, APP, ECOMM, MPS, ATM. |
| additional_info | Objeto | Obligatorio VER SECCION: Regla de Obligatoriedad. | Objeto con metadatos adicionales de la transacción. |
| additional_info.transaction_purpose | ENUM | Obligatorio | Finalidad de la transacción: 00: Compras 02: Anulaciones 03: Transferencias 04: Retiro 05: Recaudo 06: Recargas 07: Depósito Se debe enviar el código de 2 dígitos. |
| qr_code_reference | String | Obligatorio | Referencia única que se puede añadir y enviar a la red bre-b, relacionada con el pago. Máximo 17 caracteres alfanuméricos. La letra P no está permitida. Luego en Bre-B la lógica interna le agrega a ese campo el identificador del adquirente “CO.COM.VISI.TRXID” y la letra P que corresponde a una identificación interna del Nodo. Por ejemplo. Si se envía a plataforma Passport PaaS al crear el QR
Al recibir el pago de ese QR se obtendrá:
|
| additional_info.invoice_number | String | Opcional | Número de factura (máx. 25 caracteres). |
| additional_info.mobile_phone_number | String | Opcional | Número móvil vinculado a la transacción. |
| additional_info.store_label | String | Opcional | Identificador de tienda. |
| additional_info.loyalty_label | String | Opcional | Referencia a programa de lealtad del comprador. |
| additional_info.reference_label | String | Opcional | Referencia única de la transacción. |
| additional_info.customer_label | String | Opcional | Identificador único del comprador. |
| additional_info.terminal_label | String | Condicional | ID del terminal de punto de venta (POS). |
| additional_info.customer_info | ENUM | Opcional | Información requerida del comprador: ADDRESS, EMAIL, PHONE. |
| additional_info.channel_presentation | String | Opcional | Código de 3 dígitos que indica cómo fue presentado el QR. |
| vat | Objeto | Condicional | Información del IVA si se incluye monto. Obligatorio para QR dinámicos. |
| vat.vat_type | ENUM | Condicional | Tipo de cálculo del IVA: FIXED, PERCENTAGE, WALLET. |
| vat.vat_value | String | Condicional | Valor fijo en COP o porcentaje (5 decimales). |
| vat.vat_base | String | Condicional | Base del valor sobre el cual se calcula el IVA. |
| inc | Objeto | Condicional | Información del INC. Aplicable si se incluye monto. |
| inc.inc_type | ENUM | Condicional | Tipo de cálculo del INC: FIXED, PERCENTAGE, WALLET. |
| inc.inc_value | String | Condicional | Valor fijo en COP o porcentaje (5 decimales). |
| amount | Objeto | Opcional | Valor de la transacción codificada en el QR. |
| amount.value | String | Opcional | Valor del pago (e.g., "100000.00"). |
| amount.currency | ENUM | Opcional | Debe ser COP. |
| tip | Objeto | Opcional | Información sobre propina (opcional). |
| tip.tip_type | ENUM | Opcional | Método de cálculo: REQUEST, FIXED, PERCENTAGE. |
| tip.tip_value | String | Opcional | Requerido si el tipo es FIXED. |
| tip.tip_percentage | String | Opcional | Requerido si el tipo es PERCENTAGE. |
Regla de Obligatoriedad - Objeto: additional_info
El objeto additional.info es opcional. Si se incluye, debe contener obligatoriamente los parámetros terminal_label y transaction_purpose.
Ejemplo de Solicitud
curl --location 'https://api.paas-sandbox.co.passportfintech.com/v1/qrcodes' \--header 'Content-Type: application/json' \--header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \--data '{ "key_id": "e7f75ffc-22b8-4cfe-884b-8ebcb008b680", "customer_id": "31eb66c3-f309-48ce-8b12-086f9e76b84c", "type": "DYNAMIC", "channel": "MPOS", "vat": { "vat_type": "FIXED", "vat_value": "100.00", "vat_base_value": "100.00" }, "inc": { "inc_type": "FIXED", "inc_value": "10.00" }, "amount": { "value": "100000.00", "currency": "COP" }, "additional_info":{ "transaction_purpose": "00", "invoice_number": "123", "terminal_label": "01", "store_label": "sasc0193", "mobile_phone_number": "3503503456", "loyalty_label": "1234", "reference_label": "pago impuesto", "customer_label": "0001", "customer_info": "EMAIL", "channel_presentation": "400" }, "qr_code_reference": "uniquereferencefortracking" }'Cuerpo de la Respuesta
- Código HTTP: 201 Created.
- Retorna un código QR creado y asociado a los metadatos de la solicitud.
Ejemplo de Respuesta
{ "created_at": "2025-05-12T20:30:17.547227Z", "qr_code_data": "00020101021226550015CO.COM.VISI.LLA0332jimmyjohns1111402545255@test.com49270015CO.COM.VISI.RED0104VISI52045782530317054130000100000.005802CO5919Test Business O9F126006Bogota61059827362120808PURCHASE80290017CO.COM.VISI.CANAL0104MPOS81260016CO.COM.VISI.CIVA01020282290015CO.COM.VISI.IVA0106100.0083300016CO.COM.VISI.BASE0106100.0084260016CO.COM.VISI.CINC01020285280015CO.COM.VISI.INC010510.0090610017CO.COM.VISI.TRXID01364A07229A-7B14-4B63-85D5-79572E130E0763040351", "qr_code_image": "iVBORw0KGgoAAAANSUhEUgAAAyoAAAMqAQAAAABFsohqAAAKI0lEQVR4nO2dXYrrRhCFT0WGeZQhC5ilyDvIkoZZUnZgLcULCEiPAxKVh+76aflCmITc2xZHD8PIkv1hQ5fq51S1KH7CMf/2MygAMcQQQwwxxBBDDDHEEEMMMcQQ832M1OMCua0XYL7uInIF5AZAbmu9DqwicsMumMXuu2Ev78WcPsU+8vbzvw0xxBDzrUNVVTGpquoyKIChnALjBmDcoKob9I6hvjYtg9bXRlW9j1rfBgzlU+of/+T7uX40Yog5JWatj229l/Nd9L6+KbBeAKxvWq7q40318wpgljcFVpFyy6RfonezGwCA4h+0mP/5IIYYYr5/XA7ngvEv0VkAmRRQYL9g/qMubMx/bOUCJgVkWq523/q7yvS4bAIAT+XHc/1oxBBzKoxFBAuqp38fVVUXQO8lGFBb0qNqDQaWQcspEG+LAKEGDfDgghEBMcR0jDnmBaoVUMsG+NW62AHUm3VDzh8Aae0zL0AMMS+HKdn9KyAfjwvktr6p/bmgJgcAyMcylFyB3DxrMD3e1AwAgGkBpNYNRH7JtyGGGGK+cZTl3cTxuwDjl+j8vkGx7mJP+10wXyEKfIkClgmc379ssY9folh30WNq4Fw/GjHEnAqT8gJ6B2B1v5oXOLj7JWFQIgf4w784/huAUesFzxUwIiCGmN4xOf9X4321iN5XMkrqr6YJ6n+WJih2Y0oZw8FPaQWIIaZ/jFmB8siPZe8iIs/9qwuLvKBQ/9NaVSifV6oFgDsJtALEENM1JlcB4OWBO4Di5KfyQHH326ABvuzNPyifOrUOBq0AMcT0i3ErsNmatni/igZgnv6kHhG4ljgExVUlYJ9a/osY4lw/GjHEnAqTIoKk/EkGAKEfyobCFAEePpiGICUM4qAVIIaYfjGe8FPT+7SdQ/5aufmQCZzSis+GIrwCWgFiiOkd01QKRysA3Mu1wbN+NS+QBITuPVg0EbrDmkVMDgGtADHE9Itxvz0n9iPhVyUAZhmKUZjSI98MRX34R93ALAOtADHEdI7JCb9JD3n+zVOE8Kd9G/lH8cC9AvcFbA4BrQAxxHSNSXmBqAdELdBCBS8AjM06T1UAZAFS05hEK0AMMV1jki9gjr959S4YskwggJIhAHL4EP2DoR2E+RbUCxBDTO+Ypp7X6ACqV6++sEdPAvoSB6JuAORbXEhAX4AYYjrHZCuQPX2fOaAWDHjDkemLI5rIPkPqN1D6AsQQ8wKYY09htBSVqykdaI/81FOYzENcdSchGYpz/WjEEHMqTErumUNv67wKA7NGODUTaCoSen2hrQ8qIwJiiHkBTHbey2Fq4UOvYCz2lDXwC8mWRDMBqBcghpgXwHhEYJnAWNP5QR9NhFkHkFsHk6oY1lPI+QLEEPNCmHFDHS84bsB89deAdEE+tIoK80DCqCo8LtDPd00DCWuscc4fjRhiToFptYORE6yvmWTYpw+UUysKJF8gXIO4QF+AGGJeAJMqheU8RwQ+OgxAmkGSZEJ+tNlBewetADHEvBbGhUBls9FbHTpsxb9VBLPUvcpEroCVBlX1Uy6Qm6uLis/weNMfYP7HgxhiiPkXh2UHgaduQO8UiOkDVRwUuw+179B2JhF9AWKIeQFM0wMYGYJl8Ne2o0yomSUQbYdNU+IUkkNaAWKI6RuTrEAzKOBZSBA7DrjI2PYz1Gwt1FOE9W20AsQQ0zWm3Y+gmS2ioRhsVQIR+Uf7UIiIgFxkoBUghpjeMU1HUEruhX+fhwqmPoLUKuStiHlMMbKWmFaAGGL6xbQziFUbeXDeoDx6g+pr40FymBMGSXpAK0AMMZ1j2gFBzWtp4pgXBbyMYHNIzeePYQTpqtkDWgFiiOkYk/YsFoxbOZXpzysADCrTn4PriHdRrIBivULn9w0C7KKzDJtJkH/f7OqXAON+0Z/6bYghhph/cUQcj7T3QOT/2tFhGuLh1EnohcPFEoMeOTAiIIaY3jHNJPJR9TiH1HOHNlMsVwWfty5r8gehLKQVIIaYfjG5UhijRV0+kC3DaPYg9jaO3Yu9RmAbGuS+IloBYojpGJN3KPNkf0r9odUS+xHDCI5bHcc2prQCxBDzCphGNdSG+kk1NFoVIG1lGFMFtEkitCNIaQWIIaZ3TCsB8O7g0aL8O+CuARBqAo0sYpIIIjRFbQLxXD8aMcScCuN9BHY+aY7oo9vYWgdz51A9PIuoYS3KBfYUEkNM/5jnvEA848cwAC4vjLctdsEnFEfJIOuHaAWIIeYlMKUMWEYJvqnqw8cGjj6QEIB8WNOQ3EYbLzhfd5GPxwVlEAl8IGGZXvgLvg0xxBDznSNC+OYB7huMLTBfwBoLD23D4T2kIeR+gXkBYojpHfM0dxDwHYma15rcfzNe0C3Iob2YeQFiiHkJTN65POUJR/cPmiFEqslJCN2wzy8OTVEzkYBWgBhiOsakSmF4/3lqWHgK5vPbGELvGViAQ80QsS0RrQAxxHSOaRx/rwxEnt9FgPnhf+wdbrc5H7WdPEIrQAwxXWPankLknGDaZtDXftrQVF1nlCYNbE22cWE3ETHEvApGbv7I/7wCIu8bMOmX1OIfdkExCo8Lco1gGdQKgvWWsoPB53vNEPyKb0MMMcR86zBfYPAJYXmzgdQcCMAEhObzh1eQ5hfnGaasFBJDTP+YpucnVm2z9n9kGVQ1iomeCYwWw8V7EGgFiCGmb0yaMQiv8VV7EDoANXlwGjWcdEZ5c6M0eThtdXKuH40YYk6FyWOB0rTQ0WUBtpzT/CEfMBKtBjaXpNnTzG0ErQAxxHSMabz6BcgzQ0Z7xtf73AOw+7KmKJyEJk3AvAAxxPSOSVYgBEMW9McmhECzUUHOFeTJZBhSTiEmENIKEENMx5gfagdNCtxOIPQl7kNHbAaJdR6U06bLgFaAGGJ6xyQPPkKA0AibV29GwaePWobAcoe+dZldDRkirQAxxLwApsiEsIro5xXWIjxu0M/roHXmgKr9t+yiuux5lgCAMlAgDydZqBoihpj+MXmD8uTLj21ewFqFmr3J3T+w2uJBYUC9ADHEvAQmqYbyToRpiFgeLxg9RHm+QIoX1GyEX6AVIIaYzjFpykis3xgmYqLgZlfig2DINzFTbzhK3YXMDhJDTOeY495EeZOhBbCpAnlmiFUUYZG/VwXv/qnTklsMaQWIIaZ/zHFhY1D9vEYTYfX55YZd9L6KYH735/5DBPO7qnyUTzFbMl+ZHSSGmP4xSUEc2YA8diyifDcPMYmoHr6HEZoaQXkbfQFiiOkbc7QCNlG47Sl8jgjSSCHPLOZEo3sFtALEENM55skK+HSxaANopgwjNRNE72Hcl7c0X6gdJIaY/jF5vkC0EKQRYwgpYW4kst4C1SQ5LCs+hAScMkIMMS+Aea4RAIgOQcReJIf+gDtCXHDY5ywPK2dEQAwxvWNE//me/37M5/rRiCGGGGKIIYYYYoghhhhiiCHmJJi/AZe7huAZpY7zAAAAAElFTkSuQmCC", "acquirer_network_identifier": "VISI", "inc": { "inc_value": "10.00", "inc_type": "FIXED" }, "key_id": "7756cfcb-0d28-4e89-bbc0-d4ebdc5b6ca1", "id": "7aa184b7-c549-467b-917f-460b4224b459", "entity_customer_id": "0d93dea5-00c4-4a9e-b3fa-cbaf5280818b", "merchant": { "merchant_category_code": "1234", "country": "CO", "merchant_name": "Test Business O9F12", "merchant_city": "Bogota", "merchant_zip_code": "98273" }, "status": "ACTIVE", "type": "DYNAMIC", "key": { "key_type": "EMAIL", "key_value": "jimmyjohns1111402545255@test.com" }, "channel": "MPOS", "amount": { "currency": "COP", "value": "100000" }, "additional_info": { "transaction_purpose": "00" }, "vat": { "vat_type": "FIXED", "vat_value": "100.00", "vat_base_value": "100.00" }, "qr_code_reference": "uniquereferencefortracking"}- La respuesta de Códigos QR incluye la imagen en formato Base64. Puedes usar cualquier librería de frontend para convertirla en una imagen legible para tu audiencia.
- Los códigos QR también son visibles en el dashboard para fines de validación.
- El
idque se devuelve es elqr_code_id, el cual se puede usar en otras peticiones
Errores Comunes y Manejo
| Código HTTP | Significado | Descripción |
|---|---|---|
| 400 Bad Request | Datos inválidos | Faltan campos requeridos o contienen valores incorrectos. |
| 401 Unauthorized | Token inválido | El token de acceso ha expirado o es inválido. |
| 403 Forbidden | Acceso denegado | La solicitud no está autorizada para validar la entidad. |
| 500 Server Error | Error del servidor | Se produjo un error inesperado al procesar la validación. |
Buenas Prácticas
- Verifica que el
key_idycustomer_idsean válidos y estén asociados correctamente. - Usa el campo
channel_presentationpara detallar cómo y dónde se muestra el QR. - Si se incluye un monto, asegúrate de incluir los objetos
vateinccon la estructura y tipos adecuados
Consideraciones para Lectura de QRs e iniciación de Pagos
INC, VAT y TIP son Informativos (no sumables al pagar)
Al leer un QR, aunque aparezcan campos INC, VAT y TIP, estos son informativos.
- Si se crea un pago, NO se deben sumar esos valores al importe.
- El pago se crea solo con el
amount.value
Lectura de QR Estático (Sin Importe):
Al leer un QR STATIC, se debe validar si contiene importe (amount.value):
- Si NO tiene importe: solicitar en la terminal que el cliente ingrese el valor.
- Si SÍ tiene importe: es un QR “híbrido” y el cliente puede modificar el valor a enviar en el pago.
QR Dinámico Sin Valor: Inválido
Un QR dinámico sin valor no debe aceptarse.