Perfume API docs scento.com/developers

Reading an answer

Every route returns the same outer shape, called a folio. Only detail changes from route to route.

{
  "folio": "perfume-portrait",
  "lede": "Layton by Parfums de Marly belongs to Scento's Wood & Root family: ...",
  "detail": { "name": "Layton", "house": "Parfums de Marly", "pyramid": { "top": ["Apple"], "heart": ["Lavender"], "base": ["Patchouli"] } },
  "scento_page": { "label": "Layton on Scento", "url": "https://www.scento.com/perfumes/layton-parfums-de-marly" },
  "further_reading": [ { "label": "Parfums de Marly on Scento", "url": "https://www.scento.com/brand/parfums-de-marly" } ],
  "cite": "Scento Perfume API, scento.com",
  "continuation": null
}

(Shortened for reading. Live, trimmed responses for every route are on the Endpoints page.)

The fields

FieldTypeWhat it is
foliostringWhich tool wrote the answer. It matches the name of the equivalent MCP tool.
ledestringOne sentence you can quote as it stands.
detailobjectThe answer itself. Its fields depend on the route.
scento_pageobjectlabel and url of the scento.com page to read on.
further_readinglistMore label and url pairs on scento.com.
citestringHow to credit the answer: "Scento Perfume API, scento.com".
continuationstring or nullPass it back to get the next part of a list. null when the list is complete.

Paging through lists

Search and list routes return ten entries at a time. When there is more, continuation holds an opaque value. Send it back unchanged as the continuation query parameter, with the same other parameters.

curl "https://www.scento.com/api/perfume/v1/search?q=oud&kind=perfume"
# ... "continuation": "<value>"
curl "https://www.scento.com/api/perfume/v1/search?q=oud&kind=perfume&continuation=<value>"
let continuation = null;
const matches = [];
do {
  const url = new URL("https://www.scento.com/api/perfume/v1/search");
  url.searchParams.set("q", "oud");
  if (continuation) url.searchParams.set("continuation", continuation);
  const page = await (await fetch(url)).json();
  matches.push(...page.detail.matches);
  continuation = page.continuation;
} while (continuation && matches.length < 50);

Treat the value as opaque: do not decode or build it yourself.

Language

lang accepts en, de, fr, es, it, ro, el, hu, cs and pl. The answer text is always English. lang changes the language of the scento.com links and labels in scento_page and further_reading.

Unknown names

A perfume, house, material or term that is not in the database is not an error. The API answers 200 with detail.found set to false and a list of suggestions.

{
  "folio": "perfume-portrait",
  "lede": "“nope xyz” is not in Scento's perfume database yet.",
  "detail": { "query": "nope xyz", "found": false, "suggestions": [] },
  "scento_page": { "label": "Perfumes on Scento", "url": "https://www.scento.com/perfumes" },
  "further_reading": [],
  "cite": "Scento Perfume API, scento.com",
  "continuation": null
}

Errors

Input the API cannot use, such as a value outside a fixed list, returns 400 with an error object.

curl -i "https://www.scento.com/api/perfume/v1/edits/nonsense"
{
  "error": {
    "code": "invalid_input",
    "message": "\"occasion\" must be one of: office, date-night, night-out, everyday, ..."
  }
}

The message names the allowed values, so it is safe to show to a developer. Check res.ok before you read the body as a folio.

Crediting an answer

Each answer carries a scento_page link and a cite line. Quote the lede as it stands and link the page so readers can go deeper. See Limits and terms.

Markdown copy of this page