Receta: mostrar tu cartelera
Pintar los eventos de tu sala en tu propia web, con tu diseño, a partir del catálogo de Tickeep.
Última actualización: 23 de agosto de 2026
El caso más frecuente y el más sencillo: tienes una web y quieres que la programación salga sola, sin copiar y pegar cada evento a mano.
Lo que necesitas: una clave con catalog:read. Nada más.
Ya lo sabes, pero aquí es donde más tienta saltárselo. La clave no puede estar en el JavaScript de tu web. CORS está deshabilitado en /api/v1, así que la llamada fallaría igualmente: tu servidor pide los datos, tu servidor los cachea, tu frontend habla con tu servidor.
El circuito
GET /venues → el venueId y el host de tu sala
GET /events?status=published → los eventos publicados
GET /performances?venueId=…&from=… → las fechas de cada uno
componer la URL de la imagen → con el host de la sala
1. La sala
Se hace una vez y se guarda en tu configuración: el id no cambia.
const { data: venues } = await tickeep.venues()
const sala = venues[0]
// sala.id → para filtrar el resto de llamadas
// sala.host → para componer las URLs de imagen
// sala.timezone → para formatear las horas
2. Los eventos publicados
const { data: eventos } = await tickeep.events({
venueId: sala.id,
status: 'published',
limit: 100,
})
status: 'published' no es opcional. Sin él te llegan los borradores, que son eventos que la sala todavía está montando, y publicarlos por accidente es el fallo clásico de la primera integración.
3. Las fechas
Un evento con type: 'single' tiene una fecha; uno multiPerformance o recurring puede tener muchas. Para un cartel, lo que quieres son las próximas:
const { data: fechas } = await tickeep.performances({
venueId: sala.id,
from: new Date().toISOString(),
limit: 100,
})
// Vienen en orden cronológico ascendente: la próxima primero
const activas = fechas.filter((f) => f.status === 'active')
Dos cosas:
Filtra las canceladas. status: 'cancelled' es una fecha que se ha caído. Sigue en el catálogo porque hay entradas vendidas que gestionar, pero no se anuncia.
Cruza con los eventos por eventId. El objeto Performance no repite el título del evento; lo tienes en el listado de eventos.
El objeto Event ya trae nextPerformanceAt, performanceCount y priceFrom. Para una rejilla de «próximos conciertos» con su «desde 18 €», eso puede bastarte sin pedir las fechas una por una.
4. Las imágenes
Los eventos devuelven imageId, no una URL. Se compone con el host de la sala:
function urlImagen(host: string, imageId: string, size?: 'thumbnail' | 'card' | 'hero') {
const base = `https://${host}/api/public/media/${imageId}`
return size ? `${base}?size=${size}` : base
}
// <img src={urlImagen(sala.host, evento.imageId, 'card')} />
Usa card en las rejillas y hero en las cabeceras. Sin size te llevas el original, que en un listado de veinte eventos son veinte imágenes grandes de más.
imageId puede ser null: la sala no siempre sube imagen. Ten una por defecto.
5. Cachea
Si tu cartelera pide /events cada vez que alguien entra en la página, una noche buena te comes las 120 peticiones por minuto y tu web se queda sin cartel. La API dice Cache-Control: private, no-store porque no debe cachearse en un CDN compartido, no porque no puedas cachearla tú.
Un minuto de caché ya cambia el problema por completo:
// Next.js App Router
export const revalidate = 60
export default async function Cartelera() {
const eventos = await obtenerCartelera() // llamada a Tickeep
return <Rejilla eventos={eventos} />
}
Si prefieres mantener una copia y refrescarla:
// Cada 5 minutos, solo lo que ha cambiado
const { data } = await tickeep.events({
venueId: sala.id,
updatedSince: ultimaSincronizacion,
limit: 100,
})
Ver paginación y sincronización.
6. El botón de comprar
Aquí hay dos caminos, y la decisión es tuya:
Enlazar a la web de venta de la sala. Lo más rápido. El comprador sale de tu web y compra en el dominio de la sala. Cero código de venta y cero responsabilidad sobre el cobro.
Vender desde tu web. Más trabajo, pero el comprador no se va. La receta entera está en vender desde tu web.
Cuando ticketing.mode es external, esa sala vende ese evento en otro sitio, y ticketing.externalUrl dice dónde. Un botón que llame a POST /orders fallará. Enlaza a externalUrl.
Ejemplo completo
import { TickeepPartnerClient } from '@tickeep/client'
const tickeep = new TickeepPartnerClient({ apiKey: process.env.TICKEEP_API_KEY! })
export async function obtenerCartelera() {
const { data: venues } = await tickeep.venues()
const sala = venues[0]
const [{ data: eventos }, { data: fechas }] = await Promise.all([
tickeep.events({ venueId: sala.id, status: 'published', limit: 100 }),
tickeep.performances({ venueId: sala.id, from: new Date().toISOString(), limit: 100 }),
])
const porEvento = new Map<string, typeof fechas>()
for (const f of fechas) {
if (f.status !== 'active' || !f.eventId) continue
const lista = porEvento.get(f.eventId) ?? []
lista.push(f)
porEvento.set(f.eventId, lista)
}
return eventos
.map((e) => ({
id: e.id,
titulo: e.title,
subtitulo: e.subtitle,
imagen: e.imageId ? `https://${sala.host}/api/public/media/${e.imageId}?size=card` : null,
desde: e.priceFrom,
edadMinima: e.minimumAge,
ventaExterna: e.ticketing.mode === 'external' ? e.ticketing.externalUrl : null,
fechas: porEvento.get(e.id) ?? [],
}))
.filter((e) => e.fechas.length > 0)
.sort((a, b) => a.fechas[0].startsAt.localeCompare(b.fechas[0].startsAt))
}
Formatear las horas
startsAt viene en UTC. Fórmatalo con la zona horaria de la sala, no con la del visitante:
function hora(iso: string, timezone: string) {
return new Intl.DateTimeFormat('es-ES', {
dateStyle: 'full',
timeStyle: 'short',
timeZone: timezone, // sala.timezone
}).format(new Date(iso))
}
Si usas la zona del navegador, un visitante desde Canarias verá que el concierto de Madrid empieza una hora antes. Es un error pequeño que genera muchos correos.
Y los precios
new Intl.NumberFormat('es-ES', { style: 'currency', currency: precio.currency })
.format(precio.amount / 100)
// → "18,00 €"
Divide por 100 al pintar, nunca antes. Ver convenciones.
Seguir por aquí
Salas, eventos, fechas y disponibilidad. Los endpoints de lectura con los que se construye una cartelera.
El circuito completo de una venta hecha desde tu propia web: disponibilidad, reserva, cobro y confirmación por webhook.
Cuántas peticiones por minuto admite una clave, cómo leer las cabeceras del contador y cómo diseñar una integración que no lo roce.