API reference

Look up an endpoint, copy the contract, and ship. Authenticated routes take ?apiKey= or an x-api-key header.

Base /api/v1 v1 Markdown source /docs.md

TM Events API Reference

Base URL: /api/v1

Browse this reference in a browser at /docs. Raw markdown is at /docs.md or GET /api/v1/docs.

All authenticated endpoints require an API key via ?apiKey=<key> query parameter or x-api-key header. Price keys are seperate.


All Routes

Method Path Description Scopes
POST /events/ List events with filters events:read
GET /events/:id Get single event events:read
GET /events/third-party/:id Get third-party URLs events:read
GET /events/price/filtered-by-price Get events by price range events:read, price:read
GET /events/:id/sectioned-pricing Get per-section pricing events:read, price:read
GET /events/:id/early-pricing Get early host price tiers events:read, price:read
GET /events/:id/early-seats Get configured box-office seat map events:read, price:read
GET /events/:id/early-codes Get early promo codes events:read, code:read
GET /events/:id/active-price Get active price range events:read, active-price:read
POST /events/active-price Get active prices (bulk) events:read, active-price:read
GET /events/cheapest-tickets Get cheapest events events:read, active-price:read
GET /events/:id/codes Get presale codes events:read, code:read
GET /events/:id/get-ins Get historical get-in prices events:read, get-ins:read
GET /events/:id/seats Get seat counts (dropped vs pending) events:read, stock:read
GET /events/:id/seats/all Get all seen seats (priced) for event events:read, stock:read
GET /events/:id/stock Get full live stock events:read, stock:read
GET /events/:id/limited-stock Get stock by price break events:read, limited-stock:read
POST /sales/ List events by sale date events:read, sales:read
GET /sales/event/:eventId Get sales by event events:read, sales:read
GET /artists/:id/genre Get artist genre events:read, artists:read
GET /secondaries/compare/ticketmaster/:id Compare TM vs secondary get-in secondaries:read
GET /secondaries/all/listings Combined marketplace listings secondaries:read
GET /secondaries/stubhub/listings/:id StubHub listings secondaries:read
GET /secondaries/vividseats/listings/:id Vivid Seats listings secondaries:read
GET /secondaries/gametime/listings/:id Gametime listings secondaries:read
GET /secondaries/seatgeek/listings/:id SeatGeek listings secondaries:read

Events

Base path: /api/v1/events

All event routes pass through logging and rate-limit middleware.


POST /

List events with filters.

Auth: None (public)

Request Body:

{
  "filters": {
    "eventStartDate": "2025-06-01",
    "eventEndDate": "2025-12-31",
    "status": "onsale",
    "sort": "date",
    "order": "desc",
    "page": 0,
    "limit": 25,
    "onlyTmEvents": false,
    "vividStrict": false,
    "excludePastEvents": true,
    "tmStrict": false,
    "maxInventory": 0
  }
}
Field Type Description
eventStartDate string (YYYY-MM-DD) Start of date range (default: today)
eventEndDate string (YYYY-MM-DD) End of date range (default: 1 year from start)
status string Filter by event status
sort string "date" or "status"
order string "asc" or "desc"
page int Page number (0-indexed)
limit int Results per page (min 10)
onlyTmEvents bool Only include events with a TM ID
vividStrict bool Only include events with a Vivid Seats ID
excludePastEvents bool Exclude events that have already started
tmStrict bool Only include events with updated seat inventory
maxInventory int Max available seats filter (requires tmStrict)

Response (200):

{
  "data": {
    "events": [
      {
        "tm_id": "abc123",
        "name": "Event Name",
        "start_time": "2025-07-01T20:00:00Z",
        "end_time": "2025-07-01T23:00:00Z",
        "status": "onsale",
        "url": "https://www.ticketmaster.com/...",
        "image_url": "https://...",
        "currency": "USD",
        "category": "Music",
        "genre": "Rock",
        "venue": {
          "name": "Madison Square Garden",
          "capacity": 20000,
          "street": "4 Pennsylvania Plaza",
          "city": "New York",
          "state": "NY",
          "country": "US"
        },
        "price": {
          "min_price": 49.99,
          "max_price": 299.99,
          "currency": "USD"
        },
        "sales": {
          "public": {
            "start_date_time": "2025-05-01T10:00:00Z",
            "end_date_time": "2025-07-01T18:00:00Z",
            "start_tbd": false
          },
          "presales": [
            {
              "name": "Artist Presale",
              "description": "Exclusive artist presale",
              "start_date_time": "2025-04-28T10:00:00Z",
              "end_date_time": "2025-04-30T22:00:00Z",
              "url": "https://...",
              "visible": true
            }
          ]
        },
        "details": {
          "stubhub": {
            "url": "https://...",
            "relevent_id": "...",
            "low_price": 55.0,
            "high_price": 500.0,
            "total_listings": 120,
            "total_seats": 350
          },
          "vivid_seats": { "..." : "..." },
          "seat_geek": { "..." : "..." },
          "game_time": { "..." : "..." },
          "automatiq": { "..." : "..." }
        },
        "attraction": {
          "name": "Artist Name",
          "type": "Music",
          "upcoming_events": 15,
          "url": "https://...",
          "seo_name": "artist-name",
          "league": ""
        }
      }
    ]
  },
  "total": 1500,
  "count": 25,
  "page": 0,
  "total_pages": 60,
  "pages_remaining": 59,
  "limit": 25
}

GET /:id

Get a single event by TM ID.

Auth: events:read

Params:

  • id (path) -- Ticketmaster event ID
  • getSales (query, optional) -- "true" to include Vivid/StubHub sales data

Response (200):

{
  "event": { "...EventData..." }
}

Errors:

  • 400 -- Invalid event ID
  • 404 -- Event not found

GET /third-party/:id

Get third-party marketplace URLs for an event.

Auth: None

Response (200):

{
  "name": "Event Name",
  "ticketmaster": "https://www.ticketmaster.com/...",
  "vivid": "https://www.vividseats.com/...",
  "stubhub": "https://www.stubhub.com/...",
  "seatGeek": "https://www.seatgeek.com/..."
}

GET /price/filtered-by-price

Get events filtered by price range.

Auth: price:read

Query Params:

  • minPrice (required) -- Minimum price
  • maxPrice (optional, default: 999999999) -- Maximum price
  • countryCode (optional, default: "US") -- Comma-separated country codes

Response (200):

{
  "events": [ "...EventData[]..." ],
  "total": 42
}

GET /:id/sectioned-pricing

Get per-section min/max pricing for an event (live from websocket monitor).

Auth: events:read, price:read

Response (200):

{
  "ticketMapper": {
    "ORCH1": {
      "section": "ORCH1",
      "minPrice": 89.50,
      "maxPrice": 350.00
    },
    "MEZZ2": {
      "section": "MEZZ2",
      "minPrice": 45.00,
      "maxPrice": 120.00
    }
  }
}

GET /:id/early-pricing

Get the host price scale for an event as soon as the venue box office loads it,
often before the public pricing buffer has anything.

Auth: events:read, price:read

Query:

Param Default Description
availability true Include live seat counts per tier.
allTicketTypes false Include senior/student/group variants; default is base adult only.

Response (200):

{
  "eventId": "150064F581713D8B",
  "currency": "USD",
  "minPrice": 73.75,
  "maxPrice": 133.75,
  "totalAvailableSeats": 842,
  "pricing": [
    {
      "faceValue": 129.5,
      "fees": 4.25,
      "total": 133.75,
      "availableSeats": 120,
      "maximumContiguousSeats": 8
    }
  ]
}

Errors:

  • 404 -- Early pricing is unavailable for this event

GET /:id/early-seats

Get the configured section, row, and seat ranges joined to their preloaded
price codes. This seat map is often available before public onsale and is not
live inventory — a configured range can still be held back when the sale opens.

Auth: events:read, price:read

totalSeats is the venue summary when present, otherwise the sum of parsed
ranges. priceMappedSeatCount is seats that joined to at least one price
code; unpricedSeatCount is the remainder. Ranges with no matching price
code omit pricing. All money fields are major currency units.

Response (200):

{
  "eventId": "150064F581713D8B",
  "currency": "USD",
  "totalSeats": 1840,
  "sectionCount": 12,
  "seatRangeCount": 86,
  "priceMappedSeatCount": 1620,
  "unpricedSeatCount": 220,
  "sections": [
    {
      "name": "101",
      "description": "Lower Bowl",
      "type": "Standard",
      "generalAdmission": false,
      "seatCount": 48,
      "ranges": [
        {
          "row": "A",
          "firstSeat": "1",
          "lastSeat": "8",
          "seatCount": 8,
          "seatIncrement": 1,
          "pricing": [
            {
              "description": "Adult",
              "faceValue": 129.5,
              "fees": 4.25,
              "tax": 0,
              "serviceCharge": 0,
              "total": 133.75
            }
          ]
        },
        {
          "row": "B",
          "firstSeat": "1",
          "lastSeat": "8",
          "seatCount": 8,
          "seatIncrement": 1
        }
      ]
    }
  ]
}

Responses are cached for 2 minutes (Cache-Control: public, max-age=…).

Errors:

  • 400 -- Missing event ID
  • 404 -- Early seats are unavailable for this event

GET /:id/early-codes

Get early promo codes for an event.

Auth: events:read, code:read

Response (200):

{
  "eventId": "abc123",
  "codes": ["PRESALE"]
}

An event with no matching code returns an empty codes array.

Errors:

  • 404 -- Early codes are unavailable for this event

GET /:id/active-price

Get the active (real-time) price range for an event.

Auth: events:read, active-price:read

Response (200):

{
  "eventId": "abc123",
  "prices": {
    "minPrice": 29.99,
    "maxPrice": 499.99,
    "allInMinPrice": 45.00,
    "allInMaxPrice": 525.00,
    "allInMinPriceFiltered": 50.00,
    "allInMaxPriceFiltered": 510.00,
    "facilityFee": 5.50,
    "updatedAt": "2025-06-15T14:30:00Z"
  }
}

POST /active-price

Get active prices for multiple events at once.

Auth: active-price:read

Request Body:

{
  "event_ids": ["abc123", "def456", "ghi789"]
}

Response (200):

{
  "data": [
    {
      "eventId": "abc123",
      "prices": {
        "minPrice": 29.99,
        "maxPrice": 499.99,
        "allInMinPrice": 45.00,
        "allInMaxPrice": 525.00,
        "allInMinPriceFiltered": 50.00,
        "allInMaxPriceFiltered": 510.00,
        "facilityFee": 5.50,
        "updatedAt": "2025-06-15T14:30:00Z"
      }
    }
  ]
}

GET /cheapest-tickets

Get cheapest active-priced events within a date range.

Auth: active-price:read

Query Params:

  • limit (optional, default: 25, max: 300)
  • startDate (optional, RFC3339, default: yesterday)
  • endDate (optional, RFC3339, default: tomorrow)
  • maxPrice (optional) -- Max all-in min price filter

Response (200):

{
  "data": [ "...ActivePriceResponse[]..." ]
}

GET /:id/codes

Get presale/offer codes for an event (live from websocket monitor + database).

Auth: events:read, code:read

Response (200):

[
  {
    "ID": "...",
    "EventID": "abc123",
    "Code": "510002",
    "Name": "Mastercard presales"
  }
]

GET /:id/get-ins

Get historical "get-in" prices for an event.

Auth: events:read, get-ins:read

Response (200):

{
  "eventId": "abc123",
  "prices": [
    {
      "price": 55.00,
      "market": "primary",
      "currency": "USD",
      "scrapedAt": "2025-06-10T12:00:00Z"
    }
  ]
}

GET /:id/seats

Get seat counts for an event, split by priced vs unpriced.

Auth: events:read, stock:read

Response (200):

{
  "event_id": "abc123",
  "total": 5000,
  "seen": 3200,
  "pending": 1800
}

GET /:id/seats/all

Dump every "seen" seat for an event (rows where list_price > 0). No pagination — returns the full set.

Auth: events:read, stock:read

Response (200):

{
  "event_id": "abc123",
  "count": 3200,
  "seats": [
    {
      "Section": "111A",
      "Row": "29",
      "SeatNumber": 14,
      "Name": "POTENT",
      "Description": "Artist Presale",
      "Password": true,
      "ListPrice": 119.5,
      "FaceValue": 115,
      "FacilityFees": 4.5,
      "ServiceCharge": 30.45,
      "FirstSeenAt": "2025-06-10T12:00:00Z",
      "LastUpdatedAt": "2025-06-15T14:30:00Z"
    }
  ]
}

GET /:id/stock

Get full live stock (all available tickets) for an event.

Auth: events:read, stock:read

A numeric :id is a SeatGeek event id (SeatGeek-primary). Those return this
same shape from SeatGeek box-office inventory (open and mercury markets)
and are not looked up as Ticketmaster events. codes is then SeatGeek's
price types, keyed by price type id, with code the price type label. map
is empty. A stored event whose URL is seatgeek.com, or that is neither
Ticketmaster nor AXS and has a SeatGeek id, takes the same path. Every other
event still comes from the Ticketmaster feed.

Query Params:

  • did (optional, default: "default") -- Display ID

Response (200):

{
  "eventId": "abc123",
  "availableSeats": 1500,
  "platinumSeats": 75,
  "map": "https://mapsapi.tmol.io/maps/geometry/3/event/abc123/image?...",
  "bySection": {
    "ORCH1": 120,
    "MEZZ2": 85
  },
  "codes": {
    "Mastercard Presale": {
      "code": "Mastercard Presale",
      "description": "...",
      "quantity": 50
    }
  },
  "stock": [
    {
      "name": "Standard Ticket",
      "section": "ORCH1",
      "row": "A",
      "seat": "12",
      "listPrice": 150.00,
      "faceValue": 125.00,
      "facilityFee": 10.00,
      "serviceCharge": 15.00,
      "password": false
    }
  ],
  "consecutivePairs": 25,
  "pairs": [
    [
      { "section": "ORCH1", "row": "A", "seat": "12", "..." : "..." },
      { "section": "ORCH1", "row": "A", "seat": "13", "..." : "..." }
    ]
  ]
}

Errors:

  • 404 -- No stock available

GET /:id/limited-stock

Get stock summarized by price break (no individual ticket listing).

Auth: limited-stock:read

Query Params:

  • did (optional, default: "default")

Response (200):

{
  "eventId": "abc123",
  "availableSeats": 1500,
  "priceBreaks": [
    {
      "listPrice": 150.00,
      "faceValue": 125.00,
      "facilityFee": 10.00,
      "serviceCharge": 15.00,
      "quantity": 200
    },
    {
      "listPrice": 85.00,
      "faceValue": 70.00,
      "facilityFee": 5.00,
      "serviceCharge": 10.00,
      "quantity": 450
    }
  ]
}

Sales

Base path: /api/v1/sales

Auth (all routes): sales:read


POST /

List events by sale date range (presale/public sale start dates).

Request Body:

{
  "filters": {
    "eventId": "abc123",
    "saleStartDate": "2025-06-01",
    "saleEndDate": "2025-06-30",
    "status": "onsale",
    "sort": "date",
    "order": "desc",
    "page": 0,
    "limit": 25
  }
}

Response (200):

{
  "data": {
    "events": [ "...EventData[]..." ]
  },
  "total": 100,
  "count": 25,
  "page": 0,
  "total_pages": 4,
  "pages_remaining": 3,
  "limit": 25
}

GET /event/:eventId

Get sales by event ID.

Response (200):

{
  "message": "Get sales by event",
  "eventId": "abc123"
}

Artists

Base path: /api/v1/artists

Auth (all routes): artists:read


GET /:id/genre

Get genre classification for an artist by legacy ID.

Response (200):

{
  "artist_id": "K8vZ917...",
  "artist_name": "Artist Name",
  "genre": "Rock",
  "sub_genre": "Alternative",
  "sub_type": "Band",
  "segment": "Music",
  "url": "https://..."
}

Secondaries

Base path: /api/v1/secondaries

Auth (all routes): secondaries:read

All secondaries routes pass through logging and rate-limit middleware.

Listings are normalized into a shared shape. Sections are grouped into zones
(100s, 200s, …; sections under 100 become Floor; named areas like GA
stay as-is). getIn is the cheapest listing price; highTicket is the most
expensive.

Single-marketplace listing endpoints populate getIn, highTicket, and
breakdown. GET /all/listings and GET /compare/ticketmaster/:id merge
listings across sources and do not aggregate those top-level fields.


GET /compare/ticketmaster/:id

Compare Ticketmaster dropped-seat (primary) get-in prices per zone against
StubHub, Vivid Seats, Gametime, and SeatGeek get-in prices for the same event.

:id is a Ticketmaster event ID. Linked marketplace IDs are resolved from the
event record (stubhub, vividseats, gametime, and seatgeek when present).
A marketplace with no linked ID is skipped.

percentChange is the change from the primary get-in to the secondary get-in:
positive means the secondary market is more expensive (markup); negative means
it is cheaper than the dropped-seat price.

Auth: secondaries:read

Params:

  • id (path) -- Ticketmaster event ID

Response (200):

{
  "total": 4200,
  "totalListings": 980,
  "getIn": 0,
  "highTicket": 0,
  "eventIds": {
    "ticketmaster": "abc123",
    "stubhub": "104512345",
    "vividseats": "3845123",
    "seatgeek": "6123456",
    "gametime": "gt_abc123"
  },
  "comparison": [
    {
      "zone": "100s",
      "primaryGetIn": 89.50,
      "primaryPriceBreaks": [
        { "price": 89.50, "seats": 24 },
        { "price": 125.00, "seats": 18 }
      ],
      "marketplaces": [
        {
          "marketplace": "gametime",
          "getIn": 112.00,
          "difference": 22.50,
          "percentChange": 25.14
        },
        {
          "marketplace": "stubhub",
          "getIn": 145.00,
          "difference": 55.50,
          "percentChange": 62.01
        },
        {
          "marketplace": "vividseats",
          "getIn": 138.00,
          "difference": 48.50,
          "percentChange": 54.19
        }
      ]
    }
  ],
  "listings": [
    {
      "marketplace": "stubhub",
      "section": "111",
      "row": "12",
      "qty": 2,
      "price": 145.00,
      "formattedPrice": "$145.00"
    },
    {
      "marketplace": "ticketmaster",
      "section": "111A",
      "row": "14",
      "qty": 1,
      "price": 89.50,
      "formattedPrice": "$89.50"
    }
  ]
}

Primary listings use all-in price (faceValue + facilityFees + serviceCharge).
primaryPriceBreaks only count Ticketmaster seats that are currently in stock.

Errors:

  • 400 -- Missing event ID
  • 500 -- Failed to load the event, dropped seats, or marketplace listings

GET /all/listings

Fetch listings from multiple marketplaces in one request and return them as a
single combined list.

At least one of vividId, stubhubId, gametimeId, or seatgeekId is
required. Each marketplace is fetched only when its id is provided.

Auth: secondaries:read

Query Params:

  • vividId (optional) -- Vivid Seats event ID
  • stubhubId (optional) -- StubHub event ID
  • gametimeId (optional) -- Gametime event ID
  • seatgeekId (optional) -- SeatGeek event ID
  • zoneId (optional) -- StubHub zone/selection filter (selection). Ignored
    for Vivid Seats, Gametime, and SeatGeek.

Response (200):

{
  "total": 850,
  "totalListings": 210,
  "getIn": 0,
  "highTicket": 0,
  "listings": [
    {
      "marketplace": "vividseats",
      "section": "111",
      "row": "8",
      "qty": 2,
      "price": 138.00,
      "formattedPrice": "138.00"
    },
    {
      "marketplace": "stubhub",
      "section": "111",
      "row": "12",
      "qty": 2,
      "price": 145.00,
      "formattedPrice": "$145.00"
    },
    {
      "marketplace": "gametime",
      "section": "112",
      "row": "4",
      "qty": 3,
      "price": 112.00,
      "formattedPrice": "$112.00"
    }
  ]
}

A marketplace that fails to fetch is omitted from the result (the others still
return). breakdown is not populated on this endpoint.

Errors:

  • 400 -- No marketplace event ID was provided

GET /stubhub/listings/:id

Get StubHub listings for an event, with zone-level breakdown.

Auth: secondaries:read

Params:

  • id (path) -- StubHub event ID
  • zoneId (query, optional) -- Zone/selection filter (selection)

Response (200):

{
  "total": 420,
  "totalListings": 95,
  "getIn": 89.00,
  "highTicket": 650.00,
  "breakdown": {
    "stubhub": {
      "count": 420,
      "getIn": 89.00,
      "highTicket": 650.00,
      "zones": {
        "100s": {
          "seats": 180,
          "listings": 40,
          "getIn": 145.00,
          "highTicket": 425.00
        },
        "200s": {
          "seats": 240,
          "listings": 55,
          "getIn": 89.00,
          "highTicket": 650.00
        }
      }
    }
  },
  "listings": [
    {
      "marketplace": "stubhub",
      "section": "111",
      "row": "12",
      "qty": 2,
      "price": 145.00,
      "formattedPrice": "$145.00"
    }
  ]
}

Errors:

  • 400 -- Missing event ID
  • 500 -- Failed to get listings

GET /vividseats/listings/:id

Get Vivid Seats listings for an event, with zone-level breakdown.

Prices are all-in (aip).

Auth: secondaries:read

Params:

  • id (path) -- Vivid Seats event ID

Response (200):

{
  "total": 310,
  "totalListings": 72,
  "getIn": 92.00,
  "highTicket": 480.00,
  "breakdown": {
    "vividseats": {
      "count": 310,
      "getIn": 92.00,
      "highTicket": 480.00,
      "zones": {
        "100s": {
          "seats": 140,
          "listings": 30,
          "getIn": 138.00,
          "highTicket": 380.00
        }
      }
    }
  },
  "listings": [
    {
      "marketplace": "vividseats",
      "section": "111",
      "row": "8",
      "qty": 2,
      "price": 138.00,
      "formattedPrice": "138.00"
    }
  ]
}

Errors:

  • 400 -- Missing event ID
  • 500 -- Failed to get listings

GET /gametime/listings/:id

Get Gametime listings for an event, with zone-level breakdown.

Prices are all-in totals (cents converted to dollars).

Auth: secondaries:read

Params:

  • id (path) -- Gametime event ID

Response (200):

{
  "total": 120,
  "totalListings": 43,
  "getIn": 78.00,
  "highTicket": 320.00,
  "breakdown": {
    "gametime": {
      "count": 120,
      "getIn": 78.00,
      "highTicket": 320.00,
      "zones": {
        "Floor": {
          "seats": 48,
          "listings": 16,
          "getIn": 210.00,
          "highTicket": 320.00
        },
        "100s": {
          "seats": 72,
          "listings": 27,
          "getIn": 78.00,
          "highTicket": 195.00
        }
      }
    }
  },
  "listings": [
    {
      "marketplace": "gametime",
      "section": "112",
      "row": "4",
      "qty": 3,
      "price": 112.00,
      "formattedPrice": "$112.00"
    }
  ]
}

Errors:

  • 400 -- Missing event ID
  • 500 -- Failed to get listings

GET /seatgeek/listings/:id

Get SeatGeek listings for an event, with zone-level breakdown.

:id is a SeatGeek numeric event ID. Every seller channel is included (box
office and resale). price is the all-in price per ticket and qty is the
listing quantity.

SeatGeek sits behind DataDome; challenges are solved transparently. A cold
call takes a couple of seconds, and later calls for the same event reuse the
session.

Auth: secondaries:read

Params:

  • id (path) -- SeatGeek event ID

Response (200):

{
  "total": 3961,
  "totalListings": 1064,
  "getIn": 89.00,
  "highTicket": 1494.72,
  "breakdown": {
    "seatgeek": {
      "count": 3961,
      "getIn": 89.00,
      "highTicket": 1494.72,
      "zones": {
        "100s": {
          "seats": 2140,
          "listings": 612,
          "getIn": 89.00,
          "highTicket": 1494.72
        }
      }
    }
  },
  "listings": [
    {
      "marketplace": "seatgeek",
      "section": "105",
      "row": "1",
      "qty": 2,
      "price": 1494.72,
      "formattedPrice": "$1494.72"
    }
  ]
}

Errors:

  • 400 -- Missing event ID
  • 404 -- Event not found
  • 500 -- Failed to get listings

Available Auth Scopes

Scope Description Includes
events:read Read event data —
price:read Read pricing data events:read
active-price:read Read active/real-time prices events:read
stock:read Read live stock data events:read
limited-stock:read Read limited stock (price breaks) events:read, stock:read
code:read Read presale codes events:read
get-ins:read Read get-in prices events:read
sales:read Read sales data events:read
artists:read Read artist data events:read
secondaries:read Read secondary-market listings events:read

The Includes column lists scopes automatically granted when this scope is subscribed. For example, subscribing to active-price:read also grants events:read and price:read at no additional cost — you only pay the active-price:read tier price.


Scope Pricing

Each scope is priced individually based on the customer's monthly request volume for endpoints covered by that scope. Prices below are in USD per month and represent the flat monthly cost for the included request quota in that tier. Subscribing to any scope automatically grants the bundled scopes listed in the Available Auth Scopes table (e.g. every paid scope includes events:read).

Tiers are billed monthly. A customer subscribes to one tier per scope. Combined / bundled pricing is negotiated separately for Enterprise.

Scope Tier 1 — up to 1K req/mo Tier 2 — up to 10K req/mo Tier 3 — up to 50K req/mo Enterprise (100K+ req/mo)
events:read $200 $500 $1,000 Contact sales
price:read $TBD $TBD $TBD Contact sales
active-price:read $300 $750 $1,250 Contact sales
stock:read $400 $900 $2,000 Contact sales
limited-stock:read $450 $1000 $2,200 Contact sales
code:read $300 $750 $1,250 Contact sales
get-ins:read $300 $750 $1,250 Contact sales
sales:read $300 $750 $1,250 Contact sales
artists:read $220 $525 $1,050 Contact sales
secondaries:read $TBD $TBD $TBD Contact sales

Billing Notes

  • A "request" is any successful (2xx) or client-error (4xx, excluding 429) response on an endpoint that requires the given scope.
  • 429 (rate-limited) and 5xx responses are not billed.
  • If an endpoint requires multiple scopes (e.g. /events/:id/sectioned-pricing requires events:read + price:read), the request counts against each subscribed scope's quota.
  • Unused quota does not roll over month to month.
  • Exceeding a tier's request quota requires upgrading to the next tier for the following billing period.

Common Error Responses

All error responses follow this format:

{
  "error": "Description of the error"
}
Status Meaning
400 Bad request / missing required parameters
401 Missing or invalid API key
403 Insufficient permissions (wrong scopes)
404 Resource not found
429 Rate limit exceeded
500 Internal server error

Rate Limit Error (429):

{
  "error": "Rate limit exceeded",
  "retry_after": 1200.5,
  "reset_time": "2025-06-15T15:30:00Z",
  "rate_limit": {
    "requests_per_window": 100,
    "window_duration_seconds": 3600
  }
}

Rate limit headers are included on all authenticated responses:

  • X-RateLimit-Limit -- Max requests per window
  • X-RateLimit-Remaining -- Remaining requests
  • X-RateLimit-Reset -- Unix timestamp when window resets