Referencia: pedidos
El flujo de venta en dos tiempos: reservar, cobrar y emitir. Con los cuatro endpoints que lo componen y qué hace cada uno.
Última actualización: 23 de agosto de 2026
Leer pedidos necesita orders:read. Crearlos y moverlos, orders:write —que ya incluye la lectura—.
Pedidos
La venta en dos tiempos: reservar el stock y después cobrar.
/ordersExige Idempotency-KeyReservar entradas y abrir un pedidoGET/ordersListar pedidosGET/orders/{reference}Abrir un pedido por su referenciaPOST/orders/{reference}/confirmConfirmar que has cobrado y emitir las entradasPOST/orders/{reference}/payment-linkGenerar un enlace para que pague el compradorPOST/orders/{reference}/cancelAnular una reserva y liberar el stockEl flujo, de un vistazo
Tickeep vende en dos tiempos, igual que una taquilla física: primero se aparta la entrada, después se cobra.
POST /orders → reserva el stock, estado "pending", 30 min
├── POST /orders/{ref}/confirm → has cobrado tú, fuera de Tickeep
└── POST /orders/{ref}/payment-link → que pague el comprador por la pasarela de la sala
POST /orders/{ref}/cancel → libera el stock ya, sin esperar a que caduque
Existe así porque cobrar tarda. Si la reserva y el cobro fueran la misma operación, entre que el comprador mete la tarjeta y el banco responde, otro podría llevarse la última entrada — y tendrías un cobro hecho sin entrada que entregar.
Los pedidos van por reference
TK-TEMPO-20260823-AB12
No por id. La referencia es lo que ve el comprador, lo que sale en su email y lo que te dicta por teléfono cuando llama. El id interno no le sirve a nadie fuera de la base de datos.
Crear un pedido
/ordersReserva el stock y crea el pedido en estado pending. Exige Idempotency-Key.
{
"venueId": "6a42356a296cb2dfe6ba1c7f",
"items": [
{ "ticketTypeId": "6a7209f2c3d4e5f60718293a", "quantity": 2 }
],
"customer": {
"email": "ana@ejemplo.com",
"name": "Ana Ruiz",
"phone": "600123456"
},
"channel": "online",
"invoice": true
}
| Campo | Obligatorio | Notas |
|---|---|---|
venueId | Sí | Debe estar dentro del ámbito de la clave |
items | Sí | Al menos un elemento. Varias tarifas en el mismo pedido, sin problema |
items[].ticketTypeId | Sí | De esa sala y a la venta |
items[].quantity | Sí | Entero mayor que cero |
customer.email | No | Sin él no se manda ningún email |
customer.name | No | |
customer.phone | No | |
channel | No | online (por defecto) o boxOffice |
invoice | No | false para no emitir factura. Ausente = sí |
Devuelve 201 con el objeto Order completo.
Nunca se mandan importes
Fíjate en que en el cuerpo no hay ni un solo importe. Mandas qué tarifa y cuántas, y el precio, el IVA y los gastos de gestión se calculan contra la base de datos de la sala. Si un cliente pudiera fijar el precio, podría venderse entradas a cero euros — y esa es una vulnerabilidad, no una funcionalidad.
Si tu web enseña un precio, sácalo de /availability y vuelve a comprobar el total del pedido que devuelve POST /orders antes de cobrar. Es el único número que cuenta.
channel
online(por defecto) — venta por internet. Cobra los gastos de gestión que tenga configurados la sala.boxOffice— venta en mostrador. Solo cobra gastos de gestión si la sala los tiene activados también para taquilla, que casi nunca es el caso.
Elige según dónde ocurre la venta de verdad. Si estás integrando el TPV físico de la sala, es boxOffice; si es tu web, es online.
invoice
invoice ausente o true emite factura. Solo false la evita. La asimetría es deliberada: una factura de más se ve y se rectifica, mientras que una que falta es un agujero fiscal que no avisa hasta el cierre del ejercicio.
Ponlo a false solo si esa venta ya se factura en otro sitio.
Idempotency-Key
Obligatoria. Sin ella:
{ "error": "invalid_input", "details": { "header": "Idempotency-Key", "reason": "required" } }
Entero en idempotencia.
La reserva caduca
El pedido nace con reservationExpiresAt 30 minutos por delante. Pasado ese punto, un proceso lo cancela solo y libera el stock.
Los estados que puedes recibir:
| Código | Motivo |
|---|---|
201 | Pedido creado, stock reservado |
400 invalid_input | Falta Idempotency-Key, o falta venueId |
403 forbidden | La clave no llega a esa sala, o le falta orders:write |
409 sold_out | Sin stock, aforo completo o promoción agotada |
409 idempotency_key_reuse | Misma clave, cuerpo distinto |
422 unprocessable | Tarifa de otra sala, fuera de ventana, fuera de canal, o items vacío |
Confirmar el cobro
/orders/{reference}/confirmRegistra que el cobro ocurrió fuera de Tickeep y emite las entradas al momento.
{
"paymentMethod": "cardTerminal",
"reference": "AUT-884213"
}
| Campo | Valores |
|---|---|
paymentMethod | cash · cardTerminal · external (por defecto) |
reference | Referencia del datáfono o de tu pasarela, para cuadrar con el extracto |
Este endpoint no mueve dinero. Registra que el dinero se movió en otro sitio: tu datáfono, tu pasarela, efectivo en mano. Si lo que quieres es que el comprador pague por la pasarela de la sala, lo tuyo es el enlace de pago.
Usa external cuando has cobrado por tu cuenta y no quieres detallar cómo. cash y cardTerminal cuando estás integrando una taquilla física y sí importa distinguirlo en los informes.
La respuesta trae las entradas
{
"order": { "…": "el pedido, ya con status: paid" },
"ticketsStatus": "issued",
"tickets": [
{ "code": "TMP-9K4X-72QD", "status": "valid", "…": "…" }
]
}
Las entradas se emiten en línea, no en segundo plano, porque quien confirma un cobro en mostrador necesita el código ya, no dentro de treinta segundos.
ticketsStatus | Qué significa |
|---|---|
issued | Emitidas. Están en tickets |
pending | Las emitirá el proceso de fondo en segundos. Vuelve a consultar el pedido |
failed | Algo falló en la emisión. El cobro está registrado; escríbenos con el X-Request-Id |
pending no es un error: significa que otro proceso ganó la carrera y las está emitiendo. El pedido está cobrado igualmente.
Errores
| Código | Motivo |
|---|---|
403 forbidden | details.reason: "notAnApiOrder" — ese pedido no lo creaste por API |
404 not_found | La referencia no existe o está fuera del ámbito de la clave |
409 conflict | details.reason: "notPending" — ya no estaba pendiente |
422 unprocessable | paymentMethod no admitido |
Un pedido nacido en la web de venta de la sala o en la taquilla del panel no se confirma ni se cancela por API. Cada canal tiene su circuito de cobro y su auditoría, y mezclarlos dejaría un rastro imposible de cuadrar.
Un 409 conflict casi siempre es una de dos: alguien ya lo confirmó, o la reserva caducó mientras cobrabas. Lee el pedido con GET /orders/{reference} para saber cuál de las dos, y si caducó, abre la venta otra vez.
Enlace de pago
/orders/{reference}/payment-linkDevuelve una URL para que pague el comprador por la pasarela de la sala.
Sin cuerpo. Devuelve 201:
{
"url": "https://entradas.salatempo.com/taquilla/TK-TEMPO-20260823-AB12?k=…",
"expiresAt": "2026-08-23T18:30:00.000Z"
}
El dinero entra por Redsys o Stripe, según lo que tenga configurado la sala. Puedes mandarla por email, enseñarla como QR en un mostrador o abrirla en tu web.
Cuando el comprador paga, el webhook de la pasarela marca el pedido como pagado y dispara la emisión y el envío de las entradas por el camino de siempre. Tú te enteras con el webhook order.paid — no hace falta que preguntes en bucle.
Caduca con la reserva. El expiresAt es el mismo reservationExpiresAt del pedido: pasado ese punto el pedido se cancela solo y el enlace deja de valer.
El pedido tiene que estar pending. Si no, 409 conflict.
Lleva un token propio, distinto del que descarga las entradas. Es a propósito: este enlace acaba compartido por canales que no controlamos, y no debe servir además para bajarse las entradas del pedido.
Cancelar
/orders/{reference}/cancelAnula una reserva pendiente y libera el stock en el acto.
Sin cuerpo. Devuelve el pedido con status: "cancelled".
Llámalo en cuanto sepas que la compra no va a completarse: el comprador cierra la pestaña, abandona el carrito, el pago falla. Si no lo haces, esas entradas siguen bloqueadas media hora y no se le pueden vender a nadie.
Solo cancela pedidos pendientes. Un pedido ya pagado no se cancela: eso es una devolución, mueve dinero real y se hace desde el panel. Ver devoluciones.
Sobre un pedido pagado responde 409 conflict con details.reason: "notPending".
Consultar pedidos
/ordersListado, del más reciente al más antiguo.
| Parámetro | Valores |
|---|---|
venueId | Id de sala |
status | pending · paid · cancelled · failed · refunded |
email | Email exacto del comprador |
updatedSince | Fecha ISO 8601, para sincronización incremental |
limit | 1–100, por defecto 25 |
cursor | El nextCursor de la página anterior |
# Ventas pagadas de una sala desde una fecha
curl -G https://app.tickeep.com/api/v1/orders \
-H "Authorization: Bearer $TICKEEP_API_KEY" \
--data-urlencode "venueId=$VENUE" \
--data-urlencode "status=paid" \
--data-urlencode "updatedSince=2026-08-01T00:00:00Z" \
--data-urlencode "limit=100"
/orders/{reference}Un pedido por su referencia.
Devuelve todos los pedidos de la sala, no solo los creados por API: también los de la web de venta y los de taquilla. El campo source te dice de dónde vino cada uno (online, boxOffice o api).
Campos que conviene mirar
| Campo | Nota |
|---|---|
status | El estado del pedido |
source | Canal de origen |
paymentMethod | cash, cardTerminal, redsys, stripe, free, demo o pending |
lines[].eventName | Congelado en el momento de la venta, no el nombre actual del catálogo |
subtotal / serviceFee / total | Los tres importes, en céntimos |
ticketsIssued | Si ya existen las entradas |
reservationExpiresAt | Cuándo caduca la reserva. null si ya no está pendiente |
paidAt | Cuándo se cobró |
eventName y ticketTypeName guardan lo que se llamaban el día de la venta. Si la sala renombra el evento después, el pedido sigue diciendo lo que el comprador compró. Es lo correcto para una factura, y explica por qué a veces no coinciden con el catálogo actual.
Ciclo de estados
pending ──confirm──────────────→ paid ──(devolución en el panel)──→ refunded
│ ↑
├──cancel──→ cancelled │
│ │
└──caduca a los 30 min──→ cancelled
│
(pago por enlace) ─────────────┘
failed aparece cuando un cobro por pasarela se rompe a mitad. No es un estado al que puedas llevar un pedido tú.
Lo que no se puede hacer
- Modificar un pedido. Ni cambiar cantidades, ni añadir líneas, ni corregir el email. Cancela y crea otro.
- Reembolsar. Mueve dinero real; se hace desde el panel, con una persona detrás.
- Confirmar pedidos de otros canales. Ver más arriba.
Seguir por aquí
Cómo funciona la cabecera Idempotency-Key, por qué es obligatoria al crear un pedido y por qué no lo es en el resto.
El circuito completo de una venta hecha desde tu propia web: disponibilidad, reserva, cobro y confirmación por webhook.
Consultar entradas emitidas y validarlas en puerta desde tu propio hardware, con el veredicto que devuelve cada escaneo.