Przejdź do głównej zawartości

REST i GraphQL API w Claude Code

Claude Code buduje niezawodne API REST i GraphQL, gdy kontrakt powstaje pierwszy: plik OpenAPI lub schemat GraphQL uzgodniony w trybie planowania, a potem implementacja po jednym zasobie, zaczynając od testów. Człowiek przegląda kontrakt. Lint specyfikacji, fuzzing zgodności ze schematem, test pokrycia uwierzytelniania i hook Stop dowodzą, że handlery się z nim zgadzają.

Partner potrzebuje dwunastu endpointów, OAuth2 client credentials, limitów zapytań i podpisanych webhooków w dwa tygodnie. Prosisz Claude Code o „API dla partnera” i dostajesz naraz 2000 linii: trzy różne kształty błędów, jedną trasę bez uwierzytelniania i plik OpenAPI, który opisuje to, o co prosiłeś, a nie to, co faktycznie trafiło do kodu. Ta strona jest dla programistów, którzy budują endpointy API w terminalu z Claude Code, oraz dla tech leadów, którzy chcą, żeby każda zmiana API w repozytorium przechodziła te same bramki bez przeglądu linijka po linijce.

  • Pętlę kontrakt-najpierw: projekt w trybie planowania, zatwierdzenie specyfikacji, implementacja po jednym zasobie na iterację.
  • Pięć promptów do skopiowania: projekt kontraktu, iteracja zasobu zaczynająca się od testów, test pokrycia uwierzytelniania, naprawa N+1 w GraphQL z asercją liczby zapytań oraz podpisane dostarczanie webhooków.
  • Zestaw bramek, który dowodzi zgodności bez czytania każdego handlera: Spectral, Schemathesis, test pokrycia uwierzytelniania i hook Stop.
  • Subagenta recenzenta kontraktów API w trybie tylko do odczytu, którego możesz zacommitować jeszcze dziś.
  • Typowe awarie API pisanych przez agenta, każdą z procedurą naprawy.

Claude Code czyta CLAUDE.md na początku każdej sesji. Wpisz tam decyzje, które recenzent API sprawdza ręcznie, żeby agent nie musiał ich zgadywać, a każda iteracja stosowała tę samą odpowiedź. Gdzie umieścić plik, opisuje strona o ładowaniu plików pamięci Claude Code.

## API conventions (CLAUDE.md)
- Contract: docs/openapi.yaml is the source of truth. Change it first, in its own commit.
- Stack: Express + TypeScript, Zod for validation, Vitest + supertest for tests.
- Every error response uses ErrorResponse from src/types/api.ts:
{ "error": "UPPER_SNAKE_CODE", "message": string, "requestId": string, "details"?: [...] }
- Middleware order on every route: requestId -> auth -> rateLimit -> validate -> handler.
- Every route under /api/v1/partner/ requires partnerAuth and requireScope(...).
Exceptions: GET /health and POST /oauth/token. No others.
- Lists use cursor pagination: { data, pagination: { nextCursor, hasMore } }. No offset.
- Strings need maxLength, numbers min/max, arrays maxItems. No unbounded input.
- Never log request bodies, tokens or Authorization headers.

Trzy ostatnie reguły recenzent musiałby inaczej wyłapywać ręcznie, więc zapisz je wprost.

Jak zbudować w Claude Code API, któremu można ufać?

Dział zatytułowany „Jak zbudować w Claude Code API, któremu można ufać?”

Kolejność ma większe znaczenie niż same prompty. Każdy krok daje coś, co możesz sprawdzić, zanim zacznie się następny.

  1. Zaprojektuj kontrakt w trybie planowania.

    Uruchom claude --permission-mode plan albo wpisz /plan w trwającej sesji. W trybie planowania Claude Code czyta kod i proponuje, ale niczego nie edytuje, więc o nazwy zasobów i kody statusu spierasz się, zanim powstanie jakikolwiek handler. To przypadek szczególny szerszej metody, którą opisuje strona o programowaniu sterowanym specyfikacją.

  2. Zlintuj kontrakt, a potem go zatwierdź.

    Zapisz zatwierdzony projekt w docs/openapi.yaml i uruchom na nim Spectral w terminalu:

    Okno terminala
    npx @stoplight/spectral-cli lint docs/openapi.yaml --fail-severity warn

    Spectral potrzebuje zestawu reguł. Utwórz .spectral.yaml z extends: ["spectral:oas"], żeby włączyć wbudowane reguły OpenAPI, i dopisz własne. Kontrakt to jedyny artefakt, który człowiek czyta w całości: nazwy zasobów, kody statusu, zakresy uprawnień i odpowiedzi na otwarte pytania Claude. Zacommituj go osobno, żeby każda późniejsza zmiana w nim była widoczna w przeglądzie.

  3. Implementuj po jednym zasobie na iterację, zaczynając od testów.

    Wyjdź z trybu planowania skrótem Shift+Tab, który przełącza tryby uprawnień, i implementuj w trybie auto albo acceptEdits. Od v2.1.283 (kanał latest) tryb auto jest trybem startowym sesji interaktywnych w każdym planie i u każdego dostawcy, więc często trafiasz do niego bez wybierania. Wyjątkiem są sesje na modelach, których tryb auto nie obsługuje (np. domyślna sesja Microsoft Foundry), i sesje, w których plik ustawień zawiera disableAutoMode; jeśli startujesz w trybie Manual, wybierz auto albo acceptEdits skrótem Shift+Tab. Zaimplementuj produkty przed zamówieniami. Iteracja na tyle mała, że mieści się w jednej sesji, utrzymuje czysty kontekst i daje zielony punkt kontrolny, do którego wrócisz przez /rewind, jeśli kolejna iteracja się posypie.

  4. Sprawdź działające API ręcznie.

    Uruchom serwer deweloperski i sprawdź iterację sam, w tej samej sesji. Linia zaczynająca się od ! uruchamia polecenie bezpośrednio w trybie powłoki, bez interpretowania i zatwierdzania przez Claude. Polecenie i jego wynik trafiają do kontekstu, więc Claude może zareagować na to, co pokazują. Nie wpisuj w te polecenia prawdziwych tokenów, bo wynik zostaje w transkrypcie.

    Okno terminala
    ! curl -s -w '\n%{http_code}\n' "http://localhost:3000/api/v1/products?minPrice=-1" \
    -H "Authorization: Bearer $API_TEST_TOKEN"

    Jedno wywołanie curl dowodzi jednej ścieżki. Krok 5 dowodzi reszty.

  5. Sfuzzuj implementację na podstawie kontraktu.

    Schemathesis generuje żądania z docs/openapi.yaml, także niepoprawne, i sprawdza każdą odpowiedź względem zadeklarowanego schematu i kodów statusu:

    Okno terminala
    uvx schemathesis run docs/openapi.yaml --url http://localhost:3000 \
    --checks all -H "Authorization: Bearer $API_TEST_TOKEN" --max-failures 10

    Wklej błędy z powrotem do Claude z poleceniem „fix the implementation, not the spec, unless the spec is wrong; say which”. Każdy błąd to albo usterka handlera, albo decyzja kontraktowa, która wymaga człowieka. Testy kontraktowe między usługami i szerszą strategię testowania API opisuje strona o automatyzacji testów API.

  6. Przeglądaj dowody, a nie każdy handler.

    Uruchom /code-review i /security-review na iteracji, a sprawdzenie kontraktu przekaż subagentowi recenzentowi z następnej sekcji. Ty czytasz diff kontraktu, listę testów i wynik bramek. Handler otwierasz tylko tam, gdzie wskazuje bramka albo recenzent.

Które bramki dowodzą, że API działa, bez czytania każdego handlera?

Dział zatytułowany „Które bramki dowodzą, że API działa, bez czytania każdego handlera?”

Każda bramka łapie klasę błędów, którą człowiek przegapia, przeglądając pobieżnie 2000 linii. Pierwsze cztery uruchamiaj w CI przy każdym pull requeście; listą bramek zarządza tech lead i to on zatwierdza zmiany kontraktu.

BramkaCo łapiePolecenie lub plikKiedy działa
Lint SpectralNiespójne nazwy, brakujące odpowiedzi błędów, nieudokumentowane operacjenpx @stoplight/spectral-cli lint docs/openapi.yamlHook Stop, CI
Testy integracyjneZłe kody statusu, zepsuta walidacja, macierz 401/403npm run test:apiHook Stop, CI
Test pokrycia uwierzytelnianiaTrasę zarejestrowaną bez partnerAuth albo bez sprawdzenia zakresutests/routes/auth-coverage.test.tsCI
SchemathesisOdpowiedzi niezgodne z kontraktem; błędy 500 przy nietypowym wejściuuvx schemathesis run … --checks allCI, na uruchomionym serwerze
/security-reviewWstrzyknięcia, sekrety w logach, brak autoryzacji na ścieżce danychW sesjiPrzed pull requestem
Zatwierdzenie przez człowiekaCzy kontrakt opisuje właściwy produktDiff docs/openapi.yamlPull request

Test pokrycia uwierzytelniania warto napisać pierwszego dnia, bo trasa bez uwierzytelniania przechodzi wszystkie pozostałe bramki. Niech wylicza trasy, które aplikacja faktycznie rejestruje, żeby nowa trasa była objęta testem bez niczyjej pamięci:

Ostatnie polecenie jest kluczowe: bramka, której nigdy nie widziałeś czerwonej, to bramka nieprzetestowana.

Niech Claude Code uruchamia bramki, zanim powie „gotowe”

Dział zatytułowany „Niech Claude Code uruchamia bramki, zanim powie „gotowe””

Hook Stop uruchamia się, gdy Claude próbuje zakończyć turę. Jeśli bramki nie przechodzą, hook blokuje zakończenie i oddaje wynik agentowi, więc „gotowe” oznacza zielone bramki. Zapisz skrypt jako .claude/hooks/api-gates.sh i nadaj mu prawo wykonywania:

#!/usr/bin/env bash
# .claude/hooks/api-gates.sh (Stop)
set -uo pipefail
cd "$CLAUDE_PROJECT_DIR" || exit 0
retrying=$(jq -r '.stop_hook_active')
[[ -z $(git status --porcelain -- docs/openapi.yaml src tests) ]] && exit 0
if out=$(npx @stoplight/spectral-cli lint docs/openapi.yaml --fail-severity warn 2>&1 \
&& npm run --silent test:api 2>&1); then exit 0; fi
if [[ $retrying == "true" ]]; then
jq -nc '{systemMessage: "API gates still fail after one retry. Stopping for a human."}'
exit 0
fi
jq -nc --arg r "API gates fail. Fix them before you finish. Last 40 lines:
$(tail -n 40 <<<"$out")" '{decision: "block", reason: $r}'

Hook uruchamia bramki tylko wtedy, gdy specyfikacja, src lub tests mają niezacommitowane zmiany, więc jeśli Claude zrobi commit w trakcie tury, hook przepuści ją bez żadnego sprawdzenia. Zabezpieczeniem dla zacommitowanej pracy jest CI.

Zarejestruj go w .claude/settings.json. Forma exec (command plus args) przekazuje ścieżkę skryptu jako jeden argument, więc zadziała także ścieżka projektu ze spacjami:

{
"hooks": {
"Stop": [
{ "hooks": [{ "type": "command", "command": "bash",
"args": ["${CLAUDE_PROJECT_DIR}/.claude/hooks/api-gates.sh"], "timeout": 300 }] }
]
}
}

Skrypt czyta pole stop_hook_active, które ma wartość true, gdy Claude już kontynuuje pracę z powodu hooka Stop, i poddaje się po jednej ponownej próbie. Claude Code sam ogranicza kontynuacje wymuszone hookiem Stop do ośmiu z rzędu, ale bramka, która zawodzi dwa razy, zwykle wymaga decyzji człowieka, a nie kolejnych prób. Wartość timeout jest w sekundach. Wzorzec „jedna ponowna próba, potem eskalacja do człowieka” i pozostałe zdarzenia hooków opisuje strona o hookach, które egzekwują twoje bramki.

Subagent recenzent, który sprawdza kontrakt, a nie styl

Dział zatytułowany „Subagent recenzent, który sprawdza kontrakt, a nie styl”

Subagent przegląda kod we własnym oknie kontekstu i zwraca werdykt. Daj mu narzędzia tylko do odczytu, żeby nie mógł „naprawić” tego, co ma ocenić. Zapisz jako .claude/agents/api-contract-reviewer.md:

---
name: api-contract-reviewer
description: Checks that API handlers match docs/openapi.yaml and CLAUDE.md API conventions. Use after implementing or changing an endpoint.
tools: Read, Grep, Glob
---
You review API changes against docs/openapi.yaml and the API conventions in CLAUDE.md.
You never edit files. For every changed route report, with file and line:
- operations in the code that are missing from the spec, and the reverse
- error responses that do not use ErrorResponse
- middleware order that differs from CLAUDE.md
- unbounded inputs (string without maxLength, array without maxItems)
- list endpoints without cursor pagination
End with VERDICT: PASS or VERDICT: FAIL and the count of findings.

Traktuj jego werdykt jako twierdzenie do potwierdzenia, nie jako dowód: dowodem są bramki powyżej, a subagent znajduje to, czego one nie obejmują. Więcej wzorców znajdziesz na stronie o własnych subagentach.

Pętla jest ta sama, tylko zamiast docs/openapi.yaml masz plik schematu: napisz schema.graphql w trybie planowania, zatwierdź go i implementuj resolvery typ po typie. Błąd typowy dla GraphQL to zapytania N+1, które przechodzą każdy test funkcjonalny na małym zestawie danych. Zrób z liczby zapytań asercję w teście, żeby poprawka była udowodniona, a nie tylko zadeklarowana.

Schemathesis przyjmuje też schemat GraphQL: lokalny plik schema.graphql z --url albo sam adres endpointu, więc bramka fuzzingu przenosi się bez zmian. Do pracy z SQL świadomej schematu podłącz serwer MCP bazy danych, żeby Claude sprawdzał indeksy i plany zapytań na prawdziwym schemacie zamiast zgadywać.

Webhooki, limity zapytań i paginacja bez niespodzianek

Dział zatytułowany „Webhooki, limity zapytań i paginacja bez niespodzianek”

Te trzy obszary psują się w API pisanych przez agenta na produkcji, a nie w testach, bo błąd ujawnia się dopiero przy ponowieniach, pod obciążeniem albo na dużych danych. Opisz w prompcie zachowanie w razie awarii i poproś o test tego zachowania.

Przy limitach zapytań i paginacji proś o konkretne sprawdzenia:

  • Limity zapytań: test, który wysyła limit + 1 żądań i sprawdza odpowiedź 429 z nagłówkiem Retry-After, a także X-RateLimit-Remaining w każdej odpowiedzi. Zapytaj, gdzie żyje licznik; licznik w pamięci procesu zeruje się przy każdym wdrożeniu i jest inny na każdej instancji.
  • Paginacja: test, który przechodzi przez 250 zasianych wierszy z włączonym filtrem i sprawdza brak duplikatów i brak luk. Błędy kursora ujawniają się dopiero przy remisach w kluczu sortowania, więc celowo zasiej remisy.
  • Wydajność: test, który zasiewa 10 000 wierszy i mierzy liczbę zapytań oraz p95 opóźnienia endpointu listy dla każdego filtra. Zestaw 20 wierszy ukrywa brakujący indeks.
ObjawPrzyczynaNaprawa
Trzy różne kształty błędów w różnych endpointachBrak jednego typu błędu w kontekście; każda iteracja wymyśliła własnyDodaj regułę ErrorResponse do CLAUDE.md, a potem: „grep every res.status( and throw under src/routes/ and convert each to ErrorResponse; list what you changed.” Następnym razem wyłapie to Spectral, jeśli dodasz regułę wymagającą wspólnego schematu błędu.
Trasa trafia do kodu bez uwierzytelnianiaTrasę dodano w późniejszej iteracji, a prompt nie powtórzył regułyTest pokrycia uwierzytelniania; jeśli nie zawiódł, to nie wylicza prawdziwego routera. Najpierw napraw test, potem trasę.
Testy przechodzą, Schemathesis zwraca błędy 500Testy obejmują wejścia, o których pomyślał Claude; fuzzer wysyła te, o których nie pomyślałWklej niezaliczony przypadek do sesji i poproś o test regresyjny, który go odtwarza, zanim powstanie poprawka.
Claude zmienia specyfikację, żeby pasowała do błędnego handleraPolecenie „make Schemathesis pass” da się spełnić, osłabiając kontraktTrzymaj zmiany docs/openapi.yaml w osobnych commitach i wymagaj dla tego pliku zatwierdzenia przez człowieka (wpis w CODEOWNERS). W każdym prompcie naprawczym pisz „fix the implementation, not the spec”. Ogólny wzorzec opisuje strona o ochronie wyroczni.
Claude osłabia albo usuwa niezaliczony testPrompt nagradzał zieleń, a nie poprawnośćPisz „do not edit a test to make it pass” (prompt iteracji to robi) i porównuj liczbę testów przed i po w pull requeście.
Sesja dryfuje po kilku zasobachKontekst wypełniają wcześniejsze iteracje i wyniki testówJeden zasób na sesję; kolejny zacznij od /clear albo w nowej sesji. Długie przebiegi testów deleguj do subagenta, żeby wracały tylko błędy.
Walidacja odrzuca prawdziwe dane partneraGranice zgadnięto, zamiast wziąć je z systemu źródłowegoProś o granice jako otwarte pytania w prompcie kontraktu i odpowiedz na nie na podstawie przykładowych danych partnera przed zatwierdzeniem.

Przewodnik międzynarzędziowy opisuje tę samą metodę spec-first dla Codex i Cursora, a do tego testy kontraktowe z Pact i wersjonowanie API. Sąsiednie strony o Claude Code obejmują warstwy pod API i wokół niego.

Planujesz funkcję, zanim powstanie kontrakt? Zacznij od planowania funkcji w Claude Code. Pracujesz w Codex? Zobacz tworzenie API w Codex.