Fakturnia Developers Szybki start Dokumentacja API English

Kontrahenci

Kontrahent to nabywca lub odbiorca na Twoich dokumentach. API udostępnia pełny CRUD pod /clients, a przy tworzeniu dokumentów możesz wskazać kontrahenta po id zamiast przesyłać jego dane za każdym razem.

Wymagane zakresy uprawnień: clients:browse, clients:read, clients:create, clients:update, clients:delete (osobno dla każdej operacji).

Lista kontrahentów

curl -s "https://prod.api.fakturnia.pl/external/v1/clients?searchQuery=Kowalski&currentPage=1&itemsPerPage=20" \
  -H "Authorization: Bearer $TOKEN"

searchQuery filtruje po nazwie. Lista jest paginowana: odpowiedź zawiera totalCount i totalPages.

Tworzenie kontrahenta

Kontrahent jest firmą (type: "company") albo osobą (type: "person"). Firma wymaga name, osoba wymaga firstName i lastName.

curl -s -X POST https://prod.api.fakturnia.pl/external/v1/clients \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "company",
    "name": "Przykład Sp. z o.o.",
    "identifierType": "nip",
    "nip": "5252248481",
    "street": "ul. Prosta 1",
    "postalCode": "00-001",
    "city": "Warszawa",
    "countryCode": "PL",
    "email": "biuro@przyklad.pl"
  }'

Pole identifierType mówi, którym identyfikatorem kontrahent jest wskazany w KSeF; zasady opisuje sekcja Identyfikatory kontrahenta.

Pozostałe pola są opcjonalne: regon, krs, bdo, pesel, idNumber, dane adresowe (street, postalCode, city, country, countryCode), kontaktowe (phoneNumber, email, emailAddresses, www, fax) oraz description.

Dane polskiej firmy możesz pobrać automatycznie z GUS przez wyszukiwanie po NIP, zamiast przepisywać je ręcznie.

Identyfikatory kontrahenta

Faktura w KSeF wskazuje nabywcę (i odbiorcę) dokładnie jednym identyfikatorem. identifierType wybiera, którym, a API sprawdza i zapisuje go w postaci, którą przyjmie KSeF. Te same zasady obowiązują kontrahentów (POST i PUT /clients) oraz nabywcę i odbiorcę podanych danymi przy tworzeniu dokumentów (POST /documents, POST /documents/validate, PUT i PATCH /documents/{id}).

identifierType Kontrahent Wymagane pola Przykład W KSeF
nip polska firma nip "nip": "5261040828" NIP
vatEu firma z innego kraju UE vatUE z prefiksem kraju kontrahent z Niemiec: "identifierType": "vatEu", "vatUE": "DE123456789" KodUE + NrVatUE
other firma spoza UE albo z UE bez numeru VAT UE countryCode, otherTaxIdentifier "countryCode": "US", "otherTaxIdentifier": "12-3456789" KodKraju + NrID
idWew jednostka wewnętrzna, tylko jako odbiorca dokumentu idWew "idWew": "5252248481-16006" IDWew
none osoba prywatna albo brak identyfikatora brak "type": "person" BrakID

Jak API zapisuje identyfikatory:

  • NIP to 10 cyfr: spacje, myślniki i prefiks PL są usuwane (PL 526-104-08-28 zapisuje się jako 5261040828), a cyfra kontrolna musi się zgadzać.
  • Numer VAT UE jest zapisywany w vatUE z prefiksem kraju, wielkimi literami i bez spacji (de 123 456 789 to DE123456789). Numer bez prefiksu dostaje prefiks z countryCode. Grecja ma w numerach VAT prefiks EL (podany GR zamieniamy na EL), a countryCode pozostaje GR. Po prefiksie dozwolone są cyfry, wielkie litery, + i *, od 1 do 12 znaków. Pole nip nigdy nie przechowuje zagranicznego numeru.
  • Polska firma z numerem VAT UE (np. do faktur WDT) ma identifierType: "nip", NIP w nip i PL z tym samym NIP-em w vatUE.
  • Irlandia Północna (XI) nie jest krajem UE w KSeF: podaj ją jako other z countryCode: "XI".
  • other wymaga kraju (countryCode, kod ISO, np. US, CH, GB, UA) i identyfikatora do 50 znaków; identyfikator zostaje zapisany tak, jak go podasz.
  • idWew ma postać NIP-NNNNN i przysługuje tylko odbiorcy: nabywca z idWew dostaje błąd.

Gdy nie podasz identifierType

API ustala typ z danych, a każde ustalenie zwraca w data.warnings, żeby integracja mogła zacząć wysyłać typ jawnie:

Dane Ustalony typ Co zapisuje API
nip z polskim NIP-em (10 cyfr, także z PL, spacjami albo myślnikami) nip NIP jako 10 cyfr
nip z numerem VAT UE kraju UE, np. DE123456789 vatEu numer w vatUE, pusty nip, countryCode z prefiksu, gdy brak
nip z numerem bez prefiksu i countryCode kraju UE innego niż Polska, np. 123456789 i DE vatEu vatUE = DE123456789
vatUE przy countryCode kraju UE innego niż Polska, albo sam vatUE z prefiksem kraju UE vatEu numer w vatUE
sam vatUE z prefiksem PL nip NIP z numeru VAT UE
nip albo vatUE z numerem kraju spoza UE (np. GB…, XI…) albo nip przy countryCode spoza UE other numer w otherTaxIdentifier
sam otherTaxIdentifier other bez zmian
sam idWew idWew bez zmian
brak identyfikatora none bez zmian

Polski NIP z błędną cyfrą kontrolną jest odrzucany także wtedy, gdy typ został ustalony.

Ostrzeżenia w odpowiedzi

POST i PUT /clients zwracają data.warnings obok data.client, a dokumenty obok data.document (przy validate obok data.preview). Lista jest pusta, gdy identyfikatory podano jawnie i poprawnie.

{
  "success": true,
  "data": {
    "client": { "identifierType": "vatEu", "nip": null, "vatUE": "DE123456789", "countryCode": "DE" },
    "warnings": [
      { "code": "IDENTIFIER_TYPE_INFERRED", "field": "identifierType", "message": "Nie podano identifierType: przyjęto vatEu (numer VAT UE). Podawaj identifierType jawnie." },
      { "code": "IDENTIFIER_MOVED", "field": "vatUE", "message": "Numer DE123456789 przeniesiono z pola nip do vatUE: pole nip jest tylko na polski NIP." },
      { "code": "COUNTRY_CODE_INFERRED", "field": "countryCode", "message": "Nie podano countryCode: przyjęto DE z prefiksu numeru VAT UE DE123456789." }
    ]
  }
}
code Znaczenie
IDENTIFIER_TYPE_INFERRED nie podano identifierType, API je ustaliło
IDENTIFIER_MOVED numer z niewłaściwego pola przeniesiono do vatUE albo otherTaxIdentifier
IDENTIFIER_IGNORED pole niepasujące do typu pominięto (np. nip przy vatEu)
COUNTRY_CODE_INFERRED countryCode przyjęto z prefiksu numeru
VAT_UE_PREFIX_NORMALIZED grecki prefiks GR zamieniono na EL

Przy dokumentach field ma prefiks strony, np. buyer.vatUE.

Sprzeczne dane

Sprzeczności API odrzuca z nazwą pola w errors: kontrahenci z kodem 422 VALIDATION_ERROR, dokumenty z kodem 422 PARTY_IDENTIFIER_INVALID (pole z prefiksem buyer. albo receiver.). Przykłady: identifierType: "nip" z numerem DE123456789, vatEu z numerem PL… albo XI…, numer VAT UE bez prefiksu i bez kraju UE, NIP o złej długości albo z błędną cyfrą kontrolną, różne numery VAT UE w nip i vatUE, other bez kraju, idWew u nabywcy, nieznana wartość identifierType.

Kontrahent zapisany wcześniej z danymi, których dziś API by nie przyjęło, pozostaje edytowalny: PUT nie sprawdza ponownie identyfikatorów równych zapisanym. Nabywca podany danymi z takim samym błędnym NIP-em jak zapisany kontrahent jest brany z kartoteki.

Pobieranie, aktualizacja i usuwanie

# Szczegóły
curl -s https://prod.api.fakturnia.pl/external/v1/clients/{id} \
  -H "Authorization: Bearer $TOKEN"

# Aktualizacja (PUT, pełne zastąpienie pól)
curl -s -X PUT https://prod.api.fakturnia.pl/external/v1/clients/{id} \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "type": "company", "name": "Przykład Sp. z o.o.", "email": "faktury@przyklad.pl" }'

# Usunięcie
curl -s -X DELETE https://prod.api.fakturnia.pl/external/v1/clients/{id} \
  -H "Authorization: Bearer $TOKEN"

PUT działa jak pełna aktualizacja: prześlij komplet pól, które kontrahent ma mieć po zmianie. Usunięcie kontrahenta nie zmienia wystawionych wcześniej dokumentów, dane nabywcy są na nich utrwalone.

Webhooki

Operacje zapisu emitują zdarzenia webhook: client.created, client.updated, client.deleted.