Developers · read-only
Registry API.
Everything the registry publishes — store profiles, trust scores with per-component breakdowns, catalogs and daily history — is available as JSON, CSV, RSS and SVG. No keys, no signup, CORS open. Published under CC BY 4.0 — reuse it, including commercially, and credit the registry with a link to the store profile.
The data itself — field dictionary, cadence, limits, citation: /dataset · Score methodology: /how-we-score · machine summary for AI crawlers: /llms.txt
GET/api
API index: lists the available endpoints, their parameters and the usage terms.
- endpoints.registry.params
- accepted query params for /api/registry: page (integer, default 1) and niche (beauty-skincare | fashion | supplements | home-kitchen | food-drink).
- id
- the store slug — the stable key for a record. Use this to reference a store.
- code
- display label only (BTY-0042). The prefix follows the niche, so it changes if a store is recategorised — never key on it.
- terms
- CC BY 4.0 — free to use, including commercially, with attribution: a link to the store profile.
- rate limits
- Read endpoints are unmetered; they are edge-cached, so polling them costs you latency rather than access. /api/suggest is the exception — it runs a live query per keystroke and is capped per IP, returning 429 with Retry-After: 10 when you exceed it. Honour Retry-After rather than retrying immediately; there is no key to raise, and no limit that a paid plan would lift, because there are no plans.
- stability
- Field names and shapes are additive: new fields may appear, existing ones are not renamed or removed without a version note. The scoring formula is versioned separately — trust_score and every history row carry rules_version, and what each version changed is listed on /changelog. Current: rules v0.8.
shape example (truncated)
{
"name": "StoreProfiles Registry API",
"description": "Public, read-only access to the independent registry…",
"endpoints": {
"registry": {
"url": "https://storeprofiles.com/api/registry",
"params": {
"page": "integer, default 1 (50 per page)",
"niche": "beauty-skincare | fashion | supplements | home-kitchen | food-drink"
}
},
"store": { "url": "https://storeprofiles.com/api/store/{slug}" }
},
"terms": "CC BY 4.0 — attribution: link to the store profile"
}GET/api/registry
Paginated list of every store on record, 50 per page, ranked by trust score. Filters: ?page=2, ?niche=fashion.
- meta
- total (count of live stores), page, per_page (50), niche (null when unfiltered).
- stores[].code
- registry record code — niche prefix + id, e.g. BTY-0042. Display-only, stable.
- stores[].claimed
- true once the owner verified domain control via meta tag. Adds +15 to the score (rules v0.8), never editing rights.
- stores[].trust_score
- integer 0–100, computed from the store's public product feed. Null while the first audit is in preparation.
- stores[].profile / api
- canonical URLs of the human profile page and this store's JSON endpoint.
shape example (truncated)
{
"meta": { "total": 599, "page": 1, "per_page": 50, "niche": null },
"stores": [
{
"code": "BTY-0042",
"slug": "example-beauty",
"name": "Example Beauty Co.",
"domain": "examplebeauty.com",
"niche": "beauty-skincare",
"claimed": false,
"trust_score": 78,
"product_count": 100,
"profile": "https://storeprofiles.com/store/example-beauty",
"api": "https://storeprofiles.com/api/store/example-beauty",
"updated_at": "2026-07-18T04:12:09.000Z"
}
]
}GET/api/store/{slug}
One store in full: profile, score breakdown, catalog stats, AI audit, up to 12 products and daily history. 404 { "error": "not_on_record" } for unknown or dead stores.
- verdict
- a ready-to-quote sentence answering "is {store} legit": the trust score plus the strongest pro and main caveat, computed from public data. Null before the first audit. Same text the profile exposes to answer engines.
- niche_percentile
- the store's standing among audited peers in its niche, 0–100 ("higher than N% of niche stores"). Null when the niche has fewer than 8 scored stores.
- score_breakdown
- the trust-score receipt, one {got, max} pair per component: on_record (5), catalog_depth (≤25), images (≤15), descriptions (≤12), pricing_data (≤8), claimed (15) plus verified_signals (≤20), the verified tier from collected external facts (policies, reviews, speed). The maxima sum to exactly 100 and the components sum to trust_score — no separate cap since rules v0.7, and since v0.8 verified_signals is only added when the catalog clears a quality bar. Same formula as /how-we-score.
- catalog
- product_count plus min_price, avg_price and currency computed from priced products only.
- review
- latest versioned AI audit: model, version, pros/cons (each point cites its source), who_for, created_at. Null before the first audit.
- owner_response
- the owner's public reply to the audit ({text, at}), or null. Replying never edits the audit itself.
- top_products
- up to 12 products: title, price, currency, image_url, url, product_type.
- history
- daily snapshots (up to 365): day (YYYY-MM-DD), product_count, avg_price, min_price, trust_score, rules_version — chart-ready trend data. Compare trust_score only across snapshots sharing a rules_version: a formula change is our step, not the store's.
- partner_program
- {active: false}, or {active: true, commission_pct, notes} once the owner enabled it in the dashboard.
shape example (truncated)
{
"code": "BTY-0042",
"slug": "example-beauty",
"name": "Example Beauty Co.",
"domain": "examplebeauty.com",
"niche": "beauty-skincare",
"claimed": false,
"profile": "https://storeprofiles.com/store/example-beauty",
"badge": "https://storeprofiles.com/badge/example-beauty",
"trust_score": 64,
"verdict": "Is Example Beauty Co. legit? Yes — independent trust score 64/100, computed from public data, not paid reviews. Strongest signal: deep catalog…",
"niche_percentile": 74,
"score_breakdown": {
"on_record": { "got": 5, "max": 5 },
"catalog_depth": { "got": 21, "max": 25 },
"images": { "got": 13, "max": 15 },
"descriptions": { "got": 9, "max": 12 },
"pricing_data": { "got": 8, "max": 8 },
"claimed": { "got": 0, "max": 15 },
"verified_signals": { "got": 8, "max": 20 }
},
"catalog": {
"product_count": 100,
"min_price": "9.00",
"avg_price": "24.85",
"currency": "USD"
},
"review": {
"model": "claude-sonnet",
"version": 3,
"pros": [{ "point": "…", "source": "products.json" }],
"cons": [{ "point": "…", "source": "products.json" }],
"who_for": "…",
"created_at": "2026-07-15T02:00:11.000Z"
},
"owner_response": null,
"top_products": [
{
"title": "Vitamin C Serum",
"price": "24.00",
"currency": "USD",
"image_url": "https://cdn.shopify.com/…/serum.jpg",
"url": "https://examplebeauty.com/products/vitamin-c-serum",
"product_type": "Serum"
}
],
"history": [
{
"day": "2026-07-17",
"product_count": 100,
"avg_price": "24.85",
"min_price": "9.00",
"trust_score": 78,
"rules_version": "v0.8"
}
],
"partner_program": { "active": false },
"data_updated": "2026-07-18T04:12:09.000Z"
}GET/badge/{slug}
Embeddable SVG trust badge (200×52): "TRUST 78/100" with a score bar, or "ON RECORD" while the score is pending. Cached 24 h; 404 for stores not on record.
- response
- image/svg+xml — drop it into an <img> tag. Stores embed it on their own site; every badge links back to the live profile, so the number can't go stale or be faked.
embed example
<a href="https://storeprofiles.com/store/example-beauty">
<img src="https://storeprofiles.com/badge/example-beauty"
width="200" height="52"
alt="StoreProfiles trust 78/100" />
</a>GET/feed.xml
RSS 2.0 feed of registry activity: the 25 most recent audits (one item per audit) plus one synthetic weekly-digest item, so feed readers and monitoring tools catch new audits without polling the JSON API.
- item (audit)
- title “{store} audited — {score}/100”, link to the profile, stable guid per audit, and a description quoting the audit's first pro and con, each with its source.
- item (weekly)
- one “This week in the registry — {ISO week}” item with live counts of audits published, stores claimed and partners queued since Monday; links to /weekly.
- headers
- Content-Type application/rss+xml, hourly cache.
GET/registry.csv
The whole live registry as one CSV download (Content-Disposition: attachment; filename registry-YYYY-MM-DD.csv) — ready for spreadsheets, pandas or BI tools.
- columns
- slug, name, domain, niche, status, trust_score, products, distinct_products, min_price, currency, claimed, profile_url. One row per live store, ranked by trust score.
- min_price / currency
- entry price — the cheapest product priced at 2 or above in the store's modal (most common) currency; the currency column is that modal currency. Same rule the niche reports use, so mixed-currency catalogs never distort the number.
- escaping
- RFC 4180 — names containing commas, quotes or newlines arrive quoted, inner quotes doubled.
shape example (first rows)
slug,name,domain,niche,status,trust_score,products,distinct_products,min_price,currency,claimed,profile_url example-beauty,"Example Beauty, Co.",examplebeauty.com,beauty-skincare,ingested,78,100,86,9.00,USD,false,https://storeprofiles.com/store/example-beauty
Terms of use, in plain words
- CORS is open — every endpoint sends
Access-Control-Allow-Origin: *, so browser apps can call it directly. - Responses are cached for an hour (the badge for 24 h). Data refreshes on the daily ingest, so polling more often than hourly buys nothing.
- No auth, no keys — and no uptime or rate-limit promises. Be gentle; abusive traffic gets blocked without ceremony.
- Where the data comes from:the stores' own public product feeds. Every number is checkable at its source — see /how-we-score.
- Scores are computed, never sold. No store can pay to be listed, scored, or ranked — and the API returns the same numbers the profile pages show.