Przejdź do treści
FARMA

API

Te same dane, które widać na stronach FARMY, do pobrania w JSON-ie: placówki ochrony zdrowia, katalog leków, podmioty z KRS i słownik terytorialny. Dostęp na klucz, przyznawany ręcznie i na czas określony.

Jak to działa

Każde wywołanie to zwykłe żądanie GET z kluczem w nagłówku:

curl -H "X-Api-Key: farma_TWOJ_KLUCZ" \
  "https://farma.waw.pl/api/v1/placowki/?typ=apteka&teryt=1465011"

Klucz wolno też podać parametrem ?klucz=, ale to droga gorsza: parametr adresu ląduje w logach serwera, w historii przeglądarki i w nagłówku Referer wysyłanym na obce strony. Nagłówek nie.

Zasoby

AdresCo zwracaFiltry
/api/v1/placowki/ Apteki, hurtownie i placówki NFZ: nazwa, typ, adres, gmina. q (nazwa), typ, teryt (gmina), od_id, strona
/api/v1/leki/ Katalog leków z RPL: nazwa, moc, postać, ATC, podmiot, kategoria. q (nazwa lub substancja), kategoria (na-recepte|bez-recepty), od_id, strona
/api/v1/firmy/ Podmioty z KRS: dane rejestrowe, adres, kapitał, PKD. q (nazwa, KRS, NIP, REGON), pkd, teryt (gmina), od_id, strona
/api/v1/lokalizacje/ Słownik terytorialny: województwa, powiaty, gminy z kodem TERYT. q (nazwa), poziom (wojewodztwo|powiat|gmina), od_id, strona
/api/v1/zrodla/ Rejestry, z których pochodzą dane: adres, licencja, częstotliwość. brak — zasób mieści się w jednej odpowiedzi
/api/v1/oceny/ FARMA SCORE i ocena dostępności leczenia dla gmin, razem z pokryciem danych i wersją metodologii. teryt (gmina), typ (farma_score|zdrowie), min_pokrycie, strona

CSV zamiast JSON-a

Każdy zasób oddaje też arkusz — wystarczy dopisać format=csv:

curl -H "X-Api-Key: farma_TWOJ_KLUCZ" \
  "https://farma.waw.pl/api/v1/leki/?kategoria=bez-recepty&format=csv" -o leki.csv

Plik ma separator średnik i znacznik BOM — tak, żeby Excel na polskich ustawieniach otworzył go w kolumnach i bez krzaków. Metryczka źródła nie ma się gdzie zmieścić w tabeli, więc idzie w liniach komentarza zaczynających się od # na początku pliku.

Stronicowanie: kursor, nie numer strony

Do przejścia przez cały zasób służy od_id — identyfikator ostatniego rekordu, który już masz:

curl -H "X-Api-Key: farma_TWOJ_KLUCZ" \
  "https://farma.waw.pl/api/v1/leki/?od_id=1200"

Wartość do następnego wywołania wraca w strona.nastepne_od_id i w nagłówku Link: rel="next". Gdy jest_dalszy_ciag jest false, to koniec.

Stare ?strona= nadal działa i działać będzie, ale ma dwie wady, których nie da się naprawić: koszt rośnie z numerem strony (baza musi przewinąć wszystko, co przed nią), a rekord dopisany między żądaniami przesuwa całą resztę — dostaniesz ten sam wiersz dwa razy albo nie dostaniesz go wcale, i nie masz jak się o tym dowiedzieć.

Specyfikacja i wersja

Maszynowy opis API: /api/openapi.json (OpenAPI 3.0). Generowany z tego samego rejestru zasobów, z którego działa API — nie da się więc rozjechać z rzeczywistością, bo nie ma osobnego pliku do zapomnienia.

Każda odpowiedź niesie nagłówek API-Wersja. Dopóki nie ma wersji drugiej, nie ma nagłówków Deprecation ani Sunset — i to jest cała obietnica: adresy /api/v1/ nie znikną bez wcześniejszego nagłówka mówiącego, kiedy.

Potrzebujesz całości? Nie pisz pętli

To API oddaje sto rekordów na żądanie. Katalog leków ma ich ponad dwadzieścia tysięcy — przejście po nim stronami to dwieście z górą żądań i kwadrans czekania, żeby dostać plik ważący kilka megabajtów.

Na to są paczki otwartych danych: całe zbiory, jeden plik, jedno pobranie, wszystkie kolumny. Bez klucza i bez limitu. API zostaje do pytań punktowych — paczka odpowiada na pytania o całość.

Co wraca

{
  "status": "ok",
  "dane": [ … ],
  "strona": { "numer": 1, "na_stronie": 100, "zwrocono": 100, "wszystkich": 23841, "stron": 239 },
  "zrodlo": {
    "rejestry": [ { "kod": "rejestr_aptek", "nazwa": "…", "licencja": "…", "ostatnia_sync": "…" } ],
    "pobrano": "2026-09-18T07:30:00+02:00"
  },
  "uwaga": "Dane pochodzą z rejestrów publicznych…"
}

Sekcja zrodlo jest w każdej odpowiedzi i to nie jest ozdobnik. Ten portal obiecuje, że każda liczba ma podane pochodzenie; dane wyjęte przez API trafią do cudzych opracowań, gdzie tej obietnicy już nikt nie powtórzy. Metryczka jedzie więc razem z danymi — razem z datą ostatniego importu, bo „apteka czynna" sprzed pół roku i sprzed godziny to dwie różne informacje.

Limity

Każdy klucz ma limit na minutę i na dobę; ustala je administrator przy przyznaniu dostępu. Stan zużycia wraca w nagłówkach każdej odpowiedzi:

X-Limit-Doba: 1000
X-Limit-Doba-Zostalo: 964
X-Limit-Minuta: 60

Po przekroczeniu wraca kod 429 i zdanie mówiące, który limit padł i kiedy się odnowi. Limity liczymy przed wykonaniem zapytania do bazy — inaczej chroniłyby licznik, a nie serwer.

Czego API nie oddaje

Opinii i ocen wystawionych przez czytelników. To treść moderowana, pisana w zaufaniu do tego portalu, a nie zbiór do hurtowego wyjęcia. Reszta danych pochodzi z rejestrów publicznych i jest dostępna także u źródła — tu jest tylko wygodniej.

API służy do odczytu. Metoda inna niż GET dostaje kod 405.

Wniosek o klucz

Klucz dostaniesz od razu po wysłaniu, ale nieczynny — zadziała, gdy administrator przyzna dostęp. Robimy tak, bo poczty wychodzącej ten portal jeszcze nie ma, a wydanie klucza od razu jest uczciwsze niż obietnica maila, który nie przyjdzie.