Přeskočit na obsah
Naše paměť

Geni API: proč se zápis povede a přesto nic nezapíše

Nejzákeřnější chyba při práci s Geni API není ta, co spadne, ale ta, co se tváří úspěšně a data zahodí.

Dva zápisové endpointy Geni vracejí stejnou odpověď, ale každý uloží jiná data.
Dva zápisové endpointy Geni vracejí stejnou odpověď, ale každý uloží jiná data.

5 minut čtení

Když začnete propojovat svá lokální genealogická data s globálním stromem na Geni.com, dříve nebo později narazíte na potřebu automatizace. Ruční přepisování desítek nebo stovek profilů je nejen únavné, ale především náchylné k chybám. Rozhodnete se tedy využít Geni API. Zpočátku se zdá vše přímočaré: autentizace přes OAuth2 funguje, čtení profilů vrací krásně strukturovaný JSON, a tak se pustíte do zápisu. Vytvoříte skript, posíláte payloady a terminál se plní zelenými hláškami s HTTP statusem 200 OK. Všechno běží jako po drátkách.

Pak ale otevřete webové rozhraní Geni a zjistíte, že na profilech chybí povolání. Nebo že zmizely přesné dny a měsíce narození a zůstaly jen roky. Přitom API jasně hlásilo úspěch. Právě jste narazili na jednu z nejtemnějších uliček automatizované genealogie: nejzákeřnější chyba není ta, co vaši aplikaci shodí s pětistovkou, ale ta, co vrátí 200 a tiše nedělá vůbec nic, nebo hůř, ničí existující detaily.

Dva endpointy, jeden zmatek

Základní problém spočívá v tom, že Geni API nabízí pro úpravu profilu dva různé zápisové endpointy: /profile/update-basics a prosté /profile/update. Na první pohled by se mohlo zdát, že jde o synonyma nebo historické relikty, které dělají víceméně totéž. Opak je pravdou. Liší se sice jen v několika málo polích, ale tyto rozdíly jsou naprosto zásadní pro integritu vašich dat.

Klíčová pole jako occupation (povolání), public (viditelnost profilu) a locked (uzamčení) endpoint /update-basics nezapíše - podle dokumentace na ně vede jen /update. Jak uvidíte níže, neznamená to, že by je nepřijal žádný jiný endpoint. Pokud se pokusíte tato specifická pole odeslat na /update-basics, narazíte na architektonické rozhodnutí, které vás bude stát hodiny ladění.

Tiché zahození dat

Představte si následující situaci. Máte v databázi u profilu zjištěné povolání (např. mlynář) a chcete ho zapsat. Pošlete následující požadavek:

curl -X POST "https://www.geni.com/api/profile/update-basics?access_token=VASE_TOKEN" \
     -d "id=profile-12345" \
     -d "occupation=mlynář" \
     -d "first_name=Jan"

Očekáváte, že pokud endpoint pole occupation nepodporuje, vrátí HTTP 400 Bad Request s chybovou hláškou, že pole není povoleno. Geni API se ale zachová jinak. Parametr occupation tiše zahodí, jméno "Jan" (pokud se měnilo) aktualizuje a vrátí vám sebevědomé 200 OK.

Z pohledu vašeho skriptu se operace zdařila. Zaznamenáte si do lokální databáze, že profil byl úspěšně synchronizován. Ve skutečnosti se ale povolání nezapsalo. Vaše data jsou nyní asynchronní a vy o tom nevíte. Tento typ selhání je extrémně nebezpečný, protože nevytváří žádné logy chyb. Zjistíte to až náhodným manuálním auditem, často měsíce poté, co skript proběhl.

Destruktivní zápis vnořených objektů

Tiché zahazování dat ale není jediným úskalím. Mnohem destruktivnější je způsob, jakým API zpracovává vnořené objekty (nested objects), jako jsou například data narození či úmrtí.

Řekněme, že u profilu již existuje datum narození: 15. března 1850. Vy jste v matrice objevili nový údaj - profil se týká osoby, která se narodila v roce 1851, nikoliv 1850. Rozhodnete se tedy opravit rok. V dobré víře pošlete payload, který obsahuje pouze změněný rok:

{
  "birth": {
    "date": {
      "year": 1851
    }
  }
}

Odesíláte na endpoint /update. Odpověď? 200 OK. Podíváte se na profil a zjistíte, že datum narození je nyní pouze "1851". Den a měsíc nenávratně zmizely.

Co se stalo? Geni API neprovádí u vnořených objektů operaci typu merge (sloučení s existujícími daty), ale replace (kompletní nahrazení). Vnořený objekt se přepisuje celý: zapíšeš rok narození a smažeš tím den a měsíc. Pokud zapíšete jen rok, posíláte implicitně informaci, že den a měsíc jsou prázdné. Tímto způsobem můžete velmi snadno zničit léta manuální práce. Správný postup vyžaduje nejprve načíst celý stávající objekt birth, modifikovat v něm pouze rok, a poté odeslat celý objekt zpět.

# Takto vypadá správný zápis celého objektu přes cURL
curl -X POST "https://www.geni.com/api/profile/update?access_token=VASE_TOKEN" \
     -d "id=profile-12345" \
     -d "birth[date][year]=1851" \
     -d "birth[date][month]=3" \
     -d "birth[date][day]=15"

Jediný spolehlivý indikátor úspěchu

Vzhledem k těmto specifikům se nabízí otázka: jak vůbec poznat, že zápis skutečně prošel a zapsal to, co měl? Jak jsme si ukázali, HTTP 200 ani návratový JSON samotný nestačí.

Skutečnost je taková, že že se zápis stoprocentně povedl, poznáš jedině podle updated_at - ne podle odpovědi. Pokud pošlete změnu, která je API tiše ignorována, hodnota updated_at (čas poslední úpravy profilu) se nezmění.

Spolehlivý zápisový cyklus tedy musí vypadat takto:

  1. Přečtení profilu (uložení původního updated_at).
  2. Sestavení dat a odeslání POST požadavku.
  3. Přijetí 200 OK.
  4. Nové přečtení profilu a porovnání nového updated_at s původním. Pouze pokud se časové razítko posunulo, víte, že se na serveru něco reálně změnilo.

Dokumentace je spodní hranice, ne výčet

Když se s těmito problémy setkáte, pravděpodobně zamíříte do oficiální dokumentace. Zde vás ale čeká další překvapení. Dokumentace Geni API je spodní hranice možného, ne vyčerpávající výčet.

Zářným příkladem je endpoint /profile/add-parent. Jeho účelem je vytvořit nový profil rodiče k existující osobě. V dokumentaci occupation vůbec nemá, ale přesto ho přijímá.

Zkusili jsme totiž occupation přidat rovnou do volání add-parent - a API ho přijalo a úspěšně uložilo. Ověřeno to bylo zpětným čtením nově vytvořeného profilu přes GET požadavek. Kolik dalších takových nezdokumentovaných polí jednotlivé endpointy přijímají, je otázkou experimentování.

Rada na závěr: Mapujte terén

Spoléhat se při práci s Geni API jen na selský rozum a dokumentaci je přímá cesta k poškozeným datům. Předtím, než vypustíte jakýkoliv skript na ostrá data, musíte si vybudovat vlastní testovací sadu.

Rada na závěr: stáhni si dokumentaci lokálně a udělej si vlastní, podrobnou tabulku „které pole jde zapsat kterým endpointem". Bez toho se jenom hádáš se strojem, který vás bude chlácholit statusem 200, zatímco vám bude ignorovat posílaná data. Agentické nástroje vyžadují přesně vymezené hranice a ty vám Geni API samo nedá. Musíte si je otestovat sami.