REST API pro napojení vašeho systému na Zuboklik
Kompletní dokumentace partnerského API: autentizace, endpointy pro pacienty a objednání, registrace webhooků a ověření HMAC podpisu.
# Vytvoření nového pacienta
curl -X POST https://app.zuboklik.cz/api/v1/patients \
-H 'Authorization: Bearer VÁŠ_API_KLÍČ' \
-H 'Content-Type: application/json' \
-d '{
"patient": {
"first_name": "Jan",
"last_name": "Novák",
"phone_number": "+420777111222",
"pin": "9001011234"
}
}'Autentizace ordinace
Každá ordinace, která chce zpřístupnit API, dostane od Zubokliku jeden hlavní API klíč. Ten slouží k registraci vašeho napojeného systému a k ověření identity ordinace.
Jak získat API klíč
- 1
Kontaktujte Zuboklik
Napište na technicka@zuboklik.cz — ověříme, že vaše řešení splňuje naše partnerské podmínky, a nasdílíme vám API klíč ordinace.
- 2
API klíč uložte bezpečně
Klíč obdržíte jednorázově při registraci. Uchovávejte jej v secrets manageru (Vault, AWS Secrets Manager, Keychain). Nikdy jej neukládejte do git repozitáře.
- 3
Klíč v produkci pravidelně rotujte
Při podezření na kompromitaci kontaktujte Zuboklik — klíč zneplatníme a vygenerujeme nový. Doporučujeme rotaci alespoň jednou za 12 měsíců.
# API klíč ordinace se posílá v hlavičce # Authorization: ApiKey <office_api_key> # alternativně: X-Api-Key: <office_api_key> # Používá se pouze ve dvou scénářích: # 1) registrace nového ConnectedSystem # 2) odpojení (DELETE) ConnectedSystem # # Všude jinde (čtení/zápis pacientů, objednání, # správa webhooků) použijte Bearer token vašeho # ConnectedSystemu, viz další sekce.
Dva typy klíčů, nepleťte si je
API klíč ordinace (ApiKey) prokazuje vlastnictví ordinace. Bearer token vašeho ConnectedSystemu prokazuje, že jste již napojeni. Jsou to dvě různé věci — v produkční komunikaci budete typicky používat jen Bearer token, ApiKey slouží jen k bootstrapu a odpojení.
Připojení vašeho systému
Po získání API klíče ordinace zaregistrujte svůj systém jedním HTTP požadavkem. V odpovědi dostanete Bearer token, který budete používat pro veškerou další komunikaci.
Registrace nového systému
Jméno vašeho systému musí být unikátní v rámci ordinace. Slouží k identifikaci v audit logu a k vizualizaci v administraci Zubokliku.
Hlavičky požadavku
Tělo požadavku
Odpověď 201 Created
api_key si uložte: API klíč v odpovědi dostanete pouze jednou. Ihned jej uložte do secrets manageru — v databázi je uložen pouze jeho SHA-256 otisk. Při ztrátě klíče je nutné vytvořit nový ConnectedSystem.
Odpojení systému
Systém se odpojí jedním požadavkem. Po odpojení už jeho Bearer token nefunguje a nelze jej obnovit — pro opětovné napojení je nutné vytvořit nový ConnectedSystem.
Hlavičky požadavku
Volitelně můžete do query přidat důvod: ?reason=migrace-na-v2. Důvod se uloží do audit logu ordinace.
Bezpečnostní kontrola: DELETE vyžaduje jak Bearer token vašeho systému, tak API klíč ordinace. Tím je zajištěno, že útočník s ukradeným Bearer tokenem nemůže odpojit systém jiné ordinace.
Správa pacientů
CRUD endpointy pro pacienty. Všechny operace jsou automaticky scopovány na ordinaci, která vlastní Bearer token. Pacienti jiných ordinací nejsou přístupní.
Vrátí aktivní pacienty ordinace (deaktivovaní se nezahrnují), seřazené podle příjmení a jména. Stránkování je výchozí 25 pacientů na stránku, maximálně 100.
Příklad požadavku
Příklad odpovědi 200 OK
Vrátí jednoho aktivního pacienta podle relativního ID v ordinaci.
Příklad požadavku
Příklad odpovědi 200 OK
Vytvoří nového pacienta. PIN slouží k přihlášení v Zubokliku. Pokud pacient se stejným PINem v ordinaci již existuje, vrátí API chybu 422.
Příklad požadavku
Příklad odpovědi 201 Created
Aktualizuje vybrané atributy pacienta. Neposlané atributy zůstanou nezměněné.
Příklad požadavku
Příklad odpovědi 200 OK
Pacient se fyzicky neodstraní (smazání by porušilo zákonem danou retenční povinnost), pouze se nastaví deactivated_at a deactivate_reason. Pacient se přestane zobrazovat v seznamech a nelze jej znovu použít pro nové objednání.
Příklad požadavku
Odpověď
Správa objednání (Entry)
Objednání v Zubokliku se nazývají Entry. Každé objednání má typ (EntryType), stav (EntryState) a volitelně vazbu na pacienta přes patient_symptoms.
Vrátí objednání ordinace, nejnovější první. Dovolené (vacation) záznamy jsou vynechány — ty slouží jen internímu blokování kalendáře.
Příklad požadavku
Stránkovaná odpověď 200 OK
Vrátí jedno objednání včetně patient_symptoms.
Příklad požadavku
Odpověď 200 OK
Vytvoří nové objednání pro ordinaci. Pokud entry vyžaduje vazbu na pacienta, je nutné dodat pole patient_symptoms_attributes s patient_id a symptom_id. Pacient musí existovat v téže ordinaci.
Příklad požadavku
Odpověď 201 Created
Aktualizuje vybrané atributy. Pokud je v těle patient_symptoms_attributes, stávající vazby se nahradí novými.
Příklad požadavku
Odpověď 200 OK
Fyzicky odstraní objednání z databáze. Tato operace je nevratná — pokud chcete objednání pouze zrušit, změňte entry_state_id na odpovídající stav (např. canceled).
Příklad požadavku
Odpověď
Ukázka kompletního Entry objektu
Toto je plná struktura odpovědi, kterou vrací GET /api/v1/entries/:id a POST /api/v1/entries.
Real-time notifikace o změnách
Webhooky vám umožní reagovat na změny v Zubokliku v reálném čase — žádné periodické polling. Každý CRUD nad objednáním nebo pacientem vaší ordinace zašle POST na váš endpoint s HMAC podpisem.
1. Zaregistrujte URL
POST na /api/v1/webhooks s URL vašeho endpointu. Dostanete zpět jednorázově HMAC secret.
2. Ověřte podpis
Vždy ověřte hlavičku X-Zuboklik-Signature proti tělu požadavku a X-Zuboklik-Timestamp.
3. Odpovězte rychle
Váš endpoint musí odpovědět 2xx do 10 sekund. Při pomalé odpovědi se doručení opakuje.
Registrace nového webhooku
URL musí být https a nesmí směřovat na privátní IP adresu ani na metadata služby cloudů (SSRF ochrana). Maximální délka URL je 2048 znaků.
Požadavek
Odpověď 201 Created
secret si uložte: HMAC secret dostanete v odpovědi pouze jednou. Ihned jej uložte do secrets manageru. Zuboklik ukládá jen SHA-256 otisk. Při ztrátě je nutné vytvořit nový webhook (nový secret).
Formát payloadu
Payload je záměrně minimální: pouze ID a typ události. Pro získání detailů zavolejte zpětně GET na příslušný endpoint.
Proč je payload tenký? V případě kompromitace webhook URL uniknou jen ID a typy. Plná data získáte jen tehdy, pokud útočník zároveň zná váš Bearer token.
HTTP hlavičky doručení
| Hlavička | Příklad | Význam |
|---|---|---|
| X-Zuboklik-Signature | a1b2c3d4…(64 hex znaků) | HMAC-SHA256(payload, secret) počítaný vůči tělu požadavku a X-Zuboklik-Timestamp. |
| X-Zuboklik-Timestamp | 1752670800 | Unix timestamp v sekundách v době doručení. Slouží k ochraně proti replay útokům. |
| X-Zuboklik-Delivery | f1e2d3c4-… | Unikátní ID doručení, vhodné pro deduplikaci na vaší straně. |
| X-Zuboklik-Event | patient_created | Typ události (stejná hodnota jako event v těle payloadu). |
Ověření HMAC podpisu
Každý webhook je podepsaný HMAC-SHA256. Podpis se počítá z těla požadavku a timestampu. Cílem je dvoufaktorové ověření: (1) sdílíte s námi secret, (2) každá zpráva je opatřena jedinečným podpisem.
Algoritmus
Podpis se počítá nad řetězcem složeným z těla požadavku a timestampu. Obě strany tak musí počítat ze stejných vstupních dat — v opačném případě podpis nesedí.
- 1Vezměte surové tělo požadavku (raw body, ne parsovaný JSON).
- 2Připojte k němu X-Zuboklik-Timestamp oddělený tečkou: {body}.{timestamp}.
- 3Spočítejte HMAC-SHA256 s vaším webhook secretem.
- 4Porovnejte výsledek (hex) s hlavičkou X-Zuboklik-Signature — musí se shodovat bit po bitu.
- 5Volitelně zkontrolujte, že X-Zuboklik-Timestamp není starší než 5 minut (ochrana proti replay).
require 'openssl'
def verify(body, timestamp, signature, secret)
expected = OpenSSL::HMAC.hexdigest(
'SHA256',
secret,
"#{body}.#{timestamp}"
)
ActiveSupport::SecurityUtils.secure_compare(expected, signature)
end
# V controlleru (Rails):
# def webhook
# body = request.raw_post
# ts = request.headers['X-Zuboklik-Timestamp']
# sig = request.headers['X-Zuboklik-Signature']
# ok = verify(body, ts, sig, ENV['ZUBOKLIK_WEBHOOK_SECRET'])
# head :unauthorized unless ok
# # ... zpracování payloadu ...
# endOchrana proti replay útokům
Při ověření podpisu vždy zkontrolujte, že X-Zuboklik-Timestamp není starší než 5 minut (případně jiný rozumný limit podle vašeho use-case). Tím zabráníte tomu, aby útočník mohl zachycenou zprávu odeslat znovu.
Časté dotazy
Praktické odpovědi na otázky, které typicky řeší partneři při prvním napojení.
Ano — založte si zkušební ordinaci přes standardní registrační formulář (Wizards::Office) a v nastavení získejte API klíč. Všechny operace jsou izolované na úrovni ordinace, takže se nemusíte bát vedlejších efektů.
API povoluje 600 požadavků za minutu na jeden ConnectedSystem. Při překročení dostanete HTTP 429 Too Many Requests s hlavičkou Retry-After. Doporučujeme implementovat exponenciální backoff.
API vrací JSON s polem errors obsahujícím název atributu a lidsky čitelnou zprávu. Implementujte zobrazení těchto zpráv koncovému uživateli vašeho systému — zákazník tak dostane srozumitelnou zpětnou vazbu.
Ne. Webhook URL musí být veřejně dostupná a směřovat na https endpoint. Toto omezení chrání před SSRF útoky na interní infrastrukturu Zubokliku.
Kontaktujte nás okamžitě na technicka@zuboklik.cz. Klíč zneplatníme, všechny vaše ConnectedSystemy se odpojí a budete si muset zaregistrovat nové. Staré klíče již nikdy nebudou fungovat.
Ano, v produkci vyžadujeme výhradně HTTPS. HTTP požadavky dostanou odpověď 426 Upgrade Required. Pro lokální vývoj můžete použít reverse proxy (např. ngrok).
Chcete napojit svůj systém?
Pokud máte zájem o partnerské API, napište nám. Probereme vaše potřeby, nasdílíme vám API klíč pro vaši testovací ordinaci a pomůžeme s integrací.