WordPress REST API — przegląd przed integracją z .NET

Zanim podłączysz WordPressa do aplikacji .NET, warto poznać jego REST API od środka — endpointy, autentykację i szybkie testy w Postmanie.

JAJarosław Armatys 7 min czytania
Wersja wideo tego wpisu — obejrzyj na YouTube

W poprzednim odcinku skończyliśmy na integracji z Google Places API — aplikacja konsolowa potrafi już pobrać dane firmy z bazy i wzbogacić je informacjami z Google. Teraz czas na drugą połowę pipeline'u: publikację tych danych jako wpisów w WordPressie. Zanim jednak napiszemy pierwszy HttpClient.PostAsync(...) z poziomu .NET, zatrzymajmy się na chwilę po stronie WordPressa. Zobaczmy, co on w ogóle wystawia, jak się do niego autoryzować i jak szybko sprawdzić, że wszystko odpowiada tak, jak powinno.

WordPress ma wbudowane REST API

Jeżeli nigdy nie zaglądałeś do WordPressa od strony dewelopera, to może być dla ciebie zaskoczenie: on od wersji 4.7 ma wbudowane REST API. Nie potrzebujesz żadnej dodatkowej wtyczki, żeby zacząć z nim gadać — wystarczy, że masz świeżą instalację.

Baza wszystkich endpointów jest zawsze pod tym samym prefiksem:

curl https://twoja-strona.pl/wp-json/

Pod tym adresem dostaniesz tzw. index — spis wszystkiego, co API udostępnia: namespace'y, routes, schematy danych. To jest twój pierwszy punkt orientacyjny, kiedy wchodzisz na nieznaną instancję WordPressa. Dla naszych potrzeb (importer, który publikuje ogłoszenia) interesuje nas namespace wp/v2 — to tam mieszka cała podstawowa treść: posty, kategorie, tagi, użytkownicy i media.

W WordPressie nie musisz budować endpointów od zera. Cała podstawowa treść — posty, strony, custom post types, taksonomie — wystawia się sama. Naszą rolą jest tylko się do niej poprawnie zaadresować i uwierzytelnić.

Najważniejsze endpointy

Kiedy piszesz klienta w .NET, najczęściej skończysz na czterech, może pięciu endpointach. Warto je znać z głowy:

# Lista postów
curl https://twoja-strona.pl/wp-json/wp/v2/posts

# Konkretny post po ID
curl https://twoja-strona.pl/wp-json/wp/v2/posts/123

# Kategorie i tagi (przydatne przy mapowaniu)
curl https://twoja-strona.pl/wp-json/wp/v2/categories
curl https://twoja-strona.pl/wp-json/wp/v2/tags

# Użytkownicy
curl https://twoja-strona.pl/wp-json/wp/v2/users

# Media (jeżeli wgrywasz zdjęcia razem z postami)
curl https://twoja-strona.pl/wp-json/wp/v2/media

GET /posts możesz odpalić od razu — nie wymaga autoryzacji, bo to publiczne treści widoczne na stronie. Spróbuj to zrobić od razu na swojej instancji: dostaniesz JSON-a z listą postów, statusami, datami, linkami, excerpt i content w dwóch formach — rendered (już jako HTML) i raw (surowe, ale tylko po autoryzacji).

Dla naszego WP Importera najważniejszy będzie POST /posts — to on tworzy nowe wpisy. W moim projekcie posts to w rzeczywistości custom post type listing (ogłoszenia firm), ale mechanika jest identyczna. Zmienia się tylko segment URL:

curl https://twoja-strona.pl/wp-json/wp/v2/listings

Jeżeli twój szablon używa custom post types, sprawdź w kodzie wtyczki albo motywu, jakie typy są zarejestrowane i czy mają flagę show_in_rest => true. Bez niej API ich po prostu nie zobaczy.

Application Passwords zamiast basic auth

I tu zaczyna się najciekawsze. GET publicznych postów idzie bez logowania, ale zapis — POST, PUT, DELETE — wymaga uwierzytelnienia. I tu jest kilka szkół.

W moim oryginalnym setupie (kręcony w 2022 roku) używałem wtyczki JWT Auth. Pobierałem token, wklejałem go jako Bearer i lecieliśmy dalej. Działa, ale dziś już nie polecam tej drogi — z prostego powodu. WordPress od wersji 5.6 ma wbudowany mechanizm Application Passwords, który robi dokładnie to samo, tylko bez instalowania żadnej wtyczki i bez martwienia się o konfigurację JWT secret key w wp-config.php.

Application Passwords to najprostsza i najbezpieczniejsza droga, żeby aplikacja zewnętrzna mogła pisać do WordPressa. Nie mylić ze zwykłym hasłem użytkownika — to osobny, długi ciąg, który możesz w każdej chwili unieważnić.

Jak to wygląda w praktyce:

  1. Wchodzisz w Użytkownicy → Twój profil w panelu WP.
  2. Scrollujesz na sam dół do sekcji Application Passwords.
  3. Wpisujesz nazwę (np. „WP Importer .NET"), klikasz Add New Application Password.
  4. WP pokaże ci jednorazowo ciąg typu abcd efgh ijkl mnop qrst uvwx — kopiujesz go do bezpiecznego miejsca (managera haseł, appsettings.json, secretów CI). Drugi raz go nie zobaczysz.

Od tej chwili możesz się logować zwykłym Basic Authem, ale zamiast hasła użytkownika podajesz Application Password. Przykładowe wywołanie:

curl -u "admin:xxxx xxxx xxxx xxxx xxxx xxxx" \
  -H "Content-Type: application/json" \
  -d '{"title":"Test","status":"publish","content":"Hello"}' \
  https://twoja-strona.pl/wp-json/wp/v2/posts

Spacje w haśle zostaw — są częścią formatu. cURL sam zakoduje to base64 i wstawi do nagłówka Authorization: Basic .... W .NET zrobisz to samo w HttpClient, tylko zamiast flagi -u dodasz DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64).

Co z rolami? Tu uważaj — to jest pułapka, którą sam złapałem. Jeżeli dostajesz 401 albo 403 przy próbie utworzenia wpisu, pierwsze co — sprawdź, czy twój użytkownik faktycznie ma uprawnienia do publikowania. Rola Subscriber nie wystarczy. Author też nie, jeśli piszesz pod cudzym userem. W produkcyjnym setupie zakładaj dedykowane konto z rolą Editor albo custom role z flagą publish_posts, nigdy nie używaj admina aplikacji z automatu.

Testowanie w Postmanie

Zanim odpalisz .NET, zrób sobie przysługę — wszystkie scenariusze przetestuj najpierw w Postmanie albo zwykłym curlu. To cofa godziny debugowania. Ja typowo mam rozpisane cztery zapytania:

1. GET /posts — sanity check, czy API w ogóle odpowiada:

curl https://twoja-strona.pl/wp-json/wp/v2/posts?per_page=3

2. POST /posts bez autoryzacji — żeby zobaczyć, jaki błąd WP zwraca, kiedy nie ma credentiali:

curl -X POST https://twoja-strona.pl/wp-json/wp/v2/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"No auth","status":"publish"}'

Dostaniesz 401 z kodem rest_cannot_create — warto go znać, bo to najczęstsza odpowiedź, jaką zobaczysz z produkcji, kiedy coś pójdzie nie tak.

3. POST /posts z poprawnym Application Password — happy path:

curl -u "importer:abcd efgh ijkl mnop" \
  -H "Content-Type: application/json" \
  -d '{"title":"Siemka YouTube","status":"publish","content":"Treść z aplikacji"}' \
  https://twoja-strona.pl/wp-json/wp/v2/posts

Odpowiedź to pełny obiekt wpisu — włącznie z wygenerowanym id, slug, link i datą publikacji. Zapisz sobie ten JSON jako fixture do testów integracyjnych w .NET.

4. POST /posts z custom metadanymi — bo w realnym WordPressie rzadko kiedy wystarczy sam tytuł i content. W moim projekcie każde ogłoszenie ma NIP, KRS, formę prawną — to są meta fields dodane przez szablon. WP domyślnie ich nie wystawia w REST. Musisz albo dopisać register_meta(...) w kodzie, albo użyć wtyczki w stylu ACF to REST API / Meta Box, żeby pole pokazało się w JSON-ie i dało się zapisać.

Sprawdź najpierw, co dostajesz w odpowiedzi GET — jeżeli twojego meta pola nie ma w response, to zapis też nie zadziała, niezależnie od tego, jak poprawnie zbudujesz body. REST API WordPressa jest strict w obie strony.

Kiedy zapytania działają w Postmanie, przeniesienie tego do .NET sprowadza się do trzech rzeczy: skonfigurować HttpClient z base URL-em, dodać nagłówek Authorization: Basic <base64> i serializować body przez JsonContent.Create(...). Całą logikę zamkniesz w jednym serwisie typu IWordPressClient, który wstrzykniesz przez DI — czyli dokładnie tak, jak to zrobiliśmy wcześniej dla klienta Google Places.

Co dalej?

W następnym odcinku bierzemy to, co przed chwilą przeklikaliśmy w Postmanie, i przenosimy do naszej aplikacji konsolowej. Pokażę, jak w .NET pobrać dane do logowania z appsettings.json, zbudować kliencką klasę do WordPressa i zrobić pierwszy realny POST /posts z poziomu kodu — z pełną obsługą odpowiedzi i błędów. A potem dorzucimy do tego pętlę, która przejedzie wszystkie firmy z bazy i opublikuje je jako ogłoszenia jedna po drugiej.

Jeżeli masz pytania do tego, jak skonfigurować Application Passwords albo jak ominąć brakujące pola meta — walnij w komentarz, chętnie rozwinę temat w osobnym filmiku.

Tagi:#course-dotnet-wordpress#wordpress#api#rest

Masz pytanie do tego wpisu?

Napisz do mnie — chętnie porozmawiam o szczegółach technicznych, albo o tym jak zastosować to u Ciebie w projekcie.