Customs Check
Vérifier gratuitement

Développeurs

API de contrôle douanier

Le même contrôle que sur ce site, appelé depuis votre logiciel. Vous envoyez un dossier en JSON, vous recevez un score sur 100, les points bloquants, les alertes et les actions recommandées — avec des codes d'anomalies stables et des messages traduits dans les 24 langues officielles de l'Union européenne.

API serveur-à-serveur. Une clé est un secret. Les appels depuis un navigateur ne sont pas pris en charge et aucun en-tête CORS n'est envoyé sur les routes authentifiées : une clé qui arrive dans un navigateur est une clé divulguée.

Vue d'ensemble

L'API expose le moteur de contrôle du validateur : treize règles transverses, quatre règles de complétude documentaire et les validateurs propres à chaque système déclaratif. Elle ne télétransmet rien et n'interroge aucune base tarifaire — elle vérifie la cohérence interne et le format de votre dossier avant que vous ne prépariez la déclaration.

Toutes les routes sont préfixées par leur version. Les routes de découverte et la spécification sont publiques : un intégrateur, ou un agent, peut lire le schéma avant même d'avoir une clé.

RouteRôleAuthentification
POST/v1/checksContrôle un dossier et renvoie le rapport completClé requise
POST/v1/checks/batchContrôle jusqu'à 25 dossiers en un appelClé requise
GET/v1/meRenvoie la clé courante et son quota, sans le consommerClé requise
GET/v1/declaration-typesListe les types de déclaration reconnusPublique
GET/v1/declaration-types/{type}Décrit les champs attendus pour un typePublique
GET/v1/openapi.jsonSpécification OpenAPI 3.1 de l'APIPublique

Authentification

L'API s'authentifie par jeton porteur. Le jeton n'est affiché qu'une fois, au moment de la création : seule son empreinte est conservée, une clé perdue se remplace mais ne se récupère pas.

Vous pouvez détenir trois clés actives simultanément, ce qui permet de faire tourner une clé sans interrompre votre intégration : créez la nouvelle, déployez-la, puis révoquez l'ancienne.

  1. 1Créez une clé depuis votre compte, dans l'espace « Clés API ».
  2. 2Envoyez-la dans l'en-tête Authorization de chaque requête.
  3. 3Révoquez-la si elle fuite : la coupure est immédiate et le contenu des dossiers soumis avec cette clé est purgé dans la foulée.
Authorization: Bearer cc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Premier contrôle

Un dossier se compose d'un type, d'un en-tête et de lignes de marchandises. Toutes les valeurs sont des chaînes de caractères : le moteur s'occupe de les interpréter. Les noms des champs se découvrent à l'exécution, type par type.

La réponse arrive immédiatement, il n'y a rien à interroger ensuite.

Requête
curl https://www.customs-check.com/api/v1/checks \
  -H "Authorization: Bearer $CUSTOM_CHECK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "import-export",
    "reference": "PO-2026-114",
    "header": {
      "flow": "IM",
      "shipmentCountry": "CN",
      "destinationCountry": "FR",
      "incoterm": "FOB",
      "companyName": "Acme SAS",
      "companyCountry": "FR",
      "eori": "FR12345678900012",
      "transportMode": "sea",
      "currency": "USD",
      "invoiceTotal": "12500"
    },
    "items": [
      {
        "description": "Leather sport shoes",
        "hsCode": "6403990000",
        "quantity": "500",
        "value": "12500",
        "origin": "VN",
        "grossMass": "850",
        "netMass": "800"
      }
    ],
    "documents": { "commercialInvoice": "available", "packingList": "missing" }
  }'

Lire la réponse

Chaque anomalie porte à la fois une identité machine et une phrase lisible. Construisez votre logique sur l'identité machine : elle ne change pas sans changement de version.

severity · code · path · rule
Contrat stableStables. De nouveaux codes peuvent apparaître, les codes existants ne sont pas renommés sans changement de version.
field · message · text
AffichageTraduits pour l'affichage. Ils peuvent être reformulés à tout moment : ne les comparez jamais dans votre code.
engine.version
Change dès qu'une évolution des règles modifie le score d'un dossier inchangé. Archivez-la avec vos rapports.

Le champ « path » suit la forme de votre requête, ce qui permet de rattacher une anomalie directement au champ concerné dans votre propre interface.

header.<champ> · items.<n>.<champ> · documents.<category> · global

Réponse
{
  "id": "4c749e25-3408-48f9-b3ca-b18a7ad84681",
  "createdAt": "2026-09-16T12:46:13.186Z",
  "type": "import-export",
  "locale": "en",
  "reference": "PO-2026-114",
  "score": 90,
  "level": "good",
  "counts": { "errors": 0, "warnings": 2, "infos": 0 },
  "documents": { "commercialInvoice": "available", "packingList": "missing" },
  "issues": [
    {
      "severity": "warning",
      "code": "docPackingListMissing",
      "path": "documents.packingList",
      "rule": "DOC-002",
      "params": null,
      "field": "Packing list",
      "message": "Packing list not provided",
      "text": "Packing list not provided"
    },
    {
      "severity": "warning",
      "code": "docTransportMissing",
      "path": "documents.transportDocument",
      "rule": "DOC-003",
      "params": null,
      "field": "Transport document (B/L, AWB, CMR)",
      "message": "Transport document not provided",
      "text": "Transport document not provided"
    }
  ],
  "actions": [
    { "severity": "warning", "code": "docPackingListMissing",
      "path": "documents.packingList", "text": "Add: Packing list" }
  ],
  "tips": [],
  "engine": { "version": "1.0.0", "rules": 13 }
}

Découvrir les champs

Les types de déclaration et leurs champs sont publics, aucune clé n'est nécessaire. C'est la route à utiliser pour construire un formulaire, alimenter un mappage depuis votre ERP, ou donner à un agent le schéma qu'il doit remplir.

Les noms renvoyés ici sont exactement les clés à employer dans l'en-tête et dans chaque ligne de marchandise. Les listes d'options sont résolues et traduites ; ajoutez le paramètre pour les omettre si la réponse vous paraît trop lourde.

# The 8 declaration types
curl "https://www.customs-check.com/api/v1/declaration-types?locale=en"

# The fields of one type
curl "https://www.customs-check.com/api/v1/declaration-types/h7?locale=en"

# Same, without the resolved option lists
curl "https://www.customs-check.com/api/v1/declaration-types/h7?options=false"

Traitement par lot

Jusqu'à 25 dossiers par appel. La réponse est toujours un succès dès lors que le lot est accepté, et chaque entrée porte son propre statut : un dossier mal formé ne fait jamais échouer les autres.

Si le quota restant ne couvre pas toutes les entrées valides, le lot entier est refusé plutôt que traité partiellement — vous n'avez jamais à deviner où le traitement s'est arrêté.

curl https://www.customs-check.com/api/v1/checks/batch \
  -H "Authorization: Bearer $CUSTOM_CHECK_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "checks": [ { "type": "h7", "header": {}, "items": [] } ] }'

Quota

Chaque clé dispose de 500 contrôles par jour calendaire UTC. L'état courant accompagne chaque réponse authentifiée, vous n'avez donc jamais besoin d'un appel supplémentaire pour le connaître.

Les appels refusés sont comptés : un client qui boucle sur des requêtes invalides se limite donc lui-même. Le quota est fixé par clé — écrivez-nous s'il vous faut davantage.

Réponse
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 437
X-RateLimit-Reset: 1789603200
X-RateLimit-Policy: 500;w=86400

Erreurs

Les messages d'erreur sont en anglais uniquement : ce sont des messages de protocole, destinés à des développeurs. Seul le contenu métier est traduit.

Chaque réponse porte un identifiant de requête, repris dans le corps. Citez-le lorsque vous nous contactez, il nous mène directement à l'appel concerné.

{
  "error": {
    "code": "invalid_request",
    "message": "The request body failed validation.",
    "details": [
      { "path": "items.0.quantity", "message": "expected a string" }
    ],
    "requestId": "2bbb0946-6178-4b54-921c-b28f794c44bd"
  }
}
StatutcodeSignification
400invalid_jsonLe corps n'est pas du JSON valide.
422invalid_requestLe JSON est valide mais son contenu ne l'est pas. Le détail indique le champ fautif.
401missing_credentialsEn-tête Authorization absent ou mal formé.
401invalid_keyClé inconnue.
401key_revokedClé révoquée.
403account_suspendedLe compte propriétaire de la clé est suspendu.
415unsupported_media_typeLe type de contenu n'est pas du JSON.
413payload_too_largeCorps de requête trop volumineux.
429rate_limit_exceededQuota journalier atteint. Voir l'en-tête Retry-After.
500internal_errorErreur de notre côté. Réessayez, puis signalez-la-nous avec l'identifiant de requête.

Données et conservation

Les dossiers transmis par l'API sont des données de vos clients : nous en gardons le moins possible, et vous disposez d'un interrupteur pour n'en garder aucune.

  • Envoyez « store » à false pour que rien du contenu ne soit écrit : seuls le score et les codes d'anomalies sont conservés.
  • À défaut, le contenu des dossiers est purgé au bout de 30 jours.
  • Révoquer une clé purge immédiatement le contenu des dossiers qu'elle a soumis.
  • Les traitements ont lieu à Francfort et la base est hébergée dans l'Union européenne.
  • Aucun fichier n'est déposé par l'API : vous déclarez seulement quels documents vous détenez.

200 items · 256 KB · 25 / batch · reference ≤ 64

Ce que cette API n'est pas

Le contrôle est une aide à la préparation. Il ne constitue pas une validation par l'administration des douanes, il ne dépose rien, et il ne remplace pas les obligations réglementaires applicables à votre opération.

Les codes douaniers sont vérifiés sur leur format et leur cohérence avec l'opération, jamais confrontés à une base tarifaire : un code bien formé reste un code à vérifier.