# Ciclo de vida del QR En QRwey!, un **código QR** representa una **intención de autofactura**. El API **no expone un campo explícito de estado**; en su lugar, el estado de un QR se **infiere a partir del comportamiento del endpoint de [resolución](/guides/resolve-qr)**. Esta guía explica cómo interpretar correctamente ese ciclo de vida usando las respuestas del API, de forma alineada al contrato OpenAPI. ## Principio clave > QRwey! **no devuelve un campo `status`**. El estado de un QR se **deduce** a partir del código HTTP al resolverlo. Esto permite mantener el API simple y seguro, sin exponer estados internos innecesarios. ## Flujo lógico (inferido) De forma conceptual, un QR pasa por las siguientes fases **lógicas**: ``` Generado → Válido → (Consumido | Expirado | Inválido) ``` Estas fases **no se devuelven como valores**, se interpretan mediante el resultado del endpoint de [resolución](/guides/resolve-qr). ## Cómo interpretar el estado de un QR La siguiente tabla describe **cómo interpretar la respuesta del API** al resolver un QR: | Respuesta del API | Interpretación | | --- | --- | | `200 OK` | El QR es válido y puede usarse | | `409 Conflict` | El QR ya fue consumido | | `410 Gone` | El QR expiró | | `404 Not Found` | El QR es inválido o fue revocado | | `422 Unprocessable Entity` | Error de reglas de negocio o configuración | Este comportamiento aplica al endpoint: ``` GET /api/v1/qrs?v=&t=&m= ``` ## QR válido (`200 OK`) Cuando el endpoint responde `200 OK`: - El QR es auténtico - La firma es válida - La transacción existe - La información fiscal puede mostrarse al usuario Acciones recomendadas: - Mostrar el detalle de la transacción - Permitir al usuario revisar la información - Continuar el flujo de autofactura en la app móvil de QRwey! ## QR consumido (`409 Conflict`) Cuando el endpoint responde `409 Conflict`: - El QR **ya fue utilizado** - No puede volver a usarse - La intención ya fue confirmada Acciones recomendadas: - Mostrar mensaje de “QR ya utilizado o factura timbrada” - Evitar reintentos - No revelar información sensible ## QR expirado (`410 Gone`) Cuando el endpoint responde `410 Gone`: - El QR alcanzó su fecha `expires_at` - No puede resolverse - No puede reactivarse Acciones recomendadas: - Informar al usuario que el QR expiró - Solicitar generar un nuevo QR ## QR inválido (`404 Not Found`) Cuando el endpoint responde `404 Not Found`: - El token no existe - El QR fue revocado o purgado - El QR es incorrecto Acciones recomendadas: - Tratarlo como QR inválido - No diferenciar entre “no existe” o “revocado” - Mostrar mensaje genérico ## Error de negocio (`422 Unprocessable Entity`) Este error indica: - Problemas de configuración - Reglas fiscales no cumplidas - Datos inconsistentes Acciones recomendadas: - Revisar el cuerpo de la respuesta (`code`, `message`) - Registrar el error para soporte - No mostrar detalles técnicos al usuario final ## Expiración (`expires_at`) Cada QR define una ventana de validez mediante `expires_at`. Recomendaciones: - Usa expiraciones cortas (5 días, hasta fin de mes, etc.) - Alinearlo con las reglas del negocio - Maneja siempre `410 Gone` - No intentes reutilizar QRs expirados ## Reuso del QR 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` ## Buenas prácticas de seguridad - Resuelve QRs siempre desde backend - Nunca confíes en datos de cualquier QR sin validarlos vía API - No expongas lógica de validación en frontend - Maneja explícitamente todos los códigos 4xx ## Checklist para producción Antes de ir a producción: - [ ] Interpretas el estado solo por código HTTP - [ ] Manejas `409`, `410`, `404` y `422` - [ ] No dependes de campos inexistentes (`status`) - [ ] Logs con request-id y timestamps - [ ] Mensajes claros para el usuario final ## ¿Qué sigue? - Reintentos seguros: [Idempotencia & Reintentos](/guides/idempotency) - Manejo de errores: [Manejo de errores](/guides/error-handling) - Flujo completo: [Quickstart](/guides/quickstart)