API-documentatie
Integreer HS code classificatie in je applicaties met de Import8 REST API.
https://import8.nl/api
Authenticatie
Alle API-verzoeken (behalve /health) vereisen authenticatie via een API key. Genereer API keys in je dashboard.
Stuur je API key mee via de Authorization header met het Bearer-schema:
curl -H "Authorization: Bearer c8_your_api_key" \
https://import8.nl/api/v1/me
import requests
response = requests.get(
"https://import8.nl/api/v1/me",
headers={"Authorization": "Bearer c8_your_api_key"}
)
print(response.json())
const response = await fetch('https://import8.nl/api/v1/me', {
headers: { 'Authorization': 'Bearer c8_your_api_key' }
});
const data = await response.json();
Verbruik bijhouden
Alle classificatie-endpoints bevatten een usage object in de response, zodat je je resterende credits kunt bijhouden zonder een apart API-verzoek.
"usage": {
"credits_remaining": 47
}
| Veld | Type | Beschrijving |
|---|---|---|
| credits_remaining | integer | Aantal resterende credits over alle actieve saldi |
/v1/classify
Dien een product in voor HS code classificatie. De classificatie wordt asynchroon verwerkt -- je ontvangt een 202 Accepted response met een classificatie-ID. Poll voor resultaten of configureer een webhook.
Request Body
| Parameter | Type | Verplicht | Beschrijving |
|---|---|---|---|
| image_url | string | optional | URL van een productafbeelding (maximaal 5 afbeeldingen) |
| image_base64 | string | optional | Base64-gecodeerde productafbeelding |
| description | string | optional | Productbeschrijving als tekst |
| origin_country | string | optional | 2-letterige ISO landcode van het herkomstland |
| destination_country | string | optional | 2-letterige ISO landcode (standaard: NL) |
| goods_value | number | optional | Eenheidsprijs van de goederen (FOB). Indien opgegeven wordt de landed cost automatisch berekend na classificatie. |
| quantity | integer | optional | Aantal eenheden (standaard: 1) |
| shipping_cost | number | optional | Verzend- / vrachtkosten (standaard: 0) |
| insurance_cost | number | optional | Verzekeringskosten (standaard: 0) |
| currency | string | optional | 3-letterige valutacode (standaard: EUR). Ondersteund: EUR, USD, GBP, CNY. |
Let op: Minimaal een van image_url, image_base64, of description is verplicht.
Landed cost: Wanneer goods_value is opgegeven, bevat het classificatieresultaat een landed_cost object met CIF-waarde, invoerrechten, antidumping, BTW en totale landed cost. Dit gebruikt dezelfde berekening als het standalone POST /v1/landed-cost endpoint.
Voorbeeldverzoek
curl -X POST https://import8.nl/api/v1/classify \
-H "Authorization: Bearer c8_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"description": "Wireless bluetooth over-ear headphones with noise cancellation",
"image_url": "https://example.com/product.jpg",
"origin_country": "CN",
"destination_country": "NL",
"goods_value": 25.00,
"quantity": 100,
"shipping_cost": 150.00,
"insurance_cost": 12.50,
"currency": "EUR"
}'
import requests
response = requests.post(
"https://import8.nl/api/v1/classify",
headers={"Authorization": "Bearer c8_your_api_key"},
json={
"description": "Wireless bluetooth over-ear headphones with noise cancellation",
"image_url": "https://example.com/product.jpg",
"origin_country": "CN",
"destination_country": "NL",
"goods_value": 25.00,
"quantity": 100,
"shipping_cost": 150.00,
"insurance_cost": 12.50,
"currency": "EUR"
}
)
data = response.json()
classification_id = data["data"]["id"]
print(f"Classification queued: {classification_id}")
const response = await fetch('https://import8.nl/api/v1/classify', {
method: 'POST',
headers: {
'Authorization': 'Bearer c8_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
description: 'Wireless bluetooth over-ear headphones with noise cancellation',
image_url: 'https://example.com/product.jpg',
origin_country: 'CN',
destination_country: 'NL',
goods_value: 25.00,
quantity: 100,
shipping_cost: 150.00,
insurance_cost: 12.50,
currency: 'EUR',
}),
});
const { data } = await response.json();
console.log('Classification queued:', data.id);
Response 202 Accepted
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"message": "Classification queued. Poll GET /v1/classifications/{id} for results, or configure a webhook to receive notifications."
},
"usage": {
"credits_remaining": 47
}
}
/v1/classifications/{id}
Haal een classificatieresultaat op via het UUID. Poll dit endpoint na het indienen van een classificatieverzoek totdat de status verandert van pending naar completed.
Voorbeeldverzoek
curl https://import8.nl/api/v1/classifications/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer c8_your_api_key"
import requests
import time
classification_id = "550e8400-e29b-41d4-a716-446655440000"
# Poll until completed (typically 25-35 seconds)
while True:
response = requests.get(
f"https://import8.nl/api/v1/classifications/{classification_id}",
headers={"Authorization": "Bearer c8_your_api_key"}
)
data = response.json()["data"]
if data["status"] == "completed":
print(f"HS Code: {data['hs_code']['code_8']}")
print(f"Confidence: {data['confidence']}%")
break
elif data["status"] == "failed":
print("Classification failed")
break
time.sleep(5)
const classificationId = '550e8400-e29b-41d4-a716-446655440000';
// Poll until completed
async function pollResult() {
const response = await fetch(
`https://import8.nl/api/v1/classifications/${classificationId}`,
{ headers: { 'Authorization': 'Bearer c8_your_api_key' } }
);
const { data } = await response.json();
if (data.status === 'completed') return data;
if (data.status === 'failed') throw new Error('Classification failed');
await new Promise(r => setTimeout(r, 5000));
return pollResult();
}
Response 200 OK
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"source": "api",
"created_at": "2026-03-03T12:00:00+00:00",
"hs_code": {
"code_6": "8518.30",
"code_8": "8518.30.00",
"description": "Headphones and earphones",
"chapter": "85"
},
"confidence": 92,
"reasoning": "The product is wireless bluetooth headphones, which fall under HS heading 8518 for microphones, loudspeakers, and headphones.",
"decision_tree": [
{"level": "section", "code": "XVI", "description": "Machinery and mechanical appliances"},
{"level": "chapter", "code": "85", "description": "Electrical machinery and equipment"},
{"level": "heading", "code": "8518", "description": "Microphones, loudspeakers, headphones"}
],
"alternative_codes": [
{
"code": "8518.10.00",
"description": "Microphones",
"reasoning": "Would apply if the product includes a built-in microphone as primary function"
}
],
"product_summary": "Wireless bluetooth over-ear headphones with noise cancellation",
"ai_usage": {
"input_tokens": 1234,
"output_tokens": 567,
"cost_usd": 0.00408
},
"completed_at": "2026-03-03T12:00:30+00:00",
"landed_cost": {
"cif_value": 2662.50,
"duty": {
"rate": "0.0%",
"amount": 0,
"type": "mfn"
},
"anti_dumping": {
"rate": "0.0%",
"amount": 0
},
"vat": {
"rate": "21.00%",
"amount": 559.13
},
"total_landed_cost": 3221.63,
"currency": "EUR"
}
},
"usage": {
"credits_remaining": 47
}
}
/v1/classifications
Bekijk alle classificaties van je organisatie, gesorteerd op nieuwste eerst. Resultaten zijn gepagineerd.
Query Parameters
| Parameter | Type | Standaard | Beschrijving |
|---|---|---|---|
| per_page | integer | 20 | Aantal resultaten per pagina (max 100) |
Response 200 OK
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"product_summary": "Wireless bluetooth over-ear headphones",
"hs_code": "8518.30.00",
"confidence": 92,
"created_at": "2026-03-03T12:00:00+00:00"
}
],
"meta": {
"current_page": 1,
"per_page": 20,
"total": 42,
"last_page": 3
},
"usage": {
"credits_remaining": 47
}
}
/v1/classify/batch
Dien tot 100 producten in voor classificatie in een enkel verzoek. Elk item wordt individueel en asynchroon verwerkt. Retourneert een batch-ID om de voortgang te volgen.
Request Body
| Parameter | Type | Verplicht | Beschrijving |
|---|---|---|---|
| items | array | required | Array van classificatieverzoeken (max 100). Elk item heeft dezelfde velden als POST /v1/classify. |
Voorbeeldverzoek
curl -X POST https://import8.nl/api/v1/classify/batch \
-H "Authorization: Bearer c8_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"items": [
{"description": "Wireless bluetooth headphones", "origin_country": "CN"},
{"description": "Stainless steel water bottle", "origin_country": "CN"},
{"description": "Cotton t-shirt, men, crew neck", "origin_country": "BD"}
]
}'
response = requests.post(
"https://import8.nl/api/v1/classify/batch",
headers={"Authorization": "Bearer c8_your_api_key"},
json={
"items": [
{"description": "Wireless bluetooth headphones", "origin_country": "CN"},
{"description": "Stainless steel water bottle", "origin_country": "CN"},
{"description": "Cotton t-shirt, men, crew neck", "origin_country": "BD"}
]
}
)
batch_id = response.json()["data"]["batch_id"]
const response = await fetch('https://import8.nl/api/v1/classify/batch', {
method: 'POST',
headers: {
'Authorization': 'Bearer c8_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
items: [
{ description: 'Wireless bluetooth headphones', origin_country: 'CN' },
{ description: 'Stainless steel water bottle', origin_country: 'CN' },
{ description: 'Cotton t-shirt, men, crew neck', origin_country: 'BD' },
]
}),
});
Response 202 Accepted
{
"success": true,
"data": {
"batch_id": "batch_abc123",
"total": 3,
"classification_ids": [
"550e8400-e29b-41d4-a716-446655440001",
"550e8400-e29b-41d4-a716-446655440002",
"550e8400-e29b-41d4-a716-446655440003"
]
},
"usage": {
"credits_remaining": 47
}
}
/v1/classify/batch/{batch_id}
Controleer de status van een batch-classificatieverzoek. Retourneert de status van elke individuele classificatie in de batch.
Response 200 OK
{
"success": true,
"data": {
"batch_id": "batch_abc123",
"total": 3,
"completed": 2,
"pending": 1,
"failed": 0,
"classifications": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "completed",
"hs_code": "8518.30.00"
},
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"status": "completed",
"hs_code": "7323.93.00"
},
{
"id": "550e8400-e29b-41d4-a716-446655440003",
"status": "pending",
"hs_code": null
}
]
},
"usage": {
"credits_remaining": 44
}
}
/v1/classifications/{id}/feedback
Geef feedback op een classificatieresultaat. Bevestig dat de classificatie correct was of geef de juiste HS code op. Dit helpt het systeem te verbeteren.
Request Body
| Parameter | Type | Verplicht | Beschrijving |
|---|---|---|---|
| status | string | required | confirmed of corrected |
| corrected_code | string | if corrected | De juiste HS code (verplicht wanneer status corrected is) |
Voorbeeld: Bevestigen
curl -X POST https://import8.nl/api/v1/classifications/550e8400-.../feedback \
-H "Authorization: Bearer c8_your_api_key" \
-H "Content-Type: application/json" \
-d '{"status": "confirmed"}'
Voorbeeld: Corrigeren
curl -X POST https://import8.nl/api/v1/classifications/550e8400-.../feedback \
-H "Authorization: Bearer c8_your_api_key" \
-H "Content-Type: application/json" \
-d '{"status": "corrected", "corrected_code": "8518.10.00"}'
/v1/usage
Haal de huidige verbruiksstatistieken op voor je organisatie in de lopende factureringsperiode.
Response 200 OK
{
"success": true,
"data": {
"plan": {
"name": "Starter",
"display_name": "Starter"
},
"classifications": {
"current": 42,
"limit": 500,
"remaining": 458,
"percentage": 8
},
"period": {
"year": 2026,
"month": 3
}
}
}
/v1/me
Haal accountinformatie op voor de geauthenticeerde API key, inclusief organisatiegegevens en creditsaldo.
Response 200 OK
{
"success": true,
"data": {
"organization": {
"name": "Acme Trading Co.",
"email": "api@acmetrading.com",
"country": "NL"
},
"credits": {
"remaining": 247,
"total_purchased": 250,
"total_used": 3,
"earliest_expiry": "2027-03-26T00:00:00+00:00"
},
"limits": {
"rate_limit_per_minute": 20,
"max_api_keys": 3
}
}
}
/health
Controleer de API-status. Dit endpoint vereist geen authenticatie.
curl https://import8.nl/api/health
# Response:
{
"success": true,
"data": {
"status": "operational"
}
}
/v1/duty-rates/{hs_code}
Haal invoerrechten op voor een 10-cijferige HS code. Retourneert MFN-rechten, preferentiele rechten, antidumpingrechten en BTW-tarief.
Query Parameters
| Parameter | Type | Beschrijving |
|---|---|---|
| origin | string | 2-letterige ISO landcode om preferentiele rechten te filteren |
| destination | string | 2-letterige ISO landcode voor BTW-berekening (standaard: NL) |
Voorbeeld
curl "https://import8.nl/api/v1/duty-rates/8518300090?origin=CN&destination=NL" \
-H "Authorization: Bearer c8_your_api_key"
Response 200 OK
{
"success": true,
"data": {
"hs_code": "8518300090",
"description": "Headphones and earphones",
"mfn_duty": {
"rate": "2.00%",
"expression": "2.000 %"
},
"preferential_duties": [
{
"scheme": "GSP",
"rate": "0.00%",
"countries": ["CN", "VN", "BD"]
}
],
"anti_dumping": [],
"vat_rate": "21.00%"
}
}
/v1/landed-cost
Bereken de totale landed cost voor het importeren van een product. Combineert CIF-waarde, invoerrechten, antidumpingrechten en BTW.
Request Body
| Parameter | Type | Verplicht | Beschrijving |
|---|---|---|---|
| hs_code | string | required | 10-cijferige HS goederencode |
| origin_country | string | required | 2-letterige ISO landcode |
| destination_country | string | optional | Standaard: NL |
| value | number | required | Productwaarde (min: 0,01) |
| currency | string | optional | Standaard: EUR |
| shipping | number | optional | Verzendkosten (standaard: 0) |
| insurance | number | optional | Verzekeringskosten (standaard: 0) |
Response 200 OK
{
"success": true,
"data": {
"cif_value": 31.50,
"duty": {
"rate": "0.00%",
"amount": 0.00,
"type": "preferential"
},
"anti_dumping": {
"rate": "0.00%",
"amount": 0.00
},
"vat": {
"rate": "21.00%",
"amount": 6.62
},
"total_landed_cost": 38.12,
"currency": "EUR"
}
}
/v1/webhook
Configureer een webhook-URL om pushmeldingen te ontvangen wanneer classificaties worden voltooid of mislukken. Een ondertekeningsgeheim wordt automatisch gegenereerd.
Let op: Het geheim wordt alleen geretourneerd bij het aanmaken van de webhook. Sla het veilig op -- je kunt het niet opnieuw ophalen.
Voorbeeld
curl -X PUT https://import8.nl/api/v1/webhook \
-H "Authorization: Bearer c8_your_api_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/webhook"}'
Response 200 OK
{
"success": true,
"data": {
"url": "https://example.com/webhook",
"secret": "whsec_a1b2c3d4e5f6g7h8i9j0..."
}
}
/v1/webhook
Verwijder de geconfigureerde webhook. Je ontvangt geen meldingen meer.
curl -X DELETE https://import8.nl/api/v1/webhook \
-H "Authorization: Bearer c8_your_api_key"
# Response:
{
"success": true,
"message": "Webhook removed."
}
Webhook Events
Wanneer een classificatie is verwerkt, stuurt Import8 een POST verzoek naar je webhook-URL met het eventtype in de X-Import8-Event header.
| Event | Beschrijving |
|---|---|
| classification.completed | Classificatie succesvol afgerond |
| classification.failed | Classificatie mislukt door een fout |
Headers
| Header | Beschrijving |
|---|---|
| X-Import8-Event | Eventtype (bijv. classification.completed) |
| X-Import8-Signature | HMAC-SHA256 handtekening: sha256={hex_digest} |
| User-Agent | Import8-Webhook/1.0 |
Voorbeeld Payload
{
"event": "classification.completed",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"source": "api",
"hs_code": {
"code_6": "851830",
"code_8": "85183000",
"code_10": "8518300090",
"description": "Headphones and earphones",
"chapter": "85"
},
"confidence": 95,
"reasoning": "Wireless bluetooth headphones with noise cancellation...",
"product_summary": "Over-ear wireless bluetooth headphones",
"created_at": "2026-03-04T12:00:00+00:00",
"completed_at": "2026-03-04T12:00:30+00:00"
}
}
Webhook Verificatie
Verifieer de X-Import8-Signature header om te controleren dat verzoeken van Import8 afkomstig zijn. De handtekening is een HMAC-SHA256 hex digest van de ruwe request body, met je webhook-geheim als sleutel, voorafgegaan door sha256=.
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
const crypto = require("crypto");
function verifyWebhook(payload, signature, secret) {
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(payload).digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
function verifyWebhook(string $payload, string $signature, string $secret): bool
{
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
return hash_equals($expected, $signature);
}
Rate Limits
Rate limits worden per API key toegepast en zijn afhankelijk van je creditpakket. Elke API-response bevat rate limit headers:
| Header | Beschrijving |
|---|---|
| X-RateLimit-Limit | Maximaal aantal verzoeken per venster |
| X-RateLimit-Remaining | Resterende verzoeken in het huidige venster |
| X-RateLimit-Reset | Unix-timestamp wanneer het venster reset |
Bij overschrijding retourneert de API 429 Too Many Requests met een Retry-After header.
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
{
"success": false,
"message": "Rate limit exceeded. Please retry after 30 seconds."
}
Foutcodes
De API gebruikt standaard HTTP-statuscodes:
| Status | Betekenis |
|---|---|
| 200 | Succesvol |
| 202 | Geaccepteerd -- classificatie in wachtrij |
| 401 | Ongeldige of ontbrekende API key |
| 404 | Bron niet gevonden |
| 422 | Validatiefout -- controleer de request body |
| 429 | Rate limit of verbruikslimiet overschreden |
| 500 | Serverfout |
Foutresponse formaat
{
"success": false,
"message": "Description of the error"
}