Weryfikacja kontrahenta to w Polsce nie fanaberia, tylko element należytej staranności — status VAT i zgodność rachunku z Białą Listą wprost wpływają na to, czy zaliczysz koszt i odliczysz VAT. Problem w tym, że oficjalne źródła (Ministerstwo Finansów, Ministerstwo Sprawiedliwości, GUS, Komisja Europejska) mają rozproszone, różniące się między sobą API. Poniżej pokazuję, jak sprowadzić to do kilku wywołań HTTP, które zwracają czysty JSON — z poziomu curl
, Pythona i agenta AI mówiącego protokołem MCP.
Wszystkie przykłady korzystają z skanfirmy.pl — zestawu narzędzi do weryfikacji firm po NIP/KRS/REGON oraz unijnego VAT (VIES). Dane pochodzą wprost z oficjalnych rejestrów, endpointy są bez opłat i bez rejestracji (bez klucza API), a warstwa webowa działa client-side, bez trackingu.
Najprostszy przypadek — sprawdzenie NIP-u. Endpoint jest publiczny, metoda GET
, odpowiedź to JSON:
curl https://skanfirmy.pl/nip/5260250995
W odpowiedzi dostaniesz m.in. status VAT (czynny/zwolniony/niezarejestrowany), dane podmiotu z Wykazu VAT oraz rachunki figurujące na Białej Liście. Dostępne ścieżki:
GET /nip/{nip}
— status VAT i dane z Białej Listy dla jednego NIP-uGET /nips/{lista}
— kilka NIP-ów naraz (lista rozdzielona przecinkami)GET /regon/{nip}
— dane z rejestru REGON (GUS)GET /vies/{country}/{number}
— walidacja unijnego numeru VAT (np. /vies/DE/811128135
)Ponieważ to zwykły GET zwracający JSON, wpina się bez ceremonii w dowolny pipeline — cron, funkcję serverless, hook w CI, cokolwiek co potrafi zrobić request HTTP.
Z biblioteką requests
całość mieści się w kilku linijkach. Poniżej minimalna funkcja, która sprawdza status VAT i sygnalizuje wyjątkiem, gdy podmiot nie jest czynnym płatnikiem:
import requests
def sprawdz_vat(nip: str) -> dict:
r = requests.get(f"https://skanfirmy.pl/nip/{nip}", timeout=10)
r.raise_for_status()
dane = r.json()
status = dane.get("vatStatus") or dane.get("status")
if status != "Czynny":
raise ValueError(f"NIP {nip}: status VAT = {status!r}")
return dane
wynik = sprawdz_vat("5260250995")
print("Rachunki na Białej Liście:", wynik.get("accountNumbers", []))
Jedna uwaga na dobre praktyki: literały zwracane przez rejestry MF ("Czynny"
, "Zwolniony"
) traktuj jako wartości kanoniczne — porównuj się do oryginału, a ewentualne tłumaczenie zostaw wyłącznie na warstwę prezentacji. Dzięki temu logika nie rozjedzie się przy zmianie języka interfejsu.
Masę NIP-ów do przetworzenia hurtowo? Do jednorazowego batcha z eksportem CSV/JSON jest webowe /bulk, a programistycznie ten sam efekt osiągniesz przez GET /nips/{lista}
.
Tu robi się ciekawie. Kluczowy wyróżnik skanfirmy.pl to pełna dostępność dla agentów: pod https://skanfirmy.pl/mcp
stoi serwer Model Context Protocol z 9 narzędziami — również bez klucza API. Agent (np. asystent księgowy) może wywołać weryfikację NIP-u tak samo, jak człowiek klika w formularz.
MCP mówi po JSON-RPC 2.0 przez POST
. Wywołanie konkretnego narzędzia to metoda tools/call
:
curl -X POST https://skanfirmy.pl/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "sprawdz_nip",
"arguments": { "nip": "5260250995" }
}
}'
Listę narzędzi z ich schematami wejścia zwróci tools/list
(ta sama koperta, inna method
). Dla agentów, które wolą samo REST, jest jeszcze https://skanfirmy.pl/llms.txt
— mapa endpointów i sposobu użycia w formacie czytelnym dla modeli. Chcąc iść szerzej niż polskie rejestry, zajrzyj do serwisu siostrzanego otwarteapi.pl — katalogu publicznych API (polskich i światowych) pod kątem agentów AI.
Status VAT kontrahenta czy jego rachunek na Białej Liście potrafią zmienić się z dnia na dzień — a jednorazowy check tego nie wychwyci. Dlatego jest /monitoring: codzienne alerty o zmianie statusu VAT lub rachunku, z powiadomieniem push przez webhook podpisany HMAC. W praktyce dopinasz endpoint u siebie, weryfikujesz podpis nagłówka i reagujesz — bez odpytywania rejestrów w pętli.
Cały serwis jest dwujęzyczny. Angielskie odpowiedniki stron żyją pod prefiksem /en/
(np. https://skanfirmy.pl/en/
), a endpointy REST i MCP są językowo neutralne — działają identycznie niezależnie od tego, po której stronie interfejsu jesteś.
Podsumowując: trzy warstwy, jedno źródło danych. curl
/GET do szybkiego sprawdzenia, requests
do wpięcia w kod, MCP do agenta — wszystko zwraca JSON, bez rejestracji i bez klucza API. Reszta to już Twój pipeline.