GET /label/lookup

Turns an ingredient designation as it appears on a label or a datasheet - a common name, an INCI name, a chemical denomination, a food-additive name - into the exact identifiers the EU labelling routes require: a CAS or EC number for /label/chem/classify and /label/chem/svhc, an INCI name for /label/cosmetic/ingredient, an E number for /label/food/additive. The answer comes from the referentials already ingested, with no network call and no secret at request time.

This route resolves an identity. It renders no regulatory verdict - those are the four routes it opens. See the live /catalog for the authoritative listing and price.

A none does not mean “unregulated”

Read this before anything else on the page, because the reader of a labelling route arrives with a compliance question. A none says one thing only: this text is absent from the ingested referentials, at their date. It is never a statement that the substance is unregulated, unclassified, or free to use.

The clearest proof is in the examples below. dimethyl ketone comes back none - and it is a common name for acetone, which carries a harmonised classification in Annex VI (q=acetone returns it). The referentials publish “acetone”, “propan-2-one” and “propanone”, not “dimethyl ketone”, and this route matches only what they publish. A none is a reason to find the designation the regulation uses, never a reason to conclude anything about the substance.

Only the designations the referentials publish

Matching uses only the names, synonyms and identifiers the referentials themselves publish - the ;-separated denominations of an Annex VI entry, the synonyms of a food additive, the INCI names of the cosmetics annexes and of CosIng. There is no synonym dictionary of our own, and that is a decision, not a gap: inventing one would mean selling our own referential as if it were official. Every candidate this route serves can be traced to a line a regulator or the Commission published.

Every answer carries that rule in the fixed sentence of data.limits, served verbatim:

A resolution names what the referential publishes for the text you sent, as of the date carried by the provenance; it does not certify that the entity resolved is the one you had in mind. A common name may designate a group of substances rather than a single one, and this resolution never chooses for you: every candidate found is listed. Matching is exact on the shared normalisation of the designations published by the referentials themselves — no fuzzy matching and no synonym dictionary of our own — so ‘none’ means the text is absent from the ingested referentials at that date, never that the substance is unregulated.

q is a designation, not an identifier: a CAS number or an E number sent as q (67-64-1, E330) comes back none, because the referentials publish those as identifiers, not as names. If the agent already holds one, it should call the target route directly.

The verdict, and why ambiguous is the point here

verdictMeaningcandidates
exactOne candidate answersexactly one element
ambiguousSeveral do - all served, up to 25, with total exacttwo or more elements
noneThe ingested referentials publish nothing for this text, at their date[]

candidates is always present - empty on none, a one-element list on exact. All three verdicts are a 200, billed: a dated none is what stops an agent from inventing a CAS number.

ambiguous is common here, and it is the feature rather than the defect: one designation usually carries several natures of identifier - a CAS, an EC number, an INCI name, an E number - and they are all returned. One call to ?q=sodium nitrite opens the chemical, the cosmetic and the food route at once. A common name may also designate a group of substances (petroleum gas matches 182 Annex VI entries); the service never picks one.

Five natures, each naming what it opens

Each candidate’s id is the identifier the downstream route accepts as is, and each candidate lists in endpoints the routes that identifier opens - those of the referentials that actually returned it, never a theoretical list:

id_kindExample idOpens
cas7632-00-0/label/chem/classify, /label/chem/svhc, /label/cosmetic/ingredient - per referential
ec231-555-9same as cas
inciSodium nitrite/label/cosmetic/ingredient
e_numberE250/label/food/additive
namean indexed denominationthe route of the referential that indexes it - see below

A name candidate appears when a referential publishes an entry without a usable identifier: a placeholder cell (-) or a composite cell listing several numbers (13463-67-7/1317-70-0/1317-80-2, the form the Cosmetics Regulation publishes for titanium dioxide). Those cells are never served as an id - the downstream route would reject them, and splitting them would be rewriting the source. They are counted in data.source_identifiers_not_usable, and the entry stays reachable through the denomination its referential indexes. A candidate no route would resolve is never served.

Five referentials, and one of them is not binding

referentialauthorityPublishesOpens
annex_vibindingECHA Annex VI (CLP) - CAS, EC, denominations/label/chem/classify
candidate_listbindingECHA Candidate List of SVHC (REACH Art. 59(10)) - CAS, EC, names/label/chem/svhc
cosmeticsbindingRegulation (EC) No 1223/2009, Annexes II to VI - INCI, CAS, EC/label/cosmetic/ingredient
food_additivesbindingRegulation (EC) No 1333/2008, Annexes II and III - E numbers, names, synonyms/label/food/additive
cosing_indexinformation_onlyCosIng (European Commission) - INCI, CAS, EC/label/cosmetic/ingredient

CosIng is information_only, and every response says so on its line in data.referentials. It resolves an identity - it is the path from an INCI list on a cosmetic label to an identifier, and many everyday ingredients (Aqua, Glycerin) are only there, because the annexes list regulated substances only. But it carries no legal force: only the four binding publications do. A candidate whose sources is only cosing_index is an identity to look up, never a verdict - the verdict is what /label/cosmetic/ingredient returns for it.

The health and nutrition claims register behind /label/claims/check is never queried here: it holds wordings, not substance identifiers.

Parameters

ParameterTypeRequiredDescription
qstringyesThe ingredient designation as it appears on the label. At least one letter or digit
domainstringnochem, cosmetic or food - limits the referentials queried
product_typestringnoCosmetic product type - only together with domain=cosmetic
GET /label/lookup?q=sodium%20nitrite&domain=food
  • Normalisation is the referentials’ own. Case and punctuation are folded (punctuation becomes a word separation); stereochemical and positional prefixes and multipliers are kept, because dropping them would make distinct substances converge.
  • domain reduces, never reshapes: it narrows the referentials queried (every referential in scope is still listed in data.referentials).
  • product_type narrows cosmetic annex entries only - which is why it requires domain=cosmetic: a filter that silently had no effect would return a wider list than asked without saying so. It follows the same rule as /label/cosmetic/ingredient: an entry with no product-type condition - an Annex II prohibition, notably - is never dropped. Hiding a prohibited substance because a product type was given would be the worst possible defect here.
  • No pagination. The list is capped at 25; total counts every candidate before the cap and truncated says whether it was cut. Narrow with domain instead of paging - a second page would be a second paid call for the same question. A truncated list is never exact.

200 response - UnifiedResponse

{
  "data": { ... },
  "provenance": {
    "source": "ECHA Annex VI (CLP), harmonised classification and labelling; ECHA Candidate List of SVHC (REACH Art. 59(10)); Regulation (EC) No 1223/2009 on cosmetic products — consolidated text (EUR-Lex), Annexes II to VI; CosIng (European Commission) via public EU Search API; Regulation (EC) No 1333/2008 on food additives — consolidated text (EUR-Lex), Annex II (Union list by food category) and Annex III",
    "fetched_at": "2026-10-15T15:41:31.717766173Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-05-01T00:00:00Z" }
  }
}
  • provenance.source: every referential queried.
  • freshness.as_of: the oldest of their dates - the per-referential date and regulatory version live in data.referentials.

Fields of data

FieldTypeDescription
querystringThe text you sent, echoed as received
verdictstringexact, ambiguous or none
candidatesobject[]Always served. Ordered by nature (cas, ec, inci, e_number, name), then by identifier - a mechanical order, never a relevance ranking. At most 25
totalnumberCandidates found before the cap; the verdict is derived from it
truncatedboolWhether the served list is cut
referentialsobject[]Every referential in scope: referential, authority (binding / information_only), searched, source, as_of, and version (the ATP in application, the consolidated text) when published
source_identifiers_not_usablenumberIdentifier cells the referentials publish for this text that are not usable identifiers. Absent when zero - its absence is the guarantee no published identifier was set aside
limitsstringThe fixed sentence quoted above

Each candidate:

FieldTypeDescription
idstringThe identifier, to pass downstream as is
id_kindstringcas, ec, inci, e_number or name
labelstringThe designation as the source publishes it - from the first referential in the fixed query order
sourcesstring[]The referentials that publish this identifier for your text. The same identifier from several referentials is one candidate whose sources merge
endpointsstring[]The routes this identifier opens

Example - exact

GET /label/lookup?q=Advantame:

{
  "data": {
    "query": "Advantame",
    "verdict": "exact",
    "candidates": [
      {
        "id": "E969",
        "id_kind": "e_number",
        "label": "Advantame",
        "sources": ["food_additives"],
        "endpoints": ["/label/food/additive"]
      }
    ],
    "total": 1,
    "truncated": false,
    "referentials": [
      { "referential": "annex_vi", "authority": "binding", "searched": true, "source": "ECHA Annex VI (CLP), harmonised classification and labelling", "as_of": "2026-05-01", "version": "Annex VI to CLP — harmonised entries in application (latest adaptation: ATP22)" },
      { "referential": "candidate_list", "authority": "binding", "searched": true, "source": "ECHA Candidate List of SVHC (REACH Art. 59(10))", "as_of": "2026-10-12" },
      { "referential": "cosmetics", "authority": "binding", "searched": true, "source": "Regulation (EC) No 1223/2009 on cosmetic products — consolidated text (EUR-Lex), Annexes II to VI", "as_of": "2026-05-01", "version": "02009R1223 — EN — 01.05.2026" },
      { "referential": "cosing_index", "authority": "information_only", "searched": true, "source": "CosIng (European Commission) via public EU Search API", "as_of": "2026-05-01" },
      { "referential": "food_additives", "authority": "binding", "searched": true, "source": "Regulation (EC) No 1333/2008 on food additives — consolidated text (EUR-Lex), Annex II (Union list by food category) and Annex III", "as_of": "2026-08-18", "version": "02008R1333 — EN — 18.08.2026" }
    ],
    "limits": "A resolution names what the referential publishes for the text you sent, as of the date carried by the provenance; it does not certify that the entity resolved is the one you had in mind. A common name may designate a group of substances rather than a single one, and this resolution never chooses for you: every candidate found is listed. Matching is exact on the shared normalisation of the designations published by the referentials themselves — no fuzzy matching and no synonym dictionary of our own — so 'none' means the text is absent from the ingested referentials at that date, never that the substance is unregulated."
  },
  "provenance": {
    "source": "ECHA Annex VI (CLP), …; Regulation (EC) No 1333/2008 on food additives — …",
    "fetched_at": "2026-10-15T15:41:31.717766173Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-05-01T00:00:00Z" }
  }
}

A sweetener known only to the food-additive Union list: one identifier, one route. E969 goes straight into /label/food/additive?e_number=E969.

Example - ambiguous, three routes in one call

GET /label/lookup?q=sodium%20nitrite (referentials, limits and provenance as above):

{
  "data": {
    "query": "sodium nitrite",
    "verdict": "ambiguous",
    "candidates": [
      {
        "id": "7632-00-0",
        "id_kind": "cas",
        "label": "sodium nitrite",
        "sources": ["annex_vi", "cosmetics", "cosing_index"],
        "endpoints": ["/label/chem/classify", "/label/cosmetic/ingredient"]
      },
      {
        "id": "231-555-9",
        "id_kind": "ec",
        "label": "sodium nitrite",
        "sources": ["annex_vi", "cosmetics", "cosing_index"],
        "endpoints": ["/label/chem/classify", "/label/cosmetic/ingredient"]
      },
      {
        "id": "Sodium nitrite",
        "id_kind": "inci",
        "label": "Sodium nitrite",
        "sources": ["cosmetics", "cosing_index"],
        "endpoints": ["/label/cosmetic/ingredient"]
      },
      {
        "id": "E250",
        "id_kind": "e_number",
        "label": "Sodium nitrite",
        "sources": ["food_additives"],
        "endpoints": ["/label/food/additive"]
      }
    ],
    "total": 4,
    "truncated": false,
    "referentials": [ "…" ],
    "limits": "A resolution names what the referential publishes for the text you sent, …"
  },
  "provenance": { "…": "…" }
}

Four identifiers of one substance, each naming what it opens: the CAS and EC numbers reach the CLP harmonised classification and the cosmetics annexes, the INCI name reaches the cosmetics annexes, E250 reaches the food-additive Union list. Which one to follow depends on the product the agent is labelling

  • the lookup does not guess it.

Example - none

GET /label/lookup?q=dimethyl%20ketone (referentials as above, all five searched: true):

{
  "data": {
    "query": "dimethyl ketone",
    "verdict": "none",
    "candidates": [],
    "total": 0,
    "truncated": false,
    "referentials": [ "…" ],
    "limits": "A resolution names what the referential publishes for the text you sent, as of the date carried by the provenance; it does not certify that the entity resolved is the one you had in mind. A common name may designate a group of substances rather than a single one, and this resolution never chooses for you: every candidate found is listed. Matching is exact on the shared normalisation of the designations published by the referentials themselves — no fuzzy matching and no synonym dictionary of our own — so 'none' means the text is absent from the ingested referentials at that date, never that the substance is unregulated."
  },
  "provenance": {
    "source": "ECHA Annex VI (CLP), …; Regulation (EC) No 1333/2008 on food additives — …",
    "fetched_at": "2026-10-15T15:41:31.646002901Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-05-01T00:00:00Z" }
  }
}

A 200, billed - and the substance is regulated: “dimethyl ketone” is acetone, an Annex VI entry published as acetone; propan-2-one; propanone. q=propanone resolves it (CAS 67-64-1, EC 200-662-2). This is the none the page warned about: the absence of a designation, never the absence of a regulation.

Errors

Only requests the service cannot answer leave the 200 range - none of them are billed. There is no 404 for a designation the referentials do not publish: that is a none.

StatuscodeCase
400MISSING_PARAMETERq absent or empty
400INVALID_INPUTq without any letter or digit; a domain outside chem/cosmetic/food; product_type without domain=cosmetic
503DATA_UNAVAILABLENo referential in the requested scope is ingested - “no referential”, which is not “absent from the referential”
500INTERNALInternal error (detail logged, not exposed)
{ "code": "INVALID_INPUT", "error": "'product_type' narrows cosmetic annex entries only: pass it together with 'domain=cosmetic'" }
{ "code": "INVALID_INPUT", "error": "unknown domain: 'pharma' (expected one of 'chem', 'cosmetic', 'food')" }

Attribution

  • Annex VI of the CLP Regulation and the Candidate List of Substances of Very High Concern (REACH Article 59(10)), published by ECHA (legal notice - commercial reuse permitted).
  • Regulation (EC) No 1223/2009 on cosmetic products and Regulation (EC) No 1333/2008 on food additives, consolidated texts published on EUR-Lex (European Union).
  • The CosIng index of the European Commission, used for identity resolution only.

See also