Concepts
The few ideas every endpoint, alert and webhook is built on. Read this once and the rest of the API reads plainly.
Sources
A source is one online store we read: nearly always a brand's own. It has a short name
(source, such as source_3) that every record and filter uses, and a display name.
GET /api/v1/sources lists every source we read, with its kind. The ones your plan opens come
first, with their counts and when each was last checked (last_checked). The rest are listed by
name and size only, with open: false. Asking for a locked source by name is refused with
402 source_locked.
Products and variants
A product is one model at one source: its name, brand, category, description, images and page. A variant is one colour or size of it. Each variant has its own price, list price, stock and specs, so a price or a stock change always belongs to a variant.
- Ids are UUIDs, and stay the same for as long as we track the product: store them to recognise a product or variant on your side.
- Lists give a product's price as a range across its variants (
price_fromtoprice_to). One product's page gives every variant. - Specs (such as weight, dimensions and material) are what the source states. What it does not state is left out, never guessed.
Markets and money
Every price is in the source's own market: region is a country code (ISO 3166-1, such as US)
and currency a currency code (ISO 4217, such as USD). Prices are never converted, and never
compared across currencies.
| Field | Example | What it is |
|---|---|---|
price | "229.00" | The price now, as an exact decimal string. |
price_minor | 22900 | The same in minor units (cents): an integer, safe to add up. |
list_price | "249.00" | The price before any sale, as the source states it. |
on_sale | true | The price is below the list price. |
discount_pct | 8 | How far below, in whole percent. |
Use the string or the integer, not a float: 0.1 + 0.2 is not 0.3 in floating point.
Time and freshness
Every time is ISO 8601 in UTC, ending in Z. first_seen_at is when we first read a product,
observed_at when a price was read, and occurred_at when a change was found.
Most sources are read about every two hours. A read that fails, or that a store blocks, records nothing: no change, and never "out of stock". The last known values stay, so missing data and a real change are never confused.
Changes (events)
Each change is an event with an id. Ids rise in the order events are recorded, which is how the feed is followed (Pagination). An event exists only when the change was stored, and is never edited afterwards. There are ten kinds, in three groups:
| type | Group | Means |
|---|---|---|
new_product | assortment | A product appeared on a source. |
new_variant | assortment | A product gained a colour or size. |
price_down | price | A variant's price fell. |
price_up | price | A variant's price rose. |
sale_started | price | A variant went on sale: its price is now below its list price. |
sale_ended | price | A variant came off sale. |
back_in_stock | stock | A variant that was out of stock can be bought again. |
out_of_stock | stock | A variant sold out. |
product_gone | assortment | A product left its source. |
product_back | assortment | A product that had left its source is listed again. |
A product counts as gone (product_gone) only after it has been missing from complete reads of its
store for about a day and a half, so a page that failed to load once is not a product that left.
GET /api/v1/event-types returns this list, and needs no key.
Alerts
An alert is a saved filter on the feed. Its matches show on your account's Alerts page and at
GET /api/v1/alerts/feed, and with "channel": "webhook" each is also posted to your address
(Webhooks). Every field is optional: left out, it matches any source, category,
product and kind of change.
- Make one with
POST /api/v1/alerts; change one withPATCH /api/v1/alerts/{alert_id}, sending only the fields to change. max_priceneeds acurrency.{"status": "paused"}stops an alert;"active"starts it again.
A new alert's webhook hears of what happens from then on (last_event_id), not of the past.
Plans and what you can read
Your plan decides which sources are open; every feature works on every plan. Lists and the feed
include only open sources, and naming a locked one is refused with 402. Limits per plan are in
Errors & limits.