Přeskočit na hlavní obsah

Zálohové faktury a jejich odečtení

Zálohová faktura je výzva k zaplacení předem, ne daňový doklad. V API se chová jinak než ostatní doklady: nemá datum zdanitelného plnění, nezaúčtovává se a z konečné faktury se odečítá polem, jehož tvar v odpovědi neodpovídá tvaru v požadavku.

Zálohová faktura není daňový doklad​

Zálohová faktura sama o sobě nezakládá povinnost přiznat DPH ani nárok na odpočet. Vytištěné PDF to říká přímo – nese větu Zálohová faktura neslouží jako daňový doklad!

Z toho plyne, jak vypadá zdroj v API:

  • Nemá date_vat ani date_vat_prev. Datum zdanitelného plnění na zálohu nepatří, obě pole na tomhle zdroji neexistují.
  • Nemá /account ani accounted. Zálohová faktura se do účetního deníku nezapisuje. Do účetnictví se dostane až přijatá platba, která ji hradí – ta zaúčtování má, viz Platby přijaté.
  • Má dvě částky navíc. to_be_paid říká, kolik na záloze zbývá uhradit; to_be_invoiced, kolik zbývá odečíst na konečné faktuře.

Zdroje jsou dva: Zálohové faktury vydané a Zálohové faktury přijaté. Endpoint pro úhradu má jen ten vydaný.

Celý průběh v jednom příkladu​

Scénář má tři kroky: vystavíte zálohu, zaevidujete její úhradu a pak vystavíte konečnou fakturu, na které se záloha odečte.

Ukázková čísla

ID, čísla dokladů a částky jsou vymyšlené. Endpointy, názvy polí a tvar odpovědí odpovídají referenci.

1. Vystavte zálohovou fakturu​

curl -s -X POST https://online.iucto.cz/api/1.3/proforma_invoice_issued \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $IUCTO_API_KEY" \
-d '{
"customer_id": 785,
"date": "2026-08-13",
"maturity_date": "2026-08-27",
"currency": "CZK",
"payment_type": "transfer",
"bank_account": 456,
"items": [
{
"text": "Záloha na dodávku podle smlouvy 2026/114",
"amount": 1,
"price": 10000,
"vat": 21
}
]
}'

Povinná pole jsou customer_id, date, maturity_date, currency, payment_type a alespoň jedna položka; položka potřebuje text, amount, price a vat. Odpověď 201 vrací detail dokladu:

{
"_links": { "self": { "href": "/1.3/proforma_invoice_issued/4001" } },
"id": 4001,
"sequence_code": "ZF20260014",
"date": "2026-08-13",
"maturity_date": "2026-08-27",
"currency": "CZK",
"price": 10000.0,
"price_inc_vat": 12100.0,
"to_be_paid": 12100.0,
"to_be_invoiced": 12100.0,
"deleted": false
}

2. Zaevidujte úhradu zálohy​

curl -s -X PUT https://online.iucto.cz/api/1.3/proforma_invoice_issued/4001/pay \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $IUCTO_API_KEY" \
-d '{ "date": "2026-08-20", "bank_account": 456 }'

Odpověď 200 není detail zálohy, ale detail nově vzniklé platby přijaté:

{
"_links": { "self": { "href": "/1.3/payment_received/9120" } },
"id": 9120,
"sequence_code": "BP20260233",
"proforma_invoice_id": "4001",
"invoice": null,
"date": "2026-08-20",
"date_vat": "2026-08-20",
"currency": "CZK",
"price": 10000.0,
"price_inc_vat": 12100.0,
"payment_type": "transfer"
}

Po tomhle volání má záloha to_be_paid nula. Odkaz na platbu si uložte – budete ho potřebovat, kdyby se záloha měla rušit.

proforma_invoice_id je řetězec

V odpovědi se vrací jako "4001", ne jako číslo. Parser, který na tomhle poli očekává integer, spadne.

3. Vystavte konečnou fakturu s odečtem​

curl -s -X POST https://online.iucto.cz/api/1.3/invoice_issued \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $IUCTO_API_KEY" \
-d '{
"customer_id": 785,
"date": "2026-09-01",
"date_vat": "2026-09-01",
"maturity_date": "2026-09-15",
"currency": "CZK",
"payment_type": "transfer",
"bank_account": 456,
"proforma_invoice": [4001],
"items": [
{
"text": "Dodávka podle smlouvy 2026/114",
"amount": 1,
"price": 10000,
"vat": 21,
"accountentrytype_id": 7,
"vattype_id": 1
},
{
"text": "Uhrazeno zálohou ZF20260014",
"amount": 1,
"price": -10000,
"vat": 21,
"accountentrytype_id": 126,
"vattype_id": 1
}
]
}'

Všimněte si, že odečet jsou dvě různé věci: pole proforma_invoice s ID zálohy a záporná položka s částkou. Proč, vysvětluje následující sekce.

Pravidla akce /pay​

PUT /proforma_invoice_issued/{id}/pay je jediná akce /pay v celém API. Ostatní doklady se hradí tak, že k nim založíte platbu; u zálohové faktury existuje tahle zkratka navíc.

Platí pro ni:

  • Vytváří vždy plnou úhradu. Částka se v požadavku zadat nedá – platba vznikne na to, co ze zálohy zbývá uhradit (to_be_paid).
  • Vrací detail platby přijaté, ne detail zálohy. Tvar odpovídá GET /payment_received/{id}.
  • date je povinné a musí spadat do otevřeného účetního období.
  • bank_account a cash_register se vylučují. Poslat lze nejvýš jeden. Když nepošlete ani jeden, použije se bankovní účet z dokladu – to ale jde jen u dokladů s payment_type transfer nebo creditcard, které účet vyplněný mají. Jinak přijde 400 s hláškou Vyberte pokladnu, nebo bankovní účet pro platbu.
  • Měna platby se bere z vybraného účtu nebo pokladny, ne z dokladu.
  • Už uhrazenou zálohu odmítne hláškou Záloha je již uhrazena.

Částečná úhrada​

Částečnou úhradu přes /pay zadat nelze. Založte platbu přímo a navažte ji na zálohu polem proforma_invoice_id:

curl -s -X POST https://online.iucto.cz/api/1.3/payment_received \
-H "Content-Type: application/json" \
-H "X-Auth-Key: $IUCTO_API_KEY" \
-d '{
"customer_id": 785,
"proforma_invoice_id": 4001,
"date": "2026-08-20",
"payment_type": "transfer",
"bank_account": 456,
"items": [
{ "text": "Částečná úhrada zálohy ZF20260014", "amount": 1,
"price": 5000, "vat": 21, "accountentrytype_id": 189, "vattype_id": 1 }
]
}'

Platba se páruje nejvýš na jeden doklad – proforma_invoice_id, invoice_id a creditnote_received_id se nedají kombinovat.

Odečtení zálohy na faktuře vydané​

Zálohu odečtete tak, že při vytváření nebo editaci faktury vydané pošlete její ID v poli proforma_invoice (od verze API 1.2). Pole je součástí parametrů faktury vydané a přijímá pole ID, tedy i víc záloh najednou.

Samotné pole ale žádnou částku neodečte. Vytvoří jen vazbu mezi fakturou a zálohou. Součet faktury se počítá z jejích položek, takže odečet musí být na faktuře jako samostatná položka se zápornou cenou – přesně jako v kroku 3 výše.

Jak takovou položku sestavit:

Pole položkyHodnota
pricezáporná, ve výši odečítané zálohy
vat, vattype_idstejné jako na záloze
accountentrytype_idtyp účetní položky pro odečet zálohy
textlibovolný popis, typicky s číslem zálohy

ID typů účetních položek jsou pro každou firmu jiná – načtěte si je dotazem GET /accountentry_type?doctype=FV a vyberte položku pro přijaté zálohy. Jinak se zaúčtování řídí stejnými pravidly jako u každé jiné položky, viz Zaúčtování položek.

to_be_invoiced se odečtem přes API nesníží

Hodnota to_be_invoiced na záloze se počítá z položek faktury, které nesou vnitřní odkaz na konkrétní zálohu. Tenhle odkaz se přes API nastavit nedá – položky mají jen pole vyjmenovaná v referenci. Kolik ze zálohy zbývá odečíst, si proto musí integrace hlídat sama.

Past: proforma_invoice se čte jinak, než se zapisuje​

Pole proforma_invoice má v odpovědi jiný tvar než v požadavku. Je to jediné místo, kde se dá bez varování poslat zpátky přesně to, co server vrátil, a skončit chybou.

SměrTvar
GET (odpověď)pole objektů – [{ "id": 4001 }]
POST / PUT (požadavek)pole holých čísel – [4001]

Kdo si detail faktury stáhne, změní jednu položku a pošle celý objekt zpět na PUT, narazí. Validace každý prvek pole přetypuje na celé číslo, takže z objektu {"id": 4001} vznikne 1:

{ "errors": { "proforma_invoice": "Neplatné ID zálohové faktury vydané '1'" } }

Odpověď je 400. Tvary chybových těl a jak je rozlišit popisuje Chyby a jak je číst.

Řešení je jednoduché – před zápisem pole převeďte:

$invoice['proforma_invoice'] = array_column($detail['proforma_invoice'], 'id');

Smazání zálohové faktury​

DELETE /proforma_invoice_issued/{id} selže, jakmile je na záloze navázaný jiný záznam. Odpověď je 403 s hláškou Nelze smazat záznam. Vazbu vytvoří dvě věci:

  • úhrada – platba přijatá s proforma_invoice_id mířícím na zálohu, ať už vznikla přes /pay nebo přímo,
  • odečet – faktura vydaná, která má zálohu v poli proforma_invoice.

Pořadí kroků při rušení je tedy opačné než při vystavování: nejdřív odeberte zálohu z faktury (PUT na fakturu bez jejího ID v proforma_invoice), pak smažte platbu a teprve nakonec zálohu.

Druhá příčina 403 je uzavřené období – hláška je pak jiná (Doklad je smazaný, nebo účetní období, či období DPH je uzavřeno.), viz Uzavřené období.

Záloha na faktuře přijaté​

Na přijaté straně to funguje stejně jako na vydané. POST /invoice_received i PUT /invoice_received/{id} přijmou proforma_invoice jako pole ID zálohových faktur přijatých (od verze API 1.2) a v odpovědi se pole vrací jako pole objektů – stejná asymetrie tvarů jako u faktury vydané.

Kam dál​