# Developers

> Free perfume API and MCP server: 5 read-only operations (search perfumes, get a perfume, list houses, get a house, store information) at https://parfum1.com/mcp and https://parfum1.com/api/perfume/v1, with an OpenAPI 3.1 file, copy-paste examples and the discovery files.

Documentation index for parfum1: https://parfum1.com/llms.txt

Last updated 5 November 2026

parfum1 has a free, read-only perfume API and MCP server. An agent or an app can search the catalogue, read a perfume with its notes and every decant size, price and stock as the product page shows them, browse the perfume houses and read the delivery, returns, payment and contact facts. No key and no account are needed.

## Connect an MCP client

The MCP server runs at https://parfum1.com/mcp. It is stateless: every request is a JSON-RPC message sent with POST, and every answer is plain JSON, so there is no session to keep. It is read-only and needs no key.

| Setting | Value |
| --- | --- |
| Endpoint | https://parfum1.com/mcp |
| Transport | Streamable HTTP, POST with JSON responses (a GET answers 405) |
| Authentication | None |
| Protocol versions | 2025-11-25, 2025-06-18, 2025-03-26 |
| Methods | initialize, notifications/initialized, ping, tools/list, tools/call |
| Server card | https://parfum1.com/.well-known/mcp/server-card.json |
| Server version | 1.0.0 |

Clients that take a server address only need the endpoint. A client configured with a JSON file usually reads like this:

```json
{
  "mcpServers": {
    "parfum1": {
      "url": "https://parfum1.com/mcp"
    }
  }
}
```

Check the connection and call a tool straight from a terminal:

```bash
curl -s https://parfum1.com/mcp \
  -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"example","version":"1.0.0"}}}'

curl -s https://parfum1.com/mcp \
  -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_perfumes","arguments":{"query":"hacivat","per_page":1}}}'
```

## MCP tools

The server offers 5 tools. All of them are read-only (they carry the readOnlyHint annotation) and each has a JSON Schema for its input. An input mistake or an unknown handle comes back as a tool result marked as an error, with a message that says what to change.

| Tool | What it does | Inputs |
| --- | --- | --- |
| `search_perfumes` | Search the parfum1 catalogue by words in the perfume name, house or scent family (all words must match, accents ignored), optionally within one house. Returns a page of perfumes in popularity order with the starting price, stock, rating and product URL. | `query`, `house`, `page`, `per_page` |
| `get_perfume` | Read one perfume by its handle: name, house, description, top, heart and base notes, and every size (3, 10 and 30 ml) with the price, the struck regular price, price per ml and whether it is in stock, exactly as the product page shows them, plus the full bottle (listed out of stock) and the product URL. | `handle` (required) |
| `list_houses` | List the perfume houses in the catalogue, A to Z, with their handle, whether the house is a niche house, the number of perfumes and the house page URL. Optionally filter by words in the house name. | `query` |
| `get_house` | Read one perfume house by its handle: its introduction, the number of perfumes and the first 50 of them with starting price and stock. Use search_perfumes with the house for the rest. | `handle` (required) |
| `get_store_info` | Read how parfum1 works, with the same facts as its help pages: delivery (dispatch, cost, countries), returns, payment methods, contact details and its own social profiles. Pass a topic for one, or none for all four. | `topic` |

## REST API

The same 5 operations are plain GET requests under https://parfum1.com/api/perfume/v1. Every answer is JSON. The OpenAPI 3.1 description, with schemas and examples, is at https://parfum1.com/openapi.json.

| Operation | Request | Parameters |
| --- | --- | --- |
| `searchPerfumes` | GET https://parfum1.com/api/perfume/v1/perfumes | `query`, `house`, `page`, `per_page` |
| `getPerfume` | GET https://parfum1.com/api/perfume/v1/perfumes/{handle} | `handle` (required) |
| `listHouses` | GET https://parfum1.com/api/perfume/v1/houses | `query` |
| `getHouse` | GET https://parfum1.com/api/perfume/v1/houses/{handle} | `handle` (required) |
| `getStoreInfo` | GET https://parfum1.com/api/perfume/v1/store-info | `topic` |

Search for a perfume:

```bash
curl -s 'https://parfum1.com/api/perfume/v1/perfumes?query=hacivat&per_page=1'
```

The answer (page 1 of 2; values change with the catalogue):

```json
{
  "query": "hacivat",
  "house": null,
  "page": 1,
  "per_page": 1,
  "total": 2,
  "total_pages": 2,
  "results": [
    {
      "handle": "hacivat-by-nishane",
      "name": "Nishane Hacivat",
      "house": "Nishane",
      "family": "woody",
      "gender": "men",
      "from_price_eur": 12.15,
      "from_size_ml": 3,
      "was_price_eur": 18.9,
      "in_stock": true,
      "rating": 4.9,
      "review_count": 47,
      "url": "https://parfum1.com/perfume/hacivat-by-nishane",
      "api_url": "https://parfum1.com/api/perfume/v1/perfumes/hacivat-by-nishane",
      "image": "https://img.parfum1.com/pfm/hacivat-by-nishane/day-9e75cb12/full"
    }
  ]
}
```

Read one perfume by its handle with getPerfume:

```bash
curl -s 'https://parfum1.com/api/perfume/v1/perfumes/hacivat-by-nishane'
```

```json
{
  "handle": "hacivat-by-nishane",
  "name": "Nishane Hacivat",
  "house": {
    "name": "Nishane",
    "handle": "nishane",
    "url": "https://parfum1.com/houses/nishane"
  },
  "url": "https://parfum1.com/perfume/hacivat-by-nishane",
  "api_url": "https://parfum1.com/api/perfume/v1/perfumes/hacivat-by-nishane",
  "concentration": "Extrait de Parfum",
  "family": "woody",
  "gender": "men",
  "launch_year": 2017,
  "tagline": "Pineapple, oakmoss and sunlit wood",
  "description": "Bergamot, grapefruit and pineapple open bright and sharp, then cedar, jasmine and patchouli build a woody, slightly earthy heart. Oakmoss and woody notes dry the finish. An extrait for warm nights out, with strong sillage and long-lasting wear. It is lively without being loud.",
  "notes": {
    "top": [
      "Bergamot",
      "Grapefruit",
      "Pineapple"
    ],
    "heart": [
      "Cedar",
      "Jasmine",
      "Patchouli"
    ],
    "base": [
      "Oakmoss",
      "Woody Notes"
    ]
  },
  "accords": [
    "woody",
    "citrus",
    "mossy",
    "earthy",
    "fruity",
    "sweet"
  ],
  "currency": "EUR",
  "sizes": [
    {
      "size_ml": 3,
      "price_eur": 12.15,
      "was_price_eur": 18.9,
      "price_per_ml_eur": 4.05,
      "in_stock": true
    },
    {
      "size_ml": 10,
      "price_eur": 33.39,
      "was_price_eur": 61.9,
      "price_per_ml_eur": 3.34,
      "in_stock": true
    },
    {
      "size_ml": 30,
      "price_eur": 88.2,
      "was_price_eur": 195.9,
      "price_per_ml_eur": 2.94,
      "in_stock": true
    }
  ],
  "full_bottle": {
    "size_ml": 100,
    "in_stock": false,
    "price_eur": null
  },
  "rating": {
    "value": 4.9,
    "count": 47
  },
  "images": [
    "https://img.parfum1.com/pfm/hacivat-by-nishane/day-9e75cb12/full",
    "https://img.parfum1.com/pfm/hacivat-by-nishane/golden-242b9e99/full",
    "https://img.parfum1.com/pfm/hacivat-by-nishane/spot-1c1c76f9/full"
  ]
}
```

## What the answers contain

- Prices are in euros and include VAT. `price_eur` is the price charged and `was_price_eur` the struck regular price shown beside it on the product page.
- Every perfume is sold as a decant in 3, 10 and 30 ml. `sizes` lists each one with its price, price per ml and `in_stock`, as the buy box shows them.
- The full bottle is listed on every perfume and is always out of stock, shown without a price, as on the product page.
- `notes` are the top, heart and base notes and `description` is the text printed on the product page.
- Every perfume and house carries its page address in `url`, and the answers are in English.
- Search words must all match the perfume name, house or scent family; accents and capital letters are ignored.
- Lists are paged: `page` starts at 1 and `per_page` goes up to 50.

Ordering happens on the website: send people to the `url` of the perfume.

## Errors and caching

Errors are JSON with a real status code. A bad parameter is a 400, an unknown handle or path is a 404, and a catalogue that is briefly unavailable is a 503 with a Retry-After header.

```json
{
  "error": {
    "code": "not_found",
    "message": "No perfume with the handle \"x\". Find handles with search_perfumes (GET /perfumes)."
  }
}
```

Successful answers are cached for an hour at the edge and served stale for a day while they refresh, so a price or a stock level can trail the product page by up to an hour. Cross-origin requests from a browser are allowed.

## Discovery files

| File | Address | What it is |
| --- | --- | --- |
| OpenAPI | https://parfum1.com/openapi.json | OpenAPI 3.1 description of the REST API |
| MCP server card | https://parfum1.com/.well-known/mcp/server-card.json | Server name, version, endpoint, capabilities and tools (also at /.well-known/mcp.json) |
| API catalog | https://parfum1.com/.well-known/api-catalog | RFC 9727 linkset listing the REST API and the MCP server with their descriptions |
| Agent catalog | https://parfum1.com/.well-known/ai-catalog.json | Agent resource catalogue with example questions for each interface |
| llms.txt | https://parfum1.com/llms.txt | Index of the site for agents, with Markdown copies of the help pages |

This page is also available as Markdown at https://parfum1.com/developers.md.

## Questions

Questions about the API or a wrong answer: write to support@parfum1.com. The data is the same catalogue the shop runs on.
