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.md
# 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

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

Release gate checklist

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.

Tip: pair this with contract tests in CI and keep examples synchronized with real API fixtures. Last updated: March 25, 2026.