# Is this substance on the REACH Candidate List? > The SVHC Candidate List changes about twice a year, past every model cutoff. One offline call returns a dated verdict, the Article 57 reasons, and the duties inclusion triggers. Published 2026-08-10 · HTML version: https://invoket.com/blog/is-this-substance-on-the-reach-candidate-list --- An agent asked whether a substance is a **Substance of Very High Concern** has asked a question that only a *dated* answer can settle. The ECHA **Candidate List** under **REACH Article 59(10)** is a moving legal publication: it gained its two most recent entries on **4 February 2026**, and it will move again. A model answering from training data answers from whichever version of the list it last saw — and cannot know it is out of date. [`GET /label/chem/svhc`](/docs/api/label-chem-svhc) answers from the **last published list**, honestly dated: `listed` or `not_listed`, the **Article 57** reasons for inclusion, the inclusion date, the ECHA decision documents, and the generic supply-chain obligations the listing triggers — resolved from a local store, with no network call and no secret at request time. ## Why a language model is the wrong source for this list The Candidate List is not a stable reference text. ECHA has updated it **36 times since its first publication on 28 October 2008**, reaching **253 entries** with the update of 4 February 2026 — roughly two updates a year, every year, for seventeen years. Two properties follow, and both break model recall: - **Every update lands after some model's cutoff.** The February 2026 update added *n*-hexane (CAS 110-54-3), on the ground of "Specific target organ toxicity after repeated exposure (Article 57(f) - human health)", and Bisphenol AF (CAS 1478-61-1), "Toxic for reproduction (Article 57c)". A model trained before that date does not know these two entries exist, and has no way to signal the gap. - **Only the published list is authentic.** Article 59(10) requires ECHA to publish and update the Candidate List on its website without delay once an inclusion decision is taken. The list on that site is the list; a reconstruction from memory is not a weaker version of it, it is a different object. The failure mode is not a refusal. It is a fluent, plausible, undated answer — the exact shape a compliance decision must not be built on. ## 253 entries, just over 500 substances An **entry** on the Candidate List is not always a single substance. Several entries are **groups**: a family of stereoisomers, a set of salts, a range of related compounds, all covered by one inclusion decision. The published export expands those groups into their individual members, which is why the list served on **2026-08-01** carries **253 published entries** but just over **500 substance records**, indexed by roughly 770 identifiers. That expansion is the whole reason a CAS lookup can work at all. An agent holding a CAS number from a supplier declaration does not know whether that number sits in the list under its own name or inside a group entry — the endpoint resolves either case to the entry that governs it. ## One call, one dated verdict `GET /label/chem/svhc?cas=84-74-2` — dibutyl phthalate, an entry that carries several identifiers, cumulative reasons and its decision documents: ```json { "data": { "verdict": "listed", "entries": [ { "name": "Dibutyl phthalate (DBP)", "identifiers": [{ "ec": "201-557-4" }, { "cas": "84-74-2" }], "reasons": [ "Toxic for reproduction (Article 57c)", "Endocrine disrupting properties (Article 57(f) - environment)", "Endocrine disrupting properties (Article 57(f) - human health)" ], "included_at": "2008-10-28", "decisions": [ "https://echa.europa.eu/documents/10162/d33fd29e-5170-440f-8c16-10ecd87cf472", "..." ], "obligations": { "article_33": "...", "scip": "..." } } ] }, "provenance": { "source": "ECHA Candidate List of SVHC (REACH Art. 59(10))", "freshness": { "kind": "snapshot", "as_of": "2026-08-01T00:00:00Z" } } } ``` Four points in that payload carry the weight: - **`reasons` are cumulative and verbatim.** An entry accumulates Article 57 grounds over its life — DBP was included in 2008 for reproductive toxicity and gained endocrine-disruption grounds later. The strings are the regulatory publication, not a paraphrase. - **`identifiers` are relayed individually, never paired.** The Candidate List publishes EC and CAS numbers **without a 1:1 correspondence**, so each is a separate `{ ec }` or `{ cas }` object. Pairing them would invent a mapping the regulator does not publish. - **`decisions` count documents, not reasons.** ECHA publishes one decision document per ground added over time, as URLs only — no short reference of the `ED/01/2021` kind exists in the source, so none is served. The DBP entry carries four documents for three reasons, and that asymmetry is the source's. - **`freshness.as_of` is the publication date of the list served**, not the ingestion date. The dated list *is* the answer. ## `not_listed` is an answer, and it is billed A well-formed CAS the list does not carry is not a miss. `cas=7732-18-5` (water) returns a **200** with `verdict: "not_listed"`, an empty `entries`, and a note that refuses to overclaim: > Not on the ECHA Candidate List of SVHC as published on 2026-08-01. This > verdict is dated: it means the substance was not listed at that date, not that > it never will be. Absence from the Candidate List does not mean the substance > is of no concern. This is the x402 golden rule applied to a register: the agent asked "is this on the list?", and "not on the list published on ``" is the answer it paid for — never a 404. Only requests the service *cannot* answer leave the 200 range and go unbilled: no key, several keys, a bad check digit, an empty name. ## Three keys, and the ones that only a name reaches Exactly one of `cas`, `ec` or `name` per call. `cas` and `ec` are **check-digit validated before any lookup**, with the same rigour as an IBAN's mod-97 — a transposed digit is a `400 INVALID_INPUT` naming the rejected literal, not a confident lookup of the wrong substance: ```json { "code": "INVALID_INPUT", "error": "invalid CAS check digit: '84-74-3'" } ``` Two consequences of the source shape are worth wiring into an agent: - **Some SVHC have no CAS and no EC number.** UVCB substances — of Unknown or Variable composition — are reachable **only by their exact Candidate List name**, and their entry carries an empty `identifiers` array. Medium-chain chlorinated paraffins (MCCP), listed 2021-07-08 for PBT and vPvB grounds, is one of them. - **An ambiguous name is never disambiguated silently.** `name=Boric acid` returns **both** Candidate List entries that carry that name, one of them without identifiers. Picking one would be a guess presented as a fact. Lookup is by CAS, EC or **exact** name — there is no fuzzy search in v1. An agent working from free text should resolve to an identifier first. ## The obligations it relays — and the line it does not cross Every listed entry carries the two supply-chain duties that inclusion triggers, as fixed sourced text: - **REACH Article 33** — a supplier of an article containing the substance above **0.1 % w/w** must give the recipient sufficient information for safe use, including at minimum the substance name; on request, the same information goes to a consumer within **45 days, free of charge**. - **SCIP notification** — under the Waste Framework Directive 2008/98/EC, Article 9(1)(i), suppliers placing such articles on the EU market must submit information on them to the ECHA SCIP database, an obligation in force since 5 January 2021. These are the **same constants on every listed entry**, and that is deliberate. The service relays the obligation an inclusion *triggers*; it does **not** compute whether that obligation applies to *your* article. It does not know your concentration, your role in the supply chain, your importer status, or your product. Nor does it cover the separate REACH Article 7(2) notification duty for producers and importers of articles. Treat `obligations` as generic regulatory facts — never as a compliance verdict on your case, and never as legal advice. That boundary is the service. The same discipline governs freshness: the list is refreshed off-band from the official ECHA publication, and a missed refresh keeps serving the last good snapshot with `freshness.as_of` telling the truth about it. Staleness never becomes a 5xx. A dataset never ingested at all is a `503 DATA_UNAVAILABLE` — there is no last good snapshot to serve. ## Where it sits in the x402 loop No account, no key, no contract review precedes the first call: 1. **Discover** the endpoint in the live catalog, call it, receive the `402` challenge. 2. **Pay** — sign the chosen rail and replay the request. 3. **Read** — `verdict`, `reasons`, `included_at`, `decisions`, `obligations`, and the `as_of` that dates all of it. 4. **Branch** — clear the substance, flag the article for an Article 33 and SCIP workflow, or route it to a human with the ECHA decision documents cited. A bill of materials does not need one settlement per line: [`POST /label/chem/svhc/batch`](/docs/api/label-chem-svhc-batch) screens up to **200** substances — mixing CAS, EC and exact names — in a single call, priced per unit. The [Quickstart](/docs/quickstart) walks the full discover → `402` → pay → replay cycle with runnable snippets. Price and accepted rails are served live by the [catalog](https://api.invoket.com/catalog), never pinned in an article. ## Chain it with the rest of the label family Candidate List status is one dated regulatory verdict among several, and they compose: - [`GET /label/chem/classify`](/docs/api/label-chem-classify) — the harmonised CLP classification of a substance (Annex VI), **versioned by ATP**: hazard classes, H statements and pictograms as in force at the date you ask. - [`GET /label/cosmetic/ingredient`](/docs/api/label-cosmetic-ingredient) — prohibited, restricted or annex-authorised status under Regulation (EC) No 1223/2009. - [`GET /label/food/additive`](/docs/api/label-food-additive) — whether an additive is authorised in a given food category, at which level. A pre-market screen usually runs `chem/classify` and `chem/svhc` together: the first says what the label must carry, the second says what the supply chain must be told. Both answer from a dated publication rather than from recall — which is the only property that makes either of them safe to put behind an autonomous agent. For the full field reference and error codes, see the [`GET /label/chem/svhc` documentation](/docs/api/label-chem-svhc); for how agents discover and call Invoket endpoints, see [For agents](/docs/for-agents).