TickerDocs
REST API

Ticket market data API

The ticket market data API: primary and resale prices, inventory and demand per event, price history, name-to-id search, performer rank, views and screens.

Ticker's market data over HTTP: price, inventory and demand for an event, the history of those readings, a name-to-id search, and performer rank. It authenticates with an API key. There is one Ticker API, and this is its reference.

OpenAPI document, v1

Getting started

Create a key in Settings, under API, then send it as a bearer token against this base URL.

Base URL
https://api.findticker.com
Request
curl -s \
  -H "Authorization: Bearer $TICKER_API_KEY" \
  "https://api.findticker.com/api/feed/v1/events/ev7k3m9qp2xd/shopping?range=28d&columns=interest,sales"

Responses are JSON. A null means the reading was not observed, never that it was zero. Values are as of computed_at, the time the reading was computed. The shopping series is a list of points, each stamped with its snapshot_date.

Response
{
  "event_id": "ev7k3m9qp2xd",
  "current": {
    "interest": 412,
    "sales": 9
  },
  "series": [
    {
      "snapshot_date": "2026-08-31",
      "interest": 412,
      "sales": 9
    }
  ],
  "meta": {
    "range": "28d",
    "coverage_start": "2026-08-04",
    "points": 28,
    "columns": ["interest", "sales"]
  }
}

Where the prices come from

Every price this API returns is an asking price: what a seller listed a ticket at on resale, or what the box office lists on the primary market, at the moment Ticker read the marketplace. None of them is the price a ticket changed hands at, and no field reports one.

When a seat stops being open on the primary market the API calls it taken. A sale, a hold and a seat not yet released look the same from outside, so taken is never a count of sales. When a listing leaves resale, a buyer may have taken it or its seller may have withdrawn it; the API does not tell those apart, and it reports the last asking price, not a clearing price.

Authentication

Send the key in the Authorization header. Every secret starts with tk_live_.

Header
Authorization: Bearer tk_live_...

The key reaches the data routes and nothing else. The rest of the Ticker API is session-authenticated, so a key cannot read a watchlist, an alert, or an account, and it cannot create another key.

The account's plan is re-read on every request. A downgrade or a cancellation stops the reads at the next call with a 402, without touching the key. A 403 is the other refusal: the plan is there and API access has not been granted.

Ids

Every route takes Ticker ids. An event id is ev plus ten characters, a performer id is pf plus ten characters, and every id the API returns is in that form.

A marketplace id resolves in the same slot when it carries its source prefix, vs:, tm: or tp:. That form does not expire. A bare marketplace id is read as vs: until 2027-09-13 and answers 404 after that date, so nothing you already hold breaks today and nothing stays tied to a marketplace for ever. A whole url segment with its slug is a 400: send the id alone.

Resolve an id by name with the same key:

GET /api/feed/v1/search

1 unit

Resolves a name to the Ticker event ids and performer ids the reading routes accept. Ids only, no readings.

qRequired. At least two letters or digits; the % _ and * wildcards are a 400.
limitHow many matches to return, at the published search cap.
Lookup
curl -s \
  -H "Authorization: Bearer $TICKER_API_KEY" \
  "https://api.findticker.com/api/feed/v1/search?q=morgan%20wallen&limit=5"

Each match carries an event_id, the value every route below takes, and a performer_id for the performer route.

Enumeration

Search resolves a name. It does not page a catalog: there is no list-by-date, list-by-city or list-by-performer route, no cursor on the search response, and a q that is a single character or a wildcard returns 400. Arrive with a name or with ids you already hold.

A screen is the one way to reach events you cannot name, and it is bounded by price rather than by shape: a filter returns matches, and every match returned costs a unit against the same unit budget. Nothing hands back ids for free.

Shopping routes

Every read is priced in budget units. The two below are the shopping pair. They answer with current, the latest reading, and series, a list of points each stamped with its snapshot_date. Values are as of computed_at. They are the only routes that take columns.

GET /api/feed/v1/events/{eventId}/shopping

1 unit

Shopping demand for one event: the current reading, and a series of points each stamped with its snapshot_date.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404.
rangeHow far back the series reaches: 7d, 14d, 28d, 90d. Defaults to 28d.
include_seriesSet to false to return the current reading alone. Defaults to true.
columnsComma-separated metric names. Omit for both interest and sales.

POST /api/feed/v1/events/shopping

1 unit per event id returned

The same reading for many events in one call.

event_idsRequired array of Ticker event ids, each ev plus ten characters. Every id form the single-event routes take works here too, and two spellings of one event are one event. Duplicates are collapsed before the bound is applied, and an id the catalog does not know, or one in a form the API cannot read, comes back under meta.missing rather than failing the call.
rangeOne of 7d, 14d, 28d, 90d. Defaults to 28d.
include_seriesBoolean. Defaults to false on the batch, so a wide read stays cheap.
columnsArray of metric names. Omit for both interest and sales.

A batch carries up to 200 ids. Every batch response echoes the bound in force as meta.batch_max, so a client can size its pages from the answer rather than from this page.

Batch request
curl -s -X POST "https://api.findticker.com/api/feed/v1/events/shopping" \
  -H "Authorization: Bearer $TICKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_ids": ["ev7k3m9qp2xd", "ev2p5w8xd4mq"],
    "range": "7d",
    "include_series": true,
    "columns": ["interest", "sales"]
  }'
Batch response
{
  "data": [ /* one entry per known id, in the order asked for */ ],
  "meta": {
    "requested": 2,
    "returned": 1,
    "missing": ["ev2p5w8xd4mq"],
    "batch_max": 200
  }
}

Columns

columns applies to the two shopping routes above and to no other route on this page. It narrows a shopping response to interest and sales. An unknown name is a 400 whose message lists the valid set.

A missing key and a null value mean different things. Absent means the request did not select it. Null means it was selected and not observed.

Shopping

ColumnName in the appReading
interestInterestDemand, scorecurrent + series
salesSalesDemand, scorecurrent + series
snapshot_dateseries

Both metrics are rolling-window levels, not flows. sales is how briskly the event is selling over the window, not a count of tickets that changed hands.

Analytics

The analytics pair returns this set on every call. It does not take columns. Values are as of computed_at. prediction_markets is present only when at least one Kalshi market maps to the event; the same array appears on the performer route, alongside its raw X counts and Kalshi probability.

ColumnName in the appReading
event_idEvent ididcurrent
computed_atComputed attimestampcurrent
lowest_price_currentLowestPricing, $current
median_price_currentMedianPricing, $current
p25_price_currentP25Pricing, $current
p75_price_currentP75Pricing, $current
lowest_face_value_currentLowest face$current
median_face_value_currentMedian face$current
average_face_value_currentAvg facePricing, $current
highest_face_value_currentHighest face$current
p25_face_value_currentP25 face$current
p75_face_value_currentP75 face$current
listings_currentListingsInventory & demand, countcurrent
tickets_currentTicketsInventory & demand, countcurrent
percent_remainingSecondary remainingInventory & demand, %current
interestInterestDemand, scorecurrent
salesSalesDemand, scorecurrent
last_price_snapshot_datePriced as ofEvent & timing, datecurrent
partial_rowcurrent
primary_statuscurrent
prediction_marketscurrent

Other routes

None of these take columns. The analytics pair answers one flat reading per event, history answers a list of points stamped as_of_date, search answers ids only, and the performer route answers a rank position and its series.

GET /api/feed/v1/events/{eventId}/analytics

1 unit

The current reading for one event: lowest, median, p25 and p75 price, the face-value set, listings, tickets, percent remaining, interest and sales. Values are as of computed_at.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404.

POST /api/feed/v1/events/analytics

1 unit per event id returned

The same reading for many events, in the envelope the shopping batch already uses.

event_idsRequired array of Ticker event ids, each ev plus ten characters. Every id form the single-event routes take works here too, and two spellings of one event are one event and one unit. Duplicates collapse before the bound applies, and an id the catalog does not know, or one in a form the API cannot read, comes back under meta.missing rather than failing the call. meta.units_charged states what the call cost.

GET /api/feed/v1/events/{eventId}/history

1 unit, whatever days

Price, inventory and demand for one event across the days window, one point per as_of_date, each as of its own computed_at.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404.
daysDefaults to the published cap and stays at that cap: a larger value returns the cap and sets meta.days_capped, never an error.

GET /api/feed/v1/events/{eventId}/sections

1 unit, whatever the sections and whatever days

Current price and inventory per section of the house for one event, and optionally each section's history.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404.
daysOptional. Omit it for current levels only. Pass it to attach a history to every section: points stamped as_of_date and snapshot_time, the time of the last reading behind each point. It stays at the published cap: a larger value returns the cap and sets meta.days_capped, never an error. Sections are keyed by the label printed on a ticket, and meta.truncated says whether the window was shortened at the oldest end to keep the payload sane.

GET /api/feed/v1/events/{eventId}/sections/live

1 unit

Live section capacity: seats open now per section, with the section's capacity and the share of it no longer open.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. A known event with no live reading answers 200 with meta.covered false; 404 is only an id the catalog does not know. Per section you get open_count, capacity, percent_taken, is_general_admission, base_section, min_price, median_price and max_price. percent_taken is capacity minus the open seats: a seat that sold, one held back and one withdrawn all count the same, so it is never a sold count. capacity is null, never 0, when the seat map states none, and covered false means no live reading rather than an empty house.

GET /api/feed/v1/events/{eventId}/ga-history

1 unit a call or a page

How many tickets each general admission section of one event had open over time, with its peak and its last change.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. A known event with no live reading answers 200 with meta.covered false; 404 is only an id the catalog does not know. Per section you get open_count, peak_open_count, peak_at, observed_additions, observed_removals, first_observed_at, last_changed_at and removed_at. The additions and removals are observed changes: a returned or re-released ticket adds again, so they are not a count of distinct tickets.
sectionOptional. A general admission section's code. Adds that section's exact points, oldest first, one per observed change; meta.next_cursor pages the rest.
occurrenceOptional, 0 unless the event lists the code twice. section and occurrence together name one section.
cursorOptional. meta.next_cursor from the previous page.

GET /api/feed/v1/events/{eventId}/inventory

1 unit, whatever the days

How many seats were open over time on one event, on the primary book and on the resale book.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404.
daysOptional. How far back to read. It stays at the published cap: a larger value returns the cap and sets meta.days_capped, never an error. The two books are read in one pass and stamped seconds apart, so both land on one point; a null on a book means that pass did not read it, never zero.

GET /api/feed/v1/events/{eventId}/section-frames

1 unit, whatever the sections and whatever the window

Every section's open seat count at each step across a window, in one answer, so you can replay how one event drained.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404.
sinceOptional, ISO 8601. Defaults to 24 hours ago and reaches back at most 7 days. An event with no section readings answers an empty frame list rather than a 404, which is the common case.
untilOptional, ISO 8601. Defaults to now.
intervalOptional step size, 5m, 15m, 1h or 6h. Ask for one too fine for the window and a wider one is served, never a shorter window; meta.interval says which and meta.coarsened says it happened. At most 96 steps. counts[i] is sections[i] at that step, and null there means that section has no reading at or before it, which is not the same as zero. total is the whole house at that step and is null until every section in sections has been read at least once; sections_read says how many of them have, and adding counts up yourself gives the part that was read.

GET /api/feed/v1/events/{eventId}/sale-windows

1 unit

When one event goes on sale, and to whom before that: the named presale windows and the public window.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404.

GET /api/feed/v1/events/{eventId}/seat-history

1 unit a page, whatever the page holds

What happened to one seat: when it was first seen, every price it was re-listed at, every period it was not for sale, and whether it has gone.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404. Most events have no per-seat reading at all; those answer meta.covered false with an empty list rather than a 404.
place_indexNames the seat by its index in the seat map's index space, which the seat position read returns. Pass this or the section, row and seat trio, not neither.
sectionWith row and seat, names the seat the way a ticket prints it. All three are required together.
rowWith section and seat, names the seat the way a ticket prints it.
seatWith section and row, names the seat the way a ticket prints it.
daysOptional. How far back to read, 90 days by default. It stays at the published cap rather than erroring. A change is one of listed, repriced, unavailable or gone; gone means sold or pulled and is only ever set on a seat that has not come back.
cursorOptional. meta.next_cursor from the previous page, for older changes. A seat with a long history comes in pages, newest first, and the pages join end to end into the seat's whole list. Keep days the same across pages. gone is only ever on the first page.

GET /api/feed/v1/events/{eventId}/seller-concentration

1 unit

How concentrated an event's inventory is among the sellers behind it, as counts and shares. No seller is named or identified.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404. An event with no reading yet answers concentration null, which is the common case.

GET /api/feed/v1/events/{eventId}/seller-market

1 unit

The market of chosen sellers on one event: their price series over a range, and their current book per section. Sellers are named by the letters the seller series draws. No seller is identified.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. An id the catalog does not know returns 404.
sellersRequired. Seller letters, A,F. Only a seller whose peak live listings over the range reached 10 can be chosen; any other letter selects nothing, and sellers in the answer lists the letters that did.
rangeOptional. 3d, 7d, 30d, 90d or all, 7d by default.
sectionsOptional. Section ids as the sections route keys them. Given, both the series and the book are those sellers inside those sections.

GET /api/feed/v1/events/{eventId}/seller-series

1 unit

The same block as one point per hour across the window, an hour with no reading being a point of nulls: how many sellers held inventory in that hour, how many of the event's tickets had a known seller of record, and one line per seller with what it held. No seller is named or identified.

eventIdPath. A Ticker event id, ev plus ten characters, as returned by the search route. A marketplace id also resolves when it carries its source prefix (vs:, tm:, tp:), and a bare marketplace id resolves until 2027-09-13. An id the catalog does not know returns 404. An event with no readings yet answers series null, which is the common case.
hoursOptional. How many of the most recent hours to return, 168 by default. It stays at the published cap of 720 rather than erroring. A seller gets a line once it has been among the five largest of an hour, or once it has grown into the event without reaching them, and it keeps that line for the rest of the window. Labels are the order the sellers first appear inside the window, not a rank, and they do not carry across events or across calls with a different window.

GET /api/feed/v1/search

1 unit

Resolves a name to the Ticker event ids and performer ids the reading routes accept. Ids only, no readings.

qRequired. At least two letters or digits; the % _ and * wildcards are a 400.
limitHow many matches to return, at the published search cap.

GET /api/feed/v1/performers/{performerId}

1 unit

A performer's current popularity rank, the raw aggregates behind it, and a rank series of points stamped snapshot_date. Rank is published as a position, never as its inputs.

performerIdPath. A Ticker performer id, pf plus ten characters, which the search route returns under performers. A marketplace id also resolves with its vs: prefix, and bare until 2027-09-13.

GET /api/feed/v1/venues/{venueId}/schedule

1 unit per event returned

A venue's identity and everything on there inside a forward window, soonest first. The same rows the venue's public page shows: name, date, sale dates and the get-in price.

venueIdPath. A Ticker venue id, vn plus ten characters, which the search route returns under venues. A marketplace id also resolves with its vs: prefix, and bare until 2027-09-13.
daysHow far forward to look. Default 30, maximum 365.
limitMost events to return, at most 200. Each one costs a unit, so a narrow window costs less than a wide one.

GET /api/feed/v1/usage

0 units

This account's feed spend: today's budget, what each key spent today, and 30 UTC days of history.

Views and screens

These three answer with a set of events rather than a reading for an id. A saved View is one you built in the product and the key reads back its current matches. A screen takes the question in plain language, compiles it with the same model the product's own screener uses, and returns the matching list together with the filter that ran, so nothing about the answer is opaque.

GET /api/feed/v1/views

1 unit

The saved Views on the key's own account, each with the columns its filter reads.

GET /api/feed/v1/views/{viewId}/results

1 unit per event returned

The events one saved View matches right now, with the filter that ran. Values are as of computed_at.

viewIdPath. A View id from the Views route. A View on another account returns 404, the same answer as a View that does not exist.
pageWhich page of matches to return. Defaults to the first.
limitMatches per page, at the published page cap. Every match returned costs a unit.

POST /api/feed/v1/screen

1 unit per event returned, plus one assist request

Ask for events in plain language and get the matching list back with the filter the question compiled to. Values are as of computed_at.

queryRequired. The question in plain language, not a filter. It is compiled by the same model the product's own screener uses, and the compiled filter comes back in the response so you can see what ran.
pageWhich page of matches to return. Defaults to the first.
limitMatches per page, at the published page cap. Omit to let the question decide, within that cap.

Rows carry the analytics reading, the same set the analytics route serves. The compile spends one request from the account's assist allowance and the rows spend budget units, so a question that matches fifty events costs fifty units and one assist request.

Screen request
curl -s -X POST \
  -H "Authorization: Bearer $TICKER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"events under $80 with more than 200 listings"}' \
  "https://api.findticker.com/api/feed/v1/screen"
Screen response
{
  "query": "events under $80 with more than 200 listings",
  "predicate": {
    "all": [
      { "col": "ea.median_price_current", "op": "<", "val": 80 },
      { "col": "ea.listings_current", "op": ">", "val": 200 }
    ]
  },
  "sort": null,
  "note": null,
  "total": 143,
  "rows": [ { "event_id": "...", "median_price_current": 62, "listings_current": 318 } ],
  "meta": { "page": 1, "limit": 50, "returned": 50, "units_charged": 50 }
}

Freshness

How current each route's answer is, and the field that says so. A reading carries the time it was computed; read that field rather than assuming an age. No route promises a schedule: history runs from the first reading to today, and no reading is overwritten.

RouteHow current
GET /api/feed/v1/events/{eventId}/shoppingAs of computed_at. The series is a list of points, each stamped with its snapshot_date.
POST /api/feed/v1/events/shoppingAs of computed_at.
GET /api/feed/v1/events/{eventId}/analyticsAs of computed_at.
POST /api/feed/v1/events/analyticsAs of computed_at.
GET /api/feed/v1/events/{eventId}/historypoints stamped as_of_date, each with its own computed_at; days reaches 30 back at most.
GET /api/feed/v1/events/{eventId}/inventoryOne point per reading, 30 days back at most.
GET /api/feed/v1/events/{eventId}/section-framesCounts carry forward between readings; as_of says how old the newest reading behind each step is.
GET /api/feed/v1/events/{eventId}/sale-windowsThe sale dates the event states.
GET /api/feed/v1/events/{eventId}/sectionsThe latest reading per section, as of as_of; with days, each section carries a history of points stamped as_of_date and snapshot_time.
GET /api/feed/v1/events/{eventId}/seat-historyEvery change to the seat since it was first seen, newest first.
GET /api/feed/v1/events/{eventId}/sections/liveThe live state of the house at the time of the call, not a computed reading.
GET /api/feed/v1/events/{eventId}/ga-historyEach general admission section's changes over time; it runs behind sections/live, which is the read for what is open now.
GET /api/feed/v1/events/{eventId}/seller-concentrationThe latest reading for the event, or null when there is none yet.
GET /api/feed/v1/events/{eventId}/seller-seriesOne point per hour across the window; an hour with no reading is a point of nulls, not a gap.
GET /api/feed/v1/events/{eventId}/seller-marketOne point per reading across the range, plus the current listings per section.
GET /api/feed/v1/searchIds, not readings.
GET /api/feed/v1/performers/{performerId}As of computed_at, with a rank history of points stamped snapshot_date, 30 days back.
GET /api/feed/v1/venues/{venueId}/scheduleThe same rows the public venue page renders.
GET /api/feed/v1/viewsThe Views as saved at the time of the call.
GET /api/feed/v1/views/{viewId}/resultsAs of computed_at.
POST /api/feed/v1/screenAs of computed_at.
GET /api/feed/v1/usagetoday is the budget in force (limit, used, remaining, resets_at), written on every billed request; history is one row per day for the last 30 UTC days.

Rate limits

A shared unit budget for each UTC date and a per-minute request budget belong to the account, not to a key, so five keys share one allowance and rotating a key does not buy more calls.

A read costs one unit per event id it returns. A single read costs one. A batch of known ids costs one unit per id returned. Ids the catalog does not know cost nothing and come back under meta.missing. A history read costs one whatever its days value, and a search costs one because it returns ids rather than readings.

Every 200 carries X-Feed-Limit and X-Feed-Remaining. When either budget is exhausted the call returns 429 with Retry-After in seconds: seconds until the minute clears for the burst ceiling, seconds until midnight UTC for the day. Every 200 also carries X-Feed-Cost, the units that call spent.

An admitted request counts on the attempt, so a client that retries an error in a loop is still bounded. A call refused on authentication or entitlement is never admitted, so it costs nothing and carries no X-Feed header at all. These are current limits, not an SLA.

Key lifecycle

Keys live in Settings, under API. An account can hold five at once, which is what makes rotation possible: create the replacement, move your integration over, then revoke the old one.

The secret appears once, in the dialog that creates it. Ticker stores a SHA-256 hash of it and the non-secret prefix, so no route can return the secret a second time and nobody at Ticker can read it back. Copy it into your secret store before you close that dialog. If you lose it, revoke the key and create another.

After creation a key is identified by its prefix, tk_live_ plus eight characters, next to its name, creation date and last use. Revoking is immediate: requests carrying that key return 401 from the next call on.

Treat a key like a password. Keep it server-side, out of source control and out of browser code, and revoke it the moment you think it has leaked.

Errors

Every error is JSON in one shape:

{ "code": 401, "message": "…" }
CodeMeaning
400A malformed request, an unknown columns name (the message lists the valid set), a batch over the size bound, or, on a single-id route, an id in a form the API cannot read: a url segment with its slug, or an unknown source prefix. A batch names such an id under meta.missing instead.
401The Authorization header is missing, malformed, or names a revoked key.
402The key is valid but its account no longer holds what the API requires, or the account has used its assist allowance on the screen route. The body carries reason.
403The key is valid and the account holds the plan, but API access has not been granted. Ask us.
404The read was given an event id the catalog does not know, or a View id that is not on this account. A well-formed id we have never seen is a 404, not a 400.
429The burst ceiling or the unit budget is used up. Retry-After carries the seconds.
500A server-side failure. Retry with backoff.

A known event that has no reading yet is not an error. The shopping routes return 200 with current set to null and an empty series; the analytics and history routes return 200 with null readings.

Prefer an AI client?

Everything the API exposes is also reachable through the MCP server: no key, OAuth sign-in, and the same readings as tools. Use the API when you want raw HTTP from your own code; use MCP when an assistant is doing the reading.

On this page