> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gomry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Catalog

> Return your events, one page at a time

# Catalog

Returns your events: what **could** be sold, as opposed to what is for sale right now. Retail polls this every 15 minutes and stores the results. It is the only endpoint whose data Retail keeps.

<Note>
  A catalog entry is a durable description of a real event, safe to store and show. A [listing](/vendor-api/listings) is a quote with a short life. Keep the two apart: nothing here should say how many tickets are purchasable.
</Note>

## Query Parameters

<ParamField query="vendorKey" type="string" required>
  Your supplier identifier.
</ParamField>

<ParamField query="page" type="integer" default="1">
  1-based page number.
</ParamField>

<ParamField query="updatedSince" type="string">
  ISO 8601 instant. Return only events changed since then. When absent, Retail is doing a full sweep. If your system has no modified-since filter you may ignore this parameter and return everything.
</ParamField>

<ParamField query="vendorEventId" type="string">
  Look up a single event, used when Retail re-reads one that looks stale. Optional to support: if you ignore it and return an ordinary page, Retail keeps only the matching row.
</ParamField>

## Paging

Paging is required. A real catalog runs to tens of thousands of events, and answering in one response will time out. Size your pages so each answers within **30 seconds**.

<Warning>
  **`nextPage: null` is the only end-of-catalog signal.** An empty `events` array on a page in the middle is treated as a hiccup, not the end. Retail uses absence from the catalog to flag events for review, so ending early by mistake looks like you dropped every event after that page.
</Warning>

## Response

<ResponseField name="events" type="array" required>
  <Expandable title="Event object">
    <ResponseField name="vendorEventId" type="string" required>
      Your id for the event, as a string.
    </ResponseField>

    <ResponseField name="name" type="string" required>
      Event name as a buyer should read it.
    </ResponseField>

    <ResponseField name="occursAt" type="string | null">
      The start instant in UTC, ISO 8601.

      **Do not create this by appending `Z` to a local time.** Some systems do, which shifts events by hours. If you cannot convert honestly, send `null` and fill `occursAtLocal` instead. Retail prefers rebuilding the instant from local time.
    </ResponseField>

    <ResponseField name="occursAtLocal" type="string | null">
      The local wall-clock start as your system states it, ISO 8601 **with offset**, for example `2026-11-14T20:00:00-05:00`.
    </ResponseField>

    <ResponseField name="timeTbd" type="boolean">
      `true` when the date or time is not confirmed. A placeholder time such as midnight otherwise shows to a buyer as a real "12:00 AM" start.
    </ResponseField>

    <ResponseField name="venue" type="object">
      Omit the whole object if you have no venue data. Never send a venue without a name.

      <Expandable title="Venue object">
        <ResponseField name="name" type="string" required>Venue name.</ResponseField>
        <ResponseField name="streetAddress" type="string">Street address.</ResponseField>
        <ResponseField name="locality" type="string">City.</ResponseField>
        <ResponseField name="region" type="string">State or region.</ResponseField>
        <ResponseField name="countryCode" type="string">ISO 3166-1 alpha-2, for example `US`.</ResponseField>
        <ResponseField name="postalCode" type="string">Postal code.</ResponseField>
        <ResponseField name="latitude" type="number">Latitude.</ResponseField>
        <ResponseField name="longitude" type="number">Longitude.</ResponseField>

        <ResponseField name="timezone" type="string">
          IANA zone, for example `Europe/Madrid`. **Send it whenever you have it.** Without it Retail has to derive the zone, and when that fails the event is stored in UTC and shows the wrong start time.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="categoryName" type="string">
      Your category, for example `Concerts`.
    </ResponseField>

    <ResponseField name="performerNames" type="string[]" default="[]">
      Performers or teams, headliner first.
    </ResponseField>

    <ResponseField name="state" type="string">
      Your lifecycle state for the event, in your own vocabulary, for example `shown`, `postponed` or `rescheduled`. **`ignored` means not for sale**, and Retail never shows it to a buyer.
    </ResponseField>

    <ResponseField name="updatedAt" type="string | null">
      Your last-modified stamp for the event. Drives incremental sync.
    </ResponseField>

    <ResponseField name="availableCount" type="integer">
      Indicative only. How many listings you see on the event, **never** a purchasable quantity. Retail stores it as an observation and gets real supply from listings.
    </ResponseField>

    <ResponseField name="seatingChartUrl" type="string">
      Optional. Retail does not show this URL to buyers. Maps are served through [Venue map](/vendor-api/venue-map).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="nextPage" type="integer | null" required>
  The next page number, or `null` when the catalog is exhausted.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -H "X-API-Key: $GOMRY_RETAIL_API_KEY" \
    "https://integration.example.com/api/vendor/v1/catalog?vendorKey=acme&page=1&updatedSince=2026-09-30T00:00:00.000Z"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "events": [
      {
        "vendorEventId": "3273941",
        "name": "City FC vs United",
        "occursAt": "2026-11-14T20:00:00.000Z",
        "occursAtLocal": "2026-11-14T15:00:00-05:00",
        "timeTbd": false,
        "venue": {
          "name": "Riverside Stadium",
          "locality": "Philadelphia",
          "region": "PA",
          "countryCode": "US",
          "postalCode": "19148",
          "latitude": 39.9008,
          "longitude": -75.1675,
          "timezone": "America/New_York"
        },
        "categoryName": "Soccer",
        "performerNames": ["City FC", "United"],
        "state": "shown",
        "updatedAt": "2026-09-29T11:42:10.000Z",
        "availableCount": 174
      }
    ],
    "nextPage": 2
  }
  ```
</ResponseExample>
