Use Cases (Atualizado: 03/06/2026)

Claude Code com OpenAPI 3.1: validação Swagger e geração TypeScript

Crie specs OpenAPI 3.1 com Claude Code, valide com Swagger e gere clientes TypeScript confiáveis.

Claude Code com OpenAPI 3.1: validação Swagger e geração TypeScript

Claude Code consegue criar uma especificação OpenAPI rapidamente. O risco começa quando esse arquivo vira contrato sem revisão. A IA pode inferir campos a partir de uma tela, criar valores de enum que não existem no banco ou mudar o formato de erro entre endpoints.

Neste guia, vamos usar Claude Code como assistente de manutenção de contrato, não como dono da verdade. Você vai criar uma especificação OpenAPI 3.1, validar o arquivo, gerar um cliente TypeScript e um stub de servidor, além de adicionar uma checagem simples contra schemas alucinados. OpenAPI descreve endpoints REST, requests, responses, autenticação e erros em formato legível por ferramentas. Swagger é o ecossistema usado para editar, visualizar e revisar esses documentos.

Masa testou o fluxo em uma API pequena de pedidos. O prompt livre gerou um status cancelled plausível, mas inexistente no modelo. O resultado ficou confiável quando o prompt definiu os arquivos a ler, proibiu campos não comprovados, executou validações e colocou dúvidas fora do schema público.

Referências oficiais: em 3 de junho de 2026, OpenAPI Specification latest aponta para 3.2.0, mas os exemplos deste artigo ficam em openapi: 3.1.0 por compatibilidade com geradores. Use OpenAPI Specification 3.1.2, Swagger Editor documentation, OpenAPI Generator usage, typescript-fetch generator e typescript-nestjs-server generator. Para OpenAPI 3.1, confirme o suporte do Swagger Editor Next na documentação atual.

Leia também o guia de desenvolvimento de APIs, o guia de testes de API, as boas práticas de segurança e as boas práticas de CLAUDE.md.

flowchart LR
  A["Implementação, DB, testes"] --> B["Claude Code rascunha OpenAPI"]
  B --> C["Validação Swagger e CLI"]
  C --> D["Cliente TypeScript"]
  C --> E["Testes de contrato"]
  C --> F["Revisão de segurança"]
  D --> G["Frontend ou parceiros"]
  E --> H["Gate de CI"]
  F --> H

Casos de uso

CasoClaude Code fazTime decide
Documentar API existenteRotas, modelos, status HTTP, autenticaçãoCampos públicos, compatibilidade, nomes
Desenvolvimento contract-firstRascunho OpenAPI 3.1, exemplos, comandosRegras de negócio, erros, escopo
Integração frontendCliente TypeScript e exemplosUX, retry, mensagens
Testes de contratooperationId, respostas 4xx, enums, authPolítica de breaking change e exceções
Revisão de segurançaSchemas públicos, auth, PII, IDs internosRisco legal, auditoria, promessas a parceiros
API para parceirosDescrições Swagger, exemplos, authContratos, limites, suporte

Se código, banco, testes ou decisão de produto não provam um detalhe, ele não deve entrar no schema público.

Setup copiável

Use Node.js 20+. O OpenAPI Generator usa Java para gerar código.

mkdir openapi-claude-demo
cd openapi-claude-demo
npm init -y
npm install -D @openapitools/openapi-generator-cli js-yaml
mkdir specs generated scripts

package.json:

{
  "type": "module",
  "scripts": {
    "validate:openapi": "openapi-generator-cli validate -i specs/openapi.yaml",
    "lint:contract": "node scripts/check-openapi-rules.mjs",
    "test:contract": "node --test scripts/contract.test.mjs",
    "generate:client": "openapi-generator-cli generate -i specs/openapi.yaml -g typescript-fetch -o generated/client --additional-properties=supportsES6=true,npmName=@example/orders-client,npmVersion=0.1.0",
    "generate:server": "openapi-generator-cli generate -i specs/openapi.yaml -g typescript-nestjs-server -o generated/server",
    "contract": "npm run validate:openapi && npm run lint:contract && npm run test:contract && npm run generate:client"
  },
  "devDependencies": {
    "@openapitools/openapi-generator-cli": "latest",
    "js-yaml": "latest"
  }
}

specs/openapi.yaml:

openapi: 3.1.0
info:
  title: Orders API
  version: 0.1.0
  description: Contract-first sample API for order intake.
servers:
  - url: https://api.example.com/v1
paths:
  /orders:
    post:
      operationId: createOrder
      summary: Create an order
      tags: [orders]
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateOrderRequest"
      responses:
        "201":
          description: Order created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Order"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  responses:
    BadRequest:
      description: Invalid request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ErrorResponse"
    Unauthorized:
      description: Missing or invalid token
  schemas:
    CreateOrderRequest:
      type: object
      additionalProperties: false
      required: [customerEmail, items]
      properties:
        customerEmail:
          type: string
          format: email
        note:
          type: [string, "null"]
        items:
          type: array
          minItems: 1
          items:
            $ref: "#/components/schemas/OrderItemInput"
    OrderItemInput:
      type: object
      additionalProperties: false
      required: [sku, quantity]
      properties:
        sku:
          type: string
        quantity:
          type: integer
          minimum: 1
    Order:
      type: object
      additionalProperties: false
      required: [id, customerEmail, status, items, createdAt]
      properties:
        id:
          type: string
          format: uuid
        customerEmail:
          type: string
          format: email
        status:
          type: string
          enum: [pending, paid]
        items:
          type: array
          items:
            $ref: "#/components/schemas/OrderItemInput"
        createdAt:
          type: string
          format: date-time
    ErrorResponse:
      type: object
      additionalProperties: false
      required: [code, message]
      properties:
        code:
          type: string
          enum: [invalid_request, unauthorized]
        message:
          type: string

scripts/check-openapi-rules.mjs:

import { readFileSync } from "node:fs";

const spec = readFileSync("specs/openapi.yaml", "utf8");
const forbidden = [
  { pattern: /\bTBD\b|\bTODO\b|placeholder/i, reason: "unfinished placeholder" },
  { pattern: /nullable:\s*true/, reason: "OpenAPI 3.1 should use JSON Schema null types" },
  { pattern: /password|secret|clientSecret|apiKey/i, reason: "review sensitive fields before publishing" }
];

const errors = forbidden.filter((rule) => rule.pattern.test(spec)).map((rule) => `- ${rule.reason}`);
if (!spec.includes("additionalProperties: false")) errors.push("- schemas should explicitly decide additionalProperties");
if (errors.length > 0) {
  console.error("Contract review failed:\n" + errors.join("\n"));
  process.exit(1);
}
console.log("Contract review passed.");

Adicione também um teste de contrato para CI. Ele verifica o contrato público: operationId, segurança em operações mutantes, respostas 4xx compartilhadas e o enum atual de Order.status.

// scripts/contract.test.mjs
import { readFileSync } from "node:fs";
import assert from "node:assert/strict";
import test from "node:test";
import { load } from "js-yaml";

const doc = load(readFileSync("specs/openapi.yaml", "utf8"));
const httpMethods = new Set(["get", "put", "post", "delete", "patch", "options", "head", "trace"]);

function operations() {
  return Object.entries(doc.paths ?? {}).flatMap(([path, pathItem]) =>
    Object.entries(pathItem)
      .filter(([method]) => httpMethods.has(method))
      .map(([method, operation]) => ({ path, method, operation }))
  );
}

test("operationId is unique and camelCase", () => {
  const ids = operations().map(({ operation }) => operation.operationId);
  assert.equal(new Set(ids).size, ids.length);
  for (const id of ids) assert.match(id, /^[a-z][A-Za-z0-9]*$/);
});

test("mutating operations require security", () => {
  for (const { path, method, operation } of operations()) {
    if (["get", "head", "options"].includes(method)) continue;
    assert.ok(operation.security?.length, `${method.toUpperCase()} ${path} must declare security`);
  }
});

test("client-visible 4xx responses reuse shared components", () => {
  for (const { path, method, operation } of operations()) {
    for (const [status, response] of Object.entries(operation.responses ?? {})) {
      if (!status.startsWith("4")) continue;
      assert.ok(response.$ref?.startsWith("#/components/responses/"), `${method.toUpperCase()} ${path} ${status}`);
    }
  }
});

test("Order status enum matches the current implementation decision", () => {
  const status = doc.components.schemas.Order.properties.status;
  assert.deepEqual(status.enum, ["pending", "paid"]);
});

Execute:

npm run validate:openapi
npm run lint:contract
npm run test:contract
npm run generate:client
npm run generate:server

Prompt para Claude Code

Crie um contrato OpenAPI 3.1 para a API de pedidos.
Leia src/routes/orders.ts, src/domain/order.ts, prisma/schema.prisma e tests/orders.test.ts.
Não invente campos, enums ou códigos de erro sem prova em código, schema, testes ou nota de produto.
Coloque dúvidas em x-claude-review, não em schemas públicos.
Não use nullable: true. Use operationId estável em camelCase.
Declare security em operações protegidas. Campos internos, PII e possíveis secrets ficam em x-claude-review antes de schemas públicos.
Execute npm run validate:openapi, npm run lint:contract e npm run test:contract, depois corrija falhas.
Retorne o diff, um exemplo de cliente TypeScript, notas de segurança e pontos para revisão humana.

Testes de contrato e segurança

Em APIs SaaS ou para parceiros, revisar OpenAPI não é só revisar texto. Separe spec review, client gerado, testes de contrato e segurança. Spec review olha paths, métodos, schemas, status e exemplos. O client gerado valida tipos typescript-fetch e null/optional. Testes de contrato bloqueiam auth ausente, erros inconsistentes e enums quebrados. Segurança revisa campos públicos, PII, IDs internos, URLs de servidor e possíveis secrets.

Claude Code pode organizar diffs, rascunhar testes e preparar a tabela de revisão. A equipe continua decidindo o que pode ser publicado, quais rate limits serão prometidos, quais riscos legais existem e quais evidências de auditoria são necessárias.

Armadilhas comuns

As falhas mais comuns são schemas inventados, formatos de erro inconsistentes, hábitos de OpenAPI 3.0 dentro de arquivos 3.1, edição manual do código gerado e revisão apenas visual no Swagger. A fonte da verdade é specs/openapi.yaml; cliente e stub devem ser regenerados.

Treinamento e consultoria

OpenAPI é um bom tema de treinamento porque entrega resultados concretos: spec, cliente TypeScript, stub de servidor, teste de contrato, validação e checklist de CI. Quem trabalha sozinho pode começar pelos produtos ClaudeCodeLab com prompts e checklists. Times que precisam adaptar isso a um repositório real, CLAUDE.md, testes de API e revisão de segurança podem usar treinamento e consultoria Claude Code.

Verificação prática

No teste de Masa, o prompt livre adicionou status não implementados e mudou o envelope de erro. Com arquivos obrigatórios, regra de não inventar, openapi-generator-cli validate, script local e node --test, a revisão humana ficou concentrada em campos públicos, evolução de enums, mensagens de autenticação e possível vazamento de dados internos. OpenAPI funcionou como contrato compartilhado entre IA e equipe.

#Claude Code #OpenAPI #Swagger #API design #REST
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.