Every price an API returns was seen at some moment. What matters is knowing that moment, and refreshing the products where it matters.
Published
A real-time price is fetched from the retailer while your request waits. A cached (or stored) price was collected earlier and is served from a database. Most pricing services mix the two: they keep a store of prices and refresh parts of it on a schedule or on demand.
The label on the product page matters less than one field in the response: when was this price seen? A stored price from ten minutes ago is fresher than a “real-time” page that a retailer served from its own cache an hour ago.
| Fetched at request time | Served from a store | |
|---|---|---|
| Response time | Seconds, set by the slowest retailer | Fast and consistent |
| When a retailer blocks or times out | That price is missing from the response | The last price seen is returned, with its age |
| Retailers per request | Limited by how many sites can be fetched in time | Every retailer on file for the product |
| Price history | Only what you store yourself, from the day you start | Whatever the store has kept |
| Cost driver | Every request triggers fetches at every retailer | Lookups, plus whatever is refreshed |
Request-time fetching earns its cost when the exact current price decides something right now: confirming a price at checkout, or acting during a short sale. For comparison listings, catalog enrichment, analytics and history, a store with honest timestamps is usually the better fit.
The Data API serves offers from its store: tens of millions of current offers across tens of thousands of retailers. Every offer carries a timestamp field, the time ShopSavvy last saw that price, so you can always tell how fresh it is.
Nothing here is fetched while your request waits, so a lookup never fails because one retailer was slow. The price you get is the last one seen, and the timestamp says when that was.
Scheduling API documentation → What gets refreshed on your cadence, the schedule values, and what it costs.
Decide how old a price may be for each use, and filter on the timestamp before you show or act on it. This works the same for any API that returns a seen-at time per price.
Keep offers seen within a window and pick the cheapest of those.
type Offer = { retailer: string; price: number; timestamp: string }
// Offers seen within maxAgeHours of now, newest first.
function freshOffers(offers: Offer[], maxAgeHours: number, now: Date = new Date()): Offer[] {
const cutoff = now.getTime() - maxAgeHours * 3_600_000
return offers
.filter((offer) => Date.parse(offer.timestamp) >= cutoff)
.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp))
}
// The cheapest offer that is fresh enough, or null when none is.
function cheapestFresh(offers: Offer[], maxAgeHours: number, now: Date = new Date()): Offer | null {
const fresh = freshOffers(offers, maxAgeHours, now)
return fresh.length === 0 ? null : fresh.reduce((best, offer) => (offer.price < best.price ? offer : best))
}A price comparison page might accept a day; a deal alert might want a few hours and say “last checked” next to the price; an analytics job might keep everything and record the age as a column.
How to evaluate a product pricing data API → Due-diligence questions with ShopSavvy’s own answers and where to check them.
Not necessarily. A request-time fetch can fail, get a blocked or regional page, or read a retailer’s own cached page. A stored price with an exact seen-at time can be more useful, because you know its age and can decide whether it is fresh enough.
No. It serves offers from its store, and every offer carries the time ShopSavvy last saw it. Products you schedule are re-checked hourly, daily or weekly at retailers it can re-check through an official retailer API (Amazon and Best Buy today); other retailers update as ShopSavvy sees them.
Read the timestamp on each offer. In the ShopSavvy Data API it is the ISO 8601 time the price was last seen, and price history entries carry the time each change was seen.