Referencia de la API
Cada ruta que sirve la API, quién puede llamarla, y cómo funcionan el inicio de sesión, los permisos, los espacios de trabajo, las reservas, los pagos, los errores, las listas y los límites.
Para el paquete Full Stack
URL base y formato de respuesta
Cada ruta se sirve bajo el prefijo /api. En local, la URL base es http://localhost:8000/api. En un servidor es la dirección de tu API seguida de /api, el mismo valor que leen ambos frontends en NEXT_PUBLIC_API_BASE_URL (Variables de entorno). Las imágenes se sirven fuera del prefijo, en /media/….
Las rutas del sitio web son públicas o aceptan el token de un asistente; las del panel necesitan el token bearer de un miembro del personal, y la mayoría también un permiso. Los cuerpos de las peticiones son JSON, salvo las subidas de archivos. Cada respuesta llega en el mismo sobre:
{
"success": true,
"data": { },
"message": ""
}data contiene el resultado. message es una frase corta que rellenan algunas escrituras, en el idioma de la petición, y vacío en los demás casos. El dinero es un número entero de unidades menores con su currency (price_minor: 2000 son 20,00), y cada fecha es una cadena ISO en UTC; cada evento lleva además su time_zone.
La comprobación de estado no necesita token:
curl http://localhost:8000/api/health{"success":true,"data":{"status":"ok","database":"up"},"message":""}Cuando no se puede leer la base de datos, sigue respondiendo 200, con "status":"degraded" y "database":"down". La comprobación de estado de la imagen de Docker lee ese campo.
Errores
Un fallo mantiene el envoltorio, con success: false y el estado HTTP:
{
"success": false,
"data": null,
"message": "…",
"errors": { "email": ["…"] },
"code": "SEAT_UNAVAILABLE",
"details": { "seats": ["A12"] }
}messagees una frase en el idioma de la petición.errorsaparece en un fallo de validación, con los problemas por campo, indexados por la ruta que envió el cliente (comotitle.enoattendee.email).- Un campo desconocido en un cuerpo se rechaza con
400, yerrorslo nombra. El registro, por ejemplo, acepta solo los campos listados abajo. codeydetailsaparecen cuando una pantalla reacciona a un rechazo concreto:SEAT_UNAVAILABLEcon los asientos tomados,HOLD_EXPIRED,SOLD_OUT,ALREADY_ADMITTEDcon la primera admisión,VERSION_CONFLICT,NOT_READYcon lo que falta,COOLDOWNconretry_afteren segundos.- Una ruta protegida sin token, o con uno caducado, responde
401; un token sin el permiso responde403. - Una petición que supera un límite responde
429.
Cabeceras
| Encabezado | Se envía con | Qué lleva |
|---|---|---|
Authorization: Bearer … | Rutas del personal y de asistentes | El token de POST /api/auth/login (personal) o POST /api/customer-auth/login (asistente). Los dos tipos no son intercambiables |
X-Workspace-Id | Rutas del personal | El espacio de trabajo al que se dirige la petición. Uno al que el miembro no pertenece se ignora y se usa el propio |
X-Hold-Token | Una reserva y el pago hecho desde ella | El secreto de la reserva, devuelto una sola vez cuando se crea la reserva |
X-Order-Token | Rutas de pedidos de un invitado | El secreto del pedido, devuelto una sola vez por POST /api/checkout. Los pedidos propios de un asistente con sesión iniciada solo necesitan su token |
Idempotency-Key | POST /api/holds, POST /api/checkout, POST /api/admin/orders/:reference/refunds | Un UUID creado cuando se abre el formulario. Un reintento con la misma clave y el mismo cuerpo devuelve la primera respuesta en lugar de hacer el trabajo dos veces; sin ella, la petición se rechaza |
Accept-Language | Cualquier ruta | ar para mensajes en árabe; cualquier otro valor responde en inglés |
Los textos de eventos, recintos y tipos de entrada llevan ambos idiomas como { "en": "…", "ar": "…" } diga lo que diga Accept-Language, y el cliente elige uno, recurriendo al inglés cuando el árabe está vacío.
Listas y paginación
{ "data": [ ], "page": 1, "limit": 10, "total": 36, "totalPages": 4 }- La mayoría de las listas se paginan con
pageylimit, con un máximo de 100 por página: 9 eventos por página en el sitio web, y por defecto 10 eventos, recintos y asistentes y 8 pedidos en el panel. Varias devuelven ademáscountspor pestaña o estado. - Las listas de equipo, roles y ajustes del sitio se paginan con
pageypage_count, y las consultas conpageypage_size(10 por defecto, como máximo 50). - Las listas del panel llegan con los actualizados más recientemente primero, con el id como desempate, así que la paginación es estable. El catálogo del sitio web llega con lo más cercano primero.
- Los filtros de la lista del equipo (
email,name,phone) se combinan: una fila debe coincidir con todos los dados.namecoincide con el nombre, el apellido, el nombre de usuario o el nombre completo.
Inicio de sesión
Iniciar sesión como miembro del personal
Terminalcurl -X POST http://localhost:8000/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"YOUR_EMAIL","password":"YOUR_PASSWORD"}'Usa una de las cuentas del panel de Instalación, o la tuya.
data.access_tokenes el token, contoken_typeBearery el miembro del personal con sus roles y permisos. El token duraJWT_EXPIRATION,7dpor defecto, yexpires_ininforma de ese valor tal como está escrito.GET /api/auth/medevuelve al miembro del personal con sesión iniciada con sus roles y permisos.Llama a una ruta protegida
Terminalcurl http://localhost:8000/api/admin/orders \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "X-Workspace-Id: 1"
- Un correo desconocido y una contraseña incorrecta responden ambos
401con el mismo mensaje. - Diez inicios de sesión fallidos desde una misma dirección en 15 minutos responden
429hasta que el fallo más antiguo cumple 15 minutos (RATE_LIMIT_LOGIN). Los inicios de sesión correctos no se cuentan. Los inicios de sesión del personal y de los asistentes se cuentan por separado. - Las cuentas del personal vienen de los datos de ejemplo o de la página Team; no hay registro de personal. Un cliente cierra sesión olvidando su token.
GET /api/admin/workspace/membershipslista los espacios de trabajo a los que pertenece el miembro, los suyos primero. Envía el id del elegido comoX-Workspace-Id.
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/auth/login | Cualquiera | Inicio de sesión del personal: email, password |
GET | /api/auth/me | Cualquier miembro del personal con sesión iniciada | El miembro del personal con sesión iniciada, sus roles y permisos |
GET | /api/admin/workspace/memberships | Cualquier miembro del personal con sesión iniciada | Los espacios de trabajo del miembro, para el selector de la barra de navegación |
Permisos
Las rutas del personal comprueban un permiso llamado <area>.<action>. Un miembro tiene todos los permisos de todos los roles que posee, y el rol es el mismo en cada espacio de trabajo al que pertenece. Los 29 permisos y los cuatro roles de ejemplo (Owner, Manager, Finance, Check-in) están listados en Equipo, roles y espacios de trabajo.
Eventos, recintos y organizadores en el sitio web
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/public/events | Cualquiera | Eventos públicos próximos, los más cercanos primero. q (título, resumen, recinto, ciudad u organizador), category, city, venue y organiser (slugs), from y to (YYYY-MM-DD), page, limit. Los borradores, los eventos no listados y los eventos que han terminado se dejan fuera |
GET | /api/public/events/cities | Cualquiera | Las ciudades con eventos próximos y cuántos tiene cada una, para el filtro de ciudad |
GET | /api/public/events/:slug | Cualquiera | Un evento completo: descripción, agenda, el recinto con su dirección, accesibilidad, transporte y ubicación, el código de sesión, y los tipos de entrada con precio, comisión, plazas restantes y el límite por pedido. Un evento cancelado responde con status: cancelled |
GET | /api/public/sessions/:code/availability | Cualquiera | Disponibilidad en vivo para el mapa de asientos: el reloj del servidor, hold_seconds, max_per_order, la comisión, los tipos de entrada, el plano de asientos publicado (o null para entrada general) y cada asiento como available, held, sold o unavailable |
GET | /api/public/categories | Cualquiera | Las categorías de eventos |
GET | /api/public/organisers | Cualquiera | Los organizadores |
GET | /api/public/organisers/:slug | Cualquiera | Un organizador con hasta 24 de sus próximos eventos y su total |
GET | /api/public/venues | Cualquiera | Los recintos, con sus próximos eventos y sus asientos |
GET | /api/public/venues/:slug | Cualquiera | Un recinto, con su plano de asientos publicado |
GET | /api/public/settings | Cualquiera | Lo que el sitio web necesita para poner precio y hora a una compra: el nombre del espacio de trabajo, currency, fee_bps (la comisión de reserva que paga el asistente en cada entrada, 300 es un 3 %), hold_seconds, max_per_order, time_zone, support_email, payment_methods y mail_simulated (verdadero mientras los correos se escriben en el registro de la API) |
GET | /api/settings/public | Cualquiera | El site_name, contact_email y contact_city del sitio |
Los ingresos del organizador nunca forman parte de una respuesta pública.
Cuentas de asistentes
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/customer-auth/register | Cualquiera | Registro: first_name, last_name, email, password (de 8 a 72 caracteres con una letra y un dígito), terms_accepted (true), y opcionalmente role (attendee u organiser, nunca se lee). Cualquier otro campo responde 400 nombrándolo. Responde 201, con sesión iniciada al instante, y envía un código de seis dígitos |
POST | /api/customer-auth/login | Cualquiera | Inicio de sesión del asistente: email, password, y remember para un token de 30 días en lugar de uno de un día |
POST | /api/customer-auth/logout | Cualquiera | Responde { signed_out: true }; los tokens no guardan estado, así que el cliente olvida su copia |
POST | /api/customer-auth/forgot-password | Cualquiera | email. Envía un enlace de restablecimiento válido durante una hora cuando la cuenta existe, y responde igual en ambos casos |
POST | /api/customer-auth/reset-password | Cualquiera | token (del enlace) y la nueva password. Un enlace caducado o ya usado responde 400 con TOKEN_EXPIRED |
POST | /api/customer-auth/verify-email | Un asistente con sesión iniciada | code, los seis dígitos del correo, válido durante 24 horas. Los pedidos comprados con esa dirección como invitado se unen a la cuenta |
POST | /api/customer-auth/resend-verification | Un asistente con sesión iniciada | Envía un código nuevo; como máximo una vez por minuto (429 con COOLDOWN y retry_after) |
GET | /api/me | Un asistente con sesión iniciada | El perfil del asistente |
PATCH | /api/me | Un asistente con sesión iniciada | Cambia first_name, last_name, email, marketing_emails o reminder_emails |
GET | /api/me/saved | Un asistente con sesión iniciada | Eventos guardados, como tarjetas |
GET | /api/me/saved/slugs | Un asistente con sesión iniciada | Solo los slugs de los eventos guardados, para los botones de corazón |
PUT | /api/me/saved/:slug | Un asistente con sesión iniciada | Guardar un evento |
DELETE | /api/me/saved/:slug | Un asistente con sesión iniciada | Quitar un evento de guardados |
GET | /api/me/tickets | Un asistente con sesión iniciada | Las entradas del asistente como upcoming y past, una tarjeta por pedido |
GET | /api/me/tickets/:reference | Un asistente con sesión iniciada | Los pases de un pedido, con los códigos QR y los enlaces de descarga |
GET | /api/me/orders | Un asistente con sesión iniciada | Los pedidos del asistente |
GET | /api/me/orders/:reference | Un asistente con sesión iniciada | El recibo de un pedido, con su línea de tiempo |
El registro está limitado a 10 por dirección en 10 minutos, y las solicitudes de restablecimiento de contraseña a 5. Mientras no haya una clave de correo, los códigos y los enlaces se escriben en el registro de la API, y mail_simulated lo indica.
Reservas y pago
Una compra son dos llamadas: reservar los asientos o plazas, y luego pagar desde la reserva. Ambas funcionan para un invitado y para un asistente con sesión iniciada, cuyo token se lee cuando se envía.
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/holds | Cualquiera | Reserva { session_code, seats: ["A12", "B12"] } para asientos reservados, o { session_code, ticket_type_id, quantity } para entrada general, de 1 a 8 a la vez. Necesita Idempotency-Key. Responde 201 con la reserva, su expires_at y el reloj del servidor, y su token, que se muestra una sola vez |
GET | /api/holds/:id | El propietario de la reserva, con X-Hold-Token | Lee la reserva |
PATCH | /api/holds/:id | El propietario de la reserva, con X-Hold-Token | Sustituye la selección; el plazo no se mueve |
DELETE | /api/holds/:id | El propietario de la reserva, con X-Hold-Token | Libera los asientos ahora |
GET | /api/checkout/methods | Cualquiera | Los métodos de pago ofrecidos, cada uno con provider y live |
POST | /api/checkout | El propietario de la reserva, con X-Hold-Token | hold_id, attendee (first_name, last_name, email), provider (stripe, paypal o simulated) y terms_accepted. Necesita Idempotency-Key. Responde 201 con order_reference, status, redirect_url y access_token, el secreto del pedido, que se muestra una sola vez. El Accept-Language de la petición (ar, si no en) se guarda en el pedido como locale, el idioma de cada correo sobre él |
- Una reserva dura el tiempo de reserva del espacio de trabajo (
hold_seconds, diez minutos en los datos de ejemplo), contado con el reloj del servidor. Pasado ese tiempo, la reserva responde410conHOLD_EXPIREDy los asientos vuelven a estar libres. - Un asiento que otra persona tiene reservado o compró responde
409conSEAT_UNAVAILABLEy los asientos endetails.seats; un tipo de entrada completo respondeSOLD_OUT; más del límite por pedido respondeTOO_MANY. - Envía el navegador a
redirect_url: la página propia de Stripe o PayPal, o la página del simulador del sitio web. Los datos de la tarjeta nunca se envían a esta API. - Una reserva cuyo total es 0 no necesita
provider: el pedido se confirma al instante con el proveedorfreey el estadopaid, yredirect_urles su página de confirmación.
Pedidos, archivos de entradas y pagos
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/orders/:reference/status | El asistente del pedido, o un invitado con X-Order-Token | status (pending_payment, paid, payment_failed, expired, payment_review, partially_refunded, refunded), el proveedor y el reloj del servidor, para la página que espera el pago |
GET | /api/orders/:reference/receipt | El asistente del pedido, o un invitado con X-Order-Token | El pedido con su evento, recinto, entradas (cada entrada pagada con su código QR), el estado del correo de entradas y los enlaces firmados de downloads |
POST | /api/orders/:reference/resend-email | El asistente del pedido, o un invitado con X-Order-Token | Vuelve a enviar las entradas a la dirección del pedido, en el idioma del Accept-Language de la petición. Responde 202, o 429 con COOLDOWN dentro del minuto siguiente al último envío |
GET | /api/orders/:reference/tickets.pdf | Cualquiera que tenga el enlace firmado | Todas las entradas del pedido en un solo PDF |
GET | /api/orders/:reference/calendar.ics | Cualquiera que tenga el enlace firmado | El evento como archivo de calendario |
GET | /api/tickets/:reference/pdf | Cualquiera que tenga el enlace firmado | Una entrada como PDF |
GET | /api/payments/return/paypal | Cualquiera | PayPal envía aquí al comprador: la API captura el pago y redirige a la página de espera del sitio web (o a su página de cancelado) |
POST | /api/payments/simulated/:reference/complete | La página del simulador, con el token del pedido | token y outcome (pay, fail o cancel). Responde 404 siempre que el simulador no se ofrece |
POST | /api/webhooks/:provider | Stripe o PayPal | stripe o paypal. La firma se comprueba contra STRIPE_WEBHOOK_SECRET o PAYPAL_WEBHOOK_ID; una ausente o incorrecta responde 401. Cada evento se atiende una sola vez, por muchas veces que se envíe |
- Los enlaces de descarga están firmados con
expysigy funcionan 30 minutos desde el recibo que los creó; uno caducado responde404, y volver a leer el recibo crea otros nuevos. Se construyen a partir dePUBLIC_API_URL. - Las entradas se emiten cuando el proveedor confirma el pago, mediante su webhook, el retorno de PayPal o el simulador. Stripe envía
checkout.session.completed,checkout.session.async_payment_succeeded,checkout.session.async_payment_failedyrefund.updated; PayPalPAYMENT.CAPTURE.COMPLETED,PAYMENT.CAPTURE.DENIEDyPAYMENT.CAPTURE.REFUNDED. - El simulador se ofrece mientras no haya definida una clave real de Stripe o PayPal;
PAYMENTS_SIMULATOR=onuofflo anula.
El formulario de contacto
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
POST | /api/leads | Cualquiera | name, email, subject (general, tickets, organisers, scale, press), message (de 10 a 2000 caracteres) y client_token (un UUID v4). Responde 201 con { id, received_at } |
- Un
client_tokenrepetido devuelve el recibo del primer envío en lugar de guardar un segundo. - Un campo
companyrellenado se trata como un bot: la respuesta es igual y no se guarda nada. - Cada dirección puede enviar cinco en diez minutos; el siguiente responde
429.
Eventos
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/admin/events | Personal con events.view | Eventos con counts por pestaña. tab (all, published, draft, ended), q, category, status, venue (id), from, to, sort (starts_at, si no la última actualización), order (asc, desc), page, limit |
GET | /api/admin/events/:id | Personal con events.view | Un evento para el editor, con su lista de comprobación readiness, version y el inicio y el fin en hora local |
POST | /api/admin/events | Personal con events.edit | Crea un borrador: title, summary, description (cada uno en, ar), category (slug), venue_id, color (pink, yellow, teal, blue), admission_mode (reserved, general), visibility (public, unlisted), starts_local, ends_local, time_zone, agenda y ticket_types (title, price_minor, capacity, y opcionalmente description, max_per_order, status), opcionalmente slug |
PATCH | /api/admin/events/:id | Personal con events.edit | Guarda los mismos campos con la version que cargó el editor. Un guardado más reciente responde 409 con VERSION_CONFLICT; el precio de un tipo de entrada vendido está bloqueado (PRICE_LOCKED) |
POST | /api/admin/events/:id/publish | Personal con events.publish | Pone un borrador a la venta. Uno que no está listo responde 400 con NOT_READY y lo que falta |
POST | /api/admin/events/:id/unpublish | Personal con events.publish | Vuelve a borrador: las ventas se detienen y las reservas se liberan, las entradas ya vendidas siguen siendo válidas |
POST | /api/admin/events/:id/cancel | Personal con events.publish | { confirm }, el slug del evento escrito completo. Las ventas y la admisión se detienen, y se envía un correo al titular de cada pedido pagado. Los reembolsos se hacen después, pedido por pedido |
POST | /api/admin/events/:id/duplicate | Personal con events.edit | Un borrador nuevo con los mismos detalles y tipos de entrada, y sin ventas |
POST | /api/admin/events/:id/archive | Personal con events.publish | Archiva un borrador, o un evento que ha terminado o se ha cancelado |
GET | /api/admin/events/:id/attendees | Personal con events.view | Las entradas del evento con titular, asiento, tipo, estado y hora de admisión. q, status (admitted, not_admitted, void), page, limit |
Recintos y planos de asientos
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/admin/venues | Personal con venues.view | Recintos. q, city, page, limit |
GET | /api/admin/venues/map | Personal con venues.view | El marcador de cada recinto para el mapa |
GET | /api/admin/venues/:id | Personal con venues.view | Un recinto con sus planos |
POST | /api/admin/venues | Personal con venues.edit | Añade un recinto: name (en, ar), address, city, time_zone, capacity, accessibility (en, ar), y opcionalmente slug, transit, location (latitude, longitude) |
PATCH | /api/admin/venues/:id | Personal con venues.edit | Cambia cualquiera de esos campos |
GET | /api/admin/venues/:id/layouts | Personal con venues.view | Las versiones del plano del recinto |
GET | /api/admin/venues/:id/layouts/:version | Personal con venues.view | Una versión con sus asientos |
POST | /api/admin/venues/:id/layouts | Personal con venues.edit | Empieza un borrador nuevo |
PATCH | /api/admin/venues/:id/layouts/:version | Personal con venues.edit | Guarda el borrador: rows (de 1 a 40), seats_per_row (de 1 a 60), aisles_after (hasta 6), seats (label, y opcionalmente accessible, companion, disabled, price_tier de 0 a 9) y loaded_at. Un borrador guardado por otra persona desde entonces responde 409 con VERSION_CONFLICT |
POST | /api/admin/venues/:id/layouts/:version/publish | Personal con venues.edit | { acknowledged: true }. Publica el borrador como el plano del recinto; los asientos ya vendidos conservan la versión con la que se vendieron. Se rechaza un plano vacío, o con más asientos que el aforo del recinto (OVER_CAPACITY) |
Pedidos, entradas y reembolsos
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/admin/orders | Personal con orders.view | Pedidos con counts por estado. status (paid, pending_payment, refunded, payment_failed, payment_review), event (slug), provider (stripe, paypal, simulated, free), q (referencia, correo o nombre), from, to, page, limit |
GET | /api/admin/orders/events | Personal con orders.view | Cada evento que tiene pedidos, para el filtro de la página de pedidos |
GET | /api/admin/orders/:reference | Personal con orders.view | Un pedido: entradas, reembolsos, la línea de tiempo del pago, un enlace a él en el panel del proveedor y su version |
GET | /api/admin/orders/:reference/refund-preview | Personal con refunds.create | Lo que devolvería reembolsar ?tickets=TKT-1042-2,…, por entrada |
POST | /api/admin/orders/:reference/refunds | Personal con refunds.create | Reembolsa entradas completas: tickets (de 1 a 8 referencias), reason (customer_request, event_cancelled, duplicate_order, event_changed, other), acknowledged (true) y order_version. Necesita Idempotency-Key. Responde 202 con el reembolso pending |
POST | /api/admin/refunds/:id/retry | Personal con refunds.create | Vuelve a enviar al proveedor un reembolso fallido |
POST | /api/admin/refunds/:id/restore | Personal con refunds.create | Cierra definitivamente un reembolso fallido; sus entradas vuelven a ser válidas |
POST | /api/admin/tickets/:reference/reissue | Personal con tickets.manage | Un código QR nuevo para una entrada válida; el código antiguo deja de funcionar en la puerta |
POST | /api/admin/tickets/:reference/void | Personal con tickets.manage | Anula una entrada gratuita. Una entrada pagada responde 409 con USE_REFUND: se reembolsa en su lugar |
Sus entradas se suspenden (refund_pending) en cuanto se pide el reembolso, así que la puerta las rechaza. El reembolso se resuelve cuando el proveedor lo confirma, unos segundos después en el simulador: las entradas se anulan entonces y sus asientos vuelven a la venta. Un reembolso fallido las mantiene suspendidas hasta que se reintenta o se restaura, lo que las vuelve a hacer válidas. Lee el pedido de nuevo para ver en qué punto está.
Control de acceso en la puerta
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/admin/check-in/sessions | Personal con checkin.scan | Las sesiones que este miembro puede escanear, desde hace un día en adelante, con los recuentos de admitidos y esperados y si las puertas están abiertas |
GET | /api/admin/check-in/sessions/:code/summary | Personal con checkin.scan | Admitidos, esperados, restantes y las alertas pendientes |
GET | /api/admin/check-in/sessions/:code/scans | Personal con checkin.scan | Los escaneos recientes, cada uno admitted, eligible, duplicate, wrong_session, void o not_found |
POST | /api/admin/check-in/sessions/:code/acknowledge | Personal con checkin.scan | Marca las alertas de la sesión como vistas |
POST | /api/admin/check-in/validate | Personal con checkin.scan | session_code y code: lo que leyó la cámara, o una referencia de entrada escrita como TKT-1042-1. Dice si la entrada puede entrar, sin admitirla |
POST | /api/admin/check-in/admit | Personal con checkin.scan | Lo mismo con client_request_id (un UUID), y admite la entrada. Una entrada que ya entró responde 409 con ALREADY_ADMITTED, cuándo y quién; WRONG_SESSION y TICKET_VOID también se rechazan |
GET | /api/admin/session-staff | Personal con admins.edit | Qué personal de control de acceso está asignado a qué sesiones |
PUT | /api/admin/session-staff/:code | Personal con admins.edit | Define el personal de puerta de una sesión: admin_ids, separados por comas |
Los miembros que pueden editar o publicar eventos llegan a todas las sesiones; los demás solo a las sesiones que tienen asignadas, y otra responde 403. Cada miembro puede hacer 120 comprobaciones por minuto.
Resumen, informes y exportaciones
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/admin/overview | Personal con overview.view | El resumen: totales, la serie de ventas, ventas por evento, proveedor y categoría, la puerta en vivo, los próximos eventos y lo que necesita atención. range (last_7_days, last_30_days, this_month, all), last_30_days por defecto |
GET | /api/admin/reports | Personal con reports.view | Las mismas cifras de ventas, para range, o from y to, y opcionalmente un event |
POST | /api/admin/reports/export | Personal con reports.export | Inicia un CSV: kind (orders, sales, attendees) y filters opcional. Responde 202 con su id |
GET | /api/admin/reports/exports/:id | Personal con reports.export | Cómo va la exportación; cuando está lista, su download_url |
GET | /api/admin/reports/exports/:id/download | Cualquiera que tenga el token del enlace | El archivo CSV. El enlace funciona durante una hora y se muestra una sola vez |
Los archivos CSV se escriben en EXPORT_DIR en segundo plano, y el enlace de descarga se construye a partir de PUBLIC_API_URL.
Espacio de trabajo, pagos y ajustes del sitio
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/admin/workspace | Personal con settings.view | El espacio de trabajo: nombre, correo de soporte, moneda, zona horaria, comisión de reserva (fee_bps), hold_seconds y max_per_order (solo lectura: son columnas cargadas desde back-end/src/database/seeders/data/settings.json), y notification_settings, los interruptores de la campana de notificaciones del equipo |
PATCH | /api/admin/workspace | Personal con settings.edit | Cambia name, support_email, currency (USD, EUR, GBP, AED, SAR), time_zone, fee_bps (de 0 a 2000, centésimas de porcentaje; el asistente siempre lo paga al pagar) o notification_settings (order_paid, refund_requested, checkin_alerts), con la version cargada. La moneda se bloquea cuando el espacio de trabajo ha vendido (CURRENCY_LOCKED). Cualquier otro campo, incluidos fee_payer, hold_seconds y max_per_order, responde 400 |
GET | /api/admin/payment-providers | Personal con settings.view | El configured, live y offered de cada proveedor. Las claves permanecen en el .env de la API y nunca se devuelven |
GET | /api/settings | Personal con settings.view | Todos los ajustes del sitio. search, category, page, page_count |
GET | /api/settings/:key | Personal con settings.view | Un ajuste por clave |
PATCH | /api/settings/:key | Personal con settings.edit | Cambiar el valor de un ajuste |
DELETE | /api/settings/:key | Personal con settings.edit | Eliminar un ajuste |
Equipo y roles
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/admins | Personal con admins.view | El equipo del espacio de trabajo. email, name, phone (deben coincidir todos los dados), page, page_count |
GET | /api/admins/statistics | Personal con admins.view | Recuentos para la lista del equipo |
GET | /api/admins/:id | Personal con admins.view | Un miembro, por id o nombre de usuario |
POST | /api/admins | Personal con admins.create | Añade un miembro: first_name, last_name, email, password y password_confirmation (6 caracteres o más), opcionalmente phone |
PATCH | /api/admins/:id | Personal con admins.edit | Cambia un miembro |
PATCH | /api/admins/:id/roles | Personal con admins.assign_roles | Define los roles de un miembro: role_ids |
DELETE | /api/admins/:id | Personal con admins.delete | Saca a un miembro del espacio de trabajo actual. La cuenta en sí se borra solo cuando era su último espacio de trabajo; data.removed responde workspace o account. Eliminarse a uno mismo responde 403 con REMOVE_SELF, y eliminar al último propietario del espacio de trabajo 409 con LAST_OWNER |
PATCH | /api/admins/profile | Cualquier miembro del personal con sesión iniciada | Cambia los propios first_name, last_name, email, phone, profile_picture o country_id del miembro con sesión iniciada. Un password o role_ids en el cuerpo responde 400: la contraseña tiene su propia ruta |
PATCH | /api/admins/profile/password | Cualquier miembro del personal con sesión iniciada | Cambia la propia contraseña del miembro con sesión iniciada: current_password, password, password_confirmation |
GET | /api/roles | Personal con roles.view | Roles. name, guard_name, created_from, created_to, page, page_count |
GET | /api/roles/statistics | Personal con roles.view | Recuentos para la lista de roles |
GET | /api/roles/select | Personal con roles.view | El id y el nombre de cada rol, para un selector |
GET | /api/roles/permissions | Personal con roles.view | Todos los permisos, agrupados por área |
GET | /api/roles/:id | Personal con roles.view | Un rol con sus permisos |
POST | /api/roles | Personal con roles.create | Añade un rol: name |
PUT | /api/roles/:id | Personal con roles.edit | Renombra un rol: name |
POST | /api/roles/:id/permissions | Personal con roles.assign_permissions | Define los permissions de un rol, por nombre |
DELETE | /api/roles/:id | Personal con roles.delete | Elimina un rol |
Consultas, notificaciones y subidas
| Método | Ruta | Quién puede llamarla | Qué hace |
|---|---|---|---|
GET | /api/leads | Personal con leads.view | Consultas del formulario de contacto, con recuentos por estado. status, q, received_within_days, page, page_size |
GET | /api/leads/:id | Personal con leads.view | Una consulta |
PATCH | /api/leads/:id | Personal con leads.edit | Define status (new, contacted, closed), notes o assigned_admin_id |
GET | /api/notifications | Cualquier miembro del personal con sesión iniciada | Las 30 notificaciones más recientes del miembro con sesión iniciada |
PATCH | /api/notifications/read-all | Cualquier miembro del personal con sesión iniciada | Marcarlas todas como leídas |
PATCH | /api/notifications/:id/read | Cualquier miembro del personal con sesión iniciada | Marca una como leída |
DELETE | /api/notifications/:id | Cualquier miembro del personal con sesión iniciada | Elimina una |
POST | /api/helpers/upload | Cualquier miembro del personal con sesión iniciada | Guarda un archivo (multipart file, con path para la carpeta, for para el ajuste de tamaño como venue, cover, logo o profile, y type). Las fotos se recodifican, con un máximo de 1920 píxeles de ancho; los vídeos se aceptan como MP4, WebM, MOV o M4V; 150 MB como máximo. Responde con las direcciones del archivo guardado |
Las notificaciones cubren pedidos pagados, solicitudes de reembolso, alertas de la puerta, consultas nuevas y conceptos de recinto terminados, y se conservan 30 días. Una subida no tiene permiso propio: lo que el archivo llega a ser lo comprueba la ruta que lo guarda. Los archivos van al bucket R2 cuando sus cinco variables están definidas, y a MEDIA_UPLOAD_DIR en caso contrario.
Límites por dirección
| Ruta | Límite | Variable |
|---|---|---|
POST /api/auth/login, POST /api/customer-auth/login | 10 inicios de sesión fallidos cada 15 minutos, cada uno contado por separado | RATE_LIMIT_LOGIN |
POST /api/customer-auth/register | 10 cada 10 minutos | Ninguno |
POST /api/customer-auth/forgot-password | 5 cada 10 minutos | Ninguno |
POST /api/leads | 5 cada 10 minutos | Ninguno |
POST /api/admin/check-in/validate, /admit | 120 por minuto por miembro del personal | Ninguno |
POST /api/customer-auth/resend-verification, POST /api/orders/:reference/resend-email | Una vez por minuto | Ninguno |
Una petición que supera un límite responde 429. Las cuentas están en la memoria de la API, así que un reinicio las borra. Detrás de un proxy inverso, define TRUST_PROXY para que cada visitante se cuente en su propia dirección.
Asistente de eventos con IA y sus conversaciones
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
La ruta de streaming del asistente, su lista de modelos, la aprobación de borradores y las conversaciones guardadas.
Estudio de recintos
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Las rutas del estudio: generaciones y los conceptos guardados en un recinto.
Servidor MCP
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
El endpoint MCP para agentes de programación y cómo se autoriza.
Actualizaciones en directo por WebSocket
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Los namespaces de Socket.IO que escucha el panel, sus eventos y cómo se autoriza una conexión.
Rutas del modo demostración
Incluido con tu compra. Inicia sesión para leerlo o ábrelo en tu descarga.
Las rutas que existen solo para una compilación de demostración pública.