API Spec Template
Use this structure to make API contracts testable, reviewable, and stable for client/server teams. The notes below help you avoid hidden breaking changes.
# API Spec Template (OpenAPI mindset) ## Endpoint - Method: GET/POST/PUT/DELETE - Path: /v1/... - Owner: ... ## Request - Headers: - Query: - Body schema: - field: type / required / default / constraints - Example request: ## Response - Success (2xx): - schema: - example: - Error (4xx/5xx): - code: string - message: string - traceId: string - example: ## Compatibility - Backward compatibility notes: - Deprecation strategy: ## Test Checklist - [ ] happy path - [ ] validation errors - [ ] auth/permission - [ ] timeout/retry/idempotency
What this template protects
- Consumer breakage from undocumented schema changes.
- Inconsistent error shapes across endpoints.
- Retry bugs on write endpoints without idempotency rules.
- Release surprises caused by unclear compatibility policy.
How to fill key sections
The Request section should specify field type, required flag, constraints, and defaults. The Response section should include the exact success schema and standardized error envelope. The Compatibility section clarifies what can change in place versus what needs versioning. The Test Checklist should cover success, validation, auth, conflict, timeout, and retry paths.
Documenting these upfront is usually faster than reverse-engineering contract intent after bugs appear.
Common contract anti-patterns
- Renaming/removing response fields in the same API version.
- Returning different error formats by endpoint owner preference.
- Relying on undocumented default sort order in list APIs.
- Treating retries as infrastructure-only concerns.
Release gate checklist
- Contract tests run in CI and include non-happy paths.
- Breaking changes are versioned and announced.
- Monitoring can detect response code/schema anomalies.
- Rollback preserves previous consumer behavior.
Related guides: API contract checklist and Given/When/Then template.
Real-world example: payment refund endpoint
## Endpoint POST /v1/payments/:paymentId/refund ## Request | Field | Type | Required | Constraints | |-------------|--------|----------|------------------------| | amount | number | yes | > 0, ≤ original amount | | reason | string | yes | max 500 chars | | idempotencyKey | string | yes | UUID v4, unique per refund | ## Response - Success (200): - refundId: string (UUID) - status: "pending" | "completed" - amount: number - createdAt: ISO 8601 - Error (409 — duplicate idempotency key): - code: "REFUND_ALREADY_PROCESSED" - message: "A refund with this idempotency key already exists" - traceId: string - existingRefundId: string - Error (422 — exceeds original): - code: "REFUND_EXCEEDS_PAYMENT" - message: "Refund amount exceeds original payment" - traceId: string ## Compatibility - This is v1; field additions are non-breaking - Removing `reason` field would require v2 ## Test Checklist - [x] happy path: full and partial refund - [x] validation: amount > original, missing fields - [x] idempotency: duplicate key returns 409 with original refund - [x] auth: only payment owner or admin can refund - [x] timeout: refund request times out → status check via GET
Editorial note
This template covers API specification for spec-first engineering teams. The refund endpoint example is an illustrative scenario.
- Author: Daniel Marsh
- Editorial policy: How we review and update content
- Corrections: Contact the editor
Tip: pair this with contract tests in CI and keep examples synchronized with real API fixtures. Last updated: March 25, 2026.