CosIng API · Public REST endpoints · Integrity-verified 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 integrity-verified incremental SQL patches for production. For teams who need CosIng data in their product without scraping ec.europa.eu or maintaining a diff engine.

Free API key

Query the CosIng database in one call

The public read endpoints use a free API key that you get with your email. Send it in the X-API-Key header. 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" \
  -H "X-API-Key: $BDAPI_API_KEY"

{
  "rows": [{
    "result_type": "ingredient",
    "inci_name": "PHENOXYETHANOL",
    "cas_no": "122-99-6",
    "ec_no": "204-589-7",
    "chemical_name": "2-Phenoxyethanol",
    "function_names": ["ANTIMICROBIAL", "PRESERVATIVE"],
    "slug": "phenoxyethanol",
    "has_fiche": true,
    "matched_via": "inci",
    "fiche_url": "https://bdapi.app/en/cosing-database/ingredient/phenoxyethanol/"
  }],
  "total": 1
}

# Live substance counts per Annex (II-VI)
curl "https://api.bdapi.app/api/public/cosing/stats" \
  -H "X-API-Key: $BDAPI_API_KEY"

Response trimmed for readability. Search covers regulated ingredients by default — add regulated_only=false for the full INCI inventory. The free daily quota is 500 requests per email. Since 12 October 2026, calls without a key return 401 api_key_required. The search on bdapi.app stays free and needs no key.

The free key covers ingredient identity. The regulatory data (Annex, reference number, maximum concentrations, conditions and warnings) is on the paid plans. See plans →

Get a free API key

Enter your email and we will send you a key. It is only delivered by email. The free daily quota is 500 requests per email.

Reference

Public read endpoints, with documented rate limits

Three read-only endpoints on the free key: identity search, Annex counts 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

Ingredient identity search by INCI name, CAS or EC number. Each row returns INCI name, CAS, EC number, chemical name, functions and fiche_url, the link to the public fiche on bdapi.app. 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/watch/latest

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

60 req/min

Paid plans: the other /api/public/cosing/* routes return regulatory data and answer 403 paid_plan_required to the free key: ingredient/:slug, ingredients/slugs, annex/:code/ingredients, cmr, allergens, microplastics, recently-prohibited, substance/:slug, substances/slugs, functions/slugs, function/:slug/ingredients, ingredient/:slug/publications, publication/ingredients.

Every response carries CDN-friendly Cache-Control headers. Error codes: 401 api_key_required or invalid_api_key (missing or invalid key), 403 paid_plan_required (paid-plan route; not counted against the quota), 429 daily_quota_exceeded (daily quota used up until the next UTC day) and the rate-limit 429, which 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 the ingredient lookup against the free endpoints, then move to a paid plan for the regulatory data and the licensed sync: 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 ingredient identity lookups. 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 integrity-verified 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 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

Patches verified with SHA-256 + 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 SHA-256 verified 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?+

Yes. Ingredient identity search (/api/public/cosing/search: INCI name, CAS, EC number, chemical name, functions and a link to the public fiche) and the Annex counts (/api/public/cosing/stats) are free with an API key that you get with your email. Send it in the X-API-Key header. The regulatory data (Annex entries, maximum concentrations, conditions, warnings, the Annex and CMR listings and the full ingredient detail) is on the paid plans; with the free key those routes return 403 paid_plan_required. The free daily quota is 500 requests per email, on top of the per-IP limits (30 to 60 requests per minute depending on the route). Since 12 October 2026, calls without a key return 401 api_key_required. The search on bdapi.app stays free and needs no key, and so does the regulatory watch feed (/api/public/watch). Responses are served with CDN-friendly cache headers. The licensed API adds what production needs: SHA-256-verified 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 an integrity-verified (SHA-256) 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?