Dokumentacja

Wstęp

Poniższa dokumentacja kierowana jest głównie do programistów aplikacji chcących wykorzystać dane o jakości powietrza w swoich projektach. Zalecamy zapoznanie się z treścią dokumentacji, a w szczególności z wyjaśnieniem pewnych podstawowych pojęć. Mamy nadzieję, że dokumentacja będzie pomocna w procesie integracji z naszym API. Dokładamy wszelkich starań by dokumentacja była aktualna i kompletna. W razie pytań zapraszamy do kontaktu. Ta dokumentacja jest open-source i może być edytowana na GitHub.

Co nowego w API 2.0

Niniejsza dokumentacja dotyczy API w wersji 2.0. W stosunku do poprzedniej wersji wprowadziliśmy liczne zmiany i usprawnienia:

  • "Sensory" zostały zastąpione w API przez "Instalacje".
  • Wprowadziliśmy wsparcie dla różnych indeksów oraz standardów jakości powietrza.
  • Wprowadziliśmy w API prostsze w użyciu, bardziej intuicyjne operacje. Uprościliśmy i ujednoliciliśmy modele odpowiedzi. Dodaliśmy lepszą walidację zapytań i obsługę błędów. Usunęliśmy nieobsługiwane / niedziałające parametry i redundantne albo nieintuicyjne operacje.
  • Zwracamy w API więcej szczegółów nt. "Sponsora" instalacji.
  • Zwracamy w API dokładniejsze dane nt. adresu instalacji oraz wysokość nad poziomem morza na jakiej zamontowany jest sensor.
  • Zwracamy w API kolor reprezentujący poziom zanieczyszczeń oraz dodatkowe teksty dotyczące danego indeksu jakości powietrza.
  • Zwracamy w API jednostki oraz typy pomiarów które wspieramy.
  • Zwracamy w API teksty w różnych językach.

Wsparcie dla API 1.0

Z dniem 28.02.2019 zakończyliśmy wsparcie starej wersji API 1.0.

Informacje ogólne

Airly API oparte jest o koncepcję REST. Nasze API udostępnia operacje zorganizowane wokół zasobów (Installations oraz Measurements), które mają intuicyjne i przewidywalne ścieżki URL. Bazujemy na standardowych mechanizmach protokołu HTTP w kwestiach takich jak wykonywanie operacji (metody HTTP) czy obsługa zwracanych błędów (statusy HTTP).

Możliwe jest wywoływanie operacji API z poziomu aplikacji klienckich z innych domen - API wspiera tzw. cross-origin.

Wszystkie operacje zwracają odpowiedzi w formacie JSON (w tym także błędy) wraz z nagłówkiem HTTP Content-Type: application/json, kodowane zestawem znaków UTF-8, chyba, że zaznaczono inaczej w opisie danej operacji.

Uwierzytelnianie

Korzystanie z API wymaga utworzenia konta użytkownika. Alternatywnie, możliwe jest logowanie istniejącym kontem GitHub, Google lub Facebook.

Po zarejestrowaniu zostaje wygenerowany klucz apikey, którym należy uwierzytelniać wszystkie zapytania do API. Klucz można podać albo w dodatkowym nagłówku http o nazwie apikey albo jako parametr zapytania.

Nagłówek

W celu uwierzytelnienia zapytania do Airly API należy przekazać nagłówek apikey z wartością klucza.

apikey: <apikey>

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/meta/indexes'

Zasady użytkowania oraz limity

Zasady użytkowania

W wersji darmowej dostępu do API użytkownik zobowiązuje się do wykorzystywania API wyłącznie w celach niekomercyjnych.

Obok danych pochodzących z naszego API prezentowanych w aplikacjach należy umieścić nasze logo: svg, png.

Więcej szczegółów dotyczących zasad wykorzystania API można znaleźć w naszym Regulaminie.

Limity

W celu zachowania wysokiej przepustowości i jakości usługi dla wszystkich użytkowników, stosujemy limitowanie w dostępie do API.

Domyślny limit dla wszystkich użytkowników wynosi 100 zapytań dziennie dla pojedynczego klucza.

Zliczaniu podlegają wszystkie zapytania HTTP wysyłane do API, niezależnie od tego czy były wykonane poprawnie czy też zwróciły błąd. Każde pojedyncze zapytanie zmniejsza aktualnie dostępny limit o 1. Liczniki resetują się o północy UTC (limit dzienny) oraz o każdej pełnej minucie (limit minutowy).

tip Powyższy limit pozwala np. na odpytywanie o pomiary pojedynczego sensora z częstotliwością co 15 minut przez całą dobę, lub na zbieranie danych z 4 sensorów z częstotliwością co godzinę przez całą dobę, powinien zatem być wystarczający w większości indywidualnych zastosowań.

W przypadku aplikacji które wyświetlają dane w sposób ciągły zalecamy aby zapisywać odpowiedzi API w pamięci lokalnej (cache) i odświeżać je w tle w określonych odstępach czasu.

W przypadku przekroczenia limitu zapytanie do API zwróci status HTTP 429 - Too Many Requests.

Jeżeli potrzebujesz zwiększenia swojego limitu API lub chcesz wykorzystać nasze dane w projekcie komercyjnym, skontaktuj się z nami.

Nagłówki RateLimit

Każda odpowiedź z API zawiera dodatkowe nagłówki informujące o limitach obowiązujących używany klucz API oraz o ich aktualnym użyciu. Nazwy nagłówków zaczynają się od X-RateLimit-Limit- oraz X-RateLimit-Remaining-, np.:

X-RateLimit-Limit-day: 100
X-RateLimit-Remaining-day: 96

Język

Niektóre operacje API zwracają wartości opisowe, np. tekstowy opis aktualnej jakości powietrza. Teksty te zwracane są w odpowiednim języku wedle preferencji użytkownika.

Aby wybrać język API należy przesłać w zapytaniu nagłówek Accept-Language, z odpowiednią wartością.

Aktualnie wspierany jest język angielski ("en" - domyślny) oraz polski ("pl").

Błędy

Poprawnie wykonane zapytania do API zwracają kod HTTP 200 OK oraz odpowiedź w formacie JSON. W pozostałych przypadkach zwracany jest kod błędu HTTP adekwatny do sytuacji. Ilustruje to poniższa tabela:

400 - Bad Request zapytanie było niepoprawne, np. użyto niepoprawnych wartości parametrów
401 - Unauthorized nie podano klucza API (apikey)
404 - Not Found zapytanie lub ścieżka url wskazują na nieistniejący zasób
405 - Method Not Allowed zapytanie HTTP korzysta z niedozwolonej metody (np. POST zamiast GET)
406 - Not Acceptable zapytano o odpowiedź w niewspieranym formacie (np. Accept text/xml zamiast application/json)
429 - Too Many Requests przekroczono limit zapytań API (patrz Limity)
500 - Internal Server Error wystąpił błąd serwera Airly

Ponadto w przypadku błędu zwrócona zostaje odpowiedź w formacie JSON o następującej treści:

{
  "errorCode": "kod błędu",
  "message": "opis błędu",
  "details": {
    <mapa klucz-wartość z dodatkowymi szczegółami błędu>
  }
}

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/measurements/point?lat=200&lng=19.940984'

Odpowiedź

HTTP Status: 400
{
  "errorCode": "API_REQUEST_INVALID",
  "message": "API Request was not valid",
  "details": {
    "violations": [
      {
        "parameter": "lat",
        "message": "latitude value must be between -90.0 and +90.0",
        "rejectedValue": 200
      }
    ]
  }
}

Współrzędne geograficzne

Wszystkie współrzędne geograficzne występujące w API (zarówno jako parametry zapytań, oraz jako pola w odpowiedziach) są współrzędnymi w odniesieniu systemu WGS 84.

Pola latitude (lub lat) oznaczają szerokość geograficzną, zaś longitude (lng) długość geograficzną.

Współrzędne podane są jako stopnie dziesiętne w postaci liczby zmiennoprzecinkowej w formacie double, tzn. bez minut i sekund kątowych, za to z częścią dziesiętną reprezentującą ułamkową część stopnia.

Pole latitude (lat) może przyjmować wartości od -90.0 do +90.0, zaś pole longitude (lng) wartości od -180.0 do +180.0.

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/installations/204'

Odpowiedź

{
  "id": 204,
  "location": {
    "latitude": 50.062006,
    "longitude": 19.940984
  },
  ...
}

Czas

Wszystkie wartości czasu występujące w API (zarówno jako parametry zapytań, oraz jako pola w odpowiedziach) są w formacie ISO8601 w odniesieniu do strefy UTC np. 2018-08-24T08:24:48.652Z.

Średnie wartości pomiarowe wyliczane dla określonego przedziału czasu (np. średnie godzinowe) zwracane są wraz z przedziałem czasu, którego dotyczą. Przedział ten jest podany jako para atrybutów fromDateTime oraz tillDateTime i jest to przedział lewostronnie domknięty i prawostronnie otwarty [fromDateTime, tillDatetime).

Kompresja GZIP

Wszystkie operacje API wspierają kompresję GZIP. Włączenie kompresji znacząco zmniejsza rozmiar danych przesyłanych z API i może skrócić czas ich pobierania i jest to zalecana praktyka.

W celu włączenia kompresji należy w zapytaniu HTTP przesłać dodatkowy nagłówek Accept-Encoding: gzip. Należy zwrócić uwagę aby klient HTTP używany do komunikacji z API był odpowiednio skonfigurowany i obsługiwał skompresowane odpowiedzi.

Przykład zapytania

curl -X GET -sD - \
    --compressed \
    --header 'Accept: application/json' \
    --header 'Accept-Encoding: gzip' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/measurements/installation?installationId=204'

Odpowiedź

HTTP/2 200
date: Tue, 18 Sep 2018 13:18:19 GMT
content-type: application/json;charset=UTF-8
...
content-encoding: gzip

{ ... }

Kompatybilność

Na ile to tylko możliwe, niniejsze API będzie rozwijane z zachowaniem kompatybilności wstecznej.

Odpowiedzi JSON mają następujące cechy gwarantujące stabilność API:

  • Pola obiektów JSON zawsze zachowują swoją nazwę oraz typ wartości
  • Pola oznaczone jako obowiązkowe zawsze będą zwracane w odpowiedzi i nigdy nie zostaną usunięte z API
  • Pola oznaczone jako opcjonalne mogą ale nie muszą być zwrócone przez API, i jako takie mogą również być usunięte z API całkowicie
  • Struktury dynamiczne, takie jak listy i mapy mogą zawierać dowolną liczbę elementów; w szczególności mogą być puste
  • Nowe pola mogą być dodane do odpowiedzi API w dowolnym momencie. Nie będą one kolidować z istniejącymi polami ani zmieniać ich znaczenia

tip W praktyce powyższe zasady oznaczają, że pola obowiązkowe zawsze będą w odpowiedzi i nie ma potrzeby sprawdzania ich obecności. Pola opcjonalne należy zawsze sprawdzać pod kątem obecności a ich brak lub wartość null należy stosownie obsłużyć. Nie należy oczekiwać, że listy bądź mapy będą zawierać jakieś określone spodziewane wartości, bądź konkretną liczbę elementów.

Np. instalacja która z jakiegoś powodu mierzy tylko wartości pogodowe (np. sensor pyłów jest uszkodzony), w polu values nie zwróci wartości pyłów PM.

Korzystając z bibliotek do parsowania JSON należy skonfigurować je tak, by ignorowały nowe, nieznane pola, ponieważ wraz z rozwojem API możemy dodawać nowe pola do odpowiedzi bez uprzedzenia.

Jeżeli zajdzie konieczność zmiany jakichś operacji lub modeli odpowiedzi w sposób niekompatybilny wstecz, wówczas utworzona zostanie nowa operacja API z nowym modelem odpowiedzi. Będziemy utrzymywać zarówno starą jak i nową operację do czasu aż stara operacja będzie mogła być w sposób bezpieczny wycofana i usunięta. Jeśli taka sytuacja zajdzie poinformujemy użytkowników API.

Zachowanie interfejsu API może ulec zmianie bez ostrzeżenia, jeśli istniejące zachowanie jest nieprawidłowe lub stanowi lukę w zabezpieczeniach.

Pojęcia

Instalacje

W poprzedniej wersji API operowaliśmy pojęciem sensora. Można było np. zapytać jakie sensory znajdują się na danym obszarze, oraz odpytać poszczególne sensory o ich pomiary za pomocą identyfikatora sensora (sensorId). Niestety takie podejście rodzi pewne problemy. Nasza flota urządzeń cały czas się rozrasta i nie sposób uniknąć sytuacji gdy jakieś urządzenie trzeba np. wymienić na nowe, albo przenieść w inne miejsce. Niestety taka sytuacja może skutkować odpytywaniem o niewłaściwy sensor, np. taki którego już nie ma, albo który został gdzieś przeniesiony.

W nowym API rozwiązujemy ten problem wprowadzając pojęcie instalacji. Instalacja wiąże ze sobą sensor oraz lokalizację, w której jest zamontowany w danym momencie. Można zatem bezpiecznie odpytywać o pomiary konkretną instalację, bez ryzyka, że będzie się pytało o niewłaściwy sensor.

Jeżeli w danym miejscu sensor został zdeinstalowany, to dalsze zapytania o tę samą instalację mogą zwrócić jeden z dwóch rodzajów odpowiedzi:

  • jeżeli w tym miejscu nastąpiła wymiana sensora na nowy, to zapytania będą zwracały kod HTTP 301 Moved Permanently wraz z nagłówkiem Location wskazującym na nowy url, który należy odpytać zamiast dotychczasowego. Dodatkowo zwracana jest odpowiedź w formacie JSON
{
    "errorCode": "INSTALLATION_REPLACED",
    "message": "Installation was replaced with another one",
    "details": {
        "successorId": <identyfikator nowej instalacji>
    }
}
  • jeżeli w tym miejscu nie ma nowego sensora ("następcy") to zapytania będą zwracały kod błędu 404 Not Found

Zasadniczo zalecamy korzystanie z innych operacji API, np. takich, które zwracają pomiary dla danej lokalizacji lub takich, które zwracają uśrednione pomiary dla danego obszaru. Wówczas nie trzeba przejmować się instalacjami, ich identyfikatorami, itd. Jeśli jednak ktoś chce odpytywać konkretną instalację, musi brać pod uwagę powyższe i stosownie obsługiwać zwracane kody odpowiedzi.

Sponsorzy

Sponsorem instalacji jest organizacja bądź instytucja, która zakupiła nasze urządzenie. Zazwyczaj jest to lokalna administracja, np. władze gminy bądź powiatu, ale także firmy oraz osoby prywatne. Wiele urządzeń rozdaliśmy również w ramach różnych akcji takich jak #PolskaOddycha czy #KrakówOddycha.

Informacje o tym, kto jest sponsorem danej instalacji są dostępne u nas na platformie, w API oraz na naszej mapie. Prezentując określoną markę, bądź gminę na naszej platformie, chcemy w ten sposób podziękować naszym klientom za włączenie się w walkę o czyste powietrze. W API dostępne są: nazwa, logo (link do obrazka) oraz adres www strony sponsora.

Przy publicznym prezentowaniu danych z konkretnej instalacji w swojej aplikacji nie ma żadnych wymogów co do podkreślenia, z której konkretnie instalacji pochodzi sensor lub kto jest jej sponsorem, natomiast nie może to być prezentowane w sposób mylący i niejasny dla użytkownika np. jeśli wyświetlana jest średnia z kilku instalacji dla całego miasta powinno się podkreślić takowy fakt.

Locations

Lokalizacja składa się z unikalnego id lokalizacji, szerokości i wysokości geograficznej oraz bardziej opisowych informacji o miejscu takich jak np. nazwa ulicy, miasta, państwa. Każda instalacja znajduje się w swojej lokalizacji przy czym do 1 lokalizacji może być przypisana maksymalnie 1 instalacja jednocześnie, oznacza to, że jeżeli instalacje funkcjonowały w okresach, które się nie pokrywają, to mogą one być przypisane do tej samej lokalizacji.

API pozwala wykonywać zapytania na bazie id lokalizacji, dzięki temu możemy wygodnie pobrać dane ze wszystkich instalacji, które funkcjonowały w wybranym miejscu, czyli w odpowiedzi zawarte są też dane z czujników historycznych, które zostały zastąpione nowym urządzeniem.

Pomiary

Wszystkie operacje zaczynające się od /v2/measurements/ zwracają ujednolicony format odpowiedzi zawierający dane pomiarowe z danej instalacji lub wybranego obszaru (w zależności od parametrów operacji). Każda odpowiedź zawiera pola:

  • current - są to dane pomiarowe z ostatniej godziny (średnia krocząca z ostatnich 60 minut)
  • history - pomiary historyczne, obecnie 24 ostatnie pełne godziny zawierające średnie pomiary godzinowe, posortowane rosnąco
  • forecast - prognoza pomiarów, obecnie 24 nadchodzące godziny zawierające przewidywane średnie pomiary godzinowe, posortowane rosnąco

W każdym z powyższych pól znajdziemy zarówno surowe wartości pomiarowe, jak i wyliczone z nich wartości indeksów oraz ewentualne przekroczenia standardów jakości powietrza.

W przypadku prezentowania w swoich aplikacjach danych pochodzących bezpośrednio z API lub będących efektem ich przetworzenia (np. wyliczenie innego indeksu) zalecane jest w jasny i czytelny sposób podkreślanie co dane wartości oznaczają.

Typy pomiarów

Nasze urządzenia mierzą szereg różnych wartości: temperaturę, wilgotność, ciśnienie atmosferyczne, stężenia pyłów itd. Nasze API daje jednak dostęp również do danych pochodzących z innych stacji pomiarowych (np. stacji GIOŚ), które mierzą tylko niektóre z tych parametrów (np. tylko PM10, obecnie nie przetwarzamy i nie udostępniamy innych zanieczyszczeń niż pyłowe). Aby dać dostęp do wszystkich tych danych w sposób jednolity, dane pomiarowe zwracane są w dynamicznej strukturze w postaci listy (json array), której poszczególne elementy to obiekty zawierające parę "nazwa-wartość" dla określonego typu pomiaru.

Listę wszystkich typów pomiarów, które wspiera platforma, ich nazwy oraz stosowane jednostki można pobrać odpytując adres /v2/meta/measurements.

Indeksy

Indeks jakości powietrza to sposób przeliczenia surowych danych pomiarowych dla różnych zanieczyszczeń (np. pyłów, gazów itp.) na jedną wartość reprezentującą stopień zanieczyszczenia powietrza. Indeksom jakości powietrza zazwyczaj towarzyszy wartość liczbowa z arbitralnie dobranej skali (np. 0-100), skwantowany poziom zanieczyszczeń (np. "Niski", "Wysoki"), kolor reprezentujący dany poziom zanieczyszczenia (np. zielony, czerwony) a czasem także dodatkowe wartości opisowe, jak np. ostrzeżenie o skutkach zdrowotnych jakie niesie dane zanieczyszczenie.

Celem indeksu jakości powietrza jest prezentowanie danych o poziomie zanieczyszczeń w sposób prosty, przejrzysty i zrozumiały dla ogółu społeczeństwa, w szczególności przez osoby które nie są zaznajomione z obowiązującymi normami i np. nie wiedzą jakie wartości pyłu PM10 w powietrzu są bezpieczne a jakie niebezpieczne dla zdrowia. Po drugie indeks sprowadza dane dla różnych składników zanieczyszczeń (np. pyły, gazy) do jednej wartości i reprezentuje ujednolicony (i nieco uproszczony) obraz jakości powietrza w danym miejscu, niezależnie od tego, który czynnik zanieczyszczający powietrze dominuje na danym terenie.

Indeksy jakości powietrza tworzone są przez krajowe i międzynarodowe organizacje zajmujące się ochroną środowiska. Istnieją różne indeksy stosowane w różnych krajach. Np. w Unii Europejskiej szeroko stosowany jest indeks CAQI przygotowany w ramach projektu CITEAIR. W Polsce dodatkowo stosowany jest Polski Indeks Jakości Powietrza (PIJP) zdefiniowany i wyliczany przez Główny Inspektorat Ochrony Środowiska. Ponieważ różne indeksy mają różny sposób obliczania, ten same dane pomiarowe na danym terenie mogą być interpretowane jako różne wartości indeksów, różne poziomy zanieczyszczeń i być reprezentowane przez różne kolory.

Platforma Airly wspiera w tej chwili dwa indeksy jakości powietrza: CAQI, oraz Polski Indeks Jakości Powietrza - PIJP. Odpowiedzi API zawierają indeks wyliczony dla danych pomiarowych określony parametrem zapytania indexType.

Listę wszystkich indeksów które wspiera platforma oraz definicje ich poziomów i przedziałów wraz z kolorami można uzyskać odpytując adres /v2/meta/indexes.

AirlyCAQI

Ostatni poziom indeksu CAQI zaczyna się na wartości 100 i nie obrazuje już intuicyjnie kolejnych zmian poziomów zanieczyszczeń. Niestety, w warunkach polskich w sezonie zimowym poziom stężeń pyłu bardzo często przekracza i utrzymuje się powyżej wartości 100 CAQI na rozległych terenach, nieraz przez całą dobę. Aby lepiej uwidocznić ten problem postanowiliśmy wprowadzić dodatkowe poziomy CAQI wraz z przypisanymi wartościami kolorów. W ten sposób powstał indeks AirlyCAQI. Wartość liczbowa AirlyCAQI wyliczana jest dokładnie tak samo jak dla CAQI, różni się tylko rozgraniczeniem poszczególnych przedziałów dla najwyższych stężeń zanieczyszczeń. Ma też więcej poziomów (7, podczas gdy CAQI definiuje tylko 5) i odrobinę przyjemniejsze dla oka kolory, dobrane specjalnie dla naszej platformy. Indeks AirlyCAQI to domyślny indeks zwracany w API.

Standardy

Standard jakości powietrza, zwany również normą, to wysokość stężenia określonego składnika zanieczyszczenia powietrza, która uważana jest za pewną dopuszczalną wartość graniczną. Występowanie w powietrzu stężeń przekraczających tę wartość może mieć niekorzystny wpływ na nasze zdrowie, tym większy czym większe jest przekroczenie dopuszczalnej normy. Określaniem standardów jakości powietrza zajmują się krajowe i międzynarodowe organizacje zdrowotne np. Światowa Organizacja Zdrowia (WHO).

W Airly API udostępniamy wartości norm PM10 oraz PM2.5. W odpowiedzi API zwracana jest wartość normy oraz procentowy stopień jej przekroczenia przez dany składnik zanieczyszczenia w danym momencie. Obecnie API wspiera jedynie normy WHO dla PM2.5 oraz PM10.

Operacje API

Instalacje

Operacje z grupy /v2/installations/ umożliwiają wyszukiwanie instalacji oraz pobieranie ich metadanych takich jak położenie, dane adresowe itd. Wszystkie operacje zwracają jednolity format odpowiedzi, której poszczególne pola oznaczają:

  • id (integer) - unikalny identyfikator instalacji; za pomocą id można odpytywać o pomiary konkretnej instalacji
  • latitude, longitude (double) - współrzędne geograficzne instalacji; określają dokładne położenie czujnika na mapie
  • locationId (integer) - unikalny identyfikator lokalizacji; za pomocą id można odpytywać o pomiary konkretnej lokalizacji
  • address:
    • country, city, street, number (string) - dane adresowe instalacji; każde z pól opcjonalne, może być puste
    • displayAddress1, displayAddress2 (string) - dodatkowe informacje dot. lokalizacji np. nazwa szkoły lub przedszkola; pola opcjonalne
  • elevation (double) - określa wysokość w metrach nad poziomem morza na jakiej zamontowany jest sensor
  • airly (bool) - flaga określająca czy instalacja jest urządzeniem Airly; np. stacje pomiarowe GIOŚ są oznaczone jako false
  • sponsor:
    • id (integer) - identyfikator sponsora instalacji
    • name (string) - nazwa sponsora instalacji
    • description (string) - dodatkowy tekst opisujący sponsora instalacji, pole opcjonalne
    • logo (string) - adres url prowadzący do logo sponsora (obrazek w formacie jpg); pole opcjonalne
    • link (string) - adres url prowadzący do strony www sponsora; pole opcjonalne
    • displayName (string) - dodatkowe informacje dot. sponsora np. akronim nazwy sponsora; pole opcjonalne

Przykład obiektu Installation

{
  "id": 204,
  "location": {
    "latitude": 50.062006,
    "longitude": 19.940984
  },
  "locationId": 204,
  "address": {
    "country": "Poland",
    "city": "Kraków",
    "street": "Mikołajska",
    "number": "4B",
    "displayAddress1": "Kraków",
    "displayAddress2": "Mikołajska"
  },
  "elevation": 220.38,
  "airly": true,
  "sponsor": {
    "id": 7,
    "name": "KrakówOddycha",
    "description": "Sensor Airly w ramach akcji",
    "logo": "https://cdn.airly.org/logo/KrakówOddycha.jpg",
    "link": "https://przykladowy_link_do_strony_sponsora.pl",
    "displayName": "KrakówOddycha"
  }
}

GET /v2/installations/{installationId}

Operacja zwraca dane pojedynczej instalacji wskazanej identyfikatorem installationId.

Parametry wymagane:

  • installationId (integer) - parametr w ścieżce url; identyfikator instalacji

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/installations/204'

GET /v2/installations/location

Operacja zwraca dane pojedynczej instalacji wskazanej identyfikatorem locationId, w odpowiedzi zawsze znajduje się instalacja obecnie funkcjonująca.

Parametry wymagane:

  • locationId (integer) - parametr w ścieżce url; identyfikator lokalizacji

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/installations/location?locationId=8077'

GET /v2/installations/sensor

Operacja zwraca dane pojedynczej instalacji wskazanej identyfikatorem sensorId, w odpowiedzi zawsze znajduje się instalacja obecnie funkcjonująca.

Parametry wymagane:

  • sensorId (integer) - parametr w ścieżce url; identyfikator sensora

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/installations/sensor?sensorId=204'

GET /v2/installations/nearest

Operacja zwraca listę instalacji, które znajdują się najbliżej określonego punktu, posortowane według odległości od tego punktu.

Parametry wymagane:

  • lat (double) - szerokość geograficzna punktu w postaci dziesiętnej, np. 50.062006
  • lng (double) - długość geograficzna punktu w postaci dziesiętnej, np. 19.940984

Parametry opcjonalne:

  • maxDistanceKM (double) - domyślna wartość 3.0; określa limit odległości w kilometrach w jakiej od określonego punktu muszą leżeć wszystkie znalezione instalacje; wartość ujemna oznacza brak limitu
  • maxResults (integer) - domyślna wartość 1; określa limit instalacji zwróconych w odpowiedzi; wartość ujemna oznacza brak limitu

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/installations/nearest?lat=50.062006&lng=19.940984&maxDistanceKM=5&maxResults=3'

Pomiary

Operacje z grupy /v2/measurements/ umożliwiają pobieranie danych pomiarowych według różnych kryteriów. Wszystkie operacje zwracają jednolity format odpowiedzi, która zawiera następujące pola:

  • current - pojedynczy element typu AveragedValues; zawiera uśrednione pomiary dla ostatnich 60 minut (średnia krocząca); dla stacji pomiarowych innych niż Airly (np. GIOŚ) może zawierać dane do 3 godzin wstecz, z uwagi na opóźnienia w przesyłaniu danych przez GIOŚ
  • history - lista elementów typu AveragedValues; zawiera listę historycznych średnich pomiarów godzinowych, za ostatnie 24 pełne godziny
  • forecast - lista elementów typu AveragedValues; zawiera listę prognozowanych średnich pomiarów godzinowych, dla kolejnych 24 pełnych godzin

tip Pole history zawiera dane dla 24 ostatnich pełnych godzin, tzn. przykładowo jeżeli aktualnie jest godzina 09:27 UTC, to pole będzie zawierać 24 elementy, z których pierwszy zawiera dane dla przedziału czasu 09:00-10:00 UTC poprzedniego dnia, a ostatni dla przedziału 08:00-09:00 UTC dziś.

Natomiast pole forecast zawiera prognozowane dane dla 24 kolejnych pełnych godzin, przy czym pierwsza godzina to aktualna godzina; przykładowo jeżeli aktualnie jest godzina 09:27 UTC, to pole będzie zawierać 24 elementy, z których pierwszy zawiera dane dla przedziału czasu 09:00-10:00 UTC dziś, a ostatni dla przedziału 08:00-09:00 UTC następnego dnia.

Warto zauważyć że pola history oraz forecast tworzą nieprzerwany ciąg danych dla 48 godzin, z których pierwsze 24 godziny stanowią wartości zmierzone, a kolejne 24 godziny to wartości prognozowane.

Pole current zawiera średnie dane pomiarowe za ostatnie 60 minut (średnia krocząca) licząc od "teraz", tj. od momentu wysłania zapytania. Przykładowo jeśli aktualnie jest godzina 09:27 UTC, to pole to zawiera dane dla przedziału czasu 08:27-09:27 UTC. Przy czym dla instalacji innych niż Airly (np. stacje GIOŚ) pole to może zawierać dane do 3 godzin wstecz, z uwagi na opóźnienia w przesyłaniu danych przez podmioty zewnętrzne.

Obiekt AveragedValues składa się z pól:

  • fromDateTime / tillDateTime (string) - znacznik czasu w formacie ISO8601; zawiera datę i czas w odniesieniu do strefy UTC; pola w odpowiedzi oznaczają przedział czasu dla którego zostały zebrane i uśrednione dane pomiarowe z danej instalacji, lub na danym obszarze
  • values - lista obiektów typu value; pojedynczy obiekt składa się z pól
    • name (string) - nazwa (typ) danego pomiaru; np. PM10
    • value (double) - zmierzona wielkość pomiarowa; np. stężenie 25µg/m3
  • indexes - lista obiektów typu Index; pojedynczy obiekt reprezentuje wartość indeksu obliczonego dla danych pomiarowych zawartych w values
    • name (string) - nazwa obliczonego indeksu (np. CAQI, albo PIJP)
    • value (double) - wartość numeryczna obliczonego indeksu
    • level (string) - poziom indeksu (np. HIGH, albo LOW itp)
    • description (string) - tekstowy opis danego poziomu zanieczyszczeń; wartość pola jest zwracana w języku wedle nagłówka Accept-Language
    • advice (string) - dodatkowy tekst zawierający zalecenia dot. danego poziomu zanieczyszczeń; wartość pola jest zwracana w języku wedle nagłówka Accept-Language
    • color (string) - kolor odpowiadający danemu poziomowi indeksu; w formacie heksadecymalnym RGB (np. #D1CF1E)
  • standards - lista obiektów typu Standard; pojedynczy obiekt reprezentuje określony standard jakości powietrza
    • name (string) - nazwa standardu; aktualnie jedynie standardy WHO
    • pollutant (string) - nazwa typu pomiaru dla którego określony jest standard jakości, aktualnie wspierane są PM10 oraz PM25
    • limit (double) - poziom stężenia danego zanieczyszczenia, który nie powinien być przekraczany w danym okresie czasu; inaczej, wartość dla której stężenie osiąga 100% normy
    • percent (double) - wartość stężenia danego zanieczyszczenia wyrażona jako procentowy udział tego stężenia w normie / limicie; np. dla stężenia PM10 25µg/m3, wartość procentowa względem normy 50µg/m3 wynosi 50%.

 

Parametry zapytań wspólne dla wszystkich operacji:

  • indexType - określa typ indeksu jaki ma być obliczony i zwrócony w odpowiedzi dla danych pomiarowych; wspierane wartości to aktualnie: AIRLY_CAQI (domyślna), CAQI, oraz PIJP; (w obecnej wersji API zwracany jest tylko jeden wybrany indeks)
  • indexPollutant - określa zbiór rodzajów zanieczyszczeń jakie mają być brane pod uwagę podczas wyliczania wartości obliczanego indeksu, wspierane wartości to aktualnie: PM (domyślna = {PM10, PM25}), PM10, PM25, O3, NO2, SO2, CO, ALL (zbiór wszystkich podanych)

Przykład obiektu Measurements

{
  "current": {
    "fromDateTime": "2018-08-24T08:24:48.652Z",
    "tillDateTime": "2018-08-24T09:24:48.652Z",
    "values": [
      { "name": "PM1",          "value": 12.73   },
      { "name": "PM25",         "value": 18.7    },
      { "name": "PM10",         "value": 35.53   },
      { "name": "PRESSURE",     "value": 1012.62 },
      { "name": "HUMIDITY",     "value": 66.44   },
      { "name": "TEMPERATURE",  "value": 24.71   },
      ...
    ],
    "indexes": [
      {
        "name": "AIRLY_CAQI",
        "value": 35.53,
        "level": "LOW",
        "description": "Dobre powietrze.",
        "advice": "Możesz bez obaw wyjść na zewnątrz.",
        "color": "#D1CF1E"
      }
    ],
    "standards": [
      {
        "name": "WHO",
        "pollutant": "PM25",
        "limit": 25,
        "percent": 74.81
      },
      ...
    ]
  },
  "history": [ ... ],
  "forecast": [ ... ]
}

GET /v2/measurements/installation

Operacja zwraca pomiary dla konkretnej instalacji danej parametrem installationId.

W przypadku gdy dana instalacja nie istnieje, lub gdy sensor w danym miejscu został zdemontowany, zwraca status 404 Not Found.

W przypadku gdy instalacja w danym miejscu została zastąpiona innym urządzeniem, zwraca status 301 Moved Permanently wraz z nagłówkiem Location prowadzącym do URL z pomiarami nowej instalacji.

Parametry wymagane:

  • installationId (integer) - identyfikator instalacji

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/measurements/installation?installationId=204'

GET /v2/measurements/location

Operacja zwraca połączone pomiary dla instalacji danych parametrem locationId.

W przypadku gdy dana lokalizacja nie istnieje, lub gdy żaden sensor nie działał w ciągu ostatnihc 24 godziny, zwraca status 404 Not Found.

Parametry wymagane:

  • locationId (integer) - identyfikator lokalizacji

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/measurements/location?locationId=8077'

GET /v2/measurements/nearest

Operacja zwraca pomiary dla instalacji najbliższej określonej lokalizacji.

W przypadku gdy w odległości maxDistanceKM od punktu nie znaleziono żadnej instalacji, zwraca status 404 Not Found.

Parametry wymagane:

  • lat (double) - szerokość geograficzna punktu w postaci dziesiętnej, np. 50.062006
  • lng (double) - długość geograficzna punktu w postaci dziesiętnej, np. 19.940984

Parametry opcjonalne:

  • maxDistanceKM (double) - domyślna wartość 3.0; określa limit odległości w kilometrach w jakiej od określonego punktu musi leżeć poszukiwana instalacja; wartość ujemna oznacza brak limitu

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/measurements/nearest?lat=50.062006&lng=19.940984&maxDistanceKM=5'

GET /v2/measurements/point

Operacja zwraca pomiary dla dowolnego punktu na mapie.

Wartości pomiarowe interpolowane są z okolicznych sensorów (leżących w odległości do 1,5km od punktu). Wartość pomiaru wyliczana jest jako średnia ważona z okolicznych sensorów, z wagą odwrotnie proporcjonalną do odległości sensora od zadanego punktu.

Parametry wymagane:

  • lat (double) - szerokość geograficzna punktu w postaci dziesiętnej, np. 50.062006
  • lng (double) - długość geograficzna punktu w postaci dziesiętnej, np. 19.940984

Przykład zapytania

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/measurements/point?lat=50.062006&lng=19.940984'

Meta

Niektóre typy danych w API mają dynamiczny charakter i ich zakresy mogą zmieniać się w czasie. Np. w przyszłości w API mogą pojawić się nowe typy pomiarów (np. gazy) lub wsparcie dla indeksów z innych państw. Operacje z grupy /v2/meta zwracają informacje o tym jakie konkretnie rodzaje danych są aktualnie dostępne w API.

tip Dzięki operacjom meta można budować bardziej dynamiczne aplikacje i interfejsy użytkownika, które dostosowują się w locie do danych zwracanych przez API. Np. na naszej mapie kolorowa legenda opisująca poziomy indeksów tworzona jest właśnie dzięki operacji meta.

GET /v2/meta/indexes

Operacja zwraca listę typów indeksów dostępnych w API wraz z listą poziomów zdefiniowanych w ramach danego indeksu.

Lista zawiera obiekty typu IndexType, które zawierają następujące pola:

  • name (string) - nazwa typu indeksu, np. AIRLY_CAQI
  • levels - lista definicji poziomów indeksu, obiekty typu IndexLevel zawierające:
    • values (string)- tekstowy opis zakresu wartości danego indeksu obejmującego ten poziom, np. 0-25
    • level (string) - nazwa poziomu indeksu np. "VERY_LOW"
    • description (string) - opis poziomu indeksu (pole tłumaczone), np. "Bardzo Niski"
    • color (string) - wartość koloru dla tego poziomu indeksu (np. "#6BC926)

Przykład zapytania:

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/meta/indexes'

Przykład odpowiedzi

[
  {
    "name": "AIRLY_CAQI",
    "levels": [
      {
        "values": "0-25",
        "level": "VERY_LOW",
        "description": "Very Low",
        "color": "#6BC926"
      },
      ...
    ]
  },
  ...
]

GET /v2/meta/measurements

Operacja zwraca listę wszystkich typów pomiarów dostępnych w API wraz z ich nazwami i stosowanymi jednostkami.

Lista zawiera obiekty typu MeasurementType, które zawierają następujące pola

  • name (string) - nazwa typu pomiaru, np. PM10
  • label (string) - nazwa opisowa typu pomiaru (pole tłumaczone)
  • unit (string) - jednostka stosowana dla tego typu pomiaru

Przykład zapytania:

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/meta/measurements'

Przykład odpowiedzi

[
  {
    "name": "PM10",
    "label": "PM10",
    "unit": "µg/m³"
  },
  {
    "name": "TEMPERATURE",
    "label": "Temperature",
    "unit": "°C"
  },
  ...
]

GET /v2/meta/standards

Operacja zwraca listę typów standardów jakości powietrza dostępnych w API wraz z maksymalnymi, dopuszczalnymi wartościami stężeń dla poszczególnych składników zanieczyszczenia powietrza.

Lista zawiera obiekty typu StandardType, które zawierają następujące pola:

  • name (string) - nazwa typu standard, np. WHO
  • standardLimits - mapa klucz-wartość z maksymalnymi wartościami stężeń składników zanieczyszczenia powietrza zdefiniowanych przez standard, zawsze w µg/m³

Przykład zapytania:

curl -X GET \
    --header 'Accept: application/json' \
    --header 'apikey: <apikey>' \
    'https://airapi.airly.eu/v2/meta/standards'

Przykład odpowiedzi

[
  {
    "name": "WHO",
    "standardLimits": {
      "CO": 4000.0,
      "NO2": 25.0,
      "PM10": 45.0,
      "PM25": 15.0,
      "O3": 100.0,
      "SO2": 40.0
    }
  },
  ...
]

Podsumowanie

Dołożyliśmy wszelkich starań, aby niniejsza dokumentacja była napisana w sposób przejrzysty oraz zrozumiały. Gdyby jednak tak nie było, gorąco zachęcamy do jej ulepszania. Wszelkie zmiany możesz sugerować za pomocą platformy GitHub. Dziękujemy.