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
| Adres | Co zwraca | Filtry |
|---|---|---|
/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.