76. REST API (automatizace a integrace)
MyÚčto.cz nabízí veřejné REST API pro integraci s e-shopy, CRM, Make/Zapier a vlastními skripty. API používá Personal Access Tokens (PAT) v hlavičce Authorization.
Dokumentační rozhraní
K dispozici jsou tři varianty stejné dokumentace nad jedním OpenAPI specem (navzájem se prolinkují v horní liště):
| URL | Nástroj | Použití |
|---|---|---|
| /api/docs | Swagger UI | „Try it out" — vlož API token (Authorize) a volej endpointy přímo z prohlížeče |
| /api/reference | Redoc | Pretty static reference, 3-sloupcový layout, lepší typografie pro čtení |
| /api/scalar | Scalar | Moderní reference s vestavěným API klientem a fulltext vyhledáváním |
| /api/openapi.yaml | Raw OpenAPI 3.1 | Import do Postmana, Insomnie, Zapier Custom App, Make HTTP modulu |
openapi.yaml dnes pokrývá i novější agendy nad rámec fakturace a klientů — účetnictví (tagy okolo podvojného účetnictví, účtové osnovy, období a deníku), sklad (skladové karty, pohyby, doklady, inventury), e-shop (katalog zboží, kategorie, číselníky) a klientský portál (agregovaný přehled hospodaření). Detailní chování jednotlivých endpointů popisují kapitoly k dané agendě — tady jde jen o to, že přes REST API se dá automatizovat i tahle část systému.
76.1 Vytvoření tokenu
- Systém → API tokeny (admin) nebo profil uživatele.
- Klikni Nový token, vyplň:
- Název — pojmenuj integraci (např. „Make zapier reporting“).
- Dodavatel — když má účet víc firem, vyber, do které firmy token patří. Doporučeno; token bound na konkrétního dodavatele nemůže přistupovat k datům jiných firem.
- Rozsah —
read(jen GET) neboread & write(plné API). - Expirace — volitelná. Bez expirace token platí, dokud ho ručně nezrušíš.
- Čerstvé ověření — použij passkey nebo TOTP. Passkey otevře systémový dialog zařízení; TOTP vyžaduje aktuální šestimístný kód. Ověření je jednorázové a vázané přímo na vytvoření tokenu.
- Po vytvoření zobrazíme plain-text token (
mi_pat_…) — jen jednou. Ulož ho do password manageru, zpětně už ho nezobrazíme.
Samotné přihlášení pomocí MFA nestačí: vytvoření PAT vždy vyžaduje nový účelový step-up, pokud má účet passkey nebo TOTP. Účet bez jakéhokoli silného faktoru se místo toho prokáže aktuálním heslem. Proof pro jinou operaci ani odemčení zamčené PWA token nevytvoří. PAT je bearer credential a serverový zámek browserové session se na něj nevztahuje; chraň jej vlastní expirací, minimálním scopem a včasnou revokací.
76.2 Použití tokenu
curl -H "Authorization: Bearer mi_pat_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
https://myucto.cz/api/v1/auth/api-me
Response:
{
"user": { "id": 1, "email": "you@example.com", "name": "Petr", "role": "admin" },
"supplier": { "id": 1, "company_name": "Acme s.r.o.", "display_name": "Acme" },
"auth_method": "bearer",
"token": { "id": 42, "name": "Make integrace", "prefix": "mi_pat_abcd", "scope": "read_write", "expires_at": null }
}
Příklady
Seznam faktur za leden 2026:
curl -H "Authorization: Bearer mi_pat_…" \
"https://myucto.cz/api/v1/invoices?from=2026-01-01&to=2026-01-31"
Vytvoření klienta:
curl -X POST https://myucto.cz/api/v1/clients \
-H "Authorization: Bearer mi_pat_…" \
-H "Content-Type: application/json" \
-d '{
"company_name": "Nový klient s.r.o.",
"ic": "12345678",
"street": "Hlavní 1",
"city": "Praha",
"zip": "11000",
"country_id": 1
}'
Označení faktury jako zaplacené:
curl -X POST https://myucto.cz/api/v1/invoices/123/mark-paid \
-H "Authorization: Bearer mi_pat_…" \
-H "Content-Type: application/json" \
-d '{"paid_at": "2026-05-10"}'
76.3 Verzování
- Stabilní cesta:
/api/v1/... - Každá response vrací hlavičku
X-API-Version: 1. - Pokud přidáme nekompatibilní změnu, půjde do
/api/v2/...; v1 zůstane funkční.
76.4 Rate limity
- 600 requestů / minutu / token (defaultně, konfigurovatelně přes
cfg.rate_limits.api_per_min_per_token). - Při překročení vrátíme
429 Too Many Requests+Retry-After: <s>.
Každá bearer-authed response vrací tyto headers, ať si můžeš self-throttle před tím, než narazíš na 429:
X-RateLimit-Limit: 600 (limit v aktuálním okně)
X-RateLimit-Remaining: 587 (kolik volání ti ještě zbývá)
X-RateLimit-Reset: 42 (sekundy do reset countru)
Doporučujeme klienta s retry-with-backoff (axios-retry, Retry-After-aware) + sledovat X-RateLimit-Remaining a brzdit, když klesá pod ~10 %.
76.5 Multi-supplier
Pokud má účet víc firem (dodavatelů), máš dvě možnosti:
| Token bound na supplier_id (doporučeno) | Token globální |
|---|---|
| Token operuje vždy v kontextu této firmy. | Klient pošle hlavičku X-Supplier-Id: <id> u každého requestu. |
Hlavička X-Supplier-Id se ignoruje. | Bez hlavičky = výchozí firma. |
| Token nemůže „skočit“ do jiné firmy = bezpečnější. | Flexibilnější pro power-user skripty. |
76.6 Scopes
| Scope | Povolené metody |
|---|---|
read | GET, HEAD |
read_write | všechny (POST, PUT, PATCH, DELETE) |
Volání s nedostatečným scopem vrátí 403 insufficient_scope.
76.7 Chybové odpovědi
Všechny chyby v unifikovaném formátu:
{ "error": { "code": "validation_failed", "message": "Pole 'name' je povinné." } }
| Kód | Význam |
|---|---|
unauthenticated / invalid_token | Chybí nebo neplatný token |
insufficient_scope | Token nemá read_write |
validation_failed | Tělo neprošlo validací |
not_found | Zdroj neexistuje (nebo nepatří aktuálnímu supplier-ovi) |
rate_limited | Překročen limit (viz Retry-After) |
76.8 Nastavení dodavatele a číslování dokladů přes API
Veřejný subset nastavení dodavatele jde měnit tokenem se scope read_write (uživatel tokenu musí být admin):
PUT /api/v1/settings/supplier— částečný update: fakturační údaje, defaulty, číslování dokladů (invoice_number_format,proforma_number_format,credit_note_number_format,purchase_invoice_number_format,invoice_number_period) a branding (email_branding_enabled,email_accent_color,pdf_logo_show_name,display_name,tagline). Tato pole představují původní nastavení dodavatele, které se používá při vypnutých brandingových profilech. Logo se přes tento endpoint nastavit nedá.
PUT /api/v1/settings/supplier/invoice-counter— nastaví counter číselné řady tak, aby příští vystavený doklad dostal zadané číslo. Hodí se při migraci z jiného fakturačního software (navázání na existující řadu):
curl -X PUT https://mojefirma.example/api/v1/settings/supplier/invoice-counter \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "type": "invoice", "next_number": 42 }'
# → { "type": "invoice", "next_number": 42, "counter": 41,
# "period": "202607", "preview": "2607042" }
Counter jde i snížit; pokud by nové číslo kolidovalo s už vystaveným dokladem, vystavení se samoopravně posune na první volné číslo — duplicitní číslo nikdy nevznikne. Volitelné date (YYYY-MM-DD) určuje období řady (při invoice_number_period = year/month), default je dnešek.
POST /api/v1/settings/supplier/logo— multipart upload loga (polefile; PNG / JPG / SVG / WebP, max 1 MiB). Logo se v e-mailech a PDF ukládá do původního nastavení dodavatele a zobrazuje při zapnutém brandingu.DELETEna stejné cestě logo odebere:
curl -X POST https://mojefirma.example/api/v1/settings/supplier/logo \
-H "Authorization: Bearer $TOKEN" \
-F "file=@logo.png"
# → { "logo_path": "storage/supplier-logos/sup-1.png", "width": 480, "height": 160 }
76.9 Brandingový profil faktury
Po zapnutí modulu brandingových profilů vrací aktivní profily aktuálního dodavatele read-only endpoint:
curl -H "Authorization: Bearer $TOKEN" \
https://mojefirma.example/api/v1/branding-profiles
Hodnotu id lze poslat při vytvoření konceptu faktury:
curl -X POST https://mojefirma.example/api/v1/invoices \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_id": 123,
"branding_profile_id": 5,
"issue_date": "2026-07-20",
"due_date": "2026-08-03",
"items": [{
"description": "Konzultační služby",
"quantity": 1,
"unit": "h",
"unit_price_without_vat": 2500,
"vat_rate_id": 1
}]
}'
Profil musí být aktivní a patřit stejnému dodavateli jako klient. Jinak API vrátí HTTP 400 s kódem integrity_violation. Když branding_profile_id v těle chybí nebo je null, nový koncept převezme výchozí profil klienta a následně výchozí profil dodavatele. Není-li žádný nastaven, použije základní identitu.
Při vystavení se výsledná identita včetně cesty k verzi loga uloží do snapshotu faktury. Pozdější úprava profilu tedy již vystavený doklad nezmění.
76.10 Export faktur přes API
— hromadný export vystavených dokladů za měsíc (nebo period=quarterly&year=YYYY&quarter=1..4). PDF ZIP, ISDOC, Pohoda, Stereo, Money S3 XML nebo CSV; date_by=tax zařazuje dle DUZP (shodně s výkazy DPH). Jde o stejnou logiku jako na obrazovce Export / Import → Export vystavených.
GET /api/v1/invoices/{id}/isdoc— ISDOC XML jedné vystavené faktury (koncept nelze, 400). PDF varianta existovala už dřív (GET /api/v1/invoices/{id}/pdf).
curl -H "Authorization: Bearer $TOKEN" -OJ \
"https://mojefirma.example/api/v1/invoices/export?format=isdoc&month=2026-06"
76.11 Bezpečnost tokenů — best practices
- Ukládej token jako secret (password manager, Make encrypted variable, GitHub Secrets…). Nepushuj do gitu.
- Vyhraď token jedné integraci — pokud aplikaci přestaneš používat, zruš jen tenhle token, ostatní zůstanou funkční.
- Read-only kde to jde — reporting do BI nepotřebuje
read_write. - Bound na supplier_id — minimalizuje radius pádu při kompromitaci.
- Sleduj
last_used_atv UI — token, který se 3 měsíce nepoužil, asi nepotřebuješ. - Při ztrátě/podezření — okamžitě Zrušit v UI. Revokace je instantní (žádný cache).
76.12 Co API nepokrývá
- Admin a settings endpointy (
/api/admin/*a/api/settings/*mimo veřejný subset — supplier, číselníky) nejsou vopenapi.yaml- jsou určené pro interní administraci, integrace na nich stavět nemá smysl. Platí to i pro interní podpisové endpointy, například per-dokladový výběr podpisu (/api/documents/.../signature-selection). - Webhooks zatím nejsou — pokud potřebuješ notifikaci o platbě, použij polling
/api/v1/invoices?status=paid&from=<last_check>. - OAuth2 nepodporujeme — PAT je vědomé zjednodušení pro tenhle typ produktu.
- Idempotency-Key zatím není implementován; pokud Make po retry vytváří duplicitní záznam, otevři issue.