Przewodnik integracji

Integracja KSeF API w Pythonie

Jak wysłać fakturę KSeF FA(3) z Pythona przez API Notaly (requests): POST /invoices, obsługa błędów i śledzenie statusu.

Aktualizacja

Wprowadzenie

Python sprawdzi się, gdy faktury KSeF wysyłasz z usługi backendowej, zadania cron albo potoku danych. Notaly odbiera słownik JSON, sam tworzy plik FA(3), sprawdza go względem oficjalnego schematu XSD i przekazuje do KSeF — Ty nie dotykasz XML-a ręcznie. Przykład opiera się na popularnej bibliotece requests, którą zainstalujesz przez pip install requests.

Przygotowanie

Po założeniu darmowego konta sandbox skopiuj klucz API z panelu. W sandboksie NIP sprzedawcy musi być równy 2745013933; każda inna wartość zostanie odrzucona z kodem 422 seller_nip_not_authorized, zanim faktura zostanie wliczona do limitu trzech darmowych faktur testowych. Klucz trzymaj w zmiennej środowiskowej (NOTALY_API_KEY), zamiast wpisywać go wprost w kodzie.

Wysyłka faktury

import os
import requests

NOTALY_API_KEY = os.environ["NOTALY_API_KEY"]

faktura = {
    "number": "FV/2026/10/001",
    "issueDate": "2026-10-12",
    "currency": "PLN",
    "seller": {"nip": "2745013933", "name": "Example Sp. z o.o. (FICTIONAL)", "address": {"line1": "ul. Testowa 1, 00-001 Warszawa", "country": "PL"}},
    "buyer": {"nip": "1234563218", "name": "Test Customer S.A. (FICTIONAL)", "address": {"line1": "ul. Probna 2, 30-001 Kraków", "country": "PL"}},
    "items": [
        {"name": "SaaS subscription - October", "unit": "pcs.", "quantity": 1, "unitNetPrice": 1000, "vatRate": 23},
        {"name": "Support", "unit": "hrs.", "quantity": 2, "unitNetPrice": 150.5, "vatRate": 8},
    ],
}

response = requests.post(
    "https://api.getnotaly.com/invoices",
    headers={"Authorization": f"Bearer {NOTALY_API_KEY}"},
    json=faktura,
    timeout=30,
)
response.raise_for_status()
utworzona = response.json()
print(f"Faktura {utworzona['id']} ma status {utworzona['status']}")

Argument json=faktura sam serializuje słownik i ustawia nagłówek Content-Type: application/json. timeout=30 chroni przed zawieszeniem żądania. W razie błędu HTTP raise_for_status() rzuca wyjątek, który możesz złapać i ponowić wysyłkę.

Odpowiedź i statusy

Serwer zwraca obiekt JSON z polami id i status. status to submitted, gdy KSeF przyjął zgłoszenie, albo draft, gdy KSeF był chwilowo niedostępny i faktura czeka na ponowienie. Zaakceptowana faktura zyskuje pola upo i pdfUrl. Notaly weryfikuje i wysyła fakturę; stawki VAT i klasyfikacja podatkowa pozostają po Twojej stronie.

Najczęstsze problemy

Zamiast analizować komunikaty, sprawdzaj pole error. validation_failed (422) przynosi listę details z informacją, które pole jest niepoprawne. quota_exceeded (402) oznacza, że limit trzech darmowych faktur sandbox został wyczerpany. ksef_unavailable (503) jest przejściowe — ponów z backoffem. Błędy uwierzytelniania to 401 (brak klucza lub błędny klucz) i 404 (poprawny klucz, ale cudzy zasób).

Śledzenie do końca

Status sprawdzisz przez GET /invoices/{id} z tym samym nagłówkiem Authorization albo przez webhooki. Faktura przechodzi kolejno draft → submitted → accepted lub rejected; odrzucona zawiera kod error, który warto zapisać w logu.

Źródła

Źródło: getnotaly.com

Najczęstsze pytania

Czy muszę coś instalować?

Tylko bibliotekę requests: pip install requests. Zalecany Python 3.8+.

Jak bezpiecznie ponawiać wysyłkę?

Wyślij nagłówek Idempotency-Key, żeby ta sama faktura nie powstała dwa razy.

Wystaw pierwszą fakturę testową w KSeF jeszcze dziś

Załóż konto sandbox: klucz API w kilka sekund, 3 darmowe faktury testowe w KSeF TEST, bez karty płatniczej.