Faktúry

Vystavenie faktúry cez POST /v1/agent/invoices. Predávajúci sa odvodzuje z organizácie (X-Organization-Id), kupujúci z poľa customer alebo z existujúceho customer_id. Číslovanie, výpočet DPH, PDF a QR kód prebiehajú server‑side rovnako ako pri ručnom vystavení.

Endpoint

MetódaCestaScopeHlavičky
POST/v1/agent/invoicesinvoice:createX-API-Key, X-Organization-Id

Na endpoint sa vzťahuje per‑org rate limit 30 požiadaviek / minútu (nad rámec globálneho limitu kľúča). Mena faktúry je predvolene mena firmy, inú viď currency nižšie.

Telo požiadavky

PoleTypPovinnéPopis
typeinvoice | proforma | self_invoice | final_invoice | credit_note | debit_noteNieTyp dokladu, default invoice. Každý typ má vlastný číselný rad. proforma = zálohová faktúra (výzva na úhradu, nie daňový doklad — nemá DUZP a nedá sa odoslať cez Peppol); self_invoice (samofaktúra) ide cez Peppol pod profilom BIS Self-Billing 3.0; credit_note = dobropis, debit_note = ťarchopis, final_invoice = vyúčtovacia faktúra.
customer_idUUIDPodmienečneID existujúceho zákazníka. Povinné je customer_id ALEBO customer.
customerobjektPodmienečneInline zákazník (vytvorí sa kontakt). Viď tabuľku nižšie.
itemspole objektovÁnoAspoň 1 položka. Viď tabuľku položiek nižšie.
vehicle_idUUIDNieID existujúceho vozidla (modul vozidiel).
vehicle_platestring (≤20)NieŠPZ vozidla: vyhľadá sa vozidlo (normalizuje sa na veľké písmená bez medzier).
payment_methodbank_transfer | cash | card | online | offsetNieDefault bank_transfer (mapuje sa interne na „bank“). online = online platobná služba (PayPal, brána), offset = vzájomný zápočet. Do Peppol UBL sa prenáša ako PaymentMeansCode (UNCL4461): 30 / 10 / 48 / 68 / 97.
currencyISO 4217NieMena dokladu. Bez nej mena firmy (EUR pre slovenskú, CZK pre českú). Viď Cudzia mena a kurz.
exchange_ratestring (desatinné číslo)NieKurz cudzej meny: jednotky currency na jednu jednotku domácej meny firmy. Bez neho kurz ECB / ČNB. Viď Cudzia mena a kurz.
due_daysint 0–365NieSplatnosť v dňoch od dátumu vystavenia. Default 14. Pozn.: ak má organizácia nastavené defaultDueDays, použije sa to. Nekombinujte s due_date.
due_dateYYYY-MM-DDNieDátum splatnosti napriamo — alternatíva k due_days (obe naraz = 400). Nesmie byť pred issue_date.
notestring (≤2000)NiePoznámka na faktúre (viditeľná zákazníkovi).
internal_notestring (≤2000)NieInterná poznámka (nie na PDF).
issue_dateYYYY-MM-DDNieDátum vystavenia. Default dnes.
delivery_dateYYYY-MM-DDNieDátum dodania. Default = issue_date.
order_numberstring (≤100)NieČíslo objednávky (orderReference).
invoice_numberstring (≤50)NieVlastné číslo dokladu (napr. z vášho systému). Bez neho sa číslo pridelí z číselného radu organizácie. Obsadené číslo vráti 409. Variabilný symbol = číslice z čísla (posledných 10).
delivery_addressobjektPri režimoch K ánoDodacia adresa (BG-15): name?, street, city, zip, country (2 písmená). Povinná pri intra_eu_goods / intra_eu_transfer / intra_eu_triangulation (BR-IC-12 vyžaduje krajinu dodania), inak voliteľná.
exemption_reasonstring (1–500)NieDôvod oslobodenia od DPH (BT-120) pre 0 % položky — tlačí sa na PDF a prenáša do UBL. Ak žiadna položka nemá vat_rate 0, ignoruje sa. U neplatcu DPH nahrádza predvolený text „Dodávateľ nie je platcom DPH“.
already_paidbooleanNieDefault false. Pri true sa faktúra vystaví so stavom „paid“ a plnou úhradou k dátumu vystavenia.
attachmentsarray (≤10)NiePrílohy (PDF/JPG/PNG/CSV/XLSX/ODS, base64). Pri odoslaní cez Peppol sa vložia priamo do dokladu → dorazia príjemcovi aj na iné systémy (napr. Doklado).
Každá príloha je objekt { filename, mime_code, base64_content } (voliteľne description). Povolené typy: PDF, JPG, PNG, CSV, XLSX, ODS (presne Peppol BIS 3.0 zoznam — DOC/DOCX/XLS/GIF sieť nedoručí, konvertujte ich na PDF); spolu max 10 MB (Peppol limit). Typ sa overuje z obsahu; CSV prejde len s názvom súboru končiacim na .csv. Prílohu možno pridať aj dodatočne k existujúcej faktúre cez POST /v1/agent/invoices/{id}/attachments a spravovať cez GET / DELETE na tej istej ceste.

Objekt customer

Maps na tabuľku kontaktov. Pri inline zákazníkovi sa vytvorí nový kontakt typu customer.

PoleTypPovinnéPopis
namestring 1–300ÁnoNázov firmy alebo meno zákazníka.
icostring (8 cifier)NieIČO: presne 8 číslic.
dicstringNieDIČ: 10 cifier (SK) alebo kód krajiny + 8–10 cifier (napr. CZ12345678). Normalizuje sa na veľké písmená bez medzier.
ic_dphstring (SK + 10 cifier)NieIČ DPH vo formáte SK2120035951.
addressstring | objektNieBuď celý reťazec, alebo objekt { street, city, postalCode, country }. Pre Peppol je potrebný objekt s úplnou adresou.
emailemail (≤254)NiePrázdny string sa berie ako neuvedené.
phonestring E.164 (≤16)NieFormát E.164, napr. +421900123456. Oddeľovače a prefix 00 sa normalizujú (0042... → +42...). Neplatné číslo vráti 400 VALIDATION_ERROR. Prázdny string sa berie ako neuvedené.
address ako objekt vyžaduje neprázdne street, city, postalCode a 2‑písmenový country. Ak pošlete adresu len ako reťazec, reťazec sa uloží do poľa street a country sa nastaví na "SK"; city a postalCode zostanú prázdne: pre Peppol nedostatočné (viď nižšie). Pre Peppol odosielanie vždy posielajte úplný adresný objekt.

Objekt položky (items[])

PoleTypPovinnéPopis
descriptionstring 1–500ÁnoNázov / popis položky.
quantityčíslo > 0ÁnoMnožstvo (akceptuje aj číselný string).
unitenumNieDefault ks. Povolené: ks, hod, l, m, km, súbor, kg, t, g, cm, m2, m3, set, deň, bal, kpl. Do UBL sa mapujú na kódy UN/ECE Rec 20 (km → KMT, kg → KGM, t → TNE, m2 → MTK, deň → DAY …); súbor nemá kód a ide ako C62.
unit_pricečíslo ≥ 0ÁnoJednotková cena bez DPH.
vat_rateintÁnoSadzba DPH v percentách. Povolené: 0, 5, 19, 23.
tax_treatmentenumNieDaňový režim 0 % položky: domestic (default), reverse_charge_service, intra_eu_goods, intra_eu_transfer, intra_eu_triangulation, export_goods. Iná hodnota ako domestic je povolená len pri vat_rate 0 (inak 400) a len pre platcu DPH. Všetky položky s rovnakou sadzbou musia mať rovnaký režim (inak 400). Určuje kategóriu DPH v UBL — tabuľka nižšie.

Kategórie DPH pri 0 % (mapovanie do UBL)

Sadzba 0 % sama o sebe nestačí — EN 16931 rozlišuje prečo je položka bez dane. Kategóriu určuje tax_treatment položky a exemption_reason dokladu (BT-120):

Situáciatax_treatmentexemption_reasonKategória (BT-151)VATEX kód
Prenos daňovej povinnosti (§ 69)reverse_charge_servicevoliteľnéAEVATEX-EU-AE
Dodanie tovaru do EÚ (§ 43), premiestnenie, trojstranný obchodintra_eu_goods / intra_eu_transfer / intra_eu_triangulationvoliteľnéKVATEX-EU-IC
Vývoz mimo EÚ (§ 47)export_goodsvoliteľnéGVATEX-EU-G
Oslobodené plnenie (§ 28–42, margin schémy …)domestic / neuvedenéáno (text dôvodu)Epodľa textu (napr. VATEX-EU-F)
Nulová sadzba bez dôvodudomestic / neuvedenénieZ—
Dodávateľ nie je platcom DPH(nepovolené)voliteľné, prepíše defaultOVATEX-EU-O
Bez tax_treatment a bez exemption_reason ostáva správanie ako doteraz (kategória Z). Ak si chcete výsledné UBL pozrieť pred odoslaním, použite GET /v1/agent/invoices/{id}/xml — vráti náhľad (viď nižšie).
Kategóriu určuje výhradne tax_treatment, nie text dôvodu. Ak exemption_reason sám znie ako prenos / vývoz / dodanie do EÚ (napr. „§ 69“, „prenos daňovej povinnosti“, „export“) a položka nemá cezhraničný režim, požiadavka vráti 400 s pokynom, ktorý režim nastaviť. Režimy K (intra_eu_*) navyše vyžadujú delivery_address s krajinou dodania (BT-80, BR-IC-12). Kategória O (mimo predmetu dane) nemôže byť na jednom doklade s položkami s DPH (BR-O-11). Pri self_invoice je dodávateľom kontakt — pre AE/K/G/E musí mať IČ DPH.
Ak organizácia nie je platcom DPH (nemá ic_dph ani isVatPayer), žiadna položka nesmie mať vat_rate > 0; inak požiadavka zlyhá s VALIDATION_ERROR („Nie ste platcom DPH“). Faktúra dostane výnimku „Dodávateľ nie je platcom DPH“.

Kompletný príklad

POST /v1/agent/invoices
X-API-Key: efk_pk_test_...
X-Organization-Id: 0a2c1f3e-…
Idempotency-Key: 7f0c2a4e-order-2026-042
Content-Type: application/json

{
  "customer": {
    "name": "Odberateľ s.r.o.",
    "ico": "87654321",
    "dic": "2010101010",
    "ic_dph": "SK2010101010",
    "address": {
      "street": "Obchodná 5",
      "city": "Košice",
      "postalCode": "04001",
      "country": "SK"
    },
    "email": "fakturacia@odberatel.sk",
    "phone": "+421900123456"
  },
  "items": [
    {
      "description": "Servisné práce",
      "quantity": 2,
      "unit": "hod",
      "unit_price": 50,
      "vat_rate": 23
    },
    {
      "description": "Náhradný diel",
      "quantity": 1,
      "unit": "ks",
      "unit_price": 80,
      "vat_rate": 23
    }
  ],
  "payment_method": "bank_transfer",
  "due_days": 14,
  "note": "Ďakujeme za dôveru.",
  "order_number": "OBJ-2026-042",
  "invoice_number": "2026-000042"
}

Odpoveď

HTTP/1.1 201 Created

{
  "id": "b1f0d7a2-…",
  "invoice_number": "2026001",
  "status": "issued",
  "customer": { "id": "…", "name": "Odberateľ s.r.o." },
  "items": [ … ],
  "subtotal": "180.00",
  "vat_total": "41.40",
  "total": "221.40",
  "currency": "EUR",
  "exchange_rate": null,
  "issue_date": "2026-06-22",
  "due_date": "2026-07-06",
  "pdf_url": "https://…",
  "created_at": "2026-06-22T10:00:00.000Z"
}

Hodnota id sa používa pri odoslaní cez Peppol (POST /v1/agent/peppol/send/{id}) aj pri zisťovaní stavu.

Cudzia mena a kurz

Bez currency sa faktúra vystaví v mene firmy (EUR pre slovenskú, CZK pre českú). Inú menu pošlite v poli currency (EUR, CZK, USD, GBP, PLN, CHF, HUF, RON, BGN, SEK, DKK, NOK, HRK, RSD, UAH, RUB, TRY, CNY, JPY, CAD, AUD). Pole exchange_rate je desatinné číslo v texte väčšie ako 0 (najviac 7 celých a 8 desatinných miest): počet jednotiek currency na jednu jednotku domácej meny firmy. Slovenská firma, 1 EUR = 1.0842 USD: "exchange_rate": "1.0842".

{
  "customer_id": "550e8400-…",
  "currency": "USD",
  "exchange_rate": "1.0842",
  "items": [ { "description": "Konzultácie", "quantity": 1, "unit": "ks", "unit_price": 500, "vat_rate": 0 } ]
}

Bez exchange_rate na faktúre v cudzej mene server doplní kurz ECB (slovenská firma) alebo ČNB (česká firma) k dátumu zdaniteľného plnenia (delivery_date, inak issue_date). Ak sa kurz nepodarí získať, faktúra sa aj tak vytvorí s exchange_rate: null. Odpoveď POST /v1/agent/invoices aj GET /v1/agent/invoices/{id} nesú exchange_rate (string alebo null) vedľa currency.

exchange_rate pri faktúre v domácej mene vráti 400. Dobropis alebo ťarchopis s original_invoice_id musí byť v mene pôvodnej faktúry, inak 400 — správa uvádza, akú menu poslať. Bankový účet (bank_account_id) musí mať rovnakú menu ako faktúra (BANK_ACCOUNT_CURRENCY_MISMATCH).

Idempotencia (retry bez duplikátov)

POST /v1/agent/invoices podporuje voliteľnú hlavičku Idempotency-Key: primárny mechanizmus ochrany pred duplicitnými faktúrami pri automatických retry. Rovnaký kľúč s rovnakým telom vráti uloženú odpoveď (faktúra sa nevytvorí druhýkrát a číslo radu sa neminie); rovnaký kľúč s iným telom, alebo súbežná požiadavka s rovnakým kľúčom, vráti 409. Bez hlavičky sa správanie nemení.

Číslovanie dokladov je postupné a nepreskočiteľné: duplikát vzniknutý retry sa nedá zmazať, len stornovať dobropisom. Preto pri každom klientovi s retry logikou vždy posielajte Idempotency-Key (napr. UUID objednávky). Rovnaká hlavička funguje aj na POST /v1/agent/expenses. Ako doplnok si po úspešnej odpovedi ukladajte vrátené id.

Stiahnutie PDF / XML

Vystavenú faktúru viete stiahnuť ako PDF aj ako UBL XML. Obe operácie sú scopeinvoice:download a vracajú súbor ako prílohu (Content-Disposition: attachment).

MetódaCestaScopeContent-Type
GET/v1/agent/invoices/{id}/pdfinvoice:downloadapplication/pdf
GET/v1/agent/invoices/{id}/xmlinvoice:downloadapplication/xml

Po odoslaní cez Peppol je XML presné UBL, ktoré bolo odovzdané Prístupovému bodu (uchované pre zákonnú archiváciu e‑faktúr). Pred odoslaním endpoint vráti náhľad vygenerovaný tým istým builderom, ktorý používa odosielanie — bez zápisu do DB, bez strhnutia kreditu a bez vložených príloh (tie sa do dokladu vkladajú až pri odoslaní). Ktorý variant ste dostali, hovorí hlavička X-Efaktura-Ubl-Source: archive | preview. Náhľad použite na overenie mapovania business JSON → UBL (jednotky, kategórie DPH, strany). Názov súboru je číslo faktúry ({numberPrefix}{number}.xml).

GET /v1/agent/invoices/b1f0d7a2-…/xml
X-API-Key: efk_pk_test_...
X-Organization-Id: 0a2c1f3e-…

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Content-Disposition: attachment; filename="OF2026001.xml"
X-Efaktura-Ubl-Source: preview

<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">…</Invoice>

Vzájomný zápočet

Zápočet vydanej faktúry s prijatým dokladom tej istej protistrany (napr. platforma fakturuje klientovi službu a jeho odmenu eviduje ako prijatý doklad). Jedno volanie zapíše úhradu so spôsobom offset na faktúru aj na prijatý doklad a obe spáruje. Len pre slovenské firmy. Ak potrebujete uhradiť len jednu stranu, použite POST /v1/agent/invoices/{id}/payments.

MetódaCestaScopePoznámka
POST/v1/agent/offsetsinvoice:update + receipt:updatePodporuje Idempotency-Key.
GET/v1/agent/offsetsinvoice:readFiltre invoice_id, expense_id, page, per_page (≤100).
PoleTypPovinnéPopis
invoice_idUUIDÁnoVydaná faktúra, len type invoice.
expense_idUUIDÁnoPrijatá faktúra dodávateľa tej istej protistrany.
amountstringÁnoKladná suma s najviac 2 desatinnými miestami. Nesmie presiahnuť zostatok žiadneho z oboch dokladov (bez tolerancie na zaokrúhlenie).
offset_dateYYYY-MM-DDNieDefault dnes (Europe/Bratislava). Nie v budúcnosti ani pred dátumom vystavenia niektorého z dokladov.
referencestring (≤100)NieVaše číslo zápočtu / vyúčtovania.
notestring (≤500)NiePoznámka.
POST /v1/agent/offsets
X-API-Key: efk_pk_test_...
X-Organization-Id: 0a2c1f3e-…
Idempotency-Key: 3c8e1d52-settlement-2026-10
Content-Type: application/json

{
  "invoice_id": "b1f0d7a2-…",
  "expense_id": "5b7e91c4-…",
  "amount": "110.70",
  "offset_date": "2026-10-31",
  "reference": "VYUCT-2026-10"
}

HTTP/1.1 201 Created

{
  "data": {
    "id": "3d9a60f8-…",
    "invoice_id": "b1f0d7a2-…",
    "expense_id": "5b7e91c4-…",
    "amount": "110.70",
    "currency": "EUR",
    "offset_date": "2026-10-31",
    "reference": "VYUCT-2026-10",
    "note": null,
    "accounting_program": { "status": "pending", "reason": null },
    "created_at": "2026-10-31T09:12:00.000Z",
    "invoice": { "id": "b1f0d7a2-…", "total": "270.60", "paid_amount": "110.70", "outstanding": "159.90", "status": "partially_paid" },
    "expense": { "id": "5b7e91c4-…", "total": "110.70", "paid_amount": "110.70", "outstanding": "0.00", "payment_status": "paid" }
  }
}

Úhrady zápočtu sa nedajú zmazať samostatne, ani doklady, ktoré zápočet uhradil (409). Ak niektorý doklad neexistuje, odpoveď je 404. Chyby 400:

KódVýznam
OFFSET_NOT_SUPPORTEDČeská firma — zápočet cez API je len pre slovenské.
OFFSET_INVOICE_TYPEFaktúra nie je type invoice (samofaktúra, zálohová faktúra a dobropis sa nezapočítavajú).
OFFSET_INVOICE_STATUSFaktúra je koncept, čaká na schválenie alebo je stornovaná.
OFFSET_EXPENSE_TYPEDoklad nie je schválená prijatá faktúra dodávateľa.
OFFSET_COUNTERPARTY_MISMATCHKontakt, IČO ani DIČ oboch dokladov sa nezhodujú. Pri osobe bez IČO pošlite prijatý doklad s rovnakým contact_id ako faktúra.
OFFSET_CURRENCY_MISMATCHDoklady majú rôzne meny.
OFFSET_DATEDátum je v budúcnosti alebo pred dátumom vystavenia niektorého z dokladov.
OFFSET_EXCEEDS_BALANCESuma presahuje zostatok faktúry alebo prijatého dokladu.
Účtovný program: pri firme s konektorom Omega vytvorí eFaktúra pre každý zápočet jeden interný doklad (IDZ), keď zrkadlo Omegy obsahuje oba doklady (prijatá faktúra MD 321 / D 395, vydaná faktúra MD 395 / D 311). Dovtedy je accounting_program.status pending a reason hovorí prečo; po vytvorení dokladu je sent s internal_document_id. Pri iných programoch sa zápočet automaticky neexportuje.

Požiadavky na úplnosť pre Peppol

Faktúra vystavená cez tento endpoint je v poriadku ako bežný doklad, ale aby ju bolo možné odoslať cez Peppol, výsledné UBL XML musí prejsť EN 16931 + Peppol BIS Billing 3.0 a navyše slovenským FS overlayom. SK overlay sa uplatní, keď je krajina predávajúceho SK, a vyžaduje:

Pravidlo (BT)PoleZdroj v API
SK-BT-35Ulica predávajúcehoaddress.street organizácie
SK-BT-37Mesto predávajúcehoaddress.city organizácie
SK-BT-38PSČ predávajúcehoaddress.postalCode organizácie
SK-BT-50Ulica kupujúcehocustomer.address.street
SK-BT-52Mesto kupujúcehocustomer.address.city
SK-BT-53PSČ kupujúcehocustomer.address.postalCode
SK-BT-30schemeID pri registračnom ID predávajúcehoodvodené z IČO/DIČ organizácie
SK-BT-47schemeID pri registračnom ID kupujúcehoodvodené z IČO/DIČ kupujúceho
Ak chýba čo i len jedno z polí adresy predávajúceho alebo kupujúceho, odoslanie cez Peppol zlyhá na SK overlayi (napr. SK-BT-35-REQUIRED). Preto pri zakladaní organizácie aj pri vytváraní zákazníka vždy posielajte úplnú adresu (street + city + postalCode + country).

Smerovanie na príjemcu v Peppol prebieha cez DIČ kupujúceho (sandbox: 9915:<DIČ>, produkcia: 0245:<DIČ>). Pre korektnú VAT kategorizáciu (BR‑S/BR‑E) má mať predávajúci aj kupujúci ic_dph. Pred odoslaním viete UBL XML pre‑validovať: viď Validácia.

Faktúru vystavenú týmto endpointom odošlete cez POST /v1/agent/peppol/send/{id}; tesne pred odoslaním ju skontrolujte suchým behom (dry‑run) cez POST /v1/agent/invoices/{id}/preflight (viď Odporúčaný tok): bez zápisu do DB a bez strhnutia kreditu. Samostatný /peppol/preflight je len pre UBL/CII, ktoré si skladáte sami. Ak si UBL/CII skladáte sami a nechcete ísť cez /agent/invoices, jedným volaním zvalidujete, rezervujete kredit a odošlete cez Konektor.