{"openapi":"3.0.3","info":{"title":"Fragrance data API","version":"1.0.0","description":"Server-to-server API over our fragrance dataset. Priced per record: list 1 unit, basic 2, full 4; one unit is $0.0025. Authentication is Authorization: Bearer <key>. There is no CORS - do not call this from a browser, where the key would be public. Ids are opaque and permanent: a record that disappears from the upstream catalogue keeps its id and its last known content with source_status \"absent\", so a 404 on a record only ever means \"no record with this id has been issued\". A repeated id in a batch is charged again. An account reads up to 50,000 records per UTC day; the limit lifts at 00:00 UTC."},"servers":[{"url":"https://fragdb.net"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"retry_after":{"type":"integer","description":"Seconds; also sent as Retry-After."},"required_units":{"type":"integer","description":"payment_required: units the request needs."},"available_units":{"type":"integer","description":"payment_required: units on the balance."},"daily_remaining":{"type":"integer","description":"daily_cap: records left today."},"samples":{"type":"array","items":{"type":"string"},"description":"Test keys: the ids a test key may read."}}}}},"Fragrance":{"type":"object","properties":{"id":{"type":"string","description":"Our stable opaque id of the fragrance.","pattern":"^f_[0-9a-hjkmnp-tv-z]{10}$","x-level":"list"},"brand":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"description":"Brand of the fragrance.","x-level":"list"},"name":{"type":"string","description":"Fragrance name (English, as published).","x-level":"list"},"year":{"type":"integer","nullable":true,"description":"Launch year.","x-level":"list"},"gender":{"type":"string","enum":["female","male","unisex"],"description":"Normalised gender: female | male | unisex.","x-level":"list"},"gender_raw":{"type":"string","description":"Source gender key (label translations in gender_i18n at level full).","x-level":"list"},"rating":{"type":"number","nullable":true,"description":"Average community rating on rating_scale.","x-level":"list"},"rating_scale":{"type":"integer","description":"Maximum of the rating scale.","x-level":"list"},"votes":{"type":"integer","nullable":true,"description":"Number of rating votes.","x-level":"list"},"images":{"type":"object","properties":{"thumbnail":{"type":"string","format":"uri","nullable":true,"description":"200 px thumbnail of the bottle photo on our CDN.","x-level":"list"},"photo":{"type":"string","format":"uri","nullable":true,"description":"Bottle photo (light background), webp, long side ≤ 2400 px.","x-level":"basic"},"cutout":{"type":"string","format":"uri","nullable":true,"description":"Bottle cutout with transparent background (for dark themes), 750×1000 webp with alpha; null when the source has none.","x-level":"basic"}},"x-level":"list","required":["thumbnail","photo","cutout"]},"collection":{"type":"string","nullable":true,"description":"Collection / line name (free text, no id).","x-level":"basic"},"reviews_count":{"type":"integer","nullable":true,"description":"Number of community reviews; null when the source shows none (0 or 1 are not distinguished by the source).","x-level":"basic"},"accords":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"strength":{"type":"integer"},"name_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the accord name (full level only)."}},"required":["id","name","strength"]},"nullable":true,"description":"Main accords, strongest first; strength = percent of the strongest accord (30–100, first is always 100). Accord ids (fa_) group and join accords across records; v1 has no accord endpoint and no accord lines in the index.","x-level":"basic"},"perfumers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"description":"Perfumers credited for the fragrance.","x-level":"basic"},"notes":{"type":"object","nullable":true,"properties":{"layout":{"type":"array","items":{"type":"string","enum":["top","middle","base","notes"]},"description":"The layers present, in order."},"top":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"opacity":{"type":"number","nullable":true},"weight":{"type":"number","nullable":true},"name_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Translations of the note name, {language: name}."},"images":{"type":"object","properties":{"icon":{"type":"string","format":"uri","nullable":true}},"required":["icon"]}},"required":["id","name","opacity","weight","name_i18n","images"],"description":"A note appears at most once in a layer."},"nullable":true},"middle":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"opacity":{"type":"number","nullable":true},"weight":{"type":"number","nullable":true},"name_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Translations of the note name, {language: name}."},"images":{"type":"object","properties":{"icon":{"type":"string","format":"uri","nullable":true}},"required":["icon"]}},"required":["id","name","opacity","weight","name_i18n","images"],"description":"A note appears at most once in a layer."},"nullable":true},"base":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"opacity":{"type":"number","nullable":true},"weight":{"type":"number","nullable":true},"name_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Translations of the note name, {language: name}."},"images":{"type":"object","properties":{"icon":{"type":"string","format":"uri","nullable":true}},"required":["icon"]}},"required":["id","name","opacity","weight","name_i18n","images"],"description":"A note appears at most once in a layer."},"nullable":true},"notes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"opacity":{"type":"number","nullable":true},"weight":{"type":"number","nullable":true},"name_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"description":"Translations of the note name, {language: name}."},"images":{"type":"object","properties":{"icon":{"type":"string","format":"uri","nullable":true}},"required":["icon"]}},"required":["id","name","opacity","weight","name_i18n","images"],"description":"A note appears at most once in a layer."},"nullable":true}},"required":["layout","top","middle","base","notes"],"description":"Note pyramid exactly as published. layout = the levels present, in order; each level is an array of {id, name, opacity, weight, images}; absent levels are null. Three layouts occur: [top, middle, base] (also any subset of these), and [notes] — a flat list without positions. opacity (0.74–1.0) and weight (2.5–5.0) are the source's rendering parameters derived from votes; the first note of a level has the maximum weight. images.icon is the note icon on our CDN - the same URL as images.icon of GET /notes/{id} - or null when the note has no icon.","x-level":"full"},"appreciation":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"votes":{"type":"integer","nullable":true},"pct":{"type":"number"},"label_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the vote label, {language: label}."}},"required":["key","votes","pct"]},"description":"Like/dislike votes, 5 fixed keys in order love, like, ok, dislike, hate; pct = votes / sum × 100 (2 decimals); labels inline via label_i18n at level full.","x-level":"full"},"price_value":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"votes":{"type":"integer","nullable":true},"pct":{"type":"number"},"label_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the vote label, {language: label}."}},"required":["key","votes","pct"]},"description":"Price/value votes, 5 keys: way_overpriced, overpriced, ok, good_value, great_value; pct of the sum, integer-rounded.","x-level":"full"},"gender_votes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"votes":{"type":"integer","nullable":true},"pct":{"type":"number"},"label_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the vote label, {language: label}."}},"required":["key","votes","pct"]},"description":"Gender perception votes, 5 keys: female, more_female, unisex, more_male, male; pct of the sum.","x-level":"full"},"longevity":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"votes":{"type":"integer","nullable":true},"pct":{"type":"number"},"label_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the vote label, {language: label}."}},"required":["key","votes","pct"]},"description":"Longevity votes, 5 keys: very_weak, weak, moderate, long_lasting, eternal; pct of the sum.","x-level":"full"},"sillage":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"votes":{"type":"integer","nullable":true},"pct":{"type":"number"},"label_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the vote label, {language: label}."}},"required":["key","votes","pct"]},"description":"Sillage votes, 4 keys: intimate, moderate, strong, enormous; pct of the sum.","x-level":"full"},"season":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"votes":{"type":"integer","nullable":true},"pct":{"type":"number"},"label_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the vote label, {language: label}."}},"required":["key","votes","pct"]},"description":"Season votes, 4 keys: winter, spring, summer, fall. pct = votes / max over season AND time_of_day × 100 (2 decimals) — the source normalises both blocks to one common maximum.","x-level":"full"},"time_of_day":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"votes":{"type":"integer","nullable":true},"pct":{"type":"number"},"label_i18n":{"type":"object","additionalProperties":{"type":"string"},"nullable":true,"x-level":"full","description":"Translations of the vote label, {language: label}."}},"required":["key","votes","pct"]},"description":"Day/night votes, 2 keys season_day, season_night (labels inline via label_i18n); pct on the same common maximum as season.","x-level":"full"},"gender_i18n":{"type":"object","additionalProperties":{"type":"string"},"description":"Label of gender_raw in English and 22 languages.","x-level":"full","nullable":true},"description":{"type":"string","nullable":true,"description":"Descriptive text of the fragrance as plain text (source HTML with <p> paragraphs converted to paragraphs separated by blank lines); ≈520 characters on average, up to ≈7 900. Owner 15.09: in v1.","x-level":"full"},"pros_cons":{"type":"object","properties":{"pros":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"likes":{"type":"integer"},"dislikes":{"type":"integer"}},"required":["text","likes","dislikes"]}},"cons":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"likes":{"type":"integer"},"dislikes":{"type":"integer"}},"required":["text","likes","dislikes"]}}},"required":["pros","cons"],"nullable":true,"description":"Community pros and cons with agree/disagree counts, as published (9% of records have them). Owner 15.09: in v1.","x-level":"full"},"related":{"type":"object","properties":{"by_designer":{"type":"array","items":{"type":"string"},"description":"Other fragrances of the same brand shown by the source (up to 20). Refreshed with every release and NOT tracked by change_status or updated_in: members and order may change while the record stays \"unchanged\".","x-level":"full"},"in_collection":{"type":"array","items":{"type":"string"},"description":"Fragrances of the same collection (up to 1 019). Refreshed with every release and NOT tracked by change_status or updated_in: members and order may change while the record stays \"unchanged\".","x-level":"full"},"also_like":{"type":"array","items":{"type":"string"},"description":"\"People who like this also like\" (up to 20). Refreshed with every release and NOT tracked by change_status or updated_in: members and order may change while the record stays \"unchanged\".","x-level":"full"},"reminds_of":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"yes":{"type":"integer"},"no":{"type":"integer"}},"required":["id","yes","no"]},"description":"\"Reminds me of\" votes: yes/no counts per fragrance (up to 20; order as published).","x-level":"full"}},"x-level":"full","required":["by_designer","in_collection","also_like","reminds_of"]},"source_status":{"type":"string","enum":["present","absent","merged"],"description":"present | absent | merged. absent = not seen in the latest release; the record is kept (R-18).","x-level":"list"},"last_seen":{"type":"string","description":"Date (YYYY-MM-DD) of the latest release that contained the record.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","x-level":"list"},"merged_into":{"type":"string","nullable":true,"description":"Our id of the record this one was merged into by the source, else null.","x-level":"list"},"change_status":{"type":"string","description":"new | unchanged | updated relative to the previous release (new = first appearance; updated = something in the record changed).","enum":["new","unchanged","updated"],"x-level":"list"},"updated_in":{"type":"string","description":"Date (YYYY-MM-DD) of the latest release in which anything in the record changed, or in which it first appeared. Release dates sort as strings; the release tag is in GET /release and X-Data-Release.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","x-level":"list"},"update_kind":{"type":"string","enum":["content","stats"],"description":"What changed in a record marked updated. content: the record's own data, such as its name, brand, year, composition, perfumers or images; fetch it again. stats: only figures that move with the community and the catalogue, such as ratings, votes and vote breakdowns, the accord profile or counters; the record's content is the same. Present only when change_status is updated; a record without update_kind has not been updated.","x-level":"list"}},"required":["id","brand","name","year","gender","gender_raw","rating","rating_scale","votes","images","source_status","last_seen","merged_into","change_status","updated_in"],"description":"Every property carries x-level, the lowest level that returns it. A request at a level returns every field of that level and below - always present, null when empty - plus the service fields; fields of higher levels are absent."},"Account":{"type":"object","required":["active","balance_units","paid_units","grants","period","daily","index","release","release_date"],"properties":{"active":{"type":"boolean"},"balance_units":{"type":"integer","description":"paid_units plus unexpired grant units."},"paid_units":{"type":"integer"},"grants":{"type":"array","description":"Unexpired grant batches, the soonest to expire first.","items":{"type":"object","required":["units_left","expires_at","kind"],"properties":{"units_left":{"type":"integer"},"expires_at":{"type":"string","format":"date-time","nullable":true,"description":"When the unused units of this batch expire; null for a batch without an expiry (units that come with a plan). Batches are spent soonest-expiring first."},"kind":{"type":"string","enum":["plan","starter","other"],"description":"plan: units that come with a plan, no expiry; starter: units that come with a data file purchase; other: any other grant."}}}},"period":{"type":"object","nullable":true,"required":["started_at","spent_units","minimum_units","shortfall_units"],"properties":{"started_at":{"type":"string","format":"date-time"},"spent_units":{"type":"integer"},"minimum_units":{"type":"integer"},"shortfall_units":{"type":"integer"}}},"daily":{"type":"object","required":["records_used","records_cap","records_remaining"],"description":"Records per UTC day.","properties":{"records_used":{"type":"integer"},"records_cap":{"type":"integer"},"records_remaining":{"type":"integer"}}},"index":{"type":"object","required":["downloads_today","downloads_cap","remaining"],"description":"Index downloads per UTC day.","properties":{"downloads_today":{"type":"integer"},"downloads_cap":{"type":"integer"},"remaining":{"type":"integer"}}},"release":{"type":"string"},"release_date":{"type":"string","nullable":true}}},"Release":{"type":"object","required":["release","release_date","fragrances","source_status_counts","changed_counts","reference_counts","reference_changed_counts","index"],"properties":{"release":{"type":"string"},"release_date":{"type":"string","nullable":true},"fragrances":{"type":"integer","description":"Records in the catalogue, every source_status."},"source_status_counts":{"type":"object","additionalProperties":{"type":"integer"},"description":"Fragrances by source_status."},"changed_counts":{"type":"object","additionalProperties":{"type":"integer"},"description":"Fragrances by change_status."},"reference_counts":{"type":"object","additionalProperties":{"type":"integer"},"description":"brands, perfumers, notes: records."},"reference_changed_counts":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer"}},"description":"{brands|perfumers|notes: {change_status: count}}"},"index":{"type":"object","nullable":true,"description":"The published index of THIS release; null while it is still being built, when /api/v1/index answers 503 index_rebuilding.","required":["etag","bytes","records","reference_lines"],"properties":{"etag":{"type":"string"},"bytes":{"type":"integer"},"records":{"type":"integer","description":"Fragrance lines."},"reference_lines":{"type":"object","nullable":true,"additionalProperties":{"type":"integer"},"description":"Index lines per reference kind: {brand, perfumer, note}."}}}}},"Brand":{"type":"object","properties":{"id":{"type":"string","description":"Our opaque brand id.","x-level":"basic"},"name":{"type":"string","description":"Brand name.","x-level":"basic"},"country":{"type":"string","nullable":true,"description":"Country (English, 117 values).","x-level":"basic"},"main_activity":{"type":"string","nullable":true,"description":"Main activity of the brand (free text, 105 values, case as published).","x-level":"basic"},"website":{"type":"string","format":"uri","nullable":true,"description":"Official brand website.","x-level":"basic"},"parent_company":{"type":"string","nullable":true,"description":"Parent company.","x-level":"basic"},"fragrance_count":{"type":"integer","description":"Number of fragrance records in this release that belong to the brand (the brand_id lines of the release index).","x-level":"basic"},"images":{"type":"object","properties":{"logo":{"type":"string","format":"uri","nullable":true,"description":"Brand logo on our CDN.","x-level":"basic"}},"x-level":"basic","required":["logo"]},"country_i18n":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Country name in 22 languages (keys = language codes). (2026-09-17: declared as served - a language without a translation is null, the key stays.)","x-level":"full"},"main_activity_i18n":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Main activity in 22 languages. (2026-09-17: declared as served - a language without a translation is null, the key stays.)","x-level":"full"},"source_status":{"type":"string","enum":["present","absent","merged"],"description":"present = in the current release; absent = no longer in the upstream catalogue, last known content kept; merged = folded into merged_into.","x-level":"basic"},"last_seen":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date (YYYY-MM-DD) of the latest release that contained the record.","x-level":"basic"},"merged_into":{"type":"string","nullable":true,"description":"The id this record was merged into, or null.","x-level":"basic"},"change_status":{"type":"string","description":"new | unchanged | updated against the previous release (updated = something in the record changed).","x-level":"basic","enum":["new","unchanged","updated"]},"updated_in":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date (YYYY-MM-DD) of the latest release in which anything in the record changed, or in which it first appeared. Release dates sort as strings; the release tag is in GET /release and X-Data-Release.","x-level":"basic"},"update_kind":{"type":"string","enum":["content","stats"],"description":"What changed in a record marked updated. content: the record's own data, such as its name, brand, year, composition, perfumers or images; fetch it again. stats: only figures that move with the community and the catalogue, such as ratings, votes and vote breakdowns, the accord profile or counters; the record's content is the same. Present only when change_status is updated; a record without update_kind has not been updated.","x-level":"basic"}},"required":["id","name","country","main_activity","website","parent_company","fragrance_count","images","source_status","last_seen","merged_into","change_status","updated_in"],"description":"Every property carries x-level, the lowest level that returns it. A request at a level returns every field of that level and below - always present, null when empty - plus the service fields; fields of higher levels are absent."},"Perfumer":{"type":"object","properties":{"id":{"type":"string","description":"Our opaque perfumer id.","x-level":"basic"},"name":{"type":"string","description":"Perfumer name.","x-level":"basic"},"status":{"type":"string","nullable":true,"description":"Role/status as published (83 values; 'Perfumer' for most).","x-level":"basic"},"company":{"type":"string","nullable":true,"description":"Current company.","x-level":"basic"},"also_worked":{"type":"string","nullable":true,"description":"Previous companies (free text).","x-level":"basic"},"education":{"type":"string","nullable":true,"description":"Education (free text).","x-level":"basic"},"web":{"type":"string","format":"uri","nullable":true,"description":"Personal / professional website.","x-level":"basic"},"fragrance_count":{"type":"integer","description":"Number of fragrance records in this release that credit the perfumer.","x-level":"basic"},"images":{"type":"object","properties":{"photo":{"type":"string","format":"uri","nullable":true,"description":"Portrait on our CDN (43.5% have one).","x-level":"basic"}},"x-level":"basic","required":["photo"]},"status_i18n":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Status in 22 languages. (2026-09-17: declared as served - a language without a translation is null, the key stays.)","x-level":"full"},"name_i18n":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Name in 9 non-Latin scripts (ru uk ja zh ko ar he el mn) where available. (2026-09-17: declared as served - a language without a translation is null, the key stays.)","x-level":"full"},"source_status":{"type":"string","enum":["present","absent","merged"],"description":"present = in the current release; absent = no longer in the upstream catalogue, last known content kept; merged = folded into merged_into.","x-level":"basic"},"last_seen":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date (YYYY-MM-DD) of the latest release that contained the record.","x-level":"basic"},"merged_into":{"type":"string","nullable":true,"description":"The id this record was merged into, or null.","x-level":"basic"},"change_status":{"type":"string","description":"new | unchanged | updated against the previous release (updated = something in the record changed).","x-level":"basic","enum":["new","unchanged","updated"]},"updated_in":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date (YYYY-MM-DD) of the latest release in which anything in the record changed, or in which it first appeared. Release dates sort as strings; the release tag is in GET /release and X-Data-Release.","x-level":"basic"},"update_kind":{"type":"string","enum":["content","stats"],"description":"What changed in a record marked updated. content: the record's own data, such as its name, brand, year, composition, perfumers or images; fetch it again. stats: only figures that move with the community and the catalogue, such as ratings, votes and vote breakdowns, the accord profile or counters; the record's content is the same. Present only when change_status is updated; a record without update_kind has not been updated.","x-level":"basic"}},"required":["id","name","status","company","also_worked","education","web","fragrance_count","images","source_status","last_seen","merged_into","change_status","updated_in"],"description":"Every property carries x-level, the lowest level that returns it. A request at a level returns every field of that level and below - always present, null when empty - plus the service fields; fields of higher levels are absent."},"Note":{"type":"object","properties":{"id":{"type":"string","description":"Our opaque note id. Each source triple (name, page, icon) is a separate id, so aliases have their own ids.","x-level":"basic"},"name":{"type":"string","description":"Note name.","x-level":"basic"},"latin_name":{"type":"string","nullable":true,"description":"Latin (botanical) name.","x-level":"basic"},"other_names":{"type":"array","items":{"type":"string"},"description":"Other names / synonyms.","x-level":"basic"},"group":{"type":"string","description":"Note group, 13 fixed values (Flowers; Fruits, vegetables and nuts; Natural and synthetic, popular and weird; Greens, herbs and fougeres; Woods and mosses; Sweets and gourmand smells; Spices; Beverages; Citrus smells; Musk, amber, animalic smells; White flowers; Resins and balsams; Uncategorized).","x-level":"basic"},"odor_profile":{"type":"string","nullable":true,"description":"Short odour description (≈96 characters).","x-level":"basic"},"fragrance_count":{"type":"integer","description":"Number of fragrance records in this release with this note in their pyramid (a fragrance counts once, whatever the level).","x-level":"basic"},"images":{"type":"object","properties":{"icon":{"type":"string","format":"uri","nullable":true,"description":"Note icon on our CDN.","x-level":"basic"},"alt_icons":{"type":"array","items":{"type":"string","format":"uri"},"description":"Alternative icon renderings (t2/t3).","x-level":"basic"},"background":{"type":"string","format":"uri","nullable":true,"description":"Background image of the note.","x-level":"basic"}},"x-level":"basic","required":["icon","alt_icons","background"]},"name_i18n":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Note name in 22 languages. (2026-09-17: declared as served - a language without a translation is null, the key stays.)","x-level":"full"},"group_i18n":{"type":"object","additionalProperties":{"type":"string","nullable":true},"description":"Group name in 22 languages. (2026-09-17: declared as served - a language without a translation is null, the key stays.)","x-level":"full"},"source_status":{"type":"string","enum":["present","absent","merged"],"description":"present = in the current release; absent = no longer in the upstream catalogue, last known content kept; merged = folded into merged_into.","x-level":"basic"},"last_seen":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date (YYYY-MM-DD) of the latest release that contained the record.","x-level":"basic"},"merged_into":{"type":"string","nullable":true,"description":"The id this record was merged into, or null.","x-level":"basic"},"change_status":{"type":"string","description":"new | unchanged | updated against the previous release (updated = something in the record changed).","x-level":"basic","enum":["new","unchanged","updated"]},"updated_in":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Date (YYYY-MM-DD) of the latest release in which anything in the record changed, or in which it first appeared. Release dates sort as strings; the release tag is in GET /release and X-Data-Release.","x-level":"basic"},"update_kind":{"type":"string","enum":["content","stats"],"description":"What changed in a record marked updated. content: the record's own data, such as its name, brand, year, composition, perfumers or images; fetch it again. stats: only figures that move with the community and the catalogue, such as ratings, votes and vote breakdowns, the accord profile or counters; the record's content is the same. Present only when change_status is updated; a record without update_kind has not been updated.","x-level":"basic"}},"required":["id","name","latin_name","other_names","group","odor_profile","fragrance_count","images","source_status","last_seen","merged_into","change_status","updated_in"],"description":"Every property carries x-level, the lowest level that returns it. A request at a level returns every field of that level and below - always present, null when empty - plus the service fields; fields of higher levels are absent."}}},"security":[{"bearerAuth":[]}],"paths":{"/api/v1/fragrances/{id}":{"get":{"summary":"One fragrance record","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"level","in":"query","required":false,"schema":{"type":"string","enum":["list","basic","full"],"default":"list"},"description":"Units per record: list 1, basic 2, full 4. A full request for a record whose full-only fields are all empty (null, empty, or vote counts that are all zero) is charged at the basic price; the document returned is still the full one. When the source later adds such data (for example the first note), the same id is charged at the full price from that release on, and the index shows it as updated."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"The ETag of an earlier answer to the same request. If the answer is unchanged: 304, no body, nothing charged, not counted against the daily limit. The ETag covers the whole answer, service fields included. A HEAD request is free as well."}],"responses":{"200":{"description":"The record","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}},"ETag":{"description":"Send it back in If-None-Match.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fragrance"}}}},"304":{"description":"Not modified - free, outside the daily limit","headers":{"ETag":{"schema":{"type":"string"}},"X-Charged-Units":{"description":"Always 0.","schema":{"type":"integer"}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/fragrances/batch":{"post":{"summary":"Up to 100 fragrance records","description":"Items come back in request order and length. A repeated id is returned and charged again (a repeated record is a repeated sale) - deduplicate before sending. An id that was never issued comes back as null, is listed in problems and costs nothing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100},"level":{"type":"string","enum":["list","basic","full"],"default":"list"}}}}}},"responses":{"200":{"description":"Items in request order","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["items","problems","charged_units"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Fragrance","nullable":true}},"problems":{"type":"array","items":{"type":"object","required":["id","code"],"properties":{"id":{"type":"string"},"code":{"type":"string","enum":["not_found","unavailable_for_legal_reasons"]}}}},"charged_units":{"type":"integer"}}}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"413":{"description":"payload_too_large - the body is over 256 KB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"unsupported_media_type - send JSON as UTF-8","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/account":{"get":{"summary":"Balance, period and limits (free)","responses":{"200":{"description":"Account state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/release":{"get":{"summary":"Current release and what changed in it (free)","responses":{"200":{"description":"Release info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Release"}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/index":{"get":{"summary":"Catalogue index for the current release (free, 5 per UTC day)","description":"A gzipped JSONL file: one JSON object per line. Every line has a \"kind\": \"fragrance\" lines carry id, brand_id, brand, name, year, gender, source_status, merged_into, change_status and updated_in; \"brand\", \"perfumer\" and \"note\" lines carry only id, source_status, merged_into, change_status and updated_in - the change feed of those records (no names). Any line whose change_status is updated also carries update_kind. Skip lines whose kind you do not know: new kinds may appear. change_status is new, unchanged or updated; updated_in is a release date (YYYY-MM-DD). The update_kind says what changed: content (fetch it again) or stats (only figures that move with the community and the catalogue); it is present only on updated lines. Lists that are refreshed with every release (related items; a brand's popular and new items) do not count as a change. Send If-None-Match with the previous ETag: a 304 is free and does not count against the daily limit.","parameters":[{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"gzipped JSONL, one object per line","headers":{"ETag":{"schema":{"type":"string"}},"X-Index-Remaining":{"description":"Index downloads left today (UTC).","schema":{"type":"integer"}}},"content":{"application/gzip":{"schema":{"type":"string","format":"binary"}}}},"304":{"description":"Not modified - free, outside the limit"},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the index needs a positive balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/brands/{id}":{"get":{"summary":"One brand record","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"level","in":"query","schema":{"type":"string","enum":["basic","full"],"default":"basic"},"description":"basic 2 units, full 4; a full request for a record with no localisations is charged as basic."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"The ETag of an earlier answer to the same request. If the answer is unchanged: 304, no body, nothing charged, not counted against the daily limit. The ETag covers the whole answer, service fields included. A HEAD request is free as well."}],"responses":{"200":{"description":"The record","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}},"ETag":{"description":"Send it back in If-None-Match.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Brand"}}}},"304":{"description":"Not modified - free, outside the daily limit","headers":{"ETag":{"schema":{"type":"string"}},"X-Charged-Units":{"description":"Always 0.","schema":{"type":"integer"}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/brands/batch":{"post":{"summary":"Up to 100 brand records","description":"Items come back in request order and length. A repeated id is returned and charged again (a repeated record is a repeated sale) - deduplicate before sending. An id that was never issued comes back as null, is listed in problems and costs nothing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100},"level":{"type":"string","enum":["basic","full"],"default":"basic"}}}}}},"responses":{"200":{"description":"Items in request order","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["items","problems","charged_units"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Brand","nullable":true}},"problems":{"type":"array","items":{"type":"object","required":["id","code"],"properties":{"id":{"type":"string"},"code":{"type":"string","enum":["not_found","unavailable_for_legal_reasons"]}}}},"charged_units":{"type":"integer"}}}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"413":{"description":"payload_too_large - the body is over 256 KB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"unsupported_media_type - send JSON as UTF-8","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/perfumers/{id}":{"get":{"summary":"One perfumer record","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"level","in":"query","schema":{"type":"string","enum":["basic","full"],"default":"basic"},"description":"basic 2 units, full 4; a full request for a record with no localisations is charged as basic."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"The ETag of an earlier answer to the same request. If the answer is unchanged: 304, no body, nothing charged, not counted against the daily limit. The ETag covers the whole answer, service fields included. A HEAD request is free as well."}],"responses":{"200":{"description":"The record","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}},"ETag":{"description":"Send it back in If-None-Match.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Perfumer"}}}},"304":{"description":"Not modified - free, outside the daily limit","headers":{"ETag":{"schema":{"type":"string"}},"X-Charged-Units":{"description":"Always 0.","schema":{"type":"integer"}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/perfumers/batch":{"post":{"summary":"Up to 100 perfumer records","description":"Items come back in request order and length. A repeated id is returned and charged again (a repeated record is a repeated sale) - deduplicate before sending. An id that was never issued comes back as null, is listed in problems and costs nothing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100},"level":{"type":"string","enum":["basic","full"],"default":"basic"}}}}}},"responses":{"200":{"description":"Items in request order","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["items","problems","charged_units"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Perfumer","nullable":true}},"problems":{"type":"array","items":{"type":"object","required":["id","code"],"properties":{"id":{"type":"string"},"code":{"type":"string","enum":["not_found","unavailable_for_legal_reasons"]}}}},"charged_units":{"type":"integer"}}}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"413":{"description":"payload_too_large - the body is over 256 KB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"unsupported_media_type - send JSON as UTF-8","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/notes/{id}":{"get":{"summary":"One note record","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"level","in":"query","schema":{"type":"string","enum":["basic","full"],"default":"basic"},"description":"basic 2 units, full 4; a full request for a record with no localisations is charged as basic."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"The ETag of an earlier answer to the same request. If the answer is unchanged: 304, no body, nothing charged, not counted against the daily limit. The ETag covers the whole answer, service fields included. A HEAD request is free as well."}],"responses":{"200":{"description":"The record","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}},"ETag":{"description":"Send it back in If-None-Match.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Note"}}}},"304":{"description":"Not modified - free, outside the daily limit","headers":{"ETag":{"schema":{"type":"string"}},"X-Charged-Units":{"description":"Always 0.","schema":{"type":"integer"}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}},"/api/v1/notes/batch":{"post":{"summary":"Up to 100 note records","description":"Items come back in request order and length. A repeated id is returned and charged again (a repeated record is a repeated sale) - deduplicate before sending. An id that was never issued comes back as null, is listed in problems and costs nothing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":100},"level":{"type":"string","enum":["basic","full"],"default":"basic"}}}}}},"responses":{"200":{"description":"Items in request order","headers":{"X-Charged-Units":{"description":"Units charged by this request (0 for a test key).","schema":{"type":"integer"}},"X-Balance-Units":{"description":"Units left on the balance after this request.","schema":{"type":"integer"}},"X-Daily-Remaining":{"description":"Records the account may still read today (UTC).","schema":{"type":"integer"}},"X-Data-Release":{"description":"The data release that answered.","schema":{"type":"string"}},"X-Request-Id":{"description":"Quote it when writing to us.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["items","problems","charged_units"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Note","nullable":true}},"problems":{"type":"array","items":{"type":"object","required":["id","code"],"properties":{"id":{"type":"string"},"code":{"type":"string","enum":["not_found","unavailable_for_legal_reasons"]}}}},"charged_units":{"type":"integer"}}}}}},"400":{"description":"bad_request - nothing is charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"unauthorized - one answer for every reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"payment_required - the whole request is refused, nothing charged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"wrong_site - this key was not issued for this site","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found - no such endpoint, or no record with this id has ever been issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"method_not_allowed - see the Allow header","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Allow":{"schema":{"type":"string"}}}},"413":{"description":"payload_too_large - the body is over 256 KB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"unsupported_media_type - send JSON as UTF-8","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited | daily_cap | index_cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait. For daily_cap and index_cap: until 00:00 UTC, when the caps lift.","schema":{"type":"integer"}}}},"451":{"description":"unavailable_for_legal_reasons - the record is withheld; its id is never reused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"api_disabled | maintenance | index_rebuilding (the index endpoint, while the published index still belongs to the previous release)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}}}}}}}