CosIng API · Public REST endpoints · Signed SQL patches · Webhooks
CosIng API: the EU cosmetic ingredient database, delivered as a live API
The EU CosIng database (INCI names, CAS numbers, EINECS, Annex II–VI restrictions) as a REST API: free public endpoints to start today, and signed incremental SQL patches for production. For teams who need CosIng data in their product without scraping ec.europa.eu or maintaining a diff engine.
No API key
Query the CosIng database in one call
The public read endpoints require no registration and no API key. Copy, paste, and you have live CosIng data.
# Search the CosIng database by INCI name, CAS or EC number
curl "https://api.bdapi.app/api/public/cosing/search?q=phenoxyethanol&limit=1"
{
"rows": [{
"inci_name": "PHENOXYETHANOL",
"cas_no": "122-99-6",
"ec_no": "204-589-7",
"function_names": ["ANTIMICROBIAL", "PRESERVATIVE"],
"cosmetic_restriction": "V/29",
"slug": "phenoxyethanol",
"regulatory": { "annexes": [ /* Annex V entry, ref 29 */ ] }
}],
"total": 1
}
# Live substance counts per Annex (II-VI)
curl "https://api.bdapi.app/api/public/cosing/stats"
# Substances added to Annex II in the last 12 months
curl "https://api.bdapi.app/api/public/cosing/recently-prohibited?months=12"Response captured from the live API. Search covers regulated ingredients by default — add regulated_only=false for the full INCI inventory.
Reference
Public read endpoints, with documented rate limits
Eight read-only endpoints over the CosIng database and the regulatory watch feed. Limits are per IP per minute — published here because production software deserves to know its budget.
GET /api/public/cosing/searchFull-text search across INCI names, CAS and EC numbers. Defaults to regulated ingredients (Annexes II–VI); pass regulated_only=false to search the full INCI inventory.
60 req/minGET /api/public/cosing/statsLive counts per Annex (II–VI): substances, CAS numbers and inventory totals — the same numbers shown across this site.
30 req/minGET /api/public/cosing/ingredient/:slugFull ingredient detail: INCI name, CAS, EC number, functions, Annex restrictions and cross-references.
120 req/minGET /api/public/cosing/ingredients/slugsEvery ingredient slug with last-update timestamps — built for static-site generators and sitemap builds.
10 req/minGET /api/public/cosing/annex/:code/ingredientsPaginated ingredient list for one Annex — code is ii, iii, iv, v or vi.
60 req/minGET /api/public/cosing/cmrSubstances carrying a CMR classification (carcinogenic, mutagenic or reprotoxic).
60 req/minGET /api/public/cosing/recently-prohibitedSubstances added to Annex II within the last N months (?months=1–24, default 6), with update dates.
60 req/minGET /api/public/watch/latestLatest regulatory events across DG SANTE, SCCS, EUR-Lex and Safety Gate, with official source URLs.
60 req/minEvery response carries CDN-friendly Cache-Control headers. A 429 includes retryAfter in seconds. Full OpenAPI 3.1 specification on request →
Use cases
What teams build with it
Cosmetic formulation & PLM software
Validate INCI lists against Annex II–VI restrictions inside your own product. Prototype against the public endpoints, then move to the licensed sync for an offline PostgreSQL replica with no per-request dependency.
Certification bodies & regulatory consultants
Check CMR classifications, recent Annex II additions and restriction conditions programmatically before signing off a dossier — with every answer traceable to the official EC source.
Content, research & internal tooling
Power ingredient glossaries, dashboards and static sites with live Annex counts and per-ingredient detail. CDN-friendly cache headers make it cheap to consume at build time.
Production
The licensed sync API: four calls
Once the prototype works, production should not depend on per-request calls. The licensed API replicates the full CosIng dataset into your own PostgreSQL with signed incremental SQL patches.
# 1. Check whether a newer CosIng version exists
curl -X POST https://api.bdapi.app/api/versions/check \
-H "Authorization: Bearer $LICENSE_KEY" \
-H "Content-Type: application/json" \
-d '{"current_version": "1.0.0"}'
# 2. Download the signed incremental SQL patch
curl https://api.bdapi.app/api/versions/1.1.0/patch \
-H "Authorization: Bearer $LICENSE_KEY" \
-o patch.sql
# 3. Verify SHA-256 integrity before applying
curl -sI https://api.bdapi.app/api/versions/1.1.0/patch \
-H "Authorization: Bearer $LICENSE_KEY" \
| grep -i x-hash-sha256
# 4. Apply in a single PostgreSQL transaction, then confirm
psql -1 -f patch.sql && curl -X POST .../api/versions/confirm \
-H "Authorization: Bearer $LICENSE_KEY" \
-d '{"version":"1.1.0","success":true,"error":null}'If the hash does not match, the apply never happens. Automatic rollback if the transaction fails. No surprises.
Evaluation
CosIng API vs the alternatives
Three ways to access CosIng data. Only one is built for production.
| BD-API CosIng API | Downloading the official .xls | Consumer ingredient-lookup APIs | |
|---|---|---|---|
| Freshness | Auto-synced on every EC XLS change (CRON-driven, weekly by default, up to daily) | Manual re-download required — you notice changes only when you check | Varies; often days or weeks behind the official source |
| Integrity | SHA-256 signed patches + HMAC-SHA256 webhook notifications | None — no hash, no signature, no way to detect tampering | None at the data layer |
| Format | Structured PostgreSQL with FK between Annexes, substances and CAS numbers | Raw spreadsheet cells — columns shift between releases | Per-request JSON — one lookup at a time, no relational structure |
| Delivery | Incremental signed patches applied inside a single SQL transaction | Full-file download every time, even if one row changed | One ingredient per API call — no batch, no sync |
| Audit trail | Source, timestamp and verifiable proof per change — what auditors require | None — you cannot prove when you received the data or what changed | None at the data layer |
| Built for | Cosmetic software vendors who need CosIng live in their product | One-off human checks by regulatory affairs teams | B2C apps and ingredient safety scores for end users |
BD-API CosIng API
Auto-synced on every EC XLS change (CRON-driven, weekly by default, up to daily)
Official .xls download
Manual re-download required — you notice changes only when you check
Consumer lookup APIs
Varies; often days or weeks behind the official source
BD-API CosIng API
SHA-256 signed patches + HMAC-SHA256 webhook notifications
Official .xls download
None — no hash, no signature, no way to detect tampering
Consumer lookup APIs
None at the data layer
BD-API CosIng API
Structured PostgreSQL with FK between Annexes, substances and CAS numbers
Official .xls download
Raw spreadsheet cells — columns shift between releases
Consumer lookup APIs
Per-request JSON — one lookup at a time, no relational structure
BD-API CosIng API
Incremental signed patches applied inside a single SQL transaction
Official .xls download
Full-file download every time, even if one row changed
Consumer lookup APIs
One ingredient per API call — no batch, no sync
BD-API CosIng API
Source, timestamp and verifiable proof per change — what auditors require
Official .xls download
None — you cannot prove when you received the data or what changed
Consumer lookup APIs
None at the data layer
BD-API CosIng API
Cosmetic software vendors who need CosIng live in their product
Official .xls download
One-off human checks by regulatory affairs teams
Consumer lookup APIs
B2C apps and ingredient safety scores for end users
CosIng API
Questions about the data and delivery
Is there a free public CosIng API I can try without an API key?+
Yes. The read endpoints under /api/public — search, stats, ingredient detail, Annex listings, CMR, recently prohibited and the regulatory watch feed — require no API key and no registration. They are rate-limited per IP (10 to 120 requests per minute depending on the route) and served with CDN-friendly cache headers. The licensed API adds what production needs: signed incremental SQL patches into your own PostgreSQL, webhooks and email alerts. Hands-on guide with verified examples →
Why does the public search return no results for some well-known ingredients?+
By default /cosing/search only returns ingredients whose Annex II–VI entry is linked in the relational layer — that is what most compliance lookups need. Some inventory entries, retinol among them, are keyed under a separate substance record, so they do not appear in the default result set. Pass regulated_only=false to search the full INCI inventory of roughly 33,000 entries.
What exactly does the CosIng API return?+
Each sync returns a signed incremental SQL patch: only the rows that changed since your current version. The patch contains UPSERT statements for substances, CAS numbers, EINECS entries and Annex restrictions (Annexes II–VI), plus a SHA-256 hash in the response headers. You apply it in a single PostgreSQL transaction and confirm with a follow-up call. Nothing is overwritten blindly — every column that changed has a before/after trace.
How is it kept in sync with the official CosIng?+
BD-API polls the official European Commission XLS on a configurable CRON schedule — weekly by default, configurable up to daily. When a new XLS is published, the diff engine runs within minutes, produces a versioned SQL patch, and queues it for delivery. Your installation polls /api/versions/check at whatever cadence you prefer — you only download when there is actually a newer version.
Is it a per-request lookup or a full dataset?+
Neither. It is incremental: on first sync you receive a full baseline, on every subsequent sync you receive only what changed. You own a live PostgreSQL replica of the full CosIng dataset — all ~2,385 entries across Annexes II–VI — with foreign keys between Annexes, substances and CAS numbers. No per-query fees, no round-trips at request time, no rate-limit surprises in production. Browse the CosIng database →
How do I verify the data has not been tampered with?+
Every patch ships with a SHA-256 hash in the x-hash-sha256 response header. Your client downloads the patch, computes the hash locally, and compares before calling psql. If the hashes do not match, the apply never happens. Webhook notifications from the watch pipeline carry an HMAC-SHA256 signature you verify with your shared secret before processing.
Can I self-host the data?+
Yes — that is the whole point. Patches are pure SQL in your own PostgreSQL. BD-API has no read path into your database, no SDK that must stay running, and no proprietary binary format. If you ever stop using BD-API, the data you have already applied stays in your database, intact and queryable forever. Seven criteria to evaluate a CosIng data source →