# Displaying content

## Glossary

| Term | Meaning |
|  --- | --- |
| **media** | The `logo` and `gallery` fields collectively. |
| **content fields** | All displayable fields: `name`, `description`, `shortDescription`, `termsOfUse`, `logo`, `gallery`, `venue`. |


## Introduction

The API exposes content at two levels:

- **TicketingCatalog** —  carries the default branding and editorial content.
- **TicketingProductBase** — carries its own content when it differs from the catalog defaults.


Both resources expose the same set of content fields:

| Field | Type | Notes |
|  --- | --- | --- |
| `name` | string | Display name. Always set. |
| `description` | string (HTML) | Long description. Localized. Always set on product base. May be null on catalog. |
| `shortDescription` | string (HTML) or null | Short description. Localized. May be null. |
| `termsOfUse` | string (HTML) or null | Terms of use. Localized. May be null. |
| `logo` | `{ publicUrl }` or null | Logo image URL. |
| `gallery` | `{ publicUrl }[]` | Ordered list of gallery image URLs. Empty array when none. |
| `venue` | object or null | Venue name, address, coordinates, contact. |


The `description`, `shortDescription`, and `termsOfUse` fields contain **HTML strings** and must be rendered as such (e.g. with `innerHTML` or an HTML renderer). Strip tags or escape them only if you intend to display plain text.

For media and venue fields, the resolution rule is:

- If the product base provides a value, use it.
- If the product base field is absent (`logo: null`, `gallery: []`, `venue: null`), fall back to the catalog value.


This fallback is **not applied by the API** — it is the client's responsibility to resolve the correct value to display.

## Step 1: Fetch catalog data

Use the [GET /v1/ticketing/catalogs/{id}](/openapi/ticketingcatalog/api_v1ticketingcatalogs_id_get) endpoint to retrieve a catalog with its media fields.

### Request

```bash
curl --request GET \
  --url https://api.korusticket.com/v1/ticketing/catalogs/0196f2ef-c0de-7456-ac8e-8e2479c54aa5 \
  -H 'accept: application/ld+json' \
  -H 'Authorization: Bearer {{YOUR_JWT_TOKEN}}' \
  -H 'Accept-Language: fr'
```

### Response

```json
{
  "@context": "/contexts/TicketingCatalog",
  "@id": "/v1/ticketing/catalogs/0196f2ef-c0de-7456-ac8e-8e2479c54aa5",
  "@type": "TicketingCatalog",
  "id": "0196f2ef-c0de-7456-ac8e-8e2479c54aa5",
  "name": "Olympique Lyonnais",
  "description": "<p>Bienvenue au club de football <strong>Olympique Lyonnais</strong>.</p>",
  "shortDescription": "<b>Le club phare de la région Auvergne-Rhône-Alpes.</b>",
  "termsOfUse": "<p>En achetant un billet, vous acceptez les conditions générales de vente.</p>",
  "logo": {
    "publicUrl": "https://cdn.korusticket.com/catalogs/ol-logo.png"
  },
  "gallery": [
    { "publicUrl": "https://cdn.korusticket.com/catalogs/ol-stadium-1.jpg" },
    { "publicUrl": "https://cdn.korusticket.com/catalogs/ol-stadium-2.jpg" }
  ],
  "venue": {
    "name": "Groupama Stadium",
    "line1": "10 avenue Simone-Veil",
    "postalCode": "69150",
    "city": "Décines-Charpieu",
    "country": "FR",
    "latitude": "45.7654",
    "longitude": "5.0932"
  }
}
```

Store this catalog object in your cache. It provides the default media and venue for all product bases belonging to this catalog.

## Step 2: Fetch product base data

Use the [GET /v1/ticketing/product_bases/{id}](/openapi/ticketingproductbase/api_v1ticketingproduct_bases_id_get) endpoint to retrieve a product base.

### Case A — product base uses catalog defaults

When `logo` is `null` and `gallery` is empty, the product base does not carry its own media. Display the catalog's values instead.

#### Request

```bash
curl --request GET \
  --url https://api.korusticket.com/v1/ticketing/product_bases/0199570c-3380-7e12-9dcd-7cbe238e71f0 \
  -H 'accept: application/ld+json' \
  -H 'Authorization: Bearer {{YOUR_JWT_TOKEN}}' \
  -H 'Accept-Language: fr'
```

#### Response

```json
{
  "@context": "/contexts/TicketingProductBase",
  "@id": "/v1/ticketing/product_bases/0199570c-3380-7e12-9dcd-7cbe238e71f0",
  "@type": "TicketingProductBase",
  "id": "0199570c-3380-7e12-9dcd-7cbe238e71f0",
  "name": "Ligue 1 - OL / FC Lorient - 31 déc. 2025",
  "description": "<p>Rejoignez-nous pour ce match de Ligue 1.</p>",
  "shortDescription": null,
  "termsOfUse": null,
  "logo": null,
  "gallery": [],
  "venue": null
}
```

In this case: use the club logo, the club's gallery images, and the club's home stadium as venue. The product base `shortDescription` and `termsOfUse` being null means the catalog values apply if you wish to display them.

### Case B — product base overrides catalog defaults

When the match takes place in a different stadium or has its own dedicated visuals, the product base returns non-null values.

#### Response

```json
{
  "@context": "/contexts/TicketingProductBase",
  "@id": "/v1/ticketing/product_bases/0199570c-3380-7e12-9dcd-7cbe238e71f0",
  "@type": "TicketingProductBase",
  "id": "0199570c-3380-7e12-9dcd-7cbe238e71f0",
  "name": "Coupe de France - OL / PSG - Finale",
  "description": "<p>La grande finale de la Coupe de France au Stade de France.</p>",
  "shortDescription": "<b>Un match exceptionnel hors de son stade habituel.</b>",
  "termsOfUse": "<p>Conditions spécifiques à cet événement.</p>",
  "logo": {
    "publicUrl": "https://cdn.korusticket.com/events/finale-coupe-de-france.png"
  },
  "gallery": [
    { "publicUrl": "https://cdn.korusticket.com/events/stade-de-france-1.jpg" }
  ],
  "venue": {
    "name": "Stade de France",
    "line1": "ZAC du Cornillon Nord",
    "postalCode": "93216",
    "city": "Saint-Denis",
    "country": "FR",
    "latitude": "48.9244",
    "longitude": "2.3601"
  }
}
```

In this case: display the event-specific logo, gallery, venue, and all text fields from the product base — ignoring the catalog values.

## Step 3: Resolution logic

Apply the following rules when rendering a product base page:

```
name             = productBase.name
description      = productBase.description
shortDescription = productBase.shortDescription ?? catalog.shortDescription
termsOfUse       = productBase.termsOfUse       ?? catalog.termsOfUse
logo             = productBase.logo             ?? catalog.logo
gallery          = productBase.gallery.length > 0 ? productBase.gallery : catalog.gallery
venue            = productBase.venue            ?? catalog.venue
```

`name` and `description` are always specific to the product base and never fall back to the catalog.

`shortDescription`, `termsOfUse`, `logo`, `gallery`, and `venue` follow the same override pattern: the product base value takes precedence; the catalog value is the fallback when absent.