API reference
Deals
GET/v1/dealsProducts priced below their normal price, with the website's filters. Includes recently ended deals.
stateone oflivearchive- Default
- live
archive = deals that ended in the last 14 days.
min_discountnumber, range 0–100- Default
- 5
Minimum % below normal.
max_discountnumber, range 0–100Maximum % below normal.
categorystring- Example
- Kitchen
Raw category group, e.g.
Kitchen,CE.min_price_centsinteger, range ≥ 0Live: current price. Archive: deal price.
max_price_centsinteger, range ≥ 0Live: current price. Archive: deal price.
in_stock0 | 1- Default
- 0
1 = only products in stock at the last check.
seen_within_hoursinteger, range ≥ 1Live only: price seen within this many hours.
min_ratingnumber, range 0–5Minimum star rating.
min_reviewsinteger, range ≥ 0Minimum number of ratings.
min_history_daysinteger, range ≥ 0Tracked for at least this many days. Every deal has at least 14.
lowest_seen0 | 1- Default
- 0
Live only: 1 = at (within 1% of) the lowest price of the last 45 days.
include_suspect0 | 1- Default
- 0
1 = include prices under $1 or more than 90% below normal (likely listing errors).
sortone ofdiscountsavingpricerecent- Default
- discount
Archive always sorts by end time.
limitinteger, range 1–200- Default
- 50
Rows per page, max 200.
cursorstringFrom
next_cursor.
A JSON object. Money is integer cents (USD) and times are milliseconds since the Unix epoch. Fields marked nullable can be null.
stateone oflivearchiveEchoes the request.
min_discountnumberEchoes the minimum discount applied.
countintegerRows in this page.
total_cappedbooleanTrue when more rows matched than the 4,000-row working set; narrow the filters to see others.
next_cursorstringnullablePass as
cursorfor the next page. Null on the last page.deals[].stringasin ASIN.
deals[].stringnullabletitle Title.
deals[].stringnullableimage Image URL.
deals[].numbernullablerating Star rating.
deals[].integernullablereview_count Number of ratings.
deals[].stringnullablecategory Raw category group.
deals[].stringnullablecategory_label Readable category name.
deals[].booleannullablein_stock Availability at the last check.
deals[].integernullablecurrent_cents Current price.
deals[].integernullablereference_cents Normal price.
deals[].numbernullablediscount_pct Percent below normal. Archive rows: the discount while the deal ran.
deals[].integernullableseen_at When the current price was last seen.
deals[].one ofgreatgoodnormalverdict. label great at 20%+ below normal, good at 5–20%, normal under 5% (only when
min_discountis below 5). Archive rows: the label the deal had while it ran, not today's.deals[].numbernullableverdict. pct_vs_normal Same as
discount_pct.deals[].objectnullablelisting_claim {label, claimed_pct}when the listing shows a crossed-out price for the current price.deals[].integernullablewas_cents Archive only: the deal price.
deals[].integernullableended_at Archive only: when the deal ended.
deals[].booleansuspect Only with
include_suspect=1: present and true on likely listing errors (under $1, or more than 90% below normal). Absent on every other row.
- Deals need at least 14 days of history: there's no verdict before that.
- Results come from a working set of the top 4,000 rows by the chosen sort;
total_cappedtells you when that cut applied. - Calls count toward your key's per-minute ceiling (Free 60, Pro 300, Business 1,200 calls a minute), and deals calls have their own: 60 a minute (30 on Free). A call over either gets 429
rate limit exceededand isn't charged. - Each call with a valid key counts as one request against your daily quota, even if the request then fails. A call turned away by a per-minute ceiling (429
rate limit exceeded) doesn't count.
- 401
missing api keyNo key sent.
- 401
invalid api keyUnknown or revoked key.
- 405
method not allowedThe data endpoints are GET only. The
Allowheader lists the methods an endpoint answers: GET, HEAD and OPTIONS (POST and OPTIONS for/v1/keys/rotate). - 429
rate limit exceededMore than your plan's per-minute ceiling; wait
Retry-Afterseconds. Not charged. The body addslimit,window_sandretry_after_s. - 429
daily quota exceededOver today's quota. The body adds
limitandused. - 500
internal errorSomething failed on our side, not in your request.
- 503
temporarily unavailableOur database can't be reached right now. Retry after the number of seconds in the
Retry-Afterheader.
Error bodies are {"error": string}. A daily-quota 429 adds limit and used; a per-minute 429 adds limit, window_s and retry_after_s, with a Retry-After header. See Errors and Quotas.
Send a real request from this page with your key. It goes from your browser straight to TrackPin.
Demo mode covers /product only. Use your key to try this endpoint.
Send a request to see the status, headers and body here.
Early access.