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ží
- 2. Autentizace
- 3. GET /api/v2/licenses
- 4. GET /api/v2/consents
- 5. Řazení a stránkování
- 6. Limity a chyby
- 7. Příklady volání
- 8. Starší API (v1)
1. K čemu API slouží
API má dva endpointy:
GET /api/v2/licensesvrací licence, na které dosáhne váš token, a jejichid.GET /api/v2/consentsvrací 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í adresa | https://cookies-spravne.cz/api/v2 |
|---|---|
| Metody | GET |
| Content-Type odpovědi | application/json |
| Cache | oba endpointy odpovídají s Cache-Control: no-store |
| Časy | UTC, ISO 8601 se sufixem Z, přesnost na sekundy |
| id souhlasu | UUID jako řetězec |
license_id | celé číslo |
| Booleany | true a false |
Úspěšná odpověď obsahuje data, meta a links. 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 a /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át | cs_ a 48 znaků, celkem 51 |
| Počet | jeden token na účet |
| Rozsah | licence vlastněné účtem a licence s ním sdílené |
| Přenos | vý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
| Pole | Typ | Význam |
|---|---|---|
id | int | Hodnota parametru license_id u endpointu /consents. |
domain | string | Doména, pro kterou licence platí. |
is_active | bool | Zda licence běží. Neaktivní licence zůstává čitelná i s celou svou historií souhlasů. |
created_at | string nebo null | Vznik 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
| Parametr | Povinný | Hodnoty | Výchozí |
|---|---|---|---|
license_id | ano | int | – |
limit | ne | 1 až 10000 | 100 |
order_by | ne | created_at, updated_at | created_at |
order | ne | asc, desc | asc |
from | ne | Y-m-d nebo ISO 8601 | – |
to | ne | Y-m-d nebo ISO 8601 | – |
cursor | ne | opaque řetězec | – |
Jak se parametry validují
license_idmusí 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“.limitnečíselný vrací400. Číselný se ořízne do rozsahu 1 až 10000:limit=50000vrátí 10000 řádků,limit=0vrátí jeden. Použitá hodnota je vždy v odpovědi v polimeta.limit.order_byaordermimo povolené hodnoty, napříkladorder_by=id, vrací400 invalid_request.fromatopřijímají buď holé datumY-m-d, nebo úplný ISO 8601 formát, který se použije přesně.from=2026-06-01znamená2026-06-01T00:00:00Z,to=2026-06-30znamená2026-06-30T23:59:59Z. Obě hranice jsou inkluzivní. Neexistující datum jako2026-02-31vrací400 invalid_date.fromvětší nežtovrátí prázdnou stránku.- Rozsah dat se aplikuje na sloupec zvolený v
order_by. Sorder_by=updated_attedyfromznamená „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
| Pole | Typ | Význam |
|---|---|---|
id | string (UUID) | Primární klíč záznamu. Přepisem volby se nemění. |
uid | string nebo null | Identifiká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_id | int | Licence, ke které záznam patří. |
created_at | string nebo null | První záznam k dané licenci. |
updated_at | string nebo null | Poslední zápis k licenci. |
necessary | bool | Nezbytné cookies. |
analytics | bool | Analytické cookies. |
marketing | bool | Marketingové cookies. |
ad_user_data | bool | Google Consent Mode, signál ad_user_data. |
ad_personalization | bool | Google Consent Mode, signál ad_personalization. |
was_shown | bool | Lišta byla návštěvníkovi zobrazena. |
was_dismissed | bool | Liš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
| Pole | Typ | Význam |
|---|---|---|
meta.count | int | Počet záznamů v data. |
meta.limit | int | Limit po oříznutí do povoleného rozsahu. |
meta.order | string | Směr řazení. |
meta.order_by | string | Použitý řadicí sloupec. |
meta.has_more | bool | Existuje další stránka. |
meta.next_cursor | string nebo null | Kurzor na další stránku. |
links.next | string nebo null | Pů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, from a to, 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_id a uid: jeden řádek na návštěvníka, přepisovaný při každé změně volby.
Příznaky was_shown a was_dismissed jsou v exportu proto, že bez nich mají tři různé situace stejný tvar, tedy všechny kategorie na false:
was_shown | was_dismissed | Co se stalo |
|---|---|---|
true | false | Návštěvník lištu viděl a všechny kategorie odmítl. |
true | true | Návštěvník lištu zavřel, aniž by kategorie nastavil. |
false | false | Liš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,fromnebotovrací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 code a message.
Limity
| Klíč | Limit |
|---|---|
| Účet s platným tokenem | 120 požadavků za minutu |
| IP adresa bez platného tokenu | 10 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
| HTTP | code | Kdy nastane |
|---|---|---|
400 | invalid_request | Chybějící nebo nevalidní license_id, order_by, order nebo limit. |
400 | invalid_date | from nebo to není Y-m-d ani ISO 8601, nebo jde o neexistující datum. |
400 | invalid_cursor | Kurzor nelze dekódovat. |
400 | cursor_mismatch | Kurzor vznikl s jinými filtry, než nese aktuální dotaz. |
401 | invalid_token | Token chybí, je nevalidní nebo byl zrušen. |
404 | license_not_found | Licence neexistuje, nebo k ní nemáte přístup. |
429 | rate_limited | Překročený limit požadavků. |
500 | server_error | Chyba 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 // ""')
donePří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 xxxxxxxxxOdpově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í.
| Parametr | Povinný | Význam |
|---|---|---|
key | ano | Licenč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. |
from | ne | Datum Y-m-d. Samostatně tvoří interval od zadaného dne do dneska, uvedený den je součástí intervalu. |
to | ne | Datum Y-m-d. Samostatně tvoří interval od počátku do zadaného dne, uvedený den není součástí intervalu. |
limit | ne | Počet záznamů na stránku. Výchozí 1000, maximální 10000. |
page | ne | Číslo stránky, první má číslo 1. |
Spojením from a to 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-count | Celkový počet záznamů odpovídajících filtrům key, from a to. |
|---|---|
x-total-pages | Celkový 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"
}
]| Pole | Typ | Význam |
|---|---|---|
_id.$oid | string | Identifikátor záznamu. |
uid | string nebo null | Unikátní ID uživatele, podle kterého je možné uživatele identifikovat. |
key | string | Licenční klíč domény. |
necessary | string | Vždy "1". |
analytics | string | "1" nebo "0" podle uděleného souhlasu. |
marketing | string | "1" nebo "0" podle uděleného souhlasu. |
config | object nebo null | $oid konfigurace z /api/consent-configs, kterou uživatel viděl. |
date_of_consent | string | Unixový 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_consentzůstává datem prvního souhlasu. Pro sledování změn použijte API v2 sorder_by=updated_at. - Chyby vrací JSON s objektem
error. Například chybějícíkeyvrací400 invalid_request.