curl --request GET \
--url https://api.syntalic.com/v1/shopper/best-priceimport requests
url = "https://api.syntalic.com/v1/shopper/best-price"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.syntalic.com/v1/shopper/best-price', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.syntalic.com/v1/shopper/best-price",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.syntalic.com/v1/shopper/best-price"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.syntalic.com/v1/shopper/best-price")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.syntalic.com/v1/shopper/best-price")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"query": "<string>",
"dropped_terms": [
"<string>"
],
"country": "<string>",
"currency": "<string>",
"product_uid": "<string>",
"entity_uid": "<string>",
"scope": "entity",
"member_count": 123,
"match_suspect": true,
"retailers_compared": 123,
"resolved_product": {},
"gpc": {},
"best_price": {
"product_uid": "<string>",
"entity_uid": "<string>",
"product_name": "<string>",
"retailer": "<string>",
"price": 123,
"list_price": 123,
"savings_pct": 123,
"in_stock": true,
"condition": "new",
"match_type": "entity",
"scraped_at": "2023-11-07T05:31:56Z"
},
"other_prices": [
{
"product_uid": "<string>",
"entity_uid": "<string>",
"retailer": "<string>",
"product_name": "<string>",
"price": 123,
"in_stock": true,
"condition": "new",
"match_type": "entity",
"observed_at": "2023-11-07T05:31:56Z"
}
],
"related_matches": [
{
"product_uid": "<string>",
"entity_uid": "<string>",
"retailer": "<string>",
"product_name": "<string>",
"price": 123,
"in_stock": true,
"condition": "new",
"match_type": "entity",
"observed_at": "2023-11-07T05:31:56Z"
}
],
"meta": {
"served_from": "<string>",
"freshness_seconds": 123,
"schema_version": "<string>",
"computed_at": "2023-11-07T05:31:56Z",
"price_observed_at_min": "2023-11-07T05:31:56Z",
"price_observed_at_max": "2023-11-07T05:31:56Z"
}
}{
"type": "<string>",
"title": "Bad Request",
"status": 400,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Payment Required",
"status": 402,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Not Found",
"status": 404,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Too Many Requests",
"status": 429,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Internal Server Error",
"status": 500,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}Find the best price for a product across retailers
Returns a nullable gpc block identifying the resolved product’s GS1 GPC product type (code, title, full ancestry, and how exact the mapping is) — null when the product’s category has no GPC mapping. Find the lowest current price for a product across retailers in US and Canada. Cross-retailer comparison is entity-matched (barcode-anchored resolution links the same physical product across platforms). Returns the cheapest option plus other retailer prices for comparison. Every price row is labeled match_type: ‘entity’ (verified same product) or ‘title’ (text match — may be a variant on broad queries); pass strict=true to restrict the comparison to entity-verified rows only. Comparison rows carry observed_at so mixed-vintage prices are distinguishable.
curl --request GET \
--url https://api.syntalic.com/v1/shopper/best-priceimport requests
url = "https://api.syntalic.com/v1/shopper/best-price"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.syntalic.com/v1/shopper/best-price', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.syntalic.com/v1/shopper/best-price",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.syntalic.com/v1/shopper/best-price"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.syntalic.com/v1/shopper/best-price")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.syntalic.com/v1/shopper/best-price")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"query": "<string>",
"dropped_terms": [
"<string>"
],
"country": "<string>",
"currency": "<string>",
"product_uid": "<string>",
"entity_uid": "<string>",
"scope": "entity",
"member_count": 123,
"match_suspect": true,
"retailers_compared": 123,
"resolved_product": {},
"gpc": {},
"best_price": {
"product_uid": "<string>",
"entity_uid": "<string>",
"product_name": "<string>",
"retailer": "<string>",
"price": 123,
"list_price": 123,
"savings_pct": 123,
"in_stock": true,
"condition": "new",
"match_type": "entity",
"scraped_at": "2023-11-07T05:31:56Z"
},
"other_prices": [
{
"product_uid": "<string>",
"entity_uid": "<string>",
"retailer": "<string>",
"product_name": "<string>",
"price": 123,
"in_stock": true,
"condition": "new",
"match_type": "entity",
"observed_at": "2023-11-07T05:31:56Z"
}
],
"related_matches": [
{
"product_uid": "<string>",
"entity_uid": "<string>",
"retailer": "<string>",
"product_name": "<string>",
"price": 123,
"in_stock": true,
"condition": "new",
"match_type": "entity",
"observed_at": "2023-11-07T05:31:56Z"
}
],
"meta": {
"served_from": "<string>",
"freshness_seconds": 123,
"schema_version": "<string>",
"computed_at": "2023-11-07T05:31:56Z",
"price_observed_at_min": "2023-11-07T05:31:56Z",
"price_observed_at_max": "2023-11-07T05:31:56Z"
}
}{
"type": "<string>",
"title": "Bad Request",
"status": 400,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Payment Required",
"status": 402,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Not Found",
"status": 404,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Too Many Requests",
"status": 429,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"type": "<string>",
"title": "Internal Server Error",
"status": 500,
"detail": "<string>",
"instance": "<string>",
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}Query Parameters
Search query (product name, keyword, or brand + model). Required unless product_uid or entity_uid is supplied.
1Stable product identifier returned by a prior Syntalic shopper response. When supplied, the endpoint should pin to this listing instead of re-resolving free text.
1Stable cross-retailer entity identifier returned by a prior Syntalic shopper response. When supplied, the endpoint should resolve within the same physical-product entity.
1Country (us or ca)
us, ca Filter to a specific retailer platform (long-tail specialty stores are also present; any platform key is accepted)
amazon, walmart, target, bestbuy, homedepot, costco, ikea, samsclub, cvs, dillards Max results to return (default 10, min 1, max 50)
1 <= x <= 50When true, restrict the comparison to entity-verified listings of the matched product (match_type 'entity' only). Default false also includes title-match rows — useful for broad queries, but may mix product variants.
Response
Best price result
Non-null when no product matched the query as written and retrieval had to drop these trailing terms to resolve one. Treat the result as an answer to the SHORTENED query: NOBULL Laces black returning these terms as ['black'] means the black variant was not found, only NOBULL Laces.
'entity' = prices span the resolved product's cross-platform entity; 'listing' = the product belongs to no multi-member entity, so only its own listing is priced.
entity, listing True when the pipeline has already flagged this entity as welding together materially different products (intra_entity_incoherent). The comparison set — and therefore the headline price — may span variants that are not substitutes; prefer strict=true or a product_uid when this is set.
Distinct retailers spanned by best_price + other_prices. 1 means no cross-retailer comparison was possible for this product — it is the cheapest listing found, not the cheapest anywhere. Most direct-to-consumer products are sold by a single merchant and can never exceed 1; named-retailer products are roughly 48x likelier to support a real comparison. related_matches are excluded from this count because they are title matches on other entities, not prices for this product.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Title-matched rows OUTSIDE the resolved entity. Not price comparisons for the same product — a cheaper row here may be a different product, and a genuinely identical SKU can also land here when entity resolution split it across retailers.
Show child attributes
Show child attributes
Show child attributes
Show child attributes

