GET /label/cosmetic/ingredient

Resolves a cosmetic ingredient into its regulatory status under Regulation (EC) No 1223/2009: prohibited (Annex II), restricted (Annex III), or authorised as a colorant (IV), preservative (V) or UV filter (VI) — with every published entry, its maximum concentration, its conditions of use and the mandatory label wording served word for word. The answer comes from a local store built from the consolidated text on EUR-Lex, so a lookup resolves in milliseconds with no network call and no secret at request time.

Use it when an agent needs a grounded, dated, sourced verdict before shipping an EU cosmetic label or clearing a formulation — “may this ingredient be used at all?”, “at what concentration, in which product type, and what must the label say?”. The answer is versioned by amending regulation: the consolidated version in force at the queried date, plus the upcoming change when a published but not-yet-applicable one modifies the entry. See the live /catalog for the authoritative endpoint listing and price.

Only the Annexes are authoritative — CosIng is informative

This is the nuance that decides whether an answer is usable. CosIng, the European Commission’s cosmetic-ingredient database, is a legally non-binding information tool: only the Annexes to the Regulation are authoritative. This service therefore keeps the two apart and says which one spoke:

  • substance.resolved_from: "annexes" — the identity comes from the authoritative source itself;
  • substance.resolved_from: "cosing_index" — CosIng recognised the substance, which is what turns an unknown identifier into an honest not_listed verdict instead of a 404;
  • source_divergence: true with a divergences[] array — a recorded gap between CosIng and an Annex applies to this substance. The Annex always prevails, and the gap is reported, never silently resolved.

The second nuance is stated in the response itself, in limits: absence from Annexes II to VI is not an authorisation. It means no specific EU-wide prohibition or restriction entry applies — the safety assessment of the ingredient and of the finished product remains the responsibility of the responsible person placing it on the market.

x402 golden rule: the agent pays for the answer to its question. A resolved identity that the Annexes do not carry is a successful answer too → 200 billed with verdict: "not_listed" — the absence is the information. Only requests the service cannot answer — zero or several keys, a bad checksum, an identity unknown to both the Annexes and CosIng, a date before the oldest ingested version — leave the 200 range and are not billed.

Parameters

Exactly one of the four keys, as a query parameter.

ParameterTypeRequiredDescription
casstringone of the fourCAS number — check-digit validated before any lookup
ecstringone of the fourEC number — check-digit validated
incistringone of the fourExact INCI name (case and spacing folded, no fuzzy match)
namestringone of the fourExact chemical name
datestringnoYYYY-MM-DD — serves the consolidated version in force at that date (defaults to today)
product_typestringnoKeeps only the conditions whose published scope covers that product type, plus the unbounded ones
GET /label/cosmetic/ingredient?inci=SALICYLIC%20ACID
GET /label/cosmetic/ingredient?cas=123-31-9&date=2026-06-01

A date earlier than the oldest ingested consolidated version is a 400 naming the bound: extrapolating a verdict backwards would be factually wrong. product_type, when provided, must not be empty.

200 response — UnifiedResponse

{
  "data": {
    "verdict": "restricted",
    "substance": { "...": "..." },
    "entries": [ "..." ],
    "version": { "...": "..." },
    "source_divergence": false,
    "note": "...",
    "limits": ["..."]
  },
  "provenance": {
    "source": "Regulation (EC) No 1223/2009 on cosmetic products — consolidated text (EUR-Lex), Annexes II to VI",
    "fetched_at": "2026-07-30T18:27:53Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-05-01T00:00:00Z" }
  }
}

Fields of data

FieldTypeDescription
verdictstringClosed enumeration: prohibited (II), restricted (III), authorised_colorant (IV), authorised_preservative (V), authorised_uv_filter (VI), not_listed
substanceobjectThe resolved identity (inci_name, chemical_name, cas_numbers, ec_numbers) with resolved_from
entriesobject[]One entry per Annex covering the substance, as published (see below); empty on not_listed
versionobjectThe consolidated version served: consolidated_ref, applicable_from, applicable_to (null when open)
source_divergencebooltrue when a recorded CosIng/Annex divergence applies; divergences[] then details it
notestringWhy the top-level verdict reads as it does — multi-Annex coverage, or the dated not_listed statement
limitsstring[]The four fixed caveats carried by every response

A substance can fall under several Annexes. The top-level verdict is then the most restrictive one, but every entry keeps its own status and all of them apply cumulativelynote says so explicitly. Reading only the top-level verdict on such a substance loses half the obligations.

An entries[] entry — the Annex as published

FieldTypeDescription
annexstringII to VI
entry_numberstringReference number in that Annex
statusstringThe status of this entry (same enumeration as verdict, minus not_listed)
conditionsobject[]product_type_or_body_part, max_concentration, other_conditions, required_label_wordingserved word for word
conditions_omitted_by_product_typeintHow many conditions the product_type filter removed — nothing is hidden
amending_actstringThe amending regulation, with amending_celex and amending_oj_date
applicable_fromstringApplicability date of the version served
upcomingobject{ change, applicable_from, consolidated_ref } when a published but not-yet-applicable version adds, modifies or removes the entry

Maximum concentrations, conditions of use and label wording are relayed exactly as published — no unit conversion, no rounding, no reformulation, no translation. "3,0 %" keeps its comma; a multi-part condition keeps its (a) (b) (c) structure and its line breaks, because those parts are what bind the concentration to the product type.

Example — a substance covered by two Annexes

GET /label/cosmetic/ingredient?inci=SALICYLIC%20ACID — restricted under Annex III and authorised as a preservative under Annex V. The verdict is the most restrictive; both entries apply.

{
  "data": {
    "verdict": "restricted",
    "substance": {
      "inci_name": "Salicylic acid",
      "chemical_name": "Benzoic acid, 2-hydroxy- (9)",
      "cas_numbers": ["69-72-7"],
      "ec_numbers": ["200-712-3"],
      "resolved_from": "annexes"
    },
    "entries": [
      {
        "annex": "III",
        "entry_number": "98",
        "status": "restricted",
        "conditions": [
          {
            "product_type_or_body_part": "(a) Rinse-off hair products\n(b) Other products except body lotion, eye shadow, mascara, eyeliner, lipstick, roll-on deodorant\n(c) Body lotion, eye shadow, mascara, eyeliner, lipstick, roll-on deodorant",
            "max_concentration": "(a) 3,0 %\n(b) 2,0 %\n(c) 0,5 %",
            "other_conditions": "(a) (b) (c)\nNot to be used in preparations for children under 3 years of age. …",
            "required_label_wording": "(a) (b) (c)\nNot to be used for children under 3 years of age (10)"
          }
        ],
        "amending_act": "COMMISSION REGULATION (EU) 2021/850 of 26 May 2021",
        "amending_celex": "32021R0850",
        "amending_oj_date": "2021-05-28",
        "applicable_from": "2026-05-01"
      },
      {
        "annex": "V",
        "entry_number": "3",
        "status": "authorised_preservative",
        "conditions": [
          {
            "max_concentration": "0,5 % (acid)",
            "other_conditions": "Not to be used in products for children under 3 years of age, except for shampoos.",
            "required_label_wording": "Not to be used for children under 3 years of age (2)"
          }
        ],
        "amending_act": "COMMISSION REGULATION (EU) 2019/1966 of 27 November 2019",
        "amending_celex": "32019R1966",
        "amending_oj_date": "2019-11-28",
        "applicable_from": "2026-05-01"
      }
    ],
    "version": {
      "consolidated_ref": "02009R1223 — EN — 01.05.2026",
      "applicable_from": "2026-05-01",
      "applicable_to": null
    },
    "source_divergence": false,
    "note": "This substance is covered by 2 entries (III/98, V/3). The top-level verdict reflects the most restrictive one; each entry carries its own status and conditions, which all apply cumulatively.",
    "limits": [
      "Absence from Annexes II to VI of Regulation (EC) No 1223/2009 is not an authorisation: it means no specific EU-wide prohibition or restriction entry applies. The safety assessment of the ingredient and of the finished product remains the responsibility of the responsible person placing it on the market.",
      "This is not a safety assessment: no concentration in a finished formulation is computed, and no conclusion is drawn on a specific product.",
      "Maximum concentrations, conditions of use and label wording are served exactly as published, without unit conversion, rounding, reformulation or translation ('quantum satis' included).",
      "CosIng is a legally non-binding information tool of the European Commission: only the Annexes to the Regulation are authoritative. Divergences are reported, never silently resolved."
    ]
  },
  "provenance": {
    "source": "Regulation (EC) No 1223/2009 on cosmetic products — consolidated text (EUR-Lex), Annexes II to VI",
    "fetched_at": "2026-07-30T18:27:53Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-05-01T00:00:00Z" }
  }
}

Adding &product_type=Rinse-off%20hair%20products keeps the Annex III entry whole (its conditions are published as one multi-part block) and trims the Annex V entry from five conditions to four, reporting "conditions_omitted_by_product_type": 1. The filter is a reading aid that counts what it removed — it never lets an agent believe it saw everything.

Example — prohibited, with a narrow authorised exception

GET /label/cosmetic/ingredient?cas=123-31-9 (hydroquinone) is prohibited under Annex II and carries an Annex III entry for artificial nail systems only:

{
  "verdict": "prohibited",
  "entries": [
    {
      "annex": "II",
      "entry_number": "1339",
      "status": "prohibited",
      "conditions": [],
      "amending_act": "COMMISSION REGULATION (EU) No 344/2013 of 4 April 2013"
    },
    {
      "annex": "III",
      "entry_number": "14",
      "status": "restricted",
      "conditions": [
        {
          "product_type_or_body_part": "Artificial nail systems",
          "max_concentration": "0,02 % (after mixing for use)",
          "other_conditions": "Professional use only",
          "required_label_wording": "— For professional use only\n— Avoid skin contact\n— Read directions for use carefully"
        }
      ]
    }
  ]
}

The three label lines are the regulatory text, served verbatim, dashes included — that is what goes on the label.

Example — not listed is a billed 200, not an authorisation

GET /label/cosmetic/ingredient?cas=56-81-5 (glycerin): CosIng recognises the substance, the Annexes do not carry it. The verdict is dated and says what it does not mean:

{
  "verdict": "not_listed",
  "substance": {
    "inci_name": "GLYCERIN",
    "cas_numbers": ["56-81-5"],
    "ec_numbers": ["200-289-5"],
    "resolved_from": "cosing_index"
  },
  "entries": [],
  "note": "Not listed in Annexes II to VI of Regulation (EC) No 1223/2009 as in force on 2026-07-30 (consolidated version 02009R1223 — EN — 01.05.2026 of the Regulation). This verdict is dated and is not an authorisation: it means no specific prohibition or restriction entry applies to this substance at that date."
}

resolved_from: "cosing_index" is what makes this verdict honest rather than a guess: the informative source vouched for the identity, the authoritative Annexes answered on the status.

What this endpoint refuses to do

The four limits are content, not a footer:

  • absence from the Annexes is not an authorisation — the safety assessment stays with the responsible person;
  • this is not a safety assessment: no concentration in a finished formulation is computed and no conclusion is drawn on a specific product;
  • values are served exactly as published, without conversion or reformulation;
  • CosIng is informative only; only the Annexes are authoritative, and divergences are reported.

There is also no fuzzy search: an approximate INCI name is a miss, not a guess.

Freshness

Answers are served from a snapshot of the consolidated Regulation, dated by the version in force at the queried date (freshness.as_of), not by the ingestion date. A missed refresh keeps serving the last good snapshot, honestly dated, and never becomes a 5xx.

Errors

Only requests the service cannot answer leave the 200 range — none of them are billed.

StatuscodeCase
400INVALID_INPUTZero or several keys; a bad CAS/EC check digit; an empty product_type; a date before the oldest ingested version
404NOT_FOUNDThe identity is unknown to both the Annexes and the CosIng index
503DATA_UNAVAILABLEThe cosmetics dataset has not been ingested yet — there is no last good snapshot to serve
500INTERNALInternal error (detail logged, not exposed)
{ "error": "parameters 'cas', 'ec', 'inci' and 'name' are mutually exclusive", "code": "INVALID_INPUT" }
{ "error": "invalid CAS check digit: '123-31-8'", "code": "INVALID_INPUT" }
{ "error": "cosmetic ingredient identity not resolved: unknown to Annexes II to VI of Regulation (EC) No 1223/2009 and to the CosIng index", "code": "NOT_FOUND" }

An unresolved identity is a 404 (nothing to answer about); a resolved identity absent from the Annexes is a billed 200 not_listed. The two are never confused.

Attribution

Verdicts are derived from Regulation (EC) No 1223/2009 on cosmetic products, consolidated text published on EUR-Lex (European Union), with the CosIng index of the European Commission used for identity resolution only.

See also