Model domeny¶
Integrator pracuje z trzema obiektami: zleceniem fiskalizacji, drukarką i powstałym z nich e-paragonem (znaczenie pojęć: słownik).
Zlecenie fiskalizacji¶
Pola dokumentu (element tablicy print_requests[] w zleceniu)¶
| Pole | Wymagane | Opis |
|---|---|---|
external_id |
tak | identyfikator dokumentu w Twoim systemie (string); chroni przed podwójną fiskalizacją — patrz unikalność. Wraca w webhookach. |
mode |
nie | tryb: print (paragon papierowy) albo e_receipt (e-paragon). Domyślnie brany z drukarki, lub print. Zapisy e-receipt/ereceipt też są akceptowane. |
vendor |
tak | identyfikator Twojego systemu — opis |
printer_id |
zalecane | id drukarki z GET /printers.json (zamiennik: printer_name — dopasowanie po nazwie). Bez obu → drukarka domyślna konta, a gdy brak → pierwsza. |
kind |
nie | typ dokumentu: receipt (paragon, domyślny) albo vat (faktura drukowana na drukarce fiskalnej). E-paragon wymaga kind=receipt. Rabaty (discount/discount_percent) działają dla obu — na fakturze zachowanie zależy od drukarki klienta, patrz rabat na fakturze. Dla kind=vat część protokołów drukarek wymaga buyer.tax_no (błąd NIP). |
system_number |
nie | numer dokumentu (drukowany; obcinany do 15 znaków). |
order_number |
nie | dodatkowy identyfikator zamówienia (do wyszukiwania w Paragony.pl). |
external_url |
nie | link do dokumentu w Twoim systemie (widoczny przy zleceniu w Paragony.pl). |
currency |
nie | tylko PLN (domyślne). Inna waluta = odrzucenie dokumentu. |
price_gross |
nie | suma brutto dokumentu; gdy brak — wyliczana z pozycji. Musi być dodatnia i zgodna z sumą pozycji (patrz walidacje). |
payment_to |
nie | termin płatności (do 16 znaków) — drukowany tylko dla kind=vat. |
payment_type / payment_type_text |
nie | forma płatności do wydruku (do 20 znaków) — patrz forma płatności. |
buyer |
nie | obiekt nabywcy: name, email, address, tax_no. email służy wyłącznie doręczeniu e-paragonu mailem — nie jest drukowany, nie wchodzi do treści e-paragonu i nie jest wymagany do fiskalizacji; jego podanie włącza automatyczną wysyłkę (E-paragon). tax_no drukowany na paragonie jako NIP nabywcy (paragon z NIP). name i address — drukowane tylko dla kind=vat. |
positions |
tak | tablica pozycji (niżej). Pusta tablica = odrzucenie dokumentu. |
recipient_name |
nie | odbiorca (do 26 znaków) — drukowany tylko dla kind=vat. |
Pola wspólne dla całego żądania (obok tablicy print_requests):
| Pole | Opis |
|---|---|
vendor |
wymagany (dla całego żądania lub per dokument) — identyfikator Twojego systemu; role i semantyka |
ptu_letter_in_names |
true → do nazwy każdej pozycji na wydruku doklejana jest litera stawki VAT (np. „ A”). |
Forma płatności¶
payment_type to kod formy płatności, payment_type_text — etykieta drukowana na
paragonie (obcinana do 20 znaków).
Rozpoznawane kody: cash, card, cheque, bon, credit, transfer, voucher,
other — dopuszczalny jest też dowolny własny kod, a dopasowanie jest czułe na wielkość
liter (CARD jest kodem własnym). Bez payment_type_text etykietę wyznacza kod: dla
rozpoznanego kanoniczna nazwa (GOTÓWKA/KARTA/CZEK/BON/KREDYT/PRZELEW/VOUCHER/INNA),
dla własnego — sam kod. Sama etykieta, bez payment_type, jest drukowana jako forma INNA.
Poza tym zachowanie zależy od drukarki klienta, a integrator jej nie wybiera:
- przy kodzie rozpoznanym część urządzeń drukuje
payment_type_textbez zmian, a część zastępuje je nazwą kanoniczną; - bez obu pól część urządzeń pomija formę płatności, a część zapisuje gotówkę.
Własną nazwę formy płatności prześlij jako własny kod w payment_type — ta ścieżka daje
ten sam wydruk na każdym urządzeniu.
Pozycje (positions[])¶
| Pole | Wymagane | Opis |
|---|---|---|
name |
tak | nazwa pozycji (drukowana; obcinana do 40 znaków/linia). |
short_name |
nie | krótsza nazwa — jeśli podana, drukowana zamiast name. |
quantity |
tak | ilość — większa od zera, dopuszczalna ułamkowa, maksymalnie 5 miejsc po przecinku (błąd). |
price_gross |
tak | cena jednostkowa brutto. |
total_price_gross |
tak | wartość brutto pozycji. Musi być dodatnia i równa price_gross × quantity (zaokrąglenie do 2 miejsc). |
tax |
tak | stawka VAT — patrz mapowanie stawek. |
discount |
nie | kwota rabatu (brutto) na pozycji. Podana ma pierwszeństwo przed discount_percent — gdy oba pola podane, discount_percent staje się wyłącznie opisem drukowanym, a kwotę rabatu wyznacza discount. Na fakturze zachowanie zależy od drukarki klienta — patrz rabat na fakturze. |
discount_percent |
nie | procent rabatu (0–100 wyłącznie), drukowany na paragonie. Bez discount kwotę wylicza API: kwota = total_price_gross − zaokrąglone(price_gross × (1 − procent/100) × quantity, 2) (połówki w górę) — przykład liczbowy. |
service |
nie | true = pozycja jest usługą (ma znaczenie dla stawki disabled — patrz niżej). |
Rabat na fakturze (kind=vat)¶
Na paragonie rabat zawsze drukuje się jako osobna pozycja. Na fakturze zależy to od drukarki klienta, a integrator jej nie wybiera:
- część urządzeń obsługuje osobną linię rabatu — rabat odejmuje drukarka, dokument drukuje się normalnie;
- pozostałe wymagają wliczenia rabatu w ceny pozycji. Jeśli rabatu nie da się wyrazić
ceną jednostkową co do grosza (typowo przy
quantity> 1), zlecenie jest odrzucane przy wydruku (komunikat) — prześlij wtedyprice_grossitotal_price_grossjuż po rabacie, bez póldiscount/discount_percent.
Walidacje zlecenia (po stronie Paragony.pl, przed wysyłką do drukarki)¶
positionsniepuste;total_price_grossiprice_grosskażdej pozycji > 0;quantitykażdej pozycji > 0 i maksymalnie 5 miejsc po przecinku;total_price_gross == price_gross × quantity(na 2 miejsca) — inaczej „Niepoprawna wartość brutto na pozycji N”;- suma
total_price_gross − discountpo pozycjach musi się równaćprice_grossdokumentu — inaczej „Niepoprawna wartość brutto na dokumencie”; currency == "PLN"; suma dokumentu dodatnia;- rozpoznawalna stawka VAT każdej pozycji (niżej);
- dla
mode=e_receipt:kind == "receipt"(buyer.emailjest opcjonalny — bez niego e-paragon powstaje normalnie, tylko nie idzie mailem); - dla
mode=e_receipt: drukarka musi obsługiwać e-paragony i mieć skonfigurowane e-paragony (polae_receiptie_receipt_configureddrukarki) — inaczej zlecenie jest przyjmowane od razu ze statusemerror(dokument nie zostanie zafiskalizowany; status widzisz w elemencie odpowiedzi tworzenia); - aktywna subskrypcja e-paragonów z dostępnym limitem (patrz błędy rozliczeń).
Dokumenty w jednym zleceniu walidowane są niezależnie — część może przejść, część zostać odrzucona; werdykt per dokument niesie odpowiedź tworzenia (kontrakt pozycyjny).
Walidacje po stronie drukarki¶
Nawet poprawnie przyjęte zlecenie może zakończyć się błędem na urządzeniu (np. brak papieru,
błąd protokołu, odrzucenie przez moduł fiskalny). Taki wynik wraca jako status error
(lub er_fatal dla nieudanej wysyłki e-paragonu po fiskalizacji) wraz z tekstowym opisem
z urządzenia — traktuj go jako komunikat diagnostyczny do pokazania użytkownikowi,
jego treść zależy od modelu drukarki.
Stawki VAT¶
Pole tax pozycji jest mapowane na literę stawki (PTU) drukarki fiskalnej:
tax |
litera PTU |
|---|---|
23 |
A |
8 |
B |
5 |
C |
0 |
D |
zw (zwolniony) |
E |
disabled |
litera Zera technicznego z ustawień konta (osobna dla towaru i usługi — pole service); wymaga wcześniejszej konfiguracji Zera technicznego w Ustawieniach na stronie Paragony.pl, inaczej błąd |
Wartości można podawać jako liczby lub stringi (23, "23", "23.0" działają tak samo).
Nierozpoznana stawka = odrzucenie dokumentu („Niepoprawna stawka VAT”).
Statusy zlecenia (cykl życia)¶
| Status | Faza | Znaczenie |
|---|---|---|
to_print |
oczekujący | w kolejce, czeka na pobranie przez drukarkę |
printing |
oczekujący | pobrane przez drukarkę, w trakcie wydruku/fiskalizacji |
printed |
końcowy | zafiskalizowany paragon papierowy |
er_pending |
przejściowy | fiskalizacja e-paragonu wykonana, e-paragon w drodze — czekamy na potwierdzenie wystawienia |
er_fail |
przejściowy | dokument zafiskalizowany, wysyłka e-paragonu chwilowo nieudana — urządzenie ponawia |
er_printed |
końcowy | e-paragon wystawiony; w webhooku przychodzi view_url |
er_fatal |
końcowy | dokument zafiskalizowany, ale e-paragon ostatecznie nie powstał |
error |
końcowy | zlecenie zakończone błędem — dokument nie został zafiskalizowany |
cancelled |
końcowy | zlecenie anulowane (żądaniem DELETE albo zastąpione nowym zleceniem na ten sam external_id) |
stateDiagram-v2
[*] --> to_print
to_print --> printing
to_print --> cancelled : anulowanie / zastąpienie
printing --> cancelled : anulowanie / zastąpienie
to_print --> error
printing --> error : błąd urządzenia
printing --> printed : paragon papierowy
printing --> er_pending : e-paragon wysłany
printing --> er_fail : wysyłka e-paragonu do ponowienia
er_pending --> er_printed : e-paragon wystawiony
er_fail --> er_printed : e-paragon wystawiony
er_pending --> er_fatal
er_fail --> er_fatal
printed --> [*]
er_printed --> [*]
er_fatal --> [*]
error --> [*]
cancelled --> [*]
Gwarancje:
er_printedjest ostateczny — raz osiągnięty nigdy się nie zmienia.- Zlecenie zafiskalizowane (
printed,er_*) nigdy nie wraca do stanów oczekujących ani doerror/cancelled. er_pendingier_failto stany przejściowe — rozstrzygną się wer_printedalboer_fatal. Dokument jest już wtedy zafiskalizowany; różnica dotyczy tylko dostarczenia e-paragonu.- W kodzie klienta porównuj status ze zbiorem, nie z jedną wartością: końcowe to
printed,er_printed,er_fatal,error,cancelled, a zafiskalizowane —printedluber_printed.
Unikalność / ochrona przed podwójną fiskalizacją¶
Dla jednej pary (vendor, external_id) może istnieć najwyżej jedno aktywne zlecenie
(o statusie innym niż error/cancelled). Unikalność liczy się w ramach Twojego konta,
per vendor —
ten sam external_id pod dwoma różnymi vendorami to dwa niezależne zlecenia. Ponowne zlecenie
z tym samym external_id (i tym samym vendorem):
- gdy istniejące jest oczekujące (
to_print/printing) → stare zostaje anulowane (cancelled), nowe je zastępuje — bezpieczny sposób na „popraw i wyślij jeszcze raz”; - gdy istniejące jest zafiskalizowane (
printed,er_*) → nowe zostaje odrzucone („Paragon jest już zafiskalizowany — nie drukujemy ponownie”). Dzięki temu nie da się przypadkiem zafiskalizować dokumentu drugi raz; - zlecenia zakończone jako
error/cancellednie blokują — można zlecić ponownie.
Drukarka¶
| Pole | Opis |
|---|---|
id |
identyfikator drukarki — tę wartość podajesz w print_requests[].printer_id |
uid |
identyfikator (UID) drukarki |
name |
nazwa widoczna w Paragony.pl; może służyć do wskazania drukarki (printer_name) |
model |
model urządzenia |
connection_method |
sposób połączenia (np. usb, tcp) |
default_mode |
domyślny tryb wydruku (print/e_receipt) — używany, gdy zlecenie nie podaje mode |
e_receipt |
czy urządzenie obsługuje e-paragony |
e_receipt_configured |
czy e-paragony są na urządzeniu skonfigurowane |
footer_text |
dodatkowy tekst stopki wydruku |
deleted |
true = drukarka usunięta; usunięcie sygnalizuje też webhook printer:destroy |
Drukarki rejestruje aplikacja Paragony.pl zainstalowana przy urządzeniu — integrator
tylko je listuje i wskazuje w zleceniach.
Pola opisowe (name, footer_text, default_mode, logo_data) zaktualizujesz przez
PATCH /printers/:id.json; pozostałe są tylko do odczytu.
Zmiany drukarek (dodanie, edycja, usunięcie) są rozgłaszane webhookami
printer:create|update|destroy — patrz Webhooki.
E-paragon¶
Powstaje po udanej fiskalizacji w trybie e_receipt. Dla integratora najważniejszy jest
view_url — publiczny link do e-paragonu (https://<prefix>.paragony.pl/<token>);
przychodzi webhookiem razem ze statusem er_printed (zawsze razem — nie ma er_printed
bez view_url) i tak samo jest polem view_url
w odpowiedzi GET.
Link przekazujesz klientowi końcowemu własnym kanałem albo zlecasz jego wysyłkę mailem przez Paragony.pl.
O wysyłce decyduje buyer.email. Dokument z adresem dostaje maila automatycznie —
po osiągnięciu statusu er_printed. Dokument bez adresu fiskalizuje się tak samo, tylko
maila nie wysyłamy.
Zlecenie nie ma pola sterującego wysyłką — nie chcesz maila dla danego dokumentu, nie przysyłaj dla niego adresu.
Dwie rzeczy modyfikują tę regułę:
- ustawienie konta „Automatycznie wysyłaj e-paragony mailem” w panelu Paragony.pl, domyślnie włączone. Wyłącza je właściciel konta — wtedy Paragony.pl nie wysyłają nic automatycznie, niezależnie od przysyłanych adresów. Twoja integracja tego nie nadpisze, bo to decyzja firmy, a nie pojedynczego zlecenia;
POST .../send_by_email.json— wysyłka ręczna (ponowna, z korektą adresu albo z adresem zebranym po fiskalizacji) w dowolnym momencie po wystawieniu e-paragonu. Działa też przy wyłączonym ustawieniu konta.
Treść wprowadzającą maila ustawiasz w tym samym panelu („Treść wprowadzająca w mailu z e-paragonem”); pusta = tekst domyślny.