KSeF Faktury
PL
Zapisz się na start
Wczesny dostęp

API jest we wczesnym dostępie: klucze testowe (KSeF TEST) wydajemy partiami osobom z listy startowej. Tryb produkcyjny włączymy później.

Poproś o dostęp

Przewodniki

WooCommerce i PrestaShop jako klienci API

Wtyczka dla WooCommerce korzysta z tego samego publicznego API co Ty. Dla PrestaShop pokazujemy, jak podłączyć sklep bezpośrednio.

WooCommerce: wtyczka KSeF Faktury

Wtyczka „KSeF Faktury for WooCommerce” to zwykły klient tego API. Przeszła testy na KSeF TEST (koszyk klasyczny i blokowy, zwroty, HPOS); do katalogu WordPress.org trafi po starcie, a uczestnicy wczesnego dostępu dostaną ją wcześniej.

  • Pole „Chcę fakturę VAT” i NIP z kontrolą sumy w koszyku klasycznym i blokowym. Potrafi też czytać NIP z istniejącego pola (np. _billing_nip, vat_number).
  • Po opłaceniu zamówienia z NIP wysyła je w tle (Action Scheduler) z Idempotency-Key i ponawia przy błędach sieci, 429 i 5xx. Za pobraniem wysyła po realizacji zamówienia.
  • Zwrot w WooCommerce zamienia w korektę.
  • W zamówieniu pokazuje status, numery faktur i KSeF oraz linki do PDF; kupujący widzi PDF na stronie zamówienia.
  • Wysyła tylko zamówienia z NIP i tylko potrzebne dane: bez adresu IP, przeglądarki, telefonu i id klienta.
  • Wymagania: PHP 7.4+, WooCommerce 8.9+, zgodność z HPOS.

Wtyczka wysyła zamówienie w formacie REST API WooCommerce v3 bez przerabiania. Tak samo możesz zrobić we własnym kodzie:

POST /v1/invoices
curl -X POST https://app.ksefshop.pl/v1/invoices \
  -H "Authorization: Bearer $KSEF_API_KEY" \
  -H "Idempotency-Key: woo-order-727" \
  -H "Content-Type: application/json" \
  -d '{
  "woocommerce_order": {
    "id": 727,
    "number": "727",
    "status": "processing",
    "currency": "PLN",
    "date_created_gmt": "2026-10-19T09:12:40",
    "date_paid_gmt": "2026-10-19T09:13:05",
    "billing": {
      "first_name": "Jan",
      "last_name": "Kowalski",
      "company": "Testowa Firma sp. z o.o.",
      "address_1": "ul. Prosta 20",
      "city": "Warszawa",
      "postcode": "00-850",
      "country": "PL",
      "email": "jan@example.com"
    },
    "payment_method": "cod",
    "meta_data": [
      {
        "key": "_ksef_buyer_nip",
        "value": "5260250274"
      }
    ],
    "line_items": [
      {
        "id": 41,
        "name": "Kubek ceramiczny 350 ml",
        "quantity": 2,
        "subtotal": "79.67",
        "subtotal_tax": "18.33",
        "total": "79.67",
        "total_tax": "18.33",
        "taxes": [
          {
            "id": 1,
            "total": "18.33"
          }
        ]
      }
    ],
    "tax_lines": [
      {
        "id": 51,
        "rate_id": 1,
        "rate_percent": 23
      }
    ],
    "shipping_lines": []
  }
}'

NIP odczytujemy z meta_data: _ksef_buyer_nip (pole wtyczki), pola koszyka blokowego, _billing_nip albo vat_number. Stawkę VAT bierzemy z tax_lines.rate_percent.

PrestaShop: bezpośrednio przez API

Gotowego modułu PrestaShop jeszcze nie ma. Do tego czasu sklep na PrestaShop łączy się z API bezpośrednio: po potwierdzeniu płatności (hook actionPaymentConfirmation) wysyła zamówienie w formacie neutralnym. Poniżej szkic modułu do dopracowania przez Twojego programistę.

Szkic modułu PrestaShop
<?php
// modules/ksefapi/ksefapi.php - szkic: opłacone zamówienia z NIP -> POST /v1/invoices
class KsefApi extends Module
{
    public function __construct()
    {
        $this->name = 'ksefapi';
        $this->version = '0.1.0';
        $this->author = 'Your company';
        parent::__construct();
        $this->displayName = 'KSeF Faktury API';
    }

    public function install()
    {
        return parent::install() && $this->registerHook('actionPaymentConfirmation');
    }

    public function hookActionPaymentConfirmation(array $params)
    {
        $order = new Order((int) $params['id_order']);
        $address = new Address((int) $order->id_address_invoice);
        if (trim((string) $address->vat_number) === '') {
            return; // konsument bez NIP: bez faktury w KSeF
        }
        $lines = [];
        foreach ($order->getProducts() as $p) {
            $lines[] = [
                'name' => $p['product_name'],
                'sku' => $p['product_reference'],
                'quantity' => (int) $p['product_quantity'],
                'unit_price' => number_format((float) $p['unit_price_tax_incl'], 2, '.', ''),
                'vat_rate' => (string) (int) round((float) $p['tax_rate']),
            ];
        }
        $shipping = [];
        if ((float) $order->total_shipping_tax_incl > 0) {
            $shipping[] = [
                'name' => (new Carrier((int) $order->id_carrier))->name,
                'price' => number_format((float) $order->total_shipping_tax_incl, 2, '.', ''),
                'vat_rate' => (string) (int) round((float) $order->carrier_tax_rate),
            ];
        }
        $payload = ['order' => [
            'external_id' => 'PS-' . $order->id,
            'number' => $order->reference,
            'paid_at' => gmdate('c'),
            'currency' => (new Currency((int) $order->id_currency))->iso_code,
            'buyer' => [
                'nip' => $address->vat_number,
                'name' => $address->company ?: trim($address->firstname . ' ' . $address->lastname),
                'address_line1' => $address->address1,
                'address_line2' => trim($address->postcode . ' ' . $address->city),
                'email' => (new Customer((int) $order->id_customer))->email,
            ],
            'lines' => $lines,
            'shipping' => $shipping,
        ]];

        // W produkcji wyślij w tle (kolejka/cron) i ponawiaj z tym samym kluczem.
        $ch = curl_init('https://app.ksefshop.pl/v1/invoices');
        curl_setopt_array($ch, [
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . Configuration::get('KSEFAPI_KEY'),
                'Idempotency-Key: order-PS-' . $order->id,
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
        ]);
        $invoice = json_decode((string) curl_exec($ch), true);
        curl_close($ch);
        if (isset($invoice['id'])) {
            Configuration::updateValue('KSEFAPI_INV_' . $order->id, $invoice['id']);
        }
    }
}

Co dopracować przed produkcją:

  • Wysyłka w tle (kolejka albo cron) z ponawianiem, zamiast wywołania w trakcie płatności. Wzór: idempotencja.
  • Rabaty koszykowe (cart rules) rozłóż na pozycje jako discount.
  • Zwroty (np. hook actionOrderSlipAdd) wysyłaj do POST /v1/invoices/{id}/corrections. Korekty
  • Numer KSeF i pdf_url zapisuj przy zamówieniu po zdarzeniu invoice.accepted. Webhooki

Inne systemy

API przyjmie zamówienie z każdego systemu, który wie, że zamówienie jest opłacone: własnego sklepu, ERP albo integracji z marketplace. Sklep na Shopify nie potrzebuje API: wystarczy aplikacja KSeF Faktury.

KSeF Faktury

Wczesny dostęp do API

Klucze testowe wydajemy partiami. Zostaw e-mail: napiszemy, gdy dostęp będzie gotowy.