Přes API nahrajete doklady a stáhnete hotový export, aniž byste otevřeli prohlížeč. Hodí se, když už doklady někde sbíráte, třeba v n8n, Make nebo ve vlastní aplikaci, a chcete je posílat rovnou k nám.
API je součástí placených tarifů. Na tarifu zdarma klíč nevydáte. Dříve vydané klíče v seznamu zůstanou a můžete je zneplatnit. Přihlásit se jimi půjde až po návratu na placený tarif.
Vydání klíče
Klíč vydáte v Tým a nastavení v sekci API klíče. Vydat ho může vlastník kanceláře a kolega s právem spravovat tým. Klient klíč vydat nemůže.
Tajnou část klíče uvidíte jen jednou, hned po vytvoření. Uložte si ji do správce hesel nebo rovnou do nastavení své automatizace. Znovu ji nezobrazíme ani my. Když ji ztratíte, klíč zneplatníte a vydáte nový.
Klíč patří jedné kanceláři a nedostane se k dokladům jiné. Zároveň nikdy neumí více než ten, kdo ho vydal: když někomu odeberete oprávnění, jeho klíče o ně přijdou hned, a když ho z kanceláře odstraníte, přestanou fungovat úplně.
Přihlášení
Klíč posílejte v hlavičce:
Authorization: Bearer cf_live_...
Rychlý start
Od souboru k importu do účetnictví to jsou čtyři volání, z toho tři na naše API:
API="https://ctenifaktur.cz/api/v1"
AUTH="Authorization: Bearer cf_live_..."
# 1. Řekněte si o adresu. Vrátí batchId a uploadUrl.
curl -X POST $API/documents \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"files":[{"fileName":"faktura.pdf",
"contentType":"application/pdf","sizeBytes":184320}]}'
# 2. Pošlete bajty. Bez hlaviček, na adresu z kroku 1.
curl -X PUT --data-binary @faktura.pdf "UPLOAD_URL"
# 3. Stav. Opakujte, dokud je status pending nebo processing.
curl $API/batches/BATCH_ID -H "$AUTH"
# 4. Export. Id jsou v uploads[].documentIds.
curl -X POST $API/documents/export \
-H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"documentIds":["DOC_ID"],"format":"pohoda"}' \
-o faktura.xml
Kompletní popis endpointů
Všechny endpointy včetně parametrů, odpovědí a chybových kódů najdete v dokumentaci API. U každého je ukázka volání v curl, JavaScriptu, Pythonu a dalších jazycích a panel, ve kterém požadavek rovnou vyzkoušíte. Ten je ale anglický.
Napojení pro vás dělá někdo, kdo neumí česky? Pošlete mu rovnou anglickou verzi. Je to tatáž dokumentace, jen anglicky.
Pro nástroje je tentýž popis ke stažení strojově:
https://ctenifaktur.cz/api/v1/openapi.json
https://ctenifaktur.cz/api/v1/openapi.json?lang=en
Je to standardní OpenAPI dokument, takže si ho naimportujete do Postmanu nebo Insomnie a máte hotovou kolekci se všemi endpointy. Generátory klientů z něj vyrobí kód ve vašem jazyce. Žádná z adres nevyžaduje klíč, popis si tedy prohlédnete ještě dřív, než API začnete používat.
Pozor na jednu věc: přeložená je dokumentace, ne API samotné. Chybové hlášky v poli message zůstávají české. Programy se ale mají řídit polem code, které je anglické a stabilní.
Nahrání dokladu
Nahrání má jeden endpoint, POST /api/v1/documents, a funguje stejně pro jeden soubor i pro dávku, pro malý sken i pro velký. Dělit velké soubory na části nemusíte, jen se vejděte do 25 MB na soubor.
POST /api/v1/documentspošlete popis souborů (název, typ, velikost). VrátíbatchIda pro každý soubor adresu.- Na tuto adresu pošlete obsah souboru metodou
PUT. Žádné hlavičky nepotřebujete.
Tím to končí. Že soubor dorazil, si všimneme sami a zpracování se rozjede do minuty. Když vám program spadne hned po odeslání souboru, o doklad ani o kredit nepřijdete.
Soubor jde takhle až do 25 MB a jedna dávka pobere až 300 souborů.
Adresa platí 15 minut. Když PUT selže, pošlete ho na tutéž adresu znovu; opakování je pro nás k nerozeznání od pomalého prvního pokusu. Soubor, který se nenahraje vůbec, zhruba po půlhodině zahodíme a kredit vrátíme.
Doklad můžete rovnou zařadit do účetní jednotky, ale nemusíte. Bez ní zůstane nezařazený a přiřadíte ho v aplikaci. Když ho chcete zařadit hned, id jednotky zjistíte z GET /api/v1/accounting-units.
Sledování zpracování
Zpracování běží na pozadí a u jednoho dokladu trvá zpravidla desítky sekund. Stav zjistíte přes GET /api/v1/batches/{id}. Ptejte se opakovaně, dokud je stav pending nebo processing. Konečné stavy jsou tři: completed, completed_with_failures a failed. Kterýkoli z nich znamená konec čekání.
Z jednoho nahraného souboru může vzniknout více dokladů, když v něm rozpoznáme několik faktur pod sebou. Proto odpověď u každého nahrání vrací seznam vzniklých dokladů, ne jeden doklad.
Hotové nahrání přitom ještě neznamená, že z něj vzniklo všechno. Když soubor obsahoval více dokladů, než se stihlo zpracovat nebo vytěžit, přibude u něj pole incomplete s počty: discarded jsou doklady, které jsme v souboru rozpoznali, ale nezpracovali, protože došly kredity nebo soubor přesáhl limit na jedno nahrání, unparsed doklady, ze kterých se nepodařilo nic vytěžit. V documentIds jsou vždy jen doklady, které jdou rovnou do exportu.
Když se část dávky nepovede, zbytek se zpracuje normálně. Dávka pak skončí ve stavu completed_with_failures a neúspěšné položky poznáte podle stavu u konkrétního souboru. Není to důvod posílat celou dávku znovu, hotové doklady se exportují běžným způsobem.
Stažení exportu
POST /api/v1/documents/export vrátí hotový soubor, ne odkaz. Podporuje formáty isdoc, pohoda a money-s3. Pohoda i Money S3 vracejí vždy jedno XML, ISDOC u jednoho dokladu soubor .isdoc a u více dokladů ZIP.
Jeden export musí obsahovat doklady z jedné účetní jednotky. Výsledný soubor totiž nese jedno IČO a smíchané doklady by se do účetního programu naimportovaly špatně. Když pošlete doklady z více jednotek, vrátíme chybu mixed_accounting_units se seznamem, který doklad patří kam, abyste je mohli rozdělit.
Totéž platí pro doklady, které jednotku nemají: musí patřit jedné firmě. Jinak by soubor dostal IČO prvního z nich a zbylé doklady by skončily v účetnictví cizí firmy, takže je odmítneme stejnou chybou. V seznamu je u každého dokladu i jeho IČO, podle kterého je rozdělíte.
Nastavení se bere z účetní jednotky dokladu, ne z požadavku. Export přes API tak vrátí stejný soubor jako stažení z aplikace.
Opakované odeslání
Když spojení selže a vy požadavek zopakujete, může se stát, že první pokus ve skutečnosti prošel. Aby se doklad nezpracoval dvakrát a nestrhly se kredity dvakrát, pošlete u nahrávání hlavičku:
Idempotency-Key: vaše-jedinečné-id
Při opakování použijte stejný klíč. Vrátíme výsledek prvního pokusu místo toho, abychom doklad zpracovali znovu. Nástroje jako n8n a Make opakují požadavky samy, takže tuhle hlavičku doporučujeme používat vždy.
Odpověď vracíme doslova, tedy i s původními adresami pro nahrání. Ty platí 15 minut, takže na opakování během pár minut, kvůli kterému hlavička existuje, to nemá vliv. Když se k požadavku vrátíte až za hodinu, adresy už soubor nepřijmou; založte nahrání znovu s novým klíčem. Kredit z prvního pokusu se vrátí sám.
Časté chyby
| Kód | Co s tím |
|---|---|
plan_required | Kancelář je na tarifu zdarma. API se odemkne po přechodu na placený tarif. |
invalid_key | Klíč je špatně opsaný, zneplatněný nebo jeho tvůrce už do kanceláře nemá přístup. |
insufficient_scope | Klíč nemá potřebné oprávnění, například klíč jen pro čtení nemůže nahrávat. |
insufficient_credits | Došly kredity. Doplňte je a pošlete požadavek znovu. |
mixed_accounting_units | Export míchá doklady z více jednotek, rozdělte ho po jednotkách. |
file_too_large | Soubor je nad 25 MB, takový nezpracujeme. |
rate_limited | Příliš mnoho požadavků. Počkejte podle hlavičky Retry-After. |
Proč se soubor nezpracoval
GET /api/v1/batches/{id} vrací u každého souboru pole uploads[].errorCode. Nejde o chybu požadavku, ale o důvod, proč neprošel jeden konkrétní soubor z dávky. Ostatní soubory běží dál.
| Kód | Co s tím |
|---|---|
upload_not_received | Bajty do úložiště nikdy nedorazily. Kredit jsme vrátili, soubor pošlete znovu. |
source_missing | Nahraný soubor se nepodařilo stáhnout. Pošlete ho znovu. |
source_rejected | Soubor je nad 25 MB nebo neodpovídá tomu, co jste ohlásili. Kredit vracíme, opakovat tentýž soubor nemá smysl. |
processing_failed | Vytěžení selhalo. Zkuste to znovu, a pokud selže i podruhé, napište nám. |