# Reading an answer: Scento Perfume API response fields, paging, errors

> Every Scento Perfume API response has folio, lede, detail, scento_page, further_reading, cite and continuation; this page shows each field, how to page with continuation, the lang values and the 400 invalid_input error.

Source of truth: https://www.scento.com/developers


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

```json
{
  "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](endpoints.md) page.)

## The fields

| Field | Type | What it is |
|---|---|---|
| `folio` | string | Which tool wrote the answer. It matches the name of the equivalent [MCP tool](mcp-server.md#the-twelve-tools). |
| `lede` | string | One sentence you can quote as it stands. |
| `detail` | object | The answer itself. Its fields depend on the route. |
| `scento_page` | object | `label` and `url` of the scento.com page to read on. |
| `further_reading` | list | More `label` and `url` pairs on scento.com. |
| `cite` | string | How to credit the answer: "Scento Perfume API, scento.com". |
| `continuation` | string or null | Pass 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.

```sh
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>"
```

```js
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`.

```json
{
  "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.

```sh
curl -i "https://www.scento.com/api/perfume/v1/edits/nonsense"
```

```json
{
  "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](limits-and-terms.md).
