Use a broad odds API and this API together.
For developers whose product needs prices across many sportsbooks and PrizePicks lines with their tiers. Not for a PrizePicks-only job, where one API is simpler, or for a job that only needs consensus, where the broad feed is enough.
Where each one fits
| Job | Use | Why |
|---|---|---|
| Consensus or fair price across many books | Broad odds API | This API reads one board and matched quotes from three venues. |
| Goblin and demon tier on each side | This API | Selections carry a tier per side, in one schema. |
| PrizePicks line moves since 28 October 2026 | This API | Change-only history, as-of boards and a change feed. |
| Labeled outcomes on PrizePicks lines | This API | Closing-line grades where meta.leagues_graded lists the league. |
| Other sports, futures, limits or deep links | Broad odds API | Not offered here. |
| A quick check against one sportsbook in NBA, NFL or NHL | This API alone | /api/v1/compare already joins BetRivers, Kalshi and Polymarket where it can. |
There is no shared identifier
Nothing connects a pp_ projection ID to another provider's fixture or player ID. Our sp_ and se_ stats IDs are opaque and meant only for joining our own endpoints. You are matching on names and times, so treat every join as an inference.
- League. Map codes explicitly. NBA and NBA1Q are different boards here.
- Event start. Compare
event.starts_atto the feed's start time inside a small window. The example uses 15 minutes. - Player name. Normalize case, accents, punctuation and suffixes. Do not expand initials or guess nicknames. Keep a reviewed alias table for the misses you care about.
- Stat and period. Map market names from your provider's market list, by hand, once. Combo and quarter markets need their own entries; an unmapped market stays unmatched.
- Side and line. Compare over to more. A different line is a different proposition, so report it, and do not treat its price as the price of this line.
Keep ambiguous and unmatched rows visible. If a name fits two events, the honest output is “ambiguous”, not the first hit. A false match costs more than a missing one.
Keep the two kinds of number apart
- A PrizePicks line with a tier is not a price.
payout_multiplieris null because the board publishes no payout per offer. - Each provider has its own clock. Keep
observed_atand the feed's timestamp beside any comparison, and do not call a gap an edge until you have checked both. - A missing quote is unknown, not zero, and not proof that a book withdrew the market.
- Our tier belongs to our row. Do not copy it onto the other provider's rows, even for its own PrizePicks entries, without checking how it labels them.
A bounded example you can run
Download pair-with-odds-feed.py, projections.demo.json and broad-odds-feed.sample.json. Python 3.9 or later, standard library only. All sample rows are fictional. It reads one page by default and at most five, and it calls no other provider.
# Runs offline. Download the client and the two sample files linked above.
python3 pair-with-odds-feed.py \
--lines-file samples/projections.demo.json \
--odds-file samples/broad-odds-feed.sample.json# One compact page: 1 credit per requested 100 rows. Your feed's rows come from a file you export.
export PRIZEPICKS_API_KEY='your saved key'
python3 pair-with-odds-feed.py --league NBA --pages 1 --odds-file my-feed.jsonOutput is one JSON line per PrizePicks line, each with a status of same_line, different_line, ambiguous or unmatched, followed by a summary on stderr. Adapt normalize_feed_row to your provider's fields. The sample uses a neutral shape and has not been run against any provider's live response, so verify field and market names against your own.
Budget both sides
Read this side compactly: limit=1000&view=compact costs 10 credits, and an unchanged 304 costs zero. See credit costs. Check both providers' terms before you show the joined data to your users; ours are summarized on the first-call page.