Dokumentace › API

API Cookies správně

HTTP API pro čtení záznamů o souhlasech, které nasbírala vaše cookie lišta. Autentizace bearer tokenem, odpovědi v JSON, stránkování kurzorem. Celá reference je na téhle jedné stránce.

Obsah stránky

1. K čemu API slouží

API má dva endpointy:

  • GET /api/v2/licenses vrací licence, na které dosáhne váš token, a jejich id.
  • GET /api/v2/consents vrací stránkovaný export souhlasů jedné licence.

Základní adresa je https://cookies-spravne.cz/api/v2.

Souhlas je v datech stav, ne událost. Jeden řádek na dvojici licence a návštěvník, přepisovaný při každé změně volby. Export tedy vrací aktuální rozhodnutí každého návštěvníka, ne časovou řadu jeho kliknutí. Podrobně v části GET /api/v2/consents.

Zápis, mazání ani webhooky API nemá. Souhlasy vznikají výhradně v liště.

Konvence

Základní adresahttps://cookies-spravne.cz/api/v2
MetodyGET
Content-Type odpovědiapplication/json
Cacheoba endpointy odpovídají s Cache-Control: no-store
ČasyUTC, ISO 8601 se sufixem Z, přesnost na sekundy
id souhlasuUUID jako řetězec
license_idcelé číslo
Booleanytruefalse

Úspěšná odpověď obsahuje data, metalinks. Chybová obsahuje error a nikdy data.

Starší API

Integrace postavené na původním systému mohou dál používat endpointy /api/consent-report/api/consent-configs. Popis najdete na konci této stránky. Nové integrace stavte na v2.

2. Autentizace

Token vygenerujete v administraci v sekci Účet → API přístup a posíláte ho v hlavičce Authorization jako bearer token. Jeden účet má vždy nejvýše jeden token.

Jak token poslat

GET /api/v2/licenses HTTP/1.1
Host: cookies-spravne.cz
Authorization: Bearer cs_2f9Ktz...

Vlastnosti tokenu

Vydáníadministrace, Účet → API přístup
Formátcs_ a 48 znaků, celkem 51
Početjeden token na účet
Rozsahlicence vlastněné účtem a licence s ním sdílené
Přenosvýhradně hlavička Authorization, parametr ?token= se nečte

Token se zobrazí jen jednou, při vygenerování. Poté v administraci uvidíte už jen poslední čtyři znaky, datum vytvoření a datum posledního použití. Token je určený pro komunikaci mezi servery, nikdy ho nevkládejte do kódu, který běží v prohlížeči.

Správa tokenu

  • Vygenerovat token vytvoří nový token a jednorázově ho zobrazí.
  • Vygenerovat nový token okamžitě nahradí ten stávající. Integrace používající starý token přestane fungovat.
  • Zrušit token okamžitě uzavře přístup.

Pole Naposledy použit je vaše kontrolka. Pokud API nepoužíváte a přesto ukazuje nedávné použití, token pravděpodobně unikl. Nechte si vygenerovat nový.

Chybný nebo chybějící token

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="cookiesspravne", error="invalid_token"
Cache-Control: no-store
Content-Type: application/json

{"error":{"code":"invalid_token","message":"The API token is missing, malformed or no longer valid."}}

3. GET /api/v2/licenses

Vrací všechny licence, na které dosáhne váš token, seřazené podle id. Bez parametrů a bez stránkování. Odsud si vezmete id, které pak použijete jako license_id při exportu souhlasů.

Požadavek

curl -sS -H "Authorization: Bearer $TOKEN" \
  "https://cookies-spravne.cz/api/v2/licenses"

Odpověď

{
  "data": [
    { "id": 1, "domain": "example.cz", "is_active": true,  "created_at": "2025-04-01T09:12:00Z" },
    { "id": 7, "domain": "eshop.cz",   "is_active": false, "created_at": "2026-01-20T14:03:00Z" }
  ]
}

Pole záznamu

PoleTypVýznam
idintHodnota parametru license_id u endpointu /consents.
domainstringDoména, pro kterou licence platí.
is_activeboolZda licence běží. Neaktivní licence zůstává čitelná i s celou svou historií souhlasů.
created_atstring nebo nullVznik licence.

Licenční klíč, kterým se autentizuje lišta, se v odpovědi nezobrazí. Stejně tak tarif ani stav fakturace.

4. GET /api/v2/consents

Stránkovaný export souhlasů jedné licence. Povinný je jediný parametr license_id, zbytek má rozumné výchozí hodnoty.

Parametry

ParametrPovinnýHodnotyVýchozí
license_idanoint
limitne1 až 10000100
order_bynecreated_at, updated_atcreated_at
orderneasc, descasc
fromneY-m-d nebo ISO 8601
toneY-m-d nebo ISO 8601
cursorneopaque řetězec

Jak se parametry validují

  • license_id musí být číslo. Chybějící, prázdný nebo nečíselný vrací 400 invalid_request. Syntakticky platný, ale bez přístupu k licenci vrací 404 license_not_found. API nerozlišuje „neexistuje“ a „nemáte přístup“.
  • limit nečíselný vrací 400. Číselný se ořízne do rozsahu 1 až 10000: limit=50000 vrátí 10000 řádků, limit=0 vrátí jeden. Použitá hodnota je vždy v odpovědi v poli meta.limit.
  • order_byorder mimo povolené hodnoty, například order_by=id, vrací 400 invalid_request.
  • fromto přijímají buď holé datum Y-m-d, nebo úplný ISO 8601 formát, který se použije přesně. from=2026-06-01 znamená 2026-06-01T00:00:00Z, to=2026-06-30 znamená 2026-06-30T23:59:59Z. Obě hranice jsou inkluzivní. Neexistující datum jako 2026-02-31 vrací 400 invalid_date. from větší než to vrátí prázdnou stránku.
  • Rozsah dat se aplikuje na sloupec zvolený v order_by.order_by=updated_at tedy from znamená „změněno od“, ne „vzniklo od“.

Odpověď

curl -sS -H "Authorization: Bearer $TOKEN" \
  "https://cookies-spravne.cz/api/v2/consents?license_id=1&limit=100"
{
  "data": [
    {
      "id": "9c1f7a2e-5b3d-4e18-9a6c-2f0d81b7e4aa",
      "uid": "aB3xY7kQ",
      "license_id": 1,
      "created_at": "2026-06-01T10:00:00Z",
      "updated_at": "2026-06-04T08:31:00Z",
      "necessary": true,
      "analytics": false,
      "marketing": false,
      "ad_user_data": false,
      "ad_personalization": false,
      "was_shown": true,
      "was_dismissed": false
    }
  ],
  "meta": {
    "count": 100,
    "limit": 100,
    "order": "asc",
    "order_by": "created_at",
    "has_more": true,
    "next_cursor": "v1.eyJ0IjoiMjAyNi0wNi0wMSAxMDowMDowMCJ9"
  },
  "links": {
    "next": "https://cookies-spravne.cz/api/v2/consents?license_id=1&limit=100&cursor=v1.eyJ0IjoiMjAyNi0wNi0wMSAxMDowMDowMCJ9"
  }
}

Pole záznamu

PoleTypVýznam
idstring (UUID)Primární klíč záznamu. Přepisem volby se nemění.
uidstring nebo nullIdentifikátor uživatele. Slouží k dohledání souhlasu, návštěvník ho vidí v liště a může vám ho nahlásit.
license_idintLicence, ke které záznam patří.
created_atstring nebo nullPrvní záznam k dané licenci.
updated_atstring nebo nullPoslední zápis k licenci.
necessaryboolNezbytné cookies.
analyticsboolAnalytické cookies.
marketingboolMarketingové cookies.
ad_user_databoolGoogle Consent Mode, signál ad_user_data.
ad_personalizationboolGoogle Consent Mode, signál ad_personalization.
was_shownboolLišta byla návštěvníkovi zobrazena.
was_dismissedboolLišta byla zavřena křížkem, bez volby kategorií.

Interní odkaz na verzi konfigurace, kterou návštěvník viděl, a příznak importu ze staršího systému se neexportují. Pokud je potřebujete, napište nám na podpora@cookies-spravne.cz.

Pole meta a links

PoleTypVýznam
meta.countintPočet záznamů v data.
meta.limitintLimit po oříznutí do povoleného rozsahu.
meta.orderstringSměr řazení.
meta.order_bystringPoužitý řadicí sloupec.
meta.has_moreboolExistuje další stránka.
meta.next_cursorstring nebo nullKurzor na další stránku.
links.nextstring nebo nullPůvodní dotaz se všemi parametry a doplněným kurzorem.

links.next je sestavený z query stringu příchozího požadavku, do kterého se doplní cursor. Zachovává tedy i limit, order_by, fromto, se kterými stránkování začalo.

Datový model souhlasu

Lištu zajímá aktuální rozhodnutí návštěvníka, ne jeho historie. Zápis je proto upsert na dvojici license_iduid: jeden řádek na návštěvníka, přepisovaný při každé změně volby.

Příznaky was_shownwas_dismissed jsou v exportu proto, že bez nich mají tři různé situace stejný tvar, tedy všechny kategorie na false:

was_shownwas_dismissedCo se stalo
truefalseNávštěvník lištu viděl a všechny kategorie odmítl.
truetrueNávštěvník lištu zavřel, aniž by kategorie nastavil.
falsefalseLišta se návštěvníkovi nevykreslila.

5. Řazení a stránkování

Pro pravidelný import dat vždy řaďte podle updated_at. Stránkuje se kurzorem, který si pamatuje filtry původního dotazu a neexpiruje.

Řazení a aktuálnost dat

Pro pravidelný import používejte order_by=updated_at. Při řazení podle jiného pole se do exportu nemusí dostat aktualizované souhlasy stávajících návštěvníků a vaše data budou neaktuální.

Důvod je v datovém modelu: souhlas je stav, ne událost. Když si návštěvník volbu rozmyslí, jeho řádek se přepíše, ale created_at zůstane staré. Při řazení podle created_at takový záznam leží dál na starém místě a váš přírůstkový import ho mine.

Stránkování

Jedna stránka vrátí nejvýše 10 000 záznamů. Další stránky se čtou parametrem cursor, jehož hodnotu najdete v odpovědi v meta.next_cursor. V links.next máte rovnou celou adresu další stránky i se všemi původními parametry.

GET /api/v2/consents?license_id=1&limit=2

{ "data": [ … 2 řádky … ],
  "meta": { "count": 2, "limit": 2, "has_more": true, "next_cursor": "v1.eyJ0IjoiMjAyNi0w…" },
  "links": { "next": "…&cursor=v1.eyJ0IjoiMjAyNi0w…" } }
GET /api/v2/consents?license_id=1&limit=2&cursor=v1.eyJ0IjoiMjAyNi0w…

{ "data": [ … 2 řádky … ],
  "meta": { "count": 2, "limit": 2, "has_more": true, "next_cursor": "v1.eyJ0IjoiMjAyNi0x…" },
  "links": { "next": "…&cursor=v1.eyJ0IjoiMjAyNi0x…" } }
GET /api/v2/consents?license_id=1&limit=2&cursor=v1.eyJ0IjoiMjAyNi0x…

{ "data": [ … 1 řádek … ],
  "meta": { "count": 1, "limit": 2, "has_more": false, "next_cursor": null },
  "links": { "next": null } }

Další stránka existuje, dokud platí has_more === true a zároveň links.next !== null. Hodnota has_more je odvozená z toho, že se načte o řádek víc, než kolik se vrátí.

Vlastnosti kurzoru

  • Zachovává filtry původního dotazu. Použití s jiným license_id, order, order_by, from nebo to vrací 400 cursor_mismatch.
  • Nevalidní kurzor vrací 400 invalid_cursor.
  • Neexpiruje. Ukazuje na pozici v pořadí, ne na výsledek dotazu.

6. Limity a chyby

S platným tokenem máte 120 požadavků za minutu. Každá chybová odpověď má stejný tvar: objekt error s poli codemessage.

Limity

KlíčLimit
Účet s platným tokenem120 požadavků za minutu
IP adresa bez platného tokenu10 požadavků za minutu

S platným tokenem se limit klíčuje na účet, nikoli na IP. Servery za jednou NAT adresou si tedy rozpočet nedělí, zato dva stroje téhož účtu ano. Při limit=10000 strop odpovídá 1 200 000 řádkům za minutu.

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{"error":{"code":"rate_limited","message":"Too many requests."}}

Odpověď 429 nenese hlavičku Retry-After ani hlavičky X-RateLimit-*. Okno je pevná minuta, stačí tedy počkat a zopakovat požadavek.

Tvar chybové odpovědi

Stejný tvar mají všechny chyby včetně 500:

{
  "error": {
    "code": "invalid_token",
    "message": "The API token is missing, malformed or no longer valid."
  }
}

Chybové kódy

HTTPcodeKdy nastane
400invalid_requestChybějící nebo nevalidní license_id, order_by, order nebo limit.
400invalid_datefrom nebo to není Y-m-d ani ISO 8601, nebo jde o neexistující datum.
400invalid_cursorKurzor nelze dekódovat.
400cursor_mismatchKurzor vznikl s jinými filtry, než nese aktuální dotaz.
401invalid_tokenToken chybí, je nevalidní nebo byl zrušen.
404license_not_foundLicence neexistuje, nebo k ní nemáte přístup.
429rate_limitedPřekročený limit požadavků.
500server_errorChyba na straně API.

Příklad

GET /api/v2/consents?license_id=abc

HTTP/1.1 400 Bad Request

{"error":{"code":"invalid_request","message":"A numeric license_id is required."}}

7. Příklady volání

Tři ukázky k rovnou použití: plný export do JSONL, přírůstkové čtení změn a načtení jedné stránky.

Plný export do JSONL

Bash s curl a jq. Prochází všechny stránky přes links.next, dokud nějaká další existuje.

#!/usr/bin/env bash
set -euo pipefail

TOKEN="cs_…"
URL="https://cookies-spravne.cz/api/v2/consents?license_id=1&limit=1000"

while [ -n "$URL" ]; do
  BODY=$(curl -sS -H "Authorization: Bearer $TOKEN" "$URL")
  echo "$BODY" | jq -c '.data[]' >> souhlasy.jsonl
  URL=$(echo "$BODY" | jq -r '.links.next // ""')
done

Přírůstkové čtení změn

JavaScript. Čte záznamy změněné od zadaného okamžiku, řadí podle updated_at a umí počkat při překročení limitu.

const TOKEN = process.env.COOKIES_SPRAVNE_TOKEN;
const BASE = 'https://cookies-spravne.cz/api/v2/consents';

async function* changes(licenseId, since) {
  let url = `${BASE}?license_id=${licenseId}&order_by=updated_at&order=asc&limit=1000`
    + (since ? `&from=${encodeURIComponent(since)}` : '');

  while (url) {
    const res = await fetch(url, { headers: { Authorization: `Bearer ${TOKEN}` } });

    if (res.status === 429) {
      await new Promise(resolve => setTimeout(resolve, 60_000));
      continue;
    }

    if (!res.ok) {
      const { error } = await res.json();
      throw new Error(`${res.status} ${error.code}: ${error.message}`);
    }

    const { data, links } = await res.json();

    yield* data;

    url = links.next;
  }
}

Jedna stránka v PHP

<?php

$token = getenv('COOKIES_SPRAVNE_TOKEN');

$context = stream_context_create([
    'http' => [
        'method' => 'GET',
        'header' => "Authorization: Bearer {$token}\r\n",
    ],
]);

$url = 'https://cookies-spravne.cz/api/v2/consents?' . http_build_query([
    'license_id' => 1,
    'order_by' => 'updated_at',
    'order' => 'asc',
    'limit' => 1000,
]);

$page = json_decode(file_get_contents($url, false, $context), true);

Při pravidelném importu si ukládejte čas posledního úspěšného běhu a příště ho předejte v parametru from spolu s order_by=updated_at. Stáhnete tak jen to, co se změnilo.

8. Starší API (v1)

Endpointy původního systému zůstávají dostupné na stejných adresách a vrací data ve stejném formátu, aby stávající integrace fungovaly beze změny.

Nové integrace stavte na API v2 popsaném výše. Tahle část je tu jen kvůli zpětné kompatibilitě.

Autentizace staršího API

Starší API se neautentizuje API tokenem, ale klíčem pro starší API, který jste dostali při aktivaci přístupu v původním systému. Pokud ho u účtu evidujeme, najdete ho v administraci v části Účet → API přístup. Pokud ho tam nevidíte, napište nám na podpora@cookies-spravne.cz.

API token z v2 na starších endpointech nefunguje a klíč pro starší API nefunguje na v2.

Klíč se posílá v hlavičce Authorization. Kvůli zpětné kompatibilitě se přijímá i hlavička Authentication, kterou uváděla původní dokumentace:

Authorization: Bearer xxxxxxxxx
Authentication: Bearer xxxxxxxxx

Odpovědi jsou vždy application/json. Chyby mají stejný tvar i kódy jako v2 a platí pro ně i stejné limity.

GET /api/consent-report

Vrací souhlasy uživatelů. Podporuje stránkování a filtrování.

ParametrPovinnýVýznam
keyanoLicenční klíč domény, ze které chcete report. Licence musí patřit vašemu účtu nebo s ním být sdílená, jinak 404 license_not_found.
fromneDatum Y-m-d. Samostatně tvoří interval od zadaného dne do dneska, uvedený den je součástí intervalu.
toneDatum Y-m-d. Samostatně tvoří interval od počátku do zadaného dne, uvedený den není součástí intervalu.
limitnePočet záznamů na stránku. Výchozí 1000, maximální 10000.
pageneČíslo stránky, první má číslo 1.

Spojením fromto vznikne interval, který zahrnuje from a nezahrnuje to. Například ?from=2022-01-01&to=2022-02-01 vrátí celý leden 2022. Filtruje se podle data prvního udělení souhlasu, tedy date_of_consent, a záznamy jsou podle něj vzestupně seřazené.

Hlavičky odpovědi

x-document-countCelkový počet záznamů odpovídajících filtrům key, fromto.
x-total-pagesCelkový počet stránek. Závisí na parametru limit.

Příklad

curl -sS -H "Authorization: Bearer $LEGACY_KEY" \
  "https://cookies-spravne.cz/api/consent-report?key=bstl7sn95ns7sno97s1q&from=2022-01-01&to=2022-02-01&page=1"
[
  {
    "_id": { "$oid": "9c1f7a2e-5b3d-4e18-9a6c-2f0d81b7e4aa" },
    "uid": "CxQ25iVbozc2o82J4RcuX1Lv5DoXpO",
    "key": "bstl7sn95ns7sno97s1q",
    "necessary": "1",
    "analytics": "0",
    "marketing": "1",
    "config": { "$oid": "4812" },
    "date_of_consent": "1644842294"
  }
]
PoleTypVýznam
_id.$oidstringIdentifikátor záznamu.
uidstring nebo nullUnikátní ID uživatele, podle kterého je možné uživatele identifikovat.
keystringLicenční klíč domény.
necessarystringVždy "1".
analyticsstring"1" nebo "0" podle uděleného souhlasu.
marketingstring"1" nebo "0" podle uděleného souhlasu.
configobject nebo null$oid konfigurace z /api/consent-configs, kterou uživatel viděl.
date_of_consentstringUnixový timestamp, kdy uživatel poprvé udělil souhlas.

GET /api/consent-configs

Vrací všechny verze nastavení lišty a jejích textů, které se návštěvníkům zobrazily. Souhlasy mohou být vázané k jinému znění lišty, proto má každý souhlas v poli config odkaz na konkrétní verzi. Jediný parametr je povinný key se stejným významem jako výše.

[
  {
    "_id": { "$oid": "4812" },
    "modified": 1644236417,
    "texts": {
      "cs": {
        "reject_all": "Odmítnout",
        "cookie_policy": "Více o cookies",
        "iframe_no_cookies": "Pro zobrazení tohoto obsahu povolte prosím ukládání cookies."
      }
    }
  }
]

_id.$oid odpovídá hodnotě config.$oid ve výpisu souhlasů, modified je unixový timestamp, kdy se tato verze poprvé zobrazila, a texts obsahuje texty lišty podle jazyka.

Rozdíly oproti původnímu systému

  • Souhlas je jeden záznam na návštěvníka. Když návštěvník volbu změní, záznam se přepíše a date_of_consent zůstává datem prvního souhlasu. Pro sledování změn použijte API v2 s order_by=updated_at.
  • Chyby vrací JSON s objektem error. Například chybějící key vrací 400 invalid_request.