Developer docs
Ticker API
Ticker's market data over HTTP: price, inventory and demand for an event, the same readings rolled up by day, a name-to-id search, and performer rank. It authenticates with an API key. There is one Ticker API, and this is its reference.
Getting started
Create a key in Settings, under API, then send it as a bearer token against this base URL.
https://api.findticker.comcurl -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 and refresh with each pipeline run. The shopping series is daily.
{
"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"]
}
}Authentication
Send the key in the Authorization header. Every secret starts with tk_live_.
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 tier 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 tier 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
qRequired. At least two letters or digits; the % _ and * wildcards are a 400.
limitHow many matches to return, at the published search cap.
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 daily budget. Nothing hands back ids for free.
Shopping routes
Ten reads in total, each priced in budget units. The two below are the shopping pair. They answer with current, the latest reading, and series, one point per UTC day. Values are as of computed_at and refresh with each pipeline run. The shopping series is daily. They are the only routes that take columns.
GET /api/feed/v1/events/{eventId}/shopping
1 unitShopping demand for one event: the current reading, and one point per UTC day.
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 daily 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 returnedThe 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.
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"]
}'{
"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 tointerest 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
interestcurrent + seriessalescurrent + seriessnapshot_dateseriesBoth metrics are rolling-window levels, not daily flows. sales is how briskly the event is selling over the window, not a count of tickets sold that day.
Analytics
The analytics pair returns this set on every call. It does not take columns. Values are as of computed_at and refresh with each pipeline run. 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.
event_idcurrentcomputed_atcurrentlowest_price_currentcurrentmedian_price_currentcurrentp25_price_currentcurrentp75_price_currentcurrentlowest_face_value_currentcurrentmedian_face_value_currentcurrentaverage_face_value_currentcurrenthighest_face_value_currentcurrentp25_face_value_currentcurrentp75_face_value_currentcurrentlistings_currentcurrenttickets_currentcurrentpercent_remainingcurrentinterestcurrentsalescurrentlast_price_snapshot_datecurrentpartial_rowcurrentprediction_marketscurrentOther routes
None of these take columns. The analytics pair answers one flat reading per event, history answers one per day, search answers ids only, and the performer route answers a rank position and its series.
GET /api/feed/v1/events/{eventId}/analytics
1 unitThe 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 and refresh with each pipeline run.
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 returnedThe 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 daysPrice, inventory and demand per day for one event. Values are as of computed_at and refresh with each pipeline run.
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/search
1 unitResolves 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 unitA performer's current popularity rank, the raw aggregates behind it, and a daily rank series. 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.
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 unitThe 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 returnedThe events one saved View matches right now, with the filter that ran. Values are as of computed_at and refresh with each pipeline run.
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 requestAsk for events in plain language and get the matching list back with the filter the question compiled to. Values are as of computed_at and refresh with each pipeline run.
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.
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"{
"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 }
}Rate limits
A shared daily unit budget 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 digest 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": "…" }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 screen route ran out of the account's daily assist allowance. The body carries reason.
403The key is valid and the account holds the tier, 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 or daily budget is exhausted. 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.