Ir al contenido

Multi-usos

Un boleto admite maxUses entradas: pulseras multi-día, pases de varios accesos, abonos. Por defecto maxUses = 1.

Envía maxUses (entero, 1 – 1000) en la fila del bulk o del feed:

{
"qrContent": "GHI.JKL",
"externalRef": "TG-1002",
"maxUses": 3,
"holderRef": "+5215512345678",
"holderName": "Carlos Ruiz"
}
SituaciónEfecto
maxUses ausente en un insert1.
maxUses ausente en un updateConserva el valor actual.
Subir maxUses en un boleto validSe aplica (amplía el cupo).
Bajar maxUses por debajo de los usos ya consumidosRechazo USES_CONFLICT: no convertimos consumo real en redención implícita.
Cambiar maxUses en un boleto redeemedRechazo REDEEMED_CONFLICT: un boleto agotado no se reabre.
maxUses fuera de 1..1000 o no entero400 VALIDATION_FAILED (y, defensivamente, INVALID_MAX_USES por fila).

En cada lectura válida en puerta:

Estado antesRespuesta al operadorEstado después
valid, uses < maxUses − 1OK con usesLeftvalid, uses + 1
valid, uses == maxUses − 1OK con usesLeft = 0redeemed con redeemedAt
redeemedDUPLICATEsin cambios
voidVOIDsin cambios
sellado a otro titular (ver abajo)HOLDER_MISMATCHsin cambios; no consume uso

usesLeft = usos restantes después de esa lectura. Dos lecturas simultáneas del mismo boleto consumen usos distintos (nunca el mismo).

  • Webhook. Cada uso genera un evento ticket.redeemed con eventId propio y, en payload, uses (consumidos, incluido este) y max_uses. Cuando uses == max_uses, ese evento corresponde al uso que agotó el boleto.

    {
    "eventId": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
    "type": "ticket.redeemed",
    "createdAt": "2026-08-30T09:12:40.512Z",
    "payload": {
    "ticket_id": "44444444-4444-4444-8444-444444444444",
    "external_ref": "TG-1002",
    "qr_content": "GHI.JKL",
    "experience_id": "22222222-2222-4222-8222-222222222222",
    "redeemed_at": "2026-08-30T09:12:40.512873+00:00",
    "redeemed_by_email": "[email protected]",
    "uses": 2,
    "max_uses": 3,
    "holder_ref": "+5215512345678"
    }
    }
  • Pull GET /v1/partner/redemptions. Lista boletos en estado redeemed, así que un boleto multi-uso aparece solo cuando agota su último uso, con el redeemedAt de ese uso. Los usos intermedios no aparecen en el pull.

  • GET /v1/partner/tickets/{ref}. Muestra status: "valid" hasta agotarse; no expone el contador.

Si necesitas contabilizar cada acceso, consume los webhooks; el pull te sirve para confirmar el agotamiento.

Para maxUses > 1, en el primer uso el boleto queda sellado al holderRef que tenía en ese momento (si lo tenía). Con la política del organizador activa (lo está por defecto), un uso posterior con un holderRef distinto del sellado responde HOLDER_MISMATCH y no consume uso. El sello se escribe siempre que haya holderRef, esté o no activa la política, así que activarla más tarde protege también a los boletos ya usados.

Lo que implica para tu integración:

  • Envía holderRef siempre y mantenlo estable.
  • Sin holderRef el boleto no se sella y no se deniega por este motivo: queda sin protección contra “prestar la pulsera”.
  • Una transferencia después del primer uso deja el boleto inutilizable hasta que el holderRef vuelva a coincidir con el sellado (o el organizador desactive la política). Ver Transferencias.