Fetch an Amazon product by ASIN with one POST to https://api.scavio.dev/api/v1/amazon/product, then run your own sentiment and price-position logic over the returned title, price, rating, and review text. Raw scraped data on its own answers nothing. A founder on r/SideProject got that feedback after launching an Amazon product API: people don't want "another search endpoint," they want sentiment aggregated across reviews, price-trend flags, and positioning signals. This tutorial shows the four steps that turn one structured product response into a small decision report. The sentiment step is a heuristic you run on real returned text, not a model with a benchmarked accuracy number. The whole loop is one paid call (the Amazon product fetch at 1 credit) plus your own code, with an optional Google Shopping cross-check at the end. You decide how strict the rules are. The point is that the API gives you clean fields to reason over, and the reasoning is yours to own.
Prerequisites
- A Scavio API key (50 free credits on signup, no card). Send it as Authorization: Bearer {API_KEY}.
- An Amazon ASIN to inspect (the 10-character code in the product URL, e.g. B08N5WRWNW).
- Python 3.9+ or Node 18+ with a way to POST JSON (requests / fetch).
- Optional: an LLM key if you want to replace the lexicon pass in step 2 with a model pass.
Walkthrough
Step 1: 1. Get the product by ASIN
POST the ASIN as query to the Amazon product endpoint. It costs 1 credit and returns the title, current price, aggregate rating, review count, and a set of individual review texts. This is the structured payload everything else runs on, so capture it once and reuse it.
curl -X POST https://api.scavio.dev/api/v1/amazon/product \
-H "Authorization: Bearer $SCAVIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "B08N5WRWNW"}'Step 2: 2. Aggregate review sentiment (heuristic)
Run a simple positive/negative lexicon over each returned review string, or send the same texts to an LLM in one pass. Count how many reviews lean positive, negative, or neutral, and surface the words driving the negatives. Treat this as a directional heuristic on real text, not a calibrated score. Don't report an accuracy percentage you didn't measure. The signal you want is the shape of the breakdown and the recurring complaint terms, which is what a buyer-intent decision actually needs.
POS = {"great", "love", "perfect", "works", "quality", "easy"}
NEG = {"broke", "cheap", "return", "stopped", "disappointed", "slow"}
def classify(text):
t = text.lower()
p = sum(w in t for w in POS)
n = sum(w in t for w in NEG)
if p > n: return "positive"
if n > p: return "negative"
return "neutral"
reviews = [r["text"] for r in product["reviews"]]
breakdown = {"positive": 0, "negative": 0, "neutral": 0}
for r in reviews:
breakdown[classify(r)] += 1Step 3: 3. Flag price position
Compare the live price against the rating and review volume from the same response. A high price with a low rating and few reviews is a weak position; a competitive price with a strong rating and high review count is a strong one. Encode that as a simple rule so the output is a flag a human or agent can act on, not a raw number.
def price_flag(price, rating, n_reviews):
if rating >= 4.3 and n_reviews >= 500:
return "strong" if price <= 50 else "premium-justified"
if rating < 3.8 or n_reviews < 50:
return "weak"
return "neutral"
flag = price_flag(product["price"], product["rating"], product["review_count"])Step 4: 4. (Optional) Cross-check demand on Google Shopping
POST the product title to https://api.scavio.dev/api/v1/google to see whether it surfaces in Shopping and organic results, which hints at competing listings and live demand. Use light_request: false for full SERP features (2 credits) or the light path (1 credit) if you only need organic links. This is a sanity check on the Amazon-only view, not a replacement for it.
curl -X POST https://api.scavio.dev/api/v1/google \
-H "Authorization: Bearer $SCAVIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "Echo Dot 5th gen", "light_request": false}'Python Example
import os, requests
KEY = os.environ["SCAVIO_API_KEY"]
HEAD = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
# 1. Product by ASIN (1 credit)
product = requests.post(
"https://api.scavio.dev/api/v1/amazon/product",
headers=HEAD, json={"query": "B08N5WRWNW"},
).json()
# 2. Sentiment heuristic over real returned review text
POS = {"great", "love", "perfect", "works", "quality", "easy"}
NEG = {"broke", "cheap", "return", "stopped", "disappointed", "slow"}
def classify(text):
t = text.lower()
p, n = sum(w in t for w in POS), sum(w in t for w in NEG)
return "positive" if p > n else "negative" if n > p else "neutral"
reviews = [r["text"] for r in product.get("reviews", [])]
breakdown = {"positive": 0, "negative": 0, "neutral": 0}
for r in reviews:
breakdown[classify(r)] += 1
# 3. Price-position flag
def price_flag(price, rating, n):
if rating >= 4.3 and n >= 500:
return "strong" if price <= 50 else "premium-justified"
if rating < 3.8 or n < 50:
return "weak"
return "neutral"
flag = price_flag(product["price"], product["rating"], product["review_count"])
print({
"asin": "B08N5WRWNW",
"title": product["title"],
"price": product["price"],
"rating": product["rating"],
"reviews_sampled": len(reviews),
"sentiment": breakdown,
"price_position": flag,
"note": "sentiment is a lexicon heuristic, not a benchmarked score",
})JavaScript Example
const KEY = process.env.SCAVIO_API_KEY;
const HEAD = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };
// 1. Product by ASIN (1 credit)
const product = await (await fetch("https://api.scavio.dev/api/v1/amazon/product", {
method: "POST", headers: HEAD, body: JSON.stringify({ query: "B08N5WRWNW" }),
})).json();
// 2. Sentiment heuristic over real returned review text
const POS = ["great", "love", "perfect", "works", "quality", "easy"];
const NEG = ["broke", "cheap", "return", "stopped", "disappointed", "slow"];
const classify = (text) => {
const t = text.toLowerCase();
const p = POS.filter((w) => t.includes(w)).length;
const n = NEG.filter((w) => t.includes(w)).length;
return p > n ? "positive" : n > p ? "negative" : "neutral";
};
const reviews = (product.reviews || []).map((r) => r.text);
const breakdown = { positive: 0, negative: 0, neutral: 0 };
for (const r of reviews) breakdown[classify(r)]++;
// 3. Price-position flag
const priceFlag = (price, rating, n) => {
if (rating >= 4.3 && n >= 500) return price <= 50 ? "strong" : "premium-justified";
if (rating < 3.8 || n < 50) return "weak";
return "neutral";
};
const flag = priceFlag(product.price, product.rating, product.review_count);
console.log({
asin: "B08N5WRWNW",
title: product.title,
price: product.price,
rating: product.rating,
reviews_sampled: reviews.length,
sentiment: breakdown,
price_position: flag,
note: "sentiment is a lexicon heuristic, not a benchmarked score",
});Expected Output
{
"asin": "B08N5WRWNW",
"title": "Echo Dot (5th Gen)",
"price": 49.99,
"rating": 4.6,
"reviews_sampled": 20,
"sentiment": { "positive": 14, "negative": 3, "neutral": 3 },
"price_position": "premium-justified",
"note": "sentiment is a lexicon heuristic, not a benchmarked score"
}