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 += 1

Klucz 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.

TrybLimit dobowyDla kogo
Bez klucza1 500 wywołań na adres IPPrzeglądanie, testy, jednorazowe skrypty.
Klucz darmowy5 000 wywołań na kluczIntegracje, codzienna synchronizacja, narzędzia wewnętrzne. Do 3 aktywnych kluczy na konto.
Limit indywidualnywg 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:

ParametrOpisPrzykład
X-RateLimit-LimitPula dobowa dla tego wywołania.5000
X-RateLimit-RemainingIle wywołań zostało do końca doby.4871
X-RateLimit-ResetMoment resetu (unix epoch, sekundy, UTC).1757116800
X-RateLimit-Scopeanonymous (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.

ParametrOpisPrzykład
400Zły parametr. Body: error, field, hint, got.sort=xyz
401invalid_api_key: nieznany klucz; api_key_revoked: klucz cofnięty w koncie.
404Nie ma takiego ogłoszenia, podmiotu, orzeczenia albo umowy.
422Sortowanie po wartości bez jednego zakresu (noticeKind=opening albo result).sort=value_desc
429quota_exceeded: wyczerpana pula dobowa (patrz niżej) albo limit minutowy. Zawsze z nagłówkiem Retry-After.
503Dane 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)

GET/api/tenders

Lista 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.

ParametrOpisPrzykład
searchFraza 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
cityMiasto (nazwa). Kilka wartości po przecinku.city=Gdańsk
provinceWojewództwo: kod PL14 albo nazwa. Kilka po przecinku.province=PL14
powiatPowiat (nazwa).powiat=wołomiński
cpvKod CPV: prefiks działu (2 cyfry), grupy lub pełny kod. Kilka po przecinku.cpv=45,48
noticeKindopening (ogłoszenia otwierające postępowanie, domyślnie) albo result (ogłoszenia o wyniku).noticeKind=result
noticeTypeKonkretny rodzaj ogłoszenia, np. ContractNotice, TenderResultNotice. Zwykle wystarczy noticeKind.noticeType=ContractNotice
orderKindworks, supplies, services. Kilka po przecinku.orderKind=works
tenderTypeTryb postępowania (symbol z BZP/TED, jak w filtrach wyszukiwarki).tenderType=podstawowy
clientTypeRodzaj zamawiającego: kody słownika BZP (cyfry i kropki), lista po przecinku.clientType=1.1.2
sourcebzp, ted, bk (Baza Konkurencyjności). Kilka po przecinku.source=ted
dateFrom / dateToZakres dat YYYY-MM-DD (włącznie).dateFrom=2026-09-01
dateFieldKtórego pola dotyczy zakres: published (domyślnie) albo deadline.dateField=deadline
onlyActivetrue: tylko ogłoszenia z terminem składania ofert w przyszłości.onlyActive=true
minValue / maxValueWartość szacunkowa (PLN, liczba bez separatorów).minValue=500000
hasDeposit, depositMin, depositMaxWadium: obecność (true/false) i zakres kwoty w PLN.hasDeposit=true
offersMin / offersMaxLiczba ofert (dla ogłoszeń o wyniku).offersMin=3
buyer_nipNIP zamawiającego (10 cyfr).buyer_nip=5250001616
contractor_nipNIP wykonawcy; zwraca ogłoszenia o wyniku, w których wygrał.contractor_nip=...
euFundedtrue: postępowania z dofinansowaniem UE.euFunded=true
excludeCancelledtrue: pomiń unieważnione.excludeCancelled=true
include_duplicatestrue: nie odfiltrowuj duplikatów (np. to samo ogłoszenie w BZP i TED).include_duplicates=true
sortnewest (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_pageStronicowanie. 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 }
}
GET/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).

GET/api/tenders/{id}/rulings

Wyroki KIO dotyczące tego postępowania.

GET/api/tenders/{id}/agreements

Umowy 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.

GET/api/buyers/{nip}

Profil zamawiającego: statystyki, ostatnie ogłoszenia, struktura CPV, wygrywający wykonawcy.

GET/api/contractors/{nip}

Profil wykonawcy: wygrane postępowania, zamawiający, wartości, konkurencja w wygranych.

GET/api/buyers/{nip}/winning-contractors

Ranking wykonawców wygrywających u tego zamawiającego.

GET/api/contractors/{nip}/winning-buyers

Zamawiający, u których ten wykonawca wygrywa najczęściej.

GET/api/entities/{nip}/rulings

Wyroki KIO, w których podmiot był stroną.

GET/api/entities/{nip}/agreements

Umowy 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.

GET/api/kio
ParametrOpisPrzykład
searchFraza pełnotekstowa (sygnatura, przedmiot, strony, treść uzasadnienia).search=rażąco niska cena
outcomeoddalono, uwzglednione, odrzucono, umorzono, inne.outcome=uwzglednione
ruling_kindwyrok albo postanowienie.ruling_kind=wyrok
date_from / date_toData orzeczenia, ISO.date_from=2026-01-01
law_articleArtykuł PZP: dokładny albo prefiks (np. „art. 226” łapie „art. 226 ust. 1 pkt 5 Pzp”).law_article=art. 226
chairpersonPrzewodniczący składu (fragment nazwiska).
partyStrona postępowania (odwołujący, zamawiający, przystępujący).
cpvKod CPV powiązanego przetargu.cpv=45
tender_id / bzp_numberPowiązanie z konkretnym ogłoszeniem BZP.
costs_min / costs_maxZasądzone koszty postępowania (PLN).
with_thesistrue: tylko orzeczenia z wyodrębnioną tezą.with_thesis=true
sortnewest (domyślnie), oldest.
page / per_pageper_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.

GET/api/kio/{slug}

Pełna treść orzeczenia z metadanymi i powiązanym ogłoszeniem.

GET/api/kio/stats

Liczby 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.

GET/api/agreements
ParametrOpisPrzykład
searchFraza pełnotekstowa (przedmiot umowy, strony).search=odbiór odpadów
provinceWojewództwo jednostki (kod PLxx).province=PL22
sortnewest, oldest, value_desc, value_asc, relevance (z frazą).sort=value_desc
page / per_pageStronicowanie 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.

GET/api/agreements/{id}

Szczegóły umowy z historią zmian i stronami.

GET/api/agreements/stats

Statystyki rejestru: liczba umów, wartości, świeżość danych.

Podpowiedzi wyszukiwania

GET/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=newest z dateFrom ustawionym na ostatni pobór i per_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-Agent z 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-*.