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.