DEV Community

Cover image for O que é Desenvolvimento de API Spec-First?
Lucas
Lucas

Posted on • Originally published at apidog.com

O que é Desenvolvimento de API Spec-First?

A maioria dos bugs de API não nasce no código, mas no contrato. O frontend esperava userId, o backend retornou user_id, e o problema só apareceu no QA. O desenvolvimento de API spec-first evita isso ao transformar a especificação no primeiro artefato do projeto, antes da implementação.

Experimente o Apidog hoje

Neste guia, você vai criar uma especificação OpenAPI pequena, usá-la para gerar mocks, orientar testes de contrato e publicar documentação antes de escrever qualquer código de servidor. A mesma abordagem também aparece como spec-driven, design-first ou contract-first. A ideia é a mesma: definir a interface primeiro e implementar depois.

O que é desenvolvimento de API spec-first

Desenvolvimento de API spec-first significa escrever um contrato legível por máquina, normalmente em OpenAPI, antes de implementar os endpoints.

Esse contrato descreve:

  • Caminhos, como GET /users
  • Parâmetros de query, path e header
  • Corpo da requisição
  • Formato das respostas
  • Códigos de status
  • Campos obrigatórios
  • Tipos e formatos, como uuid, email e date-time

A especificação deixa de ser uma documentação gerada depois do código. Ela vira a fonte da verdade:

  • O frontend consome mocks gerados a partir da spec.
  • O QA cria testes com base no contrato.
  • O backend implementa endpoints que precisam cumprir a spec.

No fluxo code-first, a equipe escreve handlers e documenta depois. No fluxo spec-first, a equipe define o contrato primeiro e usa esse arquivo para guiar implementação, testes e documentação.

Ciclo de vida spec-first vs code-first

As duas abordagens podem produzir os mesmos endpoints. A diferença está em quando os problemas aparecem.

Com spec-first, frontend, backend e QA não precisam esperar uns pelos outros. Todos trabalham a partir de uma definição compartilhada.

Exemplo prático: criando uma spec OpenAPI para /users

Vamos criar uma API simples com duas operações:

  • GET /users: lista usuários
  • POST /users: cria um usuário

1. Comece pelo cabeçalho da especificação

openapi: 3.0.3
info:
  title: Users API
  version: 1.0.0
servers:
  - url: https://api.example.com/v1
Enter fullscreen mode Exit fullscreen mode

Esse bloco define:

  • A versão do OpenAPI
  • O nome da API
  • A versão da API
  • A URL base usada pelos endpoints

2. Defina o schema compartilhado User

Use components/schemas para declarar objetos reutilizáveis.

components:
  schemas:
    User:
      type: object
      required: [id, email, createdAt]
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        name:
          type: string
        createdAt:
          type: string
          format: date-time
Enter fullscreen mode Exit fullscreen mode

Com isso, qualquer endpoint pode reutilizar o schema User usando $ref.

3. Adicione GET /users

paths:
  /users:
    get:
      summary: List users
      operationId: listUsers
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        "200":
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/User"
Enter fullscreen mode Exit fullscreen mode

Aqui o contrato deixa claro que:

  • limit é um parâmetro de query.
  • O valor padrão é 20.
  • O máximo permitido é 100.
  • A resposta 200 retorna um array de User.

4. Adicione POST /users

paths:
  /users:
    post:
      summary: Create a user
      operationId: createUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email:
                  type: string
                  format: email
                name:
                  type: string
      responses:
        "201":
          description: User created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "400":
          description: Invalid request body
Enter fullscreen mode Exit fullscreen mode

Esse endpoint define:

  • email como campo obrigatório.
  • name como campo opcional.
  • 201 para criação bem-sucedida.
  • 400 para corpo inválido.

5. Arquivo OpenAPI completo

Juntando tudo:

openapi: 3.0.3
info:
  title: Users API
  version: 1.0.0

servers:
  - url: https://api.example.com/v1

paths:
  /users:
    get:
      summary: List users
      operationId: listUsers
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        "200":
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/User"

    post:
      summary: Create a user
      operationId: createUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email:
                  type: string
                  format: email
                name:
                  type: string
      responses:
        "201":
          description: User created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
        "400":
          description: Invalid request body

components:
  schemas:
    User:
      type: object
      required: [id, email, createdAt]
      properties:
        id:
          type: string
          format: uuid
        email:
          type: string
          format: email
        name:
          type: string
        createdAt:
          type: string
          format: date-time
Enter fullscreen mode Exit fullscreen mode

Sem implementar nenhum servidor, você já definiu:

  • Campos obrigatórios
  • Tipos de dados
  • Formatos esperados
  • Status codes
  • Contrato de request e response

Gerando mocks, testes e documentação a partir da spec

A vantagem do spec-first é reutilizar o mesmo arquivo em várias etapas do ciclo de desenvolvimento.

Mocks

Um servidor mock lê a especificação e retorna respostas compatíveis com os schemas.

Por exemplo, para GET /users, uma ferramenta pode gerar uma resposta como:

[
  {
    "id": "3f6f3b7e-7c5c-4c8e-91c2-8b0f7c9b2a11",
    "email": "ana@example.com",
    "name": "Ana",
    "createdAt": "2026-06-02T10:30:00Z"
  }
]
Enter fullscreen mode Exit fullscreen mode

O frontend pode integrar com esse mock antes de o backend existir. Se a spec mudar, o mock muda junto.

Testes de contrato

A especificação também vira referência para testes.

Exemplos de validações úteis:

  • POST /users deve retornar 201 quando email é válido.
  • POST /users deve retornar 400 quando email está ausente.
  • GET /users deve retornar um array.
  • Cada item do array deve seguir o schema User.
  • id deve ser uma string no formato uuid.
  • createdAt deve estar em date-time.

Em vez de inventar asserções manualmente, você verifica se a implementação cumpre o contrato aprovado.

Documentação

A documentação da API pode ser renderizada diretamente do OpenAPI.

Isso evita manter uma segunda versão manual da referência da API. Endpoints, parâmetros, schemas e status codes vêm do mesmo YAML usado para mocks e testes.

Esse fluxo também combina bem com um fluxo de trabalho de API git-native, porque a especificação é um arquivo de texto versionável. Alterações no contrato aparecem como diffs em pull requests.

Fazendo isso no Apidog

O Apidog oferece suporte a esse fluxo pelo Modo Spec-First. Em vez de tratar OpenAPI como uma exportação final, ele trata a especificação como o projeto principal.

Um fluxo prático fica assim:

  1. Crie ou cole a especificação OpenAPI no editor.
  2. Valide o YAML.
  3. Gere mocks para os endpoints definidos.
  4. Compartilhe o mock com o frontend.
  5. Use a mesma spec para gerar documentação.
  6. Quando o backend estiver pronto, execute os endpoints reais contra o contrato.
  7. Revise mudanças da spec no Git.

A sincronização bidirecional com Git ajuda a manter o contrato revisável. Se você editar o YAML localmente e fizer push, o Apidog acompanha a mudança. Se editar no Apidog, a alteração pode ser registrada como commit para revisão da equipe.

Para uma comparação mais detalhada entre os modelos, veja spec-first vs design-first no Apidog.

Checklist spec-first antes de implementar

Use esta lista antes de liberar a implementação:

  • [ ] A especificação valida sem erros contra o schema OpenAPI.
  • [ ] Cada endpoint tem pelo menos uma resposta de sucesso.
  • [ ] Cada endpoint tem pelo menos uma resposta de erro.
  • [ ] Schemas compartilhados estão em components/schemas.
  • [ ] Objetos reutilizáveis usam $ref em vez de cópia manual.
  • [ ] Campos obrigatórios estão marcados com required.
  • [ ] Formatos como uuid, email e date-time estão definidos quando necessário.
  • [ ] A spec está versionada no Git.
  • [ ] Mudanças no contrato passam por pull request.
  • [ ] O servidor mock roda a partir da spec.
  • [ ] O frontend consegue consumir o mock.
  • [ ] Testes de contrato validam respostas reais contra os schemas.
  • [ ] A documentação publicada é renderizada a partir do mesmo arquivo.

Se todos os itens estiverem completos, frontend, backend e QA podem trabalhar em paralelo sem depender de suposições diferentes.

FAQ

Desenvolvimento de API spec-first é o mesmo que design-first?

Na prática, quase sempre sim. Design-first, contract-first e spec-first descrevem a mesma ideia: definir a interface antes da implementação.

A diferença é que spec-first enfatiza o artefato concreto usado como fonte da verdade: o arquivo OpenAPI.

Preciso escrever YAML manualmente?

Não. Você pode criar a especificação em um editor visual ou escrever YAML diretamente.

O ponto principal não é o formato de edição. O importante é que o contrato exista, seja revisável e seja aprovado antes da implementação.

Como evitar que a spec e o código fiquem desalinhados?

Trate a especificação como fonte da verdade.

Na prática:

  • Mantenha a spec no Git.
  • Revise mudanças de contrato em pull requests.
  • Rode testes de contrato na CI.
  • Faça a build falhar quando a resposta real não bater com o schema.
  • Use mocks e documentação gerados a partir do mesmo arquivo.

O desenvolvimento spec-first muda a ordem do trabalho: primeiro o contrato, depois a implementação. Essa pequena mudança reduz retrabalho, antecipa problemas de integração e permite que as equipes construam em paralelo.

Para testar o fluxo completo, abra o Modo Spec-First no Apidog e conecte sua especificação ao repositório.

Top comments (0)