Ce que demandent les développeurs avant et pendant la connexion : clés, liens, comment la décision arrive sur votre site, webhooks, journal, limites et erreurs. Chaque méthode et chaque chiffre de cette page sont ceux qu’utilise l’API aujourd’hui.
La clé n’est affichée qu’une fois, juste après sa création : copiez-la à ce moment-là, nous n’en gardons que l’empreinte. Un compte peut avoir jusqu’à 10 clés actives. Une clé dont vous n’avez plus besoin se révoque sur la même page et cesse de fonctionner immédiatement.
L’API se trouve à https://api.consent.link/v3 et parle JSON. Envoyez la clé avec chaque requête dans l’en-tête Authorization: Bearer clk_live_… (l’en-tête X-AUTH-TOKEN de notre ancienne API v2 fonctionne aussi). Une requête sans clé valide reçoit 401 unauthenticated.
Appelez l’API uniquement depuis votre serveur. Qui détient la clé peut créer des liens et lire votre journal avec toutes les données des visiteurs.
Toutes, d’un coup d’œil. Chaque chemin se place après https://api.consent.link ; les clés publiques pour vérifier les jetons de décision sont sur https://api.consent.link/.well-known/jwks.json.
Méthode
Ce qu’elle fait
POST/v3/links
Créer un lien
POST/v3/links/bulk
Créer jusqu’à 500 liens
GET/v3/links
Lister les liens, avec filtres
GET/v3/links/{id}
Un lien et ses chiffres
PATCH/v3/links/{id}
Modifier un lien
DELETE/v3/links/{id}
Désactiver un lien
GET/v3/profiles
Lister les profils de page
POST/v3/profiles
Créer un profil de page
GET/v3/profiles/{id}
Un profil de page
PATCH/v3/profiles/{id}
Modifier ou publier un profil
DELETE/v3/profiles/{id}
Supprimer un profil
POST/v3/consents/verify
Vérifier une fois un jeton de décision
GET/v3/webhooks
Liste des webhooks
POST/v3/webhooks
Ajouter un webhook
GET/v3/webhooks/{id}
Un webhook
PATCH/v3/webhooks/{id}
Modifier l'URL ou les événements, activer ou désactiver
Envoyez POST /v3/links avec la destination. La réponse est 201 avec le lien : short est l’adresse à mettre dans vos annonces, publications et e-mails, id est son code. Seul destination est obligatoire.
Les liens se créent uniquement via l’API, jamais dans l’espace client : chaque destination est vérifiée à la création du lien, ce qui écarte l’hameçonnage.
destination : où va le visiteur après sa décision. Obligatoire.
type : la mention sur la page de consentement, parmi ad, sponsored, affiliate, none. Sans lui, la mention choisie dans « Apparence ».
template : le texte de la page, un identifiant de modèle de notre bibliothèque (le tableau ci-dessous). Sans lui, le modèle choisi dans « Apparence ».
name : votre propre nom pour le lien, jusqu’à 255 caractères, affiché dans l’espace client.
external_id : votre propre identifiant, par exemple d’une publication ou d’une campagne, jusqu’à 255 caractères. Vous pouvez filtrer les liens dessus ; il ne peut plus être modifié ensuite.
metadata : un objet JSON à vous, conservé et renvoyé tel quel.
La réponse contient aussi resolved_destination (pour un tracker ou un lien raccourci, voir plus bas), status (active, disabled ou blocked), mode (live ou test) et created_at, plus warnings quand il y a quelque chose à signaler.
Modèle
Finalités
all
Statistiques, Publicité, Recommandations de produits
app
Statistiques, Attribution des installations d’application
Une adresse absolue http ou https sur un nom de domaine public, jusqu’à 2 048 caractères : pas d’adresse IP, pas de nom d’utilisateur ni de mot de passe, pas d’espace ni de barre oblique inversée. Nous la conservons octet pour octet.
Chaque nouvelle adresse est vérifiée dans notre liste de blocage et auprès de Google Web Risk, et une adresse dangereuse est refusée avec 422 destination_blocked. Si une adresse se révèle dangereuse plus tard, le lien est bloqué : il ne s’ouvre plus, ne peut plus être modifié, et votre webhook reçoit link.blocked.
Quand l’hôte de la destination est l’adresse de clic d’un réseau d’affiliation ou d’un raccourcisseur de liens, comme awin1.com, sjv.io, prf.hn, admitad.com, amzn.to, bit.ly (sous-domaines compris), nous suivons nous-mêmes ses redirections : à la création du lien, y compris en lot, et quand PATCH change sa destination. Cela fait jusqu’à 5 redirections en quelques secondes. L’adresse où la chaîne quitte les trackers pour un autre site est enregistrée, octet pour octet, comme resolved_destination. Nous ne consultons jamais les autres destinations, et leur resolved_destination reste null.
destination reste exactement telle que vous l’avez envoyée. Avec consentement, le visiteur y va, en passant par le tracker. Sans consentement, il va directement à resolved_destination, sans passer par le tracker et sans les identifiants de clic publicitaire.
Si la chaîne ne peut pas être suivie (le tracker ne redirige pas, répond trop lentement, redirige trop de fois, mène à une adresse interne ou bloquée, ou ne quitte jamais les trackers), le lien est créé quand même, mais un refus passe pour l’instant par le tracker. Chaque réponse qui montre le lien contient alors warnings avec le code tracker_unresolved, et la page du lien dans l’espace client le signale aussi. Nous réessayons en arrière-plan en attendant 5 minutes, 1 heure entre les tentatives ; dès que cela marche, resolved_destination est rempli et l’avertissement disparaît. Après la dernière tentative, vérifiez l’adresse et renvoyez-la avec PATCH. Quand il n’y a rien à signaler, la réponse n’a pas de warnings.
Nos requêtes vers les trackers portent le User-Agent Consent.link-Resolver/1 (+https://consent.link/faq/api).
Réponse
201 Created
{
"id": "pR3xd",
"short": "https://consent.link/pR3xd",
"destination": "https://www.awin1.com/cread.php?awinmid=1234&awinaffid=56789&ued=https%3A%2F%2Fshop.example%2Fboots",
"resolved_destination": null,
"type": "affiliate",
"template": "statsads",
"name": "Winter boots",
"external_id": "post-8815",
"metadata": {"campaign": "winter"},
"profile": "main",
"status": "active",
"mode": "live",
"created_at": "2026-11-03T12:00:00.000Z",
"warnings": [
{
"code": "tracker_unresolved",
"message": "The destination is a tracker redirect that could not be unwound yet: a visitor who refuses will go through the tracker. It is tried again later; resolved_destination is filled in when it works."
}
]
}
Envoyez un en-tête Idempotency-Key avec POST /v3/links et POST /v3/links/bulk : de 1 à 255 caractères ASCII imprimables, par exemple un UUID ou votre propre identifiant de la publication. Une répétition avec la même clé et le même corps dans les 24 heures renvoie les liens déjà créés, avec l’en-tête Idempotent-Replayed: true, et ne crée rien.
La même clé avec un autre corps est refusée avec 422 idempotency_key_reused. Si la première requête est encore en cours, la répétition reçoit 409 idempotency_in_progress : attendez un instant et renvoyez-la.
Oui : POST /v3/links/bulk avec {"links": [ … ]}, jusqu’à 500 liens par requête, chacun avec les mêmes champs qu’un lien seul. La réponse est 201 avec data, les liens dans l’ordre où vous les avez envoyés.
C’est tout ou rien : si un élément est invalide, rien n’est créé et l’erreur le désigne, par exemple links.3.destination.
PATCH /v3/links/{id} avec seulement les champs à changer : destination, type, template, name, metadata. null vide un champ facultatif, metadata est remplacé en entier et external_id reste tel qu’à la création. La page de consentement affiche le changement immédiatement. Une nouvelle destination est vérifiée comme celle d’un nouveau lien et, si elle est sur un autre domaine, les consentements « Ne plus demander » donnés pour l’ancien domaine ne laissent plus passer les visiteurs.
DELETE /v3/links/{id} désactive le lien : il ne s’ouvre plus et ne peut plus être modifié ni réactivé, tandis que ses enregistrements restent dans le journal. Créez un nouveau lien si vous en avez de nouveau besoin.
GET /v3/links liste vos liens, les plus récents d’abord, 50 par page (jusqu’à 100 avec limit). Filtres : status, mode, type, template, external_id, domain, ainsi que from et to pour la date de création (2026-10-31 ou 2026-10-31T14:00:00Z). Pour la page suivante, passez next_cursor de la réponse comme cursor ; null signifie qu’il n’y a plus de page.
GET /v3/links/{id} renvoie un lien avec ses stats depuis sa création : shown, granted, denied, left (a quitté la page sans décider), reused et withdrawn. Les chiffres ont quelques minutes de retard sur le journal.
La page que vous configurez dans « Apparence » de l’espace client : le modèle de texte de notre bibliothèque, les destinataires des données, la mention, le lien vers votre politique de confidentialité et, sur Business, votre logo et votre couleur. Les type et template propres au lien priment sur l’apparence. Quand vous publiez une nouvelle version, les pages de vos liens changent en moins d’une minute.
La langue est choisie d’après le navigateur du visiteur : anglais, espagnol, allemand, français, italien, portugais ou russe. Vous choisissez un modèle, pas des mots : les textes viennent de notre bibliothèque, vous ne pouvez donc pas écrire les vôtres.
Tant que rien n'est publié dans « Apparence », la page n'affiche ni le lien vers votre politique de confidentialité ni les destinataires des données. Les liens sont tout de même créés, et les réponses à POST /v3/links, POST /v3/links/bulk et PATCH /v3/links/{id} portent l'en-tête Consent-Link-Warning: design_unpublished tant que la configuration du lien n'a pas de version publiée.
Enregistrez plusieurs profils de la page dans « Apparence » ou via l’API, chacun avec son propre identifiant comme black-friday, et indiquez-en un à la création d’un lien : "profile": "black-friday" dans POST /v3/links ou dans un élément de la création en masse. Sans profile, le lien reçoit votre profil par défaut.
Un lien garde son profil : si un autre profil devient ensuite celui par défaut, les anciens liens ne bougent pas. PATCH /v3/links/{id} avec profile déplace un lien, et "profile": null le déplace vers le profil par défaut du moment. Un identifiant inconnu donne une 422 sur le champ profile. L’objet du lien indique son profile, et GET /v3/links?profile=black-friday liste les liens d’un profil. Le nombre de profils possibles dépend de l’offre : 1 sur Free, 5 sur Pro, 50 sur Business, profil par défaut compris.
GET /v3/profiles les liste, celui par défaut en premier. POST /v3/profiles en crée un avec id et policy_url (obligatoires) et, si vous le souhaitez, name, template, vendors, type, remember, brand_name et default. Il est publié immédiatement. PATCH /v3/profiles/{id} le modifie : les champs de la page publient aussitôt une nouvelle version, name et "default": true seuls ne publient rien.
DELETE /v3/profiles/{id} supprime un profil qui n’est pas celui par défaut (409 profile_is_default) et n’a pas de liens actifs (409 profile_in_use). En créer un au-delà de la limite de l’offre, ou en utiliser un qui dépasse la limite après un passage à une offre inférieure, donne 402 profiles_limit_reached. Les modifications demandent une clé réelle.
Avec consentement, le visiteur arrive sur votre destination exactement telle que vous l’avez donnée. Sans consentement, utm_* et vos autres paramètres restent aussi, et seuls les identifiants de clic publicitaire sont retirés : gclid, gbraid, wbraid, fbclid, msclkid, ttclid, twclid, li_fat_id. Dans les deux cas, nous ajoutons un paramètre, cl_ct, le jeton de décision.
Seuls les paramètres de la destination elle-même comptent : ce qui est ajouté au lien court (https://consent.link/nk7Qa?utm_source=…) n’est pas transmis. Mettez dans destination tout ce dont votre site a besoin, ou créez un lien par campagne.
Chaque redirection depuis la page de consentement porte cl_ct, un jeton signé (JWT, ES256) valable 10 minutes. Vérifiez-le depuis votre serveur avec POST /v3/consents/verify : la réponse contient la décision, et chaque jeton ne peut être vérifié qu’une fois, si bien qu’une adresse copiée ne vaut rien. Lisez le jeton, puis retirez-le de l’adresse.
Ce qu’il contient : decision (granted ou denied), purposes (ce que le visiteur a autorisé), cid (l’enregistrement du journal), sid (le pseudonyme du visiteur dans votre compte, le même sur tous vos liens), cexp (jusqu’à quand le consentement vaut, en temps Unix), link, mode, iat et exp. Ni IP, ni navigateur, ni autre donnée personnelle. Un visiteur qui a déjà accepté en laissant « Ne plus demander » passe directement, avec granted.
Vous pouvez aussi vérifier la signature vous-même avec les clés de https://api.consent.link/.well-known/jwks.json et n’importe quelle bibliothèque JWT : vérifiez exp, et que link est bien l’un de vos liens. Votre propre vérification ne peut pas savoir si un jeton a déjà servi ; la méthode de l’API, si. Erreurs : 422 token_invalid, 422 token_expired, 409 token_used.
Créez un webhook : POST /v3/webhooks avec url et les events voulus (le tableau ci-dessous). L’adresse doit être en https sur un nom d’hôte public. La réponse contient secret (whsec_…) pour vérifier les signatures : il n’est affiché qu’une fois, conservez-le. Un compte peut avoir jusqu’à 10 webhooks actifs.
L’historique des livraisons, le bouton « Réessayer » et l’activation ou la désactivation d’un webhook se trouvent dans l’espace client, sous « Compte » → « Webhooks ».
Chaque événement est un POST avec un corps JSON : id (evt_…), type, created_at, mode et data. Un enregistrement de consentement dans data.consent contient id, link, decision, purposes, scope (domain si le visiteur a laissé « Ne plus demander », sinon link), sid, dest_domain, country, notice_version, created_at et expires_at. Jamais d’IP, de navigateur ni de cookie.
Événement
Quand
data
consent.recorded
Un nouvel enregistrement : un accord, un refus ou un visiteur ayant déjà accepté
consent
consent.withdrawn
Un consentement a été retiré : par le visiteur sur « Mes consentements » ou par vous via l’API
consent, withdraws
link.blocked
Nous avons bloqué un lien car sa destination s’est révélée dangereuse
Chaque requête porte les en-têtes Consent-Event, Consent-Delivery et Consent-Signature: t=1793712000,v1=5f3a…. v1 est le HMAC-SHA256 en hexadécimal du texte t, d’un point et du corps brut de la requête, avec le secret de votre webhook comme clé.
Calculez-le sur le corps tel que reçu (avant toute analyse du JSON), comparez en temps constant, et refusez un t éloigné de plus de cinq minutes de votre horloge, pour qu’une requête enregistrée ne puisse pas être rejouée.
Une livraison compte quand votre serveur répond 2xx en 10 secondes ; les redirections ne sont pas suivies. Sinon, nous réessayons en attendant 1 minute, 5 minutes, 30 minutes, 2 heures, 12 heures entre les tentatives, 6 tentatives en tout. Après la dernière, la livraison est marquée comme échouée et reste dans l’historique, où « Réessayer » la renvoie jusqu’à 3 jours après l’événement.
Répondez donc vite et faites le travail ensuite. Un même événement peut arriver plus d’une fois, par exemple après un délai dépassé : ignorez les identifiants déjà traités. Les événements n’arrivent pas toujours dans l’ordre où ils se sont produits.
Les visiteurs voient et retirent leurs consentements sur « Mes consentements ». Si un visiteur s’adresse plutôt à vous, retirez-le en son nom : POST /v3/consents/{id}/withdraw, sans corps, avec l’identifiant de son enregistrement granted ou reused. Cela fonctionne pour tout consentement encore en vigueur, quelle que soit la profondeur du journal visible avec votre offre. La réponse est 201 avec le nouvel enregistrement withdrawn, dont le first_consent_id est le consentement retiré. Un enregistrement qui n’est pas un consentement en vigueur (refus, déjà retiré ou expiré) reçoit 409 consent_not_in_force ; un enregistrement que vous ne pouvez pas lire, 404, comme avec GET /v3/consents/{id}.
Les deux voies mènent au même résultat : un enregistrement withdrawn dans le journal, consent.withdrawn envoyé à votre webhook avec data.withdraws, l’identifiant du consentement retiré, et dès lors vos liens redemandent à ce visiteur. Un retrait clôt tous les consentements que le visiteur avait donnés pour ce domaine, et il ne compte pas dans votre limite.
Cessez d’utiliser les données du visiteur de votre côté : retrouvez-les par sid ou par l’identifiant de l’enregistrement.
Requête
curl -X POST https://api.consent.link/v3/consents/01jbz8m3k4x9w2r7d5t6q8v1yh/withdraw \
-H "Authorization: Bearer clk_live_…"
Un consentement vaut 6 mois à partir du moment où il a été donné : expires_at dans l’enregistrement, cexp dans le jeton de décision. Un enregistrement reused porte l’expires_at du consentement qu’il réutilise. Ensuite, vos liens redemandent au visiteur.
Quand un consentement granted expire sans avoir été retiré, votre webhook reçoit consent.expired avec data.consent, l’enregistrement, et data.expired_at. Nous vérifions une fois par heure : l’événement arrive dans l’heure qui suit expires_at, une fois par consentement. Les enregistrements reused n’ont pas d’événement propre : celui du consentement qu’ils réutilisent les couvre. L’événement ne part que vers les webhooks qui ont consent.expired dans events. Une expiration n’est annoncée qu’une fois, même si aucun webhook ne l’attendait alors : elle n’est pas renvoyée plus tard.
Placez notre script dans <head>, avant GTM et gtag : https://consent.link/js/consent.js. Il fixe les valeurs par défaut de Consent Mode v2 (tout refusé sauf functionality_storage et security_storage, avec wait_for_update de 500 ms), lit cl_ct dans l'adresse, vérifie sa signature avec les clés de https://api.consent.link/.well-known/jwks.json directement dans le navigateur et met à jour le consentement.
La décision est gardée dans le cookie cl_consent de votre domaine : jusqu'à cexp pour un consentement, 180 jours pour un refus, donc les pages suivantes n'ont pas besoin de bannière. Une fois vérifié, cl_ct quitte la barre d'adresse ; vos autres paramètres restent. Le script ne nous envoie rien.
Si vous enregistrez la décision de votre côté, vérifiez aussi le jeton depuis votre serveur avec POST /v3/consents/verify : le script ne peut pas savoir si un jeton a déjà servi.
Téléchargez le modèle consent-link.tpl ; dans GTM, ouvrez Modèles → Nouveau → ⋮ → Importer et enregistrez. Créez une balise à partir de ce modèle avec le déclencheur « Consent Initialization – All Pages » (« Initialisation du consentement – Toutes les pages »).
La balise fixe les valeurs par défaut, applique la décision gardée dans le cookie cl_consent et charge le script, qui vérifie un cl_ct récent. Inutile alors de mettre aussi le script dans <head>.
N'affichez pas une deuxième bannière à qui a déjà décidé sur notre page. Le script donne la décision dans window.consentLink.decision (granted, denied ou null) et window.consentLink.has('stats') ; window.consentLink.ready se résout une fois le jeton de l'adresse vérifié. Il y a aussi l'événement consentlink:update sur document et consent_link_update dans dataLayer. Chargez notre script avant celui de la bannière.
Cookiebot : transmettez la décision avec Cookiebot.submitCustomConsent et sa bannière ne s'affiche pas. OneTrust n'a pas de fonction publique pour enregistrer un consentement depuis le site : chargez donc son script seulement s'il n'y a pas de décision. Pour les autres bannières, pareil : transmettez les finalités par leur API ou ne chargez pas la bannière.
Cookiebot
window.addEventListener('CookiebotOnLoad', function () {
window.consentLink.ready.then(function (cl) {
if (cl.decision && !Cookiebot.hasResponse) {
Cookiebot.submitCustomConsent(cl.has('personalization'), cl.has('stats'), cl.has('ads'));
}
});
});
OneTrust
window.consentLink.ready.then(function (cl) {
if (cl.decision) return; // decided on consent.link: no second banner
var s = document.createElement('script');
s.src = 'https://cdn.cookielaw.org/scripttemplates/otSDKStub.js';
s.setAttribute('data-domain-script', 'YOUR-ONETRUST-ID');
document.head.appendChild(s);
});
GET /v3/consents liste les enregistrements, les plus récents d’abord, avec les filtres decision (granted, denied, reused, withdrawn), link, country (DE), from, to et la même pagination que pour les liens. GET /v3/consents/{id} renvoie un enregistrement avec ses preuves (adresse IP, navigateur, langue, l’empreinte du texte de la page, quand la page a été affichée et combien de temps le visiteur a mis) et sa place dans la chaîne d’empreintes, chain.
Un refus ne garde que la décision, l’heure, le lien et le pays : son evidence vaut donc null. L’API donne les données complètes ; l’espace client en masque une partie tant que vous n’avez pas activé la connexion en deux étapes. La profondeur visible dépend de l’offre (le tableau de « Offres et limites »).
GET /v3/consents/{id}/proof renvoie l’enregistrement en PDF : la décision, qui, ce qui a été affiché, les empreintes et comment les vérifier. Il est dans la langue de votre espace client. Disponible sur Pro et Business (402 plan_required sur Free), jusqu’à 20 par minute. Si le PDF ne peut pas être produit tout de suite, la réponse est 503 unavailable avec Retry-After.
Chaque enregistrement granted porte evidence.snapshot_hash : le SHA-256 de la page de consentement telle que le visiteur l’a vue, en HTML. Un même instantané sert à tous les visiteurs de la même page, c’est-à-dire même version de l’apparence et du texte, même langue et même type de lien. GET /v3/consents/{id}/snapshot renvoie ce HTML avec le hash dans l’en-tête X-Snapshot-Hash, et GET /v3/consents/{id}/snapshot.png une capture d’écran. Les deux suivent les règles de GET /v3/consents/{id}, profondeur du journal comprise.
Pour vérifier, calculez le SHA-256 du HTML exactement tel que reçu : il est égal à snapshot_hash, et le hash propre de l’enregistrement dans la chaîne couvre snapshot_hash, si bien que la page ne peut pas être remplacée après coup. Ce qui change d’un affichage à l’autre est figé dans l’instantané : l’hôte de la destination s’affiche example.com, la signature du formulaire est vide et son action est #. L’adresse réelle se trouve dans dest_domain et evidence.destination.
Les enregistrements reused, les refus et les enregistrements antérieurs aux instantanés ont snapshot_hash à null, et leur instantané répond 404 not_found (« This record has no page snapshot. »). Juste après une décision, les fichiers peuvent être encore en cours d’écriture : 404 not_found avec « The page snapshot is not ready yet. » veut dire de réessayer un peu plus tard. Le HTML arrive en quelques secondes, la capture d’écran un peu après. La page de l’enregistrement dans l’espace client et la preuve PDF montrent aussi la capture et le hash.
POST /v3/exports avec les filtres de GET /v3/consents (decision, link, country, from, to) répond aussitôt 202 avec l’id de l’export. Le fichier est produit en arrière-plan : vous recevez le webhook export.ready, ou interrogez GET /v3/exports/{id} jusqu’à ce que status soit ready, puis téléchargez GET /v3/exports/{id}/file. L’export indique aussi rows et le sha256 du fichier.
Les fichiers sont conservés 7 jours (410 export_expired ensuite). Jusqu’à 3 exports peuvent être en cours à la fois (429 too_many_exports). Pro et Business.
GET /v3/stats/summary donne shown, granted, denied, left, reused et withdrawn pour les jours UTC de from à to (2026-10-31, bornes incluses ; par défaut les 30 derniers jours, au plus 366 jours, aussi loin que votre offre montre le journal). Ajoutez link pour un seul lien. GET /v3/stats/daily donne les mêmes chiffres jour par jour et, sur Pro et Business, par pays avec by=country. Les robots ne sont jamais comptés.
GET /v3/usage montre les consentements de la période, votre limit, ce qui reste (remaining) et le début et la fin de la période.
L’API, les webhooks et la page de consentement en sept langues sont inclus dans chaque offre. Les offres diffèrent par les consentements par mois, la profondeur du journal affiché, le rythme de requêtes et les fonctions supplémentaires. Prix en euros, hors TVA.
Offre
Prix par mois
Consentements par mois
Journal
Requêtes par minute
Profils de page
En plus
Free
0 €
1 000
Journal sur 30 jours
60
1
—
Pro
9 €
10 000
Journal sur 1 an
300
5
Export CSV et preuve PDF · Statistiques par jour et par pays
Business
99 €
250 000
Journal sur 3 ans
1 000
50
Export CSV et preuve PDF · Statistiques par jour et par pays · Votre logo et votre couleur · Des liens sur votre propre domaine
Seuls les nouveaux accords comptent : les refus, les visites répétées avec « Ne plus demander », et les robots ne comptent pas. À 80 % et à 100 % de la limite, vous recevez un e-mail et le webhook usage.warning.
Une fois la limite atteinte, les nouveaux liens réels sont refusés avec 402 limit_reached. Tout le reste continue de fonctionner : les liens existants demandent et enregistrent toujours, les webhooks et les jetons arrivent comme d’habitude, et rien n’est masqué. La création de liens rouvre au début de la période suivante (sur Free le 1er du mois, sur les offres payantes le jour du paiement) ou juste après un passage à une offre supérieure.
Par compte, toutes clés confondues : 60 par minute sur Free, 300 sur Pro, 1 000 sur Business. Au-delà, la réponse est 429 rate_limited avec un en-tête Retry-After ; les en-têtes X-RateLimit-Limit et X-RateLimit-Remaining indiquent où vous en êtes. Certaines méthodes ont en plus leur propre limite : preuves PDF 20 par minute, nouveaux exports 10, téléchargements d’exports 30.
Toujours la même forme : le statut HTTP et un corps JSON avec un code stable et un message en anglais. Fiez-vous au code ; le message peut être reformulé. Des champs invalides donnent 422 validation_failed avec fields : chaque champ avec ses problèmes.
Statut
Code
Signification
401
unauthenticated
Pas de clé, ou clé erronée ou révoquée
402
limit_reached
Les consentements de la période sont épuisés : pas de nouveaux liens réels
402
plan_required
La fonction demande une offre supérieure
402
profiles_limit_reached
Au-delà du nombre de profils de page de l’offre
403
account_blocked
Le compte est bloqué : contactez le support
403
links_blocked
Le compte ne peut pas créer de liens : contactez le support
403
mode_mismatch
Un lien réel se modifie avec une clé réelle, un lien de test avec une clé de test
403
live_key_required
Une clé réelle est nécessaire
404
not_found
Rien avec cet identifiant dans votre compte
405
method_not_allowed
Cette méthode HTTP n’est pas autorisée sur ce chemin
409
link_disabled
Le lien est désactivé et ne peut pas être modifié
409
link_blocked
Le lien a été bloqué et ne peut pas être modifié
409
idempotency_in_progress
Une requête avec cette Idempotency-Key est encore en cours
409
token_used
Ce jeton de décision a déjà été vérifié
409
export_not_ready
L’export est encore en cours de production
409
export_failed
L’export a échoué : lancez-en un nouveau
409
consent_not_in_force
L’enregistrement n’est pas un consentement en vigueur : refus, retrait ou expiration
409
profile_is_default
Le profil par défaut ne peut pas être supprimé
409
profile_in_use
Le profil a encore des liens actifs
410
export_expired
Le fichier n’est plus conservé : lancez un nouvel export
422
validation_failed
Certains champs sont invalides : voir fields
422
destination_blocked
La destination est dangereuse ou bloquée
422
idempotency_key_reused
L’Idempotency-Key a été utilisée avec un autre corps
422
token_invalid
Pas un jeton de décision valide pour votre compte
422
token_expired
Le jeton de décision a plus de 10 minutes
422
webhooks_limit_reached
Trop de webhooks actifs
429
rate_limited
Trop de requêtes : attendez la durée de Retry-After
429
too_many_exports
Trop d’exports en cours
429
daily_limit_reached
Nouveau compte Free : les liens du jour sont épuisés, d’autres dès 00:00 UTC
500
server_error
Un problème de notre côté : réessayez plus tard
503
unavailable
Réessayez dans un instant : voir Retry-After
Réponse
422 Unprocessable Content
{
"error": {
"code": "validation_failed",
"message": "Some fields are invalid.",
"fields": {
"destination": ["The destination must be an absolute http or https URL."]
}
}
}
Créez une nouvelle clé sur « Connexion via l’API », passez votre serveur dessus, puis révoquez l’ancienne : elle cesse de fonctionner immédiatement. Révoquer une clé ne touche ni à vos liens, ni au journal, ni aux webhooks.
Gardez les clés dans les variables d’environnement de votre serveur, jamais dans un navigateur, une application mobile ou un dépôt public. Si le secret d’un webhook a pu fuiter, désactivez ce webhook dans l’espace client et créez-en un nouveau.
Prêt à vous connecter ?
Inscrivez-vous, créez une clé sur « Connexion via l’API » et envoyez votre première requête en quelques minutes.