# menta tech — Full integration documentation (es)
> Concatenated dump of every guide for AI agents. Index: https://docs.mentatech.io/llms.txt?locale=es
---
# Integración con menta tech
## Descripción general
menta tech es una capa de infraestructura que habilita mercados secundarios oficiales para plataformas de ticketing. Opera completamente sobre tus sistemas existentes. Tu plataforma sigue siendo la fuente de verdad para usuarios, tickets, ownership y fulfillment, mientras que menta provee la orquestación, la lógica y los flujos de usuario necesarios para operar una reventa segura y controlada.
La integración está diseñada para ser simple. En lugar de exponer decenas de endpoints desconectados, menta se organiza alrededor de un conjunto reducido de decisiones arquitectónicas que definen cómo funciona la reventa dentro de tu entorno. Una vez que estas decisiones están definidas, la experiencia de reventa pasa a ser totalmente automatizada y gobernada por reglas desde menta.
Esta documentación te va a guiar a través de esas decisiones. Cada una representa un punto de contacto entre tu plataforma y menta, y en conjunto conforman una integración completa y preparada para el futuro.
## En qué consiste la integración
La integración se estructura en torno a siete componentes clave. Cada uno responde una pregunta específica sobre cómo debe operar la reventa dentro de tu ecosistema:
- **Sincronización de Eventos (Event Sync)** - Cómo menta tech recibe la información de tus eventos para habilitar la reventa.
- **Estructura de la información** - Cómo se representan tus categorías o niveles de acceso para que el inventario de reventa pueda agruparse y mostrarse correctamente, en cuanto a zonas y niveles de precio.
- **Sincronización de tickets** - Cómo menta tech conoce la información de los dueños de los boletos para que los usuarios puedan publicar, gestionar y transferir tickets de reventa.
- **Autenticación** - Cómo se autentican los usuarios entre tu plataforma y menta tech, bilateralmente, usando tu sistema de identidad existente.
- **Acceso a vender** - Cómo ingresan los usuarios al flujo de publicación en reventa desde tu plataforma.
- **Acceso a comprar** - Cómo se muestra el inventario de reventa en tus páginas de evento y cómo ingresan los usuarios al flujo de compra en reventa.
- **Entrega del boleto adquirido en reventa** - Cómo menta tech te notifica luego de que la reventa se concretó para que tu sistema pueda darle el boleto al comprador.
Esta es toda la superficie de integración. No hay requisitos ocultos adicionales. Todas las capacidades de reventa que ofrece menta tech, desde CTAs dinámicos hasta componentes embebidos y balanceo automatizado de oferta y demanda, se apoyan en alguno de estos componentes.
La sección de API Reference describe cada endpoint en detalle.
## Qué puedes esperar a medida que avances
Cada sección de esta documentación:
- Explica el propósito del componente de integración
- Presenta las opciones disponibles
- Describe en qué casos tiene sentido cada opción
- Detalla cómo se adapta menta tech a tu arquitectura existente
- Mantiene la mayor parte de la complejidad del lado de menta para que tu integración se mantenga liviana
Al finalizar, vas a tener una visión clara de cómo diseñar, implementar y operar un mercado secundario oficial totalmente integrado, con el mínimo esfuerzo de ingeniería y la máxima flexibilidad.
Si es la primera vez que trabajas con menta tech, el mejor punto de partida es la sección de Conceptos clave y modelo de datos que sigue a continuación. Ahí se presentan las entidades y relaciones que se utilizan en toda la integración y que forman el vocabulario común del resto de las guías.
## Conceptos clave y modelo de datos
### Entidades
El modelo de datos de menta tech refleja cómo las plataformas de ticketing ya piensan sus eventos y tickets.
- **Evento (Event)** - Un concepto de alto nivel como "Coldplay - Music of the Spheres". Un evento puede tener uno o varios shows.
- **Función o show (Show)** - Una fecha o función específica de un evento. Cada show pertenece a un evento e incluye fecha, venue y configuración.
- **Categoría de acceso (ticketOption)** - Representa la forma en que los fans acceden a una función, por ejemplo "Campo general", "VIP", "Platea baja". Es lo que el comprador de reventa ve y elige en el flujo de compra.
- **Tipo de precio (priceType)** - Representa cómo fue fijado el precio originalmente, por ejemplo "Early bird", "Preventa", "Precio estándar". Es clave para las reglas de configuración, aunque en la reventa el comprador normalmente se enfoca en la categoría de acceso.
- **Ticket** - Representa un ticket individual que pertenece a un usuario. Un ticket pertenece a un evento (event), a una función específica (show), a una categoría de acceso (ticketOption) y opcionalmente a una variación de precio (priceType). La información del ticket incluye ownership, ubicación en la sala y otros atributos.
- **Usuario (User)** - Representa a la persona que posee tickets o compra en reventa. Tu plataforma define esta identidad usando tu propio userId y, opcionalmente, email o teléfono, según tu modelo de usuarios.
---
# Métodos de Sincronización
## Introducción
La sincronización de eventos permite a menta tech conocer tu inventario para habilitar la reventa. Existen diferentes métodos para lograr esta sincronización, dependiendo de las capacidades técnicas de tu plataforma.
Independientemente del método elegido, la estructura de la información (cómo defines tickets y precios) es crítica. Consulta la guía de **[Estructura de Datos](/es/guides/infoStructure)** para entender cómo modelar tu inventario correctamente.
## Opciones de Integración
{% table highlight-first=true highlight-row=2 %}
| Opción | Descripción | Cuándo tiene sentido | Beneficios | Limitaciones |
|--------|-------------|----------------------|------------|--------------|
| Usando la API de menta tech (recomendado) | La plataforma envía peticiones de CREATE/UPDATE directamente a menta | Cuando la sincronización en tiempo real y la precisión son importantes | Actualizaciones en tiempo cercano a real, sin polling, opción más escalable | Requiere emitir actualizaciones salientes desde el backend |
| Endpoint de eventos expuesto por la plataforma | menta tech consulta periódicamente un endpoint de eventos de la plataforma de ticketing | Cuando ya existe un endpoint de eventos ó se prefiere un modelo basado en consultas (pull) | Adopción sencilla, la plataforma controla estructura y frecuencia | Los datos pueden quedar desactualizados, el polling suma carga y no es ideal para cambios frecuentes |
| Carga manual de eventos | Los eventos se crean de forma manual, sin usar APIs | Para pilotos o partners de bajo volumen | Sin desarrollo, salida a producción más rápida | No escalable, operación manual, mayor riesgo de datos desactualizados |
{% /table %}
{% conditionaltabs id="tabs-1765309889524" %}
{% tab label="API de menta tech" %}
## Envío vía API (Push)
Este es el método recomendado para integraciones robustas. Tu backend actúa como fuente de verdad y notifica a menta cada vez que hay cambios.
### Implementación
Debes enviar requests a nuestra API cada vez que se cree, actualice o cancele un evento.
```bash
POST /v1/events
```
El cuerpo del request (JSON) dependerá del modelo de datos que elijas (Estandar, Precio Simple o Avanzado). **Revisa la guía de [Estructura de Datos](/es/guides/infoStructure)** para ver los esquemas JSON requeridos.
Enlaces útiles:
- Crear evento (API Reference)
- Actualizar evento (API Reference)
{% /tab %}
{% tab label="Endpoint expuesto por tu plataforma" %}
## Endpoint Pull
Tu plataforma expone una URL pública (ej: `https://api.tuplataforma.com/menta-feed`) y menta la consulta periódicamente para buscar actualizaciones.
### Requisitos del Endpoint
El endpoint debe devolver un JSON con la lista de eventos activos (un array de objetos). La estructura de cada evento debe incluir detalles de ubicación, productores y shows.
Dentro de cada show, la estructura de `ticketOptions` debe seguir las definiciones de la guía de **[Estructura de Datos](/es/guides/infoStructure)**.
### Estructura JSON requerida
A continuación, un ejemplo de cómo debe verse el array de eventos devuelto por tu endpoint:
{% columns gap="2rem" align="start" %}
{% column width="1" valign="top" %}
**Campos clave:**
- **Array Raíz**: La respuesta debe ser una lista `[...]`.
- **Evento**: `title`, `description`, `externalReferenceId`.
- **Location**: `city`, `venueName`, `address`.
- **Producers**: Información de contacto.
- **Shows**: Array de funciones.
- **status**: Estado del show (`ON_SALE`, `CANCELLED`, `RESCHEDULED`, `ANNOUNCED`, `HIDDEN`, `PRIVATE`).
- **dates**: Objeto de fechas del ciclo de vida (`startsAt`, `salesStartAt`, `salesEndAt`, `publicAt`).
- **tags**: Array de strings en formato `key:value`.
- **ticketOptions**: Array crítico para la reventa (categorías de acceso). Cada ítem incluye `price` (precio de la categoría **excluyendo comisiones y cargos**) y, opcionalmente, `area` (agrupador de zona — varios ticketOptions pueden compartir el mismo `area`).
- **priceTypes** *(opcional)*: Tipos de precio disponibles para la venta (ej: Adult, Special Discount, Preventa).
- **combinations** *(obligatorio si hay `priceTypes`)*: Combinaciones válidas de `ticketOption` + `priceType` que realmente existen en tu catálogo. Cada combinación lleva su propio `price` (también excluyendo comisiones y cargos) y, opcionalmente, un `description`.
{% /column %}
{% column width="1" valign="top" %}
```json
[
{
"title": "Concierto Ejemplo",
"description": "Descripción del evento de ejemplo.",
"externalReferenceId": "evt_example_001",
"shows": [
{
"title": "Concierto Ejemplo - Función Principal",
"primarySalesUrl": "https://tuplataforma.com/evento/concierto-ejemplo/show/001",
"images": [
{
"url": "https://ejemplo.com/imagenes/evento-principal.jpg",
"kind": "main"
}
],
"showId": "show_example_001",
"status": "ON_SALE",
"dates": {
"startsAt": "2025-12-15T20:00:00.000-03:00",
"salesStartAt": "2025-10-01T10:00:00.000-03:00",
"salesEndAt": "2025-12-15T18:00:00.000-03:00",
"publicAt": "2025-09-15T00:00:00.000-03:00"
},
"tags": ["genre:rock", "tour:2025"],
"ticketOptions": [
{
"title": "General",
"ticketId": "GEN_001",
"description": "Acceso general al evento",
"currency": "USD",
"price": 100,
"area": "Campo"
},
{
"title": "VIP",
"ticketId": "VIP_001",
"description": "Acceso VIP con beneficios exclusivos",
"currency": "USD",
"price": 250,
"area": "Platea"
}
],
"priceTypes": [
{
"priceTypeId": "adult",
"title": "Adult"
},
{
"priceTypeId": "special-discount",
"title": "Special Discount"
}
],
"combinations": [
{
"ticketOptionId": "GEN_001",
"priceTypeId": "adult",
"price": 100,
"description": "General – Adult"
},
{
"ticketOptionId": "GEN_001",
"priceTypeId": "special-discount",
"price": 70
},
{
"ticketOptionId": "VIP_001",
"priceTypeId": "adult",
"price": 250
}
]
}
],
"location": {
"city": "Buenos Aires",
"state": "Buenos Aires",
"venueName": "Estadio Ejemplo",
"address": "Av. Ejemplo 1234",
"country": "Argentina"
},
"producers": [
{
"name": "Productor Ejemplo",
"emails": [
"contacto@productor-ejemplo.com"
],
"producerId": "prod_001"
}
]
}
]
```
{% /column %}
{% /columns %}
{% callout type="warning" title="priceTypes y combinations" %}
Los `priceTypes` son **opcionales**: si tu catálogo no tiene variaciones de precio dentro de una misma categoría de acceso, podés omitir este array y trabajar solo con `ticketOptions` (modelo Estandar).
Ahora bien, **si enviás `priceTypes`, estás obligado a enviar `combinations`**. menta tech no genera combinaciones automáticamente: solo existirán las combinaciones que definas explícitamente en ese array. Si una combinación `ticketOption` + `priceType` no aparece en `combinations`, no existirá en menta aunque ambas dimensiones estén declaradas.
Revisá la guía de **[Estructura de Datos](/es/guides/infoStructure)** para entender cuándo conviene cada modelo.
{% /callout %}
{% callout type="info" title="Precios sin comisiones ni cargos" %}
Tanto `ticketOption.price` como `combination.price` deben expresarse **excluyendo comisiones y cargos**: es el precio base de la categoría (o de la combinación) tal como lo cobrás vos, sin fees de servicio ni impuestos adicionales que puedas sumar en el checkout primario.
Cuando hay `combinations`, el precio de cada combinación **prevalece** sobre el `price` declarado en la ticketOption asociada; la ticketOption queda como referencia de la categoría.
{% /callout %}
{% callout type="info" title="Agrupando ticketOptions con area" %}
El campo `area` en `ticketOption` **es opcional** y sirve para **agrupar categorías ubicadas en una zona similar** del venue. Varios ticketOptions pueden compartir el mismo valor de `area`.
Por ejemplo, si en "Platea Alta" tenés tres categorías comerciales diferentes (`Platea Alta VIP`, `Platea Alta Regular`, `Platea Alta Discapacitados`), las tres pueden declarar `"area": "Platea Alta"`. menta usa ese agrupador para filtros, navegación y métricas por zona.
{% /callout %}
{% /tab %}
{% tab label="Carga manual de eventos" %}
## Carga manual
Para volúmenes bajos o pruebas piloto, es posible cargar eventos mediante archivos (CSV/Excel) procesados por el equipo de operaciones de menta.
Este método no requiere desarrollo pero tiene limitaciones operativas importantes y riesgo de desactualización de datos. Contacta a tu account manager si deseas utilizar esta opción.
{% /tab %}
{% /conditionaltabs %}
---
## Estado del Show
Cada show incluye un campo `status` que representa su estado actual en el ciclo de vida. Este estado determina cómo se muestra el show y si la actividad de reventa está habilitada.
{% table highlight-first=true %}
| Estado | Descripción | Visible al público | Reventa habilitada |
| :--- | :--- | :--- | :--- |
| `ON_SALE` | Los boletos se están vendiendo activamente en el mercado primario. El show es visible públicamente y la reventa está completamente operativa. | Sí | Sí |
| `ANNOUNCED` | El show ha sido anunciado públicamente y es visible, pero la venta primaria de boletos aún no ha comenzado o fue pausada. Los usuarios pueden ver el evento pero no pueden comprar boletos en el mercado primario. La reventa puede seguir activa si los boletos fueron distribuidos previamente. | Sí | Depende de la configuración |
| `CANCELLED` | El show ha sido cancelado. No se permite más actividad de venta ni reventa. Las publicaciones de reventa existentes se eliminan y las transacciones pendientes se manejan según la política de cancelación. | Sí (marcado como cancelado) | No |
| `RESCHEDULED` | El show fue movido a una nueva fecha u horario. El campo `dates.startsAt` refleja la nueva programación. La actividad de reventa puede continuar bajo la nueva fecha dependiendo de la configuración. | Sí (marcado como reprogramado) | Depende de la configuración |
| `HIDDEN` | El show no es visible al público. No aparece en resultados de búsqueda, listados de eventos ni en el marketplace de reventa. Se usa típicamente para shows en preparación o temporalmente removidos. | No | No |
| `PRIVATE` | El show está restringido a una audiencia específica (ej., solo invitados, grupos de preventa o eventos internos). No es visible en listados públicos pero puede ser accesible mediante link directo o código de acceso. | Solo con acceso directo | Depende de la configuración |
{% /table %}
{% callout type="info" title="Estado y fechas" %}
El campo `status` refleja el **estado operativo actual** del show, mientras que el objeto `dates` proporciona la **línea de tiempo programada**. Por ejemplo, un show puede tener `status: "ANNOUNCED"` con un `dates.salesStartAt` en el futuro — lo que significa que pasará automáticamente a estar en venta en esa fecha. Envía siempre ambos campos para que menta tech pueda gestionar el ciclo de vida del show correctamente.
{% /callout %}
## Fechas del Show
El objeto `dates` agrupa todas las fechas relevantes del ciclo de vida de un show. Todas las fechas deben estar en formato ISO 8601.
{% table highlight-first=true %}
| Campo | Descripción |
| :--- | :--- |
| `dates.startsAt` | Fecha y hora de inicio del show (el horario de la función). Es la fecha de referencia principal del evento. |
| `dates.salesStartAt` | Fecha y hora en que abre la venta primaria de boletos. Antes de esta fecha, los boletos no pueden comprarse en el mercado primario. |
| `dates.salesEndAt` | Fecha y hora en que cierra la venta primaria de boletos. Después de esta fecha, los boletos ya no están disponibles en el mercado primario. |
| `dates.publicAt` | Fecha y hora en que el show se hace visible públicamente en la web. Antes de esta fecha, el show puede existir internamente pero no se muestra a los usuarios finales. |
{% /table %}
---
## Cancelación de Eventos
{% callout type="warning" title="Importancia crítica" %}
**Es fundamental informar a menta tech cuando un evento es cancelado.** La distribución del dinero a los vendedores de boletos de reventa se realiza unos días después de la fecha original del evento. Si un evento se cancela y no se notifica a menta, los pagos se procesarán normalmente después de la fecha programada y **no habrá forma de recuperar el dinero** una vez distribuido.
{% /callout %}
### ¿Por qué es tan importante?
Cuando un evento se cancela:
1. **Los compradores de reventa deben ser reembolsados** - menta gestiona automáticamente los reembolsos si se notifica la cancelación a tiempo.
2. **Los pagos a vendedores se detienen** - si no se informa la cancelación, los vendedores recibirán el pago como si el evento se hubiera realizado.
3. **No hay recuperación posterior** - una vez que los fondos son distribuidos, no es posible revertir las transacciones.
### Cómo notificar una cancelación
{% conditionaltabs id="tabs-cancellation" %}
{% tab label="API de menta tech" %}
### Cancelación vía API (Recomendado)
Para cancelar un evento mediante la API, utiliza el endpoint de cancelación:
```bash
POST /v1/events/:externalReferenceId/cancellation
```
Donde `:externalReferenceId` es el identificador único del evento en tu sistema de ticketing.
**Parámetros opcionales:**
- `showId`: Si solo deseas cancelar un show específico dentro del evento, incluye este parámetro en el query string.
{% apiembed endpoint="post-post-events-id-cancellation" show="link" width="auto" /%}
{% /tab %}
{% tab label="Endpoint expuesto por tu plataforma" %}
### Cancelación con integración Pull
Si tu integración es mediante un endpoint que menta consulta periódicamente, tienes dos opciones:
**Opción 1: Feed de eventos cancelados**
Exponer un endpoint adicional (ej: `https://api.tuplataforma.com/menta-feed/cancelled`) que devuelva la lista de eventos cancelados. menta consultará este feed periódicamente.
```json
[
{
"externalReferenceId": "evt_example_001",
"cancelledAt": "2025-01-15T10:30:00.000Z",
"showId": "show_001" // opcional, si es solo un show
}
]
```
**Opción 2: API Call directo (Recomendado)**
Aunque tu integración principal sea mediante pull, **recomendamos utilizar el API call de cancelación** para notificaciones en tiempo real:
```bash
POST /v1/events/:externalReferenceId/cancellation
```
Esto garantiza que la cancelación se procese inmediatamente sin esperar al siguiente ciclo de polling.
{% /tab %}
{% tab label="Carga manual de eventos" %}
### Cancelación con carga manual
Para integraciones de carga manual, tienes dos opciones:
**Opción 1: API Call (Recomendado)**
Aunque la carga de eventos sea manual, recomendamos implementar el API call de cancelación:
```bash
POST /v1/events/:externalReferenceId/cancellation
```
**Opción 2: Notificación al Account Manager**
Dado que este tipo de integración está orientado a plataformas con menor volumen, también es posible informar la cancelación directamente a tu account manager. Sin embargo, esto puede generar demoras en el procesamiento.
{% callout type="info" %}
Contacta a tu account manager lo antes posible cuando un evento sea cancelado para evitar pagos incorrectos.
{% /callout %}
{% /tab %}
{% /conditionaltabs %}
---
# Estructura de la información
## Introducción
Para operar correctamente la reventa, menta tech necesita una representación estructurada de tus eventos. Esta guía detalla la jerarquía de datos y los modelos disponibles para representar tu inventario, independientemente del método de sincronización que utilices.
{% callout type="info" title="Dos métodos de sincronización: PUSH y PULL" %}
La **estructura de datos que definas en esta guía aplica a ambos métodos** de sincronización con menta tech:
- **PUSH** — Tu backend envía requests a la API de menta (`POST /v1/events`, `POST /v1/events/rules`) cada vez que hay cambios. Es el método recomendado para integraciones en tiempo cercano a real.
- **PULL** — Tu plataforma expone un endpoint público y menta lo consulta periódicamente. La información viaja dentro del mismo JSON de eventos (ver [Métodos de Sincronización](/es/guides/eventData)).
Lo que cambia entre ambos es el **transporte**, no los conceptos: `ticketOption`, `priceType` y `combinations` se definen igual en los dos. Más abajo, dentro de cada modelo (Estandar y Detalle de Precio), vas a encontrar la implementación concreta para cada método.
{% /callout %}
## Jerarquía de Datos
La estructura base conecta eventos, funciones y categorías de acceso.
{% columns gap="2rem" align="start" %}
{% column width="1" valign="center" %}
{% diagram type="erd" height="500px" title="Estructura de Datos" %}
{
"nodes": [
{
"id": "node1",
"type": "custom",
"position": { "x": 88, "y": 86 },
"data": {
"label": "Evento",
"subtitle": "id, title, producer",
"background": "#ffffff"
}
},
{
"id": "node-shows",
"type": "custom",
"position": { "x": 84, "y": 238 },
"data": {
"label": "Shows",
"subtitle": "showId, date, title",
"background": "#fff3e0"
}
},
{
"id": "node-ticketA",
"type": "custom",
"position": { "x": -21, "y": 365 },
"data": {
"label": "ticketOption A",
"subtitle": "Acceso General, id",
"background": "#e3f2fd"
}
},
{
"id": "node-ticketB",
"type": "custom",
"position": { "x": 198, "y": 364 },
"data": {
"label": "ticketOption B",
"subtitle": "Acceso VIP, id",
"background": "#e3f2fd"
}
}
],
"edges": [
{
"id": "edge-1",
"source": "node1",
"target": "node-shows",
"label": "tiene uno o más",
"animated": false
},
{
"id": "edge-2",
"source": "node-shows",
"target": "node-ticketA",
"animated": true
},
{
"id": "edge-3",
"source": "node-shows",
"target": "node-ticketB",
"animated": true
}
]
}
{% /diagram %}
{% /column %}
{% column width="1" valign="center" %}
Esta jerarquía permite:
- **Validar tickets**: Confirmar elegibilidad según evento y show.
- **Generar la UI**: Mostrar categorías y mapas correctamente.
- **Aplicar reglas**: Configurar reventa a nivel evento, show o categoría.
El punto crítico es cómo defines las **categorías de acceso** (ticketOptions) y sus precios.
{% /column %}
{% /columns %}
## Modelado de Precios e Inventario
Dos dimensiones definen la estructura de tu inventario:
- **ticketOption**: la categoría de acceso (Campo, VIP). Es lo que el comprador de reventa **ve y elige**. Lleva su propio `price` (precio de la categoría **excluyendo comisiones y cargos**) y opcionalmente un `area` (agrupador de zona — varios ticketOptions pueden compartir el mismo `area`, ej: `Platea Alta VIP` y `Platea Alta Regular` con `"area": "Platea Alta"`).
- **priceType**: la variación comercial (Preventa, Early Bird). Es metadata interna.
- **combination** (cuando existen priceTypes): el par `ticketOption` + `priceType` que realmente se vende. Lleva su propio `price` (también **sin comisiones ni cargos**) y, opcionalmente, `description`. **El precio de la combinación prevalece** sobre el de la ticketOption asociada.
### ¿Por qué separarlos?
Si mezclas ambos conceptos (ej: "Campo Preventa" y "Campo General" como categorías distintas), fragmentas el inventario y confundes al comprador. Al separarlos, agrupas todo el inventario de "Campo" junto, independientemente del precio original.
menta ofrece dos modelos de integración para manejar esto:
## Tabla comparativa de modelos
{% table highlight-first=true %}
| Modelo | Qué envías | Cómo interpreta los datos menta | Cuándo tiene sentido | Beneficios | Limitaciones |
|--------|------------|--------------------------------|----------------------|------------|--------------|
| Estandar | Solo ticketOptions | Una categoría unificada por tipo de acceso | Cuando no existen variaciones de precio dentro del acceso | Integración más simple, mínima configuración | No distingue diferencias de precio, agrupamiento y filtros limitados |
| Detalle de Precio | ticketOptions + priceTypes + combinaciones reales | Solo existen las combinaciones creadas explícitamente | Cuando se necesita máximo control y precisión | El dashboard refleja exactamente tu catálogo, ideal para pricing avanzado | Requiere mantener combinaciones vía API |
{% /table %}
{% conditionaltabs id="tabs-1765310713135" %}
{% tab label="Estandar" %}
## Estandar
{% columns gap="2rem" align="start" %}
{% column width="1" %}
### Descripción general
En el modelo Estandar tu plataforma envía únicamente las ticketOptions. menta asume que cada ticketOption representa un producto único sin variaciones internas de precio.
### Implementación
Enviás únicamente las `ticketOptions`. No hace falta declarar `priceTypes` ni combinaciones. El transporte cambia según el método de sincronización que uses.
{% /column %}
{% column width="1" valign="center" %}
{% diagram type="erd" height="200px" title="Flujo Estandar" %}
{
"nodes": [
{ "id": "in", "type": "custom", "position": { "x": 20, "y": 75 }, "data": { "label": "TicketOption", "subtitle": "Campo", "background": "#e3f2fd" } },
{ "id": "out", "type": "custom", "position": { "x": 400, "y": 75 }, "data": { "label": "Producto Final", "subtitle": "Campo", "background": "#e8f5e9" } }
],
"edges": [
{ "id": "e1", "source": "in", "target": "out", "label": "se convierte en", "animated": true, "style": { "stroke": "#4caf50" } }
]
}
{% /diagram %}
{% /column %}
{% /columns %}
#### Opción A — PUSH (API de menta)
Un único API call a `POST /v1/events` enviando solo las `ticketOptions` dentro de cada show.
{% apiembed endpoint="post-events" show="link" width="auto" /%}
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
{% callout type="info" title="Estructura del request" %}
En el modelo Estandar, solo envías las ticketOptions sin información de priceTypes. menta tech tratará cada ticketOption como una categoría única sin variaciones de precio.
{% /callout %}
```json
{
"externalReferenceId": "event-123",
"shows": {
"showId": "show-456",
"ticketOptions": [
{
"title": "Campo General",
"ticketId": "campo-general",
"description": "Acceso general al campo",
"currency": "USD",
"price": 100,
"area": "Campo"
},
{
"title": "VIP",
"ticketId": "vip",
"description": "Acceso VIP con beneficios exclusivos",
"currency": "USD",
"price": 250,
"area": "Platea"
}
]
}
}
```
{% /column %}
{% column width="0.5" valign="center" sticky=true %}
{% codeannotation highlight-lines="2" %}
**externalReferenceId**: Identificador único del evento en tu plataforma. Se usa para todas las referencias futuras.
{% /codeannotation %}
{% codeannotation highlight-lines="4" %}
**showId**: Identificador único del show en tu sistema.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**ticketOptions**: Array con las categorías de acceso disponibles. Solo envías las ticketOptions, sin priceTypes.
{% /codeannotation %}
{% codeannotation highlight-lines="7" %}
**title**: Nombre visible de la categoría para el comprador de reventa.
{% /codeannotation %}
{% codeannotation highlight-lines="8" %}
**ticketId**: Identificador único de la categoría de acceso en tu sistema (equivalente a ticketOptionId).
{% /codeannotation %}
{% codeannotation highlight-lines="9" %}
**description**: Descripción de la categoría de acceso.
{% /codeannotation %}
{% codeannotation highlight-lines="10" %}
**currency**: Moneda del precio del ticket.
{% /codeannotation %}
{% codeannotation highlight-lines="11" %}
**price**: Precio de la categoría **excluyendo comisiones y cargos**.
{% /codeannotation %}
{% codeannotation highlight-lines="12" %}
**area** *(opcional)*: Agrupador de zona. Varios ticketOptions pueden compartir el mismo valor (ej: `Platea Alta VIP` y `Platea Alta Regular` con `"area": "Platea Alta"`).
{% /codeannotation %}
{% /column %}
{% /columns %}
#### Opción B — PULL (Endpoint expuesto)
En el JSON que devuelve tu endpoint (ej: `https://api.tuplataforma.com/menta-feed`), dentro de cada show incluís solo el array `ticketOptions`. No agregues `priceTypes` ni `combinations`: al omitirlos, menta interpreta el show bajo el modelo Estandar.
Consultá la guía de **[Métodos de Sincronización](/es/guides/eventData)** para ver la estructura completa del endpoint (location, producers, shows, etc.).
```json
{
"externalReferenceId": "event-123",
"shows": [
{
"showId": "show-456",
"status": "ON_SALE",
"dates": { "startsAt": "2025-12-15T20:00:00.000-03:00" },
"ticketOptions": [
{
"title": "Campo General",
"ticketId": "campo-general",
"description": "Acceso general al campo",
"currency": "USD",
"price": 100,
"area": "Campo"
},
{
"title": "VIP",
"ticketId": "vip",
"description": "Acceso VIP con beneficios exclusivos",
"currency": "USD",
"price": 250,
"area": "Platea"
}
]
}
]
}
```
### Cuándo tiene sentido este modelo
- Tus eventos no utilizan múltiples categorías de precio dentro de un mismo tipo de acceso
- Buscas la integración más simple posible
- No necesitas agrupamiento, filtrado o alertas basadas en precio
### Beneficios
- Menor esfuerzo de implementación
- Configuración de reglas muy simple, una regla por ticketOption
- No es necesario gestionar priceTypes ni combinaciones
### Limitaciones
- Si existen múltiples precios internos, el comprador no verá agrupaciones significativas
- Todos los tickets del mismo acceso se ven idénticos en reventa aunque hayan sido comprados en condiciones distintas
- No hay soporte para alertas o filtros más allá de la propia ticketOption
{% /tab %}
{% tab label="Detalle de Precio" %}
## Detalle de Precio
{% columns gap="2rem" align="start" %}
{% column width="1" %}
### Descripción general
En el modelo de Detalle de Precio Avanzado, tu plataforma envía las `ticketOptions` y `priceTypes`, y además defines explícitamente solo las combinaciones reales que existen en tu catálogo usando el endpoint `POST /v1/events/rules` con `ruleType: COMBINATION`.
menta tech **no genera combinaciones automáticamente**. Solo existirán las combinaciones que definas explícitamente.
### Implementación
Además de las `ticketOptions`, declarás los `priceTypes` disponibles y las **combinaciones reales** que existen en tu catálogo. El transporte cambia según el método de sincronización que uses.
{% /column %}
{% column width="1" valign="center" %}
{% diagram type="erd" height="350px" title="Combinación Explícita" %}
{
"nodes": [
{
"id": "to",
"type": "custom",
"position": {
"x": 692.3844155844157,
"y": 94.04220779220779
},
"data": {
"label": "TicketOption",
"subtitle": "VIP",
"background": "#e3f2fd"
}
},
{
"id": "pt1",
"type": "custom",
"position": {
"x": 960.9032467532467,
"y": 94.04220779220779
},
"data": {
"label": "PriceType",
"subtitle": "Preventa",
"background": "#f3e5f5"
}
},
{
"id": "pt2",
"type": "custom",
"position": {
"x": 414.7551948051948,
"y": 94.04220779220779
},
"data": {
"label": "PriceType",
"subtitle": "General",
"background": "#f3e5f5"
}
},
{
"id": "blocked",
"type": "custom",
"position": {
"x": 808.6194805194805,
"y": 250
},
"data": {
"label": "No Generado",
"subtitle": "Sin regla explícita",
"background": "#ffebee"
}
},
{
"id": "res2",
"type": "custom",
"position": {
"x": 578.8194805194805,
"y": 250
},
"data": {
"label": "Producto",
"subtitle": "VIP + General",
"background": "#e8f5e9"
}
}
],
"edges": [
{
"id": "e_b1",
"source": "to",
"target": "blocked",
"animated": false,
"style": {
"stroke": "#e57373",
"strokeDasharray": "5,5"
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "e_b2",
"source": "pt1",
"target": "blocked",
"animated": false,
"style": {
"stroke": "#e57373",
"strokeDasharray": "5,5"
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "e2",
"source": "to",
"target": "res2",
"animated": true,
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "e4",
"source": "pt2",
"target": "res2",
"animated": true,
"style": {
"stroke": "#9c27b0"
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
}
]
}
{% /diagram %}
{% /column %}
{% /columns %}
#### Opción A — PUSH (API de menta)
Tu plataforma realiza **dos API calls secuenciales**:
1. **Paso 1** — Crear el evento con `ticketOptions` y `priceTypes` usando `POST /v1/events`.
2. **Paso 2** — Definir las combinaciones reales usando `POST /v1/events/rules` con `ruleType: COMBINATION`.
##### Paso 1: Crear el evento
Primero, creas el evento enviando las dimensiones base (ticketOptions y priceTypes):
{% apiembed endpoint="post-events" show="link" width="auto" /%}
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
{% callout type="info" title="Estructura del request" %}
Envías las ticketOptions y priceTypes disponibles en tu sistema. En este punto, menta tech aún no crea combinaciones.
{% /callout %}
```json
{
"externalReferenceId": "event-123",
"shows": {
"showId": "show-456",
"ticketOptions": [
{
"title": "Campo General",
"ticketId": "campo-general",
"description": "Acceso general al campo",
"currency": "USD",
"price": 100,
"area": "Campo"
},
{
"title": "VIP",
"ticketId": "vip",
"description": "Acceso VIP con beneficios exclusivos",
"currency": "USD",
"price": 250,
"area": "Platea"
}
],
"priceTypes": [
{
"priceTypeId": "preventa",
"title": "Preventa"
},
{
"priceTypeId": "regular",
"title": "Precio Regular"
}
]
}
}
```
{% /column %}
{% column width="0.5" valign="center" sticky=true %}
{% codeannotation highlight-lines="2" %}
**externalReferenceId**: Identificador único del evento en tu plataforma. Se usará en el siguiente paso.
{% /codeannotation %}
{% codeannotation highlight-lines="4" %}
**showId**: Identificador único del show en tu sistema. Se usará en el siguiente paso.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**ticketOptions**: Array con las categorías de acceso disponibles en tu catálogo.
{% /codeannotation %}
{% codeannotation highlight-lines="7" %}
**title**: Nombre visible de la categoría para el comprador de reventa.
{% /codeannotation %}
{% codeannotation highlight-lines="8" %}
**ticketId**: Identificador único de la categoría de acceso en tu sistema (equivalente a ticketOptionId).
{% /codeannotation %}
{% codeannotation highlight-lines="11" %}
**price**: Precio de la categoría **excluyendo comisiones y cargos**. Si declarás `combinations`, el precio de cada combinación prevalece sobre éste.
{% /codeannotation %}
{% codeannotation highlight-lines="12" %}
**area** *(opcional)*: Agrupador de zona. Varios ticketOptions pueden compartir el mismo valor.
{% /codeannotation %}
{% codeannotation highlight-lines="23" %}
**priceTypes**: Array con los tipos de precio disponibles en tu sistema.
{% /codeannotation %}
{% codeannotation highlight-lines="25" %}
**priceTypeId**: Identificador único del tipo de precio en tu sistema. Se usará en el siguiente paso.
{% /codeannotation %}
{% /column %}
{% /columns %}
##### Paso 2: Definir combinaciones reales
Luego, defines explícitamente solo las combinaciones que realmente existen en tu catálogo:
{% apiembed endpoint="post-events-rules" show="link" width="auto" /%}
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
{% callout type="info" title="Estructura del request" %}
Solo defines las combinaciones que realmente existen en tu sistema. menta tech no generará combinaciones automáticamente. Debes especificar cada combinación válida usando `ruleType: COMBINATION`.
{% /callout %}
```json
[
{
"externalReferenceEventId": "event-123",
"showId": "show-456",
"ticketOptionId": "campo-general",
"priceTypeId": "preventa",
"ruleType": "COMBINATION",
"price": 80,
"description": "Campo General – Preventa"
},
{
"externalReferenceEventId": "event-123",
"showId": "show-456",
"ticketOptionId": "campo-general",
"priceTypeId": "regular",
"ruleType": "COMBINATION",
"price": 100
},
{
"externalReferenceEventId": "event-123",
"showId": "show-456",
"ticketOptionId": "vip",
"priceTypeId": "preventa",
"ruleType": "COMBINATION",
"price": 200
}
]
```
{% /column %}
{% column width="0.5" valign="center" sticky=true %}
{% codeannotation highlight-lines="2" %}
El body es un array de objetos, cada uno representa una combinación válida.
{% /codeannotation %}
{% codeannotation highlight-lines="4" %}
**externalReferenceEventId**: El identificador único del evento (debe coincidir con el enviado en el Paso 1).
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**showId**: El identificador único del show (debe coincidir con el enviado en el Paso 1).
{% /codeannotation %}
{% codeannotation highlight-lines="6" %}
**ticketOptionId**: Identificador de la categoría de acceso de esta combinación (debe coincidir con el `ticketId` enviado en el Paso 1).
{% /codeannotation %}
{% codeannotation highlight-lines="7" %}
**priceTypeId**: Identificador del tipo de precio de esta combinación (debe coincidir con el enviado en el Paso 1).
{% /codeannotation %}
{% codeannotation highlight-lines="8" %}
**ruleType**: Debe ser `"COMBINATION"` para definir combinaciones válidas entre ticketOption y priceType.
{% /codeannotation %}
{% codeannotation highlight-lines="9" %}
**price**: Precio de la combinación **excluyendo comisiones y cargos**. Prevalece sobre el `price` declarado en la ticketOption asociada.
{% /codeannotation %}
{% codeannotation highlight-lines="10" %}
**description** *(opcional)*: Texto libre que describe la combinación (por ejemplo, una etiqueta comercial o interna).
{% /codeannotation %}
{% /column %}
{% /columns %}
**Nota importante**: Solo las combinaciones que definas explícitamente en este segundo API call aparecerán en el dashboard y en la matriz de reventa. Si no defines una combinación (por ejemplo, VIP con Precio Regular), esa combinación no existirá en menta aunque ambas dimensiones estén sincronizadas en el Paso 1.
#### Opción B — PULL (Endpoint expuesto)
En el JSON que devuelve tu endpoint, dentro de cada show incluís tres arrays: `ticketOptions`, `priceTypes` y `combinations`. **Todo viaja en un único payload**, no hay dos pasos como en PUSH.
{% callout type="warning" title="Regla clave del PULL" %}
Si declarás `priceTypes`, **es obligatorio** incluir `combinations` listando todos los pares `ticketOption` + `priceType` válidos. menta tech no genera combinaciones automáticamente; solo existirán las que aparezcan en ese array.
Si tu catálogo no tiene variaciones de precio, omití `priceTypes` y `combinations` y usá el modelo Estandar.
{% /callout %}
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
```json
{
"externalReferenceId": "event-123",
"shows": [
{
"showId": "show-456",
"status": "ON_SALE",
"dates": { "startsAt": "2025-12-15T20:00:00.000-03:00" },
"ticketOptions": [
{
"title": "Campo General",
"ticketId": "campo-general",
"description": "Acceso general al campo",
"currency": "USD",
"price": 100,
"area": "Campo"
},
{
"title": "VIP",
"ticketId": "vip",
"description": "Acceso VIP con beneficios exclusivos",
"currency": "USD",
"price": 250,
"area": "Platea"
}
],
"priceTypes": [
{
"priceTypeId": "preventa",
"title": "Preventa"
},
{
"priceTypeId": "regular",
"title": "Precio Regular"
}
],
"combinations": [
{
"ticketOptionId": "campo-general",
"priceTypeId": "preventa",
"price": 80,
"description": "Campo General – Preventa"
},
{
"ticketOptionId": "campo-general",
"priceTypeId": "regular",
"price": 100
},
{
"ticketOptionId": "vip",
"priceTypeId": "preventa",
"price": 200
}
]
}
]
}
```
{% /column %}
{% column width="0.5" valign="center" sticky=true %}
{% codeannotation highlight-lines="7" %}
**ticketOptions**: Categorías de acceso visibles para el comprador. Cada una declara su `price` (sin comisiones ni cargos) y opcionalmente un `area`.
{% /codeannotation %}
{% codeannotation highlight-lines="14" %}
**price** (ticketOption): Precio base de la categoría, **excluyendo comisiones y cargos**. Cuando hay `combinations`, el precio de la combinación prevalece sobre éste.
{% /codeannotation %}
{% codeannotation highlight-lines="15" %}
**area** *(opcional)*: Agrupador de zona. Varios ticketOptions pueden compartir el mismo valor (ej: `Platea Alta VIP` y `Platea Alta Regular` con `"area": "Platea Alta"`).
{% /codeannotation %}
{% codeannotation highlight-lines="25" %}
**priceTypes**: Tipos de precio disponibles para la venta (ej: Adult, Special Discount, Preventa). Es **opcional**: si no tenés variaciones internas de precio, omití este array.
{% /codeannotation %}
{% codeannotation highlight-lines="35" %}
**combinations**: Pares `ticketOption` + `priceType` que realmente existen en tu catálogo. Si enviás `priceTypes`, este array **es obligatorio**. La combinación `vip + regular` no aparece porque no existe en el catálogo, y por lo tanto no se generará en menta.
{% /codeannotation %}
{% codeannotation highlight-lines="39" %}
**price** (combination): Precio de la combinación específica, **sin comisiones ni cargos**.
{% /codeannotation %}
{% codeannotation highlight-lines="40" %}
**description** *(opcional)*: Texto libre que describe la combinación.
{% /codeannotation %}
{% /column %}
{% /columns %}
Consultá la guía de **[Métodos de Sincronización](/es/guides/eventData)** para ver la estructura completa del endpoint (location, producers, dates, etc.).
### Cuándo tiene sentido este modelo
- Necesitas un mapeo preciso entre menta y tu catálogo real
- No todas las ticketOptions se combinan con todos los priceTypes
- Quieres evitar mostrar categorías o combinaciones que no existen en tu sistema primario
### Beneficios
- El dashboard refleja exactamente la configuración real de tus eventos
- No aparecen combinaciones artificiales o sin uso
- Ideal para estrategias comerciales complejas y eventos de gran escala
### Limitaciones
- Requiere gestionar combinaciones vía API
- Debe actualizarse cada vez que cambian las ticketOptions o los priceTypes
{% /tab %}
{% /conditionaltabs %}
---
# Autenticación
## Descripción General
**La autenticación** define cómo menta identifica a un usuario durante las interacciones de reventa. La identidad del usuario es necesaria para:
* Recuperar el inventario de entradas correcto para la reventa
* Asegurar que solo usuarios legítimos puedan listar o comprar entradas
* Hacer cumplir las reglas de reventa vinculadas a cuentas de usuario
* Garantizar operaciones de reventa seguras y conformes a las normas
**menta tech** admite tres mecanismos de autenticación. A diferencia de otras secciones, estos mecanismos **no son exclusivos**.
* La mayoría de las integraciones implementan tanto **Login Trust** como **Login Force** juntos.
* Si ninguno está disponible, menta proporciona un método de autenticación de respaldo utilizando **OTP**.
## Por qué importa la autenticación
La autenticación asegura que:
* Las acciones de reventa estén vinculadas al usuario correcto.
* Solo los propietarios reales puedan listar entradas.
* Solo los usuarios autenticados puedan comprar entradas.
* Se cumplan las reglas de identidad del sistema de venta de entradas primario.
* Las operaciones posteriores (entrega, reportes, cumplimiento) permanezcan consistentes.
**Se requiere una identidad de usuario válida y verificada para cada acción de reventa.**
---
## Modelos de Autenticación — Comparación
{% table highlight-first=true %}
| Modelo | Propósito | Dónde se Aplica | Notas |
| :--- | :--- | :--- | :--- |
| **Login Trust** | El partner informa a menta quién es el usuario autenticado. | Se usa siempre que la reventa es accedida por un usuario logueado. | Proporciona la experiencia más fluida. |
| **Login Force** | Requiere que los usuarios que compran en reventa inicien sesión o creen una cuenta. | Se aplica en flujos de compra. | Asegura que todos los compradores de reventa tengan una cuenta del partner. |
| **Autenticación OTP de menta** | menta autentica a los usuarios usando un código de un solo uso. | Se usa solo cuando Login Trust/Force no están implementados. | Adecuado para plataformas de invitados o sin cuentas. |
{% /table %}
---
{% conditionaltabs id="tabs-1765468408434" %}
{% tab label="Login Trust" %}
## Login Trust
### Descripción
En Login Trust, el usuario ya está autenticado en tu plataforma (web o app). En este caso, cada vez que generes una URL para lleva a tu usuario a un flujo de compra o venta administrado por menta tech, deberás especificar la identidad del usuario, sea correo electrónico ó número de teléfono, en la creación de la URL vía el endpoint HTTP.
{% diagram type="sequence" height="400px" %}
{
"nodes": [
{
"id": "actor-1",
"type": "sequence-actor",
"position": {
"x": 36.66666666666666,
"y": 30.063149335941404
},
"data": {
"label": "Usuario",
"accentColor": "#8b5cf6",
"lifelineHeight": 320
}
},
{
"id": "actor-2",
"type": "sequence-actor",
"position": {
"x": 260,
"y": 30
},
"data": {
"label": "Tu Plataforma",
"accentColor": "#f97316",
"lifelineHeight": 320
}
},
{
"id": "actor-3",
"type": "sequence-actor",
"position": {
"x": 501.1078337971647,
"y": 28.666666666666664
},
"data": {
"label": "menta tech",
"accentColor": "#3b82f6",
"lifelineHeight": 320
}
},
{
"id": "msg-1",
"type": "sequence-message",
"position": {
"x": -1.6666666666666856,
"y": 101.49999999999999
},
"data": {
"label": "Desea comprar o vender"
}
},
{
"id": "msg-1765910935647",
"type": "sequence-message",
"position": {
"x": 182.94174681528432,
"y": 160.15989697777204
},
"data": {
"label": "Genera URL de compra o venta \nespecificando el correo electrónico\ndel usuario"
}
},
{
"id": "msg-1765911134978",
"type": "sequence-message",
"position": {
"x": 450.8424675717367,
"y": 246.82261851691868
},
"data": {
"label": "Devuelve URL con un token\nde sesión de un único uso",
"isReturn": true
}
},
{
"id": "msg-1765911217230",
"type": "sequence-message",
"position": {
"x": -20.236230318487458,
"y": 322.26699190089283
},
"data": {
"label": "Ingresa a comprar o vender\nautomáticamente autenticado"
}
}
],
"edges": [
{
"id": "edge-1765910902184",
"source": "msg-1",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-2",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1765910958910",
"source": "msg-1765910935647",
"target": "actor-3",
"sourceHandle": null,
"targetHandle": "h-8",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1765911239535",
"source": "msg-1765911217230",
"target": "actor-3",
"sourceHandle": null,
"targetHandle": "h-20",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1765939085504",
"source": "actor-1",
"target": "msg-1765911134978",
"sourceHandle": "s-14",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"label": "Recibe URL",
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
}
]
}
{% /diagram %}
Los campos comunes incluyen:
- userId (identificador único preferido)
- email o phone number (dependiendo del modelo de identidad del partner)
menta no realiza autenticación adicional. La autenticación del partner es totalmente confiable.
### Cuándo usarlo
- Siempre que la experiencia de reventa sea accedida por usuarios autenticados.
- Cuando el partner tiene un sistema estable de inicio de sesión/sesión.
- Cuando se requiere una experiencia de usuario fluida.
### Características clave
- Los usuarios nunca ven un aviso de inicio de sesión adicional.
- La identidad es controlada enteramente por el partner.
- Ideal para experiencias de reventa profundamente integradas.
{% /tab %}
{% tab label="Login Force" %}
## Login Force
### Descripción
Login Force asegura que todos los compradores de reventa tengan una cuenta válida en la plataforma del partner.
Si un usuario inicia una compra de reventa sin estar autenticado:
- menta lo redirige a la página de inicio de sesión o creación de cuenta del partner.
- El usuario inicia sesión o crea una cuenta.
- El partner redirige al usuario de vuelta a menta.
- El usuario completa la compra autenticado.
Esto asegura que el comprador tenga una cuenta válida en el sistema primario antes de adquirir una entrada.
{% diagram type="sequence" height="400px" %}
{
"nodes": [
{
"id": "actor-1",
"type": "sequence-actor",
"position": {
"x": 7.3333333333333215,
"y": 30.063149335941404
},
"data": {
"label": "Usuario",
"accentColor": "#8b5cf6",
"lifelineHeight": 320
}
},
{
"id": "actor-2",
"type": "sequence-actor",
"position": {
"x": 518.6666666666666,
"y": 30.063149335941404
},
"data": {
"label": "Tu Plataforma",
"accentColor": "#f97316",
"lifelineHeight": 320
}
},
{
"id": "actor-3",
"type": "sequence-actor",
"position": {
"x": 269.10783379716474,
"y": 30.063149335941404
},
"data": {
"label": "menta tech",
"accentColor": "#3b82f6",
"lifelineHeight": 320
}
},
{
"id": "msg-1",
"type": "sequence-message",
"position": {
"x": -1.6666666666666856,
"y": 88.16666666666666
},
"data": {
"label": "Desea comprar"
}
},
{
"id": "msg-1767819209574",
"type": "sequence-message",
"position": {
"x": 174.56434292996,
"y": 156.30384645397356
},
"data": {
"label": "Durante el proceso de compra es enviado\na tu plataforma para autenticarse"
}
},
{
"id": "msg-1767819399705",
"type": "sequence-message",
"position": {
"x": -50.70649528044395,
"y": 207.69615354602647
},
"data": {
"label": " Completa autenticación \n(registro o inicio de sesión)"
}
},
{
"id": "msg-1767819586656",
"type": "sequence-message",
"position": {
"x": 453.2096641029424,
"y": 271.9465133491845
},
"data": {
"label": "Generas un One Time Token\nusando la API de menta tech"
}
},
{
"id": "msg-1767819693042",
"type": "sequence-message",
"position": {
"x": 408.69697569105756,
"y": 348.5005142710487
},
"data": {
"label": "Rediriges al usuario al returnUrl adicionando el\noneTimeToken a la URL"
}
}
],
"edges": [
{
"id": "edge-1767819166606",
"source": "msg-1",
"target": "actor-3",
"sourceHandle": null,
"targetHandle": "h-1",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"hadArrow": true
}
},
{
"id": "edge-1767819434001",
"source": "msg-1767819399705",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-11",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1767819464235",
"source": "actor-1",
"target": "msg-1767819209574",
"sourceHandle": "s-7",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true,
"hadArrow": true
}
},
{
"id": "edge-1767819608493",
"source": "actor-3",
"target": "msg-1767819586656",
"sourceHandle": "s-16",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
},
{
"id": "edge-1767819721605",
"source": "actor-1",
"target": "msg-1767819693042",
"sourceHandle": "s-22",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
}
]
}
{% /diagram %}
### Implementación
#### Detalle del Flujo
1. **El usuario es dirigido al inicio de sesión**: Durante el flujo de compra, menta redirige al usuario a la URL de inicio de sesión/registro de tu plataforma, incluyendo un parámetro de consulta `returnTo` que apunta de vuelta a la página de menta donde el usuario se encontraba.
Ejemplo de URL: `https://tuplataforma.com/login?returnTo=https://mentatech.io/sell/2738`
2. **El usuario completa la autenticación**: El usuario inicia sesión o se registra en tu plataforma.
3. **Tu plataforma solicita un One Time Token**: Tras la autenticación exitosa, tu plataforma llama a la API de menta tech para obtener un token de sesión de un solo uso para ese usuario.
4. **menta emite el token**: menta tech devuelve un token de sesión de un solo uso en la respuesta.
5. **Tu plataforma redirige al usuario de vuelta**: Tu plataforma redirige al usuario a la URL `returnTo`, agregando el token como parámetro de consulta `oneTimeToken`.
Ejemplo de redirección: `https://mentatech.io/sell/2738?oneTimeToken=abc123xyz456`
6. **El usuario continúa en menta**: El usuario retoma el flujo de compra en menta, ahora completamente autenticado.
#### Referencia de API
**Endpoint:** `GET /v1/auth/oneTimeToken`
**Base URL:** `https://api.mentatech.io`
**Headers:**
| Header | Valor | Obligatorio |
| :--- | :--- | :--- |
| Authorization | your_mentatech_apikey | Sí |
**Parámetros de consulta (Query Parameters):**
| Parámetro | Descripción | Obligatorio |
| :--- | :--- | :--- |
| user | Dirección de correo electrónico del usuario que se autenticó exitosamente en tu plataforma. | Sí |
**Ejemplo de solicitud:**
`GET https://api.mentatech.io/v1/auth/oneTimeToken?user=johndoe@email.com`
**Ejemplo de respuesta:**
```json
{
"data": "eyJlbWFpbCI6InVzZXJAZW1haWwuY29tIiwib3R0IjoiOTg0NDE3NDU0MTYiLCJ1c2VkIjpmYWxzZSwidGlja2V0U2VsbGVySWQiOiIyIiwiX2lkIjoiNjZmNDZkN2ZkMGQ0NTMzMGQxMzdhMzhiIn0="
}
```
> **Importante:** El `oneTimeToken` es válido solo por un corto período de tiempo y debe usarse inmediatamente después de ser emitido. Además, solo se puede usar una vez.
### Cuándo usarlo
- Siempre recomendado en flujos de compra de reventa.
- Cuando la identidad del comprador debe estar vinculada a una cuenta de la plataforma principal.
- Cuando los procesos posteriores (entrega, reportes, CRM, asignación de QR) requieren usuarios autenticados.
### Características clave
- Impone la creación de cuenta o inicio de sesión para todos los compradores.
- Previene compras anónimas o de invitados.
- Asegura que los compradores de reventa existan dentro del ecosistema del partner.
{% /tab %}
{% tab label="Autenticación OTP de menta" %}
## Autenticación OTP de menta
### Descripción
Si el partner no puede soportar Login Trust o Login Force, menta autentica a los usuarios a través de una contraseña de un solo uso enviada a su correo electrónico o número de teléfono.
**Flujo:**
1. El usuario ingresa su correo electrónico o teléfono.
2. menta envía un código de verificación temporal.
3. El usuario ingresa el código.
4. menta autentica la sesión.
### Cuándo usarlo
* El partner no tiene cuentas de usuario.
* El partner no puede compartir la identidad autenticada con menta.
* La plataforma utiliza flujos de pago puramente para invitados (guest checkout).
### Características clave
* No requiere integración de autenticación por parte del partner.
* Permite la reventa en plataformas sin cuentas de usuario.
* Introduce más fricción en comparación con Login Trust/Force.
{% /tab %}
{% /conditionaltabs %}
---
# Acceso a la venta - Introducción
## Descripcion general
**El acceso a la venta** define como los usuarios entran al flujo de reventa desde tu seccion de *Mis tickets* para publicar o gestionar sus entradas.
La integracion principal para acceso a la venta es la **Capa de Acceso Inteligente (SAL)**.
{% callout type="info" title="Smart Access Layer" %}
La capa de acceso inteligente tambien lo vas a encontrar como Smart Access Layer (SAL) en algunos lugares de la documentacion.
{% /callout %}
Tu plataforma llama a un endpoint de alta prioridad con una lista de tickets (u ordenes) y el identificador del usuario. menta tech responde, para cada ticket u orden, con:
- El estado actual de la reventa (`SELLABLE`, `FOR_SALE`, `SOLD`, `NOT_SELLABLE`)
- Las acciones disponibles como call-to-actions (por ejemplo: vender, editar publicacion, ver detalles)
- Las URLs para ejecutar esas acciones
- Componentes de UI opcionales (por ejemplo: banner de venta)
Tu UI utiliza esta respuesta para decidir que mostrar para cada ticket y a donde enviar al usuario cuando hace clic. La informacion de tickets se consulta bajo demanda mientras el usuario ve sus tickets o inicia una accion de reventa, por lo que menta tech no agrega carga a tus onsales principales.
menta tech admite dos modelos para el Acceso a la venta:
- **Opcion 1** Capa de Acceso Inteligente (recomendado)
- **Opcion 2** URL estatica de entrada a reventa
Las reglas de reventa subyacentes son las mismas. La decision es que tan conectada debe estar tu UI de *Mis tickets* con esas reglas.
## Comparacion de modelos de integracion
{% table highlight-first=true highlight-row=2 %}
| Modelo | Descripcion | Cuando tiene sentido | Beneficios | Limitaciones |
|--------|-------------|----------------------|-----------|--------------|
| Capa de Acceso Inteligente (recomendado) | Tu backend llama al endpoint SAL de venta con tickets u ordenes y la identidad del usuario, y recibe por item el estado y las CTAs | Quieres acciones y estados de reventa nativos dentro de *Mis tickets* | Estado en tiempo real a nivel ticket, acciones contextuales, logica impulsada por reglas de menta tech, soporta flujos a nivel ticket y a nivel orden | Requiere integrar la llamada a SAL y conectar las respuestas con tu UI |
| URL estatica de entrada a reventa | Un unico enlace "Vender tickets" envia a los usuarios a una pagina generica de entrada a reventa en menta tech | Necesitas una integracion minima o un piloto rapido | Esfuerzo de implementacion muy bajo | No hay estado ni acciones por ticket en tu UI de *Mis tickets*, la experiencia se maneja integramente en menta tech |
{% /table %}
___
{% conditionaltabs id="tabs-1765307261094" %}
{% tab label="Capa de Acceso Inteligente" %}
## Capa de Acceso Inteligente (recomendado)
### Concepto
La **Capa de Acceso Inteligente** permite que tu vista de *Mis tickets* le pregunte a menta tech, para cada ticket u orden, que se puede hacer en ese momento y como hacerlo.
Para cada item que envias, menta tech evalua:
- Si el ticket es elegible para reventa, segun las reglas configuradas en el dashboard de menta tech
- Si ya esta publicado o vendido
- Que accion tiene sentido (por ejemplo: publicar en venta, editar publicacion, ver detalles, sin accion)
- Si el vendedor necesita completar su configuracion de datos de pago
El endpoint esta disenado como un camino de alta prioridad capaz de manejar solicitudes grandes de forma eficiente, con el rendimiento necesario para acciones criticas en tiempo real.
### Endpoint
```
POST https://api.mentatech.io/v1/wrapper/accesslayer
```
**Headers:**
| Header | Requerido | Descripcion |
|-----------------|-----------|--------------------------------------|
| Authorization | Si | Tu API key |
| Content-Type | Si | `application/json` |
### Modos de request
El SAL de venta soporta dos modos de request. Debes enviar **tickets** **o** **orders** en el body, no ambos.
{% conditionaltabs id="tabs-sell-modes" %}
{% tab label="Modo tickets" %}
#### Modo tickets
Usa este modo cuando tu plataforma trackea tickets individuales. Envias cada `ticketId` y menta devuelve el estado y CTAs por ticket.
**Body del request:**
| Campo | Tipo | Requerido | Descripcion |
|--------------------------|----------|-----------|-----------------------------------------------------|
| user | string | Si | Email del usuario (el vendedor) |
| tickets | array | Si | Lista de tickets a evaluar |
| tickets[].eventId | string | Si | Identificador externo del evento |
| tickets[].showId | string | Si | Identificador externo del show |
| tickets[].ticketId | string | Si | Identificador externo del ticket |
| tickets[].ticketOptionId | string | Si | Identificador de categoria de acceso |
| tickets[].priceTypeId | string | Opcional | Identificador de tipo de precio (cuando aplica) |
**Ejemplo de request:**
```json
POST /v1/wrapper/accesslayer
Authorization: YOUR_API_KEY
{
"user": "seller@example.com",
"tickets": [
{
"eventId": "evt-123",
"showId": "show-456",
"ticketId": "T001",
"ticketOptionId": "GA"
},
{
"eventId": "evt-123",
"showId": "show-456",
"ticketId": "T002",
"ticketOptionId": "VIP",
"priceTypeId": "standard"
}
]
}
```
**Ejemplo de respuesta:**
```json
{
"data": {
"user": "seller@example.com",
"tickets": [
{
"status": "SELLABLE",
"ticketId": "T001",
"ticketOptionId": "GA",
"priceTypeId": "",
"sync": true,
"callToActions": [
{
"key": "SELL",
"text": "Sell",
"url": "https://sell-ticket.mentatickets.com/es/publish/65fdc7eb...?ticketSellerId=2&oneTimeToken=...&utm_source=sell&syncPage=true",
"enabled": true
}
]
},
{
"status": "FOR_SALE",
"ticketId": "T002",
"ticketOptionId": "VIP",
"priceTypeId": "standard",
"sync": true,
"callToActions": [
{
"key": "P2P",
"text": "Peer to Peer",
"url": "https://event.mentatickets.com/es/...?sellerId=...&ticketSellerId=2&utm_source=sell&syncPage=true",
"enabled": true
},
{
"key": "EDIT",
"text": "Edit Listing",
"url": "https://sell-ticket.mentatickets.com/es/list-item/...?listingId=...&ticketSellerId=2&oneTimeToken=...&utm_source=sell&syncPage=true",
"enabled": true
}
]
}
],
"components": [
{
"type": "banner",
"class": "sellBanner",
"sellBanner": {
"title": "Vende tus entradas",
"description": "Publica tus tickets en el marketplace",
"image": "https://cdn.example.com/sell-banner.png",
"visible": true,
"colors": {
"background": "#0A1F44",
"text": "#FFFFFF"
},
"callToAction": {
"text": "Empezar a vender",
"url": "https://sell-ticket.mentatickets.com/es/publish/...?ticketSellerId=2&utm_source=sell&syncPage=true",
"enabled": true
}
}
}
]
},
"errors": [],
"status": 200
}
```
{% /tab %}
{% tab label="Modo ordenes" %}
#### Modo ordenes
Usa este modo cuando tu plataforma trackea ordenes (cada orden contiene multiples tickets). Envias cada `orderId` con sus combinaciones de categoria, y menta devuelve un estado y CTA agregado por orden.
**Body del request:**
| Campo | Tipo | Requerido | Descripcion |
|------------------------------------|----------|-----------|-----------------------------------------------------|
| user | string | Si | Email del usuario (el vendedor) |
| orders | array | Si | Lista de ordenes a evaluar |
| orders[].orderId | string | Si | Identificador externo de la orden |
| orders[].eventId | string | Si | Identificador externo del evento |
| orders[].showId | string | Si | Identificador externo del show |
| orders[].combinations | array | Si | Combinaciones de ticket option/price type en la orden |
| orders[].combinations[].ticketOptionId | string | Si | Identificador de categoria de acceso |
| orders[].combinations[].priceTypeId | string | Opcional | Identificador de tipo de precio |
**Ejemplo de request:**
```json
POST /v1/wrapper/accesslayer
Authorization: YOUR_API_KEY
{
"user": "seller@example.com",
"orders": [
{
"orderId": "ORD-001",
"eventId": "evt-123",
"showId": "show-456",
"combinations": [
{ "ticketOptionId": "GA" },
{ "ticketOptionId": "VIP", "priceTypeId": "standard" }
]
}
]
}
```
**Ejemplo de respuesta:**
```json
{
"data": {
"user": "seller@example.com",
"orders": [
{
"orderId": "ORD-001",
"status": "SELLABLE",
"callToActions": [
{
"key": "SELL",
"text": "Sell",
"url": "https://sell-ticket.mentatickets.com/es/publish/...?ticketSellerId=2&oneTimeToken=...&utm_source=sell&syncPage=true",
"enabled": true
}
]
}
],
"components": []
},
"errors": [],
"status": 200
}
```
{% callout type="info" title="Agregacion de estado por orden" %}
Cuando una orden contiene multiples tickets, menta evalua cada ticket individualmente y devuelve un estado agregado para la orden usando esta cascada de decision:
1. Si todos los tickets son `NOT_SELLABLE` → la orden es `NOT_SELLABLE`
2. Si algun ticket es `SELLABLE` y otros ya estan publicados o vendidos → la orden es `SELLABLE` con CTA `MANAGE`
3. Si todos los tickets son `SELLABLE` (ninguno publicado o vendido) → la orden es `SELLABLE` con CTA `SELL`
4. Si todos los tickets publicados/vendidos comparten el mismo grupo y algunos estan publicados → la orden es `FOR_SALE` con CTA `EDIT`
5. Si todos los tickets publicados/vendidos comparten el mismo grupo y todos estan vendidos → la orden es `SOLD` con CTA `DETAILS`
6. Si los tickets publicados/vendidos pertenecen a grupos diferentes → la orden es `FOR_SALE` con CTA `MANAGE`
{% /callout %}
{% /tab %}
{% /conditionaltabs %}
### Referencia de estados
| Estado | Descripcion |
|----------------|-----------------------------------------------------------------------|
| `SELLABLE` | El ticket puede ser publicado en venta. CTA: `SELL` |
| `NOT_SELLABLE` | El ticket no puede ser publicado (las reglas no lo permiten) |
| `FOR_SALE` | El ticket tiene una publicacion activa. CTAs: `EDIT`, `P2P` |
| `SOLD` | El ticket fue vendido a traves del marketplace. CTA: `DETAILS` |
### Referencia de call-to-actions
| Key | Texto | Descripcion |
|----------------------|-----------------------|---------------------------------------------------------------------------|
| `SELL` | Sell | Link para iniciar el flujo de publicacion del ticket |
| `EDIT` | Edit Listing | Link para editar o ver la publicacion activa |
| `DETAILS` | View Listing Details | Link para ver detalles de la publicacion vendida |
| `P2P` | Peer to Peer | Link para compartir la publicacion (link de compra directa) |
| `PENDING_PAYOUT_INFO`| Pending Payout Info | El vendedor necesita completar su configuracion de pago (aparece junto a otros CTAs) |
| `MANAGE` | Manage Tickets | Link a la pagina de gestion de tickets (modo ordenes, estados mixtos) |
### El campo `sync` (modo tickets)
En modo tickets, cada ticket en la respuesta incluye un booleano `sync`:
- `sync: true` — el ticket ya esta sincronizado en la base de datos de menta.
- `sync: false` — el ticket aun no esta en la base de datos de menta. La URL del CTA incluye `syncPage=true` para que el frontend dispare la sincronizacion antes de publicar.
{% callout type="info" title="Tickets desconocidos" %}
menta no almacena tu inventario de tickets de forma permanente — los sincroniza bajo demanda cuando un usuario quiere vender. Esto significa que un `ticketId` que envies puede no existir aun en la base de datos de menta.
Cuando un ticket aun no es conocido por menta, el SAL de venta igualmente evalua su posibilidad de venta usando las reglas de reventa configuradas para esa combinacion de evento/show/categoria. Si las reglas permiten la publicacion, la respuesta devuelve `SELLABLE` con `sync: false` y una URL de CTA que dispara la sincronizacion automaticamente. Tu UI no necesita manejar esto de forma diferente — simplemente renderiza el CTA como siempre y menta se encarga del resto.
{% /callout %}
### Componentes
La respuesta incluye un array `components` con elementos de UI opcionales. Actualmente, el SAL de venta devuelve:
**Banner de venta** (`type: "banner"`, `class: "sellBanner"`)
Un banner promocional que incentiva al usuario a vender sus tickets. La visibilidad se controla por las reglas configuradas en el dashboard de menta tech.
| Campo | Descripcion |
|----------------------------|----------------------------------------------|
| `sellBanner.title` | Texto del titulo del banner |
| `sellBanner.description` | Texto de descripcion del banner |
| `sellBanner.image` | URL de la imagen del banner |
| `sellBanner.visible` | Si el banner debe ser renderizado |
| `sellBanner.colors` | Colores opcionales de fondo y texto |
| `sellBanner.callToAction` | CTA con texto, URL, flag enabled y colores |
### Como usarlo en tu UI
Tu pagina de *Mis tickets* deberia:
1. Resolver la lista de tickets (u ordenes) para el usuario actual.
2. Llamar al endpoint SAL de venta con los items y el email del usuario.
3. Para cada ticket u orden en la respuesta:
- Usar `status` para mostrar el estado actual (por ejemplo: Disponible para venta, En venta, Vendido).
- Renderizar cada entrada en `callToActions` como un boton o link accionable, usando `text` como label y `url` como destino.
- Si `callToActions` esta vacio, no mostrar acciones de reventa para ese item.
4. Si `components` contiene un banner de venta visible, renderizarlo en una ubicacion apropiada.
Como toda la logica de elegibilidad y estados se gestiona mediante reglas en el dashboard de menta tech, cualquier cambio que hagas ahi se refleja automaticamente en las respuestas del SAL, sin cambios de codigo de tu lado.
### Cuando tiene sentido este modelo
Usa la Capa de Acceso Inteligente cuando:
- Quieres que la reventa se sienta totalmente integrada en tu UI de *Mis tickets*.
- Necesitas estados en tiempo real a nivel ticket, como `SELLABLE`, `SOLD`, `FOR_SALE`.
- Quieres controlar desde el dashboard de menta tech en que eventos, shows o categorias esta habilitada la reventa.
- Prefieres no implementar ni mantener reglas de reventa en tu propio codigo.
- Necesitas soportar flujos de venta tanto a nivel ticket como a nivel orden.
{% /tab %}
{% tab label="URL estatica de reventa" %}
## Modelo de URL estatica de entrada a reventa
### Concepto
El modelo de entrada estatica ofrece un unico punto de entrada generico a la reventa desde tu plataforma. En lugar de preguntar a menta tech por cada ticket que mostrar, rediriges a los usuarios a una pagina generica de entrada a reventa.
**Flujo tipico:**
1. Anades un boton o elemento de menu "Vender tickets" en tu UI.
2. Ese boton apunta a una URL estatica de entrada a reventa proporcionada por menta tech.
3. menta tech autentica al usuario usando tu modelo de autenticacion elegido.
4. Dentro de menta tech, el usuario ve sus tickets elegibles y elige cuales publicar.
Tu pagina de *Mis tickets* no muestra acciones ni estados de reventa por ticket. Toda la interaccion de reventa ocurre dentro de la experiencia de menta tech.
### Cuando tiene sentido este modelo
Utiliza una URL estatica de reventa cuando:
- Quieres la integracion mas pequena posible para empezar a probar reventa.
- No necesitas acciones de reventa a nivel ticket en tu propia UI de *Mis tickets*.
- Estas ejecutando un piloto mientras planeas una futura migracion al modelo SAL.
### Beneficios
- Esfuerzo de implementacion muy bajo.
- No se requiere integracion de backend mas alla de enlazar a la URL de entrada a reventa.
- Buen punto de partida para pilotos pequenos o con fuerte limitacion de tiempo.
### Limitaciones
- No hay estado ni acciones por ticket en tu propia UI.
- El usuario siempre entra en un flujo de reventa generico y debe elegir los tickets dentro de menta tech.
- Tu plataforma no refleja las reglas de reventa definidas en el dashboard a nivel de ticket.
{% /tab %}
{% /conditionaltabs %}
---
# Sincronización de tickets para reventa
## Descripción general
Cuando un usuario quiere vender un ticket, menta tech necesita saber qué tickets posee y cuáles son elegibles para reventa. **Esta sincronización solo ocurre cuando el usuario quiere vender** — no es un proceso continuo ni requiere mantener un histórico completo.
Tu plataforma sigue siendo la fuente de verdad. menta tech consulta o recibe los datos solo cuando es necesario para habilitar la reventa.
Tu plataforma expone un endpoint que menta tech consulta cuando necesita verificar el ownership de los tickets del usuario.
{% callout type="info" title="Relación con Acceso a la venta" %}
La sincronización está ligada al acceso a la venta. Cuando un usuario quiere vender, menta tech o tu plataforma inician la sincronización según el modelo elegido. Para más detalles, consulta [Acceso a la venta](/es/guides/accessToSell-into).
{% /callout %}
## Estructura del objeto Ticket
Tu plataforma debe entregar a menta tech un objeto `ticket` con la siguiente estructura:
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
{% callout type="info" title="Estructura del objeto ticket" %}
A niveles generales, la estructura `Ticket` mantiene la siguiente forma.
{% /callout %}
```json
[
{
"ticketId": "444",
"externalReferenceEventId": "123",
"showId": "456",
"ticketOptionId": "789",
"priceTypeId": "101",
"price": 100,
"currency": "USD",
"buyer": "user@example.com",
"tags": ["category:vip", "source:online"]
}
]
```
{% /column %}
{% column width="0.5" valign="center" sticky=true %}
{% codeannotation highlight-lines="3" %}
**ticketId**: El ID del boleto único en tu plataforma.
{% /codeannotation %}
{% codeannotation highlight-lines="4" %}
**externalReferenceEventId**: El ID del evento al cual pertenece el boleto.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**showId**: El ID de la sesión o del show al cual el ticket da acceso.
{% /codeannotation %}
{% codeannotation highlight-lines="6" %}
**ticketOptionId**: El ID de la zona o tipo de boleto.
{% /codeannotation %}
{% codeannotation highlight-lines="7" %}
**priceTypeId**: El ID del tipo de precio o nivel de precio.
{% /codeannotation %}
{% codeannotation highlight-lines="8" %}
**price**: El precio final pagado por el usuario.
{% /codeannotation %}
{% codeannotation highlight-lines="9" %}
**currency**: La moneda que utilizó el usuario para abonar.
{% /codeannotation %}
{% codeannotation highlight-lines="10" %}
**buyer**: El correo electrónico del comprador.
{% /codeannotation %}
{% codeannotation highlight-lines="11" %}
**tags**: Array de strings en formato `key:value` para etiquetar información personalizada del boleto.
{% /codeannotation %}
{% /column %}
{% /columns %}
**Campos opcionales:**
- Ubicación y seating (sección, fila y asiento)
- Propiedades adicionales (props)
- Metadata operativa
- Tags (`tags`): Array de strings en formato `key:value` para etiquetado personalizado
## Cómo funciona
La sincronización está diseñada para integrarse con Smart Access Layer. menta tech orquesta automáticamente la sincronización cuando el usuario accede a las URLs de venta o antes, para acelerar la carga. Tu plataforma solo necesita exponer el endpoint y renderizar los componentes que brinda SAL.
## Endpoint de Verificación
### Cómo funciona
Tu plataforma expone un endpoint que devuelve todos los tickets que actualmente posee un usuario. menta tech consulta este endpoint en puntos clave:
- Cuando el usuario entra al flujo de reventa
- Antes de crear una publicación
- Antes de confirmar una venta
- Antes de completar una compra de reventa
Esto asegura verificación de ownership en tiempo real y evita que se publiquen o vendan tickets cancelados, refundados o transferidos.
### Flujo con Smart Access Layer
1. Tu UI llama a SAL con los `ticketIds` del usuario.
2. SAL responde con estados y acciones disponibles.
3. Cuando el usuario accede a una URL de venta, menta tech consulta automáticamente tu endpoint.
4. La sincronización se orquesta del lado de menta tech, sin intervención adicional.
{% diagram type="sequence" height="550px" %}
{
"nodes": [
{
"id": "actor-1",
"type": "sequence-actor",
"position": {
"x": 21.333333333333336,
"y": 30
},
"data": {
"label": "Vendedor",
"accentColor": "#22c55e",
"lifelineHeight": 500
}
},
{
"id": "actor-2",
"type": "sequence-actor",
"position": {
"x": 605.2162993197097,
"y": 30
},
"data": {
"label": "menta tech",
"accentColor": "#3b82f6",
"lifelineHeight": 550
}
},
{
"id": "actor-3",
"type": "sequence-actor",
"position": {
"x": 296.5055633245897,
"y": 30
},
"data": {
"label": "Tu plataforma",
"accentColor": "#f97316",
"lifelineHeight": 475
}
},
{
"id": "msg-1",
"type": "sequence-message",
"position": {
"x": -29.125985590712688,
"y": 73.51690818717502
},
"data": {
"label": "Usuario ingresa a la sección\nde sus tickets"
}
},
{
"id": "msg-2",
"type": "sequence-message",
"position": {
"x": 214.6853374070431,
"y": 164.12148590852757
},
"data": {
"label": "Solicitas la estructura para renderizar\nbotones de venta"
}
},
{
"id": "msg-3",
"type": "sequence-message",
"position": {
"x": 542.5026086166031,
"y": 233.45543217464973
},
"data": {
"label": "Retorna estructura de botones",
"isReturn": true
}
},
{
"id": "msg-4",
"type": "sequence-message",
"position": {
"x": 227.06697791581803,
"y": 274.18210726412326
},
"data": {
"label": "Dibujas los botones en el frontend\ndel usuario vendedor",
"isReturn": true
}
},
{
"id": "msg-1765986991767",
"type": "sequence-message",
"position": {
"x": -40.16298568880333,
"y": 392.42375081594577
},
"data": {
"label": "El usuario clickea el boton de vender"
}
},
{
"id": "msg-1765987013125",
"type": "sequence-message",
"position": {
"x": 459.96682051132154,
"y": 461.3755170736649
},
"data": {
"label": "Solicita los tickets que posee el usuario (pull)"
}
},
{
"id": "msg-1765987128632",
"type": "sequence-message",
"position": {
"x": -40.16298568880333,
"y": 567.7917548245065
},
"data": {
"label": "Completa el flujo de publicación"
}
},
{
"id": "msg-1766169147521",
"type": "sequence-message",
"position": {
"x": 189.87360371053717,
"y": 503.00268826845223
},
"data": {
"label": "Retornas todos los boletos de la orden a menta tech",
"isReturn": true
}
},
{
"id": "shape-1766170757110",
"type": "shape",
"position": {
"x": -48.5792044969711,
"y": 73.51690818717502
},
"data": {
"shapeType": "rectangle",
"width": 810,
"height": 287,
"borderStyle": "solid",
"borderWidth": 1,
"borderColor": "#ffffff",
"backgroundColor": "#f0f6ff",
"text": "Smart Access Layer",
"textPosition": "top",
"fontSize": 10,
"textColor": "#6ca2f9",
"zIndex": -10,
"subtitle": "",
"textOffsetY": 5
}
},
{
"id": "shape-1766171242413",
"type": "shape",
"position": {
"x": -48.5792044969711,
"y": 379.94817057389304
},
"data": {
"shapeType": "rectangle",
"width": 810,
"height": 259,
"borderStyle": "dashed",
"borderWidth": 1,
"borderColor": "#ffffff",
"backgroundColor": "#fdfaff",
"text": "Sincronización de tickets",
"textPosition": "top",
"fontSize": 10,
"textColor": "#dab3e6",
"textOffsetX": 0,
"textOffsetY": 3,
"zIndex": 0
}
}
],
"edges": [
{
"id": "edge-1765986752562",
"source": "msg-1",
"target": "actor-3",
"sourceHandle": null,
"targetHandle": "h-0",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1765986794619",
"source": "msg-2",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-4",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1766169066535",
"source": "actor-3",
"target": "msg-3",
"sourceHandle": "s-8",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
},
{
"id": "edge-1766169090822",
"source": "actor-1",
"target": "msg-4",
"sourceHandle": "s-10",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
},
{
"id": "edge-1766169109389",
"source": "msg-1765986991767",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-14",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1766169125769",
"source": "actor-3",
"target": "msg-1765987013125",
"sourceHandle": "s-20",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
},
{
"id": "edge-1766169207959",
"source": "msg-1766169147521",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-19",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": false
}
},
{
"id": "edge-1766169262499",
"source": "msg-1765987128632",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-22",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": false
}
}
]
}
{% /diagram %}
{% columns gap="2.5rem" %}
{% column %}
### Cuándo usar este modelo
Ideal si:
- Ya tienes un endpoint de "Mis Tickets" o historial de compras
- El estado del ticket cambia con frecuencia
- Priorizas consistencia y exactitud
- Prefieres mantener la lógica de estado en tu sistema
- Quieres que menta tech orqueste la sincronización automáticamente
{% /column %}
{% column %}
### Características clave
- menta tech no almacena inventarios históricos
- El estado se consulta siempre directo desde tu plataforma
- Mínima carga operativa
- Menor riesgo de inconsistencias
- Sincronización automática cuando el usuario quiere vender
{% /column %}
{% /columns %}
## Implementación
#### Request
En primer lugar, deberás exponer un endpoint al cual menta tech consultará enviándote el usuario identificador del usuario vendedor (normalmente el correo electrónico):
```
GET https://es.tuplataforma.com/api/tickets?user={userEmail}
```
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
#### Respuesta
El endpoint devuelve la lista de tickets que actualmente posee el usuario:
```json
[
{
"eventId": "5766",
"ticketId": "ab7a36b6",
"showId": "11c968de",
"paidPrice": 150.00,
"ticketOptionId": "45",
"ticketTypeId": "88",
"seating": {
"row": "D",
"seat": "4",
"section": "South Terrace"
},
"properties": {
"orderId": "ON_hcUE2N"
},
"tags": ["source:online", "promo:early-bird"]
},
{
"eventId": "5766",
"ticketId": "ab7a36b7",
"showId": "11c968de",
"paidPrice": 150.00,
"ticketOptionId": "45",
"ticketTypeId": "88",
"seating": {
"row": "D",
"seat": "5",
"section": "South Terrace"
},
"properties": {
"orderId": "ON_hcUE2N"
},
"tags": ["source:box-office", "category:vip"]
}
]
```
{% /column %}
{% column width="0.5" valign="top" %}
### Seguridad
Dos capas recomendadas:
1. **Restricción por IP**: Crea una allowlist que solo permita tráfico desde los servidores de menta tech.
2. **Encabezado con Clave Secreta**: menta tech envía todas las solicitudes HTTPS con una clave secreta en un header.
### Cómo usa menta tech esta respuesta
- Determina qué tickets puede listar el usuario para reventa
- Valida ownership inmediatamente antes de publicar o vender
- Previene la reventa de tickets inválidos
- Asegura que el flujo siempre refleje el estado actual de tu sistema
Cada acción crítica se valida contra este endpoint. menta tech nunca asume ownership basándose en datos cacheados.
### Notas importantes
- La estructura de la respuesta debe coincidir exactamente con el esquema predefinido
- Los nombres de campos pueden diferir si los identificadores se mapean consistentemente
- El endpoint debe ser confiable y estar disponible durante los flujos de reventa
**Importante:** Solo devuelve tickets válidos y que pertenecen al usuario. Los cancelados, reembolsados, transferidos o invalidados deben *omitirse*.
{% /column %}
{% /columns %}
---
# Acceso a Comprar
## Introducción
“Acceso a Comprar” define cómo los usuarios ingresan al flujo de compra del mercado secundaropio.
Mientras que *Acceso a Vender* siempre comienza en **Mis Tickets**, dentro de tu plataforma, el acceso a comprar se origina en recorridos de usuario a nivel evento, también dentro de tu plataforma, tales como:
- Página del evento
- Página de venta primaria agotada o Sold Out
- Listas de categorías
- Experiencias con mapa integrado
El modelo de integración determina:
- Cómo los compradores ven el inventario de reventa
- Dónde y cómo aparecen los CTAs
- Si la UI es contextual y basada en reglas
- Qué tan nativa es la integración dentro de la plataforma
- Si se muestra disponibilidad, precios piso y señales de marketplace
menta soporta dos modelos de integración para habilitar el flujo de compra de reventa.
---
# Acceso a Comprar — Tabla comparativa
{% table highlight-first=true highlight-row=2 %}
| Modelo | Descripción | Cuándo tiene sentido | Beneficios | Limitaciones |
|--------|-------------|----------------------|------------|--------------|
| **Capa de Acceso Inteligente (SAL) — Modo Compra** *(Recomendado)* | La plataforma llama a SAL con contexto del evento y SAL devuelve todos los componentes UI necesarios | Cuando se busca una experiencia nativa y contextual | Componentes dinámicos; UI basada en reglas; disponibilidad en tiempo real | Requiere renderizado de componentes y llamada SAL por contexto |
| **URL Estática / Redirección a menta** | Un link dirige al usuario a la página de reventa en menta | Cuando la prioridad es tiempo de salida | Implementación mínima | No hay UI dinámica ni integración contextual |
{% /table %}
{% conditionaltabs id="tabs-1765463808480" %}
{% tab label="Capa de Acceso Inteligente" %}
# Capa de Acceso Inteligente *(Recomendado)*
## Descripción general
La **Capa de Acceso Inteligente (Smart Access Layer — SAL)** en modo compra genera **todos los componentes de UI necesarios** para operar la compra de reventa.
La plataforma realiza la siguiente llamada:
```
GET /v1/wrapper/accesslayer?type=buy&eventId={eventId}&showId={showId}
```
SAL evalúa:
- Configuración de reventa por categoría
- Reglas de visibilidad
- Precios piso, disponibilidad y distribución
- Señales del marketplace
- Comportamientos UI basados en reglas
Y devuelve una estructura completa de componentes preconfigurados, como:
- Banner de compra
- Modal de compra
- Botón de comprar
- Lista de categorías (con disponibilidad y CTAs)
- Mapa del venue integrado
Todos los componentes vienen listos para renderizar y reflejan en tiempo real las reglas configuradas en el dashboard.
---
## Ejemplo de respuesta SAL (simplificado)
## Cómo interpretar la respuesta
La respuesta incluye una colección de componentes UI que la plataforma debe renderizar:
{% columns gap="2rem" align="start" %}
{% column width="1" valign="center" %}
```
{
"status": 200,
"data": [
{
"type": "banner",
"class": "buyBanner",
"buyBanner": {
"title": "Buy Tickets Now",
"description": "Best seats available",
"image": "https://cdn.example.com/sal/banner.png",
"visible": true,
"colors": {
"background": "#0A1F44",
"text": "#FFFFFF"
},
"callToAction": {
"text": "View options",
"url": "http://event.mentatickets.com",
"enabled": true
}
}
},
{
"type": "modal",
"class": "buyModal",
"buyModal": {
"title": "Complete Your Purchase",
"description": "Secure checkout in seconds",
"image": "https://cdn.example.com/sal/modal.png",
"visible": true,
"callToAction": {
"text": "Continue",
"url": "http://event.mentatickets.com",
"enabled": true
}
}
},
{
"type": "button",
"class": "buyButton",
"buyButton": {
"visible": true,
"callToAction": {
"text": "Buy Tickets",
"url": "http://event.mentatickets.com",
"enabled": true,
"colors": {
"background": "#F25C54",
"text": "#FFFFFF"
}
},
"colors": {
"background": "#F25C54",
"text": "#FFFFFF"
}
}
},
{
"type": "list",
"class": "categoriesList",
"categoriesList": {
"categories": [
{
"ticketOptionId": "17635820544251",
"quantityForSale": 0,
"floorPrice": 0,
"visible": true,
"callToAction": {
"text": "Check availability",
"url": "http://event.mentatickets.com",
"enabled": true,
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
},
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
},
{
"ticketOptionId": "17635820544252",
"quantityForSale": 0,
"floorPrice": 0,
"visible": true,
"callToAction": {
"text": "Check availability",
"url": "http://event.mentatickets.com",
"enabled": true,
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
},
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
}
]
}
},
{
"type": "map",
"class": "integratedMap",
"integratedMap": {
"map": {
"config": {
"allowOrphanTicketSelection": true
},
"totalCount": 0,
"bestListing": null,
"results": []
}
}
}
]
}
```
{% /column %}
{% column width="0.75" valign="top" sticky=true %}
{% codeannotation highlight-lines="4:22" %}
**Banner**
Indica disponibilidad, mensajes destacados o estados del marketplace.
{% /codeannotation %}
{% codeannotation highlight-lines="11" %}
**Visibilidad**
Disponible en todos los componentes: define si debes mostrarlo o no.
{% /codeannotation %}
{% codeannotation highlight-lines="23:37" %}
**Modal**
Ventana emergente para completar la compra con información destacada.
{% /codeannotation %}
{% codeannotation highlight-lines="38:57" %}
**Botón "Comprar reventa"**
Visible solo si existe inventario disponible.
{% /codeannotation %}
{% codeannotation highlight-lines="58:103" %}
**Lista de categorías**
Incluye:
- Título
- Disponibilidad
- Precio piso
- CTA específico por categoría
{% /codeannotation %}
{% codeannotation highlight-lines="103:119" %}
**Mapa Integrado**
Se habilita únicamente si:
- El evento tiene seating
- El partner decide mostrarlo
- Hay inventario distribuido por zonas
{% /codeannotation %}
**Reglas de visibilidad**
Si una categoría está deshabilitada o restringida en el dashboard,
**no aparecerá en la respuesta SAL**.
La plataforma **no debe replicar lógica de negocio**, solo renderizar lo que SAL provee.
{% /column %}
{% /columns %}
---
## Cuándo tiene sentido este modelo
- Se busca una experiencia nativa integrada dentro de la plataforma
- Se necesita visibilidad en tiempo real de disponibilidad por categoría
- La UI debe adaptarse automáticamente a reglas del dashboard
- El partner no quiere mantener lógica de elegibilidad o pricing
- Se desea unificar la experiencia primaria + secundaria
---
## Beneficios
### 1. UI completamente dinámica y basada en reglas
SAL controla qué se muestra y en qué condiciones.
### 2. Un solo endpoint para todos los componentes
Banner, botones, categorías y mapa en una sola llamada.
### 3. Adaptación automática
Los cambios en el dashboard se reflejan inmediatamente sin desarrollo adicional.
### 4. Experiencia nativa y coherente
El usuario no percibe un salto entre sistemas.
### 5. Sin duplicación de lógica
Toda la inteligencia está centralizada en menta.
---
## Limitaciones
- Requiere renderizar los componentes devueltos por SAL
- Necesita una llamada por cada contexto de compra
- No permite comportamientos personalizados fuera del modelo SAL
{% /tab %}
{% tab label="URL Estática" %}
# URL Estática
## Descripción general
La plataforma coloca un botón o enlace como:
**"Comprar entradas de reventa"**
Que redirige al usuario a un dominio de menta.
No se generan componentes dinámicos ni visibilidad contextual en la UI primaria.
---
## Generación de URLs
Existen dos formas de generar las URLs estáticas para el flujo de compra:
### 1. Vía API (Recomendado)
La forma recomendada es utilizar el endpoint de API de menta para generar URLs dinámicas con todas las opciones de configuración disponibles.
{% apiembed endpoint="get-marketplace-buyingflow-url-entrypoint" show="description,parameters,requestBody,responses" /%}
#### Parámetros principales
- **externalReferenceEventId**: Identificador del evento
- **showId**: Identificador de la función (requerido)
- **ticketOptionId**: Identificador de la categoría de acceso (opcional)
- **returnTo**: URL para redirigir usuarios después de la compra (requerido)
- **lang**: Código de idioma para la interfaz (opcional)
- **loginTrust[user]**: Email o teléfono del usuario autenticado cuando se usa Login Trust (opcional)
#### Ejemplo de uso
```bash
GET /v1/marketplace/buyingflow/url/entrypoint?externalReferenceEventId=123&showId=456&returnTo=https://example.com
Authorization: Bearer {your_api_key}
```
La respuesta incluye la URL completa lista para usar:
```json
{
"status": 200,
"data": "https://events.mentatech.io/es/123/456?ticketSellerId=1010",
"errors": null
}
```
### 2. URL manual
Alternativamente, puedes construir la URL manualmente siguiendo el formato estándar de menta, aunque esta opción ofrece menos flexibilidad y no incluye todas las opciones de configuración disponibles vía API.
---
## Autenticación y registro
### Login Trust
Puedes agregar el parámetro `loginTrust[user]` a cualquier URL generada para habilitar autenticación transparente. Esto permite que usuarios ya autenticados en tu plataforma accedan al marketplace sin necesidad de iniciar sesión nuevamente.
Para más detalles sobre la implementación de Login Trust, consulta la [guía de autenticación](/es/guides/auth).
{% callout type="info" %}
**Tip:** La URL generada puede incluir Login Trust agregando el parámetro `loginTrust[user]` con el email o teléfono del usuario autenticado. Esto funciona tanto con URLs generadas vía API como con URLs manuales.
{% /callout %}
### Forzar registro sin Login Force
Si no implementas Login Force pero necesitas que los usuarios estén registrados antes de poder comprar, puedes configurar tu endpoint de sincronización de tickets para que devuelva un código HTTP **404** cuando un usuario no autenticado intente acceder.
#### Implementación
En tu endpoint de sincronización de tickets (el que menta consulta para validar la propiedad de tickets), cuando detectes que el usuario no está autenticado o no tiene una cuenta:
**Devuelve el código HTTP 404**
Esto hará que menta redirija al usuario a tu página de registro o login antes de permitirle continuar con la compra.
---
## Cuándo tiene sentido
- Cuando el objetivo es habilitar reventa rápidamente
- Cuando no es posible integrar SAL por ahora
- Cuando no se requiere mostrar disponibilidad o precios piso en la página del evento
- Cuando SAL se planea incorporar más adelante
---
## Beneficios
- Implementación extremadamente sencilla
- Solo requiere agregar un enlace
- Permite habilitar reventa en muy poco tiempo
- Flexibilidad para agregar autenticación y parámetros vía API
---
## Limitaciones
### 1. Sin componentes dinámicos
No se muestran disponibilidad, categorías, mapas ni precios piso.
### 2. Sin lógica de visibilidad
Si la reventa está deshabilitada, la UI primaria no lo reflejará.
### 3. Sin soporte para capacidades avanzadas
Las funciones futuras requieren SAL.
{% /tab %}
{% /conditionaltabs %}
---
# Componentes UI de Smart Access Layer
Esta guía detalla cada componente que devuelve la **Capa de Acceso Inteligente (SAL)** en modo compra. Cada componente incluye su estructura JSON completa con explicaciones línea por línea.
La respuesta de SAL contiene una colección de componentes preconfigurados que tu plataforma debe renderizar. Cada componente viene con toda la información necesaria para su visualización: textos, imágenes, colores, CTAs y reglas de visibilidad.
---
{% conditionaltabs id="tabs-1767366632924" %}
{% tab label="Banner" %}
# Banner
{% columns gap="2rem" align="start" %}
{% column width="0.6" valign="top" %}
Componente visual destacado que se muestra en la página del evento para indicar disponibilidad de tickets de reventa, mensajes promocionales o estados del marketplace.
{% /column %}
{% column width="0.4" valign="top" %}

{% /column %}
{% /columns %}
---
## Estructura JSON
{% columns gap="2rem" align="start" %}
{% column width="0.75" valign="top" sticky=true %}
{% codeannotation highlight-lines="2" %}
**`type`**: Identifica que el tipo de componente es un `banner`.
{% /codeannotation %}
{% codeannotation highlight-lines="3" %}
**`class`**: Identifica un subtipo de componente. En este caso es un `banner` de tipo `compra` o `buy`.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**`title`**: Título principal del banner. Texto destacado que aparece en la parte superior.
{% /codeannotation %}
{% codeannotation highlight-lines="6" %}
**`description`**: Descripción o subtítulo del banner. Proporciona información adicional sobre el mensaje principal.
{% /codeannotation %}
{% codeannotation highlight-lines="7" %}
**`image`**: URL de la imagen de fondo o imagen principal del banner. Opcional según la configuración.
{% /codeannotation %}
{% codeannotation highlight-lines="8" %}
**`visible`**: Indica si el banner debe mostrarse. Si es `false`, no debe renderizarse.
{% /codeannotation %}
{% codeannotation highlight-lines="9:12" %}
**`colors`**: Paleta de colores del banner:
- **`background`**: Color de fondo en formato hexadecimal
- **`text`**: Color del texto en formato hexadecimal
{% /codeannotation %}
{% codeannotation highlight-lines="13:17" %}
**`callToAction`**: Botón o enlace de acción del banner:
- **`text`**: Texto del botón o enlace
- **`url`**: URL de redirección al hacer clic
- **`enabled`**: Si es `false`, el botón debe mostrarse deshabilitado
{% /codeannotation %}
**Nota importante**
Si `visible` es `false`, debes omitir completamente el renderizado de este componente, independientemente de los demás valores.
{% /column %}
{% column width="1" valign="center" %}
```json
{
"type": "banner",
"class": "buyBanner",
"buyBanner": {
"title": "Buy Tickets Now",
"description": "Best seats available",
"image": "https://cdn.example.com/sal/banner.png",
"visible": true,
"colors": {
"background": "#0A1F44",
"text": "#FFFFFF"
},
"callToAction": {
"text": "View options",
"url": "http://event.mentatickets.com",
"enabled": true
}
}
}
```
{% /column %}
{% /columns %}
{% /tab %}
{% tab label="Modal" %}
# Modal
{% columns gap="2rem" align="start" %}
{% column width="0.6" valign="top" %}
Ventana emergente que aparece sobre el contenido de la página para guiar al usuario hacia el flujo de compra de reventa. Se utiliza para captar la atención en momentos clave del recorrido.
{% /column %}
{% column width="0.4" valign="top" %}
{% /column %}
{% /columns %}
---
## Estructura JSON
{% columns gap="2rem" align="start" %}
{% column width="0.75" valign="top" sticky=true %}
{% codeannotation highlight-lines="2" %}
**`type`**: Identifica que el tipo de componente es un `modal`.
{% /codeannotation %}
{% codeannotation highlight-lines="3" %}
**`class`**: Identifica un subtipo de componente. En este caso es un `modal` de tipo `compra` o `buy`.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**`title`**: Título principal del modal. Texto destacado que aparece en la parte superior de la ventana emergente.
{% /codeannotation %}
{% codeannotation highlight-lines="6" %}
**`description`**: Descripción o cuerpo del mensaje del modal. Proporciona información adicional sobre la acción promovida.
{% /codeannotation %}
{% codeannotation highlight-lines="7" %}
**`image`**: URL de la imagen que se muestra dentro del modal. Opcional según la configuración.
{% /codeannotation %}
{% codeannotation highlight-lines="8" %}
**`visible`**: Indica si el modal debe mostrarse. Si es `false`, no debe renderizarse ni activarse.
{% /codeannotation %}
{% codeannotation highlight-lines="9:13" %}
**`callToAction`**: Botón de acción principal del modal:
- **`text`**: Texto del botón
- **`url`**: URL de redirección al hacer clic
- **`enabled`**: Si es `false`, el botón debe mostrarse deshabilitado
{% /codeannotation %}
**Notas de implementación**
- Debes implementar la funcionalidad de cierre del modal (botón X, clic fuera del modal, tecla ESC)
- El modal debe incluir un overlay semitransparente que oscurezca el contenido de fondo
- Si `visible` es `false`, el modal no debe mostrarse ni activarse automáticamente
- Puedes decidir cuándo mostrar el modal basándote en `visible: true` y tus propias reglas de UX
{% /column %}
{% column width="1" valign="center" %}
```json
{
"type": "modal",
"class": "buyModal",
"buyModal": {
"title": "Complete Your Purchase",
"description": "Secure checkout in seconds",
"image": "https://cdn.example.com/sal/modal.png",
"visible": true,
"callToAction": {
"text": "Continue",
"url": "http://event.mentatickets.com",
"enabled": true
}
}
}
```
{% /column %}
{% /columns %}
{% /tab %}
{% tab label="Botón de Compra" %}
# Botón de Compra
{% columns gap="2rem" align="start" %}
{% column width="0.6" valign="top" %}
Componente CTA que permite acceder directamente al flujo de compra de reventa. Aparece cuando hay inventario disponible y su estado refleja la disponibilidad actual del marketplace.
{% /column %}
{% column width="0.4" valign="top" %}

{% /column %}
{% /columns %}
---
## Estructura JSON
{% columns gap="2rem" align="start" %}
{% column width="0.75" valign="top" sticky=true %}
{% codeannotation highlight-lines="2" %}
**`type`**: Identifica que el tipo de componente es un `button`.
{% /codeannotation %}
{% codeannotation highlight-lines="3" %}
**`class`**: Identifica un subtipo de componente. En este caso es un `button` de tipo `compra` o `buy`.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**`visible`**: Indica si el botón debe mostrarse. Si es `false`, no debe renderizarse.
{% /codeannotation %}
{% codeannotation highlight-lines="6:15" %}
**`callToAction`**: Comportamiento y apariencia del botón:
- **`text`**: Texto del botón (ej: "Buy Tickets", "Ver opciones")
- **`url`**: URL de redirección al hacer clic
- **`enabled`**: Si es `false`, el botón debe mostrarse deshabilitado
- **`colors`**: Colores del botón:
- **`background`**: Color de fondo en hexadecimal
- **`text`**: Color del texto en hexadecimal
{% /codeannotation %}
{% codeannotation highlight-lines="16:19" %}
**`colors`**: Paleta de colores del botón. Si `callToAction.colors` está presente, tiene prioridad.
- **`background`**: Color de fondo
- **`text`**: Color del texto
{% /codeannotation %}
**Notas de implementación**
- Si `visible` es `false`, el botón no debe renderizarse
- Si `callToAction.enabled` es `false`, el botón debe mostrarse visualmente deshabilitado (opacidad reducida, cursor not-allowed)
- El botón debe ser responsive y adaptarse a diferentes tamaños de pantalla
- Puedes agregar efectos hover y active según tus estándares de diseño
- El `url` del CTA típicamente apunta al flujo de compra de reventa en menta
{% /column %}
{% column width="1" valign="center" %}
```json
{
"type": "button",
"class": "buyButton",
"buyButton": {
"visible": true,
"callToAction": {
"text": "Buy Tickets",
"url": "http://event.mentatickets.com",
"enabled": true,
"colors": {
"background": "#F25C54",
"text": "#FFFFFF"
}
},
"colors": {
"background": "#F25C54",
"text": "#FFFFFF"
}
}
}
```
{% /column %}
{% /columns %}
{% /tab %}
{% tab label="Lista de Categorias" %}
# Lista de Categorías
{% columns gap="2rem" align="start" %}
{% column width="0.6" valign="top" %}
Muestra todas las categorías de tickets disponibles para reventa con información de disponibilidad, precios piso y CTAs específicos por categoría. Cada categoría incluye su propio estado de visibilidad y disponibilidad.
{% /column %}
{% column width="0.4" valign="top" %}

{% /column %}
{% /columns %}
---
## Estructura JSON
{% columns gap="2rem" align="start" %}
{% column width="0.75" valign="top" sticky=true %}
{% codeannotation highlight-lines="2" %}
**`type`**: Identifica que el tipo de componente es una `list`.
{% /codeannotation %}
{% codeannotation highlight-lines="3" %}
**`class`**: Identifica un subtipo de componente. En este caso es una `list` de tipo `categorías` o `categories`.
{% /codeannotation %}
{% codeannotation highlight-lines="4" %}
**`categoriesList`**: Objeto contenedor que agrupa todas las categorías disponibles para reventa.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**`categories`**: Array con todas las categorías de tickets disponibles. Cada elemento representa una categoría con su información de disponibilidad, precios y CTAs.
{% /codeannotation %}
{% codeannotation highlight-lines="7" %}
**`ticketOptionId`**: Identificador único de la opción de ticket (categoría) en el sistema del partner. Permite mapear cada categoría con su equivalente en el sistema primario.
{% /codeannotation %}
{% codeannotation highlight-lines="8" %}
**`quantityForSale`**: Cantidad de tickets disponibles para reventa en esta categoría. Se actualiza en tiempo real. Si es `0`, no hay tickets disponibles.
{% /codeannotation %}
{% codeannotation highlight-lines="9" %}
**`floorPrice`**: Precio mínimo (precio piso) disponible para esta categoría. Si es `0`, puede indicar que no hay inventario o que el precio aún no se ha determinado.
{% /codeannotation %}
{% codeannotation highlight-lines="10" %}
**`visible`**: Indica si esta categoría debe mostrarse. Si es `false`, debe omitirse del renderizado.
{% /codeannotation %}
{% codeannotation highlight-lines="11:19" %}
**`callToAction`**: Botón o enlace de acción específico para esta categoría:
- **`text`**: Texto del botón (ej: "Check availability", "Ver opciones")
- **`url`**: URL de redirección, típicamente incluye parámetros de la categoría
- **`enabled`**: Si es `false`, el botón debe mostrarse deshabilitado
- **`colors`**: Colores del botón:
- **`background`**: Color de fondo
- **`text`**: Color del texto
{% /codeannotation %}
{% codeannotation highlight-lines="20:23" %}
**`colors`**: Paleta de colores para el elemento de categoría (fondo del card, borde, etc.):
- **`background`**: Color de fondo
- **`text`**: Color del texto principal
{% /codeannotation %}
**Notas de implementación**
- Debes iterar sobre el array `categories` y renderizar cada categoría que tenga `visible: true`
- Cada categoría debe mostrar claramente: nombre (si está disponible), `quantityForSale`, `floorPrice` y el CTA
- Si `quantityForSale` es `0`, puedes mostrar "Sin disponibilidad" o un mensaje similar
- Si `floorPrice` es `0` y `quantityForSale > 0`, puede indicar que el precio se está calculando
- El `ticketOptionId` debe usarse para mapear la categoría con el sistema primario si es necesario
- Las categorías con `visible: false` deben omitirse completamente del renderizado
- Puedes ordenar las categorías según tus propias reglas de UX, pero debes respetar la visibilidad
{% /column %}
{% column width="1" valign="center" %}
```json
{
"type": "list",
"class": "categoriesList",
"categoriesList": {
"categories": [
{
"ticketOptionId": "17635820544251",
"quantityForSale": 0,
"floorPrice": 0,
"visible": true,
"callToAction": {
"text": "Check availability",
"url": "http://event.mentatickets.com",
"enabled": true,
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
},
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
},
{
"ticketOptionId": "17635820544252",
"quantityForSale": 0,
"floorPrice": 0,
"visible": true,
"callToAction": {
"text": "Check availability",
"url": "http://event.mentatickets.com",
"enabled": true,
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
},
"colors": {
"background": "#FFFFFF",
"text": "#0A1F44"
}
}
]
}
}
```
{% /column %}
{% /columns %}
{% /tab %}
{% tab label="Mapa Integrado" %}
# Mapa Integrado
{% columns gap="2rem" align="start" %}
{% column width="0.6" valign="top" %}
Mapa interactivo del venue que muestra la distribución de tickets de reventa disponibles por zona/sección. Permite visualizar la disponibilidad geográfica del inventario y seleccionar tickets directamente desde el mapa. Solo se habilita cuando el evento tiene seating configurado y hay inventario distribuido.
{% /column %}
{% column width="0.4" valign="top" %}

{% /column %}
{% /columns %}
---
## Estructura JSON
{% columns gap="2rem" align="start" %}
{% column width="0.75" valign="top" sticky=true %}
{% codeannotation highlight-lines="2" %}
**`type`**: Identifica que el tipo de componente es un `map`.
{% /codeannotation %}
{% codeannotation highlight-lines="3" %}
**`class`**: Identifica un subtipo de componente. En este caso es un `map` de tipo `integrado` o `integrated`.
{% /codeannotation %}
{% codeannotation highlight-lines="4" %}
**`integratedMap`**: Objeto contenedor que agrupa toda la información relacionada con el mapa integrado.
{% /codeannotation %}
{% codeannotation highlight-lines="5" %}
**`map`**: Objeto principal que contiene la configuración y datos del mapa.
{% /codeannotation %}
{% codeannotation highlight-lines="6:8" %}
**`config`**: Configuración de comportamientos del mapa:
- **`allowOrphanTicketSelection`**: Si es `true`, permite seleccionar tickets individuales. Si es `false`, solo permite selección de grupos completos.
{% /codeannotation %}
{% codeannotation highlight-lines="9" %}
**`totalCount`**: Número total de tickets disponibles para reventa en el mapa. Si es `0`, no hay tickets disponibles.
{% /codeannotation %}
{% codeannotation highlight-lines="10" %}
**`bestListing`**: Mejor listado disponible (menor precio o mejor ubicación) o `null` si no hay listados. Puede contener precio, ubicación, cantidad de tickets, etc.
{% /codeannotation %}
{% codeannotation highlight-lines="11" %}
**`results`**: Array con los listados de tickets disponibles organizados por zona/sección. Cada elemento representa un grupo de tickets en una ubicación específica. Puede incluir zona/sección, cantidad, precio, coordenadas e información de seating.
{% /codeannotation %}
**Notas de implementación**
- El mapa solo debe renderizarse si `totalCount > 0` o si las reglas de visibilidad lo requieren incluso sin inventario
- Debes implementar la lógica de renderizado del mapa del venue, típicamente usando las coordenadas o identificadores de zonas proporcionados en `results`
- Cada elemento en `results` debe mapearse a una zona/sección visual en el mapa
- Debes manejar la interacción del usuario (clic, hover) sobre las zonas del mapa
- Si `allowOrphanTicketSelection` es `false`, debes agrupar tickets y solo permitir selección de grupos completos
- El `bestListing` puede usarse para destacar visualmente una zona recomendada en el mapa
- Si `results` está vacío, puedes mostrar el mapa sin zonas destacadas o mostrar un mensaje de "Sin disponibilidad"
- Debes integrar este mapa con el flujo de compra, redirigiendo al usuario cuando selecciona una zona
{% /column %}
{% column width="1" valign="center" %}
```json
{
"type": "map",
"class": "integratedMap",
"integratedMap": {
"map": {
"config": {
"allowOrphanTicketSelection": true
},
"totalCount": 0,
"bestListing": null,
"results": []
}
}
}
```
{% /column %}
{% /columns %}
{% /tab %}
{% /conditionaltabs %}
---
# Entregando el boleto adquirido en reventa
La responsabilidad de realizar la entrega del boleto adquirido en reventa, es pura y exclusivamente de tu sistema.
Los flujos de optimizados de compra, venta, publicación, edición y detalle de venta, con mejoras constantes para potenciar la oferta y la demanda, son de menta tech.
Al momento de concretarse una reventa, inmediatamente **vamos a comunicarle a tu sistema que esto ha ocurrido.**
{% diagram type="sequence" height="400px" %}
{
"nodes": [
{
"id": "actor-1",
"type": "sequence-actor",
"position": {
"x": 80,
"y": 30
},
"data": {
"label": "Comprador",
"accentColor": "#22c55e",
"lifelineHeight": 306
}
},
{
"id": "actor-2",
"type": "sequence-actor",
"position": {
"x": 656.2896139143585,
"y": 30
},
"data": {
"label": "Tu plataforma",
"accentColor": "#f97316",
"lifelineHeight": 306
}
},
{
"id": "msg-1765938030861",
"type": "sequence-message",
"position": {
"x": 32.95834830885329,
"y": 78.88201144077624
},
"data": {
"label": "Realiza compra de boleto\nen mercado secundario"
}
},
{
"id": "actor-1765938270969",
"type": "sequence-actor",
"position": {
"x": 303.5,
"y": 30
},
"data": {
"label": "menta tech",
"accentColor": "#3b82f6",
"lifelineHeight": 306
}
},
{
"id": "msg-1765938351644",
"type": "sequence-message",
"position": {
"x": 278.925522042515,
"y": 135.9761734763762
},
"data": {
"label": "Se realiza el cobro"
}
},
{
"id": "actor-1765938398711",
"type": "sequence-actor",
"position": {
"x": 477.93814757136727,
"y": 30
},
"data": {
"label": "Pagos",
"accentColor": "#8b5cf6",
"lifelineHeight": 306
}
},
{
"id": "msg-1765938441980",
"type": "sequence-message",
"position": {
"x": 452.604814238034,
"y": 198.0376784787317
},
"data": {
"label": "Cobro confirmado"
}
},
{
"id": "msg-1765938477466",
"type": "sequence-message",
"position": {
"x": 262.3949013346587,
"y": 258.5307840006628
},
"data": {
"label": "Notifica reventa exitosa"
}
},
{
"id": "msg-1765938519424",
"type": "sequence-message",
"position": {
"x": 371.3340207090429,
"y": 344.1852822930613
},
"data": {
"label": "Recibe el boleto"
}
}
],
"edges": [
{
"id": "edge-1765938273771",
"source": "msg-1765938030861",
"target": "actor-1765938270969",
"sourceHandle": null,
"targetHandle": "h-1",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1765938428350",
"source": "msg-1765938351644",
"target": "actor-1765938398711",
"sourceHandle": null,
"targetHandle": "h-5",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1765938457827",
"source": "actor-1765938270969",
"target": "msg-1765938441980",
"sourceHandle": "s-10",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
},
{
"id": "edge-1765938579583",
"source": "msg-1765938477466",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-15",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"label": "Webhook HTTP",
"markerEnd": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
}
},
{
"id": "edge-1765938625799",
"source": "msg-1765938519424",
"target": "actor-2",
"sourceHandle": null,
"targetHandle": "h-22",
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true,
"animationReversed": true
}
},
{
"id": "edge-1765938680272",
"source": "actor-1",
"target": "msg-1765938519424",
"sourceHandle": "s-22",
"targetHandle": null,
"animated": true,
"style": {
"stroke": "#9ca3af",
"strokeWidth": 1.5
},
"markerStart": {
"type": "arrowclosed",
"color": "#9ca3af",
"width": 16,
"height": 16
},
"data": {
"isReversed": true
}
}
]
}
{% /diagram %}
{% columns gap="2rem" align="start" %}
{% column width="1" valign="center" %}
En este momento existen diferentes alternativas que los partners que nos eligen han adoptado para hacer frente a este requerimiento.
Todas tienen en común que reciben un `Webhook vía HTTP` que menta tech emite al sistema conectado.
Luego de recibir ese Webhook cada sistema realiza las acciones necesarias para transferir el boleto del vendedor al comprador, de forma segura.
menta tech recopila toda la información que necesites para lograr esto, desde correo electrónico del comprador, hasta datos de personalización de boletos, dirección postal, número de teléfono o cuales sean estos requisitos.
Todo viaja por `Webhook` a tu sistema. A la derecha hay un ejemplo completo del `JSON` enviado desde menta tech.
{% callout type="info" title="Recopilación de información" %}
Los campos que contienen datos personales pueden recopilar la información necesaria por tu sistema para el correcto envío del boleto al comprador.
{% /callout %}
{% /column %}
{% column width="2" valign="center" %}
Ejemplo de un `Webhook` saliente de menta tech informando la reventa exitosa.
```json
{
"family": "ticket",
"action": "ticket.updated",
"data": {
"id": "127471-2", // ID del boleto vendido (de tu sistema)
"newOwnerEmail": "susana@hotmail.com", // Correo del nuevo dueño
"oldOwnerEmail": "joe@gmail.com", // Correo del dueño anterior
"reversal": false, // true si la transacción se está revirtiendo
"metadata": {
"nominal": {
"fullName": "Susana Kann",
"identificationNumber": "1307009",
"identificationType": "DNI", // Tipo de documento del nuevo boleto. Depende del país.
},
"payer": {
"fullName": "Susana Kann",
"identificationNumber": "1307009",
"identificationType": "DNI", // Tipo de documento del comprador. Depende del país.
},
"seller": {
"identification": "9282712", // Identificación del vendedor
"identificationType": "CC" // Tipo de documento del vendedor. Depende del país.
},
"order": {
"resaleId": "689a3a0bc68bd2502ce21b15", // ID de la venta (en menta tech)
"grossResalePaidAmount": 57.5, // Precio total de la venta
"grossResalePaidAmountWithoutBuyerFee": 50.0, // Precio de venta sin fee del comprador
"buyerFee": 0.15, // Fee del comprador.
"buyerFeeAmount": 7.5 // Monto del fee del comprador
}
}
}
}
```
{% /column %}
{% /columns %}
---
# API de Actualización de Inventario (Market Data)
## Descripción General
Hay dos endpoints para actualizar datos de inventario en menta tech:
1. **PUT a nivel de evento**: Para actualizar el inventario completo de un evento
2. **PUT a nivel granular**: Para actualizar inventario en lotes (por ticketOption, priceType, o combinaciones)
Ambos endpoints requieren autenticación y el `externalReferenceId` del evento.
---
## Endpoint 1: Actualización de Evento Completo
### Request
```
PUT /v1/marketdata/events/{externalReferenceId}/inventory?showId={showId}
```
**Headers requeridos:**
- `Authorization: {apiKey}`
- `Content-Type: application/json`
**Path parameters:**
- `externalReferenceId` (requerido): Identificador externo del evento
**Query parameters:**
- `showId` (opcional): Si el evento tiene múltiples shows, especifica cuál actualizar. Si el evento tiene solo un show, no es necesario.
### Body
```json
{
"capacity": 5000,
"releasedTickets": 5000,
"reservedSpace": 100,
"soldOut": false,
"soldPercentage": 75
}
```
Todos los campos son opcionales. Solo envía los que quieres actualizar.
### Ejemplo
```bash
curl -X PUT "https://api.mentatech.io/v1/marketdata/events/EVENT_2024_001/inventory?showId=show123" \
-H "Authorization: apiKey" \
-H "Content-Type: application/json" \
-d '{
"capacity": 5000,
"releasedTickets": 5000,
"reservedSpace": 100,
"soldOut": false,
"soldPercentage": 75
}'
```
### Response
La API retorna el evento actualizado con todos sus datos.
---
## Endpoint 2: Actualización en Lotes (Granular)
Este endpoint te permite actualizar inventario para múltiples categorías, tipos de precio, o combinaciones en una sola llamada. **Útil cuando tienes múltiples shows y cada uno puede tener items diferentes.**
### Request
```
PUT /v1/marketdata/events/{externalReferenceId}/inventory/details
```
**Headers requeridos:**
- `Authorization: {apiKey}`
- `Content-Type: application/json`
**Path parameters:**
- `externalReferenceId` (requerido): Identificador externo del evento
### Body
El body es un array de items. Cada item debe incluir un `showId` y puede ser de tres tipos:
```json
[
{
"showId": "show123",
"ticketOptionId": "zone_a",
"inventory": {
"releasedTickets": 1000,
"reservedSpace": 50,
"soldOut": false,
"soldPercentage": 80
}
},
{
"showId": "show123",
"priceTypeId": "early_bird",
"inventory": {
"releasedTickets": 200,
"reservedSpace": 10,
"soldOut": false,
"soldPercentage": 90
}
},
{
"showId": "show456",
"ticketOptionId": "zone_b",
"priceTypeId": "regular",
"inventory": {
"releasedTickets": 500,
"reservedSpace": 25,
"soldOut": false,
"soldPercentage": 70
}
}
]
```
### Tipos de Items
1. **Solo ticketOptionId**: Actualiza el inventario de una categoría de tickets
```json
{
"showId": "show123",
"ticketOptionId": "zone_a",
"inventory": { ... }
}
```
2. **Solo priceTypeId**: Actualiza el inventario de un tipo de precio
```json
{
"showId": "show123",
"priceTypeId": "early_bird",
"inventory": { ... }
}
```
3. **ticketOptionId + priceTypeId**: Actualiza la combinación de categoría + tipo de precio
```json
{
"showId": "show123",
"ticketOptionId": "zone_a",
"priceTypeId": "early_bird",
"inventory": { ... }
}
```
### Ejemplo Completo
```bash
curl -X PUT "https://api.mentatech.io/v1/marketdata/events/EVENT_2024_001/inventory/details" \
-H "Authorization: apiKey" \
-H "Content-Type: application/json" \
-d '[
{
"showId": "show123",
"ticketOptionId": "zone_a",
"inventory": {
"releasedTickets": 1000,
"reservedSpace": 50,
"soldOut": false,
"soldPercentage": 80
}
},
{
"showId": "show456",
"ticketOptionId": "zone_b",
"priceTypeId": "early_bird",
"inventory": {
"releasedTickets": 500,
"reservedSpace": 25,
"soldOut": false,
"soldPercentage": 70
}
}
]'
```
---
## Campos del Objeto Inventory
Estos son los campos que puedes actualizar en ambos endpoints:
| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| `capacity` | number | No | Capacidad total de tickets (solo en actualización de evento) |
| `releasedTickets` | number | No | Tickets liberados para la venta |
| `reservedSpace` | number | No | Tickets reservados (no disponibles para compra) |
| `soldOut` | boolean | No | Indica si la categoría/evento está sold out |
| `soldPercentage` | number | No | Porcentaje de venta (0-100) |
Todos los campos son **opcionales**. Solo envía los que necesitas actualizar.
---
## Casos de Uso
### Caso 1: Actualizar todo el evento a la vez sin especificación de datos granulares.
Si tienes un evento simple con un único show:
```bash
curl -X PUT "https://api.mentatech.io/v1/marketdata/events/EVENT_001/inventory" \
-H "Authorization: apiKey" \
-d '{
"releasedTickets": 5000,
"reservedSpace": 100,
"soldPercentage": 75,
"soldOut": false
}'
```
### Caso 2: Actualizar solo una categoría de tickets
Si tienes categorías diferentes (General Admission, VIP, etc.):
```bash
curl -X PUT "https://api.mentatech.io/v1/marketdata/events/EVENT_001/inventory/details" \
-H "Authorization: apiKey" \
-d '[
{
"showId": "show_main",
"ticketOptionId": "general_admission",
"inventory": {
"releasedTickets": 5000,
"reservedSpace": 100,
"soldPercentage": 75,
"soldOut": false
}
}
]'
```
### Caso 3: Actualizar múltiples shows y categorías
```bash
curl -X PUT "https://api.mentatech.io/v1/marketdata/events/EVENT_001/inventory/details" \
-H "Authorization: apiKey" \
-d '[
{
"showId": "show_1",
"ticketOptionId": "vip",
"inventory": {
"releasedTickets": 5000,
"reservedSpace": 100,
"soldPercentage": 75,
"soldOut": false
}
},
{
"showId": "show_1",
"ticketOptionId": "general",
"inventory": {
"releasedTickets": 5000,
"reservedSpace": 100,
"soldPercentage": 75,
"soldOut": false
}
},
{
"showId": "show_2",
"ticketOptionId": "vip",
"inventory": {
"releasedTickets": 5000,
"reservedSpace": 100,
"soldPercentage": 75,
"soldOut": false
}
}
]'
```
---
## Notas Importantes
- **Autenticación requerida**: Todos los requests deben incluir un token válido en el header `Authorization`
- **externalReferenceId**: Usa el identificador del evento en tu sistema.
- **showId en lotes**: Cada item del lote debe especificar el `showId` al que pertenece
- **Campos opcionales**: No necesitas enviar todos los campos; solo los que quieres actualizar
---
# API de Leads de Tickets (Market Data)
## Descripción General
El feature **Market Data de Leads de Tickets** te permite enviar información sobre usuarios que participan del ciclo de vida del boleto: usuarios que adquirieron boletos en venta primaria o que tuvieron la intención de hacerlo en algún momento. Estos datos ayudan a menta tech a identificar posibles compradores para tickets de reventa disponibles en tu plataforma.
Existen diferentes tipos de leads que podemos recibir según el estado del usuario:
- **Ticket Holder**: Usuarios que ya han comprado un boleto y son posibles vendedores de reventa
- **Abandoned Cart**: Usuarios que abandonaron su compra en venta primaria y pueden estar interesados en reventa
- **Virtual Queue**: Usuarios que estuvieron en fila virtual pero no compraron, demostrando interés
- **Wishlist**: Usuarios que se suscribieron para recibir notificaciones de disponibilidad
---
## Comparativa de Tipos de Leads
{% table highlight-first=true %}
| Tipo | Descripción | Propósito | Cuándo usar | Ventajas |
|------|-------------|----------|------------|----------|
| **Ticket Holder** | Usuario con un boleto comprado | Posible vendedor de reventa | Cuando un usuario compra un boleto | El usuario ya tiene el asset; mayor probabilidad de venta |
| **Abandoned Cart** | Usuario que abandonó compra primaria | Potencial comprador de reventa | Cuando se abandona un carrito de compra | Usuario demostró interés pero precio/timing no fueron viables |
| **Virtual Queue** | Usuario en fila virtual abandonada | Potencial comprador de reventa | Cuando el usuario se retira de la fila | Interés confirmado; posible buyer con urgencia |
| **Wishlist** | Usuario suscrito a notificaciones | Lead para notificación de oferta | Cuando el usuario se suscribe | Opt-in explícito; alta probabilidad de conversión |
{% /table %}
---
## Endpoints Disponibles
Existen dos formas de enviar leads de tickets:
1. **POST Individual**: Para enviar un único lead
2. **POST Bulk/Lote**: Para enviar múltiples leads en una sola llamada (hasta 1000 por request)
---
## Endpoint 1: Envío Individual de Lead
### Request
```
POST /v1/marketdata/ticket-leads
```
**Headers requeridos:**
- `Authorization: {apiKey}`
- `Content-Type: application/json`
### Body
El body varía según el tipo de lead. Cada uno tiene una estructura específica.
{% conditionaltabs id="tabs-ticket-leads-individual" %}
{% tab label="Ticket Holder" %}
### Ticket Holder - Estructura
Un **Ticket Holder** es un usuario que ya ha completado una compra y posee un boleto válido. Este tipo de lead es ideal para identificar posibles vendedores en reventa.
#### Campos Requeridos
- `type`: Debe ser exactamente `"TICKET_HOLDER"`
- `externalReferenceEventId`: ID externo del evento
- `showId`: ID del show específico
- `ticketId`: ID único del boleto
- `buyer`: Objeto con información del comprador (al menos un identificador: email, phone o id)
- `price`: Precio pagado por el boleto
- `currency`: Código de moneda (ISO 4217)
#### Ejemplo Completo
```json
{
"type": "TICKET_HOLDER",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"ticketId": "TICKET_abc123def456",
"buyer": {
"email": "john.doe@example.com",
"fullName": "John Doe",
"id": "user_12345"
},
"ticketOptionId": "GA",
"priceTypeId": "regular",
"purchaseDate": "2024-12-15T10:30:00Z",
"price": 99.99,
"currency": "USD",
"seating": {
"section": "A",
"row": "5",
"seat": "12"
},
"metadata": {
"section_type": "vip",
"notes": "Premium seating"
},
"tags": ["vip", "early_bird"]
}
```
#### Campos del Buyer
El objeto `buyer` debe contener **al menos uno** de estos identificadores:
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `email` | string | Email del comprador (ej: buyer@example.com) |
| `phone` | string | Teléfono del comprador (ej: +1234567890) |
| `id` | string | ID único en tu sistema (ej: user_12345, recomendado para GDPR/LGPD) |
#### Campos de Seating (Opcional)
Si tienes información de asientos:
```json
"seating": {
"section": "A",
"row": "5",
"seat": "12"
}
```
{% /tab %}
{% tab label="Abandoned Cart" %}
### Abandoned Cart - Estructura
Un **Abandoned Cart** es un usuario que inició el proceso de compra pero no completó la transacción. Estos usuarios son potenciales compradores de reventa cuando el precio o disponibilidad cambian.
#### Campos Requeridos
- `type`: Debe ser exactamente `"ABANDONED_CART"`
- `externalReferenceEventId`: ID externo del evento
- `showId`: ID del show específico
- `buyer`: Objeto con información del usuario (al menos un identificador)
#### Ejemplo Completo
```json
{
"type": "ABANDONED_CART",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"ticketId": "TICKET_def456ghi789",
"buyer": {
"email": "potential@example.com",
"id": "user_abandoned_1",
"fullName": "Jane Smith"
},
"ticketOptionId": "VIP",
"priceTypeId": "early_bird",
"purchaseDate": "2024-12-14T15:45:00Z",
"price": 149.99,
"currency": "USD",
"seating": {
"section": "B",
"row": "10"
},
"metadata": {
"last_action": "checkout",
"items_in_cart": 2,
"reason_abandoned": "payment_failed"
},
"tags": ["abandoned", "recovery_email_sent"]
}
```
#### Nota
Los campos `price` y `ticketId` son **opcionales** pero recomendados. El `purchaseDate` refiere a cuándo se abandonó el carrito.
{% /tab %}
{% tab label="Virtual Queue" %}
### Virtual Queue - Estructura
Un **Virtual Queue** es un usuario que estuvo en la fila virtual para comprar boletos pero abandonó el proceso sin realizar compra. Estos usuarios demostraron interés en tiempo real.
#### Campos Requeridos
- `type`: Debe ser exactamente `"VIRTUAL_QUEUE"`
- `externalReferenceEventId`: ID externo del evento
- `showId`: ID del show específico
- `buyer`: Objeto con información del usuario (al menos un identificador)
#### Ejemplo Completo
```json
{
"type": "VIRTUAL_QUEUE",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"ticketId": "TICKET_ghi789jkl012",
"buyer": {
"email": "queue@example.com",
"id": "user_queue_1",
"phone": "+1987654321"
},
"ticketOptionId": "GA",
"priceTypeId": "regular",
"purchaseDate": "2024-12-14T09:15:00Z",
"price": 99.99,
"currency": "USD",
"metadata": {
"queue_position": 2500,
"wait_time_minutes": 45,
"queue_exit_reason": "timeout"
},
"tags": ["queue_abandonment", "high_demand"]
}
```
#### Nota
El `purchaseDate` en este caso refiere a cuándo el usuario abandonó la fila. Los campos de `price`, `ticketOptionId` y `seating` son opcionales.
{% /tab %}
{% tab label="Wishlist" %}
### Wishlist - Estructura
Un **Wishlist** es un usuario que se suscribió explícitamente para recibir notificaciones sobre disponibilidad de boletos. Este es el lead de mayor calidad: opt-in directo.
#### Campos Requeridos
- `type`: Debe ser exactamente `"WISHLIST"`
- `externalReferenceEventId`: ID externo del evento
- `showId`: ID del show específico
- `buyer`: Objeto con información del usuario (al menos un identificador)
#### Ejemplo Completo
```json
{
"type": "WISHLIST",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": {
"email": "wishlist@example.com",
"id": "user_wishlist_1",
"fullName": "Michael Brown"
},
"ticketOptionId": "VIP",
"priceTypeId": "vip_early",
"purchaseDate": "2024-12-10T14:20:00Z",
"price": 199.99,
"currency": "USD",
"metadata": {
"notification_frequency": "daily",
"preferred_section": "floor",
"max_price_willing_to_pay": 250
}
}
```
#### Nota
Todos los campos excepto `type`, `externalReferenceEventId`, `showId` y `buyer` son opcionales. El `purchaseDate` refiere a cuándo se agregó a la wishlist.
{% /tab %}
{% /conditionaltabs %}
---
## Endpoint 2: Envío en Lote (Bulk)
### Request
```
POST /v1/marketdata/ticket-leads/bulk
```
**Headers requeridos:**
- `Authorization: {apiKey}`
- `Content-Type: application/json`
### Body
El body es un **array de leads**. Puedes mezclar diferentes tipos en un mismo request. Máximo **1000 leads por request**.
```json
[
{
"type": "TICKET_HOLDER",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"ticketId": "TICKET_abc123",
"buyer": {
"email": "buyer1@example.com",
"fullName": "John Doe"
},
"price": 99.99,
"currency": "USD"
},
{
"type": "TICKET_HOLDER",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"ticketId": "tkt_091bad9f1d83a",
"buyer": {
"id": "usr_9289370133"
},
"price": 451.31,
"currency": "MXN"
},
{
"type": "ABANDONED_CART",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": {
"email": "abandoned@example.com"
},
"ticketOptionId": "GA"
},
{
"type": "WISHLIST",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": {
"email": "wishlist@example.com",
"id": "user_wishlist_1"
},
"ticketOptionId": "VIP"
}
]
```
### Características del Bulk
- **Máximo de registros**: 1000 leads por request
- **Mezcla de tipos**: Puedes incluir TICKET_HOLDER, ABANDONED_CART, VIRTUAL_QUEUE y WISHLIST en el mismo request
- **Validación individual**: Cada lead se valida por separado
- **Idempotencia**: Los leads se crean o actualizan según el identificador del buyer (email, phone, o id)
---
## Respuesta de la API
### Respuesta Exitosa (200 OK)
Cuando el lead se envía correctamente, la API retorna:
```json
{
"status": 200,
"data": true,
"errors": null
}
```
### Manejo de Errores
Si hay un problema, la API retorna un mensaje descriptivo. Ejemplos:
**Missing required field:**
```json
{
"status": 400,
"data": null,
"errors": {
"message": "buyer.email or buyer.phone or buyer.id is required"
}
}
```
**Invalid event ID:**
```json
{
"status": 404,
"data": null,
"errors": {
"message": "Event not found"
}
}
```
---
## Campos Comunes en Todos los Tipos de Leads
Estos campos se pueden incluir en cualquier tipo de lead:
| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| `type` | string | Sí | Tipo de lead: TICKET_HOLDER, ABANDONED_CART, VIRTUAL_QUEUE, WISHLIST |
| `externalReferenceEventId` | string | Sí | ID externo del evento |
| `showId` | string | Sí | ID del show específico |
| `buyer` | object | Sí | Información del usuario (al menos un identificador) |
| `ticketId` | string | Depende | Requerido solo para TICKET_HOLDER |
| `price` | number | Depende | Requerido solo para TICKET_HOLDER |
| `currency` | string | No | Código de moneda (ISO 4217, ej: USD, MXN, EUR) |
| `ticketOptionId` | string | No | ID de la categoría de boleto (GA, VIP, etc.) |
| `priceTypeId` | string | No | ID del tipo de precio (early_bird, regular, etc.) |
| `purchaseDate` | string | No | Fecha en formato ISO 8601 (ej: 2024-12-15T10:30:00Z) |
| `seating` | object | No | Información de asientos (section, row, seat) |
| `metadata` | object | No | Datos personalizados (JSON libre) |
| `tags` | array | No | Array de strings para categorización |
---
## Ejemplos de Uso
### Caso 1: Enviar un Ticket Holder Individual
```bash
curl -X POST "https://api.mentatech.io/v1/marketdata/ticket-leads" \
-H "Authorization: apiKey" \
-H "Content-Type: application/json" \
-d '{
"type": "TICKET_HOLDER",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"ticketId": "TICKET_abc123def456",
"buyer": {
"email": "john.doe@example.com",
"fullName": "John Doe"
},
"price": 99.99,
"currency": "USD"
}'
```
### Caso 2: Enviar un Abandoned Cart Individual
```bash
curl -X POST "https://api.mentatech.io/v1/marketdata/ticket-leads" \
-H "Authorization: apiKey" \
-H "Content-Type: application/json" \
-d '{
"type": "ABANDONED_CART",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": {
"email": "potential@example.com",
"id": "user_abandoned_1"
},
"ticketOptionId": "VIP",
"price": 149.99,
"currency": "USD"
}'
```
### Caso 3: Enviar Lote Mixto (100 leads)
```bash
curl -X POST "https://api.mentatech.io/v1/marketdata/ticket-leads/bulk" \
-H "Authorization: apiKey" \
-H "Content-Type: application/json" \
-d '[
{
"type": "TICKET_HOLDER",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"ticketId": "TICKET_001",
"buyer": { "email": "user1@example.com" },
"price": 99.99,
"currency": "USD"
},
{
"type": "ABANDONED_CART",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": { "email": "user2@example.com" }
},
{
"type": "VIRTUAL_QUEUE",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": { "id": "user_3" }
},
{
"type": "WISHLIST",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": { "phone": "+1234567890" },
"ticketOptionId": "VIP"
}
]'
```
### Caso 4: Enviar Wishlist con Preferencias
```bash
curl -X POST "https://api.mentatech.io/v1/marketdata/ticket-leads" \
-H "Authorization: apiKey" \
-H "Content-Type: application/json" \
-d '{
"type": "WISHLIST",
"externalReferenceEventId": "evt_2024_metallica",
"showId": "show_nyc_20240815",
"buyer": {
"email": "wishlist@example.com",
"id": "user_wishlist_1",
"fullName": "Michael Brown"
},
"ticketOptionId": "VIP",
"metadata": {
"notification_frequency": "daily",
"preferred_section": "floor",
"max_price_willing_to_pay": 250
}
}'
```
---
## Referencia de API
{% apiembed endpoint="post-marketdata-leads" show="link" width="auto" /%}
{% apiembed endpoint="post-marketdata-leads-batch" show="link" width="auto" /%}
---
## Mejores Prácticas
### 1. Identificadores del Buyer
Siempre incluye **al menos uno** de estos para mejor tracking:
- **email**: Ideal para comunicaciones directas
- **id**: Recomendado para cumplimiento GDPR/LGPD (privacy-safe)
- **phone**: Complementario a email
```json
{
"buyer": {
"email": "user@example.com",
"id": "usr_123456",
"phone": "+1234567890"
}
}
```
### 2. Metadata para Contexto
Usa `metadata` para agregar información contextual sin afectar la estructura:
```json
{
"metadata": {
"source": "website_checkout",
"device": "mobile",
"referrer": "instagram_ad",
"utm_campaign": "metallica_tour_2024"
}
}
```
### 3. Tags para Categorización
Usa `tags` para facilitar búsquedas y reportes:
```json
{
"tags": ["vip_section", "early_bird", "high_value_customer", "recovery_needed"]
}
```
### 4. Envío en Lote para Eficiencia
Cuando tengas múltiples leads, siempre usa el endpoint bulk:
```bash
# ✅ Correcto: 1000 leads en 1 request
POST /v1/marketdata/ticket-leads/bulk
# ❌ Ineficiente: 1000 requests individuales
POST /v1/marketdata/ticket-leads (repetido 1000 veces)
```
### 5. Idempotencia y Upsert
El sistema usa el identificador del buyer para hacer upsert:
- Si `email` + `externalReferenceEventId` + `showId` existen → **Actualiza**
- Si no existen → **Crea** un nuevo registro
Esto significa que puedes enviar el mismo lead múltiples veces sin duplicados.
---
## Notas Importantes
- **Autenticación requerida**: Todos los requests deben incluir un token válido en el header `Authorization`
- **externalReferenceEventId**: Usa el identificador del evento de tu sistema.
- **showId**: Cada lead debe especificar el show al que pertenece (importante para eventos multi-date)
- **Buyer identifier**: Al menos uno (email, phone, o id) es obligatorio
- **Máximo bulk**: 1000 leads por request. Para más, haz múltiples requests
- **Upsert automático**: Los leads se actualizan automáticamente si ya existen
---
# Integración en WebViews
## Descripción general
La integración de **menta tech** dentro de una aplicación móvil se realiza mediante la incorporación de **WebViews** que cargan las URLs provistas por menta tech.
Este documento describe los pasos necesarios para implementar la integración correctamente y garantizar una experiencia fluida para los usuarios.
{% callout type="info" title="Requisito previo" %}
Antes de integrar WebViews, asegurate de tener configurada la [Autenticación de usuarios](/es/guides/auth) para que los flujos de compra y venta funcionen correctamente dentro del WebView.
{% /callout %}
---
## Configuración del WebView
Las URLs de menta tech deben cargarse directamente en el WebView de la aplicación. Para optimizar la experiencia visual e integrarla con el entorno nativo, se debe agregar el parámetro `disableLayout=true` a todas las URLs de menta tech.
Este parámetro oculta el *header* y el *footer* de la interfaz web, de modo que el contenido se adapte perfectamente al *layout* de la aplicación nativa.
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
### Parámetro
| Parámetro | Valor | Descripción |
|-----------|-------|-------------|
| `disableLayout` | `true` | Oculta header y footer de menta tech para una integración nativa |
{% /column %}
{% column width="0.5" valign="center" %}
### Ejemplo de URL
```
https://example.menta.com/endpoint?disableLayout=true
```
{% callout type="warning" title="Importante" %}
Este parámetro debe incluirse en **todas** las URLs de menta tech que se carguen dentro de un WebView. De lo contrario, se mostrará la navegación web estándar que no corresponde a una experiencia nativa.
{% /callout %}
{% /column %}
{% /columns %}
---
## Comunicación entre la App y el WebView
Para mejorar la navegación y la experiencia de usuario, se debe habilitar la comunicación bidireccional entre la aplicación y menta tech mediante el uso de `postMessage`.
Esto permite enviar y recibir eventos entre ambos entornos, como acciones de navegación o actualizaciones de estado.
{% callout type="info" title="postMessage API" %}
La API de `postMessage` es el estándar de comunicación entre el WebView y la aplicación nativa. Permite enviar mensajes estructurados en formato JSON entre ambos contextos de forma segura.
{% /callout %}
{% conditionaltabs id="tabs-webview-communication" %}
{% tab label="Acción: Ir Atrás (GoBack)" %}
### Acción: Ir Atrás (GoBack)
Para implementar la funcionalidad de "volver al paso anterior", la aplicación debe enviar un mensaje `GoBack` hacia menta tech.
Al recibir este mensaje, menta tech retrocede un paso dentro del flujo correspondiente.
#### Mensaje desde la App hacia menta tech
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
```javascript
webViewRef.current.postMessage(
JSON.stringify({
type: "NAVIGATION",
payload: "goBackStep"
})
);
```
{% /column %}
{% column width="0.5" valign="center" %}
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `type` | `string` | Tipo de mensaje. Debe ser `"NAVIGATION"` |
| `payload` | `string` | Acción a ejecutar. Debe ser `"goBackStep"` |
{% callout type="check" title="Resultado" %}
menta tech retrocede un paso en el flujo activo del WebView.
{% /callout %}
{% /column %}
{% /columns %}
#### Cuándo usarlo
- Cuando tu aplicación tiene un botón de "Atrás" nativo y querés que también controle la navegación dentro de menta tech.
- Para ofrecer una experiencia de navegación coherente entre la app y el contenido del WebView.
{% /tab %}
{% tab label="Comunicación de Step Activo" %}
### Comunicación de Step Activo
Durante todo el flujo, menta tech enviará mensajes hacia la aplicación indicando en qué paso se encuentra el usuario.
Esto permite actualizar el estado o la UI de la aplicación en tiempo real.
#### Mensaje desde menta tech hacia la App
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
```javascript
// menta tech envía este mensaje al WebView:
window.ReactNativeWebView.postMessage(
JSON.stringify({ step })
);
```
{% /column %}
{% column width="0.5" valign="center" %}
| Campo | Tipo | Descripción |
|-------|------|-------------|
| `step` | `string` | Identificador del paso actual en el flujo de menta tech |
{% callout type="info" title="Uso recomendado" %}
Escuchá estos mensajes para actualizar la UI nativa (por ejemplo: indicadores de progreso, títulos de pantalla o lógica condicional).
{% /callout %}
{% /column %}
{% /columns %}
#### Cómo escuchar mensajes en React Native
```javascript
{
const data = JSON.parse(event.nativeEvent.data);
console.log("Step actual:", data.step);
// Actualizar UI nativa según el step
}}
/>
```
{% /tab %}
{% /conditionaltabs %}
---
## Finalización del Flujo
Cuando el flujo en menta tech finaliza correctamente, la URL cargada en el WebView incluirá el parámetro `success`.
La aplicación debe monitorear los cambios en la URL del WebView para detectar este evento y cerrar el componente, regresando al contexto principal de la aplicación.
### Detección de finalización
{% columns gap="2rem" align="center" %}
{% column width="0.5" valign="center" %}
#### URL de finalización
```
https://example.menta.com/success
```
Al detectar la URL con el parámetro `success`, la aplicación debe cerrar automáticamente el WebView y restablecer la vista principal.
{% /column %}
{% column width="0.5" valign="center" %}
#### Ejemplo en React Native
```javascript
{
if (navState.url.includes("/success")) {
// Cerrar el WebView
navigation.goBack();
// Opcionalmente, refrescar datos
}
}}
/>
```
{% /column %}
{% /columns %}
{% callout type="warning" title="Importante" %}
La detección de la URL de `success` es la única forma de saber que el flujo finalizó correctamente. Asegurate de implementar esta verificación para evitar que el usuario quede atrapado en el WebView después de completar la operación.
{% /callout %}
---
## Resumen de la integración
{% table highlight-first=true %}
| Paso | Acción | Detalle |
|------|--------|---------|
| 1. Configurar WebView | Agregar `disableLayout=true` | Oculta header/footer de menta tech para una experiencia nativa |
| 2. Comunicación App → menta | Implementar `postMessage` con tipo `NAVIGATION` | Permite controlar la navegación interna (GoBack) |
| 3. Comunicación menta → App | Escuchar mensajes de `step` | Permite actualizar la UI nativa según el progreso del flujo |
| 4. Finalización | Detectar URL con `success` | Cerrar el WebView y volver al contexto principal de la app |
{% /table %}
---
# Webhooks
## Descripción General
Los **webhooks** permiten a menta tech notificar a tu plataforma en tiempo real cada vez que ocurre un evento relevante en el ecosistema de reventa. En lugar de consultar periódicamente por cambios, tu sistema recibe solicitudes HTTP POST con datos estructurados del evento en el momento en que ocurren.
Los webhooks son esenciales para:
* Mantener tu plataforma sincronizada con la actividad de reventa
* Disparar procesos posteriores (entrega de boletos, reportes, actualizaciones de CRM)
* Rastrear la actividad del marketplace (publicaciones, ventas, pagos)
* Habilitar notificaciones en tiempo real para los usuarios
## Estructura General del Payload
Cada webhook enviado por menta tech sigue un formato de envoltorio consistente:
```json
{
"family": "",
"action": "",
"type": "",
"data": { ... }
}
```
{% table highlight-first=true %}
| Campo | Descripción |
| :--- | :--- |
| `family` | Agrupa eventos relacionados (ej., `listing`, `ticket`, `event`, `notifyMe`, `payouts`). |
| `action` | El evento específico que ocurrió (ej., `listing.created`, `ticket.updated`). |
| `type` | Proporciona contexto adicional sobre la variante del evento (ej., `SINGLE`, `MULTI`, `USER_TRANSFER`). No está presente en todos los eventos. |
| `data` | El payload específico del evento con la información relevante. |
{% /table %}
## Resumen de Eventos
{% table highlight-first=true %}
| Familia | Acción | Descripción |
| :--- | :--- | :--- |
| **listing** | `listing.created` | Se publicó una nueva publicación en el mercado secundario. |
| **listing** | `listing.updated` | Se modificó una publicación existente (ej., cambio de precio). |
| **listing** | `listing.deleted` | Se eliminó una publicación del mercado secundario. |
| **ticket** | `ticket.updated` | Se completó una reventa y cambió el dueño del boleto. |
| **event** | `event.unlock` | Se desbloquearon los boletos de un evento. |
| **notifyMe** | `notifyMe.created.updated` | Se creó o actualizó una suscripción de "Avisarme". |
| **payouts** | `payouts.delivered` | Se enviaron los pagos a los vendedores de un evento/show. |
{% /table %}
---
## Notas Importantes sobre Identificadores
{% callout type="warning" %}
La mayoría de los identificadores en los payloads de webhooks — como `ticketId`, `eventId`, `showId` y el campo `id` en `ticket.updated` — provienen de **tu plataforma**. Corresponden a los IDs que asignaste al crear o sincronizar estos recursos con menta tech.
Los siguientes identificadores son generados por **menta tech**:
* `listingId` — Identificador único de una publicación en el marketplace.
* `groupId` — Agrupa boletos dentro de una misma operación de publicación.
* `resaleId` — Identificador único de una transacción de reventa completada.
* `id` (en eventos `notifyMe`) — Identificador único de una suscripción de "Avisarme".
{% /callout %}
---
## Detalle de Eventos
{% conditionaltabs id="tabs-webhooks-families" %}
{% tab label="Listing" %}
## Eventos de Listing
Los eventos de listing notifican a tu plataforma sobre cambios en el inventario del marketplace de reventa. Se disparan cada vez que un usuario crea, actualiza o elimina una publicación de boletos.
El campo `type` en los eventos de listing indica si la publicación involucra un solo boleto (`SINGLE`) o múltiples boletos (`MULTI`).
### listing.created
Se dispara cuando un usuario publica una nueva oferta en el mercado secundario.
```json
{
"family": "listing",
"action": "listing.created",
"type": "MULTI",
"data": {
"ticketId": "5102",
"sellerEmail": "maria.becerra@example.com",
"listingId": "70cde790d4e17236e08587g2",
"listingPrice": 1500,
"listingFinalPrice": 1725,
"listingPayout": {
"type": "LOCAL_FIAT_AUTOMATIC",
"data": {
"paymentMethod": "emoneyout-mxn_012",
"userForm": {
"beneficiary_name": "Maria",
"beneficiary_lastname": "Becerra",
"bank_account": "014027000012345678",
"bank_account_type": "checking"
}
}
},
"groupId": "70cde790d4e17236e08587ec"
}
}
```
### listing.updated
Se dispara cuando un usuario modifica una publicación existente (ej., cambio de precio).
```json
{
"family": "listing",
"action": "listing.updated",
"type": "SINGLE",
"data": {
"ticketId": "T3FB2E891AA4208",
"listingId": "70cedef51c3fcd8f74d0e4e1",
"listingPrice": 14,
"listingFinalPrice": 16.1,
"listingPayout": {
"type": "LOCAL_FIAT_AUTOMATIC",
"data": {
"paymentMethod": "dlocal-emoneyout-mxn_138",
"userForm": {
"beneficiary_name": "Jorge",
"beneficiary_lastname": "Ramirez",
"bank_account": "072180001098765432"
}
}
},
"groupId": "70cedef51c3fcd8f74d0e4d8",
"sellerEmail": "jorge.ramirez@example.com"
}
}
```
### listing.deleted
Se dispara cuando se elimina una publicación del mercado secundario, ya sea por el usuario o por el sistema.
```json
{
"family": "listing",
"action": "listing.deleted",
"type": "MULTI",
"data": {
"ticketId": "5102",
"sellerEmail": "maria.becerra@example.com",
"listingId": "70cde6551b66d4098c5523dc",
"listingPrice": 1500,
"listingFinalPrice": 1725,
"listingPayout": {
"type": "LOCAL_FIAT_AUTOMATIC",
"data": {
"paymentMethod": "emoneyout-mxn_012",
"userForm": {
"beneficiary_name": "Maria",
"beneficiary_lastname": "Becerra",
"bank_account": "014027000012345678",
"bank_account_type": "checking"
}
}
},
"groupId": "70cde6551b66d4098c5523dc"
}
}
```
### Campos del Payload de Listing
| Campo | Descripción | Origen del ID |
| :--- | :--- | :--- |
| `ticketId` | El identificador del boleto. | Tu plataforma |
| `sellerEmail` | Email o número de teléfono del vendedor. | — |
| `listingId` | Identificador único de la publicación. | menta tech |
| `listingPrice` | El precio establecido por el vendedor (antes de comisiones). | — |
| `listingFinalPrice` | El precio final para el comprador (incluyendo comisiones). | — |
| `listingPayout` | Configuración y método de pago para el vendedor. | — |
| `groupId` | Identificador que agrupa múltiples boletos en una misma operación de publicación. | menta tech |
{% /tab %}
{% tab label="Ticket" %}
## Eventos de Ticket
### ticket.updated
Se dispara cuando se completa una transacción de reventa y la propiedad del boleto cambia del vendedor al comprador. Este es el evento clave para iniciar la entrega del boleto en tu plataforma.
```json
{
"family": "ticket",
"action": "ticket.updated",
"type": "USER_TRANSFER",
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"newOwnerEmail": "carlos.lopez@example.com",
"oldOwnerEmail": "ana.martinez@example.com",
"reversal": false,
"metadata": {
"nominal": {
"fullName": "Carlos Lopez",
"identificationType": "DNI",
"identification": "30567890",
"externalEmail": "carlos.lopez@example.com",
"email": "carlos.lopez@example.com"
},
"payer": {
"fullName": "Carlos Lopez",
"identificationType": "DNI",
"identification": "30567890",
"externalEmail": "carlos.lopez@example.com",
"email": "carlos.lopez@example.com"
},
"seller": {
"fullName": "Ana Martinez",
"identification": "28901234",
"identificationType": "DNI"
},
"order": {
"resaleId": "70ceeed4d4e17236e085e472",
"grossResalePaidAmount": 103816.25,
"grossResalePaidAmountWithoutBuyerFee": 90275,
"sellerFee": 0.15,
"sellerFeeAmount": 11775,
"buyerFee": 0.15,
"buyerFeeAmount": 13541.25
}
}
}
}
```
{% callout type="info" %}
Este es el webhook más crítico para la entrega de boletos. Cuando recibas un evento `ticket.updated`, tu plataforma debe iniciar inmediatamente el proceso de entrega del boleto al nuevo dueño.
{% /callout %}
{% callout type="warning" title="Reversiones de transacción" %}
Cuando `reversal` es `true`, la transacción se está revirtiendo — el boleto debe ser devuelto al dueño anterior. En este caso, `metadata.nominal` contiene la información del dueño anterior (si está disponible). Tu plataforma debe deshacer la transferencia original de forma acorde.
{% /callout %}
### Campos del Payload de ticket.updated
| Campo | Descripción | Origen del ID |
| :--- | :--- | :--- |
| `id` | El identificador del boleto. | Tu plataforma |
| `newOwnerEmail` | Email del comprador (nuevo dueño del boleto). | — |
| `oldOwnerEmail` | Email del vendedor (dueño anterior del boleto). | — |
| `reversal` | `true` si la transacción se está revirtiendo (ej., contracargo, reembolso). Cuando es `true`, `metadata.nominal` contiene los datos del dueño anterior si están disponibles. Por defecto es `false`. | — |
| `metadata.nominal` | Datos de identidad de la persona a quien está asignado nominalmente el boleto. | — |
| `metadata.payer` | Datos de identidad de la persona que pagó por el boleto. | — |
| `metadata.seller` | Datos de identidad del vendedor. | — |
| `metadata.order.resaleId` | Identificador único de la transacción de reventa. | menta tech |
| `metadata.order.grossResalePaidAmount` | Monto total pagado por el comprador (incluyendo todas las comisiones). | — |
| `metadata.order.grossResalePaidAmountWithoutBuyerFee` | Monto pagado excluyendo la comisión del comprador. | — |
| `metadata.order.sellerFee` | Comisión del vendedor como decimal (ej., `0.15` = 15%). | — |
| `metadata.order.sellerFeeAmount` | Monto absoluto de la comisión del vendedor descontado de la venta. | — |
| `metadata.order.buyerFee` | Comisión del comprador como decimal (ej., `0.15` = 15%). | — |
| `metadata.order.buyerFeeAmount` | Monto absoluto de la comisión del comprador sumado al precio de venta. | — |
{% /tab %}
{% tab label="Event" %}
## Eventos de Event
### event.unlock
Se dispara cuando se desbloquean los boletos de un evento. Esto ocurre típicamente cuando el organizador del evento habilita o modifica la actividad de reventa.
{% callout type="warning" %}
Después de un `event.unlock`, las publicaciones existentes pueden seguir activas en el marketplace, pero no se pueden crear nuevas publicaciones. Tu plataforma debe tener esto en cuenta al mostrar opciones de reventa a los usuarios.
{% /callout %}
```json
{
"family": "event",
"action": "event.unlock",
"data": {
"eventId": "8544",
"showId": "8544",
"excludedEmailTicketIds": []
}
}
```
### Campos del Payload de event.unlock
| Campo | Descripción | Origen del ID |
| :--- | :--- | :--- |
| `eventId` | El identificador del evento. | Tu plataforma |
| `showId` | El identificador del show. | Tu plataforma |
| `excludedEmailTicketIds` | Lista de IDs de boletos excluidos de la operación de desbloqueo. Cuando está vacía, todos los boletos están incluidos. | Tu plataforma |
{% /tab %}
{% tab label="Notify Me" %}
## Eventos de Notify Me
### notifyMe.created.updated
Se dispara cuando un usuario crea o actualiza una suscripción de "Avisarme". Estas suscripciones permiten a los usuarios expresar interés en boletos de un evento específico y ser notificados cuando haya boletos disponibles que coincidan con sus preferencias de precio.
```json
{
"family": "notifyMe",
"action": "notifyMe.created.updated",
"data": {
"id": "70cedf0685b7a892dc5c9418",
"showId": "7322",
"eventId": "7322",
"userEmail": "pedro.sanchez@example.com",
"status": "ACTIVE",
"ticketQuantity": 1,
"ticketOptionSelections": [
{
"ticketOptionId": "36790",
"priceLimit": 13799
},
{
"ticketOptionId": "36821",
"priceLimit": 17250
},
{
"ticketOptionId": "36822",
"priceLimit": 20700
},
{
"ticketOptionId": "37489",
"priceLimit": 110400
},
{
"ticketOptionId": "38029",
"priceLimit": 4140
}
],
"createdAt": "2026-03-20T22:49:41.338Z",
"updatedAt": "2026-03-20T23:45:57.869Z"
}
}
```
### Campos del Payload de notifyMe.created.updated
| Campo | Descripción | Origen del ID |
| :--- | :--- | :--- |
| `id` | Identificador único de la suscripción. | menta tech |
| `showId` | El identificador del show. | Tu plataforma |
| `eventId` | El identificador del evento. | Tu plataforma |
| `userEmail` | Email del usuario suscrito. | — |
| `status` | Estado actual de la suscripción (ej., `ACTIVE`). | — |
| `ticketQuantity` | Cantidad de boletos que busca el usuario. | — |
| `ticketOptionSelections` | Arreglo de categorías de boletos con preferencias de precio máximo. | — |
| `ticketOptionSelections[].ticketOptionId` | El identificador de la opción/categoría de boleto. | Tu plataforma |
| `ticketOptionSelections[].priceLimit` | Precio máximo que el usuario está dispuesto a pagar por esa categoría. | — |
| `createdAt` | Timestamp ISO 8601 de creación de la suscripción. | — |
| `updatedAt` | Timestamp ISO 8601 de la última actualización. | — |
{% /tab %}
{% tab label="Payouts" %}
## Eventos de Payouts
### payouts.delivered
Se dispara cuando los pagos de un evento o show específico han sido procesados y enviados a los vendedores.
```json
{
"family": "payouts",
"action": "payouts.delivered",
"data": {
"showId": "239616",
"eventId": "12746"
}
}
```
### Campos del Payload de payouts.delivered
| Campo | Descripción | Origen del ID |
| :--- | :--- | :--- |
| `showId` | El identificador del show para el cual se procesaron los pagos. | Tu plataforma |
| `eventId` | El identificador del evento para el cual se procesaron los pagos. | Tu plataforma |
{% /tab %}
{% /conditionaltabs %}
---
# menta tech API Documentation (v.1.0)
> Agent-friendly Markdown rendering of the menta tech REST API reference. Served as `text/markdown` — no JavaScript needed.
## How to use this reference (AI agents)
- **Base URL:** `https://api.mentatech.io` — every path below is relative to it.
- **Authentication:** all endpoints require your menta tech private API key in the `Authorization` header (provided by your account manager).
- **Complete OpenAPI 3.1 spec (JSON):** [https://docs.mentatech.io/api/openapi](https://docs.mentatech.io/api/openapi) — fetch it when you need full request/response schemas, field-level descriptions and examples. This document only lists top-level fields.
- **Endpoints** are grouped by resource below, in the recommended integration order. Each entry shows parameters, top-level request-body fields and response codes.
- **Integration guides** (concepts, flows, environments, webhooks): index at [https://docs.mentatech.io/llms.txt](https://docs.mentatech.io/llms.txt), full corpus at [https://docs.mentatech.io/llms-full.txt](https://docs.mentatech.io/llms-full.txt).
- **Interactive version for humans:** https://docs.mentatech.io/es/api (or /en/api).
## Overview
API for managing events, tickets, and marketplace operations. This documentation covers integrating with the menta platform for event creation, ticket management, secondary market operations, and user authentication.
Base URL: https://api.mentatech.io - Authentication requires a valid API Key in the Authorization header.
The menta platform uses a relational data model where endpoints build upon previously created data. For example, ticket creation requires an existing event with defined price types and zones.
We recommend following this documentation sequentially as it follows the logical integration flow.
While our API has minimal required fields, providing optional fields unlocks more powerful features - from enhanced marketplace capabilities to advanced ticket management. For example, detailed seat information enables precise seat selection, while comprehensive event metadata improves the user experience.
## Endpoint index
- **Events**
- `POST /v1/events` — Create an Event
- `PUT /v1/events` — Update an Event
- `POST /v1/events/:externalReferenceId/cancellation` — Cancel an Event
- `POST /v1/events/rules` — Define And Update Event Rules
- **Tickets**
- `POST /v1/tickets` — Create a Ticket
- `POST /v1/sync/tickets` — Create a Ticket (Sync)
- `PUT /v1/tickets/:ticketId` — Update a Ticket
- `DELETE /v1/tickets/:ticketId` — Delete a Ticket
- `POST /v1/tickets/:ticketId/eventAdmission` — Register Event Admission
- `POST /v1/tickets/batch/eventAdmission` — Register Batch Event Admissions
- `GET /v1/events/tickets/salePublicUrl` — Get Ticket Sale Public URL
- **Marketplace**
- `GET /v1/marketplace/buyingflow/url/entrypoint` — Get Secondary Market Buying Flow URL
- `GET /v1/marketplace/sellingflow/url/entrypoint` — Get Start Sell Ticket URL
- `GET /v1/marketplace/sellingflow/url/order/entrypoint` — Get Start Sell Order URL
- `GET /v1/marketplace/sellingflow/details/url` — Get Sell Ticket Details URL
- `POST /v1/marketplace/checkout/url` — Create Marketplace Checkout URL
- `DELETE /v1/marketplace/items/ticket/:ticketId` — Terminate Listing
- `GET /v1/marketplace/listings/ticket/:ticketId` — Get Listing by Ticket ID
- **Build Your Own Buyingflow**
- `GET /v1/marketplace/items/events/:eventId/listedTickets` — Get Listed Tickets for Event
- `POST /v1/marketplace/buyingflow/buyIntention` — Create Buy Intention
- **Auth**
- `GET /v1/auth/oneTimeToken` — Generate One-Time Token
- **Smart Access Layer**
- `GET /v1/wrapper/accesslayer` — Get Smart Access Layer
- `POST /v1/wrapper/accesslayer` — Generate Sell Access Layer for TicketIds
- `POST /v1/wrapper/accesslayer` — Generate Sell Access Layer for OrderIds
- `POST /v1/wrapper/accesslayer/bulk` — Get Smart Access Layer (Bulk)
- **Market Data**
- `PUT /v1/marketdata/events/:externalReferenceId/inventory` — Update Event Inventory
- `PUT /v1/marketdata/events/:externalReferenceId/inventory/details` — Update Event Inventory Details
- `POST /v1/marketdata/users` — Create Ticket Holder Lead
- `POST /v1/marketdata/users` — Create Abandoned Cart Lead
- `POST /v1/marketdata/users` — Create Virtual Queue Lead
- `POST /v1/marketdata/users` — Create Wishlist Lead
- `POST /v1/marketdata/users/bulk` — Create Ticket Leads (Bulk)
## Events
Operations related to creating, updating, and managing events and their associated shows. This is the first step of the integration.
### POST /v1/events — Create an Event
Creates a new event in the system with all associated metadata. Events can include multiple shows, ticket options, and configuration settings. This endpoint provides a standardized way to integrate your ticketing system with menta and serves as the foundation for all ticket operations.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `title` (string, required)
- `description` (string, required)
- `externalReferenceId` (string, required)
- `shows` (object, required)
- `location` (object, required)
- `producers` (array of object)
- `configuration` (object, required)
- `seating` (object)
**Responses:** `200` — Event successfully created with all provided details
### PUT /v1/events — Update an Event
Updates an existing event with new information. This endpoint requires sending the complete updated event object rather than partial updates. All fields will be replaced with the new values provided. Always include the externalReferenceId to identify which event to update. We strongly recommend to send the entire event object rather than partial properties updates.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `title` (string)
- `description` (string)
- `externalReferenceId` (string, required)
- `shows` (object)
- `location` (object)
- `producers` (array of object)
- `configuration` (object)
- `seating` (object)
**Responses:** `200` — Event successfully updated with the provided information
### POST /v1/events/:externalReferenceId/cancellation — Cancel an Event
Cancels an entire event and all associated shows. This action affects all tickets linked to this event and should be used with caution. Once an event is cancelled, all tickets become invalid. Payouts for tickets sold will be cancelled and refunds will be processed for those tickets sold in the secondary market.
**Parameters:**
- `externalReferenceEventId` (path, required)
- `showId` (query)
- `showId` (query) — The ID of the show in your system.
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Event successfully cancelled with all associated shows
### POST /v1/events/rules — Define And Update Event Rules
Creates or updates rules for events, specifying behavior for ticket transfers, resales, and other operations. These rules can control various aspects of ticket lifecycle management.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, array of object) — top-level fields:
- `externalReferenceEventId` (string, required)
- `showId` (string)
- `ticketOptionId` (string)
- `priceTypeId` (string)
- `price` (anyOf)
- `ruleType` (string, required)
- `rules` (object)
**Responses:** `200` — Rules successfully defined and applied to the events
## Tickets
Operations for ticket creation, management, validation, and admission control.
### POST /v1/tickets — Create a Ticket
Creates new tickets in the menta system. This operation registers your ticket information in the platform for management and distribution. Each ticket receives a unique identifier that links back to your original ticketId. The request body requires an array of ticket objects with all necessary details. This endpoint is asynchronous and will return a response immediately, while the /v1/sync/tickets endpoint is synchronous. Using this endpoint will put your request in the queue to be processed asynchronously. For high volume of tickets, its recommended to use this endpoint as data will be processed as capacity allows.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, array of object) — top-level fields:
- `externalReferenceEventId` (string, required)
- `showId` (string | null)
- `buyer` (anyOf, required)
- `ticketId` (string, required)
- `ticketAccess` (object, required)
- `ticketOptionId` (string, required)
- `priceTypeId` (string)
- `price` (anyOf)
- `buyerEmailExternal` (string)
- `primarySaleBuyerData` (object)
- `nominalTicket` (object)
- `props` (object)
- `primarySalesFee` (object)
**Responses:** `200` — Tickets successfully created with unique identifiers
### POST /v1/sync/tickets — Create a Ticket (Sync)
Creates tickets synchronously, returning an immediate response unlike the asynchronous /v1/tickets endpoint. Not suitable for high volume requests. Errors must be handled by your end. Restricted Capacity of 60 requests per minute.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, array of object) — top-level fields:
- `externalReferenceEventId` (string, required)
- `showId` (string | null)
- `buyer` (anyOf, required)
- `ticketId` (string, required)
- `ticketAccess` (object, required)
- `ticketOptionId` (string, required)
- `priceTypeId` (string)
- `price` (anyOf)
- `buyerEmailExternal` (string)
- `primarySaleBuyerData` (object)
- `nominalTicket` (object)
- `props` (object)
- `primarySalesFee` (object)
**Responses:** `200` — Tickets successfully synchronized with the system
### PUT /v1/tickets/:ticketId — Update a Ticket
Updates an existing ticket's properties. This can be used to modify ticket access information, update buyer details, or change other ticket properties after initial creation. The ticket is identified by its ID provided in the path parameter.
**Parameters:**
- `ticketId` (path, required)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `externalReferenceEventId` (string)
- `showId` (string | null)
- `buyer` (anyOf)
- `ticketAccess` (object)
- `ticketOptionId` (string)
- `priceTypeId` (string)
- `price` (anyOf)
- `buyerEmailExternal` (string)
- `primarySaleBuyerData` (object)
- `nominalTicket` (object)
- `props` (object)
- `primarySalesFee` (object)
**Responses:** `200` — Ticket successfully updated with new information
### DELETE /v1/tickets/:ticketId — Delete a Ticket
Removes a ticket from the system, invalidating it for all purposes. This operation is typically used for tickets that were issued in error or need to be cancelled for specific reasons. If any listing is active, it will be terminated. Use with caution as this operation cannot be undone.
**Parameters:**
- `ticketId` (path, required)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Ticket successfully deleted from the system
### POST /v1/tickets/:ticketId/eventAdmission — Register Event Admission
Records a ticket admission at an event, marking the ticket as used. This is typically called by access control systems at venue entrances. The ticketId is provided in the URL path parameter.
**Parameters:**
- `ticketId` (path, required)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Admission successfully registered for the ticket
### POST /v1/tickets/batch/eventAdmission — Register Batch Event Admissions
Records multiple ticket admissions at an event in a single request. This is more efficient than making individual calls for each ticket when processing groups of attendees. The response indicates whether all admissions were successfully recorded.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, array of object) — top-level fields:
- `ticketId` (string, required)
- `entryDate` (string, required)
**Responses:** `200` — Batch admission successfully executed for all provided tickets
### GET /v1/events/tickets/salePublicUrl — Get Ticket Sale Public URL
Retrieves a public URL that directs users directly to the secondary marketplace for the event, filtered to show only the specific ticket. This URL is commonly used for direct ticket sales, especially to enable ticket sellers to share the URL through social media platforms to amplify the distribution and visibility of their ticket listing. When a potential buyer clicks the link, they are taken directly to the marketplace page showing only that specific ticket, making it easy to complete the purchase.
**Parameters:**
- `ticketId` (query, required)
- `lang` (query, required)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully generated public sales URL
## Marketplace
Operations for the secondary market, including listing tickets for sale and purchasing tickets.
### GET /v1/marketplace/buyingflow/url/entrypoint — Get Secondary Market Buying Flow URL
Retrieves the entry URL to access the secondary marketplace for purchasing tickets for the event and show specified in the query parameters. This URL directs users to the marketplace interface where they can browse and purchase available tickets from the secondary market. The marketplace provides a secure environment for secondary ticket sales with buyer and seller protections. You can optionally filter the listings by a specific ticket option ID to show only offers for that ticket type.
**Parameters:**
- `externalReferenceEventId` (query, required) — The ID of the event in your platform. This identifies which event the user will browse in the secondary marketplace.
- `showId` (query, required) — The ID of the show in your platform. This identifies the specific show within the event that the user will browse.
- `lang` (query) — Language code for the navigation interface (e.g., "es", "en"). If not specified, it defaults to the primary language of the country of operation.
- `returnTo` (query, required) — The URL to redirect users to when they press the back button or complete the purchase flow. This allows you to return users to your platform after they interact with the marketplace.
- `ticketOptionId` (query) — Optional filter to show only secondary market purchase offers for the specified ticket type ID. When provided, the marketplace will display listings filtered to this specific ticket option.
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully generated buying flow entry URL
### GET /v1/marketplace/sellingflow/url/entrypoint — Get Start Sell Ticket URL
Retrieves the URL to begin the process of selling tickets in the marketplace. This URL directs users to an interface where they can set pricing, listing conditions, and other parameters for their ticket listings. The process includes verification steps to ensure ticket validity.
**Parameters:**
- `ticketId` (query, required)
- `lang` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully generated URL for the selling flow
### GET /v1/marketplace/sellingflow/url/order/entrypoint — Get Start Sell Order URL
Retrieves the URL to start the sales order process for multiple tickets in a single transaction. This is particularly useful for selling groups of tickets or complete orders from the primary market. The generated URL leads to a specialized interface for creating these bulk listings.
**Parameters:**
- `orderId` (query, required)
- `lang` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully generated URL for starting the sales order process
### GET /v1/marketplace/sellingflow/details/url — Get Sell Ticket Details URL
Retrieves the URL for viewing and managing details of a ticket listing. This allows ticket owners to check the status of their listings, modify pricing, or remove listings from the marketplace. The URL can include authentication parameters for direct access.
**Parameters:**
- `ticketId` (query, required)
- `sellerEmail` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully generated URL for selling details
### POST /v1/marketplace/checkout/url — Create Marketplace Checkout URL
Creates and retrieves a checkout URL for marketplace purchases. This URL directs users to complete their purchase of selected tickets from the secondary market. The checkout process handles payment processing, buyer verification, and ticket transfer in a secure environment. The request requires a list of ticket listing IDs to purchase that you can get from the Get Listed Tickets for Event endpoint.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `listingIds` (array of string, required)
**Responses:** `200` — Successfully generated checkout URL for the marketplace purchase
### DELETE /v1/marketplace/items/ticket/:ticketId — Terminate Listing
Removes a ticket from the marketplace listings, making it unavailable for purchase. This is typically used when a seller wants to cancel their listing without completing a sale. The ticket reverts to its unlisted state and can be used by the owner or listed again later.
**Parameters:**
- `ticketId` (path, required)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Ticket successfully removed from marketplace listings
### GET /v1/marketplace/listings/ticket/:ticketId — Get Listing by Ticket ID
Retrieves a listing by its external ticket ID. This allows you to access information about a specific ticket listing in the marketplace. You can also filter by seller email if you want to get the listing for a specific seller.
**Parameters:**
- `ticketId` (path, required)
- `sellerEmail` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully retrieved listing by ticket ID
## Build Your Own Buyingflow
Streamlined checkout experience for marketplace purchases
### GET /v1/marketplace/items/events/:eventId/listedTickets — Get Listed Tickets for Event
Retrieves all tickets currently listed for sale for a specific event. This allows integration with your platform to display available secondary market tickets. The response includes pricing, seat information, and other details necessary for presenting the listings to potential buyers.
**Parameters:**
- `eventId` (path, required)
- `showId` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully retrieved all listed tickets for the event
### POST /v1/marketplace/buyingflow/buyIntention — Create Buy Intention
A Buy Intention is a representation of a user's intention to purchase specific tickets. This creates a temporary reservation to prevent conflicts during the checkout process. Buy intentions have a limited lifetime and will expire if the purchase is not completed within a certain timeframe. You can use this endpoint to create a buy intention for specific tickets and retrieve the payment URL to complete the purchase.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `items` (array of string, required)
- `user` (string, required)
**Responses:** `200` — Purchase intention successfully registered
## Auth
Authentication operations for secure user access and verification.
### GET /v1/auth/oneTimeToken — Generate One-Time Token
Creates a one-time authentication token for a specific user. This token can be appended to any menta URL to provide temporary authenticated access. It's useful for redirecting users from your platform to specific menta functions while maintaining their authenticated state. The token is designed for single use and will expire after being used or after a predetermined time period.
**Parameters:**
- `user` (query, required)
- `method` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — One-time token successfully generated
## Smart Access Layer
Operations for retrieving smart access layer components that provide dynamic UI elements (buttons, banners, modals, lists, maps) for buy/sell functionality.
### GET /v1/wrapper/accesslayer — Get Smart Access Layer
Retrieves smart access layer components for a specific event and show. These components provide dynamic UI elements (buttons, banners, modals, lists, maps) that can be rendered in your application to enable buy/sell access points. The components are configured based on event rules and marketplace conditions. When type="buy", both eventId and showId are required.
**Parameters:**
- `type` (query, required)
- `eventId` (query)
- `showId` (query)
- `lang` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Responses:** `200` — Successfully retrieved smart access layer components
### POST /v1/wrapper/accesslayer — Generate Sell Access Layer for TicketIds
Evaluates the sellability of a user's tickets and returns the corresponding status and call-to-actions to render in your application (e.g. SELL, EDIT, DETAILS, P2P, PENDING_PAYOUT_INFO). The request body must contain a `tickets` array with at least one ticket. For each ticket, the response includes the sellability status (SELLABLE, NOT_SELLABLE, FOR_SALE, SOLD) and the URLs to redirect the user to complete the relevant flow.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `user` (string, required)
- `tickets` (array of object, required)
**Responses:** `200` — Successfully evaluated the sell access layer and returned per-ticket results with CTAs
### POST /v1/wrapper/accesslayer — Generate Sell Access Layer for OrderIds
Evaluates the sellability of a user's orders and returns an aggregated status and call-to-actions per order (e.g. SELL, EDIT, DETAILS, MANAGE, PENDING_PAYOUT_INFO). The request body must contain an `orders` array with at least one order. Both endpoints use the same URL (`POST /v1/wrapper/accesslayer`) — the mode is determined by whether the body contains `tickets` or `orders`.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `user` (string, required)
- `orders` (array of object, required)
**Responses:** `200` — Successfully evaluated the sell access layer and returned per-order results with CTAs
_Spec key in /api/openapi: `paths["/v1/wrapper/accesslayer (orders)"]`_
### POST /v1/wrapper/accesslayer/bulk — Get Smart Access Layer (Bulk)
Retrieves smart access layer components for multiple events and shows in a single request. This endpoint is optimized for batch operations when you need to fetch components for multiple shows at once, reducing the number of API calls required. Each item in the request body must include an eventId and at least one showId. This endpoint only returns components of type button, modal, and banner.
**Parameters:**
- `type` (query, required)
- `lang` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, array of object) — top-level fields:
- `eventId` (string, required)
- `showIds` (array of string, required)
**Responses:** `200` — Successfully retrieved smart access layer components for all requested event and show combinations
## Market Data
Operations for managing event market data including inventory levels and ticket leads for identifying potential buyers and sellers in the secondary market.
### PUT /v1/marketdata/events/:externalReferenceId/inventory — Update Event Inventory
Updates inventory data for a complete event show. Use this endpoint to update capacity, released tickets, reserved space, sold out status, and sales percentage for an entire show. This provides market-level visibility into physical and real-time inventory capacity. If the event has multiple shows, you must specify showId as a query parameter; otherwise it is optional.
**Parameters:**
- `externalReferenceId` (path, required)
- `showId` (query)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `capacity` (number)
- `releasedTickets` (number)
- `reservedSpace` (number)
- `soldOut` (boolean)
- `soldPercentage` (number)
**Responses:** `200` — Successfully updated event inventory
### PUT /v1/marketdata/events/:externalReferenceId/inventory/details — Update Event Inventory Details
Updates inventory details for a complete event show. Use this endpoint to update capacity, released tickets, reserved space, sold out status, and sales percentage for an entire show. This provides market-level visibility into physical and real-time inventory capacity.
**Parameters:**
- `externalReferenceId` (path, required)
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `items` (array of object, required)
**Responses:** `200` — Successfully updated event inventory details
### POST /v1/marketdata/users — Create Ticket Holder Lead
Creates a Ticket Holder lead for a specific event show. A Ticket Holder is a user who has completed a purchase in primary sales and owns a valid ticket. These leads help menta identify potential resellers in the secondary market. The buyer object must include at least one identifier (email, phone, or id). Fields ticketId and price are required for this lead type. The system uses upsert logic: if a lead with the same buyer identifier, externalReferenceEventId, and showId already exists, it will be updated instead of duplicated.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `type` (string, required)
- `externalReferenceEventId` (string, required)
- `showId` (string, required)
- `ticketId` (string, required)
- `buyer` (object, required)
- `price` (number, required)
- `currency` (string)
- `ticketOptionId` (string)
- `priceTypeId` (string)
- `date` (string)
- `seating` (object)
- `metadata` (object)
- `tags` (array of string)
- `attributes` (array of string)
**Responses:** `200` — Ticket Holder lead successfully created or updated
_Spec key in /api/openapi: `paths["/v1/marketdata/users (Ticket Holder)"]`_
### POST /v1/marketdata/users — Create Abandoned Cart Lead
Creates an Abandoned Cart lead for a specific event show. An Abandoned Cart lead represents a user who initiated the purchase process in primary sales but did not complete the transaction. These users are potential buyers in the secondary market when price or availability changes. The buyer object must include at least one identifier (email, phone, or id). The system uses upsert logic: if a lead with the same buyer identifier, externalReferenceEventId, and showId already exists, it will be updated instead of duplicated.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `type` (string, required)
- `externalReferenceEventId` (string, required)
- `showId` (string, required)
- `ticketId` (string)
- `buyer` (object, required)
- `ticketOptionId` (string)
- `priceTypeId` (string)
- `date` (string)
- `price` (number)
- `currency` (string)
- `seating` (object)
- `metadata` (object)
- `tags` (array of string)
**Responses:** `200` — Abandoned Cart lead successfully created or updated
_Spec key in /api/openapi: `paths["/v1/marketdata/users (Abandoned Cart)"]`_
### POST /v1/marketdata/users — Create Virtual Queue Lead
Creates a Virtual Queue lead for a specific event show. A Virtual Queue lead represents a user who was in the virtual queue to purchase tickets but abandoned the process without completing a purchase. These users demonstrated real-time interest in the event and are potential buyers in the secondary market. The buyer object must include at least one identifier (email, phone, or id). The system uses upsert logic: if a lead with the same buyer identifier, externalReferenceEventId, and showId already exists, it will be updated instead of duplicated.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `type` (string, required)
- `externalReferenceEventId` (string, required)
- `showId` (string, required)
- `buyer` (object, required)
- `ticketOptionId` (string)
- `priceTypeId` (string)
- `date` (string)
- `price` (number)
- `currency` (string)
- `metadata` (object)
- `tags` (array of string)
**Responses:** `200` — Virtual Queue lead successfully created or updated
_Spec key in /api/openapi: `paths["/v1/marketdata/users (Virtual Queue)"]`_
### POST /v1/marketdata/users — Create Wishlist Lead
Creates a Wishlist lead for a specific event show. A Wishlist lead represents a user who explicitly subscribed to receive availability notifications for tickets. This is the highest quality lead type due to the direct opt-in, showing high probability of conversion. The buyer object must include at least one identifier (email, phone, or id). The system uses upsert logic: if a lead with the same buyer identifier, externalReferenceEventId, and showId already exists, it will be updated instead of duplicated.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, object) — top-level fields:
- `type` (string, required)
- `externalReferenceEventId` (string, required)
- `showId` (string, required)
- `ticketId` (string)
- `buyer` (object, required)
- `ticketOptionId` (string)
- `priceTypeId` (string)
- `date` (string)
- `price` (number)
- `currency` (string)
- `metadata` (object)
**Responses:** `200` — Wishlist lead successfully created or updated
_Spec key in /api/openapi: `paths["/v1/marketdata/users (Wishlist)"]`_
### POST /v1/marketdata/users/bulk — Create Ticket Leads (Bulk)
Creates multiple ticket leads in a single request. You can mix different lead types (TICKET_HOLDER, ABANDONED_CART, VIRTUAL_QUEUE, WISHLIST) in the same request. Maximum of 1000 leads per request. Each lead is validated individually. The system uses upsert logic based on the buyer identifier (email, phone, or id) combined with externalReferenceEventId and showId, so sending the same lead multiple times will not create duplicates.
**Parameters:**
- `Authorization` (header, required) — Your menta tech private API Key provided by your account manager.
**Request body** (`application/json`, array of object) — top-level fields:
- `type` (string, required)
- `externalReferenceEventId` (string, required)
- `showId` (string, required)
- `ticketId` (string)
- `buyer` (object, required)
- `price` (number)
- `currency` (string)
- `ticketOptionId` (string)
- `priceTypeId` (string)
- `purchaseDate` (string)
- `seating` (object)
- `metadata` (object)
- `tags` (array of string)
**Responses:** `200` — Ticket leads successfully created or updated
---
_Generated from the OpenAPI spec. Canonical machine-readable source: https://docs.mentatech.io/api/openapi_