MCP and REST
One question, one answer, for agents too
You create the API key on this page. Four steps: the key, the first request, connecting over MCP or REST, and the limits.
- Price reads without a key: 10 requests per minute
- With a key: 60 requests per minute
- MCP server and REST API with the same answers
1. Create an API key
An API key is the password your AI assistant or bot uses to sign in to Fordeal. You get it right away and it is shown only once, so save it.
2. First request
A request for the lowest price of one product, including shipping to the chosen country.
The samples contain a placeholder key. Once you create a key in step 1, yours is filled in. Without a key the request works too, at 10 requests per minute.
Command line: macOS, Linux, Windows 10 or later.
curl -s "https://fordeal.ai/api/v1/deals/best-price?query=Apple%20iPhone%2017%20256%20GB&deliver_to_country=CZ" \
-H "Authorization: Bearer fd_live_YOUR_KEY" \
-H "Accept: application/json"JavaScript with fetch: Node.js 18 or later, or a browser.
const url = new URL("https://fordeal.ai/api/v1/deals/best-price");
url.searchParams.set("query", "Apple iPhone 17 256 GB");
url.searchParams.set("deliver_to_country", "CZ");
const response = await fetch(url, {
headers: { Authorization: "Bearer fd_live_YOUR_KEY", Accept: "application/json" },
});
const answer = await response.json();
console.log(answer.headline, answer.best?.total);Python 3 with the requests library.
import requests
response = requests.get(
"https://fordeal.ai/api/v1/deals/best-price",
params={"query": "Apple iPhone 17 256 GB", "deliver_to_country": "CZ"},
headers={"Authorization": "Bearer fd_live_YOUR_KEY"},
timeout=30,
)
answer = response.json()
print(answer["headline"], (answer.get("best") or {}).get("total"))MCP client configuration, for example Claude Desktop (claude_desktop_config.json), Claude Code (.mcp.json) or Cursor.
{
"mcpServers": {
"fordeal": {
"type": "http",
"url": "https://fordeal.ai/mcp",
"headers": {
"Authorization": "Bearer fd_live_YOUR_KEY"
}
}
}
}Below is one call and its shortened answer. headline is the sentence for a person, best.url leads to the shop through /go, and commission_disclosure must be shown to the buyer.
Example answer (illustrative numbers, not today's price)
{"verdict":"buy_now",
"headline":"Kupte teď v obchodě Datart za 25 990 Kč.",
"sort":"product",
"best":{"shop":{"name":"Datart","trust":"verified","rating":0.96},
"total":{"total":26069,"goods":25990,"shipping":79,"currency":"CZK"},
"captured_at":"2026-09-30T08:00:00Z","url":"https://fordeal.ai/go/2pwgnq5cwj/…"},
"alternatives":{"cheapest_cross_border":{"shop":{"name":"NAY","country":"SK"},"total":{"total":27806}}},
"offers":[…],"history":{"days":90,"lowest":25990,"points":[…]},
"commission_disclosure":"When you buy through a Fordeal link, …"}3. Connect over MCP or REST
Streamable HTTP MCP endpoint; add it to Claude, ChatGPT, Cursor or any MCP client.
Addresses
- MCP endpointhttps://fordeal.ai/mcp
- REST API base URLhttps://fordeal.ai/api/v1
- OpenAPI 3.1https://fordeal.ai/api/openapi.json
- llms.txthttps://fordeal.ai/llms.txt
- MCP manifesthttps://fordeal.ai/.well-known/mcp.json
REST request samples
The same tools over HTTP, documented in the OpenAPI file. Results are stored and shareable at /api/v1/deals/results/{slug}. Every offer also carries marketplace (platform, seller, ships-from country, price type; null for an ordinary shop) and total.shippingSource (offer, shop_rule or unknown: where the shipping cost comes from).
GET https://fordeal.ai/api/v1/deals/best-price?query=Apple%20iPhone%2017%20256%20GB&deliver_to_country=CZ
GET https://fordeal.ai/api/v1/deals/best-price?query=Apple%20iPhone%2017%20256%20GB&deliver_to_country=CZ&sort=total
GET https://fordeal.ai/api/v1/deals/history/apple-iphone-17-256-gb?days=365
GET https://fordeal.ai/api/v1/deals/daily?country=CZ&category=televize
GET https://fordeal.ai/api/v1/deals/search?query=iphone%2017&deliver_to_country=CZ&price_max=30000&in_stock=true&sort=price
GET https://fordeal.ai/api/v1/deals/abroad?query=Apple%20iPhone%2017%20256%20GB&deliver_to_country=CZ
GET https://fordeal.ai/api/v1/deals/shops/compared?deliver_to_country=SK
GET https://fordeal.ai/api/v1/digital/compare?category=ai-chat&deliver_to_country=CZ
GET https://fordeal.ai/api/v1/digital/mobile?country=CZ&data_gb=10&minutes=300&no_commitment=true
GET https://fordeal.ai/api/v1/digital/energy?commodity=electricity&distributor=cez-distribuce&rate=D02d&mwh=2.54. Limits and terms
The limits apply to MCP and REST together.
Reading needs no key. Every answer carries machine-readable prices: amounts as numbers, ISO 4217 currency, captured_at in ISO 8601, stable product and shop slugs.
- Without a key: 10 requests per minute per IP address, MCP and REST together.
- With a key: 60 requests per minute. Generate the key further down this page by entering the agent's name and the owner's e-mail.
- Over the limit the answer is error.code "rate_limited" with retry_after_seconds.
- With the live key fd_live_ you also get a test key fd_test_ for the sandbox (simulated providers and fake money of the hidden marketplace); reading prices needs no test mode.
A key is meant for one agent. By using the API you agree to the terms of use. Rules for every answer
In short
The web page, the REST API and the MCP server return the same data: what a person sees, an agent gets. find_best_price with a query and the buyer's country returns the whole card: verdict, main offer (`best`) with product price, shipping and capture time, alternatives and history. Every answer follows the same rules as the website and carries the commission disclosure, which must be shown to the buyer.
Tools
| compare_internet | In preparation, unverified: the answer carries status: in_preparation and verified: false; present the result as an estimate, never as a recommendation. Home internet tariffs by monthly price: give the technology, speed and optionally the address or postcode; ranked by the monthly price with the commitment and the one-off fees. In preparation. |
|---|---|
| search_products | Filtered product search: query or category plus price range, brand, shops, shop country, in stock, on sale, free shipping, minimum shop rating; sort by product price, price with shipping, discount, number of shops or popularity. |
| cheaper_abroad | Is it cheaper in another country? The lowest home offer next to the lowest cross-border one, the saving and what buying abroad means (warranty, returns, delivery days). |
| list_shops | The shops compared for a country with rating, rating source and trust label, plus the shops waiting for a feed. Answers "can I trust shop X". |
| find_best_price | Text, model, EAN or a product URL plus deliver_to_country (optionally sort=total to rank with shipping). Returns the card. Send the buyer to best.url and tell them the product price, the shipping and when the price was checked. |
| get_product | A product id you already hold (its slug) plus deliver_to_country: the same card as the product page, without reading a query, so it never lands on another variant. product.variant names the storage, colour, model words and family_id. |
| product_variants | The other capacities, colours or sizes of a product, each with a stable id, current, storage, colour, its product price and stock. Pick the exact variant, then call get_product with its id. |
| price_history | Daily lowest price for up to 365 days plus every current offer. Use it to say whether today is a low. |
| daily_deals | Biggest price drops of the last 24 hours at rated shops, per country and category. |
| list_coupons | Coupon codes and promotions of compared shops valid today (from the affiliate network eHUB, refreshed every 3 hours), with the validity, the code and the tracked link. |
| product_rows | The rows above the product list: deals of the day, trending (new and watched), seasonal gift tips by budget and for whom, with their formulas. |
| trending_new_products | The home page's first row: the most searched new products, found by the data (newest model of a line, new in the catalogue, searched, clicked, found on Google, more shops listing it), with the points of every part of the score. |
| most_searched_products | Most searched products in a country over the last 7 days: Google Trends, our searches and clicks, matched to products with a photo and at least two shops; each row carries the date it was computed. |
| compare_mobile | In preparation, unverified: the answer carries status: in_preparation and verified: false; present the result as an estimate, never as a recommendation. Mobile tariffs (Czechia and Slovakia) from the operators' official price lists: give data_gb, minutes and optionally no_commitment, five_g, roaming_eu_gb; the cheapest regular price that covers it comes first. |
| compare_energy | Household electricity and gas in Czechia: give distributor, rate and yearly MWh; offers ranked by the yearly bill with VAT, split into the regulated and the supplier part, each with the supplier's official price list. |
| compare_digital | Digital services by price per month: AI subscriptions, API token prices with the cost of a given usage, picture and video tools, streaming, music, VPN, cloud. Prices from official price lists with source and check date. |
| api_price_breakdown | AI API cost split: input, input read from and written into the cache, output and the total per request and month, the other items of the price list (batch discount, long prompts), source and check date. |
| digital_price_history | Recorded price changes of digital plans (old price, new price, day, source) since tracking_since; nothing back-filled. |
| compare_energy_from_bill | Electricity or gas from the values on a bill: distributor, rate, breaker, consumption and the supplier's prices; the same ranking as the comparison, with the saving against today's price list. POST /digital/energy/bill reads the bill (PDF or photo); the file is not stored. |
| energy_unit_prices | Price of one kWh of electricity and gas with VAT per distribution area: regulated part, supplier price range, one more kWh and the average with fees, from the official price lists. |
| energy_price_history | Household electricity and gas prices per kWh since 2015 as Eurostat publishes them, half-yearly, with the dataset link. |
| energy_suppliers | Every household energy supplier with its products, prices from the official price list with dates, and where its customers find the bill. |
| estimate_appliance_energy | Yearly kWh and cost of a fridge, a washing machine or heating from the energy label or the building's certificate, at today's price of one more kWh. |
| energy_watch_status | State of a fixation-end watcher from the token of its e-mail link. |
| insurance_guide | Insurance as a guide: what to compare for each kind and the insurers' official websites, alphabetical; no price, no ranking, no commission (Fordeal is not an insurance intermediary). |
| price_watch_status | State of one price watch from the link in its e-mail: target, status and when the price last reached it. |
| check_shop_feed | Reads a product feed of a shop (address or file) and reports its health and the first issues with a preview of the products. Nothing is stored. Use it before register_shop. |
| get_shop_registration | Status of a shop registration by its id: the decision, the feed health and the stored feed report. |
| get_shop_feed_diagnostics | The last feed run of a compared shop: how many products were read, what was skipped and why, with the time of the run. |
Actions that write
The tools above only read. The ones below write: report_issue may be called by anyone, the account tools only with the signed-in person's access token (Authorization: Bearer, the token the website holds after the e-mail sign-in link). An agent's API key or no key opens no account, and every read and write applies only to the account of the token.
report_issue | Reports a wrong price, variant, category or shop of one offer. No account needed. |
|---|---|
watch_energy_fixation, confirm_energy_watch, cancel_energy_watch | Fixation-end watcher: the person's e-mail and end date; double opt-in (the person confirms by e-mail), one alert 45 days before the end, cancel link in every mail. |
list_my_price_watches, set_price_watch, update_price_watch, delete_price_watch | The person's price watches: list, create, change the target or pause, delete. |
list_my_favorites, save_favorite, remove_favorite | The person's saved products and digital plans. |
list_my_comparisons, save_comparison, share_comparison, delete_comparison | The person's saved comparisons, and a share link for one. |
Their REST routes: the same tools under /api/v1/me/… (account) and /api/v1/deals/issues.
POST /api/v1/deals/issues report_issue
POST /api/v1/deals/content-notices report_illegal_content
POST /api/v1/digital/energy/watches watch_energy_fixation
POST /api/v1/digital/energy/watches/confirm confirm_energy_watch
POST /api/v1/digital/energy/watches/cancel cancel_energy_watch
GET /api/v1/me/price-watches list_my_price_watches
POST /api/v1/me/price-watches set_price_watch
POST /api/v1/me/price-watches/{id} update_price_watch
POST /api/v1/me/price-watches/{id}/delete delete_price_watch
GET /api/v1/me/favorites list_my_favorites
POST /api/v1/me/favorites save_favorite
POST /api/v1/me/favorites/remove remove_favorite
GET /api/v1/me/comparisons list_my_comparisons
POST /api/v1/me/comparisons save_comparison
POST /api/v1/me/comparisons/{id}/share share_comparison
POST /api/v1/me/comparisons/{id}/delete delete_comparison
GET /api/v1/me/lists list_my_lists
POST /api/v1/me/lists create_list
POST /api/v1/me/lists/{id} update_list
POST /api/v1/me/lists/{id}/delete delete_list
POST /api/v1/me/lists/{id}/items add_to_list
POST /api/v1/me/lists/{id}/items/remove remove_from_list
GET /api/v1/me/profile get_my_profile
POST /api/v1/me/profile update_my_profile
POST /api/v1/me/logout sign_out
POST /api/v1/me/account/delete delete_my_account
POST /api/v1/price-watches/guest watch_product_price
POST /api/v1/price-watches/link manage_price_watch
POST /api/v1/shops/register register_shop
POST /api/v1/deals/shops/verify-ownership verify_shop_domain
GET /api/v1/shops/mine list_my_shops
GET /api/v1/shops/{slug}/statistics get_shop_statistics
POST /api/v1/cooperation/inquiries send_cooperation_inquiry
POST /api/v1/contact/messages send_contact_messageRules every answer follows
- Ranking is by product price (ČNB rate of the day) and shop trust only; the shipping to the country is on every offer separately and sort=total ranks by the sum. No paid placement.
- A shop on the ČOI or SOI risk list is never shown. An unrated shop is never
best. - A price older than 36 hours or an offer with unknown shipping is never
best; every offer carries captured_at and blockers. - Cross-border offers carry cross_border: EU warranty, returns, support languages.
- commission_disclosure is part of every answer and must be shown to the buyer.
Examples: requests and answers
Each call as curl (REST) and as an MCP JSON-RPC body, with the answer shortened (arrays show their first element). The test suite runs every one of them against the application, so the field names here are the real ones.
search_products · Search with paging: products matching a query, with total_matches and offset.
REST
curl -s "https://fordeal.ai/api/v1/deals/search?query=iphone+16+128&deliver_to_country=CZ&limit=2&offset=0"MCP tools/call (POST to the MCP endpoint)
POST https://fordeal.ai/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_products",
"arguments": {
"query": "iphone 16 128",
"deliver_to_country": "CZ",
"limit": 2,
"offset": 0
}
}
}Answer, HTTP 200, shortened
{
"deliver_to": "CZ",
"currency": "CZK",
"total_matches": 40,
"offset": 0,
"products": [
{
"slug": "apple-iphone-16-128-gb",
"name": "Apple iPhone 16 128 GB",
"match": "exact",
"match_note": null,
"total": 22990,
"recommended": true,
"currency": "CZK",
"goods": 22990,
"shipping": 0,
"shipping_known": true,
"in_stock": true,
"shops": 1,
"shop": {
"slug": "planeo-cz",
"name": "Planeo Elektro",
"country": "CZ",
"trust": "rated"
},
"captured_at": "2026-10-12T12:02:37Z"
}
],
"next_actions": [
{
"tool": "find_best_price",
"description": "Every offer of the first product with the verdict.",
"params": {
"query": "Apple iPhone 16 128 GB",
"deliver_to_country": "CZ"
}
}
]
}find_best_price · Lowest product price for a query: verdict, the recommended offer with its source, shipping and capture time, every offer with its blockers.
REST
curl -s "https://fordeal.ai/api/v1/deals/best-price?query=Apple+iPhone+16+128+GB&deliver_to_country=CZ&locale=en"MCP tools/call (POST to the MCP endpoint)
POST https://fordeal.ai/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "find_best_price",
"arguments": {
"query": "Apple iPhone 16 128 GB",
"deliver_to_country": "CZ",
"locale": "en"
}
}
}Answer, HTTP 200, shortened
{
"product": {
"slug": "apple-iphone-16-128-gb",
"name": "Apple iPhone 16 128 GB",
"brand": "Apple",
"category": "mobily",
"variant": {
"id": "apple-iphone-16-128-gb",
"family_id": "line:apple-iphone-16",
"family_kind": "line",
"storage": "128 GB",
"ram": null,
"color": null,
"color_id": null,
"model": [],
"connectivity": [],
"size": null
},
"variants_url": "/api/v1/deals/products/apple-iphone-16-128-gb/variants"
},
"match": "exact",
"match_note": null,
"verdict": "buy_now",
"headline": "Buy now at Planeo Elektro for CZK 22,990 in total.",
"reasons": [
"at_90d_low"
],
"warnings": [
"The shop has customer ratings but no verified-shop badge."
],
"best": {
"offer_id": "f8edb345-e97e-4599-99e3-3c9240481aee",
"shop": {
"slug": "planeo-cz",
"name": "Planeo Elektro",
"country": "CZ",
"trust": "rated",
"rating": 0.84,
"rating_source": "google",
"rating_captured_at": "2026-10-09T11:18:24Z"
},
"title": "Apple iPhone 16 128GB Black",
"source": "scrape",
"source_name": "planeo-cz-page",
"price": 22990,
"currency": "CZK",
"in_stock": true,
"condition": "new",
"delivery_days": null,
"unknown": [
{
"field": "delivery_days",
"reason": "not_stated"
}
],
"total": {
"deliverTo": "CZ",
"currency": "CZK",
"goods": 22990,
"shipping": 0,
"shippingUnknown": false,
"shippingApproximate": false,
"total": 22990,
"fx": null,
"crossBorder": false
},
"url": "https://fordeal.ai/go/7a2gxvdd36/f8edb345-e97e-4599-99e3-3c9240481aee",
"direct_url": "https://www.planeo.cz/apple-iphone-16-128gb-black",
"captured_at": "2026-10-12T12:02:37Z",
"age_hours": 21.6,
"stale": false,
"blockers": []
},
"offers": [
{
"offer_id": "f8edb345-e97e-4599-99e3-3c9240481aee",
"shop": {
"slug": "planeo-cz",
"name": "Planeo Elektro",
"country": "CZ",
"trust": "rated",
"rating": 0.84,
"rating_source": "google",
"rating_captured_at": "2026-10-09T11:18:24Z"
},
"title": "Apple iPhone 16 128GB Black",
"source": "scrape",
"source_name": "planeo-cz-page",
"price": 22990,
"currency": "CZK",
"in_stock": true,
"condition": "new",
"delivery_days": null,
"unknown": [
{
"field": "delivery_days",
"reason": "not_stated"
}
],
"total": {
"deliverTo": "CZ",
"currency": "CZK",
"goods": 22990,
"shipping": 0,
"shippingUnknown": false,
"shippingApproximate": false,
"total": 22990,
"fx": null,
"crossBorder": false
},
"url": "https://fordeal.ai/go/7a2gxvdd36/f8edb345-e97e-4599-99e3-3c9240481aee",
"direct_url": "https://www.planeo.cz/apple-iphone-16-128gb-black",
"captured_at": "2026-10-12T12:02:37Z",
"age_hours": 21.6,
"stale": false,
"blockers": []
}
],
"hidden_risky_shops": 0,
"history": {
"days": 90,
"currency": "CZK",
"lowest": 22990,
"highest": 22990,
"points": [
{
"date": "2026-10-01",
"price": 22990
}
]
},
"deliver_to": "CZ",
"currency": "CZK",
"fx_date": "2026-10-12",
"data_source": "stored",
"refresh_pending": false,
"commission_disclosure": "When you buy through a Fordeal link, the shop pays Fordeal a commission. It does not raise your price and it never affects the order: offers are ranked by product price and shop trust only; shipping is shown separately for each offer."
}get_product · The same card by product id, as the product page shows it.
REST
curl -s "https://fordeal.ai/api/v1/deals/products/apple-iphone-16-128-gb?deliver_to_country=CZ&locale=en"MCP tools/call (POST to the MCP endpoint)
POST https://fordeal.ai/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_product",
"arguments": {
"product": "apple-iphone-16-128-gb",
"deliver_to_country": "CZ",
"locale": "en"
}
}
}Answer, HTTP 200, shortened
{
"product": {
"slug": "apple-iphone-16-128-gb",
"name": "Apple iPhone 16 128 GB",
"brand": "Apple",
"category": "mobily",
"variant": {
"id": "apple-iphone-16-128-gb",
"family_id": "line:apple-iphone-16",
"family_kind": "line",
"storage": "128 GB",
"ram": null,
"color": null,
"color_id": null,
"model": [],
"connectivity": [],
"size": null
},
"variants_url": "/api/v1/deals/products/apple-iphone-16-128-gb/variants"
},
"match": "exact",
"match_note": null,
"verdict": "buy_now",
"headline": "Buy now at Planeo Elektro for CZK 22,990 in total.",
"reasons": [
"at_90d_low"
],
"warnings": [
"The shop has customer ratings but no verified-shop badge."
],
"best": {
"offer_id": "f8edb345-e97e-4599-99e3-3c9240481aee",
"shop": {
"slug": "planeo-cz",
"name": "Planeo Elektro",
"country": "CZ",
"trust": "rated",
"rating": 0.84,
"rating_source": "google",
"rating_captured_at": "2026-10-09T11:18:24Z"
},
"title": "Apple iPhone 16 128GB Black",
"source": "scrape",
"source_name": "planeo-cz-page",
"price": 22990,
"currency": "CZK",
"in_stock": true,
"condition": "new",
"delivery_days": null,
"unknown": [
{
"field": "delivery_days",
"reason": "not_stated"
}
],
"total": {
"deliverTo": "CZ",
"currency": "CZK",
"goods": 22990,
"shipping": 0,
"shippingUnknown": false,
"shippingApproximate": false,
"total": 22990,
"fx": null,
"crossBorder": false
},
"url": "https://fordeal.ai/go/7a2gxvdd36/f8edb345-e97e-4599-99e3-3c9240481aee",
"direct_url": "https://www.planeo.cz/apple-iphone-16-128gb-black",
"captured_at": "2026-10-12T12:02:37Z",
"age_hours": 21.6,
"stale": false,
"blockers": []
},
"offers": [
{
"offer_id": "f8edb345-e97e-4599-99e3-3c9240481aee",
"shop": {
"slug": "planeo-cz",
"name": "Planeo Elektro",
"country": "CZ",
"trust": "rated",
"rating": 0.84,
"rating_source": "google",
"rating_captured_at": "2026-10-09T11:18:24Z"
},
"title": "Apple iPhone 16 128GB Black",
"source": "scrape",
"source_name": "planeo-cz-page",
"price": 22990,
"currency": "CZK",
"in_stock": true,
"condition": "new",
"delivery_days": null,
"unknown": [
{
"field": "delivery_days",
"reason": "not_stated"
}
],
"total": {
"deliverTo": "CZ",
"currency": "CZK",
"goods": 22990,
"shipping": 0,
"shippingUnknown": false,
"shippingApproximate": false,
"total": 22990,
"fx": null,
"crossBorder": false
},
"url": "https://fordeal.ai/go/7a2gxvdd36/f8edb345-e97e-4599-99e3-3c9240481aee",
"direct_url": "https://www.planeo.cz/apple-iphone-16-128gb-black",
"captured_at": "2026-10-12T12:02:37Z",
"age_hours": 21.6,
"stale": false,
"blockers": []
}
],
"hidden_risky_shops": 0,
"history": {
"days": 90,
"currency": "CZK",
"lowest": 22990,
"highest": 22990,
"points": [
{
"date": "2026-10-01",
"price": 22990
}
]
},
"deliver_to": "CZ",
"currency": "CZK",
"fx_date": "2026-10-12",
"data_source": "stored",
"refresh_pending": false,
"commission_disclosure": "When you buy through a Fordeal link, the shop pays Fordeal a commission. It does not raise your price and it never affects the order: offers are ranked by product price and shop trust only; shipping is shown separately for each offer."
}product_variants · The variants of the product with stable ids.
REST
curl -s "https://fordeal.ai/api/v1/deals/products/apple-iphone-16-128-gb/variants?deliver_to_country=CZ&locale=en"MCP tools/call (POST to the MCP endpoint)
POST https://fordeal.ai/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "product_variants",
"arguments": {
"product": "apple-iphone-16-128-gb",
"deliver_to_country": "CZ",
"locale": "en"
}
}
}Answer, HTTP 200, shortened
{
"slug": "apple-iphone-16-128-gb",
"family_id": "line:apple-iphone-16",
"family_kind": "line",
"axes": [
"storage",
"color"
],
"currency": "CZK",
"variants": [
{
"id": "apple-iphone-16-128-gb",
"slug": "apple-iphone-16-128-gb",
"current": true,
"storage": "128 GB",
"size": "128 GB",
"color": null,
"color_id": null,
"total": 22990,
"in_stock": true,
"url": "https://fordeal.ai/en/p/apple-iphone-16-128-gb"
}
]
}price_history · Daily lowest price for 90 days and where each price comes from.
REST
curl -s "https://fordeal.ai/api/v1/deals/history/apple-iphone-16-128-gb?days=90¤cy=CZK"MCP tools/call (POST to the MCP endpoint)
POST https://fordeal.ai/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "price_history",
"arguments": {
"product": "apple-iphone-16-128-gb",
"days": 90,
"currency": "CZK"
}
}
}Answer, HTTP 200, shortened
{
"product": {
"slug": "apple-iphone-16-128-gb",
"name": "Apple iPhone 16 128 GB",
"variant": {
"id": "apple-iphone-16-128-gb",
"family_id": "line:apple-iphone-16",
"family_kind": "line",
"storage": "128 GB",
"ram": null,
"color": null,
"color_id": null,
"model": [],
"connectivity": [],
"size": null
}
},
"history": {
"days": 90,
"currency": "CZK",
"lowest": 22990,
"highest": 22990,
"points": [
{
"date": "2026-10-01",
"price": 22990
}
]
},
"offers": [
{
"shop": "Planeo Elektro",
"shop_slug": "planeo-cz",
"title": "Apple iPhone 16 128GB Black",
"price": 22990,
"currency": "CZK",
"condition": "new",
"source_name": "planeo-cz-page",
"in_history": true,
"captured_at": "2026-10-12T12:02:37Z"
}
]
}compare_digital · Digital services by price per month, each with its official price list and check date.
REST
curl -s "https://fordeal.ai/api/v1/digital/compare?category=ai-chat&deliver_to_country=CZ"MCP tools/call (POST to the MCP endpoint)
POST https://fordeal.ai/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "compare_digital",
"arguments": {
"category": "ai-chat",
"deliver_to_country": "CZ"
}
}
}Answer, HTTP 200, shortened
{
"category": "ai-chat",
"currency": "CZK",
"fx_date": "2026-10-12",
"rows": [
{
"id": "claude-free",
"provider": "Anthropic",
"service": "Claude",
"plan": "Free",
"monthly": {
"amount": 0,
"currency": "EUR"
},
"monthlyLocal": {
"amount": 0,
"currency": "CZK",
"rate": 24.39,
"rateDate": "2026-10-12"
},
"sourceUrl": "https://claude.com/pricing",
"verifiedOn": "2026-10-05"
}
]
}price_history · Unknown product: HTTP 404, error.code not_found.
REST
curl -s "https://fordeal.ai/api/v1/deals/history/no-such-product"MCP tools/call (POST to the MCP endpoint)
POST https://fordeal.ai/mcp
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "price_history",
"arguments": {
"product": "no-such-product"
}
}
}Answer, HTTP 404, shortened
{
"error": {
"code": "not_found",
"message": "unknown product no-such-product",
"fix": "Use `product.slug` from a find_best_price answer."
}
}/deals/search · A wrong parameter: HTTP 400, error.code validation with the list of issues.
REST
curl -s "https://fordeal.ai/api/v1/deals/search?query=iphone&limit=abc"Answer, HTTP 400, shortened
{
"error": {
"code": "validation",
"message": "invalid request: limit: Invalid input: expected number, received string",
"fix": "Fix the listed fields. GET /api/openapi.json documents every parameter.",
"details": {
"issues": [
"limit: Invalid input: expected number, received string"
]
}
}
}/deals/shops/compared · Over the limit: HTTP 429 with Retry-After.
REST
curl -s "https://fordeal.ai/api/v1/deals/shops/compared?country=CZ"Answer, HTTP 429, shortened
{
"error": {
"code": "rate_limited",
"message": "rate limit of 10 requests per minute reached",
"fix": "Wait 42 s and retry (Retry-After). Without an API key the limit is 10 requests per minute per IP address; generate a free key at https://fordeal.ai/agents#klic and send Authorization: Bearer <key> for 60 per minute.",
"details": {
"limit_per_min": 10,
"retry_after_seconds": 42,
"window_seconds": 60,
"limit": 10,
"remaining": 0,
"reset": 42,
"reset_at": "2026-10-28T09:15:00.000Z",
"anonymous": true,
"get_a_key": "https://fordeal.ai/agents#klic"
}
}
}Paging, limits, errors and unknown values
Paging
| search_products and GET /deals/search | limit (1 to 100, default 20) and offset (default 0); total_matches counts every match before paging. |
|---|---|
| GET /deals/products | limit up to 500 and offset; total counts the matching products. facets=true adds brands, shops, price range and attribute values over the whole filtered list. |
| A page past the end returns an empty list with the same total. | |
Limits
| Without a key | 10 requests per minute per IP address, MCP tool calls and REST together. |
|---|---|
| With a key | 60 requests per minute. |
| Over the limit | HTTP 429 with a Retry-After header in seconds, error.code rate_limited and error.details.retry_after_seconds, over MCP too. |
Errors
- Every error has the shape {"error":{"code","message","fix"}}: code is stable and machine-readable, fix says what to change.
- validation 400 (details.issues lists the wrong parameters), country_not_supported 400, invalid_input 400, unauthorized 401, forbidden 403, not_found 404, rate_limited 429, not_available 503.
- Over MCP an error is a tool result with isError: true and the same body in structuredContent.
Unknown values, estimates and stale data
| A value we do not know is null and says why: each offer lists unknown[] (delivery_days not_stated, shipping not_stated or approximate, shop_rating unrated). | |
| total.shippingUnknown true | the total is the goods price only and the offer is never best; total.shippingApproximate true: shipping is the shop's lowest stated rate, an estimate. |
|---|---|
| Every offer carries captured_at and age_hours; stale is true after 36 hours and such an offer is never best; refresh_pending is true while prices are being read again. | |
| match close with match_note | the product is the nearest variant, not the one asked for; product.variant and product_variants give the exact ids. |
| history.since is the first day with data | a 90-day window may hold fewer days. |
Answer fields, estimates and pages
- labels on every offer, the same words the website prints: lowest_price only on the lowest product price among the new offers shown; recommended on the trust-recommended offer when it is not the lowest product price (never call it the cheapest); lowest_verified_total on the cheapest total with a stated (not "from") shipping when it is not the lowest product price.
- shipping_is_estimate true: the shipping is only a "from" rate or unknown, so the total is a lower bound; saving_is_estimate true (an offer's savings_vs_best, recommended_surcharge): the difference rests on such a shipping. Say "estimated saving at the stated minimum shipping", never a certain saving.
- saving_kind is always "estimate" where a saving or difference is stated (an offer's savings_vs_best, recommended_surcharge, a cross-border saving, an energy saving_year): it is a difference at the prices and shipping captured on the days in saving_basis, never a guaranteed result. Write "estimated saving" and name the capture date, not "you save".
- price_verdict {level low|usual|high|short_history|stale, percentile, days, basis} on find_best_price, get_product and price_history rates the latest price against the last 90 days of our own captured daily lows. Under 14 days of history it makes no judgement (short_history); it is never a discount claim.
- daily_deals and GET /deals/daily list the biggest measured drops of the last 24 hours at rated shops, spread over shops and categories (max_per_shop, the website asks 4; also category, country, min_percent); the pool for Slovakia holds the euro shops that deliver there.
- report_issue and POST /deals/issues take the offer_id of the offer in question (from the card), so a wrong price or variant of one row reaches the person who reads the queue with that row; the website has the same report control on every offer row.
- The pages "cheapest X" (/nejlevnejsi/<model>) and "X vs Y" (/srovnani/<a>-vs-<b>) have no endpoints of their own: they read GET /deals/products (query, category, slugs, deliver_to_country; search_products, product_variants), and compare_digital and compare_mobile for services and operators. Ask the same question with the same tools.
- Links to a provider on a /digitalni comparison go through /go/plan/<id>, a counted redirect (plan key, page type, our own page; nothing personal; robots flagged). GET /deals/plan-clicks/{kind}/{id} (kind plan|energy|insurance|mobile) returns the provider URL without counting; an offer's own link is its url (/go/<shop>/<offer_id>).
- GET /deals/coverage (per shop) and GET /deals/coverage/groups (per category group) give today's coverage: products with a stored price, shops pricing and shops waiting for a feed. The numbers change daily, so read them instead of quoting a figure from a document.
