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/search

Full-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/min
GET /api/public/cosing/stats

Live counts per Annex (II–VI): substances, CAS numbers and inventory totals — the same numbers shown across this site.

30 req/min
GET /api/public/cosing/ingredient/:slug

Full ingredient detail: INCI name, CAS, EC number, functions, Annex restrictions and cross-references.

120 req/min
GET /api/public/cosing/ingredients/slugs

Every ingredient slug with last-update timestamps — built for static-site generators and sitemap builds.

10 req/min
GET /api/public/cosing/annex/:code/ingredients

Paginated ingredient list for one Annex — code is ii, iii, iv, v or vi.

60 req/min
GET /api/public/cosing/cmr

Substances carrying a CMR classification (carcinogenic, mutagenic or reprotoxic).

60 req/min
GET /api/public/cosing/recently-prohibited

Substances added to Annex II within the last N months (?months=1–24, default 6), with update dates.

60 req/min
GET /api/public/watch/latest

Latest regulatory events across DG SANTE, SCCS, EUR-Lex and Safety Gate, with official source URLs.

60 req/min

Every 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.

Freshness

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

Integrity

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

Format

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

Delivery

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

Audit trail

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

Built for

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 →

Ready to put CosIng data in your product?