Abonnement
Une boutique
- Vous envoyez
X-API-Key: sk_live_…, la clé affichée à l'inscription, ou régénérée dans l'espace client.- Vous payez
- Le quota mensuel de votre plan. Rien n'est encaissé à l'appel.
DOCSIntégrer l'API Address Validator
De la clé API à la production : authentification, contrat, codes de retour, cache et quotas. Puis quatre cas pratiques : appel direct, import CSV, Shopify et WooCommerce.
Démarrage
sk_live_…) s'affiche une seule fois. Ensuite, elle se régénère depuis l'espace client.POST /validate avec la clé dans l'en-tête X-API-Key.cache_key.curl -sS https://kder-ai.com/validate \
-H "X-API-Key: sk_live_VOTRE_CLE" \
-H "content-type: application/json" \
-d '{"address": {"street": "1 Rue de Paris", "city": "Saint-Denis", "state": "RE", "zip": "97400", "country": "RE"}}'
Dans tous les exemples, remplacez sk_live_VOTRE_CLE par votre clé.
Pas encore de compte ? Testez une adresse gratuitement : la page n'écrit rien et vous montre exactement ce que l'API renvoie.
Accès
Deux portes, une seule réponse. Seuls l'en-tête envoyé et le paiement changent.
Abonnement
X-API-Key: sk_live_…, la clé affichée à l'inscription, ou régénérée dans l'espace client.Paiement à l'appel · x402
X-PAYMENT : une autorisation EIP-3009 signée, construite à partir du corps de la réponse 402 (champ accepts).X-Payment-Mode.Ne mettez jamais la clé dans un dépôt git, un fichier partagé ou une URL. Elle vit dans une variable d'environnement ou un gestionnaire de secrets, et ne circule qu'en https. Une clé qui a fuité se régénère en un clic : l'ancienne cesse de fonctionner immédiatement.
Référence
POST https://kder-ai.com/validate, corps JSON, en-tête content-type: application/json.
{"address": {
"street": "1 Rue de Paris", // requis
"city": "Saint-Denis", // requis
"state": "RE", // requis (region ou etat)
"zip": "97400", // requis
"country": "RE" // optionnel, "US" par defaut (ISO 2 lettres)
}}
200{
"result": {
"validated": true,
"standardized": {"line1": "1 RUE DE PARIS", "line2": "", "city": "SAINT-DENIS",
"state": "RE", "zip": "97400", "country": "RE"},
"latitude": -20.8823, "longitude": 55.4504,
"deliverability": "residential",
"confidence": 0.99,
"degraded": false,
"cache_key": "9b7a..."
},
"price_paid": 0.0,
"transaction_id": null
}
validatedfalse n'est pas toujours un verdict : lisez degraded avant d'en tirer une conclusion.deliverabilityresidential, commercial, unknown ou invalid : le code du fournisseur, traduit en clair.confidencedegradedtrue : le fournisseur n'a pas répondu (panne, délai dépassé, disjoncteur ouvert). La réponse ne dit rien de l'adresse. Ne l'enregistrez jamais comme « adresse invalide ».price_paid0.0 pour un appel couvert par un abonnement ; le prix en USDC pour un appel payé.cache_keyCe sont les en-têtes que la route pose vraiment. Aucun autre n'est promis.
X-Payment-Modeapi_key ou x402 : comment l'appel a été payé.X-Plantrial, starter, pro ou enterprise. Mode clé seulement.X-Quota-RemainingRéférence
Huit codes possibles sur /validate. Les trois refus du mode clé (401, 402, 403) sont distincts exprès : traitez-les chacun à sa façon.
Succès
Lisez result. Gardez cache_key : c'est votre pseudonyme de cette adresse, il sert à demander un effacement.
Rien à relancer
À corriger chez vous
La clé est incomplète, révoquée (régénérée) ou destinée à un autre service. Corrigez la variable d'environnement. Ne réessayez pas en boucle.
Non : corrigez la clé
Limite ou paiement
Lisez le corps de la réponse : il dit lequel des deux cas s'applique. Un 402 de quota n'est pas une panne.
Selon le corps
{"reason": "quota_atteint"}Plafond d'usage atteint. Ce n'est pas une panne. Le compteur repart le 1er du mois (UTC).{"x402Version": 1}Le paiement manque pour cet appel. Le prix est dans le champ accepts.À corriger chez vous
L'essai gratuit est terminé et le compte est resté sur le plan d'essai. Passez à un plan payant : rien n'est prélevé automatiquement.
Non : changez de plan
À corriger chez vous
Un champ est absent ou vide. street, city, state et zip sont obligatoires ; country vaut US par défaut.
Après correction
Limite
Concerne /validate-form, l'essai sans compte, pas l'API payante. Attendez le délai annoncé dans Retry-After, ou créez un compte.
Après Retry-After
Incident côté service
Le service refuse de servir une validation qu'il ne peut pas inscrire. Réessayez. Si l'appel était payé, citez transaction_id : le rapprochement se fait à la main.
Oui, gardez transaction_id
Incident côté service
La clé n'a pas pu être vérifiée (ce n'est pas un refus), ou la base ne répond pas. Réessayez dans quelques minutes : rien n'a été consommé.
Un 503 n'est jamais une demande de paiement.
Oui, dans quelques minutes
Facturation
cache_key qui le garantit.degraded est gardé 5 minutes, pas 30 jours : « le fournisseur n'a pas répondu » n'est pas un verdict.degraded: true comme « réessayez plus tard ». Après cette fenêtre courte, le même appel obtient une vraie réponse.X-Quota-Remaining. Écrivez-nous avant la limite plutôt qu'après.price_paid: 0.0.402 (accepts) : le prix y figure, il n'est jamais à deviner./validate-form.Exemples
Quatre façons de brancher l'API. Chaque exemple lit la clé dans une variable d'environnement.
$cle = $env:ADDRESS_VALIDATOR_KEY
$corps = '{"address":{"street":"1 Rue de Paris","city":"Saint-Denis","state":"RE","zip":"97400","country":"RE"}}'
$r = Invoke-WebRequest -Uri https://kder-ai.com/validate -Method POST `
-Headers @{ "X-API-Key" = $cle } -ContentType "application/json" -Body $corps
$r.StatusCode
$r.Headers["X-Payment-Mode"], $r.Headers["X-Plan"], $r.Headers["X-Quota-Remaining"]
($r.Content | ConvertFrom-Json).result
"""Verifie un CSV d'adresses et ecrit le verdict a cote.
Le fournisseur n'est interroge qu'une fois par adresse : la reponse est mise en
cache (30 jours pour un verdict), donc une seconde execution sur le meme fichier
ne coute rien de plus.
"""
import csv
import os
import time
import requests
CLE = os.environ["ADDRESS_VALIDATOR_KEY"] # jamais dans le code, jamais dans git
API = "https://kder-ai.com/validate"
with open("colis.csv", newline="", encoding="utf-8") as source, open(
"colis-verifies.csv", "w", newline="", encoding="utf-8"
) as cible:
lecteur = csv.DictReader(source)
champs = list(lecteur.fieldnames) + [
"validated", "deliverability", "degraded", "note",
]
sortie = csv.DictWriter(cible, fieldnames=champs)
sortie.writeheader()
for ligne in lecteur:
reponse = requests.post(
API,
headers={"X-API-Key": CLE},
timeout=30,
json={
"address": {
"street": ligne["adresse"],
"city": ligne["ville"],
"state": ligne["region"],
"zip": ligne["code_postal"],
"country": ligne.get("pays") or "US",
}
},
)
if reponse.status_code in (500, 503):
time.sleep(5) # panne cote service : rien n'a ete consomme
continue
if reponse.status_code == 429:
time.sleep(int(reponse.headers.get("Retry-After", "60")))
continue
if reponse.status_code != 200:
sortie.writerow({**ligne, "note": f"refus {reponse.status_code}"})
continue
resultat = reponse.json()["result"]
sortie.writerow(
{
**ligne,
"validated": resultat["validated"],
"deliverability": resultat["deliverability"],
"degraded": resultat["degraded"],
"note": "a reverifier (fournisseur injoignable)"
if resultat["degraded"]
else "",
}
)
Ce que l'exemple illustre, et rien d'autre : la clé vient d'une variable d'environnement, le 429 est respecté (le délai est lu, pas deviné), et un résultat degraded est marqué « à re-vérifier » au lieu d'être écrit comme une adresse invalide.
orders/create (ou votre étape de préparation de colis) appelle votre service, qui interroge /validate avec l'adresse de livraison de la commande.shipping_address.address1 → street (ajoutez address2 à line2 côté résultat)city → cityprovince_code → statezip → zipcountry_code → countryvalidated: false : signalez la commande dans votre back-office avant l'expédition. degraded: true : ne bloquez rien, reprogrammez un contrôle.woocommerce_checkout_order_processed (commande payée), ou un cron qui parcourt les commandes en préparation (wc_get_orders( ['status' => 'processing'] )).$order->get_shipping_address_1() → street$order->get_shipping_city() → city$order->get_shipping_state() → state$order->get_shipping_postcode() → zip$order->get_shipping_country() → countrycache_key avec la commande : c'est le seul identifiant de l'adresse valable pour une demande d'effacement.Dans tous les cas : un seul appel par adresse et par commande, jamais dans une boucle qui ignore les codes de retour. Un 402 de quota n'est pas une panne : c'est une limite, et elle se lit dans la réponse.
Développeurs et agents IA
Un agent autonome n'a besoin ni de compte ni de clé. Chaque validation encaissée coûte 0,02 USDC, payée avec x402 sur le réseau Base.
POST /validate avec le corps habituel. Sans paiement, la réponse est un 402 dont le corps porte {"x402Version": 1} et le champ accepts : le prix y figure.accepts, et renvoyez la requête avec l'en-tête X-PAYMENT.X-Payment-Mode vaut x402, price_paid donne le prix en USDC, et transaction_id est la référence à citer en cas de 500.Pour vos agents, tout se découvre sans payer :
À savoir avant d'intégrer
degraded: true À re-vérifiercache_key) et l'issue, jamais l'adresse elle-même. Pour l'essai gratuit sans compte : rien, seulement un compteur anonyme qui fait respecter le plafond. Une demande d'effacement se fait avec le cache_key.Créez un compte pour obtenir votre clé, ou testez d'abord une adresse sans compte.