Scento is a perfume e-commerce site, and behind the shop sits a verified database of 1,623 perfumes: full note pyramids, 14 scent families, houses, character descriptions and similarity data. That database is exposed as a public REST API at https://www.scento.com/api/perfume/v1. No API key, no signup, JSON over plain HTTPS. This post walks through the endpoints with real responses, so you can build a perfume search, a "smells like" recommender or a wardrobe planner on top of it.
The full reference lives in the OpenAPI document at https://www.scento.com/api/perfume/v1/openapi.json. A human-readable version is on the Scento developers page.
One envelope, everywhere
Every endpoint returns the same shape, which keeps client code simple:
{ "folio": "perfume-search", "lede": "582 entries in Scento’s verified perfume database match “vanilla”; showing 1–10.", "detail": { "...": "the actual payload" }, "scento_page": { "label": "Vanilla 28 on Scento", "url": "https://www.scento.com/perfumes/vanilla-28-kayali" }, "further_reading": [], "cite": "Scento Perfume API, scento.com", "continuation": "cGVyZnVtZS1zZWFyY2h8MTFqMG9xa3wxMA" } folio names the document kind, lede is a one-sentence summary of the result (handy for chat interfaces and quick debugging), and detail carries the payload. continuation is how you page through long result sets: pass its value back as ?continuation=....
Search
The workhorse is GET /perfumes?q=..., a full-text search across perfumes:
curl -s "https://www.scento.com/api/perfume/v1/perfumes?q=vanilla" Each entry in detail.matches looks like this:
{ "kind": "perfume", "name": "Vanilla 28", "house": "Kayali", "family": "Velvet Sweet", "page": "https://www.scento.com/perfumes/vanilla-28-kayali" } The query "vanilla" alone matches 582 perfumes, from Kayali's Vanilla 28 to Juliette Has a Gun's Vanilla Vibes. The generic GET /search?q=... endpoint searches across all document kinds (perfumes, materials, houses) at once, with a kind filter if you want to pin it.
A single perfume
GET /perfumes/{perfume} returns the full portrait, keyed by a slug:
curl -s "https://www.scento.com/api/perfume/v1/perfumes/vanilla-28-kayali" { "folio": "perfume-portrait", "detail": { "name": "Vanilla 28", "house": "Kayali", "concentration": "eau de parfum", "family": "Velvet Sweet", "notes": ["Vanilla", "Tonka Bean", "Amberwood", "Musk", "Brown Sugar"], "character": "Vanilla orchid and brown sugar lead a deep, sweet blend with tonka absolute, amber woods and a soft layer of musk.", "character_words": ["sweet", "warm", "amber", "musky"], "wears": { "seasons": ["autumn", "winter"], "hours": ["evening", "night"] }, "signature_materials": ["Vanilla", "Tonka Bean", "Brown Sugar"] } } character_words and wears are normalized fields — useful when you're filtering or building facets rather than displaying prose.
Compare two perfumes
GET /contrast?perfumes=a,b puts two fragrances side by side. Here's a runnable JavaScript example using native fetch:
const base = "https://www.scento.com/api/perfume/v1"; async function contrast(a, b) { const res = await fetch(`${base}/contrast?perfumes=${a},${b}`); const { lede, detail } = await res.json(); console.log(lede); console.log("Shared notes:", detail.shared_materials.join(", ")); } await contrast("vanilla-28-kayali", "angels-share-by-kilian"); Output:
Vanilla 28 and Angels' Share share tonka bean, but part ways on character and season. Shared notes: Tonka Bean The detail object also carries a per-axis comparison (house, family, top, heart, base, character), which is exactly what a comparison view needs.
Find similar perfumes
GET /perfumes/{perfume}/neighbours returns structure-sharing fragrances with an explanation of each match:
{ "lede": "193 perfumes share structure with Angels' Share by Kilian Paris; the closest is Portrait Revival, sharing cinnamon, tonka bean and oakwood.", "detail": { "total": 193, "neighbours": [ { "name": "Portrait Revival", "house": "Afnan", "family": "Velvet Sweet", "shared": ["Cinnamon", "Tonka Bean", "Oakwood", "Praline", "Sandalwood"], "difference": "Adds honey and saffron to a similar frame." } ] } } Add same_house=true to stay within one brand — useful for "if you like X, the same house also makes..." features.
Materials and house data
Notes are first-class documents too. GET /materials/{material} returns aliases ("oudh", "agarwood", "aoud"...), what the material smells like, what it pairs well with, and which perfumes showcase it. To find perfumes containing several materials, use GET /materials/match — this Python snippet needs only the standard library:
import json import urllib.request url = "https://www.scento.com/api/perfume/v1/materials/match?materials=vanilla,oud,tobacco&tier=base" with urllib.request.urlopen(url) as res: data = json.load(res) print(data["lede"]) for p in data["detail"]["perfumes"][:3]: print(f'- {p["name"]} by {p["house"]} ({p["family"]})') Output:
2 perfumes in Scento's verified perfume database contain vanilla, oud and tobacco in the base, Voyage Titan pour Homme first. - Voyage Titan pour Homme by Armaf (Amber & Resin) - Alexandria Orientale by Xerjoff (Wood & Root) The tier parameter (top, heart, base, any) filters by pyramid position, and family narrows to one of the 14 scent families. Houses work the same way: GET /houses/{house} returns country, founding year, style description and the house's signature perfumes.
Errors and localization
Invalid input returns a clean 400 with a machine-readable body:
{ "error": { "code": "invalid_input", "message": "\"tier\" must be one of: top, heart, base, any." } } Every endpoint accepts a lang parameter for localized responses, so the same query can serve several locales.
Also in the box
Beyond the endpoints above: GET /families maps the 14-family tree with counts, GET /edits/{occasion} returns curated lists per occasion, GET /wardrobe builds suggestions from loved and avoided materials, and GET /lexicon/{term} and GET /journal cover perfumery vocabulary and editorial content. All are documented in the OpenAPI file.
If your tooling speaks Model Context Protocol, the same database is also exposed as an MCP server at https://www.scento.com/mcp — a dozen read-only tools, likewise without a key.
