Kramerius API dokumentace
Zdroj: README.mdAPI endpoint: kramerius.php
Endpoint slouží pro dohledání UUID stránky v Krameriu podle vstupu z Wikidat, nebo pro dohledání informací o stránce podle jejího UUID.
Stav po migraci
- Runtime resolver je provozován ve FastAPI službě
kramerius-api. - Přes gateway zůstává kontrakt
POST /kramerius/apibeze změny (požadavek je routován do FastAPI). - Soubor
kramerius/api/kramerius.phpslouží pro dokumentaci (GET /kramerius/api). - Přímé
POSTvolání na tento PHP skript není určeno pro API runtime.
URL a metoda
- URL: /kramerius/api
- Metoda POST: API lookup endpoint (Content-Type: application/json)
- Metoda GET bez query parametrů a bez body: vrátí tuto dokumentaci v HTML podobě (pro pohodlné otevření v prohlížeči)
Poznámka: GET s query parametry nebo s body není podporován a vrací 405.
Režim 1: Wikidatový lookup (wd + page)
Request body
| Pole | Povinné | Popis |
|---|---|---|
| wd | ano | QID dokumentu na Wikidatech (např. Q123456). |
| page | ano | Číslo stránky (např. 12). |
| volume | ne | Ročník nebo svazek. |
| volume_years | ne | Období ročníku (např. 1831 nebo 1830-1831). |
| issue | ne | Číslo vydání. |
| issue_type | ne | Typ vydání, používá se pro zpřesnění shody podle mods:note v streams/BIBLIO_MODS (např. večerní, večerní vydání, večerní vyd.). |
| issue_date | ne | Datum vydání (YYYY-MM-DD, YYYY-MM, YYYY nebo DD.MM.YYYY). |
| supplement | ne | Číslo přílohy (např. 1 nebo "2. příloha"). |
| debug | ne | Boolean; pokud je true, vrací se debug_trace. |
| manual_limit | ne | Integer 10-400; maximální počet kandidátů pro manuální výběr (volitelné, jinak adaptivně podle úplnosti vstupu). |
| manual_depth | ne | Integer 3-16; hloubka průchodu stromu Krameria při manuálním fallbacku (volitelné, jinak adaptivně podle úplnosti vstupu). |
Příklad requestu:
{
"wd": "Q96613911",
"page": "140",
"volume": "3",
"volume_years": "1849",
"issue": "18",
"issue_type": "",
"issue_date": "1849-04-01",
"supplement": "",
"debug": false
}Režim 2: Přímý UUID lookup (uuid)
Dohledá veškeré dostupné informace o stránce podle jejího UUID. Procházení hierarchie:
stránka → vydání → svazek → dokument.
Poznámka: pokud stránka leží ve větvi supplement, API u issue_uuid vrací přednostně UUID rodičovského čísla (periodicalitem), nikoli UUID samotné přílohy. Díky tomu zůstávají pole issue, issue_date a citace konzistentní.
Request body
| Pole | Povinné | Popis |
|---|---|---|
| uuid | ano | UUID stránky v Krameriu (např. 35d64c24-9cf2-408b-9147-935f1323be20). |
| debug | ne | Boolean; pokud je true, vrací se debug_trace. |
Příklad requestu:
{
"uuid": "35d64c24-9cf2-408b-9147-935f1323be20",
"debug": false
}Úspěšná odpověď
HTTP status: 200
Struktura odpovědi je stejná pro oba režimy (Wikidatový i UUID lookup):
{
"ok": true,
"selection_required": false,
"results_meta": {
"offset": 0,
"batch_size": 25,
"returned_count": 1,
"minimum_total_count": 1,
"has_more": false
},
"results": [
{
"api_base": "https://ndk.cz/search/api/v5.0",
"view_url": "https://ndk.cz/uuid/uuid:35d64c24-9cf2-408b-9147-935f1323be20",
"document_uuid": "ae811ecf-435d-11dd-b505-00145e5790ea",
"volume_uuid": "b1a8ec04-435d-11dd-b505-00145e5790ea",
"issue_uuid": "e5204673-435d-11dd-b505-00145e5790ea",
"page_uuid": "35d64c24-9cf2-408b-9147-935f1323be20",
"document": "Blahověst: Katolický týdenník pro Čechy, Morawany, Slowáky a Slezany",
"volume_nr": "3",
"volume_years": "1849",
"issue": "18",
"issue_type": "",
"issue_date": "1849-04-01",
"supplement": "",
"page": "140",
"page_label": "140",
"citation": "Blahověst: Katolický týdenník pro Čechy, roč. 3 (1849), č. 18, 1. dubna 1849, str. 140"
}
]
}Poznámka: Pole debug_trace je vráceno pouze při debug=true, proto v běžné odpovědi s debug=false nebude přítomno.
Význam polí v results:
| Pole | Popis |
|---|---|
| api_base | Detekovaná základní URL Kramerius API. |
| view_url | Přímý odkaz do Digitální knihovny/NDK na nalezenou stránku. |
| document_uuid | UUID dokumentu. |
| volume_uuid | UUID svazku nebo ročníku. |
| issue_uuid | UUID vydání. |
| page_uuid | UUID stránky. |
| document | Název periodika nebo dokumentu. |
| volume_nr | Číslo ročníku nebo svazku. |
| volume_years | Rok nebo období ročníku. |
| issue | Číslo vydání. |
| issue_type | Typ vydání zadaný uživatelem a použitý pro filtraci. Pokud filtr použit nebyl, může zůstat prázdné i tehdy, když se typ vydání propsal do citation. |
| issue_date | Datum vydání v ISO formátu podle dostupné přesnosti (YYYY, YYYY-MM nebo YYYY-MM-DD). Pokud upstream vrátí DD.MM.YYYY nebo MM.YYYY, API jej před vrácením normalizuje. |
| supplement | Číslo přílohy v normalizovaném formátu, pokud je k dispozici. |
| page | Normalizované číslo strany použité pro dohledání. |
| page_label | Textové označení strany vrácené Krameriem. |
| citation | Lidsky čitelná citace vhodná pro zobrazení v UI. Pokud je v Krameriu dostupný typ vydání (mods:note), může být součástí citace i bez vyplněného pole issue_type. |
Poznámka k issue_uuid: u stránek z příloh (supplement) je issue_uuid normalizováno na rodičovské vydání (periodicalitem), pokud je v metadata kontextu dostupné.
Poznámka: u textových příloh může API při nedohledání přílohy v přesně zadaném čísle projít i další kandidátní čísla ve stejném ročníku a vybrat to, které přílohu skutečně obsahuje.
Sémantika selection_required
Ideální výsledek API je právě jedna jednoznačně určená stránka. V praxi se ale mohou vrátit i více shody (širší dotaz nebo nedokonalá metadata ve zdroji).
selection_required neznamená "je více výsledků". Znamená "klient musí přepnout do ručního režimu".
| Stav | ok | selection_required | Význam |
|---|---|---|---|
| Jednoznačný výsledek (UUID nebo přesný WD dotaz) | true | false | API dohledalo cílovou stránku automaticky. |
| Více automaticky dohledaných správných výsledků (jeden stejný zdroj má více UUID nebo je na více instancích Krameria) | true | false | API vrátilo více platných výsledků; klient může použít results[0]. |
| Nejednoznačný výsledek (HTTP 300) | false | true | Automatické dohledání není jednoznačné, klient musí vybrat správnou stránku z kandidátů. |
| Nedohledán výsledek | false | true | Automatické dohledání selhalo, uživatel musí pokračovat ručně (např. přes ruční prohlížení). |
Doporučené chování klienta:
- Pokud
ok=truearesultsobsahuje více položek, vyzvat uživatele ke zpřesnění vstupu a spustit nové vyhledání. - Pokud
selection_required=true, přepnout do ručního režimu.
Chybová odpověď
Endpoint vrací chybovou odpověď ve třech praktických režimech:
HTTP 300 — manuální výběr
Endpoint nalezl více kandidátů a nelze jednoznačně určit správnou stránku. Klient musí zobrazit výběr uživateli.
{
"ok": false,
"error_code": "selection_required",
"selection_required": true,
"manual_user_message": "Bylo nalezeno více odpovídajících výsledků. Vyberte prosím správnou stránku.",
"results": [
{
"api_base": "https://ndk.cz/search/api/v5.0",
"document_uuid": "uuid:...",
"document": "...",
"volume_nr": "...",
"volume_years": "...",
"issue": "...",
"issue_type": "...",
"issue_date": "...",
"supplement": "...",
"page": "...",
"page_label": "...",
"citation": "...",
"page_uuid": "uuid:...",
"volume_uuid": "uuid:...",
"issue_uuid": "uuid:...",
"view_url": "https://ndk.cz/uuid/uuid:...",
"preview_url": "https://...",
"full_preview_url": "https://..."
}
]
}HTTP 422 — chyba dohledání
Dohledání selhalo (např. neplatný vstupní kontext stránky nebo nedostupná data zdroje). Podle typu selhání může být selection_required buď false (tvrdá chyba), nebo true (API doporučuje ruční pokračování).
{
"ok": false,
"error": "Položka na Wikidatech neobsahuje UUID dokumentu.",
"error_code": "missing_document_uuid",
"selection_required": false,
"results": [],
"results_meta": {
"offset": 0,
"batch_size": 25,
"returned_count": 0,
"minimum_total_count": 0,
"has_more": false
}
}Pole chybové odpovědi
| Pole | Popis |
|---|---|
| ok | Vždy false. |
| error | Textový popis chyby. Přítomno u chybových odpovědí mimo větev HTTP 300 s kandidáty. |
| error_code | Strojově čitelný kód chyby (viz níže). |
| status | HTTP status kód odpovědi (stejná hodnota jako ve status line). |
| selection_required | true, pokud klient musí nabídnout uživateli ruční výběr nebo ruční dohledání; jinak false. |
| results_meta.offset | Offset použité dávky výsledků. |
| results_meta.batch_size | Velikost dávky výsledků vrácené endpointem. |
| results_meta.returned_count | Počet skutečně vrácených položek v results. |
| results_meta.minimum_total_count | Minimální jistý počet nalezených položek. Pokud je has_more: true, skutečný počet může být vyšší. |
| results_meta.has_more | true, pokud existují další výsledky za aktuální dávkou. |
| manual_user_message | Zpráva pro zobrazení uživateli. Přítomno pouze při HTTP 300. |
| results | Kandidáti pro manuální výběr (HTTP 300), jinak obvykle prázdné pole. |
| error_detail | Interní detail chyby. Přítomno pouze při debug=true. |
| debug_trace | Ladící výpis průběhu. Přítomno pouze při debug=true. |
| failure_context | Kontext selhání (vstupní payload a metadata). Přítomno pouze při debug=true. |
Kódy chyb
| error_code | HTTP | Popis |
|---|---|---|
| selection_required | 300 | Nalezeno více kandidátů, vyžadován manuální výběr. |
| missing_required_params | 400 | Chybí povinný parametr (např. page). |
| invalid_wd | 400 | Neplatný formát parametru wd. |
| cors_origin_blocked | 403 | Origin je explicitně blokován blacklistem CORS. |
| cors_origin_not_allowed | 403 | Origin v CORS požadavku není na whitelistu. |
| wikidata_uuid_not_found | 404 | Na Wikidatech nebylo nalezeno UUID pro Kramerius. |
| wikidata_entity_not_found | 404 | Wikidata entita nebyla nalezena. |
| document_not_found | 404 | Dokument nebyl v cílové instanci nalezen. |
| api_base_not_found | 404 | Nepodařilo se dohledat API base pro UUID dokumentu. |
| upstream_not_found | 404 | Nadřazená služba nevrátila požadovaný zdroj. |
| all_wd_candidates_failed | 404 | Žádný kandidát z WD nevedl na použitelný výsledek. |
| method_not_allowed | 405 | Nepodporovaná HTTP metoda nebo GET s parametry/body. |
| missing_document_uuid | 422 | Wikidatový záznam neobsahuje UUID dokumentu. |
| page_not_found | 422 | Stránka podle zadaného čísla nebyla v dokumentu nalezena. |
| empty_document | 422 | Dokument nemá dostupné stránky nebo obsah. |
| invalid_upstream_json | 502 | Nadřazená služba vrátila neplatnou JSON odpověď. |
| registry_unavailable | 502 | Registr Kramerius není dostupný. |
Pole kandidátů v results (HTTP 300)
Každý kandidát obsahuje stejná pole jako úspěšná odpověď (viz tabulku výše), doplněná o:
| Pole | Popis |
|---|---|
| preview_url | URL náhledu skenu stránky. |
| full_preview_url | URL skenu stránky v plném rozlišení. |
HTTP status kódy
| HTTP status | Metoda | Popis |
|---|---|---|
| 200 | GET | Vrací dokumentaci API (pouze bez parametrů a bez body). |
| 200 | POST | Dohledání úspěšné (ok: true). |
| 204 | OPTIONS | Odpověď na preflight požadavek. |
| 300 | POST | Manuální výběr vyžadován — endpoint nalezl více kandidátů (selection_required: true). |
| 400 | POST | Neplatný nebo neúplný vstup (missing_required_params, invalid_wd). |
| 403 | GET/POST/OPTIONS | CORS origin není povolen (error_code: cors_origin_not_allowed). |
| 404 | POST | Zdroj nebyl nalezen (wikidata_uuid_not_found, document_not_found, all_wd_candidates_failed aj.). |
| 405 | * | Nepodporovaná metoda nebo GET s parametry. |
| 422 | POST | Dohledání stránky selhalo (např. missing_document_uuid, page_not_found, empty_document). |
| 502 | POST | Chyba nebo nedostupnost nadřazené služby (invalid_upstream_json, registry_unavailable). |
Omezení počtu výsledků
- Endpoint vrací maximálně prvních 25 výsledků.
results_meta.minimum_total_countvrací minimální jistý počet nalezených položek zjištěný v aktuálním průchodu.- Pokud existují další kandidáti,
results_meta.has_morejetrue. - API neposkytuje offset/cursor pro načítání dalších dávek; klient má uživatele vést k upřesnění dotazu.
CORS konfigurace
CORS je řízen pouze environment proměnnými, takže stejný endpoint lze bezpečně použít pro web, mobil i server-to-server klienty.
| Proměnná | Výchozí hodnota | Popis |
|---|---|---|
KRAMERIUS_API_CORS_MODE | whitelist | Režim CORS: whitelist (jen povolené originy) nebo blacklist (povol vše kromě blokovaných). |
CORS_MODE | whitelist | Kratší alias k KRAMERIUS_API_CORS_MODE (fallback). |
KRAMERIUS_API_CORS_ALLOWED_ORIGINS | prázdné | Čárkou oddělený whitelist originů, např. https://app.example.com,https://admin.example.com. Pokud je prázdné, CORS je vypnutý. |
CORS_ALLOWED_ORIGINS | prázdné | Kratší alias k KRAMERIUS_API_CORS_ALLOWED_ORIGINS (fallback, když hlavní proměnná není nastavena). |
KRAMERIUS_API_CORS_BLOCKED_ORIGINS | prázdné | Čárkou oddělený blacklist originů. Podporuje přesnou shodu i masku *.domena.tld. |
CORS_BLOCKED_ORIGINS | prázdné | Kratší alias k KRAMERIUS_API_CORS_BLOCKED_ORIGINS (fallback). |
KRAMERIUS_API_CORS_ALLOW_CREDENTIALS | false | Pokud je true, odpověď vrací konkrétní origin a Access-Control-Allow-Credentials: true. |
CORS_ALLOW_CREDENTIALS | false | Kratší alias k KRAMERIUS_API_CORS_ALLOW_CREDENTIALS (fallback). |
KRAMERIUS_API_CORS_ALLOWED_HEADERS | prázdné | Volitelné doplnění povolených hlaviček (k výchozím: Content-Type, Authorization, X-Requested-With, X-Request-Id, X-Client-Version). |
CORS_ALLOWED_HEADERS | prázdné | Kratší alias k KRAMERIUS_API_CORS_ALLOWED_HEADERS (fallback). |
KRAMERIUS_API_CORS_EXPOSE_HEADERS | prázdné | Volitelné hlavičky pro Access-Control-Expose-Headers. |
CORS_EXPOSE_HEADERS | prázdné | Kratší alias k KRAMERIUS_API_CORS_EXPOSE_HEADERS (fallback). |
KRAMERIUS_API_CORS_MAX_AGE | 600 | Hodnota Access-Control-Max-Age pro preflight (0 až 86400). |
CORS_MAX_AGE | 600 | Kratší alias k KRAMERIUS_API_CORS_MAX_AGE (fallback). |
Poznámka: pokud zapnete credentials, nepoužívejte wildcard origin *; nastavte explicitní whitelist.
Příklad konfigurace (dev)
export CORS_MODE="blacklist"
export CORS_BLOCKED_ORIGINS="https://evil.example,*.blocked.local"
export CORS_ALLOW_CREDENTIALS="0"
export CORS_ALLOWED_HEADERS="Content-Type,Authorization"
export CORS_MAX_AGE="600"Poznámka: v režimu blacklist je CORS otevřený pro všechny originy mimo CORS_BLOCKED_ORIGINS.
Příklad konfigurace (produkce)
export CORS_MODE="blacklist"
export CORS_BLOCKED_ORIGINS="https://evil.example,https://malicious.example,*.botnet.invalid"
export CORS_ALLOW_CREDENTIALS="0"
export KRAMERIUS_API_CORS_ALLOWED_HEADERS="Content-Type,Authorization"
export KRAMERIUS_API_CORS_EXPOSE_HEADERS="X-Request-Id"
export KRAMERIUS_API_CORS_MAX_AGE="600"Preflight odpověď při povoleném originu vrací minimálně:
Access-Control-Allow-Origin: *(v režimublacklistpřiCORS_ALLOW_CREDENTIALS=0)Access-Control-Allow-Origin: <konkrétní origin>(pokud jsou zapnuté credentials)Access-Control-Allow-Methods: POST, OPTIONSAccess-Control-Allow-Headers: Content-Type, AuthorizationAccess-Control-Max-Age: 600Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
CORS ověření přes curl
1) Jednoduchý GET z povoleného originu
curl -i 'https://tools.daelba.eu/kramerius/api/' \
-H 'Origin: https://app.example.com'2) Preflight OPTIONS
curl -i -X OPTIONS 'https://tools.daelba.eu/kramerius/api/' \
-H 'Origin: https://www.daelba.eu' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: content-type'3) Blokovaný origin
curl -i -X POST 'https://tools.daelba.eu/kramerius/api/' \
-H 'Origin: https://www.daelba.eu' \
-H 'Content-Type: application/json' \
-d '{}'curl -i -X OPTIONS 'https://tools.daelba.eu/kramerius/api/' \
-H 'Origin: https://evil.example' \
-H 'Access-Control-Request-Method: POST'curl -i -X POST 'https://tools.daelba.eu/kramerius/api/' \
-H 'Origin: https://evil.example' \
-H 'Content-Type: application/json' \
-d '{"wd":"Q123456","page":"12"}'Očekávání pro blokovaný origin: bez Access-Control-Allow-Origin, typicky HTTP 403 a JSON s error_code: cors_origin_blocked.
cURL příklady
Wikidatový lookup:
curl -X POST 'https://tools.daelba.eu/kramerius/api/' \
-H 'Content-Type: application/json' \
-d '{
"wd": "Q96613911",
"page": "140",
"volume": "3",
"volume_years": "",
"issue": "18",
"issue_type": "",
"issue_date": "1849-04-01",
"supplement": "",
"debug": false
}'Přímý UUID lookup:
curl -X POST 'https://tools.daelba.eu/kramerius/api/' \
-H 'Content-Type: application/json' \
-d '{
"uuid": "35d64c24-9cf2-408b-9147-935f1323be20",
"debug": false
}'Testování
Integrační test endpointu (s mockovanými externími HTTP odpověďmi):
php kramerius/tests/api-endpoint-integration-test.phpSmoke test CORS (lokální PHP server + curl):
bash kramerius/tests/cors-smoke-test.shPoznámka: test využívá pouze pro testovací běh environment proměnnou KRAMERIUS_HTTP_MOCK_BOOTSTRAP, která přesměruje HTTP volání na lokální mock provider.