Dla programistów
Dokumentacja API Atlasu Przetargów
Te same dane, które widzisz w wyszukiwarce, w formie JSON: ogłoszenia z BZP i TED (ponad 950 tys. rekordów), profile zamawiających i wykonawców, wyroki Krajowej Izby Odwoławczej powiązane z przetargami oraz umowy z Centralnego Rejestru Umów. Bez klucza do przeglądania, z darmowym kluczem do integracji.
Ostatnia aktualizacja: 5 września 2026
Adres bazowy
https://atlasprzetargow.pl/api
Format
JSON, UTF-8, tylko GET
Uwierzytelnianie
nagłówek X-Api-Key (opcjonalny)
Licencja danych
CC BY 4.0 z podaniem źródła
Szybki start
Pierwsze zapytanie nie wymaga rejestracji. Pobierz 5 najnowszych ogłoszeń budowlanych z Mazowsza:
curl "https://atlasprzetargow.pl/api/tenders?cpv=45&province=PL14&per_page=5"
Z kluczem (większa pula i rozliczanie per klucz, nie per adres IP) dodaj nagłówek X-Api-Key:
curl "https://atlasprzetargow.pl/api/tenders?noticeKind=opening&dateFrom=2026-09-01&sort=newest&per_page=200" \ -H "X-Api-Key: atlas_TWOJ_KLUCZ" \ -H "User-Agent: moja-firma-sync/1.0 (kontakt@moja-firma.pl)"
Ten sam pobór w Pythonie:
import requests
session = requests.Session()
session.headers.update({
"X-Api-Key": "atlas_TWOJ_KLUCZ",
"User-Agent": "moja-firma-sync/1.0 (kontakt@moja-firma.pl)",
})
page = 1
while True:
resp = session.get(
"https://atlasprzetargow.pl/api/tenders",
params={"noticeKind": "opening", "dateFrom": "2026-09-01", "sort": "newest",
"per_page": 200, "page": page},
timeout=30,
)
resp.raise_for_status()
body = resp.json()
for tender in body["data"]:
print(tender["id"], tender["title"])
print("zostało dziś:", resp.headers.get("X-RateLimit-Remaining"))
if page >= body["pages"]:
break
page += 1Klucz i limity
Limity liczymy na dobę (doba UTC, reset o 00:00 UTC, czyli 02:00 czasu polskiego latem i 01:00 zimą). Niezależnie od tego obowiązuje limit chwilowy 500 wywołań na minutę na adres IP.
| Tryb | Limit dobowy | Dla kogo |
|---|---|---|
| Bez klucza | 1 500 wywołań na adres IP | Przeglądanie, testy, jednorazowe skrypty. |
| Klucz darmowy | 5 000 wywołań na klucz | Integracje, codzienna synchronizacja, narzędzia wewnętrzne. Do 3 aktywnych kluczy na konto. |
| Limit indywidualny | wg ustaleń | Większe limity i feed dzienny (pełny zrzut zamiast paginacji): napisz na kontakt@atlasprzetargow.pl. |
Klucz tworzysz w Moje konto, zakładka API. Pokazujemy go tylko raz, zaraz po utworzeniu; potem widzisz wyłącznie jego początek i dzisiejsze zużycie. Klucz przekazuj w nagłówku X-Api-Key. Parametr ?api_key= też działa, ale klucz ląduje wtedy w logach i historii przeglądarki, więc traktuj go jako wyjście awaryjne.
Każda odpowiedź z danymi niesie nagłówki stanu limitu:
| Parametr | Opis | Przykład |
|---|---|---|
| X-RateLimit-Limit | Pula dobowa dla tego wywołania. | 5000 |
| X-RateLimit-Remaining | Ile wywołań zostało do końca doby. | 4871 |
| X-RateLimit-Reset | Moment resetu (unix epoch, sekundy, UTC). | 1757116800 |
| X-RateLimit-Scope | anonymous (per IP), key (per klucz) albo session (zalogowana przeglądarka). | key |
Odpowiedzi z cache (zwykłe przeglądanie stron, nagłówek X-Cache-Status: HIT) nie zużywają puli. Wywołania z klientów programistycznych i wszystkie wywołania z kluczem zawsze trafiają do serwera i są liczone.
Kody błędów
Błędy zwracamy jako JSON z polem error (stały identyfikator) i message po polsku.
| Parametr | Opis | Przykład |
|---|---|---|
| 400 | Zły parametr. Body: error, field, hint, got. | sort=xyz |
| 401 | invalid_api_key: nieznany klucz; api_key_revoked: klucz cofnięty w koncie. | |
| 404 | Nie ma takiego ogłoszenia, podmiotu, orzeczenia albo umowy. | |
| 422 | Sortowanie po wartości bez jednego zakresu (noticeKind=opening albo result). | sort=value_desc |
| 429 | quota_exceeded: wyczerpana pula dobowa (patrz niżej) albo limit minutowy. Zawsze z nagłówkiem Retry-After. | |
| 503 | Dane wartości w trakcie publikacji (zwykle kilka minut w nocy). Powtórz później. |
Przykład odpowiedzi 429 po wyczerpaniu puli:
HTTP/1.1 429 Too Many Requests
Retry-After: 21600
X-RateLimit-Limit: 1500
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1757116800
X-RateLimit-Scope: anonymous
{
"error": "quota_exceeded",
"scope": "anonymous",
"limit": 1500,
"resets_at": "2026-09-06T00:00:00Z",
"retry_after": 21600,
"message": "Przekroczono dobowy limit 1500 wywołań bez klucza dla tego adresu IP. ...",
"docs": "https://atlasprzetargow.pl/dokumentacja-api"
}Przetargi (BZP, TED, Baza Konkurencyjności)
/api/tendersLista ogłoszeń z filtrami wyszukiwarki. Bez noticeKind, noticeType ani search lista obejmuje tylko ogłoszenia otwierające postępowanie (to, co widać na stronie głównej). Duplikaty (to samo postępowanie w BZP i TED) są domyślnie scalone.
| Parametr | Opis | Przykład |
|---|---|---|
| search | Fraza pełnotekstowa (tytuł, zamawiający, opis). Tolerancja literówek, odmiana. Z frazą lista zawiera wszystkie rodzaje ogłoszeń, otwierające postępowanie na początku. | search=remont dachu |
| city | Miasto (nazwa). Kilka wartości po przecinku. | city=Gdańsk |
| province | Województwo: kod PL14 albo nazwa. Kilka po przecinku. | province=PL14 |
| powiat | Powiat (nazwa). | powiat=wołomiński |
| cpv | Kod CPV: prefiks działu (2 cyfry), grupy lub pełny kod. Kilka po przecinku. | cpv=45,48 |
| noticeKind | opening (ogłoszenia otwierające postępowanie, domyślnie) albo result (ogłoszenia o wyniku). | noticeKind=result |
| noticeType | Konkretny rodzaj ogłoszenia, np. ContractNotice, TenderResultNotice. Zwykle wystarczy noticeKind. | noticeType=ContractNotice |
| orderKind | works, supplies, services. Kilka po przecinku. | orderKind=works |
| tenderType | Tryb postępowania (symbol z BZP/TED, jak w filtrach wyszukiwarki). | tenderType=podstawowy |
| clientType | Rodzaj zamawiającego: kody słownika BZP (cyfry i kropki), lista po przecinku. | clientType=1.1.2 |
| source | bzp, ted, bk (Baza Konkurencyjności). Kilka po przecinku. | source=ted |
| dateFrom / dateTo | Zakres dat YYYY-MM-DD (włącznie). | dateFrom=2026-09-01 |
| dateField | Którego pola dotyczy zakres: published (domyślnie) albo deadline. | dateField=deadline |
| onlyActive | true: tylko ogłoszenia z terminem składania ofert w przyszłości. | onlyActive=true |
| minValue / maxValue | Wartość szacunkowa (PLN, liczba bez separatorów). | minValue=500000 |
| hasDeposit, depositMin, depositMax | Wadium: obecność (true/false) i zakres kwoty w PLN. | hasDeposit=true |
| offersMin / offersMax | Liczba ofert (dla ogłoszeń o wyniku). | offersMin=3 |
| buyer_nip | NIP zamawiającego (10 cyfr). | buyer_nip=5250001616 |
| contractor_nip | NIP wykonawcy; zwraca ogłoszenia o wyniku, w których wygrał. | contractor_nip=... |
| euFunded | true: postępowania z dofinansowaniem UE. | euFunded=true |
| excludeCancelled | true: pomiń unieważnione. | excludeCancelled=true |
| include_duplicates | true: nie odfiltrowuj duplikatów (np. to samo ogłoszenie w BZP i TED). | include_duplicates=true |
| sort | newest (domyślnie), oldest, deadline, title, title_desc, relevance (z frazą), value_desc, value_asc (wymaga jednego zakresu: noticeKind=opening albo result). | sort=deadline |
| page / per_page | Stronicowanie. per_page maksymalnie 200 (domyślnie 50). | page=2&per_page=200 |
Kształt odpowiedzi
{
"data": [
{
"id": "2026/BZP 00412345/01",
"title": "Remont dachu budynku szkoły podstawowej",
"buyer": "Gmina Przykładowo",
"buyerNip": "5250001616",
"buyerSlug": "n5250001616-gmina-przykladowo",
"buyerProfileHref": "/podmiot/zamawiajacy/n5250001616-gmina-przykladowo",
"city": "Przykładowo",
"province": "PL14",
"cpvCode": "45261000-4, 45453000-7",
"noticeType": "ContractNotice",
"tenderType": "Zamówienie udzielane jest w trybie podstawowym ...",
"date": "2026-09-04",
"submittingOffersDate": "2026-09-19T10:00:00",
"estimatedValue": null,
"currency": "PLN",
"depositAmount": 15000.0,
"offersCount": null,
"procedureResult": null,
"contractorName": null,
"contractors": [],
"source": "bzp",
"tedNumber": null,
"noticeUrl": "https://ezamowienia.gov.pl/mo-client-board/bzp/notice-details/...",
"latitude": 52.23,
"longitude": 21.01
}
],
"total": 18342,
"page": 1,
"pages": 92,
"per_page": 200,
"meta": { "total": 18342 }
}/api/tenders/{id}Pełny rekord ogłoszenia: pola z listy plus opis przedmiotu, kryteria oceny, warunki udziału, wykonawcy z wyniku, powiązane ogłoszenia (zmiany, wynik) i odnośnik do źródła. Identyfikator to numer BZP (np. 2026/BZP 00412345/01, zakoduj spację jako %20) albo numer TED (np. 512345-2026).
/api/tenders/{id}/rulingsWyroki KIO dotyczące tego postępowania.
/api/tenders/{id}/agreementsUmowy z Centralnego Rejestru Umów powiązane z tym postępowaniem.
Zamawiający i wykonawcy
Profile liczone z ogłoszeń: liczba postępowań, wartości, najczęstsze kody CPV, partnerzy. Identyfikatorem jest NIP (10 cyfr, bez myślników). Parametry dateFrom i dateTo zawężają okres statystyk.
/api/buyers/{nip}Profil zamawiającego: statystyki, ostatnie ogłoszenia, struktura CPV, wygrywający wykonawcy.
/api/contractors/{nip}Profil wykonawcy: wygrane postępowania, zamawiający, wartości, konkurencja w wygranych.
/api/buyers/{nip}/winning-contractorsRanking wykonawców wygrywających u tego zamawiającego.
/api/contractors/{nip}/winning-buyersZamawiający, u których ten wykonawca wygrywa najczęściej.
/api/entities/{nip}/rulingsWyroki KIO, w których podmiot był stroną.
/api/entities/{nip}/agreementsUmowy podmiotu z Centralnego Rejestru Umów.
Dane osób fizycznych prowadzących działalność publikujemy w zakresie zminimalizowanym (miejscowość i województwo zamiast adresu). Szczegóły w metodologii.
Wyroki KIO
Orzeczenia Krajowej Izby Odwoławczej sparsowane z PDF: sygnatury, strony, skład, rozstrzygnięcie, artykuły PZP, koszty, powiązanie z ogłoszeniem BZP/TED. Każde orzeczenie linkuje do przetargu i odwrotnie.
/api/kio| Parametr | Opis | Przykład |
|---|---|---|
| search | Fraza pełnotekstowa (sygnatura, przedmiot, strony, treść uzasadnienia). | search=rażąco niska cena |
| outcome | oddalono, uwzglednione, odrzucono, umorzono, inne. | outcome=uwzglednione |
| ruling_kind | wyrok albo postanowienie. | ruling_kind=wyrok |
| date_from / date_to | Data orzeczenia, ISO. | date_from=2026-01-01 |
| law_article | Artykuł PZP: dokładny albo prefiks (np. „art. 226” łapie „art. 226 ust. 1 pkt 5 Pzp”). | law_article=art. 226 |
| chairperson | Przewodniczący składu (fragment nazwiska). | |
| party | Strona postępowania (odwołujący, zamawiający, przystępujący). | |
| cpv | Kod CPV powiązanego przetargu. | cpv=45 |
| tender_id / bzp_number | Powiązanie z konkretnym ogłoszeniem BZP. | |
| costs_min / costs_max | Zasądzone koszty postępowania (PLN). | |
| with_thesis | true: tylko orzeczenia z wyodrębnioną tezą. | with_thesis=true |
| sort | newest (domyślnie), oldest. | |
| page / per_page | per_page maksymalnie 100 (domyślnie 20). |
Odpowiedź: data[] (m.in. slug, primary_signature, ruling_date, outcome, law_articles[], costs_total, thesis_snippet, tender), total, page, per_page, has_more.
/api/kio/{slug}Pełna treść orzeczenia z metadanymi i powiązanym ogłoszeniem.
/api/kio/statsLiczby orzeczeń wg rozstrzygnięcia i roku.
Centralny Rejestr Umów
Umowy jednostek sektora finansów publicznych (od 1 lipca 2026): strony, przedmiot, wartość, okres, aneksy, adnotacje o utajnieniu. Umowy łączymy po NIP z profilami podmiotów i po numerze z ogłoszeniami.
/api/agreements| Parametr | Opis | Przykład |
|---|---|---|
| search | Fraza pełnotekstowa (przedmiot umowy, strony). | search=odbiór odpadów |
| province | Województwo jednostki (kod PLxx). | province=PL22 |
| sort | newest, oldest, value_desc, value_asc, relevance (z frazą). | sort=value_desc |
| page / per_page | Stronicowanie jak w /api/tenders. |
Odpowiedź: agreements[] (m.in. id, subject, value, date_signed, jsfp_name, jsfp_nip, contractor_name, contractor_nip, amendments_count, tender_id), total, page, pages, per_page.
/api/agreements/{id}Szczegóły umowy z historią zmian i stronami.
/api/agreements/statsStatystyki rejestru: liczba umów, wartości, świeżość danych.
Podpowiedzi wyszukiwania
/api/search/suggestions?q={fraza}&limit={n}Podpowiedzi do autouzupełniania: frazy, miasta, zamawiający, kody CPV. Odpowiedź: suggestions[] z polami text, type, highlight.
Dobre praktyki
- Synchronizuj przyrostowo:
sort=newestzdateFromustawionym na ostatni pobór iper_page=200. Pełne przejście po wszystkich stronach co godzinę to kilkaset wywołań, których nie potrzebujesz. - Przy 429 odczekaj tyle, ile mówi
Retry-After. Ponawianie w pętli tylko szybciej wyczerpie pulę. - Podaj własny
User-Agentz kontaktem. Gdy coś pójdzie nie tak po naszej stronie, będziemy wiedzieć, do kogo napisać. - Cache’uj profile podmiotów i orzeczenia lokalnie; zmieniają się rzadko.
- Potrzebujesz całej bazy albo codziennego zrzutu? Feed dzienny jest tańszy dla obu stron niż paginacja: kontakt@atlasprzetargow.pl.
MCP dla asystentów AI
Atlas ma oficjalny serwer MCP (Model Context Protocol), dzięki któremu Claude, ChatGPT czy Cursor mogą przeszukiwać przetargi, profile podmiotów i wyroki KIO w rozmowie. Klucz API przekazujesz zmienną środowiskową ATLAS_API_KEY.
{
"mcpServers": {
"atlas-przetargow": {
"command": "npx",
"args": ["-y", "@atlasprzetargow/mcp"],
"env": { "ATLAS_API_KEY": "atlas_TWOJ_KLUCZ" }
}
}
}Licencja i atrybucja
Dane źródłowe (Biuletyn Zamówień Publicznych, TED, orzeczenia KIO, Centralny Rejestr Umów) są informacją publiczną. Opracowanie Atlasu (normalizacja, powiązania, profile, agregaty) udostępniamy na licencji CC BY 4.0. Możesz je wykorzystywać także komercyjnie, pod warunkiem podania źródła:
Źródło: Atlas Przetargów (https://atlasprzetargow.pl)
W produktach publicznych link do atlasprzetargow.pl powinien być klikalny. Dane prezentujemy w dobrej wierze, bez gwarancji kompletności; przy decyzjach formalnych sprawdzaj publikację źródłową w BZP lub TED. Jak liczymy i czego nie liczymy, opisujemy w metodologii danych.
Zmiany łamiące kompatybilność zapowiadamy na tej stronie z wyprzedzeniem. Historia: 5 września 2026, klucze API, limity dobowe i nagłówki X-RateLimit-*.