En QRwey!, un código QR representa una intención de autofactura. Cada QR tiene un campo status que indica su estado actual, y una fecha de expiración que limita su vigencia.
Esta guía explica cómo interpretar correctamente el ciclo de vida de un QR usando el campo status y los códigos HTTP de la API.
El estado de un QR se devuelve en el campo status tanto al generarlo (POST /v1/qrs) como al consultar su detalle (GET /v1/qrs/{qrId}).
| Status | Significado |
|---|---|
PENDING | QR generado, esperando a ser escaneado |
SCANNED | QR escaneado por el usuario desde la app |
INVOICED | La intención fue confirmada y el CFDi fue timbrado |
EXPIRED | El QR alcanzó su fecha expires_at sin ser facturado |
CANCELLED | El QR fue cancelado manualmente |
PENDING → SCANNED → INVOICED
│ │
│ └──→ EXPIRED
│
├──→ EXPIRED
│
└──→ CANCELLED- Un QR inicia en
PENDINGal ser generado - Pasa a
SCANNEDcuando el usuario lo escanea desde la app - Si el usuario confirma la factura, pasa a
INVOICED - Si el QR alcanza
expires_atsin completar el flujo, pasa aEXPIRED - Un QR puede ser cancelado manualmente en cualquier momento previo a
INVOICED
Además del campo status, el API responde con códigos HTTP que reflejan el estado:
| Respuesta del API | Interpretación |
|---|---|
200 OK | QR encontrado, revisa el campo status para conocer su estado |
404 Not Found | QR no encontrado (ID inválido o recurso eliminado) |
422 Unprocessable Entity | Error de reglas de negocio o configuración |
Este comportamiento aplica al endpoint:
GET /v1/qrs/{qrId}Cuando el status es PENDING:
- El QR fue generado exitosamente
- Aún no ha sido escaneado
- Está dentro de su ventana de vigencia
Acciones recomendadas:
- Mostrar o imprimir el QR al cliente
- Monitorear si se desea
Cuando el status es SCANNED:
- El usuario escaneó el QR desde la app de QRwey!
- La intención está siendo revisada por el usuario
- Aún no se ha confirmado la factura
Acciones recomendadas:
- Esperar a que el usuario confirme
- No generar un QR nuevo
Cuando el status es INVOICED:
- El CFDi fue timbrado exitosamente
- Los campos
invoiceycustomerdel detalle contienen la información de la factura - El flujo se completó
Acciones recomendadas:
- Registrar el
invoice.uuidpara conciliación - Descargar XML/PDF si es necesario desde
invoice.xml_urlyinvoice.pdf_url
Cuando el status es EXPIRED:
- El QR alcanzó su fecha
expires_at - No puede resolverse ni facturarse
- No puede reactivarse
Acciones recomendadas:
- Informar al usuario que el QR expiró
- Generar un nuevo QR si es necesario
Cuando el status es CANCELLED:
- El QR fue cancelado manualmente
- No puede usarse
Acciones recomendadas:
- Tratarlo como finalizado
- Generar un nuevo QR si la operación sigue vigente
Cada QR define una ventana de validez mediante expires_at.
Recomendaciones:
- Usa expiraciones acordes a las reglas del negocio (ej. 5 días, hasta fin de mes)
- Maneja siempre el estado
EXPIRED - No intentes reutilizar QRs expirados
Por diseño:
- Un QR representa una sola transacción
- No debe reutilizarse
- No debe regenerarse sin idempotencia
Si necesitas generar otro QR para la misma venta:
- Crea una nueva intención
- Usa un nuevo
Idempotency-Key
- Consulta QRs siempre desde tu backend
- No expongas lógica de validación en frontend
- Maneja explícitamente todos los estados
Antes de ir a producción:
- Consultas el campo
statuspara determinar el estado del QR - Manejas
PENDING,SCANNED,INVOICED,EXPIREDyCANCELLED - Verificas
invoiceycustomercuandostatusesINVOICED - Logs con
qr_id,statusy timestamps - Mensajes claros para el usuario final
- Reintentos seguros: Idempotencia & Reintentos
- Manejo de errores: Manejo de errores
- Flujo completo: Quickstart