# 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
