Endpoint de estado (GET)
Exponés un endpoint HTTP que devuelve el snapshot del lifecycle de una interaction. Crowder lo llama:
- Antes de generar la compra, para revalidar la cotización.
- Antes de disparar un webhook que muta lifecycle, para confirmar que la transición es válida.
- Cuando necesita un estado actualizado (incluyendo detección de expiración).
Request
Sección titulada «Request»GET {endpoint}/{interaction}Headers:
Authorization: Bearer <api_key>Accept: application/json- Sin body.
- Validá la
api_keyen tiempo constante. - Timeout del lado de Crowder: 5 s. 1 retry con backoff de 500 ms.
Lifecycle posibles
Sección titulada «Lifecycle posibles»status | Significado | HTTP |
|---|---|---|
valid | Cotización vigente. Sin compromiso de stock, sin TTL. | 200 |
reserved | Reserva activa. TTL corriendo (expiresAt presente). | 200 |
expired | El hold venció sin pago. Solo se llega desde reserved. | 410 |
confirmed | Pago capturado. Tu fulfillment en curso. La devolubilidad la declarás por item con refundable. | 200 |
refunded | Devuelta total. Solo desde confirmed, cuando se devolvieron todos los items. | 200 |
Operaciones permitidas según status actual
Sección titulada «Operaciones permitidas según status actual»status actual | purchaseReserved | purchasePaid | purchaseRefunded |
|---|---|---|---|
valid | ✅ | ❌ | ❌ |
reserved | ❌ (idempotente) | ✅ | ❌ |
expired | ❌ | ❌ | N/A |
confirmed | ❌ | ❌ | ✅ (solo items refundable: true, salvo chargeback/fraud que bypasean) |
refunded | ❌ | ❌ | N/A |
Responses
Sección titulada «Responses»Cotización vigente, sin compromiso de stock, sin TTL.
{ "status": "valid", "interaction": "pkg_abc123", "currency": "ARS", "partnerItems": [ { "uuid": "HOTEL-3N-PREMIUM", "type": "HOTEL", "description": "Hotel 3 noches · Hilton Buenos Aires", "price": 120000.00, "quantity": 1, "refundable": true } ]}Hold activo con TTL.
{ "status": "reserved", "interaction": "pkg_abc123", "currency": "ARS", "partnerItems": [/* ... */], "expiresAt": "2026-04-28T15:48:00Z"}El hold venció sin pago. Solo válido viniendo de reserved.
{ "status": "expired", "interaction": "pkg_abc123", "error": { "code": "expired", "message": "La reserva expiró sin compra." }}Códigos sugeridos en error.code: expired, out_of_stock, price_changed, cancelled_by_partner, unknown.
Pago capturado, tu fulfillment en curso. Si hubo devoluciones parciales, partnerItems refleja los items que siguen activos (los devueltos se eliminan del array).
{ "status": "confirmed", "interaction": "pkg_abc123", "currency": "ARS", "purchase": { "id": 987654, "amount": 120000.00 }, "partnerItems": [ { "uuid": "TICKET-VIP", "type": "TICKET", "description": "Acceso VIP", "price": 80000.00, "quantity": 1, "refundable": true }, { "uuid": "MERCH-REMERA", "type": "MERCH", "description": "Remera oficial", "price": 40000.00, "quantity": 1, "refundable": false } ], "url": "https://partner.example/voucher/pkg_abc123"}Terminal. Se alcanza cuando se devolvieron todos los items de la compra.
{ "status": "refunded", "interaction": "pkg_abc123", "currency": "ARS", "purchase": { "id": 987654, "amount": 120000.00 }, "partnerItems": [/* items originales de la compra */], "refund": { "amount": 120000.00, "reason": "user_request", "refundedAt": "2026-05-01T09:59:30Z", "refundId": "ref_xyz789" }}El campo url es opcional y lo emitís vos solo en respuestas post-compra (confirmed, refunded). Apunta a tu recurso asociado a la operación: voucher, comprobante o página de detalle.
Errores
Sección titulada «Errores»Toda respuesta de error usa el envelope estándar:
{ "status": "error", "error": { "code": "...", "message": "...", "details": { } }}error.code es snake_case, ≤ 64 chars, lista no cerrada. error.message es legible para el usuario, ≤ 200 chars, localizado al locale cuando viene del partner. Crowder identifica el caso por código HTTP + error.code.
| HTTP | error.code típico | Caso |
|---|---|---|
| 400 | invalid_payload | Request mal formado. |
| 401 / 403 | auth_invalid | Bearer ausente o inválido. |
| 404 | not_found | interaction desconocida. |
| 5xx | internal_error | Error interno. Crowder reintenta una vez. |
{ "status": "error", "error": { "code": "not_found", "message": "interaction no encontrada" }}Idempotencia
Sección titulada «Idempotencia»El GET puede llegarte más de una vez para la misma interaction (revalidaciones repetidas, polling, retries). Tu endpoint debe ser idempotente: responder siempre el estado actual sin efectos colaterales.