Europa APIec.europa.eu ↗
Search and retrieve European Binding Tariff Information (BTI) decisions from the EC EBTI database. Filter by country, nomenclature, dates, and keywords.
What is the Europa API?
The EC EBTI API provides access to the European Commission's Binding Tariff Information database through 2 endpoints, returning structured data on BTI decisions issued by EU member state customs authorities. The search_bti endpoint lets you query decisions by issuing country, goods description, validity dates, and EBTI keywords, while get_bti returns the complete record for a single decision including classification justification, goods description, and issuing authority details.
curl -X GET 'https://api.parse.bot/scraper/bff86fe0-12df-4ac5-83e3-d30b64895fb1/search_bti?nomenclature_code=84' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace ec-europa-eu-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: EBTI SDK — search tariff decisions, drill into details."""
from parse_apis.ec_europa_eu_api import Ebti, OrderBy, InputNotFound
client = Ebti()
# Search for BTI decisions in HS chapter 84, sorted by start date.
for summary in client.decision_summaries.search(
nomenclature_code="84",
order_by=OrderBy.START_DATE,
limit=5,
):
print(summary.reference, summary.nomenclature_code, summary.status)
# Drill into the first German result for full goods description.
hit = client.decision_summaries.search(country="DE", limit=1).first()
if hit is not None:
detail = hit.details()
print(detail.reference, detail.goods_description[:120])
print("Keywords:", detail.keywords)
print("Justification:", detail.justification)
# Direct point-lookup by a reference discovered above.
if hit is not None:
try:
decision = client.decisions.get(reference=hit.reference)
print(decision.issuing_authority, decision.place_of_issue)
except InputNotFound:
print("Decision not found")
print("exercised: decision_summaries.search / details / decisions.get")
Searches the EBTI database and returns one page of BTI decision summaries (25 per page, fixed by the site), each with its reference, issuing country, nomenclature code, validity dates, status and image count; use get_bti for the full record. All filters are optional and combine (AND). With no filters the whole set of currently valid decisions is enumerated; include_invalid adds expired/revoked decisions. A nomenclature filter matches codes starting with the given digits (a 2-digit HS chapter such as 84, or a longer CN/TARIC prefix) and nomenclature_code_to turns it into an inclusive range of prefixes. Validity start/end date ranges are inclusive. Pagination is page-based: page omitted or 1 returns the first page; total, total_pages and has_more come from the site. A search with no matches returns an empty results array with total 0. Each call costs two upstream requests (one session bootstrap plus the list page).
| Param | Type | Description |
|---|---|---|
| page | integer | 1-based page number; the site serves 25 results per page. |
| country | string | Two-letter code of the EU member state whose customs authority issued the decision (e.g. NL). Case-insensitive. |
| keywords | string | Comma-separated list of EBTI keywords (e.g. live,animals); a decision matches if it carries any of them. Do NOT pass an array. |
| order_by | string | Sort order of the result set. Omitted = the site's default ordering. |
| description | string | Free text searched in the goods description (at least 3 characters). |
| end_date_to | string | Latest end date of validity to include, ISO date YYYY-MM-DD. |
| end_date_from | string | Earliest end date of validity to include, ISO date YYYY-MM-DD. |
| start_date_to | string | Latest start date of validity to include, ISO date YYYY-MM-DD. |
| include_invalid | boolean | When true, expired and revoked decisions are included alongside currently valid ones. |
| start_date_from | string | Earliest start date of validity to include, ISO date YYYY-MM-DD. |
| nomenclature_code | string | Nomenclature (HS/CN/TARIC) code prefix, 2 to 10 digits, e.g. 84 for HS chapter 84 or 8471 for a heading. Matches decisions whose code starts with these digits (or lies in the range up to nomenclature_code_to when that is given). |
| nomenclature_code_to | string | Upper bound of an inclusive nomenclature code range, 2 to 10 digits; only meaningful together with nomenclature_code. |
{
"type": "object",
"fields": {
"page": "integer, the page returned",
"total": "integer, total number of matching decisions reported by the site",
"results": "array of BTI summaries: reference (BTI reference number, use with get_bti), country (2-letter issuing country), nomenclature_code (digits of the HS/CN/TARIC code), nomenclature_code_full (code as displayed by the site, including * padding and any additional code), start_date and end_date of validity (YYYY-MM-DD), status (e.g. VALID), image_count (integer)",
"has_more": "boolean, true when a later page exists",
"page_size": "integer, always 25",
"total_pages": "integer, number of pages available"
},
"sample": {
"data": {
"page": 2,
"total": 10902,
"results": [
{
"status": "VALID",
"country": "FR",
"end_date": "2028-06-30",
"reference": "FRBTIFR-BTI-2025-02287",
"start_date": "2025-07-01",
"image_count": 0,
"nomenclature_code": "84289090",
"nomenclature_code_full": "84289090**************"
}
],
"has_more": true,
"page_size": 25,
"total_pages": 437
},
"status": "success"
}
}About the Europa API
What the API Covers
The European Commission's EBTI (European Binding Tariff Information) database holds official tariff classification decisions issued by customs authorities across EU member states. Each BTI decision binds the issuing authority to a specific nomenclature code for a described good, and these decisions are publicly searchable. This API exposes both the search interface and the full decision detail.
search_bti Endpoint
The search_bti endpoint returns paginated summaries of BTI decisions. Results come back 25 per page (page_size is always 25), and the response includes total, total_pages, and has_more fields to support iteration. Each summary in the results array includes the reference number, country (two-letter issuing member state code), nomenclature_code, validity dates, decision status, and image count. Filters can be combined freely: use country (e.g. NL, DE) to narrow by issuing authority, description for free-text goods search (minimum 3 characters), keywords for comma-separated EBTI keyword matching, and end_date_from/end_date_to or start_date_to to filter by validity window. The order_by parameter controls sort order when the default ordering is not suitable.
get_bti Endpoint
Passing a reference value from a search result to get_bti returns the complete BTI record. The response includes goods_description and justification (the classification legal basis text), both in the decision's original language (indicated by the language field). Additional fields cover issue_date, start_date, end_date, place_of_issue, keywords (as an array), nomenclature_code, and the issuing country. This is the endpoint to use when you need the full text of the classification reasoning or need to verify the exact legal basis for a tariff code assignment.
Limitations and Notes
Decision texts and goods descriptions are returned in the language of the issuing member state — there is no automatic translation. The search endpoint does not expose a filter for nomenclature code directly; locating decisions by CN or HS code requires matching through description or keywords. Pagination is fixed at 25 results per page as set by the source database.
The Europa API is a managed, monitored endpoint for ec.europa.eu — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when ec.europa.eu changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official ec.europa.eu API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Checking the tariff nomenclature code assigned to a specific product description across EU member states
- Building a compliance tool that alerts importers when BTI decisions for their goods categories are nearing their
end_date - Aggregating BTI decisions by
countryto compare how different customs authorities classify the same class of goods - Extracting the
justificationtext fromget_btito analyze the legal basis cited in classification decisions - Feeding BTI
keywordsandnomenclature_codedata into a customs classification training dataset - Monitoring newly issued decisions in a specific validity date range using
start_date_toandend_date_fromfilters - Cross-referencing BTI decisions with HS code databases using the
nomenclature_codefield returned by both endpoints
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does the European Commission provide an official developer API for the EBTI database?+
Can I search for BTI decisions by nomenclature or HS code directly?+
nomenclature_code filter parameter in search_bti. The available filters are country, description, keywords, order_by, and date-range fields. If you need to locate decisions for a specific CN or HS code, matching via description text is the closest available option. You can fork this API on Parse and revise it to add a nomenclature code filter if the source supports one.What does get_bti return beyond what search_bti already provides?+
search_bti returns a summary per decision: reference, country, nomenclature_code, validity dates, status, and image count. get_bti adds the full goods_description, the justification (classification legal basis text), place_of_issue, issue_date, language, and the keywords array — fields not included in the search summary.Are BTI decisions from all EU member states included?+
Does the API return image attachments associated with BTI decisions?+
search_bti results include an image count per decision, indicating how many images are attached. However, get_bti does not currently return image URLs or binary image data — only structured text fields. You can fork this API on Parse and revise it to add image retrieval if the source exposes image files.