{"name":"Saldo – TechTools účetnictví API","version":"1.1","description":"Czech bookkeeping for s.r.o. and OSVČ: invoices, bank matching, double-entry ledger or daňová evidence, VAT return + kontrolní hlášení + souhrnné hlášení with EPO XML, income tax (DPFO/DPPO), OSVČ insurance, income tax returns (DPFO/DPPO) as EPO XML, OSVČ insurance, payroll, travel allowances and depreciation, plus shared invoice links, attachments, quotes and orders, Fio bank feeds and insolvency checks. Public calculators need no account; bookkeeping endpoints need a personal API key or the TechTools session cookie.","base_url":"https://techtools.cz/ucetnictvi-api","ui":"https://techtools.cz/tools/ucetnictvi/","conventions":{"money":"JSON numbers in the document currency, 2 decimals; *_czk fields are converted with the document exchange rate","dates":"ISO 8601 (YYYY-MM-DD)","errors":"{ \"error\": \"human readable message (Czech)\" } with 400/401/403/404/422","auth":"Agents: create a key in Saldo → Nastavení → API a integrace and send it as \"X-API-Key: saldo_…\" or \"Authorization: Bearer saldo_…\". A key acts with its owner's rights in every firm they belong to; read-only keys refuse every non-GET request (403 READ_ONLY_KEY). Browsers: the session cookie (_techtools_session, fetch credentials: \"include\").","csrf":"Every non-GET request that carries the session cookie must also send \"X-Saldo: 1\"; cross-site requests (Origin or Sec-Fetch-Site from another site) are refused with 403 CROSS_SITE. Requests without cookies (API keys, curl to the public calculators) need no extra header.","rate_limits":"API keys: 600 requests per minute (429 RATE_LIMITED). Calculators are CPU-only and stateless; inputs are bounded (numbers ≤ 15 digits, dates 2000–2100)"},"public_endpoints":{"docs":{"method":"GET","path":"/docs"},"rates":{"method":"GET","path":"/rates?year=2026","returns":"every statutory constant used by the engines, with source URLs"},"holidays":{"method":"GET","path":"/holidays?year=2026","returns":"Czech public holidays (deadline shifting per § 33 daňového řádu)"},"deadlines":{"method":"GET","path":"/deadlines?year=2026\u0026legal_form=osvc\u0026vat=quarterly\u0026employees=true","params":{"legal_form":"osvc|sro|as","vat":"none|monthly|quarterly|identified","employees":"bool","advisor":"bool","databox":"bool","flat_tax":"bool","recap_statement":"bool","real_estate":"bool","road_tax":"bool"},"returns":"{ events: [{ date, title, detail, category, basis }] } — every tax and insurance deadline, shifted to business days"},"codebooks":{"method":"GET","path":"/codebooks","returns":"document kinds, VAT modes, account kinds, insurers, EU countries, RC codes, tax offices…"},"qr_platba":{"method":"GET","path":"/qr?iban=CZ6508000000192000145399\u0026amount=1210\u0026vs=20260001\u0026message=Faktura","returns":"{ spayd: \"SPD*1.0*ACC:…\" } — the Czech QR Platba string (render it as a QR code)"},"shared_document":{"method":"GET","path":"/share/:token","returns":"public view of a shared invoice (JSON: document, entity, bank_account, spayd); GET /share/:token/isdoc downloads its ISDOC. The page is /tools/ucetnictvi/faktura/#\u003ctoken\u003e"},"isdoc_parse":{"method":"POST","path":"/isdoc/parse","body":"multipart field file (.isdoc/.isdocx, or a PDF with embedded ISDOC) or the raw XML as the request body","returns":"normalized invoice: parties, lines, VAT recap, payment details","example":"curl -F file=@faktura.isdoc https://techtools.cz/ucetnictvi-api/isdoc/parse"},"calculators":{"method":"POST","path":"/calc/:calculator","body":"JSON object (Content-Type: application/json) or form fields","available":{"vat":{"input":{"net":1000,"rate":21},"alt":{"gross":1210,"rate":21}},"osvc":{"input":{"year":2026,"income":900000,"flat_rate":60,"children":[{"order":1}],"spouse":false},"returns":"DPFO tax, credits, child bonus, social and health insurance, advances for next year"},"regime":{"input":{"year":2026,"income":900000,"expenses":250000},"returns":"ranked comparison of actual expenses vs výdajové paušály vs paušální daň with the recommendation"},"flat_tax":{"input":{"year":2026,"income":1400000,"income_kind":"services","vat_payer":false}},"corporate":{"input":{"year":2026,"accounting_profit":1250000,"non_deductible":[{"label":"Reprezentace","amount":18000}]}},"payroll":{"input":{"year":2026,"month":9,"contract":"hpp","gross":52000,"children":[{"order":1}]},"returns":"payslip: insurance both sides, tax advance, credits, net pay, employer cost, postings"},"travel":{"input":{"destination":"Brno","departure":"2026-09-21T06:30","arrival":"2026-09-21T19:10","km":420,"vehicle_kind":"car","consumption":6.1,"fuel":"diesel"}},"depreciation":{"input":{"price":850000,"group":2,"method":"straight","start_year":2026}},"late_interest":{"input":{"principal":48400,"due_date":"2026-05-15","paid_on":"2026-09-26"}}},"example":"curl -X POST -H 'Content-Type: application/json' -d '{\"year\":2026,\"income\":900000,\"flat_rate\":60}' https://techtools.cz/ucetnictvi-api/calc/osvc"}},"account_endpoints":{"entities":{"list":"GET /entities","create":"POST /entities { entity: {...}, bank: {...} }","demo":"POST /entities/demo?variant=sro|osvc","show":"GET /entities/:id","update":"PATCH /entities/:id","lock_period":"POST /entities/:id/lock { locked_until }","export":"GET /entities/:id/export (full JSON backup)"},"onboarding":"GET /lookup/:ico (company from ARES + RES + registr plátců DPH with a suggested profile: segment, legal form, bookkeeping, VAT status, tax office, NACE, výdajový paušál; 200 {found:false} when unknown, 502 when ARES is down), GET /lookup/banks, POST /entities with settings.profile {segment, osvc_activity, employees, foreign[], cash, assets, travel, projects, advances, commercial, keeper} and settings.modules {advances, cash, commercial, internal, payroll, assets, trips, projects, closing, multi_currency, forecast} (a missing module key means on)","getting_started":"GET /entities/:entity_id/getting_started, POST …/getting_started/dismiss { key } or { all: true }, DELETE …/getting_started (show the first steps again)","members":"GET|POST /entities/:entity_id/members { login: username or account e-mail (case-insensitive), role: accountant|editor|viewer } creates a pending invitation; DELETE …/members/:id (leave or remove)","invitations":"GET /invitations, POST /invitations/:id/accept, DELETE /invitations/:id (decline)","api_keys":"GET|POST /api_keys { name, read_only }, DELETE /api_keys/:id — browser session only; the token is returned once","accounts":"GET|POST|PATCH|DELETE /entities/:entity_id/accounts","partners":"GET|POST|PATCH|DELETE /entities/:entity_id/partners, GET …/partners/lookup?ico= (ARES; 200 {found:false} when unknown)","documents":{"list":"GET /entities/:entity_id/documents?kind=invoice_out\u0026state=unpaid|overdue|paid\u0026q=\u0026year=","template":"GET …/documents/template?kind=invoice_out","create":"POST …/documents { document: { kind, partner_id, issue_date, lines_attributes: [...] }, issue: true }","actions":"POST …/documents/:id/issue|cancel|reopen|remind, GET …/duplicate|credit_note|final_invoice|advance_document|reminder|qr|isdoc","commercial":"kinds quote_out (nabídka), order_out (objednávka), delivery_out (dodací list) are never posted; GET …/documents/:id/convert?kind=invoice_out|proforma_out|delivery_out|invoice_in returns a draft, POST …/documents/:id/outcome { outcome: accepted|rejected }","share":"POST …/documents/:id/share returns { token } for the public page, DELETE …/documents/:id/share revokes it","attachments":"GET|POST …/documents/:id/attachments (multipart file: PDF, JPG, PNG, WebP, HEIC, XML; ≤ 15 MB), GET|DELETE …/documents/:id/attachments/:attachment_id","payments":"POST …/documents/:id/payments { amount, paid_on, bank_account_id }, DELETE …/payments/:payment_id","import_isdoc":"POST …/documents/import_isdoc (multipart files[])","accountant_export":"GET …/documents/export?format=pohoda|money\u0026from=\u0026to=\u0026kinds[]=\u0026ids[]= (POHODA XML in Windows-1250 or Money S3 XML, period by DUZP / deduction date; 422 { error, problems[] })","payment_order":"GET …/documents/payables (unpaid received invoices with the payee account or the reason they cannot be paid), POST …/documents/payment_order { ids[], bank_account_id, format: auto|abo|sepa, execution_date } → ABO (.kpc, CZK) or SEPA pain.001 (EUR); the order never marks invoices as paid"},"bank":"GET …/bank_accounts, GET …/bank_transactions, POST …/bank_transactions/import (multipart file ≤ 5 MB, bank_account_id, optional statement_pdf ≤ 15 MB and period_month YYYY-MM (required with PDF or a data file without dated movements); stores the original data file and PDF with the import batch; reimport skips duplicate movements), GET …/bank_transactions/statements, GET …/bank_transactions/statements/:archive_id/data|pdf (authenticated original downloads), POST …/bank_transactions/auto_match, POST …/bank_transactions/:id/match|book|ignore|reset, POST …/bank_accounts/:id/connect { token } (Fio API, owner/accountant), POST …/bank_accounts/:id/sync","partners_checks":"GET …/partners/:id/vat_registry, POST …/partners/vat_registry_all (MFČR registr plátců DPH), POST …/partners/:id/insolvency, POST …/partners/insolvency_all (ISIR, 15 per call)","ledger":"GET …/entries?year=\u0026account=\u0026q=\u0026document_id=\u0026source_type=manual,opening\u0026page=\u0026per= (deník, per ≤ 1000), POST …/entries (ruční zápis), DELETE …/entries/:id","reports":"GET …/reports/dashboard|trial_balance|account?code=|saldokonto?side=|statements?year=|cash_book|money|compliance|forecast?days=90|projects?dimension=project|cost_center|insights?year= (Kolik je opravdu vaše, monthly set-aside, runway, Finanční zdraví)","clients":"GET /clients – all firms you are an accepted member of: VAT filing state and next deadline, overdue receivables, unmatched bank movements, drafts, period lock, last activity; most urgent first; max 200","taxes":"GET …/taxes/vat_return|control_statement|recap_statement?period=2026-09, GET …/taxes/dph|kh|sh/xml?period=, GET …/taxes/income_tax|regime?year=, GET …/taxes/income_tax/xml?year=2025 (DPFDP7 for OSVČ, DPPDP9 for companies), POST …/taxes/:report/epo?check=true (validate on mojedane.gov.cz) or without check (opens the pre-filled EPO form), GET …/taxes/filings_check?year= (readiness of the income-tax return and both přehledy: problems, warnings, deadlines, recipients), GET …/taxes/prehled_sp|prehled_zp/xml?year= (přehled OSVČ for ČSSZ, OSVC25, and for the health insurer, SZP-VZP v6), POST …/taxes/prehled_sp/validate?year= (ČSSZ pre-validation, nothing is filed), POST …/taxes/income_tax|prehled_sp|prehled_zp/filing?year= (stores the prepared filing), GET …/taxes/payments?from=2026-08\u0026to=2026-11 (payments due to the FÚ, ČSSZ and health insurers: account, IBAN, VS/KS/SS, due date moved to a business day, SPAYD for QR Platba, paid status from bank movements, missing data and where to find it; max 24 months)","filings":"GET|POST …/filings, GET|PATCH|DELETE …/filings/:id (filed = označeno jako odeslané, ne doložené doručení), GET|POST …/filings/:filing_id/evidences (originální PDF/XML/ZFO do 15 MB), GET …/filings/:filing_id/evidences/:id/file (stažení originálu), POST …/filings/:filing_id/evidences/:id/verify|void|correct (ověření, vyřazení nebo auditovaná oprava), POST|DELETE …/filings/:id/exception (výslovné schválení bez doručenky a jeho zrušení)","closing":"GET …/closing/month?year=\u0026month= (měsíční uzávěrka checklist), GET …/closing?year= (roční uzávěrka: checklist, preview of kurzové rozdíly, corporate income tax), POST|DELETE …/closing/revaluation?year= (563/663 at the ČNB rate of the balance date, invoices reversed on 1. 1.), POST|DELETE …/closing/income_tax?year= (591/341)","assets":"GET|POST|PATCH|DELETE …/assets, POST …/assets/depreciate?year=","payroll":"GET|POST|PATCH|DELETE …/employees, GET …/payslips?year=\u0026month=, POST …/payslips/generate, POST …/payslips/:id/post_entries, GET …/payslips/jmhz?year=\u0026month= (JMHZ check, totals, deadline, filings), GET …/payslips/jmhz/xml?year=\u0026month=\u0026kind=regular|corrective|cancellation (JMHZ XML 1.4.3.6, stored as a filing), POST …/payslips/jmhz/validation (ČSSZ pre-check, nothing is filed)","trips":"GET|POST|PATCH|DELETE …/trips, POST …/trips/calculate","recurring":"GET|POST|PATCH|DELETE …/recurrences, POST …/recurrences/run","autofill":"GET …/documents/items?q=\u0026kind= (line items used before: description, unit, price, VAT rate, account), GET …/documents/partner_defaults?partner_id=\u0026kind= (due days, account, VAT mode and lines from the partner's last document), GET …/documents/duplicates?kind=invoice_in\u0026partner_id=\u0026original_number=\u0026issue_date=\u0026total=\u0026currency= ({ duplicate_of } when the same received document is already booked)","bulk":"POST …/documents/bulk { operation: issue|pay|remind|delete, ids[], paid_on, bank_account_id }, GET …/documents/reminders?ids= (overdue invoices ready for a reminder with the late-payment interest)","bank_rules":"GET|POST …/bank_rules { bank_rule: { name, active, action: post|match|partner|ignore, conditions: { direction: in|out, bank_account_id, counterparty_account, counterparty_name, message|variable_symbol|constant_symbol|specific_symbol: { op: contains|equals, value }, amount_min, amount_max }, action_data: { account_code, text, partner_id } }, apply: true }, PATCH|DELETE …/bank_rules/:id, POST …/bank_rules/preview (movements the rule would take), POST …/bank_rules/apply { rule_id, transaction_ids[] }, GET …/bank_rules/draft?transaction_id= (a rule proposed from one movement, incl. the official tax office and insurer accounts), GET …/bank_rules/suggestions (repeated movements without a rule), POST …/bank_rules/reorder { ids[] }; the first matching active rule wins","imports":"GET …/imports (history of imports with counts, bookkeeping mode, opening date, money accounts), POST …/imports/preview (multipart: type contacts|documents|trial_balance|open_items|money, file ≤ 20 MB, mapping and options as JSON; nothing is saved; row status create|duplicate|skip|error), POST …/imports (same fields plus batch IMP-XXXXXX, offset, limit; imports one chunk, returns rows created|duplicate|skipped|error and next_offset, null when done), DELETE …/imports/:batch (undo; refused when the period is locked or later payments depend on it). Contacts come from any CSV, POHODA XML adresář or Money S3 firmy, documents from POHODA XML invoices, trial_balance from a předvaha CSV (MD must equal Dal), open_items and money for daňová evidence","automation":"GET …/automation (switches and what each automation did this month), PATCH …/automation { automation: { bank_rules, auto_match, fio_on_open, recurring, reminders, reminder_days: 1–90, partner_checks } } (owner or accountant), POST …/automation/run { only, force } (issues due recurring invoices and checks new contacts in ARES, ISIR and the VAT registry; safe to repeat)","calendar":"GET …/calendar?year= (JSON) or ?format=ics","audit":"GET …/events"},"disclaimer":"Výpočty vycházejí ze zákonů platných pro daný rok a ze zadaných dat. Nejsou daňovým poradenstvím; před podáním si výsledky zkontrolujte."}