| name | api-contract-first |
| description | Hard gate before implementing any API endpoint or service interface. Requires a written, reviewed contract (OpenAPI 3.x, protobuf, or GraphQL schema) before any implementation code is written. Prevents breaking changes, misaligned clients, and undocumented behaviour. |
API Contract First
The Law
NO API IMPLEMENTATION WITHOUT A REVIEWED CONTRACT.
Writing endpoints before the contract is building to a spec that doesn't exist.
The contract IS the spec. Code that matches it is correct. Code that doesn't is wrong.
When to Use
Use this skill before writing ANY of these:
- A new REST endpoint
- A new gRPC/protobuf service method
- A new GraphQL query, mutation, or subscription
- A new event schema (Kafka, SQS, webhooks)
- A new inter-service interface
The Contract Process
Step 1: Write the Contract
Choose the format that matches the project's stack:
REST → OpenAPI 3.x
paths:
/orders:
post:
summary: Create a new order
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/ValidationError'
'401':
$ref: '#/components/responses/Unauthorized'
components:
schemas:
CreateOrderRequest:
type: object
required: [userId, items]
properties:
userId:
type: string
format: uuid
items:
type: array
minItems: 1
items:
$ref: '#/components/schemas/OrderItem'
Events / Async → AsyncAPI or JSON Schema
name: order.created
version: 1.0.0
payload:
type: object
required: [orderId, userId, createdAt]
properties:
orderId: { type: string, format: uuid }
userId: { type: string, format: uuid }
createdAt: { type: string, format: date-time }
Step 2: Contract Review Checklist
Before implementation begins, verify the contract satisfies all of these:
Naming & Consistency
Completeness
Versioning
Security
Consumer Perspective
Step 3: Get Contract Approved
Save the contract file to docs/api/ or docs/events/. The contract is reviewed before implementation begins — not after.
Approval gate: the planner agent must reference the approved contract file in the implementation plan. If no contract file is referenced, the plan is not complete.
Step 4: Implement Against the Contract
Implementation is correct when it matches the contract exactly. The contract is the source of truth — not the implementation.
If the implementation reveals that the contract needs to change:
- Update the contract first
- Re-review the changed section
- Then update the implementation
Never silently diverge from the contract. Every divergence is a breaking change waiting to happen.
Step 5: Contract Tests
Write at least one contract test per endpoint that validates the actual response against the OpenAPI schema:
import { validate } from 'openapi-validator'
import { spec } from '../docs/api/openapi.yaml'
test('POST /orders response matches contract', async () => {
const response = await request(app).post('/orders').send(validPayload)
const errors = validate(spec, '/orders', 'post', response)
expect(errors).toHaveLength(0)
})
Rationalization Red Flags
These mean you are about to skip the contract step:
- "The endpoint is simple, I'll document it after"
- "The client team knows what they're getting"
- "We'll sort out the contract in the PR description"
- "It's an internal API, nobody will break"
All of these precede the same outcome: a client built on undocumented assumptions, followed by a breaking change that neither team sees coming.