API, z którym przyjemnie się pracuje, to zasługa konkretnych decyzji projektowych. Nie chodzi o filozofię, tylko o kilka praktyk, które robią różnicę w codziennej pracy programisty klienta.
Zasoby, nie akcje
REST skupia się na zasobach. Zamiast /getUserOrders?userId=5 masz /users/5/orders. Zamiast /createProduct masz POST /products. URL opisuje co, metoda HTTP opisuje operację: GET (odczyt), POST (tworzenie), PUT/PATCH (aktualizacja), DELETE (usunięcie). Konsekwentne trzymanie się tej konwencji sprawia, że API jest przewidywalne.
Spójne kody HTTP
200 to sukces, 201 to stworzenie zasobu, 400 to błąd walidacji po stronie klienta, 401 to brak autoryzacji, 403 to brak uprawnień, 404 to brak zasobu, 500 to błąd serwera. Zwracanie 200 z treścią {"error": "not found"} myli klientów i utrudnia obsługę błędów.
Wersjonowanie
API zmieniają się razem z aplikacją. Wersjonowanie przez URL (/api/v1/) lub nagłówek (Accept: application/vnd.api+json;version=1) pozwala wprowadzać zmiany bez łamania istniejących integracji. Brak wersjonowania na początku to dług, który prędzej czy później kosztuje.
Paginacja i filtrowanie
Endpointy zwracające kolekcje powinny obsługiwać paginację. Zwracanie tysięcy rekordów w jednej odpowiedzi obciąża i serwer i klienta. Typowe podejście to parametry page i per_page z metadanymi paginacji w odpowiedzi. Filtrowanie przez query params (?status=active&category=5) jest intuicyjne i łatwe do rozszerzenia.
Czytelne błędy
Odpowiedź błędu powinna mówić co poszło nie tak i dlaczego. Zamiast {"error": "validation failed"} lepiej {"errors": {"email": "Pole email jest wymagane", "name": "Pole name nie może być dłuższe niż 100 znaków"}}. Programista wie co poprawić bez szukania w logach.
Dokumentacja żywa z kodem
Dokumentacja API pisana osobno od kodu desynchronizuje się. Narzędzia jak Swagger/OpenAPI pozwalają generować interaktywną dokumentację bezpośrednio z adnotacji w kodzie lub ze specyfikacji YAML. Klienci API dostają możliwość testowania żądań bez pisania własnego kodu.