OBIEQ

API OBIEQ

Adres: https://app.obieq.pl/api/v1

OBIEQ wystawia faktury na podstawie danych z Twojego systemu i przejmuje numerację, wysyłkę do KSeF oraz pilnowanie terminów ustawowych.

Nazwy pól są angielskie, tak samo jak w API Krajowego Systemu e-Faktur.


Środowisko testowe

Integrację sprawdza się w osobnym środowisku, nie na firmie produkcyjnej.

⚠ Faktura przyjęta przez KSeF nie może zostać anulowana — jedyną drogą jest korekta, a numer w serii pozostaje zajęty.

Środowisko zakłada się w panelu: Klucze API → Załóż środowisko testowe. Powstaje wtedy bliźniacza firma z tymi samymi danymi sprzedawcy, własną numeracją i dokumentami bez znaczenia prawnego. PDF-y są oznaczone napisem „DOKUMENT TESTOWY".

Środowisko wynika z klucza:

klucz działanie
obq_test_… dokumenty testowe
obq_… dokumenty produkcyjne

⚠ Nie ma parametru przełączającego tryb w treści żądania. Wartość zapomniana w konfiguracji oznaczałaby albo faktury nieistniejące mimo potwierdzenia, albo dokumenty produkcyjne wystawione podczas testów.

Środowisko nieużywane przez 3 miesiące jest usuwane po wcześniejszym powiadomieniu mailem.


Uwierzytelnianie

Authorization: Bearer obq_klucz

Klucze wydaje się w panelu (Klucze API). Wartość klucza jest pokazywana jednorazowo — w bazie przechowywany jest wyłącznie skrót.

Firma jest ustalana na podstawie klucza i nie występuje w adresie ani w treści żądania.


Wystawienie faktury

POST /api/v1/faktury
Authorization: Bearer obq_klucz
Idempotency-Key: order-4821
Content-Type: application/json
{
  "buyer": {
    "name": "Przedszkole nr 3",
    "tax_id": "1132191233",
    "street": "Kwiatowa 5",
    "city": "Warszawa",
    "postal_code": "00-001",
    "email": "biuro@przedszkole3.pl"
  },
  "lines": [
    {
      "name": "Wizyta Mikołaja",
      "quantity": 2,
      "unit_net_cents": 30000,
      "vat_rate": "23",
      "unit": "szt.",
      "classification": "85.59.19.0"
    }
  ],
  "issue_date": "2026-09-03",
  "sale_date": "2026-09-03",
  "due_date": "2026-09-17",
  "series": "FV"
}

Wymagane są buyer.name oraz lines. Bez series dokument trafia do serii faktur sprzedaży, bez dat — przyjmowana jest data bieżąca.

Idempotency-Key

Nagłówek jest wymagany, a jego wartość musi być unikalna dla każdego dokumentu (np. identyfikator zamówienia).

⚠ Ponowienie żądania po przekroczeniu czasu oczekiwania jest standardowym zachowaniem bibliotek HTTP. Bez klucza idempotencji powstałyby dwie faktury z odrębnymi numerami dokumentujące tę samą sprzedaż.

sytuacja odpowiedź
ten sam klucz, ta sama treść ta sama faktura, ten sam numer
ten sam klucz, żądanie w toku 409
ten sam klucz, inna treść 409
poprzednia próba zakończona błędem klucz zwolniony, można ponowić

Klucz zabezpiecza przed powstaniem drugiego dokumentu, nie przed ponowną próbą.

Kwoty

Kwoty przekazuje się wyłącznie w groszach, jako liczby całkowite (unit_net_cents: 30000 odpowiada 300,00 zł).

⚠ Liczby zmiennoprzecinkowe w JSON-ie podlegają zaokrągleniom binarnym (300.00 bywa odczytane jako 299.99999), co prowadzi do rozbieżności groszowych między zamówieniem a fakturą.

Sumy dokumentu wylicza serwer na podstawie pozycji; wartości przekazane w żądaniu są pomijane.

Rabaty

Rabat podaje się na pozycji, jako kwotę albo procent:

{
  "name": "Wizyta Mikołaja",
  "quantity": 2,
  "unit_net_cents": 30000,
  "vat_rate": "23",
  "discount_cents": 6000
}

albo

{ "discount_percent": 10 }

⚠ Pola wykluczają się wzajemnie — podanie obu kończy się kodem 422.

unit_net_cents pozostaje ceną katalogową. Rabat pomniejsza wartość pozycji, a VAT jest liczony od kwoty po obniżce.

Dla przykładu powyżej: 2 × 300,00 = 600,00, rabat 60,00, wartość netto 540,00, VAT 124,20.

Rabat procentowy jest przeliczany na kwotę w chwili wystawienia i tak zapisywany. Na dokumencie widnieje jako osobna informacja przy pozycji, a do KSeF trafia w polu P_10 schematu FA(3).

⚠ Rabat nie może przekraczać wartości pozycji. Rabat od całości dokumentu nie jest obsługiwany — należy rozłożyć go na pozycje.

Odpowiedź

201 Created

{
  "data": {
    "id": 128,
    "number": "FV/17/09/2026",
    "status": "issued",
    "issue_date": "2026-09-03",
    "buyer": { "name": "Przedszkole nr 3", "tax_id": "1132191233", "email": null },
    "total_net_cents": 60000,
    "total_vat_cents": 13800,
    "total_gross_cents": 73800,
    "currency": "PLN",
    "pdf_url": "https://app.obieq.pl/api/v1/faktury/128/pdf",
    "ksef": { "required": true, "number": null },
    "delivery": {
      "sent_by": "client_system",
      "send_it_yourself": true,
      "sent_at": null,
      "sent_to": null
    }
  }
}

⚠ Pole delivery.send_it_yourself określa, czy wiadomość do nabywcy wysyła Twój system, czy OBIEQ. Zignorowanie go prowadzi do braku wysyłki albo do podwójnej wysyłki od dwóch różnych nadawców.

ksef.number jest początkowo null. Wystawienie dokumentu nie czeka na odpowiedź KSeF — przesłanie do rejestru ma odrębny termin ustawowy, a oczekiwanie na nie uzależniałoby sprzedaż od dostępności systemu Ministerstwa.


Odczyt

metoda adres opis
GET /api/v1/faktury lista, ?per_page= do 100
GET /api/v1/faktury/{id} dokument z pozycjami
GET /api/v1/faktury/{id}/pdf plik PDF

Numer KSeF pojawia się w ksef.number, zwykle w ciągu kilkunastu sekund od wystawienia. Wysyłką, ponawianiem i terminami zarządza OBIEQ.


Limity

operacja limit
POST /faktury 60 / minutę i 600 / godzinę
odczyt 300 / minutę

Limity są liczone dla klucza, nie dla adresu IP.

⚠ KSeF przyjmuje 180 faktur na godzinę dla jednego NIP-u. Powyżej tego tempa dokumenty oczekują w kolejce niezależnie od limitów API.

Odpowiedź 429 oznacza przekroczenie chwilowego limitu. Żądanie można ponowić z tym samym Idempotency-Key.


Stan usługi

GET /api/v1/stan

Nie wymaga klucza. Odpowiada {"stan":"ok"} albo kodem 503.


Kody odpowiedzi

kod znaczenie
201 faktura wystawiona
400 brak nagłówka Idempotency-Key
401 nieprawidłowy lub odwołany klucz
409 konflikt klucza idempotencji
422 nieprawidłowe dane żądania
429 przekroczony limit zapytań
503 usługa niedostępna

Opis błędu znajduje się w polu error.

Czegoś tu brakuje albo coś nie działa tak, jak napisano? Napisz na kontakt@obieq.pl — dokumentacja jest częścią produktu, więc jej błąd traktujemy jak każdy inny.