StriveLab
Strony internetowe
Usługi
RealizacjeO mnieBlogPorozmawiajmy
PL
EN

Astro

Ultraszybkie projekty, łączące lekkość ze skalowalnością.

Next.js

Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.

React

Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.

SEO & Performance

Audyt techniczny i optymalizacja pod kątem SEO i GEO.

Automatyzacja AI

Bezpieczne automatyzacje procesów i agenci AI w n8n, Make i Claude.

QA & Automation

Testy automatyczne komponentów i E2E w Cypress.

Doradztwo produktowe

Połączenie perspektywy produktu, developera i marketingu w jednym miejscu

StriveLab
Strony internetowe
Usługi
RealizacjeO mnieBlogPorozmawiajmy
PL
EN

Astro

Ultraszybkie projekty, łączące lekkość ze skalowalnością.

Next.js

Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.

React

Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.

SEO & Performance

Audyt techniczny i optymalizacja pod kątem SEO i GEO.

Automatyzacja AI

Bezpieczne automatyzacje procesów i agenci AI w n8n, Make i Claude.

QA & Automation

Testy automatyczne komponentów i E2E w Cypress.

Doradztwo produktowe

Połączenie perspektywy produktu, developera i marketingu w jednym miejscu

Astro

Ultraszybkie projekty, łączące lekkość ze skalowalnością.

Next.js

Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.

React

Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.

SEO & Performance

Audyt techniczny i optymalizacja pod kątem SEO i GEO.

Automatyzacja AI

Bezpieczne automatyzacje procesów i agenci AI w n8n, Make i Claude.

QA & Automation

Testy automatyczne komponentów i E2E w Cypress.

Doradztwo produktowe

Połączenie perspektywy produktu, developera i marketingu w jednym miejscu

RealizacjeO mnieBlog
Porozmawiajmy
PL
EN

Nowoczesne strony internetowe dla firm, które myślą odważnie.

Przewiń do góry

Nazwa

StriveLab Maciej Sala

NIP

6772218995

REGON

524008527

E-mail

contact@strivelab.pl

Usługi główne
  • Tworzenie stron internetowych
  • Strony internetowe Next.js
  • Strony internetowe Astro
  • Strony internetowe React
Inne usługi
  • Usługi
  • SEO & Performance Sprint
  • QA & Stabilizacja
  • Konsultacje Product / Delivery
  • Automatyzacja Procesów AI
  • Aplikacje webowe Next.js
  • Współpraca ciągła
Strony
  • O mnie
  • Usługi
  • Realizacje
  • Blog

© 2026 StriveLab.pl

Polityka prywatności
Backend

REST API — zasady projektowania i dobre praktyki

Praktyczny przewodnik po projektowaniu REST API. Konwencje URL, metody HTTP, błędy, wersjonowanie, paginacja i kilka ważnych niuansów, które zwykle pomija się w prostych tutorialach.

OpublikujLinkedInFacebookWyślij
Autor
Maciej Sala
Opublikowano
5 grudnia 2025 14:20
Czytanie
11 min czytania
Aktualizacja
27 maja 2026 08:00

REST (Representational State Transfer) to styl architektoniczny, który mocno wpłynął na web, a w praktyce większość API, z którymi pracujesz jako frontend developer, to raczej HTTP API inspirowane REST niż "czysty REST" z podręcznika.

Artykuł w skrócie

  • Zasoby w URL, akcje w metodach — /users/123 to zasób, DELETE /users/123 to operacja; nie używaj czasowników w URL (/deleteUser)
  • Kody statusu muszą być zgodne z semantyką — 201 dla tworzenia, 204 dla delete bez body, 400 dla błędu klienta, 409 dla konfliktu
  • Paginacja zawsze — nigdy nie zwracaj nieograniczonej listy; offset lub cursor, ale zawsze z limit i informacją o całkowitej liczbie rekordów
  • RFC 9457 dla błędów — strukturalny format error response z type, title, status, detail i instance zamiast dowolnych stringów
  • Wersjonowanie API — /v1/users lub nagłówek Accept-Version; zmiany breaking bez wersjonowania psują klientów produkcyjnych
  • Konwencje > puryzm — spójne nazewnictwo, statusy i format odpowiedzi w całym API są ważniejsze niż akademicka zgodność ze specyfikacją REST

Ale REST to nie tylko "używaj HTTP". To zbiór konwencji i zasad, które sprawiają, że API jest intuicyjne, przewidywalne i łatwe w użyciu.

W tym artykule poznasz zasady projektowania REST API to interfejs udostępniający dane przez standardowe metody HTTP (GET, POST...) pod adresami zasobów — w WordPressie domyślnie pod /wp-json/. — zarówno jako konsument (frontend), jak i twórca (backend). Szerszy kontekst aplikacyjny znajdziesz w przewodniku Backend dla frontendowca: serwer, bazy danych i API.

Top tip

Najważniejsza cecha dobrego REST API to przewidywalność. Jeśli nazwy zasobów, statusy błędów, paginacja i format odpowiedzi są konsekwentne, frontend szybciej buduje stabilne stany UI.

Zasady REST

REST opisuje sześć właściwości, które razem tworzą architekturę zwaną Representational State Transfer. Warto je znać nie po to, żeby cytatować ze specyfikacji, ale żeby rozumieć, dlaczego pewne decyzje projektowe są lepsze od innych.

1. Client-Server

Klient (frontend) i serwer (backend) są od siebie oddzielone i komunikują się przez HTTP. Ta separacja oznacza, że frontend może ewoluować niezależnie od backendu — wystarczy zachować kontrakt API. Możesz na przykład przepisać całe UI na inny framework bez dotykania backendu, albo wymienić silnik bazy danych bez wpływu na klientów.

2. Stateless

Każdy request powinien zawierać wszystko, czego serwer potrzebuje do jego obsługi — bez polegania na stanie sesji po stronie serwera. W praktyce wiele API łączy to z tokenami JWT w nagłówkach Authorization, co pozwala na stateless uwierzytelnianie. Jeśli API korzysta z sesji serwerowych lub cookies, jest to technicznie odejście od czystego REST, ale w realu to częsty kompromis — ważniejsze jest, żeby kontrakt był spójny i dobrze udokumentowany.

3. Cacheable

Odpowiedzi powinny jawnie informować klientów, czy można je cachować i jak długo. Nagłówki Cache-Control i ETag to podstawa — dzięki nim przeglądarka, CDN lub reverse proxy mogą serwować odpowiedzi bez angażowania backendu. Dla API publicznych to realny wpływ na koszty infrastruktury i czas odpowiedzi.

4. Uniform Interface

Jednolity interfejs to serce REST — zasoby identyfikowane przez URL, operacje przez metody HTTP, standaryzowane kody statusu. Dzięki tej jednolitości developer integrujący nowe API może w dużej mierze przewidzieć jego zachowanie bez czytania dokumentacji od deski do deski.

5. Layered System

Klient nie powinien zakładać, że komunikuje się bezpośrednio z serwerem docelowym. Pomiędzy nimi mogą stać load balancery, cache'e, API gateway czy reverse proxy — i to jest poprawna, wręcz pożądana architektura. Dobry design REST uwzględnia, że warstwa pośrednia może np. cachować GET-y albo rozdzielać ruch.

6. Code on Demand (opcjonalne)

Serwer może opcjonalnie przekazywać klientowi wykonywalny kod (np. JavaScript). W praktyce ta zasada jest rzadko stosowana i często pomijana w opisach REST.

Struktura URL

Zasoby (Resources)

Pierwsza zasada, której złamanie natychmiast widać w code review: URL powinien nazywać zasób, a nie akcję. Metoda HTTP jest od opisywania co robisz — URL jest od opisywania z czym.

Code
✅ Dobrze (rzeczowniki):
GET /users
GET /users/123
GET /users/123/posts

❌ Źle (czasowniki):
GET /getUsers
GET /getUserById/123
POST /createUser

Wzorzec z czasownikami pochodzi z epoki SOAP i RPC — w REST nie ma dla niego miejsca. Jeśli masz ochotę napisać /deleteUser/123, to sygnał, że powinieneś napisać DELETE /users/123.

Kolekcje vs pojedyncze zasoby

Ten podział jest fundamentem REST: kolekcja zasobów ma inny URL niż pojedynczy zasób, a operacje na obu wyglądają inaczej.

Code
/users          → kolekcja wszystkich użytkowników
/users/123      → pojedynczy użytkownik o ID 123
/users/123/posts → posty użytkownika 123

POST /users tworzy nowy zasób w kolekcji. DELETE /users/123 usuwa konkretny zasób z kolekcji. Frontend integrujący takie API może wywnioskować semantykę bez czytania dokumentacji.

Zagnieżdżone zasoby

Zagnieżdżenie w URL wyraża relację między zasobami — komentarze należą do posta, posty należą do użytkownika:

Code
GET /users/123/posts         → posty użytkownika
GET /users/123/posts/456     → konkretny post użytkownika
GET /posts/456/comments      → komentarze do posta

Zasada praktyczna: zatrzymaj się na maksymalnie 2-3 poziomach. Głębsze drzewo (/users/123/posts/456/comments/789/replies) jest trudne do czytania i sugeruje, że relacja powinna być modelowana inaczej — np. przez filtrowanie: GET /replies?commentId=789.

Konwencje nazewnictwa

Konsekwencja w nazewnictwie jest ważniejsza niż wybór konkretnej konwencji — ale warto wybrać tę, którą web de facto stosuje:

Code
✅ Dobrze:
/users              (liczba mnoga)
/blog-posts         (kebab-case)
/user-profiles

❌ Źle:
/user               (liczba pojedyncza)
/blogPosts          (camelCase)
/user_profiles      (snake_case w URL)

Liczba mnoga dla kolekcji odzwierciedla fakt, że zasób to zbiór rekordów, nie jeden rekord. Kebab-case jest standardem webowym — camelCase jest dla właściwości JSON, nie segmentów URL.

Metody HTTP i CRUD

Metoda HTTP wyraża intencję operacji — to ta część requestu, która odpowiada na pytanie "co chcesz zrobić z tym zasobem?". Mapowanie na CRUD to skrót od Create, Read, Update, Delete, czyli podstawowych operacji wykonywanych na danych. jest intuicyjne, ale ma kilka niuansów, które warto znać zanim zaczniesz projektować API.

MetodaCRUDOpisIdempotentna?Przykład
GETReadPobierz zasóbTakGET /users/123
POSTCreateUtwórz zasóbNiePOST /users
PUTUpdateZastąp zasóbTakPUT /users/123
PATCHUpdateCzęściowa aktualizacjaZależyPATCH /users/123
DELETEDeleteUsuń zasóbTakDELETE /users/123

Idempotencja oznacza, że wielokrotne wywołanie tej samej operacji daje ten sam efekt. Jeśli klient wyśle DELETE /users/123 dwa razy — drugi raz powinien dostać 404, ale stan serwera jest ten sam. Przy POST każde wywołanie tworzy nowy zasób — retry bez zabezpieczenia to duplikat.

GET — pobieranie

Code
# Kolekcja
GET /users
Response: 200 OK
{
  "data": [
    { "id": 1, "name": "Jan" },
    { "id": 2, "name": "Anna" }
  ]
}
 
# Pojedynczy zasób
GET /users/1
Response: 200 OK
{ "id": 1, "name": "Jan", "email": "jan@example.com" }
 
# Nieistniejący zasób
GET /users/999
Response: 404 Not Found

POST — tworzenie

Code
POST /users
Content-Type: application/json
 
{ "name": "Piotr", "email": "piotr@example.com" }
 
Response: 201 Created
Location: /users/3
{ "id": 3, "name": "Piotr", "email": "piotr@example.com" }

PUT — pełna aktualizacja

Code
PUT /users/3
Content-Type: application/json
 
{ "name": "Piotr Nowak", "email": "piotr.nowak@example.com" }
 
Response: 200 OK
{ "id": 3, "name": "Piotr Nowak", "email": "piotr.nowak@example.com" }

PUT zazwyczaj oznacza pełną reprezentację zasobu — jeśli nie przekażesz jakiegoś pola, serwer powinien je wyzerować lub usunąć. To jest często źródło bugów, gdy frontend wysyła tylko zmodyfikowane pola, a serwer traktuje brakujące jako "usuń". Dlatego PUT warto stosować tylko wtedy, gdy faktycznie chcesz zastąpić cały zasób.

PATCH — częściowa aktualizacja

Code
PATCH /users/3
Content-Type: application/json
 
{ "email": "nowy.email@example.com" }
 
Response: 200 OK
{ "id": 3, "name": "Piotr Nowak", "email": "nowy.email@example.com" }

PATCH aktualizuje tylko przekazane pola. To najwygodniejsza metoda dla typowych operacji — zmiana emaila, statusu, jednej właściwości — bez ryzyka przypadkowego wyzerowania reszty obiektu. Warto jednak pamiętać, że semantyka PATCH nie jest tak rygorystycznie ustandaryzowana jak PUT — różne API implementują ją różnie, dlatego dokładne zachowanie powinno być opisane w dokumentacji.

DELETE — usuwanie

Code
DELETE /users/3
 
Response: 204 No Content

Kody statusu HTTP

Kody statusu to pierwsza linia komunikacji między serwerem a klientem — zanim frontend przeczyta body odpowiedzi, sprawdza kod. Właściwe kody pozwalają frontendowi podjąć decyzję (pokaż błąd, przekieruj na login, odśwież token) bez parsowania treści. Błędne kody — np. 200 z błędem w body — łamią tę konwencję i utrudniają cachowanie, obsługę błędów i debugowanie.

2xx — Sukces

KodZnaczenieKiedy
200OKGET, PUT, PATCH sukces
201CreatedPOST sukces (nowy zasób)
204No ContentDELETE sukces, brak body

201 Created powinien pojawić się przy każdym POST, który tworzy zasób. Warto przy nim zwracać nagłówek Location z URL nowego zasobu — klient wie wtedy, gdzie sięgnąć po szczegóły bez dodatkowego GET-a. 204 No Content jest właściwą odpowiedzią na DELETE — operacja zakończyła się sukcesem, ale nie ma nic do zwrócenia.

4xx — Błąd klienta

KodZnaczenieKiedy
400Bad RequestNieprawidłowe dane
401UnauthorizedBrak/nieprawidłowy token
403ForbiddenBrak uprawnień
404Not FoundZasób nie istnieje
409ConflictKonflikt (duplikat)
422Unprocessable EntityBłąd walidacji
429Too Many RequestsRate limit

Dwa kody, które regularnie powodują zamieszanie:

401 vs 403 — 401 znaczy "nie wiem kim jesteś, zaloguj się", 403 znaczy "wiem kim jesteś, ale nie wolno Ci". Różnica jest fundamentalna dla frontend handlera: przy 401 powinno nastąpić przekierowanie na login lub odświeżenie tokenu, przy 403 wystarczy pokazać komunikat o braku uprawnień.

400 vs 422 — 400 to ogólny błąd formatu requestu (niepoprawny JSON, brakujące wymagane nagłówki), 422 to poprawny syntaktycznie request, który nie przeszedł walidacji biznesowej (np. email jest stringiem, ale nie ma znaku @). W praktyce wiele API używa tylko 400 dla obu przypadków — ważniejsze niż wybór kodu jest spójny, szczegółowy format błędu w body.

409 Conflict jest właściwy przy próbie stworzenia duplikatu (użytkownik z tym samym emailem już istnieje) lub przy konflikcie optymistycznego lockingu.

5xx — Błąd serwera

KodZnaczenieKiedy
500Internal Server ErrorNieoczekiwany błąd
502Bad GatewayProblem z upstream
503Service UnavailableSerwer przeciążony

Błędy 5xx zawsze należą do serwera — klient nie może z nimi nic zrobić poza poczekaniem i ponowieniem. 503 Service Unavailable powinien być zwracany z nagłówkiem Retry-After, żeby klient wiedział, kiedy próbować ponownie. Nigdy nie zwracaj 5xx dla błędów walidacji czy braku uprawnień — to 4xx, i to ważne rozróżnienie przy monitoringu i alertach.

Format odpowiedzi

Dobry format odpowiedzi to taki, którego klient nie musi zgadywać. Jeśli sukces wygląda inaczej przy GET a inaczej przy POST, a błąd ma różną strukturę w zależności od endpointa — integracja staje się obroną przed własnym API.

Sukces

Code
{
  "id": 123,
  "name": "Jan Kowalski",
  "email": "jan@example.com",
  "createdAt": "2025-01-15T10:30:00Z"
}

Daty powinny być zawsze w formacie ISO 8601 (2025-01-15T10:30:00Z) — łatwe do parsowania w każdym języku, jednoznaczne co do strefy czasowej.

Błąd — RFC 9457

Standard RFC 9457 (Problem Details for HTTP APIs) definiuje jednolity format dla błędów API. Zamiast wymyślać własną strukturę, warto trzymać się tego standardu:

Code
{
  "type": "https://example.com/errors/validation-error",
  "title": "Validation Error",
  "status": 422,
  "detail": "One or more fields failed validation.",
  "instance": "/api/v1/users",
  "errors": [
    { "field": "email", "message": "Invalid email format" },
    { "field": "name", "message": "Name is required" }
  ]
}

Pola type (URI identyfikujące klasę błędu), title (czytelna dla człowieka nazwa klasy), status (kod HTTP) i detail (szczegółowy opis) tworzą maszynoczytelną i jednocześnie czytelną dla developera strukturę. instance wskazuje konkretne wystąpienie błędu, co ułatwia debugowanie i korelację z logami.

Nawet jeśli nie chcesz pełnego RFC 9457, trzymaj się jednej zasady: spójny format błędów przez całe API. Mieszanie { "error": "..." }, { "message": "..." } i { "errors": [...] } w różnych endpointach to klasyczny dług techniczny.

Kolekcja z metadanymi

Code
{
  "data": [
    { "id": 1, "name": "Jan" },
    { "id": 2, "name": "Anna" }
  ],
  "meta": {
    "total": 100,
    "page": 1,
    "perPage": 10,
    "totalPages": 10
  }
}

Wrapper data + meta jest przydatny, bo pozwala rozszerzyć odpowiedź o metadane bez breaking change — wystarczy dodać nowe pole do meta.

Filtrowanie, sortowanie, paginacja

Filtrowanie (query parameters)

Code
GET /users?status=active
GET /users?role=admin&status=active
GET /products?category=electronics&minPrice=100&maxPrice=500
GET /posts?author=123&createdAfter=2025-01-01

Sortowanie

Code
GET /users?sort=name           # rosnąco
GET /users?sort=-createdAt     # malejąco (minus)
GET /users?sort=role,-name     # wielokrotne

Alternatywna konwencja:

Code
GET /users?sortBy=name&order=asc

Paginacja

Offset-based:

Code
GET /users?page=2&perPage=10
GET /users?offset=10&limit=10

Cursor-based (lepsze dla dużych zbiorów):

Code
GET /users?cursor=abc123&limit=10

Offset pagination jest prostsza do implementacji i wygodna przy panelach admina, gdzie użytkownik chce przejść na konkretną stronę wyników. Ma jednak wadę przy dużych, zmieniających się zbiorach: jeśli ktoś doda rekord między requestami, page 2 może zawierać duplikaty z page 1 albo pominąć rekord.

Cursor pagination rozwiązuje ten problem — każda strona zaczyna od konkretnego punktu w zbiorze (zwykle ID lub timestamp ostatniego rekordu), niezależnie od tego, co się zdarzyło w zbiorze między requestami. To właściwy wybór dla nieskończonego przewijania, real-time feedów i API z wysoką częstotliwością zmian danych.

Odpowiedź z paginacją:

Code
{
  "data": [...],
  "meta": {
    "total": 100,
    "page": 2,
    "perPage": 10,
    "totalPages": 10,
    "nextPage": "/users?page=3&perPage=10",
    "prevPage": "/users?page=1&perPage=10"
  }
}

Wybór pól (sparse fieldsets)

Code
GET /users?fields=id,name,email
GET /users/123?fields=name,avatar

To wygodne, ale warto whitelistować pola po stronie serwera, żeby klient nie mógł wyciągać wszystkiego bez kontroli.

Include (eager loading)

Code
GET /posts/123?include=author,comments

Tak samo jak przy fields, warto posiadać limit dopuszczalnych relacji, żeby nie zrobić przypadkiem własnego "mini-GraphQL bez guardrailów".

Code
{
  "id": 123,
  "title": "Post",
  "author": { "id": 1, "name": "Jan" },
  "comments": [...]
}

Wersjonowanie API

W URL (najpopularniejsze)

Code
GET /api/v1/users
GET /api/v2/users

W nagłówku

Code
GET /api/users
Accept: application/vnd.myapp.v2+json
# lub dedykowany nagłówek:
API-Version: 2

W query parameter

Code
GET /api/users?version=2

Rekomendacja: Wersjonowanie w URL jest najprostsze i najbardziej widoczne, ale nie każde API musi zaczynać od /v1, dlatego czasami wystarczy po prostu dobra kompatybilność wstecz i przemyślane polityki zmian.

Autoryzacja

Bearer Token (JWT)

Code
GET /api/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

API Key

Code
GET /api/users
X-API-Key: your-api-key

Odpowiedzi

Code
# Brak tokenu
401 Unauthorized
{ "error": "Authentication required" }
 
# Token wygasł
401 Unauthorized
{ "error": "Token expired" }
 
# Brak uprawnień
403 Forbidden
{ "error": "Insufficient permissions" }

Wersjonowanie API — kiedy i jak

Wersjonowanie API to jeden z tych tematów, które boli dopiero wtedy, gdy jest za późno. Jeśli masz publiczne API i wprowadzisz breaking change bez wersjonowania, psujesz wszystkich konsumentów naraz.

Breaking change to m.in.:

  • zmiana nazwy pola lub usunięcie pola z odpowiedzi
  • zmiana typu pola (string → number)
  • zmiana znaczenia kodu statusu dla danego endpointa
  • usunięcie endpointa

Non-breaking change to m.in.:

  • dodanie nowego opcjonalnego pola w odpowiedzi
  • dodanie nowego endpointa
  • dodanie opcjonalnego query parametru

Wersjonowanie w URL (/api/v1/users) jest najpopularniejsze i najprostsze — widać je w URL, łatwo testować, logować i routować na różne implementacje. Wadą jest to, że trzeba utrzymywać kilka wersji jednocześnie. Praktyczna zasada: zacznij od /v1 przy pierwszym publicznym release'ie, nawet jeśli nie masz jeszcze /v2 w planach. Dodanie wersjonowania do bezwersyjnego API jest samo w sobie breaking change.

Rate Limiting

API powinno informować o limitach:

Code
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000

Po przekroczeniu:

Code
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
  "error": "Rate limit exceeded",
  "retryAfter": 60
}

Idempotency dla wrażliwych POST-ów

Tworzenie zasobów po POST nie jest idempotentne, przy płatnościach, webhookach albo retriable requestach warto dodać klucz idempotencyjny:

Code
POST /payments
Idempotency-Key: 6d2f7b2f-8f16-4f1b-a5a8-123456789abc

Serwer powinien rozpoznać ponowienie tego samego żądania i nie wykonać operacji drugi raz.

HATEOAS (opcjonalne)

Hypermedia As The Engine Of Application State, czyli linki do powiązanych zasobów:

Code
{
  "id": 123,
  "name": "Jan",
  "_links": {
    "self": { "href": "/users/123" },
    "posts": { "href": "/users/123/posts" },
    "followers": { "href": "/users/123/followers" }
  }
}

W praktyce jest to rzadko w pełni implementowane, ale warto chociaż poznać koncept.

Przykład: API do bloga

Endpoints

Code
# Posty
GET    /api/v1/posts              # lista postów
GET    /api/v1/posts/:id          # pojedynczy post
POST   /api/v1/posts              # utwórz post
PUT    /api/v1/posts/:id          # aktualizuj post
DELETE /api/v1/posts/:id          # usuń post

# Komentarze
GET    /api/v1/posts/:id/comments          # komentarze do posta
POST   /api/v1/posts/:id/comments          # dodaj komentarz
DELETE /api/v1/posts/:id/comments/:cid     # usuń komentarz

# Użytkownicy
GET    /api/v1/users/:id          # profil użytkownika
GET    /api/v1/users/:id/posts    # posty użytkownika

Przykładowe żądania

Code
# Lista postów z filtrowaniem i paginacją
GET /api/v1/posts?status=published&sort=-createdAt&page=1&perPage=10
 
# Utwórz post
POST /api/v1/posts
Authorization: Bearer <token>
Content-Type: application/json
 
{
  "title": "Mój nowy post",
  "content": "Treść posta...",
  "tags": ["javascript", "react"]
}
 
# Odpowiedź
201 Created
{
  "id": 456,
  "title": "Mój nowy post",
  "slug": "moj-nowy-post",
  "content": "Treść posta...",
  "author": {
    "id": 123,
    "name": "Jan"
  },
  "tags": ["javascript", "react"],
  "createdAt": "2025-01-15T10:30:00Z"
}

Werdykt Labu

REST to konwencje, nie protokół. W praktyce większość API w webie to "REST-like HTTP API" — i to jest w porządku, o ile decyzje są świadome i konsekwentne przez całe API.

Konsekwencja w strukturze URL, semantyce kodów statusu i formacie błędów jest ważniejsza niż akademicka zgodność ze specyfikacją. Deweloper integrujący Twoje API powinien móc przewidzieć zachowanie nowego endpointa na podstawie istniejących — bez zagłębiania się w dokumentację każdego z nich. Paginacja, wersjonowanie i rate limiting warto przemyśleć przed pierwszym publicznym release'em, bo dodawanie ich później jest breaking change. W kontekście Next.js — rate limiting z Upstash to dobry pierwszy krok.

ŹródłaZweryfikowano: 31 maja 2026

Specyfikacje HTTP i materiały o projektowaniu REST API zweryfikowane podczas redakcji artykułu.

  • MDN — HTTP request methods
  • MDN — HTTP response status codes
  • RFC 9110 — HTTP Semantics
  • Microsoft — REST API design guidelines

Chcesz zbudować własne API? Przejdź do Backend dla frontendowca: serwer, bazy danych i API.

  • Zasady REST2 min
  • Struktura URL1 min
  • Metody HTTP i CRUD2 min
  • Kody statusu HTTP3 min
  • Format odpowiedzi1 min
  • Filtrowanie, sortowanie, paginacja1 min
  • Wersjonowanie API1 min
  • Autoryzacja1 min
  • Wersjonowanie API — kiedy i jak1 min
  • Rate Limiting1 min
  • Idempotency dla wrażliwych POST-ów1 min
  • HATEOAS (opcjonalne)1 min
  • Przykład: API do bloga1 min
  • Werdykt Labu1 min

Często zadawane pytania

Maciej Sala

O autorze

Maciej Sala

Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwija własne projekty side-projecty.

Moje artykułyWięcej o mnie

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną

Biblioteka wiedzy

Czytaj dalej

Zobacz więcej wpisów
Backend dla frontendowca: serwer, bazy danych i API
Backend dla frontendowca: serwer, bazy danych i API

Pierwsza część serii Backend dla frontendowca: architektura aplikacji, serwer, bazy danych, API, status code, paginacja, idempotency, BFF i CORS.

Maciej Sala

Maciej Sala

Founder Strivelab

28 lipca 2025
REST API WordPressa — integracja z React i Next.js
REST API WordPressa — integracja z React i Next.js

Jak połączyć WordPress z nowoczesnym frontendem bez typowych pułapek? REST API, autentykacja, custom endpoints, cache i praktyczne przykłady z Next.js.

Maciej Sala

Maciej Sala

Founder Strivelab

29 stycznia 2025
Backend dla frontendowca: cache, deployment i bezpieczeństwo
Backend dla frontendowca: cache, deployment i bezpieczeństwo

Trzecia część serii Backend dla frontendowca: Redis, HTTP cache, kolejki, file storage, deployment, CI/CD, monitoring, OWASP, rate limiting i RODO.

Maciej Sala

Maciej Sala

Founder Strivelab

30 lipca 2025
Poprzedni wpisCypress vs Playwright – który wybrać do projektu Next.js?Cypress czy Playwright do projektu Next.js? Różnice w DX, CI, browser support, component testing i realne kryteria wyboru bez fanbojstwa.
Maciej Sala

Maciej Sala

Founder Strivelab

26 listopada 2025
Następny wpisGoogle Ads Remarketing w React – dynamiczne listy odbiorców i personalizacja reklamRemarketing Google Ads w React i Next.js bez marketingowych uproszczeń: eventy, Merchant Center, listy odbiorców w GA4, Customer Match i wymogi consent.
Maciej Sala

Maciej Sala

Founder Strivelab

6 grudnia 2025