Referencia: entradas y control de acceso
Consultar entradas emitidas y validarlas en puerta desde tu propio hardware, con el veredicto que devuelve cada escaneo.
Última actualización: 23 de agosto de 2026
Consultar entradas necesita tickets:read. Validarlas, tickets:validate —que ya incluye la lectura—.
Entradas y control de acceso
Consultar las entradas emitidas y validarlas en puerta.
Listar entradas
/ticketsEntradas emitidas, de la más reciente a la más antigua.
| Parámetro | Valores |
|---|---|
venueId | Id de sala |
performanceId | Id de fecha. El filtro del control de acceso |
eventId | Id de evento |
orderId | Id de pedido |
status | valid · used · void |
limit | 1–100, por defecto 25 |
cursor | El nextCursor de la página anterior |
# El padrón de esta noche
curl -G https://app.tickeep.com/api/v1/tickets \
-H "Authorization: Bearer $TICKEEP_API_KEY" \
--data-urlencode "performanceId=$PERF" \
--data-urlencode "limit=100"
Esto es lo que alimenta un sistema de control de acceso de terceros: te descargas el padrón de la fecha antes de abrir puertas y ya sabes a quién esperas.
/tickets/{code}Una entrada por su código.
El código se puede mandar en minúsculas: se normaliza. Responde 404 si no existe o si está en una sala fuera del ámbito de la clave.
El objeto Ticket
{
"id": "6a7301bb22cc33dd44ee55ff",
"code": "TMP-9K4X-72QD",
"orderId": "6a7300aa11bb22cc33dd44ee",
"orderReference": "TK-TEMPO-20260823-AB12",
"eventId": "6a7207c4b8e1a2f5c9d04e33",
"performanceId": "6a72089e1f4c8b0d3e5a9c11",
"ticketTypeId": "6a7209f2c3d4e5f60718293a",
"venueId": "6a42356a296cb2dfe6ba1c7f",
"status": "valid",
"source": "api",
"holder": {
"name": "Ana",
"lastName": "Ruiz",
"documentType": "dni",
"documentNumber": "12345678Z"
},
"email": "ana@ejemplo.com",
"pricePaid": { "amount": 1800, "currency": "EUR" },
"checkedInAt": null,
"includes": [
{ "key": "copa", "name": "Consumición", "quantity": 1, "used": 0 }
],
"createdAt": "2026-08-23T18:02:11.000Z"
}
| Campo | Nota |
|---|---|
code | Lo que hay dentro del QR y lo que se puede teclear a mano |
status | valid, used o void |
holder | null en las entradas al portador. Solo las nominativas lo llevan |
checkedInAt | Cuándo entró. null si no ha entrado |
includes | Consumiciones, ropero y demás, con cuántas quedan por consumir |
pricePaid | Lo que se pagó por esta entrada, en céntimos |
El objeto Ticket no incluye la firma que hace válida una entrada, y no hay ningún endpoint que la devuelva. Quien la tuviera junto al código podría fabricar un QR que pasa el control. La API te da el code, que sirve para consultar y para validar contra el servidor — nunca el material con el que se falsifica.
Esto significa que no puedes generar tus propios QR de Tickeep. Si necesitas imprimir entradas o mostrarlas en tu app, lo que se distribuye es el PDF y el QR que emite Tickeep.
Validar en puerta
/tickets/{code}/check-inMarca una entrada como usada. Para tornos, lectores y software de puerta propio.
{
"performanceId": "6a72089e1f4c8b0d3e5a9c11",
"dryRun": false,
"token": "…"
}
| Campo | Notas |
|---|---|
performanceId | Opcional pero muy recomendable |
dryRun | true devuelve el veredicto sin consumir la entrada |
token | La firma del QR, si la tienes. Si falta, la validación se autoriza por el permiso de la clave |
Todos los campos son opcionales; un cuerpo vacío es válido.
Responde 200 siempre
Que una entrada esté repetida, anulada o sea de otra fecha no es un error de tu petición: es el resultado del control. Así que la respuesta es 200 con un campo result.
Reservar los códigos HTTP de error para los fallos de verdad es lo que te permite distinguir «esta persona no pasa» de «tu integración está rota». Si un alreadyUsed fuera un 409, tu manejador de errores no sabría cuál de las dos cosas ha ocurrido.
{
"result": "valid",
"ticket": { "…": "el objeto Ticket, ya con su estado nuevo" }
}
Los veredictos
result | Qué ha pasado | Qué haces en la puerta |
|---|---|---|
valid | Entrada correcta, ya consumida | Pasa |
alreadyUsed | Ya se usó. ticket.checkedInAt dice cuándo | No pasa. Enseña la hora |
void | Anulada (devolución, cancelación) | No pasa |
wrongEvent | Es de otro evento | No pasa |
wrongPerformance | Es de otra fecha del mismo evento | No pasa. Suele ser una confusión honesta |
invalidToken | El token del QR no cuadra. Posible falsificación | No pasa |
notFound | Ese código no existe | No pasa |
Solo valid consume la entrada. Ninguno de los demás la toca.
Manda siempre performanceId
Si no mandas performanceId, la entrada de la función de mañana escaneada hoy se marca como usada. Y mañana, cuando esa persona llegue de verdad, recibirá alreadyUsed.
Con performanceId, ese escaneo devuelve wrongPerformance y no consume nada.
Es un campo opcional en el contrato porque hay flujos —comprobar un código por teléfono, por ejemplo— donde no se sabe la fecha. En un lector de puerta, mándalo siempre.
dryRun
dryRun: true te da el veredicto sin consumir la entrada. Es lo que usa un torno para enseñar la ficha del asistente antes de abrir, o un portero que quiere comprobar algo sin comprometerse:
// 1. Consulta: qué tengo delante
const { result, ticket } = await tickeep.checkIn(code, { performanceId, dryRun: true })
if (result !== 'valid') return mostrarRechazo(result)
mostrarFicha(ticket) // nombre, tarifa, zona, consumiciones
// 2. Cuando la persona pasa de verdad
await tickeep.checkIn(code, { performanceId })
Cuidado con el hueco entre las dos llamadas: si haces la consulta y no completas la validación, la entrada sigue sin usar. Es correcto —no ha entrado nadie— pero tu interfaz tiene que dejarlo claro.
Dos lectores a la vez
La entrada se consume con una operación atómica. Si dos lectores escanean el mismo código en el mismo instante, uno recibe valid y el otro alreadyUsed. No hay un caso en el que los dos pasen.
Es lo que hace que puedas poner cuatro puertas en paralelo sin coordinarlas entre sí.
El token del QR
Si tu lector consigue leer el token del QR, mándalo en token y se verifica. Si no, la validación se autoriza por el permiso de la clave, igual que cuando un portero teclea un código a mano.
Un token presente pero incorrecto devuelve invalidToken y no consume nada.
Auditoría
Una validación hecha por API queda registrada a nombre de la clave, no de una persona. En el panel se distingue de las que hace el equipo con la app. Si necesitas saber quién validó qué en cada puerta, dale una clave distinta a cada puesto.
Lo que no está aquí
- Anular una entrada. Se hace desde el panel o devolviendo el pedido.
- Deshacer un check-in. Si alguien se equivoca en la puerta, se corrige desde el panel.
- Consumir una consumición del campo
includes. El contrato ya declara el campo con su contadorused, pero el consumo todavía no está expuesto por API. - Validar sin conexión. La API necesita red en cada escaneo. Para una puerta sin cobertura, lo que hay es la app de Tickeep, que está hecha para eso — ver escanear entradas.