# Ticket synchronization for resale

## Overview

Ticket synchronization lets menta tech determine which tickets a user owns and which of those tickets are eligible for resale. **This sync happens only when a user wants to sell**; it is not a continuous process and does not require keeping a full ownership history.

Your platform exposes a ticket verification endpoint. menta tech queries this endpoint when it needs to know the user’s tickets.

This information is needed to:

- Show the correct inventory in “Sell my ticket” flows
- Apply resale rules at the ticket level
- Validate ownership before allowing a listing or completing a resale purchase

The primary ticketing platform always remains the source of truth for ticket status.

{% callout type="info" title="Relationship with Access to Sell" %}
Ticket synchronization is tightly linked to Access to Sell. When a user wants to sell, menta tech or your platform triggers synchronization based on the chosen model. For details on how users enter the resale flow, see [Access to Sell](/guides/accessToSell_es).
{% /callout %}

## Ticket Object (simplified preview)

Minimal conceptual example of the ticket object used during resale flows. For the full schema, see the Ticket Data API reference.

This is only a conceptual preview. The full schema and validations are available in the API reference.

```json
{
  "ticketId": "444",
  "externalReferenceEventId": "123",
  "showId": "456",
  "ticketOptionId": "789",
  "priceTypeId": "101",
  "price": 100,
  "currency": "USD",
  "buyer": "user@example.com",
  "tags": ["category:vip", "source:online"]
}
```

At minimum, menta tech requires:

- Identifiers for the associated event and show
- Access category identifier
- Price and currency
- Ownership data for validation

Optionally, it can also receive:

- Location and seating
- Additional properties (props)
- Access URLs or PDFs
- Operational metadata
- Tags (`tags`): Array of strings in `key:value` format for custom tagging

## Why Ticket Data Matters

Reliable ticket data allows menta tech to:

### 1. Determine eligible inventory
Identify which tickets a user can list at any given moment.

### 2. Enable the right selling experience
The listing UI needs accurate event, show, category, and optional seat details.

### 3. Validate ownership before resale
Before listing or selling, menta tech checks current status with your platform.

### 4. Protect users and inventory
Prevent invalid listings, incorrect resales, and operational errors.

## How it works

Synchronization is designed to integrate with the Smart Access Layer. menta tech automatically orchestrates synchronization when the user accesses sell URLs or earlier to speed up loading. Your platform only needs to expose the endpoint and render the components provided by SAL.

## PULL - Verification Endpoint (Recommended)

### Model description

With the **PULL** model, your platform exposes a ticket verification endpoint that returns all tickets the user currently owns. menta tech calls this endpoint at key points in the resale flow:

- When the user enters the resale flow
- Before creating a listing
- Before confirming a sale
- Before completing a resale purchase

This ensures menta tech verifies ownership in real time and prevents canceled, refunded, or transferred tickets from being listed or sold.

### Flow with Smart Access Layer

When you use SAL with the Verification Endpoint:

1. Your UI calls SAL with the user’s `ticketIds`.
2. SAL responds with statuses and available actions.
3. When the user accesses a sell URL, menta tech automatically calls your verification endpoint.
4. The sync is orchestrated by menta tech, with no extra steps on your side.

{% diagram type="sequence" height="550px" %}
{
  "nodes": [
    {
      "id": "actor-1",
      "type": "sequence-actor",
      "position": {
        "x": 21.333333333333336,
        "y": 30
      },
      "data": {
        "label": "Seller",
        "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": "Your platform",
        "accentColor": "#f97316",
        "lifelineHeight": 475
      }
    },
    {
      "id": "msg-1",
      "type": "sequence-message",
      "position": {
        "x": -29.125985590712688,
        "y": 73.51690818717502
      },
      "data": {
        "label": "User opens their tickets section"
      }
    },
    {
      "id": "msg-2",
      "type": "sequence-message",
      "position": {
        "x": 214.6853374070431,
        "y": 164.12148590852757
      },
      "data": {
        "label": "You request the structure to render\nsell buttons"
      }
    },
    {
      "id": "msg-3",
      "type": "sequence-message",
      "position": {
        "x": 542.5026086166031,
        "y": 233.45543217464973
      },
      "data": {
        "label": "Returns button structure",
        "isReturn": true
      }
    },
    {
      "id": "msg-4",
      "type": "sequence-message",
      "position": {
        "x": 227.06697791581803,
        "y": 274.18210726412326
      },
      "data": {
        "label": "You render buttons on the seller’s frontend",
        "isReturn": true
      }
    },
    {
      "id": "msg-1765986991767",
      "type": "sequence-message",
      "position": {
        "x": -40.16298568880333,
        "y": 392.42375081594577
      },
      "data": {
        "label": "User clicks the sell button"
      }
    },
    {
      "id": "msg-1765987013125",
      "type": "sequence-message",
      "position": {
        "x": 459.96682051132154,
        "y": 461.3755170736649
      },
      "data": {
        "label": "Requests the tickets the user owns (pull)"
      }
    },
    {
      "id": "msg-1765987128632",
      "type": "sequence-message",
      "position": {
        "x": -40.16298568880333,
        "y": 567.7917548245065
      },
      "data": {
        "label": "Listing flow completes"
      }
    },
    {
      "id": "msg-1766169147521",
      "type": "sequence-message",
      "position": {
        "x": 189.87360371053717,
        "y": 503.00268826845223
      },
      "data": {
        "label": "You return all tickets in the order to 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": "Ticket synchronization",
        "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 %}

### When to use this model

This model is recommended when:

- You already have a “My Tickets” or purchase history endpoint
- Ticket status can change frequently
- Consistency and accuracy are priorities
- You prefer to keep all status logic in your system
- You want menta tech to orchestrate synchronization automatically

### Key characteristics

- menta tech does not store historical ticket inventories
- Status is always queried directly from your platform
- Minimal operational load for your system
- Lower risk of inconsistencies or stale data
- Synchronization is orchestrated automatically by menta tech when the user wants to sell

### Example: Verification Endpoint flow

#### Request (called by menta tech)

menta tech calls your platform’s endpoint with user context whenever ownership must be verified.

Request example:

```
GET /tickets?user={userEmail}
```

#### Security

Authentication and authorization are handled by your platform under your existing standards. Typically two security layers are applied: restricting queries to menta tech IPs (allowlist) and/or an HTTP request header with a secret key.

#### Response example (simplified)

The endpoint returns the list of tickets the user currently owns, following this structure:

```json
{
  "userEmail": "user@gmail.com",
  "tickets": [
    {
      "ticketId": "ticket_001",
      "externalReferenceEventId": "evt_123",
      "showId": "show_456",
      "ticketOptionId": "GA",
      "price": 100,
      "currency": "USD",
      "status": "VALID",
      "tags": ["source:online", "promo:early-bird"]
    },
    {
      "ticketId": "ticket_002",
      "externalReferenceEventId": "evt_123",
      "showId": "show_456",
      "ticketOptionId": "VIP",
      "price": 180,
      "currency": "USD",
      "status": "VALID",
      "tags": ["source:box-office", "category:vip"]
    }
  ]
}
```

Only tickets that are currently valid and owned by the user should be returned. Tickets that were canceled, refunded, transferred, or invalidated should be omitted or clearly marked as not eligible.

### How menta tech uses this response

menta tech uses this response to:

- Determine which tickets the user can list for resale
- Validate ownership immediately before listing or selling
- Prevent resale of tickets that are no longer valid
- Ensure the resale flow always reflects your system’s current state

At no point does menta tech assume ownership based on cached data. Every critical action is validated against this endpoint.

### Important notes

- The response structure should ideally match the predefined schema between parties.
- Field names may differ as long as identifiers can be consistently mapped. Ideally, keep the predefined property names for faster connectivity.
- The endpoint must be reliable and available during resale flows.

This model keeps full authority over tickets within your platform while letting menta tech orchestrate resale safely without introducing data inconsistencies.


