QR dinámico en facturas y cupones de pago

Un QR dinámico representa una deuda puntual: tiene su monto, su vencimiento y se paga una sola vez. Es la opción para imprimir en facturas, cupones o resúmenes. Generás un QR por comprobante, el cliente lo escanea con cualquier billetera o app bancaria y PAGOS360 te avisa cuando se pagó.

Hasta que se pague, podés corregir el monto o el vencimiento, o eliminarlo. Más información en QR dinámico.

Importante

todas las llamadas usan tu API Key (Authorization: Bearer <API Key>) y se hacen desde tu servidor. Los ejemplos usan sandbox, el entorno de pruebas (https://qr.sandbox.pagos360.com); en producción el host es https://qr.pagos360.com.

El flujo

  1. Creás los QR de tus comprobantes, en lote.

  2. Obtenés el contenido de cada QR y lo imprimís en el comprobante.

  3. Si algo cambia antes del pago, editás o eliminás el QR.

  4. Cuando el cliente paga, recibís un webhook (un aviso automático en tu sistema) y el QR pasa a Paid.

Paso 1: crear los QR (hasta 10.000 por pedido)

Usá POST /save-qr-data. total_count tiene que coincidir con la cantidad de elementos de data.

curl --request POST 'https://qr.sandbox.pagos360.com/save-qr-data' \ --header 'Authorization: Bearer <API Key>' \ --header 'Content-Type: application/json' \ --data '{ "total_count": 2, "data": [ { "id": "<account_id>-FAC000123", "multiple_payment": false, "city": "CORDOBA", "postal_code": "X5000ABC", "description": "Factura 0001-00000123", "payer_name": "Juan Pérez", "external_reference": "FAC-0001-00000123", "first_due_date": "10-10-2026", "first_total": 25000, "second_due_date": "20-10-2026", "second_total": 26500 }, { "id": "<account_id>-FAC000124", "multiple_payment": false, "city": "CORDOBA", "postal_code": "X5000ABC", "description": "Factura 0001-00000124", "payer_name": "María Gómez", "external_reference": "FAC-0001-00000124", "first_due_date": "10-10-2026", "first_total": 18000, "expiration_time": "18:00" } ] }'

Reglas principales:

Campo

Regla

id

Obligatorio. Hasta 25 caracteres, empieza con el ID de tu cuenta y un guion (<account_id>-...). Tiene que ser único: queda dentro del contenido del QR.

first_total / first_due_date

Obligatorios. Monto: número, mínimo 10, hasta 2 decimales. Fecha: DD-MM-AAAA, hoy o posterior.

second_total / second_due_date

Opcionales, van juntos. La segunda fecha tiene que ser posterior a la primera y el segundo monto, mayor o igual al primero.

expiration_time

Opcional, HH:MM (hora de Argentina). El QR vence ese día a esa hora en lugar de al final del día. No se puede combinar con segundo vencimiento.

city / postal_code

Obligatorios. Ciudad hasta 15 caracteres; código postal de exactamente 8.

description / payer_name / multiple_payment

Obligatorios.

external_reference

Opcional, hasta 255 caracteres. Usá el número de comprobante: es lo que vas a recibir en el webhook.

Respuestas:

Respuesta

Significado

[{"code": "H002", "message": "Created"}]

Se crearon todos.

[{"code": "F001", "qr_id": "...", "message": "..."}, ...]

Hay errores de validación. No se crea ningún QR del lote.

[{"code": "F002", "qr_id": "...", "message": "The qr_id already exists"}, ...]

Esos IDs ya existían. El resto del lote sí se creó.

[{"code": "Q001", ...}] / [{"code": "Q002", ...}]

total_count no coincide / más de 10.000 elementos.

[{"code": "B001", "message": "The JSON is malformed"}]

El cuerpo no es un JSON válido.

Revisá siempre el code: todas las respuestas llegan con HTTP 200. Ver Importar QR (hasta 10.000 ítems).

Más de 10.000 QR: importación por archivo

Para lotes de hasta 100.000 QR, subís un archivo y el resultado llega por webhook.

1. Pedí una URL de carga. Vence a los 60 segundos.

curl 'https://qr.sandbox.pagos360.com/bucket-url' \ --header 'Authorization: Bearer <API Key>'
{ "url": "https://...amazonaws.com/<account_id>-1759000000000.json?X-Amz-..." }

2. Subí el archivo con PUT a esa URL. Respetá el orden de las claves: webhook_url, total_count y data. Incluí siempre webhook_url: es obligatorio para que el archivo se procese.

curl --request PUT '<url>' \ --header 'Content-Type: application/json' \ --data-binary @lote.json
{ "webhook_url": "https://tu-sistema.com/webhooks/qr-lotes", "total_count": 50000, "data": [ { "id": "<account_id>-FAC000125", "...": "..." } ] }

Una respuesta HTTP 200 sin cuerpo indica que el archivo se subió.

3. Esperá el webhook en webhook_url:

{ "entity_name": "qr", "type": "batch_partial_rejected", "entity_id": 0, "payload": { "id": "887071c6-128a-4ee8-9114-96ad58cf84d5", "external_reference": "<account_id>-1759000000000.json" } }

type puede ser batch_imported (todo OK), batch_partial_rejected (algunos QR no se crearon) o batch_total_rejected (no se creó ninguno). Si es un rechazo parcial, consultá los errores con el id del payload, de a 10.000 por página:

curl 'https://qr.sandbox.pagos360.com/batch-result/887071c6-128a-4ee8-9114-96ad58cf84d5/1' \ --header 'Authorization: Bearer <API Key>'

Cada error indica el QR y los códigos de los campos que fallaron (por ejemplo, FAC000125;E10;E11). La tabla de códigos está en Importar QR (hasta 100.000 ítems).

Paso 2: imprimir el QR

Consultá cada QR con GET /status/{qr_id} y usá el campo string para generar la imagen con cualquier librería de códigos QR.

curl 'https://qr.sandbox.pagos360.com/status/<account_id>-FAC000123' \ --header 'Authorization: Bearer <API Key>'
{ "id": "<account_id>-FAC000123", "description": "Factura 0001-00000123", "first_due_date": "10-10-2026", "first_total": 25000, "second_due_date": "20-10-2026", "second_total": 26500, "external_reference": "FAC-0001-00000123", "status": "Pending", "string": "00020101021143...6304C6A8" }
Tip

obtené el string de /status para imprimir exactamente lo que guardó PAGOS360. También podés armarlo vos siguiendo el formato de QR dinámico.

Paso 3: editar o eliminar antes del pago

Editar con POST /edit-qr/{qr_id}. Funciona con QR dinámicos en Pending. Enviá todos los campos obligatorios, también los que no cambian:

curl --request POST 'https://qr.sandbox.pagos360.com/edit-qr/<account_id>-FAC000123' \ --header 'Authorization: Bearer <API Key>' \ --header 'Content-Type: application/json' \ --data '{ "multiple_payment": false, "description": "Factura 0001-00000123", "payer_name": "Juan Pérez", "first_due_date": "15-10-2026", "first_total": 24000 }'
  • La nueva fecha tiene que ser de hoy en adelante y no puede ser anterior a la que ya tenía el QR.

  • Se pueden editar multiple_payment, description, payer_name, payer_email, external_reference, first_* y second_*. No se pueden editar expiration_time, city ni postal_code.

  • Respuesta correcta: [{"code": "H005", "message": "Ok"}]. Si el QR no está en Pending: F005. Si no existe o no es dinámico: F004.

Para varios QR a la vez, usá Editar QR (hasta 10.000 ítems).

Eliminar con DELETE /delete-qr/{qr_id}. Funciona con QR en Pending. Una vez eliminado, el QR ya no se puede pagar.

curl --request DELETE 'https://qr.sandbox.pagos360.com/delete-qr/<account_id>-FAC000123' \ --header 'Authorization: Bearer <API Key>'
[{ "code": "H005", "message": "Ok" }]

Para varios QR a la vez, usá Eliminar QR (hasta 10.000 ítems).

Paso 4: enterarte del pago

Webhook. Cuando se paga un QR, PAGOS360 registra una solicitud de pago pagada y envía el webhook paid de la entidad payment_request, con el external_reference del QR. Ver Webhooks.

{ "entity_name": "payment_request", "type": "paid", "entity_id": 816, "payload": { "id": "816", "request_result_id": "546", "external_reference": "FAC-0001-00000123" } }

Consulta. GET /status/{qr_id} devuelve status: "Paid" y paid_at (solo la fecha, DD-MM-AAAA). Estados posibles: Pending, Paid, Refunded, Deleted. Ver Consultar QR.

Vencimientos

  • Hasta first_due_date inclusive se cobra first_total. Después, si hay segundo vencimiento, se cobra second_total hasta second_due_date inclusive.

  • Con expiration_time, el QR vence el día de first_due_date a esa hora.

  • Pasado el último vencimiento, la billetera no puede cobrarlo.

Importante

para volver a cobrar un QR vencido, editá sus fechas mientras siga en Pending. No hay un estado "vencido": un QR vencido sigue figurando como Pending.