Easy Invoice API
Kompletny przewodnik po tworzeniu faktur i integracji z KSeF
Easy Invoice API pozwala programistycznie tworzyć faktury VAT, dodawać pozycje, wysyłać dokumenty do Krajowego Systemu e-Faktur (KSeF) i pobierać potwierdzenia odbioru (UPO).
Ten przewodnik przeprowadzi Cię przez kompletny proces wystawienia faktury — od pustego dokumentu do numeru KSeF i kodu QR.
Konfiguracja klienta PHP
Pobierz klasę classUddsOx.php i skonfiguruj połączenie:
<?php
require_once('classUddsOx.php');
$udds = new classUddsOx();
$udds->customerCode = 'TWOJ_KOD_KLIENTA'; // Otrzymasz od KSI Media
$udds->login = 'twoj_login';
$udds->password = 'twoje_haslo';
$udds->serverUrl = 'https://api.dlaoperatora.pl/udds/';
$udds->timeout = 30; // sekundy
Dane do połączenia z API (customerCode, login, password)
otrzymasz od administratora systemu dlaoperatora.pl lub KSI Media.
Workflow tworzenia faktury
6 kroków od utworzenia do numeru KSeF
Musisz zachować kolejność kroków. Nie możesz wysłać faktury do KSeF bez wcześniejszego dodania pozycji i aktywacji dokumentu.
Tworzenie nagłówka faktury
Endpoint: createInvoiceHead
Nagłówek faktury zawiera wszystkie dane oprócz pozycji: nabywcę, daty, metodę płatności, walutę. Numer faktury generuje się automatycznie z sekwencji systemowej.
Faktura tworzy się jako TYMCZASOWA (robocza).
Możesz swobodnie dodawać/usuwać pozycje dopóki nie aktywujesz dokumentu.
Przykład — faktura krajowa PLN
<?php
/**
* KROK 1: Tworzenie nagłówka faktury
*
* Tworzymy fakturę VAT dla polskiej firmy.
* Numer faktury generuje się automatycznie z sekwencji.
*/
$params = [
// ═══════════════════════════════════════════════════════════════
// DATY I MIEJSCE
// ═══════════════════════════════════════════════════════════════
'issuePlace' => 'Warszawa', // Miejsce wystawienia
'issueDate' => date('Y-m-d'), // Data wystawienia (dziś)
'saleDate' => date('Y-m-d'), // Data sprzedaży (dziś)
// ═══════════════════════════════════════════════════════════════
// TYP DOKUMENTU
// ═══════════════════════════════════════════════════════════════
'documentType' => 'FV', // FV = Faktura VAT
// FK = Faktura korygująca
// PRO = Pro-forma
'template' => 'VAT', // VAT lub MARZA
'currency' => 'PLN', // Waluta (PLN, EUR, USD...)
// ═══════════════════════════════════════════════════════════════
// PŁATNOŚĆ
// ═══════════════════════════════════════════════════════════════
'paymentMethod' => 'przelew', // przelew, gotówka, karta
'paymentDueDate'=> date('Y-m-d', strtotime('+14 days')), // Termin płatności (+14 dni)
// ═══════════════════════════════════════════════════════════════
// NABYWCA (KUPUJĄCY)
// ═══════════════════════════════════════════════════════════════
'buyerName' => 'Innowacje IT Sp. z o.o.',
'buyerNip' => '5213456789', // NIP (10 cyfr, bez kresek)
'buyerAddress' => 'ul. Marszałkowska 100/5',
'buyerPostCode' => '00-001',
'buyerCity' => 'Warszawa',
'buyerCountry' => 'Polska',
// ═══════════════════════════════════════════════════════════════
// KSEF — oznaczyć do wysyłki już teraz
// ═══════════════════════════════════════════════════════════════
'toKsef' => 1, // 1 = wyślij do KSeF
// 0 = nie wysyłaj
// ═══════════════════════════════════════════════════════════════
// OPCJONALNE
// ═══════════════════════════════════════════════════════════════
'notes' => 'Płatność w terminie 14 dni',
'printNotes' => '1', // Drukuj uwagi na fakturze
];
$result = $udds->createInvoiceHead($params);
// ─────────────────────────────────────────────────────────────────────
// OBSŁUGA ODPOWIEDZI
// ─────────────────────────────────────────────────────────────────────
if ($result['status'] === 'OK') {
$idInvoice = $result['id']; // np. "ABCD1234EFGH5678..."
$invoiceNumber = $result['number']; // np. "FV/0001/02/2026"
echo "✅ Utworzono fakturę: {$invoiceNumber}\n";
echo " ID do dalszych operacji: {$idInvoice}\n";
} else {
echo "❌ Błąd tworzenia faktury:\n";
foreach ($result['errors'] as $error) {
echo " [{$error['code']}] {$error['message']}\n";
}
exit(1);
}
Struktura odpowiedzi
// Sukces
{
"status": "OK",
"id": "00000004M1G221031126JF1B44ASNQ6D", // ID faktury (32 znaki)
"number": "FV/0001/02/2026", // Numer faktury
"errors": []
}
// Błąd
{
"status": "ERROR",
"id": null,
"number": null,
"errors": [
{ "code": 1001, "message": "Pole buyerName jest wymagane" }
]
}
Dodawanie pozycji do faktury
Endpoint: createInvoiceItem
Każda pozycja to osobne wywołanie createInvoiceItem.
API automatycznie przelicza VAT i aktualizuje sumy na fakturze.
Wszystkie kwoty podajesz w groszach (×100)
100.00 PLN = 10000
Ilości też mnożysz przez 100
1 sztuka = 100, 0.5 kg = 50
Tabela przeliczników
| Wartość | Jak przeliczyć | Przykład |
|---|---|---|
| Cena | złotówki × 100 | 149.99 PLN → 14999 |
| Ilość | sztuki × 100 | 2.5 szt → 250 |
| Stawka VAT | string | '23', '8', 'zw', 'np' |
Przykład — różne pozycje
<?php
/**
* KROK 2: Dodawanie pozycji do faktury
*
* PAMIĘTAJ O PRZELICZNIKACH:
* - Kwoty w GROSZACH: 100.00 PLN = 10000
* - Ilości ×100: 1 sztuka = 100, 0.5 kg = 50
*/
$idInvoice = 'ABCD1234EFGH5678...'; // ID z poprzedniego kroku
// ═══════════════════════════════════════════════════════════════════════
// POZYCJA 1: Usługa programistyczna (VAT 23%)
// ═══════════════════════════════════════════════════════════════════════
$item1 = $udds->createInvoiceItem([
'idInvoice' => $idInvoice,
'name' => 'Usługa programistyczna - rozwój aplikacji webowej',
'quantity' => 100, // 1.00 sztuki (1 × 100)
'unit' => 'szt.', // Jednostka miary
'vatRate' => '23', // Stawka VAT
'priceNetto' => 500000, // 5000.00 PLN netto
]);
if ($item1['status'] === 'OK') {
echo "✅ Dodano: Usługa programistyczna\n";
echo " Netto: " . number_format($item1['calculatedValues']['valueNetto'] / 100, 2) . " PLN\n";
echo " VAT: " . number_format($item1['calculatedValues']['valueVat'] / 100, 2) . " PLN\n";
echo " Brutto: " . number_format($item1['calculatedValues']['valueBrutto'] / 100, 2) . " PLN\n";
}
// ═══════════════════════════════════════════════════════════════════════
// POZYCJA 2: Szkolenie (stawka ZW — zwolniony)
// ═══════════════════════════════════════════════════════════════════════
$item2 = $udds->createInvoiceItem([
'idInvoice' => $idInvoice,
'name' => 'Szkolenie z obsługi systemu (8h)',
'quantity' => 800, // 8.00 godzin (8 × 100)
'unit' => 'godz.',
'vatRate' => 'zw', // Zwolniony z VAT
'priceNetto' => 15000, // 150.00 PLN/godz
]);
// ═══════════════════════════════════════════════════════════════════════
// POZYCJA 3: Produkt z ilością ułamkową
// ═══════════════════════════════════════════════════════════════════════
$item3 = $udds->createInvoiceItem([
'idInvoice' => $idInvoice,
'name' => 'Kabel sieciowy Cat6',
'quantity' => 2550, // 25.50 metrów (25.5 × 100)
'unit' => 'mb', // metr bieżący
'vatRate' => '23',
'priceNetto' => 350, // 3.50 PLN/mb
]);
// Wynik: 25.5 mb × 3.50 PLN = 89.25 PLN netto
Algorytm kalkulacji VAT
valueNetto = priceNetto × quantity / 100
valueVat = round(valueNetto × vatRate / 100)
valueBrutto = valueNetto + valueVat
// Przykład: 1 szt × 500 PLN netto, VAT 23%
// valueNetto = 50000 × 100 / 100 = 50000 (500.00 PLN)
// valueVat = round(50000 × 23 / 100) = 11500 (115.00 PLN)
// valueBrutto = 50000 + 11500 = 61500 (615.00 PLN)
Aktywacja faktury
Endpoint: setInvoiceStatus
Po dodaniu wszystkich pozycji zmień status na AKTYWNA.
To "zamyka" fakturę — nadal możesz ją wysłać do KSeF, ale edycja jest ograniczona.
<?php
/**
* KROK 3: Aktywacja faktury
*
* Zmieniamy status z TYMCZASOWA na AKTYWNA.
* Po aktywacji faktura jest gotowa do wysyłki.
*/
$result = $udds->setInvoiceStatus([
'idInvoice' => $idInvoice,
'status' => 'AKTYWNA',
]);
if ($result['status'] === 'OK') {
echo "✅ Faktura aktywowana\n";
echo " Poprzedni status: {$result['data']['previousStatus']}\n";
echo " Nowy status: {$result['data']['newStatus']}\n";
} else {
echo "❌ Błąd: {$result['errors'][0]['message']}\n";
}
Jeśli faktura ma już numer KSeF (ksefNumber),
nie możesz zmienić jej statusu ani edytować treści.
Wysyłka do KSeF
Endpoint: sendInvoiceToKsef
Wysyłka do Krajowego Systemu e-Faktur wymaga działającego KSeF Service (mikroserwis) i aktywnej sesji z urzędem.
<?php
/**
* KROK 4: Wysyłka faktury do KSeF
*
* Faktura musi mieć ustawione toKsef = 1
* KSeF Service musi być uruchomiony i zainicjowany.
*/
// Opcjonalnie: jeśli nie oznaczyłeś faktury do KSeF przy tworzeniu
$udds->updateInvoiceHead([
'idInvoice' => $idInvoice,
'toKsef' => 1,
]);
// Wysyłka
$result = $udds->sendInvoiceToKsef([
'idInvoice' => $idInvoice,
]);
if ($result['status'] === 'OK') {
echo "✅ Faktura wysłana do KSeF!\n";
echo " Odpowiedź: {$result['ksefResponse']['message']}\n";
} else {
echo "❌ Błąd wysyłki: {$result['message']}\n";
// Szczegóły błędu z KSeF Service
if (isset($result['ksefResponse'])) {
echo " KSeF: [{$result['ksefResponse']['httpCode']}] ";
echo "{$result['ksefResponse']['message']}\n";
}
}
Typowe błędy KSeF Service
| Kod | Znaczenie | Rozwiązanie |
|---|---|---|
REST-003 |
KSeF nie jest zainicjowany | Uruchom sesję w KSeF Service |
REST-011 |
Brak rekordu w KSEF_FAKTURY | Ustaw toKsef = 1 |
1004 |
Błąd połączenia | Sprawdź czy KSeF Service działa |
Weryfikacja statusu, UPO i QR code
Endpoint: getInvoice
Po wysłaniu faktury KSeF przetwarza ją asynchronicznie.
Używaj getInvoice do sprawdzenia statusu i pobrania:
- Numer KSeF — oficjalny numer w systemie
- UPO — Urzędowe Poświadczenie Odbioru (link do pobrania)
- QR Code — URL weryfikacyjny do zeskanowania
Przykład — polling statusu
<?php
/**
* KROK 5: Weryfikacja statusu w KSeF
*
* KSeF przetwarza faktury asynchronicznie.
* Sprawdzamy co kilka sekund aż pojawi się numer KSeF.
*/
$maxAttempts = 10;
$delaySeconds = 3;
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
echo "🔄 Sprawdzanie statusu (próba {$attempt}/{$maxAttempts})...\n";
$invoice = $udds->getInvoice(['idInvoice' => $idInvoice]);
if ($invoice['status'] !== 'OK') {
echo "❌ Błąd pobierania faktury\n";
break;
}
$ksef = $invoice['data']['invoice']['ksef'];
// ═══════════════════════════════════════════════════════════════════
// Sprawdź czy mamy numer KSeF
// ═══════════════════════════════════════════════════════════════════
if (!empty($ksef['ksefNumber'])) {
echo "\n════════════════════════════════════════════════════════════\n";
echo "✅ FAKTURA ZAREJESTROWANA W KSEF!\n";
echo "════════════════════════════════════════════════════════════\n\n";
// ─────────────────────────────────────────────────────────────────
// NUMER KSEF — drukujesz na fakturze
// ─────────────────────────────────────────────────────────────────
echo "📋 Numer KSeF: {$ksef['ksefNumber']}\n";
echo "📅 Data KSeF: {$ksef['invoicingDatetime']}\n";
// ─────────────────────────────────────────────────────────────────
// UPO — Urzędowe Poświadczenie Odbioru
// ─────────────────────────────────────────────────────────────────
if (!empty($ksef['upoLink'])) {
echo "\n📜 UPO (Urzędowe Poświadczenie Odbioru):\n";
echo " Link: {$ksef['upoLink']}\n";
echo " Hash: {$ksef['upoHash']}\n";
}
// ─────────────────────────────────────────────────────────────────
// QR CODE — URL do weryfikacji
// ─────────────────────────────────────────────────────────────────
if (!empty($ksef['verificationUrl'])) {
echo "\n📱 QR Code / URL weryfikacyjny:\n";
echo " {$ksef['verificationUrl']}\n";
}
break; // Sukces — wychodzimy z pętli
} else {
$status = $ksef['statusDescription'] ?? 'oczekiwanie...';
echo " Status: {$status}\n";
if ($attempt < $maxAttempts) {
sleep($delaySeconds);
}
}
}
if (empty($ksef['ksefNumber'])) {
echo "\n⏳ Faktura wciąż w przetwarzaniu. Sprawdź później.\n";
}
Struktura sekcji KSEF w odpowiedzi
$invoice['data']['invoice']['ksef'] = [
'toKsef' => 1, // Flaga wysyłki
'ksefNumber' => '1234567890-20260204-...', // ⭐ Numer w KSeF
'processingCode' => 200, // Kod przetwarzania
'statusDescription' => 'Faktura przyjęta', // Opis statusu
'invoicingDatetime' => '2026-02-04 14:32:15', // Data rejestracji
'upoLink' => 'https://ksef.../upo/...', // 📜 Link do UPO
'upoHash' => 'a1b2c3d4...', // Hash UPO
'verificationUrl' => 'https://ksef.../verify/...', // 📱 URL do QR
'invoiceHash' => 'x9y8z7w6...', // Hash faktury
];
Użyj wartości verificationUrl jako danych wejściowych
dla dowolnej biblioteki QR (np. phpqrcode, endroid/qr-code).
Klient może zeskanować kod i zweryfikować fakturę w KSeF.
Faktury od netto vs od brutto
Parametr: calculationType
Faktury mogą być liczone od netto (podajesz cenę netto, system wylicza brutto) lub od brutto (podajesz cenę brutto, system wylicza netto).
Podajesz cenę netto → system wylicza VAT i brutto
Typowe dla: B2B, hurtownie, gdzie negocjujesz ceny netto
calculationType = 'netto'priceNetto = 10000
Podajesz cenę brutto → system wylicza netto i VAT
Typowe dla: B2C, sklepy, gdzie cena na metce to brutto
calculationType = 'brutto'priceBrutto = 12300
Przykład — faktura od brutto
<?php
// FAKTURA OD BRUTTO — ceny na metce
$invoiceHead = $udds->createInvoiceHead([
'issuePlace' => 'Warszawa',
'issueDate' => date('Y-m-d'),
'saleDate' => date('Y-m-d'),
'documentType' => 'FV',
'template' => 'VAT',
'currency' => 'PLN',
'calculationType' => 'brutto', // ← Wyliczanie od brutto
'paymentMethod' => 'karta',
'buyerName' => 'Jan Kowalski',
// ... pozostałe dane
]);
// Przy dodawaniu pozycji używasz priceBrutto (nie priceNetto!)
$udds->createInvoiceItem([
'idInvoice' => $invoiceHead['id'],
'name' => 'Smartfon XYZ Pro',
'quantity' => 100, // 1 szt
'unit' => 'szt.',
'vatRate' => '23',
'priceBrutto' => 249900, // 2499.00 PLN brutto
]);
// System wyliczy:
// - netto: 2031.71 PLN
// - VAT: 467.29 PLN
// - brutto: 2499.00 PLN
Faktury w walutach obcych
Parametr: currency, exchangeRate
Możesz wystawiać faktury w EUR, USD i innych walutach. Kurs NBP pobiera się automatycznie (z dnia poprzedzającego datę sprzedaży), ale możesz podać własny.
Przykład — faktura w EUR
<?php
/**
* FAKTURA W WALUCIE OBCEJ (EUR)
* Kurs wymiany pobierany automatycznie z NBP.
*/
$invoiceHead = $udds->createInvoiceHead([
'issuePlace' => 'Warszawa',
'issueDate' => date('Y-m-d'),
'saleDate' => date('Y-m-d'),
'documentType' => 'FV',
'template' => 'VAT',
// ═══════════════════════════════════════════════════════════════════
// WALUTA
// ═══════════════════════════════════════════════════════════════════
'currency' => 'EUR', // Waluta dokumentu
// Opcjonalnie: własny kurs (jeśli nie podasz — pobierze z NBP)
// 'exchangeRate' => 43250, // 4.3250 PLN/EUR (×10000!)
// 'exchangeRateDate' => date('Y-m-d', strtotime('-1 day')),
'paymentMethod' => 'przelew',
// Nabywca zagraniczny
'buyerName' => 'Acme GmbH',
'buyerNip' => 'DE123456789', // NIP z prefiksem kraju
'buyerAddress' => 'Hauptstraße 42',
'buyerPostCode' => '10115',
'buyerCity' => 'Berlin',
'buyerCountry' => 'Niemcy',
'toKsef' => 1,
]);
// Pozycje — ceny w eurocentach!
$udds->createInvoiceItem([
'idInvoice' => $invoiceHead['id'],
'name' => 'Consulting services',
'quantity' => 100,
'unit' => 'szt.',
'vatRate' => '0', // Eksport usług — 0%
'priceNetto' => 100000, // 1000.00 EUR
]);
Jeśli podajesz własny exchangeRate, pamiętaj o mnożniku ×10000.
Przykład: 4.5632 PLN/EUR → exchangeRate = 45632
Dostępne waluty
| Kod | Nazwa |
|---|---|
PLN | Polski złoty (domyślna) |
EUR | Euro |
USD | Dolar amerykański |
GBP | Funt brytyjski |
CHF | Frank szwajcarski |
CZK | Korona czeska |
Faktury VAT-marża
Parametr: template = 'MARZA'
Szablon MARZA stosuje się przy sprzedaży towarów używanych,
dzieł sztuki, antyków — gdzie VAT nalicza się tylko od marży, nie od całej wartości.
Na fakturze VAT-marża nie pokazuje się stawki VAT, kwoty VAT ani ceny netto. Klient widzi tylko kwotę brutto.
Przykład — faktura marża
<?php
/**
* FAKTURA VAT-MARŻA
*
* Stosowana przy:
* - Sprzedaży towarów używanych (komisy samochodowe)
* - Dzieł sztuki, przedmiotów kolekcjonerskich
* - Usług turystycznych (marża biura podróży)
*/
$invoiceHead = $udds->createInvoiceHead([
'issuePlace' => 'Warszawa',
'issueDate' => date('Y-m-d'),
'saleDate' => date('Y-m-d'),
'documentType' => 'FV',
// ═══════════════════════════════════════════════════════════════════
// SZABLON MARŻA
// ═══════════════════════════════════════════════════════════════════
'template' => 'MARZA',
'currency' => 'PLN',
'paymentMethod' => 'gotówka',
'buyerName' => 'Jan Kowalski',
'buyerAddress' => 'ul. Prywatna 5',
'buyerPostCode' => '00-001',
'buyerCity' => 'Warszawa',
'buyerNip' => '', // Osoba prywatna — bez NIP
'notes' => 'Procedura VAT-marża - towary używane',
]);
// Pozycja — cena to kwota brutto
$udds->createInvoiceItem([
'idInvoice' => $invoiceHead['id'],
'name' => 'Samochód używany - VW Golf 2020',
'quantity' => 100,
'unit' => 'szt.',
'vatRate' => '23', // VAT od marży (wewnętrznie)
'priceBrutto' => 4500000, // 45,000.00 PLN brutto
]);
Faktury zaliczkowe
Parametr: advanceType
System obsługuje pełny cykl zaliczek:
- Faktura zaliczkowa — przy wpłacie zaliczki
- Faktura końcowa — rozliczenie zaliczki z pozostałą kwotą
Workflow zaliczkowy
Przykład — cykl zaliczkowy
<?php
/**
* CYKL ZALICZKOWY
*
* Scenariusz:
* - Klient zamawia usługę za 10,000 PLN netto
* - Wpłaca zaliczkę 3,000 PLN netto
* - Po wykonaniu usługi wystawiamy fakturę końcową na 7,000 PLN
*/
// ═══════════════════════════════════════════════════════════════════════════════
// KROK 1: FAKTURA ZALICZKOWA (przy wpłacie)
// ═══════════════════════════════════════════════════════════════════════════════
$zaliczka = $udds->createInvoiceHead([
'issuePlace' => 'Warszawa',
'issueDate' => date('Y-m-d'),
'saleDate' => date('Y-m-d'),
'documentType' => 'FV',
'template' => 'VAT',
'currency' => 'PLN',
'paymentMethod' => 'przelew',
'advanceType' => 'Zaliczka', // ← TYP ZALICZKI
'buyerName' => 'Klient Sp. z o.o.',
'buyerNip' => '5213456789',
'buyerAddress' => 'ul. Biznesowa 10',
'buyerPostCode' => '00-001',
'buyerCity' => 'Warszawa',
]);
$udds->createInvoiceItem([
'idInvoice' => $zaliczka['id'],
'name' => 'Zaliczka na usługę programistyczną',
'quantity' => 100,
'unit' => 'szt.',
'vatRate' => '23',
'priceNetto' => 300000, // 3,000.00 PLN netto
]);
$udds->setInvoiceStatus(['idInvoice' => $zaliczka['id'], 'status' => 'AKTYWNA']);
echo "✅ Faktura zaliczkowa: {$zaliczka['number']}\n";
// ═══════════════════════════════════════════════════════════════════════════════
// KROK 2: FAKTURA KOŃCOWA (po wykonaniu usługi)
// ═══════════════════════════════════════════════════════════════════════════════
$koncowa = $udds->createInvoiceHead([
'issuePlace' => 'Warszawa',
'issueDate' => date('Y-m-d'),
'saleDate' => date('Y-m-d'),
'documentType' => 'FV',
'template' => 'VAT',
'currency' => 'PLN',
'paymentMethod' => 'przelew',
'advanceType' => 'Rozliczenie zaliczki', // ← ROZLICZENIE
'buyerName' => 'Klient Sp. z o.o.',
'buyerNip' => '5213456789',
'buyerAddress' => 'ul. Biznesowa 10',
'buyerPostCode' => '00-001',
'buyerCity' => 'Warszawa',
]);
// Pozycja za pełną usługę
$udds->createInvoiceItem([
'idInvoice' => $koncowa['id'],
'name' => 'Usługa programistyczna - projekt XYZ',
'quantity' => 100,
'unit' => 'szt.',
'vatRate' => '23',
'priceNetto' => 1000000, // 10,000.00 PLN (pełna wartość)
]);
// Pozycja odliczająca zaliczkę (WARTOŚĆ UJEMNA!)
$udds->createInvoiceItem([
'idInvoice' => $koncowa['id'],
'name' => 'Rozliczenie zaliczki z FV ' . $zaliczka['number'],
'quantity' => 100,
'unit' => 'szt.',
'vatRate' => '23',
'priceNetto' => -300000, // -3,000.00 PLN (minus!)
]);
// Do zapłaty: 10,000 - 3,000 = 7,000 PLN netto
$udds->setInvoiceStatus(['idInvoice' => $koncowa['id'], 'status' => 'AKTYWNA']);
echo "✅ Faktura końcowa: {$koncowa['number']}\n";
echo " Do zapłaty: 7,000.00 PLN netto + VAT\n";
Faktury korygujące
Parametr: documentType = 'FK'
Faktura korygująca (FK) poprawia błędy na fakturze pierwotnej
lub zmienia jej wartość (np. rabat, zwrot towaru).
Dla documentType = 'FK' musisz podać
relatedDocumentId — ID korygowanej faktury.
Przykład — korekta (zwrot towaru)
<?php
/**
* FAKTURA KORYGUJĄCA
*
* Scenariusz: Klient zwrócił 2 z 5 zakupionych produktów.
* Wystawiamy korektę zmniejszającą ilość.
*/
// ID faktury, którą korygujemy
$originalInvoiceId = '00000004M1G221031126JF1B44ASNQ6D';
// Pobierz dane oryginalnej faktury
$original = $udds->getInvoice(['idInvoice' => $originalInvoiceId]);
// ═══════════════════════════════════════════════════════════════════════════════
// TWORZENIE KOREKTY
// ═══════════════════════════════════════════════════════════════════════════════
$korekta = $udds->createInvoiceHead([
'issuePlace' => 'Warszawa',
'issueDate' => date('Y-m-d'),
'saleDate' => date('Y-m-d'),
// ═══════════════════════════════════════════════════════════════════
// TYP: FAKTURA KORYGUJĄCA
// ═══════════════════════════════════════════════════════════════════
'documentType' => 'FK',
'relatedDocumentId' => $originalInvoiceId, // ← WYMAGANE!
'template' => 'VAT',
'currency' => 'PLN',
'paymentMethod' => 'przelew',
// Dane nabywcy — takie same jak na oryginale
'buyerName' => $original['data']['invoice']['buyer']['name'],
'buyerNip' => $original['data']['invoice']['buyer']['nip'],
'buyerAddress' => $original['data']['invoice']['buyer']['address'],
'buyerPostCode' => $original['data']['invoice']['buyer']['postCode'],
'buyerCity' => $original['data']['invoice']['buyer']['city'],
'notes' => 'Korekta - zwrot towaru',
]);
// ═══════════════════════════════════════════════════════════════════════════════
// POZYCJE KOREKTY (wartości ujemne = zmniejszenie)
// ═══════════════════════════════════════════════════════════════════════════════
// Zwrot 2 sztuk produktu po 500 PLN netto
$udds->createInvoiceItem([
'idInvoice' => $korekta['id'],
'name' => 'Zwrot: Produkt XYZ (2 szt.)',
'quantity' => -200, // -2.00 szt. (ujemna ilość!)
'unit' => 'szt.',
'vatRate' => '23',
'priceNetto' => 50000, // 500.00 PLN/szt. (cena dodatnia)
]);
// Wartość pozycji: -2 × 500 = -1000 PLN netto
$udds->setInvoiceStatus(['idInvoice' => $korekta['id'], 'status' => 'AKTYWNA']);
echo "✅ Korekta: {$korekta['number']}\n";
echo " Kwota korekty: -1,000.00 PLN netto\n";
Słowniki wartości
Dozwolone wartości parametrów
API korzysta ze słowników wartości.
Podanie nieprawidłowej wartości zwróci błąd 1002.
Typy dokumentów (documentType)
| Kod | Nazwa | Uwagi |
|---|---|---|
FV | Faktura VAT | Standardowa faktura sprzedaży |
FK | Faktura Korygująca | Wymaga relatedDocumentId |
PRO | Pro-forma | Nie jest dokumentem księgowym |
Szablony (template)
| Kod | Opis |
|---|---|
VAT | Standardowa faktura VAT — pokazuje netto/brutto/VAT |
MARZA | VAT-marża — tylko kwota brutto, bez rozbicia VAT |
Stawki VAT (vatRate)
| Kod | Opis |
|---|---|
23 | Stawka podstawowa 23% |
8 | Stawka obniżona 8% |
5 | Stawka obniżona 5% |
0 | Stawka 0% (np. eksport) |
zw | Zwolniony z VAT |
np | Nie podlega VAT |
oo | Odwrotne obciążenie |
Jednostki miary (unit)
| Kod | Opis |
|---|---|
szt. | Sztuka |
kg | Kilogram |
mb | Metr bieżący |
m2 | Metr kwadratowy |
m3 | Metr sześcienny |
godz. | Godzina |
mies. | Miesiąc |
kpl. | Komplet |
usł. | Usługa |
l | Litr |
Metody płatności (paymentMethod)
| Kod | Opis |
|---|---|
przelew | Przelew bankowy |
gotówka | Gotówka |
karta | Karta płatnicza |
za pobraniem | Płatność przy odbiorze |
kompensata | Kompensata należności |
Typ zaliczki (advanceType)
| Kod | Opis |
|---|---|
(pusty) | Zwykła faktura (nie zaliczkowa) |
Zaliczka | Faktura zaliczkowa |
Rozliczenie zaliczki | Faktura końcowa rozliczająca |
Kody błędów
Referencja błędów API
createInvoiceHead
| Kod | Opis |
|---|---|
1001 | Brakuje wymaganego pola |
1002 | Nieprawidłowa wartość słownikowa |
1003 | Nieprawidłowy format daty (wymagany: YYYY-MM-DD) |
1004 | Nie znaleziono konta bankowego firmy |
1005 | Błąd sekwencji numeru faktury |
1006 | Nie znaleziono dokumentu źródłowego (dla FK) |
1007 | Błąd bazy danych |
createInvoiceItem
| Kod | Opis |
|---|---|
1001 | Brakuje wymaganego pola |
1002 | Nieprawidłowa wartość słownikowa (unit, vatRate) |
1003 | Faktura nie istnieje |
1004 | Faktura już wysłana do KSeF — nie można modyfikować |
1005 | Tryb manualny wymaga wszystkich pól wartości |
1006 | Błąd bazy danych |
sendInvoiceToKsef
| Kod | Opis |
|---|---|
1001 | Brak parametru idInvoice |
1002 | Faktura nie istnieje |
1003 | Brak konfiguracji KSeF Service |
1004 | Błąd połączenia z KSeF Service |
1005 | Błąd odpowiedzi KSeF Service |
KSeF Service (w ksefResponse.message)
| Kod | Opis |
|---|---|
REST-001 | Unauthorized — nieprawidłowy API key |
REST-003 | KSeF nie jest zainicjowany |
REST-011 | Brak rekordu w KSEF_FAKTURY |
REST-014 | Wyjątek systemowy |
Kompletny przykład
Cały proces w jednym skrypcie
Poniższy skrypt pokazuje pełny workflow: od utworzenia faktury do pobrania numeru KSeF. 📥 Pobierz plik PHP
<?php
/**
* ══════════════════════════════════════════════════════════════════════════════
* EASY INVOICE - KOMPLETNY PRZYKŁAD
* ══════════════════════════════════════════════════════════════════════════════
*
* Pełny workflow wystawiania faktury:
* 1. Utworzenie nagłówka
* 2. Dodanie pozycji
* 3. Aktywacja
* 4. Wysyłka do KSeF
* 5. Pobranie UPO i QR code
*/
require_once('classUddsOx.php');
// ══════════════════════════════════════════════════════════════════════════════
// KONFIGURACJA
// ══════════════════════════════════════════════════════════════════════════════
$udds = new classUddsOx();
$udds->customerCode = 'TWOJ_KOD';
$udds->login = 'login';
$udds->password = 'haslo';
$udds->serverUrl = 'https://api.dlaoperatora.pl/udds/';
$udds->timeout = 30;
echo "══════════════════════════════════════════════════════════════════\n";
echo " EASY INVOICE - Tworzenie faktury z wysyłką do KSeF\n";
echo "══════════════════════════════════════════════════════════════════\n\n";
// ══════════════════════════════════════════════════════════════════════════════
// KROK 1: UTWÓRZ NAGŁÓWEK FAKTURY
// ══════════════════════════════════════════════════════════════════════════════
echo "📄 KROK 1: Tworzenie nagłówka faktury...\n";
$invoiceHead = $udds->createInvoiceHead([
'issuePlace' => 'Warszawa',
'issueDate' => date('Y-m-d'),
'saleDate' => date('Y-m-d'),
'paymentMethod' => 'przelew',
'paymentDueDate'=> date('Y-m-d', strtotime('+14 days')),
'documentType' => 'FV',
'template' => 'VAT',
'currency' => 'PLN',
'buyerName' => 'Przykładowa Firma Sp. z o.o.',
'buyerNip' => '5213456789',
'buyerAddress' => 'ul. Testowa 123',
'buyerPostCode' => '00-001',
'buyerCity' => 'Warszawa',
'buyerCountry' => 'Polska',
'toKsef' => 1,
]);
if ($invoiceHead['status'] !== 'OK') {
die("❌ Błąd: " . $invoiceHead['errors'][0]['message'] . "\n");
}
$idInvoice = $invoiceHead['id'];
$invoiceNumber = $invoiceHead['number'];
echo " ✅ Utworzono: {$invoiceNumber}\n";
echo " ID: {$idInvoice}\n\n";
// ══════════════════════════════════════════════════════════════════════════════
// KROK 2: DODAJ POZYCJE
// ══════════════════════════════════════════════════════════════════════════════
echo "📦 KROK 2: Dodawanie pozycji...\n";
$items = [
['name' => 'Usługa programistyczna', 'qty' => 100, 'unit' => 'szt.', 'vat' => '23', 'price' => 500000],
['name' => 'Licencja oprogramowania', 'qty' => 100, 'unit' => 'szt.', 'vat' => '23', 'price' => 120000],
['name' => 'Wsparcie techniczne', 'qty' => 100, 'unit' => 'mies.','vat' => '23', 'price' => 50000],
];
$totalNetto = 0;
foreach ($items as $item) {
$result = $udds->createInvoiceItem([
'idInvoice' => $idInvoice,
'name' => $item['name'],
'quantity' => $item['qty'],
'unit' => $item['unit'],
'vatRate' => $item['vat'],
'priceNetto' => $item['price'],
]);
if ($result['status'] === 'OK') {
$netto = $result['calculatedValues']['valueNetto'] / 100;
$totalNetto += $netto;
echo " ✅ {$item['name']}: " . number_format($netto, 2) . " PLN\n";
}
}
echo " ────────────────────────────────\n";
echo " RAZEM NETTO: " . number_format($totalNetto, 2) . " PLN\n\n";
// ══════════════════════════════════════════════════════════════════════════════
// KROK 3: AKTYWUJ FAKTURĘ
// ══════════════════════════════════════════════════════════════════════════════
echo "✅ KROK 3: Aktywacja faktury...\n";
$activate = $udds->setInvoiceStatus([
'idInvoice' => $idInvoice,
'status' => 'AKTYWNA',
]);
if ($activate['status'] === 'OK') {
echo " ✅ Status: AKTYWNA\n\n";
} else {
die("❌ Błąd aktywacji\n");
}
// ══════════════════════════════════════════════════════════════════════════════
// KROK 4: WYŚLIJ DO KSEF
// ══════════════════════════════════════════════════════════════════════════════
echo "📤 KROK 4: Wysyłka do KSeF...\n";
$send = $udds->sendInvoiceToKsef(['idInvoice' => $idInvoice]);
if ($send['status'] === 'OK') {
echo " ✅ Wysłano do KSeF\n\n";
} else {
echo " ⚠️ Błąd: {$send['message']}\n\n";
}
// ══════════════════════════════════════════════════════════════════════════════
// KROK 5: POBIERZ STATUS, UPO, QR CODE
// ══════════════════════════════════════════════════════════════════════════════
echo "🔍 KROK 5: Weryfikacja statusu KSeF...\n";
sleep(2);
for ($i = 1; $i <= 5; $i++) {
$invoice = $udds->getInvoice(['idInvoice' => $idInvoice]);
$ksef = $invoice['data']['invoice']['ksef'] ?? [];
if (!empty($ksef['ksefNumber'])) {
echo "\n══════════════════════════════════════════════════════════════════\n";
echo " ✅ FAKTURA ZAREJESTROWANA W KSEF!\n";
echo "══════════════════════════════════════════════════════════════════\n\n";
echo "📋 Numer faktury: {$invoiceNumber}\n";
echo "📋 Numer KSeF: {$ksef['ksefNumber']}\n";
echo "📅 Data KSeF: {$ksef['invoicingDatetime']}\n";
if (!empty($ksef['upoLink'])) {
echo "\n📜 UPO: {$ksef['upoLink']}\n";
}
if (!empty($ksef['verificationUrl'])) {
echo "📱 QR: {$ksef['verificationUrl']}\n";
}
echo "\n══════════════════════════════════════════════════════════════════\n";
exit(0);
}
echo " Próba {$i}/5 - oczekiwanie...\n";
sleep(3);
}
echo "\n⏳ Faktura w przetwarzaniu. Sprawdź status później.\n";
echo " ID: {$idInvoice}\n";
Linki do pełnej dokumentacji
Szczegółowa dokumentacja wszystkich endpointów
Pełna dokumentacja API z opisem wszystkich parametrów dostępna jest pod adresem:
📚 https://api.dlaoperatora.pl/documentation/