Lär dig hur du genererar OpenAPI från beteende med Claude Code, jämför det med din API-implementation och skapa enkla klient- och servervalideringsexempel.

Ett OpenAPI-kontrakt är en gemensam beskrivning av ditt API: vilka endpoints som finns, vad du skickar, vad du får tillbaka och hur fel ser ut. Det är avtalet mellan servern och allt som anropar den (en webbapp, mobilapp eller en annan tjänst).
Problemet är drift. Det körande API:t ändras, men specen gör det inte. Eller så “putsas” specen upp för att se snyggare ut än verkligheten, medan implementationen fortsätter att returnera konstiga fält, saknade statuskoder eller inkonsekventa felformer. Med tiden slutar folk lita på OpenAPI-filen och den blir bara ytterligare en dokumentation som alla ignorerar.
Drift kommer oftast från normala påtryckningar: en snabb fix skickas utan att uppdatera specen, ett nytt valfritt fält läggs till “tillfälligt”, paginering utvecklas eller team uppdaterar olika “sanningkällor” (backend-kod, en Postman-collection och en OpenAPI-fil).
Att hålla det ärligt betyder att specen matchar verkligt beteende. Om API:t ibland returnerar 409 för en konflikt, ska det stå i kontraktet. Om ett fält kan vara null, säg det. Om autentisering krävs, lämna det inte vagt.
En bra workflow ger dig:
Den sista punkten är viktig eftersom ett kontrakt bara hjälper när det upprätthålls. En ärlig spec plus repeterbara kontroller förvandlar “API-dokumentation” till något team faktiskt kan lita på.
Om du börjar med att läsa kod eller kopiera rutter kommer din OpenAPI att beskriva vad som finns idag, inklusive egenheter du kanske inte vill lova. Beskriv istället vad API:t ska göra för en anropare, och använd specen för att verifiera att implementationen matchar.
Innan du skriver YAML eller JSON, samla ett litet set fakta per endpoint:
Skriv sedan beteende som exempel. Exempel tvingar dig att vara specifik och gör det enklare att utforma ett konsekvent kontrakt.
För ett Tasks API kan ett lyckligt flödes-exempel vara: “Skapa en task med title och få tillbaka id, title, status och createdAt.” Lägg till vanliga fel: “Saknat title returnerar 400 med {\"error\":\"title is required\"}” och “Ingen auth returnerar 401.” Om du redan känner till edge cases, inkludera dem: om dubblett-titlar är tillåtna och vad som händer när en task-id inte finns.
Fånga regler som enkla meningar som inte beror på kod-detaljer:
title är obligatoriskt och 1–120 tecken.”limit sätts (max 200).”dueDate är ISO 8601 date-time.”Slutligen, bestäm din v1-scope. Om du är osäker, håll v1 liten och tydlig (create, read, list, update status). Spara sök, bulk-uppdateringar och komplexa filter till senare så kontraktet förblir trovärdigt.
Innan du ber Claude Code skriva en spec, skriv beteendenoter i ett litet, repeterbart format. Målet är att göra det svårt att av misstag “fyll i luckor” med gissningar.
En bra mall är tillräckligt kort för att du faktiskt ska använda den, men konsekvent nog att två personer skulle beskriva samma endpoint likartat. Håll fokus på vad API:t gör, inte hur det är implementerat.
Använd ett block per endpoint:
METHOD + PATH:
Purpose (1 sentence):
Auth:
Request:
- Query:
- Headers:
- Body example (JSON):
Responses:
- 200 OK example (JSON):
- 4xx example (status + JSON):
Edge cases:
Data types (human terms):
Skriv åtminstone en konkret request och två responses. Inkludera statuskoder och realistiska JSON-bodies med faktiska fältnamn. Om ett fält är valfritt, visa ett exempel där det saknas.
Peka ut edge cases uttryckligen. Det är de platser där specer tyst blir osanna senare för att alla antog olika saker: tomma resultat, ogiltiga ID:n (400 vs 404), dubbletter (409 vs idempotent beteende), valideringsfel och pagineringsgränser.
Notera också datatyper i enkla ord innan du tänker på scheman: strängar vs nummer, date-time-format, booleans och enums (lista över tillåtna värden). Det förhindrar ett “fint” schema som inte matchar verkliga payloads.
Claude Code fungerar bäst när du behandlar det som en noggrann skrivare. Ge det dina beteendenoter och strikta regler för hur OpenAPI ska formas. Om du bara säger “skriv en OpenAPI-spec”, får du ofta gissningar, inkonsekvent namngivning och saknade felfall.
Klistra in dina beteendenoter först, och lägg till en strikt instruktionsblock. En praktisk prompt ser ut så här:
You are generating an OpenAPI 3.1 YAML spec.
Source of truth: the behavior notes below. Do not invent endpoints or fields.
If anything is unclear, list it under ASSUMPTIONS and leave TODO markers in the spec.
Requirements:
- Include: info, servers (placeholder), tags, paths, components/schemas, components/securitySchemes.
- For each operation: operationId, tags, summary, description, parameters, requestBody (when needed), responses.
- Model errors consistently with a reusable Error schema and reference it in 4xx/5xx responses.
- Keep naming consistent: PascalCase schema names, lowerCamelCase fields, stable operationId pattern.
Behavior notes:
[PASTE YOUR NOTES HERE]
Output only the OpenAPI YAML, then a short ASSUMPTIONS list.
Efter att du fått ett utkast, skanna ASSUMPTIONS först. Där vinns eller förloras ärligheten. Godkänn det som är korrekt, rätta det som är fel och kör om med uppdaterade noter.
För att hålla namngivningen konsekvent, ange konventioner i förväg och håll dig till dem. Till exempel: ett stabilt operationId-mönster, tag-namn som bara substantiv, ental schema-namn, ett delat Error-schema och ett auth-schemanamn som används överallt.
Om du jobbar i en vibe-coding-arbetsyta som Koder.ai hjälper det att spara YAML som en riktig fil tidigt och iterera i små diffar. Då ser du vilka ändringar som kom från godkända beteendebeslut kontra detaljer modellen gissade.
Innan du jämför något med produktion, se till att OpenAPI-filen är internt konsekvent. Det är det snabbaste stället att fånga önsketänkande och vaga formuleringar.
Läs varje endpoint som om du vore klientutvecklaren. Fokusera på vad en anropare måste skicka och vad de kan lita på att få tillbaka.
Ett praktiskt granskningspass:
Felresponser förtjänar extra omsorg. Välj en gemensam form och återanvänd den överallt. Vissa team håller det väldigt enkelt ({ error: string }), andra använder ett objekt ({ error: { code, message, details } }). Båda kan fungera, men blanda dem inte över endpoints och exempel. Om du gör det kommer klientkod samla på sig specialfall.
Ett snabbt sanitetstest hjälper. Om POST /tasks kräver title, ska schemat markera det som required, failure-responsen visa vilket felbody ni faktiskt returnerar, och operationen klart ange om auth krävs.
När specen läser som avsett beteende, behandla det körande API:t som sanningen om vad klienter upplever idag. Målet är inte att “vinna” mellan spec och kod, utan att yppa skillnader tidigt och fatta ett klart beslut om varje skillnad.
För ett första pass är verkliga request/response-exempel oftast enklast. Loggar och automatiserade tester fungerar också om de är pålitliga.
Håll utkik efter vanliga mismatch: endpoints som finns på ena stället men inte det andra, fältnamn eller formskillnader, statuskodsskillnader (200 vs 201, 400 vs 422), odokumenterade beteenden (pagenering, sortering, filtrering) och auth-skillnader (spec säger publik, kod kräver token).
Exempel: din OpenAPI säger att POST /tasks returnerar 201 med {id,title}. Du anropar körande API och får 200 plus {id,title,createdAt}. Det är inte “nära nog” om du genererar klient-SDKs från specen.
Innan du ändrar något, bestäm hur du löser konflikter:
Behåll varje ändring liten och granskbar: en endpoint, ett responsfält, en schema-justering. Det är lättare att granska och enklare att retesta.
När du har en spec du litar på, gör om den till små valideringsexempel. Det är det som förhindrar att drift smyger tillbaka.
På servern betyder validering att misslyckas tidigt när en förfrågan inte matchar kontraktet, och returnera ett tydligt fel. Det skyddar din data och gör buggar lättare att upptäcka.
Ett enkelt sätt att uttrycka servervalideringsexempel är att skriva dem som fall med tre delar: input, förväntad output och förväntat fel (en felkod eller ett meddelandemönster, inte exakt text).
Exempel (kontraktet säger att title är obligatoriskt och måste vara 1 till 120 tecken):
{
\"name\": \"Create task without title returns 400\",
\"request\": {\"method\": \"POST\", \"path\": \"/tasks\", \"body\": {\"title\": \"\"}},
\"expect\": {\"status\": 400, \"body\": {\"error\": {\"code\": \"VALIDATION_ERROR\"}}}
}
På klienten handlar validering om att upptäcka drift innan användare gör det. Om servern börjar returnera en annan form, eller ett obligatoriskt fält försvinner, ska dina tester flagga det.
Håll klientkontroller fokuserade på vad ni verkligen förlitar er på, som “en task har id, title, status.” Undvik att assertera varje valfritt fält eller exakt ordning. Du vill ha fel på brytande förändringar, inte på ofarliga tillägg.
Några riktlinjer som håller tester läsbara:
Om du bygger med Koder.ai kan du generera och behålla dessa exempelcases intill din OpenAPI-fil, och uppdatera dem som en del av samma granskning när beteende ändras.
Föreställ dig ett litet API med tre endpoints: POST /tasks skapar en task, GET /tasks listar tasks, och GET /tasks/{id} returnerar en task.
Börja med att skriva några konkreta exempel för en endpoint, som om du förklarade det för en testare.
För POST /tasks kan avsett beteende vara:
{ \"title\": \"Buy milk\" } och få 201 med ett nytt task-objekt, inklusive ett id, title och done:false.{} och få 400 med ett fel som { \"error\": \"title is required\" }.{ \"title\": \"x\" } (för kort) och få 422 med { \"error\": \"title must be at least 3 characters\" }.När Claude Code skapar OpenAPI bör snippet för denna endpoint fånga schemat, statuskoderna och realistiska exempel:
paths:
/tasks:
post:
summary: Create a task
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTaskRequest'
examples:
ok:
value: { \"title\": \"Buy milk\" }
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
examples:
created:
value: { \"id\": \"t_123\", \"title\": \"Buy milk\", \"done\": false }
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
missingTitle:
value: { \"error\": \"title is required\" }
'422':
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
tooShort:
value: { \"error\": \"title must be at least 3 characters\" }
En vanlig mismatch är subtil: det körande API:t returnerar 200 istället för 201, eller det returnerar { \"taskId\": 123 } istället för { \"id\": \"t_123\" }. Det är den typen av “nästan samma” skillnad som bryter genererade klienter.
Åtgärda det genom att välja en källa till sanning. Om avsett beteende är korrekt, ändra implementationen så den returnerar 201 och den överenskomna Task-formen. Om produktionsbeteendet redan används, uppdatera specen (och beteendenoterna) för att matcha verkligheten, och lägg sedan till saknade valideringar och felresponser så kunder inte blir överraskade.
Ett kontrakt blir oärligt när det slutar beskriva regler och börjar beskriva vad ditt API returnerade en viss dag. Ett enkelt test: skulle en ny implementation kunna passera denna spec utan att kopiera dagens egenheter?
En fälla är överanpassning. Du fångar ett svar och gör det till lag. Exempel: ditt API returnerar för närvarande dueDate: null för varje task, så specen säger att fältet alltid är nullable. Men den riktiga regeln kan vara “obligatoriskt när status är scheduled.” Kontraktet bör uttrycka regeln, inte bara den aktuella dataset.
Fel är där ärligheten ofta bryts. Det är frestande att bara speca succéresponser eftersom de ser rena ut. Men klienter behöver grunderna: 401 när token saknas, 403 för förbjuden åtkomst, 404 för okända ID:n och ett konsekvent valideringsfel (400 eller 422).
Andra mönster som ställer till det:
taskId i en route men id i en annan, eller priority som sträng i ett svar och siffra i ett annat).string, allt blir valfritt).Ett bra kontrakt är testbart. Om du inte kan skriva ett felande test från specen är den ännu inte ärlig.
Innan du ger en OpenAPI-fil till ett annat team (eller klistrar in den i docs), gör en snabb koll för “kan någon använda detta utan att läsa ditt sinne?”
Börja med exempel. En spec kan vara tekniskt giltig men ändå användningslös om varje request och response är abstrakt. För varje operation, inkludera minst ett realistiskt request-exempel och ett succéresponse-exempel. För fel, ett exempel per vanligt fel (auth, validering) brukar räcka.
Kontrollera sedan konsekvens. Om en endpoint returnerar { \"error\": \"...\" } och en annan { \"message\": \"...\" }, får klienter villkorlig logik överallt. Välj ett enda felformat och återanvänd det, tillsammans med förutsägbara statuskoder.
En kort checklista:
En praktisk trick: välj en endpoint, låtsas att du aldrig sett API:t, och svara “Vad skickar jag, vad får jag tillbaka och vad går sönder?” Om OpenAPI inte kan svara klart är den inte redo.
Denna workflow betalar sig när den körs regelbundet, inte bara inför en release-kris. Välj en enkel regel och håll dig till den: kör den varje gång en endpoint ändras, och kör den igen innan du publicerar en uppdaterad spec.
Håll ägarskapet enkelt. Personen som ändrar en endpoint uppdaterar beteendenoter och specutkastet. En andra person granskar “spec vs implementation”-diffen som en kodgranskning. QA eller support-kollegor är ofta bra granskare eftersom de snabbt ser otydliga responser och edge cases.
Behandla kontraktsändringar som kodändringar. Om du använder en chattbaserad builder som Koder.ai, ta en snapshot före riskabla ändringar och använd rollback när det behövs för att hålla iterationen säker. Koder.ai stödjer också export av källkod, vilket gör det enklare att ha specen och implementationen sida vid sida i ditt repo.
En rutin som brukar fungera utan att sakta ner team:
Nästa åtgärd: välj en endpoint som redan finns. Skriv 5–10 rader beteendenoter (inputs, outputs, felfall), generera ett utkast OpenAPI från de noterna, validera det, jämför det med den körande implementationen. Fixa en mismatch, retesta och upprepa. Efter en endpoint brukar vanan fastna.
OpenAPI-drift är när API:t du faktiskt kör inte längre matchar OpenAPI-filen som delas. Specen kan sakna nya fält, statuskoder eller autentiseringsregler, eller så kan den beskriva ett “idealiskt” beteende som servern inte följer.
Det spelar roll eftersom klienter (appar, andra tjänster, genererade SDK:er, tester) fattar beslut baserat på kontraktet, inte på vad din server “vanligtvis” gör.
Klientfel blir slumpmässiga och svåra att felsöka: en mobilapp förväntar sig 201 men får 200, ett SDK kan inte deserialisera ett svar eftersom ett fält bytt namn, eller felhantering bryter eftersom felformat skiljer sig.
Även när inget kraschar tappar teamen förtroendet och slutar använda specen, vilket tar bort ditt tidiga varningssystem.
För att koden speglar nuvarande beteende, inklusive oavsiktliga egenheter du kanske inte vill lova långsiktigt.
Ett bättre utgångsläge är: skriv avsedd beteende först (inputs, outputs, fel), och verifiera sedan att implementationen matchar. Det ger dig ett kontrakt du kan upprätthålla, istället för en ögonblicksbild av dagens rutter.
För varje endpoint fånga:
Välj ett felformat och återanvänd det överallt.
Ett enkelt standardval är antingen:
{ "error": "message" }, eller{ "error": { "code": "...", "message": "...", "details": ... } }Gör det konsekvent över endpoints och exempel. Konsekvens är viktigare än komplexitet eftersom klienter kommer att hårdkoda detta format.
Ge Claude Code dina beteendenoter och strikta regler, och säg åt det att inte hitta på fält. En praktisk instruktion:
TODO i specen och lista det under ASSUMPTIONS.”Error) och referera dem.”Efter generering, granska först. Det är där driften börjar om du accepterar gissningar.
Validera specen själv först:
201)Detta fångar “önsketänkande”-OpenAPI-filer innan du ens tittar på produktion.
Behandla det körande API:t som vad användare upplever idag och avgör varje avvikelse:
Håll ändringar små (en endpoint eller ett responsfält åt gången) så att du kan retesta snabbt.
Server-side validation bör misslyckas tidigt när en förfrågan inte matchar kontraktet och returnera ett tydligt fel (status + felkod/format).
Client-side validation ska upptäcka brutna svar tidigt genom att bara assertera det ni verkligen förlitar er på:
Undvik att assertera varje valfritt fält så att tester slår larm på verkliga brytningar, inte harmlösa tillägg.
En praktisk rutin är:
Om du bygger i Koder.ai kan du hålla OpenAPI-filen i samma repo som koden, ta snapshots före riskfyllda ändringar och rulla tillbaka om en spec-/kodändring blir rörig.
Om du kan skriva en konkret förfrågan och två svar är du oftast tillräckligt långt för att utarbeta en sanningsenlig spec.