Rejestry API → KRS API
API KRS Ministerstwa Sprawiedliwości: odpis aktualny w JSON
Krajowy Rejestr Sądowy ma publiczne, bezpłatne API pod adresem
api-krs.ms.gov.pl. Nie ma do niego oficjalnej dokumentacji
poza krótką notą na stronie ministerstwa, więc poniżej opisujemy je tak,
jak je zmierzyliśmy, pobierając przez nie ponad 780 tysięcy odpisów do
katalogu DebtStrike. Dalej: czego w nim brakuje i jak to uzupełnia nasze
KRS API po NIP, KRS lub REGON.
Jak wywołać api-krs.ms.gov.pl
| Element | Wartość | Uwagi |
|---|---|---|
OdpisAktualny / OdpisPelny |
ścieżka |
Aktualny to bieżący stan wpisów. Pełny zawiera też wpisy wykreślone,
czyli historię (np. byłych członków zarządu w
dzial2.reprezentacja). Obie odpowiedzi mają tę samą
strukturę.
|
{numerKRS} |
10 cyfr | Wyłącznie numer KRS, z wiodącymi zerami. API MS nie szuka po NIP ani REGON i nie ma wyszukiwarki po nazwie. |
rejestr |
P albo S |
P to rejestr przedsiębiorców, S to
stowarzyszenia, fundacje i inne organizacje. Podmiot jest w jednym z
nich; zapytanie do drugiego zwraca 404.
|
format |
json |
Bez parametru odpowiedź i tak przychodzi jako JSON. |
| uwierzytelnianie | brak | Bez klucza, bez rejestracji, bez nagłówków. |
Struktura odpowiedzi
{
"odpis": {
"rodzaj": "Aktualny",
"naglowekA": {
"rejestr": "RejP", "numerKRS": "0000934220",
"dataRejestracjiWKRS": "23.11.2021",
"dataOstatniegoWpisu": "…", "numerOstatniegoWpisu": 7,
"stanZDnia": "29.06.2026", "stanPozycji": 1,
"sygnaturaAktSprawyDotyczacejOstatniegoWpisu": "…"
},
"dane": {
"dzial1": { "danePodmiotu": { "nazwa": "…", "identyfikatory": { "nip": "…", "regon": "…" } },
"siedzibaIAdres": {…}, "umowaStatut": {…}, "kapital": {…}, "wspolnicySpzoo": […] },
"dzial2": { "reprezentacja": {…} },
"dzial3": { "przedmiotDzialalnosci": {…}, "wzmiankiOZlozonychDokumentach": {…},
"informacjaODniuKonczacymRokObrotowy": {…} },
"dzial4": {…}, "dzial5": {…}, "dzial6": {…}
}
}
}
Sześć działów odpowiada działom papierowego odpisu: 1 to tożsamość, adres,
umowa, kapitał i wspólnicy; 2 to reprezentacja i nadzór; 3 to PKD i
wzmianki o sprawozdaniach finansowych; 4 to zaległości i wierzytelności; 5
to kurator; 6 to likwidacja, upadłość, restrukturyzacja i połączenia. Daty
są w formacie DD.MM.RRRR, kwoty jako tekst z przecinkiem i
spacjami („50 000,00"), waluta osobno.
Co trzeba wiedzieć, zanim to wdrożysz
- 404 to nie awaria. Oznacza „nie ma podmiotu o tym numerze w tym rejestrze". Nasz dziennik przez pewien czas liczył zdrowe 404 jako błędy API; nie powtarzaj tego.
-
Odpowiedzi nie niosą żadnych nagłówków limitu
(
X-RateLimit-*,Retry-After) i ministerstwo nie publikuje limitu ani SLA. Zmierzone: ok. 55 ms na zapytanie, API wyrabia kilkanaście zapytań na sekundę. My pobieramy celowo wolniej, 5 zapytań/s, bo przy innym rejestrze bez opublikowanego limitu ta sama niewiadoma skończyła się dobową blokadą IP. -
Nie ma zrzutu ani listy podmiotów. Żeby zbudować bazę,
trzeba przelecieć przestrzeń numerów (najwyższe nadane numery są dziś
nieco powyżej
0001250000) i przyjąć 404 jako wynik. -
Numery KRS mają wiodące zera.
934220i0000934220to ten sam podmiot; waliduj wejście po swojej stronie. - Nazwiska w odpisie są jawne, ale bez PESEL; do beneficjentów rzeczywistych potrzebny jest osobny rejestr (CRBR).
KRS API DebtStrike: to samo źródło, po NIP, z cache
Nasz endpoint czyta ten sam odpis z Ministerstwa Sprawiedliwości i dokłada to, czego w źródle nie ma: mapowanie NIP i REGON na numer KRS, cache z datą stanu, jednolitą kopertę odpowiedzi wspólną z białą listą VAT, REGON i CRBR oraz jawne rozróżnienie „nie ma podmiotu" od „rejestr nie odpowiada".
| Parametr | Gdzie | Opis |
|---|---|---|
identifier |
ścieżka | NIP, KRS albo REGON. Most NIP→KRS robimy po swojej stronie (przez GUS, bez zużywania limitu MF). |
scope |
query |
aktualny (domyślnie) albo pelny — odpis
pełny zawiera historię wpisów.
|
fresh |
query | true pomija cache. Koszt ×3. |
certificate |
query | true wystawia certyfikat zapytania. |
Zawartość data: krs,
nip, regon, name,
legalForm, register, address,
contact, pkd, shareCapital,
representation, flags,
registrationDate, lastEntryDate,
lastFinancialStatement.
Przykład: podmiotu nie ma w rejestrze
{
"status": "not_found",
"subject": { "nip": null, "regon": null, "krs": "1132998955",
"countryCode": "PL", "resolvedVia": "direct" },
"data": null,
"meta": { "cache": { "hit": false }, "stale": false, "billed": 1 },
"timestamps": { "validAsOf": null },
"warnings": []
}
Uwaga na krótkie numery KRS. Numer KRS ma 10 cyfr z
wiodącymi zerami. /v1/krs/123 zostanie uzupełnione do
0000000123 i zwróci istniejącą spółkę — to poprawne
zachowanie rejestru, nie błąd. Jeśli przekazujesz dane od użytkownika,
waliduj po swojej stronie, czym one są.
Limity po naszej stronie: skoro MS nie publikuje limitu, przyjęliśmy własny ostrożny sufit 2000 zapytań na dobę do źródła i go mierzymy; trafienia w cache nie obciążają rejestru.
Przykład zapytania i odpowiedzi
Odpis aktualny spółki po numerze NIP. W ścieżce może stać NIP, KRS albo REGON, a parametr scope wybiera odpis aktualny (domyślnie) albo pełny.
curl -s "https://api.debtstrike.eu/v1/krs/7740001454?scope=aktualny" \
-H "Authorization: Bearer ds_test_TWOJ_KLUCZ"
Zapytanie działa z kluczem testowym ds_test_. Taki klucz zwraca stałe, syntetyczne dane podmiotu testowego (NIP 7740001454, KRS 0000028860, REGON 610188201), nie dotyka rejestrów i nie zdejmuje ani jednej jednostki pakietu ("billed": 0). Każdy inny numer zwraca status: not_found, więc przećwiczysz też tę ścieżkę. Z kluczem ds_live_ zmienia się tylko klucz, a dane są prawdziwe.
{
"status": "found",
"data": {
"krs": "0000028860",
"register": "RejP",
"name": "PODMIOT TESTOWY SPÓŁKA AKCYJNA (SANDBOX)",
"legalForm": "SPÓŁKA AKCYJNA",
"nip": "7740001454",
"regon": "61018820100000",
"registrationDate": "19.07.2001",
"lastEntryDate": "16.06.2026",
"address": { "street": "CHEMIKÓW", "building": "7", "flat": null,
"postalCode": "09-411", "city": "PŁOCK",
"voivodeship": "MAZOWIECKIE", "country": "POLSKA" },
"shareCapital": { "amount": 145117756125, "currency": "PLN" },
"pkd": { "main": "19.20.Z", "other": [] },
"representation": { "body": "ZARZĄD",
"rules": "DWAJ CZŁONKOWIE ZARZĄDU DZIAŁAJĄCY ŁĄCZNIE",
"members": [ { "role": "PREZES ZARZĄDU", "lastName": "T*****",
"firstName": "J**", "suspended": false } ] },
"flags": { "inLiquidation": false, "inBankruptcy": false,
"inRestructuring": false, "suspended": false, "dissolved": false },
"lastFinancialStatement": { "submittedAt": "16.06.2026",
"period": "01.01.2025 - 31.12.2025" }
},
"meta": { "billed": 0 }
}
Fragment odpowiedzi: pominięto koperty apiVersion, requestId, subject, source i timestamps oraz część pól adresu i pkd. Pełny kształt koperty opisuje strona przeglądowa.
Pola odpowiedzi w data
| Pole | Typ | Znaczenie |
|---|---|---|
krs |
string | Numer KRS, zawsze 10 cyfr z wiodącymi zerami. |
register |
string | Rejestr, z którego pochodzi odpis, tak jak podaje go Ministerstwo Sprawiedliwości (w przykładzie RejP). |
name |
string | Nazwa podmiotu z odpisu. |
legalForm |
string | Forma prawna z odpisu. |
nip, regon |
string | Identyfikatory podmiotu. REGON jest w postaci z odpisu i może mieć 14 cyfr. |
registrationDate, lastEntryDate |
string | Data wpisu do rejestru i data ostatniego wpisu, format DD.MM.RRRR jak w odpisie. |
address |
object | Adres siedziby: street, building, flat, postalCode, city, voivodeship, county, commune, country. |
contact |
object | email i website. Pola, których odpis nie zawiera, mają wartość null. |
shareCapital |
object | amount to liczba całkowita w groszach (w przykładzie 145117756125 to 1 451 177 561,25 zł), currency to waluta. |
pkd |
object | main i mainDescription to przeważająca działalność, other[] to pozostałe. |
representation |
object | body to organ, rules to sposób reprezentacji, members[] zawiera role, firstName, lastName, suspended. Rejestr maskuje część znaków imion i nazwisk (np. T*****). |
flags |
object | Znaczniki logiczne: inLiquidation, inBankruptcy, inRestructuring, suspended, dissolved. |
lastFinancialStatement |
object | submittedAt to data złożenia, period to okres, którego dotyczy sprawozdanie. |
Odpowiedzi i błędy tego endpointu
| HTTP | Kod lub status |
Kiedy |
|---|---|---|
| 200 | found |
Odpis znaleziony. W data są pola z tabeli wyżej. |
| 200 | not_found |
Rejestr odpowiedział, że nie ma takiego podmiotu. To fakt, na którym wolno oprzeć decyzję. |
| 200 | unavailable |
Rejestr nie odpowiedział. To brak wiedzy, nie dowód braku podmiotu. |
| 400 | invalid_identifier |
Identyfikator nie jest NIP-em, KRS-em ani REGON-em. |
| 403 | source_not_in_plan |
Klucz nie ma zakresu krs. |
| 422 | unsupported_parameter |
Parametr scope inny niż aktualny albo pelny. |
Pozostałe kody (401, 429, 500) są wspólne dla wszystkich źródeł i opisane w
tabeli błędów. Błędy mają format application/problem+json (RFC 9457) z polami code i requestId.
Pozostałe rejestry w tym samym API
Wszystkie źródła mają tę samą kopertę, ten sam sposób uwierzytelniania i te same kody błędów:
- API białej listy VAT: status podatnika i weryfikacja rachunku
- API REGON / GUS: tożsamość, adres i PKD
- CRBR API: beneficjenci rzeczywiści
- BZP API: postępowania publiczne
- SUDOP API: pomoc publiczna i de minimis
- Agregat podmiotu: REGON, VAT i KRS jednym zapytaniem
Zanim wyślesz pierwsze zapytanie
Zasady wspólne dla wszystkich źródeł opisuje strona przeglądowa:
uwierzytelnianie kluczem,
koperta odpowiedzi,
różnica między not_found a unavailable, rozliczenie zapytań i
limity. Pełny kontrakt:
/v1/openapi.json.