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.
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,emailedate-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
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
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"
Aqui o contrato deixa claro que:
-
limité um parâmetro de query. - O valor padrão é
20. - O máximo permitido é
100. - A resposta
200retorna um array deUser.
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
Esse endpoint define:
-
emailcomo campo obrigatório. -
namecomo campo opcional. -
201para criação bem-sucedida. -
400para 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
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"
}
]
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 /usersdeve retornar201quandoemailé válido. -
POST /usersdeve retornar400quandoemailestá ausente. -
GET /usersdeve retornar um array. - Cada item do array deve seguir o schema
User. -
iddeve ser uma string no formatouuid. -
createdAtdeve estar emdate-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:
- Crie ou cole a especificação OpenAPI no editor.
- Valide o YAML.
- Gere mocks para os endpoints definidos.
- Compartilhe o mock com o frontend.
- Use a mesma spec para gerar documentação.
- Quando o backend estiver pronto, execute os endpoints reais contra o contrato.
- 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
$refem vez de cópia manual. - [ ] Campos obrigatórios estão marcados com
required. - [ ] Formatos como
uuid,emailedate-timeestã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)