API v3

Domande sull’API

Quello che gli sviluppatori chiedono prima e durante il collegamento: chiavi, link, come la decisione arriva al tuo sito, webhook, registro, limiti ed errori. Ogni metodo e ogni numero di questa pagina sono quelli che l’API usa oggi.

Indirizzo
https://api.consent.link/v3
Chiave
Authorization: Bearer clk_live_…
Formato
JSON, UTF-8, risposte in inglese

Per iniziare

Come ottengo una chiave API?

Registrati e conferma la tua email. La prima pagina dopo l’accesso, «Collegati tramite API», crea la tua chiave clk_live_….

La chiave viene mostrata una sola volta, subito dopo la creazione, quindi copiala in quel momento: ne conserviamo solo l’hash. Un account può avere fino a 10 chiavi attive. Una chiave che non ti serve più si revoca nella stessa pagina e smette subito di funzionare.

Dove si trova l’API e come invio la chiave?

L’API si trova su https://api.consent.link/v3 e parla JSON. Invia la chiave con ogni richiesta nell’intestazione Authorization: Bearer clk_live_… (funziona anche l’intestazione X-AUTH-TOKEN della nostra vecchia API v2). Una richiesta senza una chiave valida riceve 401 unauthenticated.

Chiama l’API solo dal tuo server. Chi possiede la chiave può creare link e leggere il tuo registro con tutti i dati dei visitatori.

Richiesta
curl https://api.consent.link/v3/usage \
  -H "Authorization: Bearer clk_live_…"
Risposta
{
  "consents": 412,
  "limit": 1000,
  "remaining": 588,
  "period_start": "2026-11-01T00:00:00.000Z",
  "period_end": "2026-12-01T00:00:00.000Z"
}

Quali metodi ci sono?

Tutti a colpo d’occhio. Ogni percorso va dopo https://api.consent.link; le chiavi pubbliche per verificare i token di decisione sono su https://app.consent.link/.well-known/jwks.json.

MetodoCosa fa
POST/v3/linksCreare un link
POST/v3/links/bulkCreare fino a 500 link
GET/v3/linksElencare i link, con filtri
GET/v3/links/{id}Un link e i suoi numeri
PATCH/v3/links/{id}Modificare un link
DELETE/v3/links/{id}Disattivare un link
GET/v3/profilesElencare i profili di pagina
POST/v3/profilesCreare un profilo di pagina
GET/v3/profiles/{id}Un profilo di pagina
PATCH/v3/profiles/{id}Modificare o pubblicare un profilo
DELETE/v3/profiles/{id}Eliminare un profilo
POST/v3/consents/verifyVerificare una volta un token di decisione
GET/v3/webhooksElenco dei webhook
POST/v3/webhooksAggiungere un webhook
GET/v3/webhooks/{id}Un webhook
PATCH/v3/webhooks/{id}Cambiare URL o eventi, attivare e disattivare
DELETE/v3/webhooks/{id}Eliminare un webhook
GET/v3/consentsIl registro, con filtri
GET/v3/consents/{id}Una registrazione con le sue prove
POST/v3/consents/{id}/withdrawRevocare un consenso per conto del visitatore
GET/v3/consents/{id}/proofProva PDF di una registrazionePro e Business
GET/v3/consents/{id}/snapshotLa pagina vista dal visitatore, in HTML
GET/v3/consents/{id}/snapshot.pngLa pagina vista dal visitatore, come screenshot
POST/v3/exportsAvviare un’esportazione CSVPro e Business
GET/v3/exports/{id}Un’esportazione e il suo statoPro e Business
GET/v3/exports/{id}/fileScaricare il CSVPro e Business
GET/v3/stats/summaryTotali per un intervallo di giorni
GET/v3/stats/dailyNumeri per giorno (e per paese)
GET/v3/usageConsensi del periodo e limite

La pagina di consenso

Cosa vedranno i visitatori, e in quale lingua?

La pagina che imposti in «Aspetto» nell’area clienti: il modello di testo della nostra libreria, i destinatari dei dati, la dicitura, il link alla tua informativa privacy e, su Business, il tuo logo e il tuo colore. I type e template propri del link hanno la precedenza sull’aspetto. Quando pubblichi una nuova versione, le pagine dei tuoi link cambiano entro un minuto.

La lingua viene presa dal browser del visitatore: inglese, spagnolo, tedesco, francese, italiano, portoghese o russo. Scegli un modello, non le parole: i testi vengono dalla nostra libreria, quindi non puoi scriverne di tuoi.

Finché in «Aspetto» non è pubblicato nulla, la pagina non mostra il link alla tua informativa sulla privacy né i destinatari dei dati. I link vengono comunque creati, e le risposte a POST /v3/links, POST /v3/links/bulk e PATCH /v3/links/{id} portano l'intestazione Consent-Link-Warning: design_unpublished finché la configurazione del link non ha una versione pubblicata.

Come do a link diversi impostazioni di pagina diverse?

Salva più profili della pagina in «Aspetto» o tramite l’API, ciascuno con un proprio id come black-friday, e indicane uno quando crei un link: "profile": "black-friday" in POST /v3/links o in un elemento della creazione in blocco. Senza profile il link riceve il tuo profilo predefinito.

Un link mantiene il suo profilo: se in seguito un altro profilo diventa il predefinito, i link vecchi non cambiano. PATCH /v3/links/{id} con profile sposta un link, e "profile": null lo sposta sul predefinito di quel momento. Un id sconosciuto dà 422 sul campo profile. L’oggetto del link mostra il suo profile, e GET /v3/links?profile=black-friday elenca i link di un profilo. Quanti profili puoi avere dipende dal piano: 1 su Free, 5 su Pro, 50 su Business, predefinito compreso.

Come gestisco i profili tramite l’API?

GET /v3/profiles li elenca, il predefinito per primo. POST /v3/profiles ne crea uno con id e policy_url (obbligatori) e, se vuoi, name, template, vendors, type, remember, brand_name e default. Viene pubblicato subito. PATCH /v3/profiles/{id} lo modifica: i campi della pagina pubblicano subito una nuova versione, name e "default": true da soli non pubblicano nulla.

DELETE /v3/profiles/{id} elimina un profilo che non è il predefinito (409 profile_is_default) e non ha link attivi (409 profile_in_use). Crearne uno oltre il limite del piano, o usarne uno rimasto oltre il limite dopo il passaggio a un piano inferiore, dà 402 profiles_limit_reached. Le modifiche richiedono una chiave reale.

Cosa succede ai parametri del mio indirizzo, come utm o gclid?

Con il consenso il visitatore va alla tua destinazione esattamente come l’hai indicata. Senza consenso anche utm_* e gli altri tuoi parametri restano, e vengono tolti solo gli identificatori dei clic sugli annunci: gclid, gbraid, wbraid, fbclid, msclkid, ttclid, twclid, li_fat_id. In entrambi i casi aggiungiamo un parametro, cl_ct, il token di decisione.

Contano solo i parametri della destinazione stessa: ciò che viene aggiunto al link breve (https://consent.link/nk7Qa?utm_source=…) non viene passato. Metti in destination tutto ciò che serve al tuo sito, oppure crea un link per campagna.

Dove va il visitatore: con il consenso, poi senza
https://shop.example/sale?utm_source=insta&gclid=Cj0K…&cl_ct=eyJhbGciOiJFUzI1NiIs…
https://shop.example/sale?utm_source=insta&cl_ct=eyJhbGciOiJFUzI1NiIs…

Decisioni e webhook

Come fa il mio sito a sapere cosa ha deciso il visitatore?

Ogni reindirizzamento dalla pagina di consenso porta cl_ct, un token firmato (JWT, ES256) che vale 10 minuti. Verificalo dal tuo server con POST /v3/consents/verify: la risposta contiene la decisione, e ogni token si può verificare una sola volta, quindi un indirizzo copiato non vale nulla. Leggi il token, poi toglilo dall’indirizzo.

Cosa contiene: decision (granted o denied), purposes (cosa ha permesso il visitatore), cid (la registrazione nel registro), sid (lo pseudonimo del visitatore nel tuo account, lo stesso su tutti i tuoi link), cexp (fino a quando vale il consenso, in tempo Unix), link, mode, iat e exp. Niente IP, browser o altri dati personali. Un visitatore che ha già accettato lasciando «Non chiedere più» passa direttamente, con granted.

Puoi anche verificare la firma da solo con le chiavi su https://app.consent.link/.well-known/jwks.json e qualsiasi libreria JWT: controlla exp e che link sia uno dei tuoi link. La tua verifica non può sapere se un token è già stato usato; il metodo dell’API sì. Errori: 422 token_invalid, 422 token_expired, 409 token_used.

Richiesta
curl -X POST https://api.consent.link/v3/consents/verify \
  -H "Authorization: Bearer clk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"token": "eyJhbGciOiJFUzI1NiIs…"}'
Risposta
{
  "decision": "granted",
  "purposes": ["stats", "ads"],
  "cid": "01jbz8m3k4x9w2r7d5t6q8v1yh",
  "sid": "psd_Qm9xV3c…",
  "cexp": 1809345604,
  "link": "nk7Qa",
  "mode": "live",
  "iat": 1793712004,
  "exp": 1793712604
}

Come ricevo le decisioni sul mio server nel momento in cui avvengono?

Crea un webhook: POST /v3/webhooks con url e gli events che ti servono (la tabella qui sotto). L’indirizzo deve essere https su un nome host pubblico. La risposta contiene secret (whsec_…) per verificare le firme: viene mostrato una sola volta, quindi salvalo. Un account può avere fino a 10 webhook attivi.

Lo storico delle consegne, il pulsante «Riprova» e l’attivazione o disattivazione di un webhook sono nell’area clienti, in «Account» → «Webhook».

Richiesta
curl -X POST https://api.consent.link/v3/webhooks \
  -H "Authorization: Bearer clk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://shop.example/hooks/consent",
    "events": ["consent.recorded", "consent.withdrawn"]
  }'
Risposta
201 Created
{
  "id": "wh_01jbz9a7c2m5n8p3q6r9s2t5v8",
  "url": "https://shop.example/hooks/consent",
  "events": ["consent.recorded", "consent.withdrawn"],
  "mode": "live",
  "status": "active",
  "secret": "whsec_…",
  "created_at": "2026-11-03T12:00:00.000Z"
}

Quali eventi ci sono e cosa contengono?

Ogni evento è un POST con un corpo JSON: id (evt_…), type, created_at, mode e data. Una registrazione di consenso in data.consent ha id, link, decision, purposes, scope (domain se il visitatore ha lasciato «Non chiedere più», altrimenti link), sid, dest_domain, country, notice_version, created_at ed expires_at. Mai un IP, un browser o un cookie.

EventoQuandodata
consent.recordedUna nuova registrazione: un consenso, un rifiuto o un visitatore che aveva già accettatoconsent
consent.withdrawnUn consenso è stato revocato: dal visitatore su «I miei consensi» o da te tramite l’APIconsent, withdraws
link.blockedAbbiamo bloccato un link perché la sua destinazione si è rivelata pericolosalink, destination, reason, message
export.readyUn’esportazione CSV è terminata (o non è riuscita)id, status, filter, rows, bytes, sha256, file, expires_at
usage.warningÈ stato usato l’80 % o il 100 % dei consensi del periodopercent, consents, limit, period_start, period_end
consent.expiredUn consenso è scaduto: è stato dato 6 mesi fa e non è stato revocato da alloraconsent, expired_at
Cosa riceve il tuo server
POST /hooks/consent
Content-Type: application/json
Consent-Event: consent.recorded
Consent-Delivery: whd_01jbz9d4f7h0k3m6p9r2t5w8y1
Consent-Signature: t=1793712005,v1=5f3a…

{
  "id": "evt_01jbz9d4f6g9j2l5n8q1s4v7x0",
  "type": "consent.recorded",
  "created_at": "2026-11-03T12:00:05.012Z",
  "mode": "live",
  "data": {
    "consent": {
      "id": "01jbz8m3k4x9w2r7d5t6q8v1yh",
      "link": "nk7Qa",
      "decision": "granted",
      "purposes": ["stats", "ads"],
      "scope": "domain",
      "sid": "psd_Qm9xV3c…",
      "dest_domain": "shop.example",
      "country": "DE",
      "notice_version": "statsads-v1",
      "created_at": "2026-11-03T12:00:04.398Z",
      "expires_at": "2027-05-03T12:00:04.398Z"
    }
  }
}

Come verifico che un webhook arriva da voi?

Ogni richiesta porta le intestazioni Consent-Event, Consent-Delivery e Consent-Signature: t=1793712000,v1=5f3a…. v1 è l’HMAC-SHA256 esadecimale del testo t, un punto e il corpo grezzo della richiesta, con il segreto del tuo webhook come chiave.

Calcolalo sul corpo così come è arrivato (prima di interpretare il JSON), confronta in tempo costante e rifiuta un t che si discosti di più di cinque minuti dal tuo orologio, così una richiesta registrata non può essere ripetuta.

PHP
$body = file_get_contents('php://input');
parse_str(str_replace(',', '&', $_SERVER['HTTP_CONSENT_SIGNATURE'] ?? ''), $sig);
$expected = hash_hmac('sha256', ($sig['t'] ?? '').'.'.$body, $secret);
if (abs(time() - (int) ($sig['t'] ?? 0)) > 300 || ! hash_equals($expected, $sig['v1'] ?? '')) {
    http_response_code(400);
    exit;
}
Node.js
const crypto = require('node:crypto');
const sig = Object.fromEntries(req.get('Consent-Signature').split(',').map((p) => p.split('=')));
const expected = crypto.createHmac('sha256', secret).update(`${sig.t}.${rawBody}`).digest('hex');
const ok = Math.abs(Date.now() / 1000 - Number(sig.t)) <= 300
  && typeof sig.v1 === 'string' && sig.v1.length === expected.length
  && crypto.timingSafeEqual(Buffer.from(sig.v1), Buffer.from(expected));

E se il mio server è giù quando parte un evento?

Una consegna conta quando il tuo server risponde 2xx entro 10 secondi; i reindirizzamenti non vengono seguiti. Altrimenti riproviamo, aspettando 1 minuto, 5 minuti, 30 minuti, 2 ore, 12 ore tra un tentativo e l’altro, 6 tentativi in tutto. Dopo l’ultimo la consegna viene segnata come fallita e resta nello storico, dove «Riprova» la invia di nuovo fino a 3 giorni dopo l’evento.

Quindi rispondi in fretta e fai il lavoro dopo. Lo stesso evento può arrivare più di una volta, per esempio dopo un timeout: salta gli id che hai già elaborato. Gli eventi non arrivano sempre nell’ordine in cui sono avvenuti.

Come si revoca un consenso, e cosa succede poi?

I visitatori vedono e revocano i loro consensi su «I miei consensi». Se un visitatore si rivolge invece a te, revocalo per suo conto: POST /v3/consents/{id}/withdraw, senza corpo, con l’id della sua registrazione granted o reused. Funziona per qualsiasi consenso ancora in vigore, per quanto indietro il tuo piano mostri il registro. La risposta è 201 con la nuova registrazione withdrawn, il cui first_consent_id è il consenso revocato. Una registrazione che non è un consenso in vigore (rifiutato, già revocato o scaduto) riceve 409 consent_not_in_force; una che non puoi leggere, 404, come con GET /v3/consents/{id}.

Le due strade portano allo stesso risultato: una registrazione withdrawn nel registro, consent.withdrawn al tuo webhook con data.withdraws, l’id del consenso revocato, e da quel momento i tuoi link chiedono di nuovo a quel visitatore. Una revoca chiude tutti i consensi che il visitatore aveva dato prima per quel dominio, e non conta nel tuo limite.

Smetti di usare i dati del visitatore da parte tua: trovali tramite sid o tramite l’id della registrazione.

Richiesta
curl -X POST https://api.consent.link/v3/consents/01jbz8m3k4x9w2r7d5t6q8v1yh/withdraw \
  -H "Authorization: Bearer clk_live_…"
Risposta
201 Created
{
  "id": "01jc4t7v0x3z6b9d2f5h8k1m4p",
  "link": "nk7Qa",
  "decision": "withdrawn",
  "purposes": [],
  "scope": null,
  "sid": "psd_Qm9xV3c…",
  "dest_domain": "shop.example",
  "country": null,
  "notice_version": null,
  "created_at": "2026-12-14T09:30:12.051Z",
  "expires_at": null,
  "first_consent_id": "01jbz8m3k4x9w2r7d5t6q8v1yh",
  "gpc": false,
  "settings_version": null,
  "evidence": null,
  "chain": {…}
}

Quanto dura un consenso?

Un consenso vale 6 mesi da quando è stato dato: expires_at nella registrazione, cexp nel token di decisione. Una registrazione reused porta l’expires_at del consenso che riutilizza. Dopo, i tuoi link chiedono di nuovo al visitatore.

Quando un consenso granted scade senza essere stato revocato, il tuo webhook riceve consent.expired con data.consent, la registrazione, e data.expired_at. Controlliamo una volta all’ora, quindi arriva entro l’ora successiva a expires_at, una volta per consenso. Le registrazioni reused non hanno un evento proprio: le copre quello del consenso che riutilizzano. L’evento va solo ai webhook con consent.expired in events. Una scadenza viene annunciata una volta sola, anche se allora nessun webhook la aspettava: non viene inviata di nuovo più tardi.

Cosa riceve il tuo server
POST /hooks/consent
Content-Type: application/json
Consent-Event: consent.expired
Consent-Delivery: whd_01jxq3m6p9r2t5w8y1b4d7f0h3
Consent-Signature: t=1809349502,v1=9c1e…

{
  "id": "evt_01jxq3m6p8q1s4v7x0z3b6d9f2",
  "type": "consent.expired",
  "created_at": "2027-05-03T13:05:02.117Z",
  "mode": "live",
  "data": {
    "consent": {
      "id": "01jbz8m3k4x9w2r7d5t6q8v1yh",
      "link": "nk7Qa",
      "decision": "granted",
      "purposes": ["stats", "ads"],
      "scope": "domain",
      "sid": "psd_Qm9xV3c…",
      "dest_domain": "shop.example",
      "country": "DE",
      "notice_version": "statsads-v1",
      "created_at": "2026-11-03T12:00:04.398Z",
      "expires_at": "2027-05-03T12:00:04.398Z"
    },
    "expired_at": "2027-05-03T12:00:04.398Z"
  }
}

Sito e banner

Come applica il mio sito la decisione del visitatore da solo (Google Consent Mode v2)?

Inserisci il nostro script in <head>, prima di GTM e gtag: https://consent.link/js/consent.js. Imposta i valori predefiniti di Consent Mode v2 (tutto negato tranne functionality_storage e security_storage, con wait_for_update di 500 ms), legge cl_ct dall'indirizzo, verifica la firma con le chiavi di https://app.consent.link/.well-known/jwks.json direttamente nel browser e aggiorna il consenso.

La decisione resta nel cookie cl_consent del tuo dominio: fino a cexp per un consenso, 180 giorni per un rifiuto, così le pagine successive non hanno bisogno del banner. Dopo la verifica cl_ct esce dalla barra degli indirizzi; gli altri parametri restano. Lo script non ci invia nulla.

Se registri la decisione da te, verifica il token anche dal tuo server con POST /v3/consents/verify: lo script non può sapere se il token è già stato usato.

HTML
<script src="https://consent.link/js/consent.js"></script>

Come lo configuro in Google Tag Manager?

Scarica il modello consent-link.tpl; in GTM apri Modelli → Nuovo → ⋮ → Importa e salva. Crea un tag dal modello con l'attivatore «Consent Initialization – All Pages» («Inizializzazione del consenso – Tutte le pagine»).

Il tag imposta i valori predefiniti, applica la decisione salvata nel cookie cl_consent e carica lo script, che verifica un cl_ct recente. Non serve allora mettere anche lo script in <head>.

Quali segnali di Consent Mode concede ogni finalità?

Le purposes del token concedono questi segnali. Ciò che non è concesso resta negato; un rifiuto (denied) nega tutto tranne i due sempre concessi.

FinalitàSegnali di Consent Mode
stats analytics_storage
ads ad_storage, ad_user_data, ad_personalization
app_install ad_storage, ad_user_data
personalization personalization_storage
Sempre functionality_storage, security_storage

Uso Cookiebot, OneTrust o un altro banner. Cosa ne faccio?

Non mostrare un secondo banner a chi ha già deciso sulla nostra pagina. Lo script fornisce la decisione in window.consentLink.decision (granted, denied o null) e window.consentLink.has('stats'); window.consentLink.ready si risolve quando il token nell'indirizzo è stato verificato. Ci sono anche l'evento consentlink:update su document e consent_link_update in dataLayer. Carica il nostro script prima di quello del banner.

Cookiebot: passa la decisione con Cookiebot.submitCustomConsent e il suo banner non compare. OneTrust non ha una funzione pubblica per registrare il consenso dal sito, quindi carica il suo script solo se non c'è una decisione. Con gli altri banner allo stesso modo: passa le finalità tramite la loro API o non caricare il banner.

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);
});

Registro, prove e statistiche

Come leggo il registro?

GET /v3/consents elenca le registrazioni, dalle più recenti, con i filtri decision (granted, denied, reused, withdrawn), link, country (DE), from, to e la stessa paginazione dei link. GET /v3/consents/{id} restituisce una registrazione con le sue prove (indirizzo IP, browser, lingua, l’hash del testo della pagina, quando è stata mostrata la pagina e quanto ci ha messo il visitatore) e il suo posto nella catena di hash, chain.

Un rifiuto conserva solo la decisione, l’ora, il link e il paese, quindi il suo evidence è null. L’API dà i dati completi; l’area clienti ne nasconde una parte finché non attivi l’accesso in due passaggi. Quanto indietro puoi vedere dipende dal piano (la tabella in «Piani e limiti»).

Richiesta
curl "https://api.consent.link/v3/consents?decision=granted&from=2026-11-01&limit=100" \
  -H "Authorization: Bearer clk_live_…"

Come ottengo una prova PDF di un consenso?

GET /v3/consents/{id}/proof restituisce la registrazione in PDF: la decisione, chi, cosa è stato mostrato, gli hash e come verificarli. È nella lingua della tua area clienti. Disponibile su Pro e Business (402 plan_required su Free), fino a 20 al minuto. Se il PDF non si può generare in quel momento, la risposta è 503 unavailable con Retry-After.

Richiesta
curl -o proof.pdf https://api.consent.link/v3/consents/01jbz8m3k4x9w2r7d5t6q8v1yh/proof \
  -H "Authorization: Bearer clk_live_…"

Come vedo e verifico la pagina su cui il visitatore ha dato il consenso?

Ogni registrazione granted porta evidence.snapshot_hash: lo SHA-256 della pagina di consenso così come l’ha vista il visitatore, in HTML. Una stessa istantanea vale per tutti i visitatori della stessa pagina, cioè stessa versione di aspetto e testo, lingua e tipo di link. GET /v3/consents/{id}/snapshot restituisce quell’HTML con l’hash nell’intestazione X-Snapshot-Hash, e GET /v3/consents/{id}/snapshot.png uno screenshot. Per entrambi valgono le regole di GET /v3/consents/{id}, compresa la profondità del registro.

Per verificarla, calcola lo SHA-256 dell’HTML esattamente come ricevuto: è uguale a snapshot_hash, e l’hash della registrazione stessa nella catena copre snapshot_hash, quindi la pagina non si può sostituire a posteriori. Ciò che cambia da una visita all’altra è fissato nell’istantanea: l’host della destinazione appare come example.com, la firma del modulo è vuota e la sua action è #. L’indirizzo vero è in dest_domain e evidence.destination.

Le registrazioni reused, i rifiuti e le registrazioni precedenti alle istantanee hanno snapshot_hash null, e la loro istantanea risponde 404 not_found («This record has no page snapshot.»). Subito dopo una decisione i file possono essere ancora in scrittura: 404 not_found con «The page snapshot is not ready yet.» vuol dire riprovare tra poco. L’HTML arriva in pochi secondi, lo screenshot poco dopo. Anche la pagina della registrazione nell’area clienti e la prova in PDF mostrano lo screenshot e l’hash.

Richiesta
curl -o page.html https://api.consent.link/v3/consents/01jbz8m3k4x9w2r7d5t6q8v1yh/snapshot \
  -H "Authorization: Bearer clk_live_…"

sha256sum page.html

Come esporto il registro in CSV?

POST /v3/exports con i filtri di GET /v3/consents (decision, link, country, from, to) risponde subito 202 con l’id dell’esportazione. Il file viene generato in background: ricevi il webhook export.ready, oppure controlli GET /v3/exports/{id} finché status è ready, poi scarichi GET /v3/exports/{id}/file. L’esportazione riporta anche rows e lo sha256 del file.

I file vengono conservati 7 giorni (dopo, 410 export_expired). Possono essere in corso fino a 3 esportazioni contemporaneamente (429 too_many_exports). Pro e Business.

Richiesta
curl -X POST https://api.consent.link/v3/exports \
  -H "Authorization: Bearer clk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "decision": "granted",
    "from": "2026-10-01",
    "to": "2026-11-01"
  }'
Risposta
202 Accepted
{
  "id": "exp_01jbz9f2h5k8m1p4r7t0w3y6a9",
  "type": "csv",
  "status": "queued",
  "source": "api",
  "filter": {
    "decision": "granted",
    "from": "2026-10-01T00:00:00.000Z",
    "to": "2026-11-01T00:00:00.000Z"
  },
  "rows": null,
  "bytes": null,
  "sha256": null,
  "created_at": "2026-11-03T12:00:00.000Z",
  "finished_at": null,
  "expires_at": null,
  "file": null
}

Posso avere statistiche e il mio consumo tramite l’API?

GET /v3/stats/summary dà shown, granted, denied, left, reused e withdrawn per i giorni UTC da from a to (2026-10-31, entrambi inclusi; di default gli ultimi 30 giorni, al massimo 366 giorni, fin dove il tuo piano mostra il registro). Aggiungi link per un solo link. GET /v3/stats/daily dà gli stessi numeri giorno per giorno e, su Pro e Business, per paese con by=country. I bot non si contano mai.

GET /v3/usage mostra i consensi di questo periodo, il tuo limit, quanto resta (remaining) e l’inizio e la fine del periodo.

Richiesta
curl "https://api.consent.link/v3/stats/summary?from=2026-10-01&to=2026-10-31&link=nk7Qa" \
  -H "Authorization: Bearer clk_live_…"
Risposta
{
  "from": "2026-10-01",
  "to": "2026-10-31",
  "link": "nk7Qa",
  "shown": 1840,
  "granted": 1215,
  "denied": 402,
  "left": 198,
  "reused": 25,
  "withdrawn": 3
}

Piani e limiti

Cosa include ogni piano?

L’API, i webhook e la pagina di consenso in sette lingue sono in ogni piano. I piani si differenziano per i consensi al mese, quanto indietro si vede il registro, il ritmo delle richieste e le funzioni in più. Prezzi in euro, IVA esclusa.

PianoPrezzo al meseConsensi al meseRegistroRichieste al minutoProfili di paginaIn più
Free0 €1.000Registro di 30 giorni601—
Pro9 €10.000Registro di 1 anno3005Esportazione CSV e prova in PDF · Statistiche per giorno e paese
Business99 €250.000Registro di 3 anni1.00050Esportazione CSV e prova in PDF · Statistiche per giorno e paese · Il tuo logo e il tuo colore · Link sul tuo dominio

Cosa succede quando finiscono i consensi?

Contano solo i nuovi consensi dati: i rifiuti, le visite ripetute con «Non chiedere più», e i bot no. All’80 % e al 100 % del limite ricevi un’email e il webhook usage.warning.

Una volta esaurito il limite, i nuovi link reali vengono rifiutati con 402 limit_reached. Tutto il resto continua a funzionare: i link esistenti continuano a chiedere e registrare, webhook e token arrivano come sempre e non viene nascosto nulla. La creazione di link riapre all’inizio del periodo successivo (su Free il primo del mese, sui piani a pagamento il giorno del pagamento) o subito dopo il passaggio a un piano superiore.

Quante richieste posso inviare?

Per account, tutte le chiavi insieme: 60 al minuto su Free, 300 su Pro, 1.000 su Business. Oltre, la risposta è 429 rate_limited con un’intestazione Retry-After; le intestazioni X-RateLimit-Limit e X-RateLimit-Remaining mostrano a che punto sei. Alcuni metodi hanno anche un limite proprio: prove PDF 20 al minuto, nuove esportazioni 10, download di esportazioni 30.

Errori e sicurezza

Come sono fatti gli errori?

Sempre nella stessa forma: lo stato HTTP e un corpo JSON con un code stabile e un message in inglese. Basati sul code; il messaggio può essere riformulato. I campi non validi danno 422 validation_failed con fields: ogni campo con i suoi problemi.

StatoCodiceSignificato
401unauthenticatedNessuna chiave, oppure la chiave è errata o revocata
402limit_reachedI consensi del periodo sono esauriti: niente nuovi link reali
402plan_requiredLa funzione richiede un piano superiore
402profiles_limit_reachedOltre il numero di profili di pagina del piano
403account_blockedL’account è bloccato: contatta l’assistenza
403links_blockedL’account non può creare link: contatta l’assistenza
403mode_mismatchUn link reale si modifica con una chiave reale, un link di prova con una chiave di prova
403live_key_requiredServe una chiave reale
404not_foundNiente con questo id nel tuo account
405method_not_allowedQuesto metodo HTTP non è consentito su questo percorso
409link_disabledIl link è disattivato e non si può modificare
409link_blockedIl link è stato bloccato e non si può modificare
409idempotency_in_progressUna richiesta con questa Idempotency-Key è ancora in corso
409token_usedQuesto token di decisione è già stato verificato
409export_not_readyL’esportazione è ancora in preparazione
409export_failedL’esportazione non è riuscita: avviane una nuova
409consent_not_in_forceLa registrazione non è un consenso in vigore: rifiutato, revocato o scaduto
409profile_is_defaultIl profilo predefinito non si può eliminare
409profile_in_useIl profilo ha ancora link attivi
410export_expiredIl file non è più conservato: avvia una nuova esportazione
422validation_failedAlcuni campi non sono validi: vedi fields
422destination_blockedLa destinazione è pericolosa o bloccata
422idempotency_key_reusedLa Idempotency-Key è stata usata con un altro corpo
422token_invalidNon è un token di decisione valido per il tuo account
422token_expiredIl token di decisione ha più di 10 minuti
422webhooks_limit_reachedTroppi webhook attivi
429rate_limitedTroppe richieste: aspetta quanto indica Retry-After
429too_many_exportsTroppe esportazioni in corso
429daily_limit_reachedNuovo account Free: i link del giorno sono finiti, altri dalle 00:00 UTC
500server_errorQualcosa non ha funzionato da parte nostra: riprova più tardi
503unavailableRiprova tra poco: vedi Retry-After
Risposta
422 Unprocessable Content
{
  "error": {
    "code": "validation_failed",
    "message": "Some fields are invalid.",
    "fields": {
      "destination": ["The destination must be an absolute http or https URL."]
    }
  }
}

Cosa faccio se una chiave finisce in mani sbagliate?

Crea una nuova chiave su «Collegati tramite API», passa il tuo server alla nuova chiave, poi revoca la vecchia: smette subito di funzionare. Revocare una chiave non tocca i tuoi link, il registro o i webhook.

Tieni le chiavi nelle variabili d’ambiente del tuo server, mai in un browser, in un’app mobile o in un repository pubblico. Se il segreto di un webhook può essere trapelato, disattiva quel webhook nell’area clienti e creane uno nuovo.

Pronto a collegarti?

Registrati, crea una chiave in «Collegati tramite API» e invia la tua prima richiesta in pochi minuti.

Inizia gratis