Findcheap API

The Findcheap API has two capabilities:

  1. Extract — takes a product page URL as input and returns structured product data from the page.
  2. Search — takes a product page URL as input and searches the internet to find where the product is available for a lower price. For some products, the agent only returns top-level data, and a subsequent call to the Resolve endpoint is needed if further details are desired.

Every call is an HTTPS POST with a JSON body and a JSON answer.

Authentication

Every request carries an API key in the Authorization header. Keys begin with fc_live_ and are issued on request from the access page.

HTTP header
Authorization: Bearer fc_live_xxxxxxxxxxxxxxxx

A request without a valid key is answered 401. The key goes in the header only; it is not accepted in the URL.

Markets

Every call runs in a market, the country where the shopper is located. The agent reads the product page from the country specified in the market param. This is important to note because many stores show different product details to users from different countries (ex. different prices and currencies).

Set it with the market field. If left unspecified, the agent uses the page’s TLD to determine its market (.in → India, .co.uk → UK, .com.au → Australia, .ca → Canada); all other addresses default to the US.

The table below shows each market, its corresponding currency, and the primary marketplaces the agent searches in that market when Search is called.

marketCurrencyMarketplaces Search compares against
USUSDAmazon, Walmart, eBay, AliExpress, Shein, and other sites
CACADAmazon, AliExpress, other sites
AUAUDAmazon, eBay, AliExpress, other sites
ININRAmazon, Flipkart, other sites
GLOBALUSDAmazon, eBay, AliExpress, other sites; the page is fetched from the store's own country when its address names one

Extract

POST/v1/extract

The Extract endpoint takes a product page URL as input and returns structured product identity data. It answers within 30 seconds, and has a median response time of 4 seconds. A page that cannot be reached in time answers 502 unreachable, and a page that is reached but cannot be read in time answers 504 timeout.

Request body

url
string · required

The product page’s address, https only. A short link or a share link is followed to the page it names.

market
string · optional

"US", "CA", "AU", "IN" or "GLOBAL". If omitted, the market is inferred from the URL; otherwise, it defaults to US (see Markets).

Response

FieldTypeMeaning
is_product_pagebooleantrue when the address is one product's own page. false for a home page, a category or search page, a cart, an article, or a page that is gone; the other fields are then null.
urlstringThe page the read ended on, after any redirects.
marketstringThe market the page was read in.
titlestring | nullThe product's name as the page states it.
imagestring | nullThe image address of the main product photo.
pricenumber | nullThe standing price a shopper in the market pays: not a first-order, coupon or membership price. null when the page does not show one.
currencystring | nullISO 4217 code of price.
brandstring | nullThe brand, when the page names it.
in_stockboolean | nulltrue when the page says the product can be bought now, false when it is out of stock or discontinued, null when the page does not say.
reasonstring | nullWhy a read fell short: gone (the store says the page no longer exists), not_a_product_page, incomplete (a product page whose title or photo could not be read), price_in_another_currency (the price shown was another market's version and was withheld). null on a clean read.

A page that could not be fetched at all is not a 200: it is a 502 unreachable, so you can tell “gone” from “try again later”.

Example call

# -H adds a header (your key, then the body's format); -d is the JSON body.
# market is the shopper's country; omit it and the address decides (see Markets).
curl https://api.findcheap.ai/v1/extract \
  -H "Authorization: Bearer $FINDCHEAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.wearcomet.com/products/astra-burnt-toast", "market": "IN"}'

Example response

200 OK
{
  "is_product_page": true,
  "url": "https://www.wearcomet.com/products/astra-burnt-toast",
  "market": "IN",
  "title": "Astra BURNT TOAST",
  "image": "https://www.wearcomet.com/cdn/shop/files/...",
  "price": 4899.0,
  "currency": "INR",
  "brand": "wearcomet",
  "in_stock": true,
  "reason": null
}

Resolve

POST/v1/resolve

For some results, the Search endpoint only returns top-level data, to maximize search efficiency. These results carry a resolve_id instead of a url. Calling the Resolve endpoint with a resolve_id returns a direct link to the corresponding product on the merchant’s website and the merchant’s name.

An id is valid for up to two hours after the search that produced it. In rare cases, it may expire sooner, so it is advised to resolve any desired ids shortly after the search has completed.

Request body

id
string · required

The card’s resolve_id.

Response

FieldTypeMeaning
resolvedbooleantrue when url holds the retailer's link.
urlstring | nullThe product's direct link on the merchant's website, tracking parameters stripped. null when not resolved.
retailerstring | nullThe merchant's name, e.g. "B&H Photo". null when not resolved.

An id that is unknown, expired, or could not be resolved answers { "resolved": false, "url": null, "retailer": null } with a 200; it is never an error.

Example call

# The id is a Search card's resolve_id (a card whose url is null).
curl https://api.findcheap.ai/v1/resolve \
  -H "Authorization: Bearer $FINDCHEAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": "7c1f0e2b4d9a4f3e8b6a2c5d9e1f0a3b"}'

Example response

200 OK
{ "resolved": true, "url": "https://www.bhphotovideo.com/c/product/...", "retailer": "B&H Photo" }

Errors

Every error is an HTTP status with one JSON shape:

Error shape
{
  "error": {
    "type": "not_searchable",
    "message": "The address is not a readable product page (not_a_product_page)."
  }
}
StatusTypeMeaning
400invalid_requestA malformed body or a missing field; the message names it.
400invalid_urlThe address is not an https page address.
400unknown_marketmarket is not one of US, CA, AU, IN, GLOBAL.
401unauthorizedNo key, or a key that is not valid.
422not_searchableSearch: the address is not a readable product page; the message names the reason.
422refusedSearch: a used-condition search on grocery or consumable products, or one with no determinable brand.
429rate_limitedThis key is over one of its limits. Retry after the number of seconds in the Retry-After header.
502unreachableThe page could not be fetched right now; the store refused or did not answer. A retry later may succeed.
504timeoutThe call ran past its time limit on our side: 30 seconds for Extract (the page was reached but not read in time), 90 seconds for Search. Safe to retry.
500search_failedSomething failed on our side. Safe to retry with backoff.

Rate limits

The rate limits for each plan are listed on the developers page.