tickets.dev

API reference

API reference

Tickets.dev is a real-time ticket scraping API for retrieving live ticket inventory, pricing, fees, sections, rows, quantities, and seat maps from Ticketmaster, StubHub, SeatGeek, TickPick, Vivid Seats, Gametime, Viagogo, GoTickets, Paciolan, ATG Tickets, ProVenue, and GoFevo.

Introduction

The Tickets.dev API scrapes live marketplace inventory on demand. There is no crawl to schedule and no cache to go stale: each call opens the event, reads its current listings and prices, and returns the result to you. Ask for the seat maps and it renders those too.

Learn the product concepts in the ticket scraping API, ticket inventory API, ticket price API, seat map API, and ticket events API guides.

All endpoints live under a single base URL and speak JSON.

Base URL
https://api.tickets.dev/v1
Same schema, every source. A Ticketmaster capture and a Vivid Seats capture return the identical snapshot object, so you never branch on the marketplace.

Authentication

Every request must carry your API key. Send it in the x-api-key header. Create a key from the account page.

curl -G https://api.tickets.dev/v1/capture/ticketmaster \
  --data-urlencode "url=$EVENT_URL" \
  -H "x-api-key: $TICKETS_DEV_KEY"

An apiKeyquery parameter is accepted as well, for callers that can't set a header.

Keep your key server-side. It carries your full quota, so never embed it in client-side code or commit it to a repo. Rotate a key immediately if it leaks. The public sandbox key below cannot spend credits.

Sandbox

There is no separate sandbox host. Same base URL, same paths, same query parameters, same snapshot shape. One public key returns fixtures instead of a live capture.

Sandbox API key
tk_test_sandbox

Build against that key. Cut over by swapping it for your org's tk_live_… key. Nothing else in the request should have to change: not the URL, not the query, not the parser.

Sandbox request
curl -G https://api.tickets.dev/v1/capture/ticketmaster \
  --data-urlencode "url=https://www.ticketmaster.com/event/example" \
  -H "x-api-key: tk_test_sandbox"

Validation still runs, so a bad request fails the same way it would in production. Responses carry the header Tickets-Sandbox: true. Streaming captures send the same progress events, then the snapshot.

Start in the playground. Sandbox mode uses this key against the real API. Copy the snippet, then replace the key with yours when you go live.

Quickstart

Point the API at any supported event URL. The request runs the capture and returns the whole event: every listing on it, with prices and fees, in one response.

cURL
curl -G https://api.tickets.dev/v1/capture/ticketmaster \
  --data-urlencode "url=https://www.ticketmaster.com/event/XXXXXXXX" \
  -H "x-api-key: $TICKETS_DEV_KEY"

Endpoints

Pass an event URL and every marketplace returns the identical snapshotobject. The marketplace is optional: it comes from the URL's host unless you name it with source= or in the path.

MethodPathQueryReturns
GET/v1/capture?url=&source=&includeVenueMaps=Capture one event: every listing on it, in one response. A live key spends one credit; tk_test_sandbox returns a fixture and is never billed. Costs one capture with a live key.
GET/v1/capture/{source}?url=&includeVenueMaps=The same capture with the marketplace in the path, e.g. /v1/capture/ticketmaster. Costs one capture with a live key.
GET/v1/capture/sources-The marketplaces you can capture, and the hosts that route to each. Never billable.
GET/v1/health-Service status. No key required.
GET/v1/events?query=&source=&from=&to=&eventId=&page=&pageSize=Ticket event discovery and matching: search the catalog by name, performer, venue, date, or marketplace URL. Returns one unified event with every matched marketplace ID and URL. Never billed.

Parameters

NameTypeDescription
urlstring, requiredThe event page URL from a supported marketplace.
sourcestring, optionalWhich marketplace to capture from, e.g. ticketmaster. Only needed for a host we don't recognize, such as a shortener. See /v1/capture/sources for the values.
includeVenueMapsboolean, optionalRender and host the seat maps and fill venueLayout. Off by default, since the maps add time to the capture. Pass true to turn them on.

Ticket events

/v1/events is the free ticket event discovery and matching API: event name, venue, date, performers, and a sources array of marketplace ids and URLs. Search by name, or pass a marketplace URL to resolve one unified event. It never returns prices, listing counts, or ticket counts. Those stay on capture. See the ticket events API.

One parameter does the searching. ?query= takes a name, a venue or performer, a slug, or any marketplace URL, with or without a scheme, and works out which it is. An event page returns that event; a venue or performer page returns the upcoming dates. Narrow with ?from= / ?to= and ?source=. Native event ids use ?source=ticketmaster&eventId=; ?eventId= also takes the catalog id. To capture listings and prices, take a sources[].url from the response and pass it to /v1/capture?url=.

The catalog is mapped from Ticketmaster, StubHub, SeatGeek, TickPick, Vivid Seats, Gametime, GoTickets, and Paciolan today, with Viagogo, ATG Tickets, ProVenue, and GoFevo rolling out next. Until one lands, /v1/events answers source_not_indexed for it.

NameTypeDescription
querystring, optionalThe one search input. Free text matches event name, venue, city and performers. A hyphenated slug also matches venue and performer url names. A marketplace URL is resolved directly: an event page returns that event, a venue or performer page returns its dates.
urlstring, optionalAlias for query when the value is a URL. Kept so an event link can be passed under an obvious name.
eventIdstring, optionalNative marketplace event id (with source=) or a catalog id.
sourcestring, optionalRestrict to events listed on this marketplace, and scope native ids to it. Each event still returns every marketplace carrying it: this filters which events come back, not which links each one shows.
fromstring, optionalInclusive UTC start bound, ISO-8601. Searches exclude events that have already started unless you pass this; set it to a past date to include them.
tostring, optionalExclusive UTC start bound, ISO-8601.
pageinteger, optional1-based page number. Defaults to 1, capped at 200.
pageSizeinteger, optionalEvents per page. Defaults to 20, capped at 100.

Responses carry page, pageSize, total, numberOfPages and hasMore above the events array.

Searches return upcoming events. Ones that have already started are left out unless from says otherwise; events with no start time published are always included, since there is nothing to compare. Exact lookups by eventId or by URL are never filtered by date.

Catalog reads require a key, are never billed, and are not rate limited.

cURL
curl -G https://api.tickets.dev/v1/events \
  --data-urlencode "query=eagles sphere" \
  --data-urlencode "from=2026-12-01" \
  -H "x-api-key: $TICKETS_DEV_KEY"
Response
{
  "page": 1,
  "pageSize": 20,
  "total": 1,
  "numberOfPages": 1,
  "hasMore": false,
  "events": [
    {
      "id": "01M0FVJHZRFPS6Y3XM5M0BQ1RH",
      "name": "The Eagles",
      "eventDateLocal": "2026-12-11T20:30:00-08:00",
      "eventDateUtc": "2026-12-12T04:30:00.000Z",
      "venue": {
        "name": "Sphere at The Venetian Resort",
        "city": "Las Vegas",
        "state": "NV",
        "country": "US",
        "timezone": "America/Los_Angeles"
      },
      "performers": [{ "performerId": "44705", "name": "The Eagles", "master": true }],
      "sources": [
        {
          "marketplace": "ticketmaster",
          "eventId": "17006483D6FAFC60",
          "url": "https://www.ticketmaster.com/eagles-live-at-sphere-las-vegas-nevada-12-11-2026/event/17006483D6FAFC60"
        },
        {
          "marketplace": "vividseats",
          "eventId": "7256971",
          "url": "https://www.vividseats.com/the-eagles-tickets-las-vegas-sphere-at-the-venetian-resort-12-11-2026--concerts-adult-contemporary/production/7256971"
        },
        {
          "marketplace": "stubhub",
          "eventId": "161551904",
          "url": "https://www.stubhub.com/the-eagles-las-vegas-tickets-12-11-2026/event/161551904"
        },
        {
          "marketplace": "gotickets",
          "eventId": "1794730",
          "url": "https://gotickets.com/tickets/1794730/the-eagles-tickets/msg-sphere-las-vegas-nv-12-11-2026"
        }
      ],
      "updatedAt": "2026-08-25T09:14:02.418Z"
    }
  ]
}

Take any sources[].url from the response and pass it to /v1/capture?url=to get that marketplace's live listings and prices.

The snapshot object

Every capture returns one snapshot: the full listing payload for one event. It carries the event metadata, the currency, the derived stats, the flat list of listings, URLs to the rendered seat maps, and the venue layout.

FieldTypeDescription
sourcestringMarketplace the capture came from, e.g. ticketmaster.
eventIdstringThe marketplace's own id for the event.
eventNamestringEvent title.
performersPerformer[]Acts or teams on the bill, each with performerId, name, and master.
venueIdstringThe marketplace's own venue id.
venueNamestringVenue name.
venueAddressstringStreet address of the venue.
venueCitystringVenue city.
venueStatestringVenue state or province.
venueTimezonestringIANA zone of the venue, e.g. America/Chicago. Empty when the marketplace doesn't publish one.
eventDateLocalstringEvent date/time in venue-local ISO 8601.
eventDateUtcstringThe same moment in ISO 8601 UTC.
sourceUrlstringThe event page the capture read.
capturedAtstringWhen the capture ran, ISO 8601 UTC.
currencystringISO currency code for every price, e.g. USD.
notestringThe marketplace's own buyer notice for this event. An event with nothing to sell (sold out, canceled, or not yet on sale) is a normal 200 with an empty listings array and the reason here.
sectionLevelUrlstringSection-level overview SVG. Empty unless the request passed includeVenueMaps=true. See Seat maps.
seatLevelUrlstringZoomed seat-level SVG. Same includeVenueMaps opt-in as above.
statsStatsWhole-event pricing we derive from listings (see below).
listingsListing[]Every available listing (see below).
venueLayoutVenueLayoutThe venue map as data: sections, rows and seats. Same includeVenueMaps opt-in as the maps. See The venueLayout object.
Response
{
  "source": "ticketmaster",
  "eventId": "17006483D6FAFC60",
  "eventName": "Eagles Live at Sphere",
  "venueId": "189524",
  "venueName": "Sphere",
  "venueCity": "Las Vegas",
  "venueState": "NV",
  "venueTimezone": "America/Los_Angeles",
  "eventDateLocal": "2026-12-11T20:30:00-08:00",
  "eventDateUtc": "2026-12-12T04:30:00+00:00",
  "currency": "USD",
  "sectionLevelUrl": "https://storage.tickets.dev/…/section.svg",
  "seatLevelUrl": "https://storage.tickets.dev/…/seats.svg",
  "stats": {
    "listingCount": 136,
    "ticketCount": 1037,
    "getInPrice": 303.08,
    "medianPrice": 710.95,
    "avgPrice": 746.14,
    "maxPrice": 2309.85
  },
  "listings": [{
    "listingId": "",
    "inventoryType": "primary",
    "section": "208",
    "row": "9",
    "quantity": 3,
    "ticketPrice": 1157.5,
    "fee": 208.35,
    "totalPrice": 1365.85,
    "sellableQuantities": "1,2,3"
  }],
  "venueLayout": {
    "level": "seat",
    "capacity": 16390,
    "sections": [{
      "section": "101",
      "group": "",
      "ga": false,
      "capacity": 522,
      "rows": [{ "row": "34", "capacity": 21, "seats": "1,2,3,…,19,20,21" }]
    }]
  }
}

The stats object

stats is worked out from the listings. Every figure is per ticket and all-in, like totalPrice, and counted per listing: a ten-seat listing counts once. A capture with no listings reports zeroes.

FieldTypeDescription
listingCountnumberHow many listings the capture returned.
ticketCountnumberTotal seats across every listing: how deep the inventory is.
getInPricenumberCheapest all-in price per ticket: the get-in price.
medianPricenumberMedian all-in price per ticket, across listings.
avgPricenumberAverage all-in price per ticket, across listings.
maxPricenumberHighest all-in price per ticket.

The listing object

Each entry in listings is one group of same-price seats. Every field below comes back from every marketplace.

FieldTypeDescription
listingIdstringStable id for the listing.
inventoryTypestringe.g. primary, resale, verified.
sectionstringSection name or number as the marketplace spells it, with a leading Section word removed, so "Section 101" reads 101 everywhere. The same string as the maps' data-section and venueLayout. Case is the marketplace's own, so casefold when joining across marketplaces.
rowstringRow label.
quantitynumberSeats available in this listing.
ticketPricenumberFace price per ticket, before fees.
feenumberPer-ticket fees.
totalPricenumberAll-in price per ticket, excluding sales tax. Normalized to the same meaning on every marketplace.
ticketTypestringHow the ticket is delivered, e.g. Mobile Transfer.
sellableQuantitiesstringComma-separated quantities you can actually buy, e.g. 2,4.
groupstringThe marketplace's own seating tier, e.g. Upper.
seatsstringComma-separated seat numbers, when exposed by the source.
listingNotesstringSeller notes, e.g. Aisle seat.
dealScorestringThe marketplace's own value-for-money score, as it shows it. Empty where the source doesn't publish one, and not comparable between marketplaces.

Seat maps

Pass includeVenueMaps=true and the capture renders two SVGs and hosts them for you:

  • sectionLevelUrl, the overview: the venue outline, the stage, and one shape per section.
  • seatLevelUrl, the zoomed detail: rows or seats, as fine as the venue's map goes.

The two share a viewBox. The seat file is one group in the section map's coordinates, so append it to the same <svg> when someone zooms in. Sections are tens of kilobytes and seats hundreds, so fetch it only on zoom.

Every region carries data-section, and data-row where the map has rows, spelled the way listings[].section spells it, so a listing binds to its shape by name.

The same parameter fills venueLayout: the sections, rows and seats behind those shapes as data.

Without the parameter both fields come back as empty strings. The fields are always present, so a client never has to branch on their existence. seatLevelUrl is also empty where the marketplace publishes only a section level map.

cURL
curl -G https://api.tickets.dev/v1/capture/ticketmaster \
  --data-urlencode "url=$EVENT_URL" \
  --data-urlencode "includeVenueMaps=true" \
  -H "x-api-key: $TICKETS_DEV_KEY"

The venueLayout object

venueLayout is the venue map as data: its sections, the rows in each and the seats in each row. It is read from the same map as the seat maps, for this event's setup of the venue. Pass includeVenueMaps=true to get it; without it the field is { "level": "none", "sections": [] }.

Names match. Sections, rows and seats are spelled the same in venueLayout, in listings and in the maps' data-section, data-row and data-seat.

Seats are in order across the row. A row numbered odd on one side of the aisle and even on the other reads 5,3,1,2,4,6, so neighbours sit next to each other in the string.

level is how deep the map goes. Capacities come at seat level, counted from the seats.

FieldTypeDescription
levelstringHow deep the map goes: seat, row, section or none.
capacitynumber, optionalSeats in the venue. Only at seat level.
sectionsSection[]In the map's order.

Section

FieldTypeDescription
sectionstringMatches listings[].section and data-section.
groupstringThe map's zone for the section, e.g. Lower Bowl. Empty if the map has none.
gabooleanGeneral admission: no rows or seats.
capacitynumber, optionalSeats in the section. Only at seat level.
rowsRow[]In the map's order. Empty for GA or when the map stops at sections.

Row

FieldTypeDescription
rowstringMatches listings[].row and data-row.
capacitynumber, optionalSeats in the row. Only at seat level.
seatsstringEvery seat in the row on the map, comma-joined in order across the row. Matches listings[].seats and data-seat. Empty when the map stops at rows.
venueLayout, trimmed to two rows
{
  "level": "seat",
  "capacity": 16390,
  "sections": [
    {
      "section": "101",
      "group": "",
      "ga": false,
      "capacity": 522,
      "rows": [
        {
          "row": "33",
          "capacity": 21,
          "seats": "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21"
        },
        {
          "row": "36",
          "capacity": 15,
          "seats": "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15"
        }
      ]
    }
  ]
}

Marketplaces

Every marketplace returns the same snapshot. Pass an event URL from one of its domains and the marketplace is worked out for you. The paths below are the explicit form, and the last segment of each is also the value for source=:

MarketplacePathEvent URL domains
Ticketmaster API/v1/capture/ticketmasterticketmaster.com, livenation.com
StubHub API/v1/capture/stubhubstubhub.com
SeatGeek API/v1/capture/seatgeekseatgeek.com
TickPick API/v1/capture/tickpicktickpick.com
Vivid Seats API/v1/capture/vividseatsvividseats.com
Gametime API/v1/capture/gametimegametime.co
Viagogo API/v1/capture/viagogoviagogo.com
GoTickets API/v1/capture/goticketsgotickets.com
Paciolan API/v1/capture/paciolanevenue.net
ATG Tickets API/v1/capture/atgatgtickets.com, us.atgtickets.com
ProVenue API/v1/capture/provenuemlb.tickets.com, mpv.tickets.com
GoFevo API/v1/capture/gofevogofevo.com
Country domains and subdomains work too. Each marketplace is matched on its brand name, so viagogo.de, stubhub.co.uk, ticketmaster.ca and m.ticketmaster.com are all accepted.

A URL from a domain we don't recognize works if you name the marketplace with source=; without it the capture returns marketplace_required. A URL from a different marketplace than the one you named returns marketplace_mismatch.

Errors

Every error carries a stable code and the request_id that also comes back in the x-request-id header. Branch on the code, not the status: several distinct failures share a status, and the code is what tells you whether retrying is worth it.

{
  "error": {
    "code": "marketplace_mismatch",
    "message": "Requested source \"stubhub\" but the URL is a ticketmaster event.",
    "outcome": "rejected",
    "retryable": false,
    "request_id": "6068316c-29d3-447f-b42c-b46f80debd0d"
  }
}

outcome and retryable say what to do with any error, including codes added after you integrate.

outcomeWhat it meansWhat to do
successA capture ran and returned an event. There is no error envelope: this is the 200.Use the snapshot. This is the only outcome that spends a capture.
not_foundThe capture ran, and the marketplace has no event at that URL.Fix the URL. Retrying returns the same answer more slowly.
failureThe capture could not complete. Ours, not yours.Retry. Back off if it persists, then tell us the request_id.
rejectedThe request never became a capture: the key, the URL, the plan, or capacity.Fix the request or the account. Only rate_limited is worth waiting out.
On /capture/stream the response is committed as 200 before the capture starts, so a failure arrives as an error event carrying these same fields rather than as an HTTP status. Read the event, not the status.
StatusCodeMeaning
400missing_urlNo url was given.
400invalid_urlurl is not a valid http(s) URL.
400marketplace_requiredThe URL's host is not one we recognize, so name the marketplace with source=.
400marketplace_mismatchThe source you named and the URL disagree.
401missing_keyNo API key was sent.
401invalid_keyThe key is unknown or revoked.
402no_planNo captures remaining. Choose a plan to continue.
402subscription_inactiveThe subscription lapsed. Update the payment method.
404unknown_marketplaceNo such marketplace. See /v1/capture/sources.
404event_not_foundThe marketplace has no event at that URL. Check the URL: retrying returns the same answer.
429quota_exceededNo captures left on the balance.
429rate_limitedToo many captures in flight, or capacity is saturated. Honour Retry-After.
502capture_failedThe capture could not complete.
503capture_unavailableOur side is down, not your rate. Safe to retry.
504capture_timeoutThe capture did not finish in time. Safe to retry.
Only success counts against your quota. Failures, rejections and event_not_found are never billed, including the case where a marketplace serves a page for a URL with no event on it, which comes back as 404 event_not_found rather than an empty capture.

Rate limits

Each plan adds captures each invoice and sets a ceiling on how many captures can run at once. Spending them returns 429 quota_exceeded; whatever is left stays on your balance. See the pricing table for the limits on every tier.

A 429 rate_limited means slow down for a moment, not that you are out of quota: either too many of your captures are already running, or capture capacity is momentarily full. It carries a Retry-After header and is never billed. Honour the header and retry. The free ticket events catalog is not rate limited at all.

Data use

A capture only reads public data: the listings, prices, fees and seat maps the marketplace shows any visitor on its event page, with no login. Tickets.dev puts no license terms on what a capture returns. Store it, analyze it, build products on it and show it to your own users, with no attribution required.

Questions? Reach us at contact@tickets.dev  ·  Back to Tickets.dev