Feed de reconciliación
Complemento del push: si le das al equipo de alpadevs una URL de feed, nuestro cron la consulta periódicamente y sincroniza tu inventario hacia el espejo. Sirve para detectar drift: boletos que vendiste pero nunca nos pusheaste, o anulaciones que se perdieron.
| Parámetro (lo configura Gate) | Valor |
|---|---|
| URL del feed | https:// y host público (mismas reglas que la URL del webhook). |
| Frecuencia | Configurable entre 5 minutos y 24 horas. |
| Autenticación (opcional) | El valor completo del header Authorization que debemos enviar (p. ej. Bearer <token>). Se guarda server-side y nunca se muestra. |
| Timeout | 15 segundos por consulta. |
Qué debe responder tu feed
Sección titulada «Qué debe responder tu feed»GET <tu feed URL> (enviamos Accept: application/json y, si lo configuraste, tu
header Authorization) → 200 con este JSON:
{ "rows": [ { "experienceId": "22222222-2222-4222-8222-222222222222", "qrContent": "ABC.DEF", "externalRef": "TG-1001", "status": "valid", "holderRef": "user-42", "holderName": "Ana Pérez", "metadata": { "priceName": "VIP" } }, { "experienceId": "22222222-2222-4222-8222-222222222222", "qrContent": "GHI.JKL", "externalRef": "TG-1002", "status": "valid", "maxUses": 3, "holderRef": "+5215512345678", "holderName": "Carlos Ruiz" }, { "experienceId": "22222222-2222-4222-8222-222222222222", "qrContent": "MNO.PQR", "externalRef": "TG-1003", "status": "void" } ]}| Campo | Tipo | Obligatorio | Límite | Descripción |
|---|---|---|---|---|
rows | array | Sí | ≤ 5000 filas | Puede ser []. |
experienceId | string (UUID) | Sí (por fila) | A qué experiencia pertenece el boleto. | |
qrContent | string | Sí | 1 – 500 | Igual que en el bulk; se normaliza igual. |
externalRef | string | No (recomendado) | ≤ 200 | |
status | "valid" | "void" | No | default valid | Incluye siempre el estado real (ver advertencia abajo). |
maxUses | integer | No | 1 – 1000 | |
holderRef | string | No (recomendado) | ≤ 200 | |
holderName | string | No | ≤ 200 | |
metadata | object | No |
Cada fila es exactamente una fila del bulk más
experienceId. Si tienes más de 5000 boletos vigentes, devuelve los más recientes
primero.
Semántica
Sección titulada «Semántica»- Es el mismo upsert idempotente del bulk: reenviar todo tu inventario en cada pull
es seguro; los boletos ya redimidos en puerta no se pisan (
REDEEMED_CONFLICT). qrContentse normaliza igual que en el bulk (trim+chlde URLs).statusausente equivale avalid: un boleto anulado que aparezca en el feed sinstatus: "void"se reactiva. Publica el estado real de cada boleto.- Las filas se agrupan por
experienceIdy se aplican en lotes de 1000. Una experiencia no enlazada a tu proveedor rechaza su grupo (queda registrado) pero no afecta al resto de experiencias del mismo feed. - Todo lo que aparezca solo en el feed (y no en el espejo) se importa y se marca como drift detectado en el log de sincronización que ve el equipo de alpadevs.
- Las transferencias con QR nuevo que lleguen por el feed también se aplican (cuentan
como
reissueden el log), pero no se consideran drift. Aun así, no dependas del feed para transferencias: en puerta el QR viejo deja de valer solo cuando nos llega el nuevo.
El feed no sustituye al bulk
Sección titulada «El feed no sustituye al bulk»Úsalo como red de seguridad. El push inmediato (/tickets/bulk al vender,
/tickets/void al anular) sigue siendo la vía principal para que la puerta tenga datos
frescos; el feed corre como mucho cada 5 minutos.
Ejemplo mínimo de implementación
Sección titulada «Ejemplo mínimo de implementación»Un endpoint que devuelve los boletos vigentes de tus eventos enlazados, con su estado:
-- pseudo-SQL orientativoselect experience_id as "experienceId", qr_content as "qrContent", ticket_id as "externalRef", case when voided then 'void' else 'valid' end as "status", max_uses as "maxUses", owner_id as "holderRef", owner_name as "holderName"from ticketswhere event_id in (/* eventos enlazados en Gate */)order by updated_at desclimit 5000;