6 min

Generare OpenAPI dal comportamento con Claude Code, onestamente

Impara a generare OpenAPI dal comportamento usando Claude Code, confrontala con l'implementazione dell'API e crea esempi semplici di validazione client e server.

Generare OpenAPI dal comportamento con Claude Code, onestamente

Perché i contratti OpenAPI si discostano (e perché conta)

Un contratto OpenAPI è una descrizione condivisa della tua API: quali endpoint esistono, cosa invii, cosa ricevi in risposta e come sono gli errori. È l'accordo tra il server e chiunque lo chiami (un'app web, un'app mobile o un altro servizio).

Il problema è lo drift. L'API in esecuzione cambia, ma la spec no. Oppure la spec viene “ripulita” per apparire più bella della realtà, mentre l'implementazione continua a restituire campi strani, codici di stato mancanti o forme di errore inconsistenti. Col tempo, le persone smettono di fidarsi del file OpenAPI e diventa solo un'altra doc che tutti ignorano.

Lo drift di solito nasce da pressioni normali: una correzione veloce viene rilasciata senza aggiornare la spec, un nuovo campo opzionale viene aggiunto “temporaneamente”, la paginazione evolve o i team aggiornano diverse “sorgenti di verità” (codice backend, collection Postman e file OpenAPI).

Mantenere onesta la spec significa che la spec corrisponde al comportamento reale. Se l'API a volte restituisce 409 per un conflitto, questo appartiene al contratto. Se un campo è nullable, dillo. Se è richiesta l'autenticazione, non lasciarlo vago.

Un buon workflow ti lascia con:

  • Un file OpenAPI che riflette comportamento desiderato e osservato
  • Un insieme semplice di controlli per cogliere lo drift presto, prima che i client si rompano
  • Esempi concreti di validazione client e server che puoi copiare nel tuo codice

Quest'ultimo punto conta perché un contratto aiuta solo quando è applicato. Una spec onesta più controlli ripetibili trasforma la “documentazione API” in qualcosa di cui i team possono fidarsi.

Parti dal comportamento intenzionale, non dal codice

Se parti leggendo il codice o copiando le route, il tuo OpenAPI descriverà ciò che esiste oggi, incluse le stranezze che potresti non voler promettere. Invece, descrivi cosa dovrebbe fare l'API per un chiamante e poi usa la spec per verificare che l'implementazione corrisponda.

Prima di scrivere YAML o JSON, raccogli un piccolo set di fatti per endpoint:

  • Cosa fa (metodo e path)
  • Cosa accetta (header, query, path params, body)
  • Cosa restituisce (codice di successo, forma della risposta, header chiave)
  • Cosa può fallire (errori probabili, codici di stato, forma del body di errore)
  • Chi può chiamarlo (auth e ruoli, se rilevante)

Poi scrivi il comportamento come esempi. Gli esempi ti costringono a essere specifico e rendono più facile redigere un contratto coerente.

Per una Tasks API, un esempio di happy path potrebbe essere: “Crea un task con title e ricevi id, title, status e createdAt.” Aggiungi fallimenti comuni: “Title mancante restituisce 400 con {\"error\":\"title is required\"}” e “Nessuna auth restituisce 401.” Se conosci già edge case, includili: se i titoli duplicati sono permessi e cosa succede quando un ID task non esiste.

Cattura le regole con frasi semplici che non dipendano dai dettagli del codice:

  • title è obbligatorio e lungo 1-120 caratteri.”
  • “La lista restituisce fino a 50 item a meno che non sia impostato limit (max 200).”
  • dueDate è ISO 8601 date-time.”
  • “Gli endpoint di scrittura richiedono un token utente.”

Infine, decidi l'ambito della v1. Se sei incerto, mantieni la v1 piccola e chiara (create, read, list, update status). Salva ricerca, aggiornamenti bulk e filtri complessi per dopo così il contratto resta credibile.

Un template leggero per descrivere gli endpoint

Prima di chiedere a Claude Code di scrivere una spec, scrivi note sul comportamento in un formato piccolo e ripetibile. L'obiettivo è rendere difficile “riempire i buchi” con congetture.

Un buon template è abbastanza breve da essere effettivamente usato, ma coerente così due persone descriverebbero lo stesso endpoint in modo simile. Mantienilo focalizzato su cosa fa l'API, non su come è implementata.

Endpoint behavior note template

Use one 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):

Scrivi almeno una richiesta concreta e due risposte. Includi codici di stato e corpi JSON realistici con nomi di campo reali. Se un campo è opzionale, mostra un esempio in cui manca.

Indica esplicitamente gli edge case. Questi sono i punti dove le spec diventano silenziosamente false più tardi perché ognuno assume qualcosa di diverso: risultati vuoti, ID invalidi (400 vs 404), duplicati (409 vs comportamento idempotente), errori di validazione e limiti di paginazione.

Nota anche i tipi di dato in termini umani prima di pensare agli schemi: stringhe vs numeri, formati date-time, booleani ed enum (elenco valori ammessi). Questo evita uno schema “bello” che non corrisponde ai payload reali.

Bozza la spec OpenAPI con Claude Code (prompt che funziona)

Claude Code funziona meglio se lo tratti come uno scriba attento. Dagli le tue note comportamentali e regole strette su come la OpenAPI deve essere strutturata. Se dici solo “scrivi una spec OpenAPI”, solitamente otterrai congetture, naming incoerente e casi di errore mancanti.

Incolla prima le note di comportamento, poi aggiungi un blocco di istruzioni rigorose. Un prompt pratico è così:

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.

Dopo aver ottenuto la bozza, controlla prima le ASSUMPTIONS. Lì si gioca l'onestà. Approva ciò che è corretto, correggi ciò che è sbagliato e rilancia con note aggiornate.

Per mantenere il naming coerente, dichiara le convenzioni all'inizio e rispettale. Per esempio: pattern stabile per operationId, nomi tag solo sostantivi, nomi di schema singolari, un Error condiviso e un solo nome per lo auth scheme usato ovunque.

Se lavori in un workspace vibe-coding come Koder.ai, aiuta salvare lo YAML come file reale presto e iterare in piccoli diff. Così vedi quali cambiamenti sono derivati da decisioni comportamentali approvate rispetto a dettagli che il modello ha indovinato.

Valida la spec prima di confrontarla con l'API in esecuzione

Spedisci e testa più velocemente
Distribuisci e ospita la tua API insieme all'app così i team possono testare il contratto end-to-end.

Prima di confrontare qualsiasi cosa con la produzione, assicurati che il file OpenAPI sia internamente consistente. Questo è il luogo più veloce per intercettare desideri e linguaggio vago.

Leggi ogni endpoint come se fossi lo sviluppatore client. Concentrati su cosa il chiamante deve inviare e su cosa può aspettarsi di ricevere.

Un passaggio pratico di revisione:

  • Required vs optional: marca i campi required correttamente ed evita “tutto opzionale”.
  • Tipi e formati: sii esplicito su UUID, email, date-time, valori min/max.
  • Esempi: aggiungi almeno un esempio di richiesta e risposta realistici per endpoint e mantieni gli esempi allineati con gli schemi.
  • Codici di stato: allineali alle note di comportamento (create è spesso 201, non 200). Scegli 400 vs 422 e sii coerente.
  • Auth: indica cosa è richiesto per ogni endpoint e se i ruoli influenzano l'accesso.

Gli errori meritano attenzione extra. Scegli una shape condivisa e riutilizzala ovunque. Alcuni team la tengono molto semplice ({ error: string }), altri usano un oggetto dettagliato ({ error: { code, message, details } }). Entrambe possono funzionare, ma non mescolarle tra endpoint ed esempi. Se lo fai, il codice client accumulerà casi speciali.

Uno scenario rapido di sanity check aiuta. Se POST /tasks richiede title, lo schema dovrebbe marcarlo required, la risposta di errore dovrebbe mostrare il corpo di errore realmente restituito e l'operazione dovrebbe indicare chiaramente se l'auth è richiesta.

Confronta la spec con l'implementazione in esecuzione

Una volta che la spec legge come comportamento intenzionale, tratta l'API in esecuzione come la verità di ciò che i client sperimentano oggi. Lo scopo non è “vincere” tra spec e codice, ma far emergere le differenze presto e prendere una decisione chiara su ciascuna.

Per una prima passata, campioni reali di request/response sono spesso l'opzione più semplice. Anche i log e i test automatizzati funzionano se sono affidabili.

Fai attenzione alle incongruenze comuni: endpoint presenti in un posto ma non nell'altro, differenze nei nomi o nella forma dei campi, differenze nei codici di stato (200 vs 201, 400 vs 422), comportamenti non documentati (paginazione, ordinamento, filtri) e differenze di auth (la spec dice pubblico, il codice richiede token).

Esempio: la tua OpenAPI dice che POST /tasks restituisce 201 con {id,title}. Chiami l'API in esecuzione e ottieni 200 più {id,title,createdAt}. Non è “abbastanza vicino” se generi SDK dai file spec.

Prima di modificare qualsiasi cosa, decidi come risolvere i conflitti:

  • Se il comportamento è corretto ma non documentato, aggiorna la spec.
  • Se la spec è il contratto concordato, modifica il codice per matchare.
  • Se nessuno dei due è giusto, aggiusta prima il comportamento intenzionale, poi aggiorna entrambi.

Mantieni ogni cambiamento piccolo e revisionabile: un endpoint, una risposta, una modifica di schema. È più facile da revisionare e da ritestare.

Produci esempi di validazione client e server dal contratto

Una volta che hai una spec di cui ti fidi, trasformala in piccoli esempi di validazione. Questo è ciò che impedisce al drift di tornare.

Validazione lato server (rifiuta richieste non valide)

Sul server, la validazione significa fallire velocemente quando una richiesta non corrisponde al contratto e restituire un errore chiaro. Questo protegge i dati e rende i bug più facili da individuare.

Un modo semplice per esprimere esempi di validazione server è scriverli come casi con tre parti: input, output atteso ed errore atteso (un codice di errore o un pattern, non il testo esatto).

Esempio (il contratto dice che title è richiesto e deve essere 1-120 chars):

{
  "name": "Create task without title returns 400",
  "request": {"method": "POST", "path": "/tasks", "body": {"title": ""}},
  "expect": {"status": 400, "body": {"error": {"code": "VALIDATION_ERROR"}}}
}

Validazione lato client (cattura i cambiamenti breaking presto)

Sul client, la validazione serve a rilevare lo drift prima che lo vedano gli utenti. Se il server inizia a restituire una forma diversa, o un campo richiesto scompare, i tuoi test dovrebbero segnalarlo.

Mantieni i controlli client focalizzati su ciò di cui fai davvero affidamento, come “un task ha id, title, status.” Evita di asserire ogni campo opzionale o l'ordine esatto. Vuoi fallimenti su cambiamenti breaking, non su aggiunte innocue.

Alcune linee guida per mantenere i test leggibili:

  • Preferisci verificare presenza e tipo invece dei valori esatti.
  • Asserisci solo i campi required, a meno che un campo opzionale non sia critico.
  • Per gli errori, controlla lo status e un codice di errore, non il messaggio completo.
  • Consenti campi extra a meno che il contratto non li proibisca esplicitamente.

Se usi Koder.ai, puoi generare e tenere questi casi esempio accanto al file OpenAPI, poi aggiornarli come parte della stessa review quando il comportamento cambia.

Scenario di esempio: una semplice Tasks API end-to-end

Tieni le modifiche al sicuro
Scatta una snapshot prima di modifiche rischiose, poi rollback se spec e implementazione divergono.

Immagina una piccola API con tre endpoint: POST /tasks crea un task, GET /tasks lista i task e GET /tasks/{id} restituisce un singolo task.

Inizia scrivendo alcuni esempi concreti per un endpoint, come se lo spiegassi a un tester.

Per POST /tasks, il comportamento intenzionale potrebbe essere:

  • Successo: invia { "title": "Buy milk" } e ricevi 201 con un oggetto task nuovo, includendo id, title e done:false.
  • Errore 1: invia {} e ricevi 400 con un errore tipo { "error": "title is required" }.
  • Errore 2: invia { "title": "x" } (troppo corto) e ricevi 422 con { "error": "title must be at least 3 characters" }.

Quando Claude Code bozza l'OpenAPI, lo snippet per questo endpoint dovrebbe catturare schema, codici di stato ed esempi realistici:

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" }

Una discrepanza comune è sottile: l'API in esecuzione restituisce 200 invece di 201, oppure restituisce { "taskId": 123 } invece di { "id": "t_123" }. Questo tipo di differenza “quasi uguale” rompe gli SDK generati.

Risolvi scegliendo una fonte di verità. Se il comportamento intenzionale è corretto, modifica l'implementazione per restituire 201 e la forma Task concordata. Se il comportamento in produzione è già sfruttato, aggiorna la spec (e le note di comportamento) per riflettere la realtà, poi aggiungi la validazione e le risposte di errore mancanti in modo che i client non siano sorpresi.

Errori comuni che rendono un contratto disonesto

Un contratto diventa disonesto quando smette di descrivere regole e inizia a descrivere qualunque cosa la tua API abbia restituito in un giorno fortunato. Un semplice test: una nuova implementazione potrebbe passare questa spec senza copiare le stranezze di oggi?

Un tranello è l'overfitting. Catturi una risposta e la trasformi in legge. Esempio: la tua API attualmente restituisce dueDate: null per ogni task, quindi la spec dice che il campo è sempre nullable. Ma la regola reale potrebbe essere “richiesto quando lo status è scheduled.” Il contratto dovrebbe esprimere la regola, non solo il dataset corrente.

Gli errori sono dove l'onestà spesso si rompe. È allettante specificare solo le risposte di successo perché sembrano pulite. Ma i client hanno bisogno delle basi: 401 quando manca il token, 403 per accesso vietato, 404 per ID sconosciuti e un errore di validazione coerente (400 o 422).

Altri pattern problematici:

  • Nomi e tipi che divergono tra endpoint (taskId in una route ma id altrove, o priority come stringa in una risposta e numero in un'altra).
  • Esempi che contraddicono gli schemi (valori enum non corrispondono, esempi date-time non in ISO 8601).
  • Tipi allargati per evitare decisioni (tutto diventa string, tutto opzionale).
  • La spec suona come copy marketing (“veloce”, “sicuro”) invece che un contratto testabile.

Un buon contratto è testabile. Se non riesci a scrivere un test fallibile partendo dalla spec, non è ancora onesto.

Controlli rapidi prima di condividere o pubblicare il file OpenAPI

Correggi lo drift su un endpoint
Modifica un endpoint, retesta le risposte reali e correggi le incongruenze mentre sono piccole.

Prima di consegnare un file OpenAPI a un altro team (o incollarlo nella docs), fai una rapida verifica “può qualcuno usare questo senza leggere la tua mente?”

Inizia con gli esempi. Una spec può essere valida e comunque inutile se ogni request e response è astratta. Per ogni operazione, includi almeno un esempio realistico di richiesta e una risposta di successo. Per gli errori, un esempio per ogni fallimento comune (auth, validazione) è quasi sempre sufficiente.

Poi controlla la coerenza. Se un endpoint restituisce { "error": "..." } e un altro { "message": "..." }, i client finiranno con logiche ramificate ovunque. Scegli una sola shape di errore e riutilizzala, insieme a codici di stato prevedibili.

Una checklist breve:

  • Campi required, formati (email, uuid, date-time) ed enum sono espliciti.
  • Codici di stato intenzionali e coerenti tra endpoint simili.
  • Risposte di errore includono schema ed esempi, non solo lo status.
  • Riesegui 2-3 chiamate reali per endpoint (test, curl, Postman o log) e confronta i payload con la spec.
  • Puoi scrivere una piccola chiamata client dalla spec senza indovinare header, nomi di campo o nullability.

Un trucco pratico: scegli un endpoint, fai finta di non aver mai visto l'API e rispondi “Cosa invio, cosa ricevo indietro e cosa si rompe?” Se l'OpenAPI non può rispondere chiaramente, non è pronta.

Prossimi passi: rendilo un'abitudine (e mantieni le modifiche al sicuro)

Questo workflow ripaga quando viene eseguito regolarmente, non solo durante un rilascio affannoso. Scegli una regola semplice e rispettala: eseguila ogni volta che un endpoint cambia e di nuovo prima di pubblicare una spec aggiornata.

Mantieni la ownership semplice. Chi cambia un endpoint aggiorna le note di comportamento e la bozza di spec. Una seconda persona revisiona il “spec vs implementation” come una code review. QA o colleghi del support spesso sono ottimi revisori perché individuano risposte poco chiare e edge case rapidamente.

Tratta le modifiche al contratto come modifiche al codice. Se usi un builder chat-driven come Koder.ai, fare uno snapshot prima di modifiche rischiose e usare rollback quando serve mantiene l'iterazione sicura. Koder.ai supporta anche l'esportazione del codice sorgente, il che rende più semplice mantenere spec e implementazione affiancate nel repo.

Una routine che di solito funziona senza rallentare i team:

  • Scrivi le note di comportamento quando aggiungi un endpoint
  • Valida la spec ed esegui i contract test prima di fare merge
  • Confronta la spec con un'API in esecuzione prima del rilascio
  • Scatta uno snapshot prima di modifiche rischiose; rollback se il diff diventa confuso

Prossima azione: scegli un endpoint esistente. Scrivi 5-10 righe di note sul comportamento (input, output, casi di errore), genera una bozza OpenAPI da quelle note, validala, poi confrontala con l'implementazione in esecuzione. Risolvi una discrepanza, ritesta e ripeti. Dopo un endpoint, l'abitudine tende a consolidarsi.

Domande frequenti

What does “OpenAPI drift” mean in plain terms?

Lo drift di OpenAPI è quando l'API che effettivamente esegui non corrisponde più al file OpenAPI che le persone condividono. La spec potrebbe non contenere nuovi campi, codici di stato o regole di autenticazione, oppure potrebbe descrivere un comportamento “ideale” che il server non segue.

Conta perché i client (app, altri servizi, SDK generati, test) prendono decisioni basate sul contratto, non su ciò che il server “di solito” fa.

What are the most common ways drift shows up for client teams?

I problemi per i team client spesso appaiono così: una mobile app si aspetta 201 ma riceve 200, un SDK non riesce a deserializzare una risposta perché un campo è stato rinominato, o la gestione degli errori fallisce perché le shape degli errori sono diverse.

Anche quando nulla si rompe, i team perdono fiducia e smettono di usare la spec, eliminando il tuo sistema di allerta precoce.

Why shouldn’t I start the OpenAPI spec by copying backend code?

Perché il codice riflette il comportamento attuale, inclusi bachi o stranezze che forse non vuoi promettere a lungo termine.

Un approccio migliore: scrivi prima il comportamento intenzionale (input, output, errori), poi verifica che l'implementazione corrisponda. Questo ti dà un contratto applicabile, invece di un'istantanea delle route di oggi.

What’s the minimum “behavior notes” I should write per endpoint?

Per ogni endpoint raccogli:

  • Purpose: cosa fa in una frase
  • Auth: token/ruoli richiesti o pubblico
  • Request: query/path params, header e un esempio JSON di body
  • Responses: almeno un esempio di successo e uno o due esempi realistici di errore con codici di stato
  • Edge cases: ID mancanti/invalidi, duplicati (409?), risultati vuoti, limiti di paginazione

Se riesci a scrivere una richiesta concreta e due risposte, di solito hai abbastanza materiale per bozzare una spec veritiera.

How do I keep error responses consistent across the whole spec?

Scegli una shape di errore e riutilizzala ovunque.

Un default semplice può essere una di queste due opzioni:

  • { "error": "message" }, oppure
  • { "error": { "code": "...", "message": "...", "details": ... } }

Rendila coerente tra endpoint e esempi. La coerenza conta più della sofisticazione perché i client tenderanno a codificare rigidamente questa shape.

How can I prompt Claude Code so it doesn’t make up endpoints or fields?

Dai a Claude Code le tue note di comportamento e istruzioni stringenti, e digli di non inventare campi.

Istruzioni pratiche:

  • “Source of truth is the behavior notes. Do not guess.”
  • “If unclear, add TODO in the spec and list it under ASSUMPTIONS.”
  • “Include reusable schemas (like Error) and reference them.”
  • “Use consistent naming (PascalCase schemas, lowerCamelCase fields).”

Dopo la generazione, controlla prima la sezione ASSUMPTIONS: lì si vede se il modello ha indovinato qualcosa che non va bene.

What should I check in the OpenAPI file before I compare it to the running API?

Valida prima la spec internamente:

  • Campi required vs optional
  • Formati espliciti (UUID, email, ISO 8601 date-time)
  • Esempi allineati agli schemi (enum, tipi, nullability)
  • Codici di stato intenzionali e coerenti (es. create spesso 201)
  • Requisiti di auth per endpoint

Questo intercetta file OpenAPI “di desiderio” prima ancora di guardare la produzione.

When the spec and the running API disagree, which one should I change?

Tratta l'API in esecuzione come ciò che gli utenti sperimentano oggi e prendi decisioni caso per caso:

  • Se il comportamento è corretto ma non documentato: aggiorna la spec
  • Se la spec è il contratto concordato: modifica il codice
  • Se nessuno dei due è corretto: decidi prima il comportamento intenzionale, poi aggiorna entrambi

Mantieni le modifiche piccole (un endpoint o una risposta alla volta) per poterle ritestare velocemente.

What do “server-side” vs “client-side” contract validation checks look like?

Validazione server-side: rifiutare rapidamente richieste che violano il contratto e restituire un errore chiaro (status + codice/shape).

Validazione client-side: rilevare cambiamenti breaking risposte prima che arrivino agli utenti, asserendo solo ciò su cui davvero fai affidamento:

  • I campi richiesti esistono e hanno il tipo corretto
  • I codici di stato corrispondono ai flussi attesi
  • Le risposte di errore hanno la shape concordata

Evita di asserire ogni campo opzionale così i test falliscono per rotture reali, non per aggiunte innocue.

What’s a simple habit to prevent drift from coming back?

Una routine pratica:

  • Aggiorna le note di comportamento e la spec quando aggiungi un endpoint
  • Valida il file OpenAPI (schemi, esempi, codici di stato, auth)
  • Confronta alcuni campioni reali request/response contro la spec prima del rilascio
  • Aggiungi piccoli controlli di contratto nei test così lo drift viene catturato automaticamente

Se usi Koder.ai, tieni il file OpenAPI vicino al codice, fai snapshot prima di modifiche rischiose e rollback se una modifica crea confusione.

Related posts