Vystavení dokladu
/api/v2/sync/invoicesOperace je určená pro systémy mimo pokladnu, například e-shop nebo rezervační systém: doklad vystaví server a vrátí ho celý zpátky. Jeden požadavek nese 1 až 100 dokladů. Každý se zpracuje samostatně a buď se zapíše celý, nebo vůbec.
Pole options.response musí mít hodnotu documents. Bez ní běží interní režim, který používá pokladna, a ten vrací jen pole successInvoices bez dat dokladu. Odpověď v režimu documents poznáte podle pole documents.
Číslo dokladu a variabilní symbol
Číslo neposílejte. Server přidělí další číslo v řadě skladu vystavení, dopočítá numberFormated podle prefixu a počtu číslic v tiskové sestavě a nastaví variable. Přidělování probíhá pod zámkem, takže souběžné požadavky nedostanou stejné číslo.
Variabilní symbol má vždy 1 až 10 číslic. Když ho nepošlete, použije se numberFormated. Tisková sestava skladu proto potřebuje číselný prefix, například [ROK] a 6 číslic, což dá 2026000042. Prefix s písmeny nebo číslo delší než 10 znaků doklad odmítne s kódem variable-invalid.
Opakované odeslání
Pole hash je povinné a v rámci firmy jedinečné. Když doklad se stejným hash už existuje, nový nevznikne, sklad se znovu neodepíše a odpověď vrátí existující doklad s duplicate: true.
Po výpadku spojení nebo vypršení časového limitu proto pošlete stejný požadavek znovu se stejným hash. Dokud nemáte odpověď, nový hash negenerujte.
Sklady a nastavení
Pro každý prodejní kanál (pokladna na místě, e-shop) doporučujeme samostatný sklad s vlastní tiskovou sestavou. Sklad určuje číselnou řadu, prefix, bankovní účet, nastavení EET i uzávěrku a doklady se započítají do uzávěrky svého skladu.
- Do skladu, do kterého vystavuje API, nevystavujte zároveň z pokladny v prohlížeči, jinak se čísla z obou zdrojů mohou překrývat.
- Dva sklady nesmí mít tiskovou sestavu se stejným prefixem, jinak by vznikla dvě stejná čísla dokladu.
- Uživatel, kterému patří API token, musí mít přístup do všech skladů, do kterých vystavuje.
Položky a ceny
Ceny dokladu počítá váš systém, server je nepřepočítává. Kódy měny (prices.currency) a sazeb DPH (vat.code) musí existovat v číselnících firmy, jinak se doklad odmítne s kódem validation.
Položka bez id produktu je volná položka, například vstupenka nebo voucher. Neodepisuje sklad a do pole code můžete uložit vlastní kód. V odpovědi se vrací id položky a code, takže si můžete uložit vazbu kód → doklad → položka. Pro jednoznačné dohledání posílejte každý kód jako samostatnou položku s count: 1.
Odběratel
Pole contact |
Co server udělá |
|---|---|
{"id": 123} |
Použije existující kontakt firmy. |
externalId a údaje |
Hledá kontakt podle externalId (vaše ID zákazníka), pak podle IČ. |
ic a údaje bez externalId |
Hledá kontakt podle IČ, při více shodách nejnovější. |
| nic nenalezeno | Založí nový kontakt v adresáři. |
Údaje odběratele: companyName, name, surname, ic, dic, street, town, zip, country, email, phone. Musí obsahovat aspoň companyName nebo jméno. IČ u country CZ (výchozí) má 8 číslic.
Nalezený kontakt se přepíše na poslané údaje. Výsledek najdete v contactId a contactAction: created (založen), updated (údaje se změnily), matched (beze změny). Fyzická osoba bez IČ a bez externalId se zakládá vždy nově.
Doklad nad 10 000 Kč včetně DPH musí mít odběratele, jinak se odmítne s kódem customer-required. Pokud potřebujete podobu odběratele v okamžiku prodeje, zapněte modul Archiv dokladů (PDF/A), viz Archiv dokladu.
EET a uhrazenost
O EET se stará pokladna podle tiskové sestavy skladu vystavení, kód POK ani údaje EET neposílejte. Výsledek je v eet.status:
none: doklad se do EET neeviduje,registered: evidován, kód veet.pok,pending: EET je nedostupné. Doklad je platný a pokladna ho doeviduje později.
Uhrazenost nastavíte polem paid. Bez něj je doklad placený hotově nebo kartou uhrazený a ostatní neuhrazené. Hotovostní platba nad 270 000 Kč se odmítne s kódem cash-limit.
HTML dokladu
S options.html: true obsahuje html samostatný dokument se styly, logem a QR kódem uvnitř, bez odkazů na jiné adresy. Můžete ho vytisknout nebo převést do PDF. Účtenka (cash) má šířku 58 nebo 80 mm podle tiskárny v tiskové sestavě skladu uživatele, kterému patří API token (bez tiskárny 80 mm). Šířka je v paperWidth, v požadavku se nenastavuje. Faktura (invoice) formát A4 nebo vlastní tiskovou šablonu firmy. U jiných typů je html null a důvod je v htmlError.
htmlSha256 je otisk SHA-256 vráceného HTML. S logem firmy může mít HTML stovky kB. Server HTML neukládá, každé volání ho vytvoří znovu podle aktuálních údajů dokladu a firmy. Opakované odeslání se stejným hash proto může vrátit jiné HTML, například po změně loga. Stejné HTML vrátí kdykoli později i operace HTML dokladu.
Archiv dokladu
Archiv zapíná modul 10224 Archiv dokladů (PDF/A) uživatele, kterému patří API token. V požadavku se nic nenastavuje, starší volba options.archive se ignoruje. S modulem vznikne u každého dokladu na pozadí archivní PDF/A, obvykle do dvou minut. Bez modulu se doklad vystaví normálně, jen bez archivu.
Stav je v archive:
status:none(archiv nevzniká),pending(PDF se vytváří),done(hotovo),failed(PDF se nepodařilo vytvořit, doklad je platný),fileId: ID přílohy s archivním PDF, dokud není hotové,null,pdfSha256: otisk SHA-256 archivního PDF,error: důvod u stavufailed.
Archivní PDF stáhnete operací Archiv dokladu.
Odpověď a chyby
Odpověď má HTTP 200 i tehdy, když se některé doklady nezpracovaly. Ty najdete ve failedInvoices s pořadím v požadavku (index), hash, strojovým kódem code a popisem message:
| Kód | Význam |
|---|---|
validation |
Chybí nebo je neplatné pole dokladu, neznámý kód měny nebo sazby DPH. Název pole je v message. |
hash-required |
Chybí hash. |
stock-not-allowed |
Sklad vystavení neexistuje, je smazaný, nebo do něj uživatel nemá přístup. |
numbering-failed |
Sklad nemá tiskovou sestavu nebo číslo nejde přidělit. |
variable-invalid |
Variabilní symbol nemá 1 až 10 číslic, nebo tisková sestava má nečíselný prefix. |
customer-required |
Doklad nad 10 000 Kč včetně DPH bez odběratele. |
contact-invalid |
Neplatné údaje odběratele, například IČ nebo e-mail. |
cash-limit |
Hotovostní platba nad 270 000 Kč. |
author-not-found, company-mismatch |
Neplatný autor dokladu (author.id). Pole neposílejte, autorem je uživatel tokenu. |
internal |
Neočekávaná chyba. Doklad se nezapsal, můžete ho poslat znovu se stejným hash. |
Data a časy v documents (issued, eet.registered) mají formát ISO 8601 s časovou zónou, například 2026-11-06T16:28:00+01:00.
Doklad odmítnutý ve failedInvoices se nezapíše. Po opravě ho můžete poslat znovu se stejným hash.
Autentizace a oprávnění
Vyžaduje API token: Bearer v hlavičce nebo URL token.
Parametry
Tělo požadavku
| Název | Typ | Povinný | Popis | Příklad |
|---|---|---|---|---|
options.response | enum | ano | Vždy documents. Bez této hodnoty běží interní režim pokladny, který tu nepopisujeme a který vrací jen potvrzení bez dat dokladu. | documents |
options.html | boolean | ne | true vrátí u každého dokladu samostatný HTML dokument k tisku nebo převodu do PDF. Výchozí false. | 1 |
invoices | array | ano | Doklady k vystavení, nejvýše 100 v jednom požadavku. Každý se zpracuje samostatně. | [{...}] |
invoices[].hash | string | ano | Vaše jedinečné ID dokladu, nejvýše 64 znaků, např. ID objednávky nebo UUID. Podle něj server pozná opakované odeslání. | hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11 |
invoices[].issuingStock.id | integer | ne | Sklad vystavení. Určuje tiskovou sestavu, číselnou řadu, bankovní účet, EET a uzávěrku. Uživatel tokenu musí mít do skladu přístup. Bez hodnoty platí aktivní sklad uživatele. | 12 |
invoices[].type | enum | ano | Typ dokladu: cash (účtenka) nebo invoice (faktura). Další typy dokladů z pokladny server přijme, HTML pro ně ale nevrací. | cash |
invoices[].payment | enum | ano | Způsob platby: cash (hotově), card (kartou nebo platební bránou), bank (převodem). | card |
invoices[].paid | boolean | ne | Uhrazenost dokladu. Výchozí true pro cash a card, jinak false. | 1 |
invoices[].issued | datetime | ne | Datum a čas vystavení. Bez časové zóny se bere jako čas v Praze. Výchozí je okamžik přijetí. | 2026-11-06 16:28:00 |
invoices[].taxable | date | ne | Datum zdanitelného plnění (DUZP). Výchozí je den vystavení. | 2026-11-06 |
invoices[].due | date | ne | Datum splatnosti. Výchozí je den vystavení. | 2026-11-20 |
invoices[].variable | string | ne | Variabilní symbol, 1 až 10 číslic. Bez hodnoty se použije číslo dokladu. U QR platby pošlete variableSymbol z QR platby. | 2026000042 |
invoices[].number | integer | ne | Neposílejte. Číslo přidělí server jako další v řadě skladu vystavení. | null |
invoices[].text | string | ne | Poznámka na dokladu. | Objednávka 2026-1187 |
invoices[].transactionInfo | object | ne | Údaje z platebního terminálu ve stejném tvaru jako z pokladny. Vytisknou se na účtence. | {"card":{"type":"VISA","last4Digits":"4603"},"transactionCode":"AUTH42"} |
invoices[].items | array | ano | Položky dokladu, aspoň jedna. | [{...}] |
invoices[].items[].name | string | ano | Název položky. U produktu z katalogu (items[].id) se může vynechat. | Vstupné dospělý |
invoices[].items[].code | string | ne | Váš kód položky, nejvýše 500 znaků, např. kód vstupenky nebo voucheru. Vrací se v odpovědi u položky. | TKT-8F2K-19QX |
invoices[].items[].count | number | ano | Množství. | 1 |
invoices[].items[].itemPriceExclVat | number | ano | Cena za kus bez DPH. | 200.89 |
invoices[].items[].itemPriceInclVat | number | ano | Cena za kus s DPH. | 225 |
invoices[].items[].vat.code | string | ano | Kód sazby DPH z číselníku firmy (Nastavení → Sazby DPH). | 12 |
invoices[].items[].discount | number | ne | Sleva na položce v procentech, vytiskne se u položky. Ceny ani součty server podle ní nepřepočítává. Výchozí 0. | 0 |
invoices[].items[].id | integer | ne | ID produktu z katalogu firmy. Bez hodnoty vznikne volná položka, která neodepisuje sklad. | null |
invoices[].items[].storable | boolean | ne | Odepsat položku ze skladu. Výchozí true u produktu z katalogu, false u volné položky. | |
invoices[].prices.currency | string | ano | Kód měny z číselníku firmy (Nastavení → Měny), u koruny obvykle Kč. | Kč |
invoices[].prices.priceInclVat | number | ano | Celková cena dokladu s DPH. | 450 |
invoices[].prices.prices | array | ano | Rekapitulace podle sazeb DPH: code (kód sazby), priceExclVat (základ), priceInclVat (s DPH). | [{"code":"12","priceExclVat":401.79,"priceInclVat":450}] |
invoices[].contact | object | ne | Odběratel. Buď {"id": ...} existujícího kontaktu, nebo údaje odběratele, podle kterých server kontakt v adresáři najde, nebo založí. Viz Odběratel. | {"externalId":"c3a1f0e2-7d4b-4e55-9a0c-1f2e3d4c5b6a","companyName":"Ukázková škola","ic":"12345679"} |
Příklad požadavku
curl
curl -X POST 'https://www.elpokladny.cz/api/v2/sync/invoices' \
-H 'Authorization: Bearer elp_live_example.example_secret' \
-H 'Content-Type: application/json' \
--data-raw '{
"options": {
"response": "documents",
"html": true
},
"invoices": [
{
"hash": "hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11",
"issuingStock": { "id": 12 },
"type": "cash",
"payment": "card",
"issued": "2026-11-06 16:28:00",
"items": [
{
"name": "Vstupné dospělý",
"code": "TKT-8F2K-19QX",
"count": 1,
"itemPriceExclVat": 200.89,
"itemPriceInclVat": 225,
"vat": { "code": "12" }
},
{
"name": "Vstupné dospělý",
"code": "TKT-8F2K-19QY",
"count": 1,
"itemPriceExclVat": 200.89,
"itemPriceInclVat": 225,
"vat": { "code": "12" }
}
],
"prices": {
"currency": "Kč",
"priceInclVat": 450,
"prices": [
{ "code": "12", "priceExclVat": 401.79, "priceInclVat": 450 }
]
}
}
]
}'PHP
<?php
$ch = curl_init('https://www.elpokladny.cz/api/v2/sync/invoices');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array (
0 => 'Authorization: Bearer elp_live_example.example_secret',
1 => 'Content-Type: application/json',
),
CURLOPT_POSTFIELDS => '{
"options": {
"response": "documents",
"html": true
},
"invoices": [
{
"hash": "hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11",
"issuingStock": { "id": 12 },
"type": "cash",
"payment": "card",
"issued": "2026-11-06 16:28:00",
"items": [
{
"name": "Vstupné dospělý",
"code": "TKT-8F2K-19QX",
"count": 1,
"itemPriceExclVat": 200.89,
"itemPriceInclVat": 225,
"vat": { "code": "12" }
},
{
"name": "Vstupné dospělý",
"code": "TKT-8F2K-19QY",
"count": 1,
"itemPriceExclVat": 200.89,
"itemPriceInclVat": 225,
"vat": { "code": "12" }
}
],
"prices": {
"currency": "Kč",
"priceInclVat": 450,
"prices": [
{ "code": "12", "priceExclVat": 401.79, "priceInclVat": 450 }
]
}
}
]
}',
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;javascript
const response = await fetch("https://www.elpokladny.cz/api/v2/sync/invoices", {
"method": "POST",
"headers": {
"Authorization": "Bearer elp_live_example.example_secret",
"Content-Type": "application/json"
},
"body": "{\n \"options\": {\n \"response\": \"documents\",\n \"html\": true\n },\n \"invoices\": [\n {\n \"hash\": \"hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11\",\n \"issuingStock\": { \"id\": 12 },\n \"type\": \"cash\",\n \"payment\": \"card\",\n \"issued\": \"2026-11-06 16:28:00\",\n \"items\": [\n {\n \"name\": \"Vstupné dospělý\",\n \"code\": \"TKT-8F2K-19QX\",\n \"count\": 1,\n \"itemPriceExclVat\": 200.89,\n \"itemPriceInclVat\": 225,\n \"vat\": { \"code\": \"12\" }\n },\n {\n \"name\": \"Vstupné dospělý\",\n \"code\": \"TKT-8F2K-19QY\",\n \"count\": 1,\n \"itemPriceExclVat\": 200.89,\n \"itemPriceInclVat\": 225,\n \"vat\": { \"code\": \"12\" }\n }\n ],\n \"prices\": {\n \"currency\": \"Kč\",\n \"priceInclVat\": 450,\n \"prices\": [\n { \"code\": \"12\", \"priceExclVat\": 401.79, \"priceInclVat\": 450 }\n ]\n }\n }\n ]\n}"
});
const data = await response.json();Ukázkové odpovědi
Doklad vystaven (HTTP 200)
application/json
{
"status": "success",
"successInvoices": [
{
"number": 42,
"type": "cash",
"hash": "hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11",
"stocksInfo": []
}
],
"documents": [
{
"id": 18234,
"hash": "hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11",
"duplicate": false,
"stockId": 12,
"type": "cash",
"number": 42,
"numberFormated": "2026000042",
"variable": "2026000042",
"issued": "2026-11-06T16:28:00+01:00",
"taxable": "2026-11-06",
"due": "2026-11-06",
"payment": "card",
"paid": true,
"storno": false,
"stornoId": null,
"currency": "Kč",
"priceExclVat": 401.79,
"priceInclVat": 450,
"vat": [
{ "code": "12", "rate": 12, "base": 401.79, "vat": 48.21, "total": 450 }
],
"items": [
{
"id": 99101,
"productId": null,
"name": "Vstupné dospělý",
"code": "TKT-8F2K-19QX",
"count": 1,
"itemPriceInclVat": 225,
"priceInclVat": 225,
"vatCode": "12"
},
{
"id": 99102,
"productId": null,
"name": "Vstupné dospělý",
"code": "TKT-8F2K-19QY",
"count": 1,
"itemPriceInclVat": 225,
"priceInclVat": 225,
"vatCode": "12"
}
],
"contactId": null,
"contactAction": null,
"eet": { "status": "registered", "pok": "...", "registered": "2026-11-06T16:28:01+01:00" },
"html": "<!DOCTYPE html>\n<html lang=\"cs\">...</html>",
"htmlTemplate": "58mm_invoice",
"paperWidth": 80,
"htmlSha256": "c1e79486b77cc5a03da65835bc82864bedffdc00f7e3029d8ba0bfab878bfb88",
"htmlError": null,
"archive": { "status": "none", "fileId": null }
}
],
"failedInvoices": []
}
Opakované odeslání stejného hash (HTTP 200)
application/json
{
"status": "success",
"successInvoices": [
{
"number": 42,
"type": "cash",
"hash": "hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11",
"stocksInfo": []
}
],
"documents": [
{
"id": 18234,
"hash": "hyd-7f3c2a9e-1b4d-4c0a-9a51-2b7e0f6d1c11",
"duplicate": true,
"stockId": 12,
"type": "cash",
"number": 42,
"numberFormated": "2026000042",
"variable": "2026000042",
"payment": "card",
"paid": true,
"priceInclVat": 450,
"archive": { "status": "none", "fileId": null }
}
],
"failedInvoices": []
}
Odmítnuté doklady ve failedInvoices (HTTP 200)
application/json
{
"status": "success",
"successInvoices": [],
"documents": [],
"failedInvoices": [
{
"index": 0,
"hash": "hyd-bad-vs",
"number": null,
"code": "variable-invalid",
"message": "Variabilní symbol musí být 1 až 10 číslic."
},
{
"index": 1,
"hash": "hyd-big",
"number": null,
"code": "customer-required",
"message": "Doklad nad 10 000 Kč vč. DPH musí mít odběratele."
}
]
}
Neplatné options (HTTP 400)
application/json
{
"status": "error",
"code": "invalid-options",
"message": "options.html musí být true / false."
}
Chybí platný API token (HTTP 401)
application/json
{
"status": "error",
"message": "Unauthorized"
}
Možné chyby
| HTTP | Kdy | Podoba |
|---|---|---|
| 400 | Neplatné options (code invalid-options), chybějící nebo prázdné pole invoices (invoices-empty) nebo víc než 100 dokladů (batch-too-large). Nezpracuje se žádný doklad. | |
| 401 | Chybí nebo je neplatný API token. | status-message |
| 403 | API token se použil z IP adresy, která není u přístupu povolená, nebo je přístup odepřen. | status-message |