# API Contract Reviewer

Review an API design for REST compliance, consistency, security, breaking changes, and developer experience. Accepts OpenAPI specs, markdown endpoint lists, or plain descriptions.

## Quick Reference

# API Contract Reviewer

> **Purpose:** Review an API design — REST endpoints, OpenAPI spec, or informal description — for consistency, REST principle adherence, security posture, breaking change risk, and developer experience quality. Catches design mistakes before they become permanent.

---

## Invocation

```
/api-review <spec-or-description>
```

**Accepts:**
- OpenAPI YAML or JSON
- Markdown list of endpoints
- Plain English description of the API

---

## Review Dimensions

### 1. REST Compliance

- HTTP verbs used correctly?
  - `GET` = read, safe, idempotent
  - `POST` = create or non-idempotent action
  - `PUT` = full replace, idempotent
  - `PATCH` = partial update, idempotent
  - `DELETE` = remove, idempotent
- Resource names are nouns, not verbs (`/users` not `/getUsers`)
- Nested resources used appropriately (`/users/{id}/orders` vs `?user_id=`)
- Status codes appropriate: 201 (created), 204 (no content), 400 (bad request), 401 (unauth), 403 (forbidden), 404 (not found), 409 (conflict), 422 (validation), 429 (rate limit)

---

### 2. Consistency Audit

- Naming convention: consistent across all endpoints? (camelCase vs snake_case vs kebab-case)
- Pagination: consistent style on all list endpoints? (cursor vs offset, same field names)
- Error response shape: same structure everywhere?
- Date format: ISO 8601 throughout? (`2026-02-20T00:00:00Z`)
- ID format: UUID vs integer vs slug — consistent?
- Envelope style: `{ data: [...] }` vs `[...]` — consistent?

---

### 3. Security Review

- Authentication requirements stated for every endpoint?
- Authorization: can users access other users' resources? Is it enforced?
- Rate limiting: mutation endpoints (`POST`, `PUT`, `DELETE`) protected?
- Input validation constraints defined in spec (max lengths, allowed values)?
- Sensitive data in responses? (passwords, tokens, internal IDs, PII)
- Webhook endpoints: HMAC signature verification mentioned?

---

### 4. Breaking Change Analysis

If reviewing a v2 or modification to an existing API:

| Change | Breaking? |
|--------|-----------|
| Add new optional field to response | No |
| Add new required field to request | **Yes** |
| Remove field from response | **Yes** |
| Rename field | **Yes** |
| Change field type | **Yes** |
| Change status code | **Yes** |
| Add new endpoint | No |
| Remove endpoint | **Yes** |

List every breaking change with a migration guide.

---

### 5. Developer Experience

- Field names self-documenting? (`userId` not `uid`)
- Error messages actionable? ("Email is required" not "invalid input")
- Pagination cursor-based or offset-based? (cursor preferred for large/live datasets)
- Batch endpoints for operations typically done in loops?
- Consistent use of `_at` suffix for timestamps (`created_at`, `updated_at`)?

---

## Output Format

```
## API Review: [API Name]

### Summary
[2-3 sentence quality assessment]

### Findings

[SEVERITY] Category — METHOD /path
Issue description.
Suggested fix: ...

### Breaking Changes
[List or "None identified"]

### Recommendations
[Prioritized improvements]

### Score: [X/10]
```

**Severity levels:**
- `CRITICAL` — Security hole or data loss risk
- `HIGH` — Bug that will cause real failures
- `MEDIUM` — Consistency or DX issue
- `LOW` — Style or minor improvement

---

## Rules

- Flag **every** mutation endpoint that doesn't explicitly state its auth requirement
- Unbounded list endpoints (no pagination, no LIMIT) are always rated **MEDIUM** or higher
- REST violations rated **LOW** unless they cause real interoperability problems
- Never approve an API that exposes user data from other users without authorization checks
- If the API has no versioning strategy: flag it as **MEDIUM** and suggest `/v1/` prefix

## Playground

<!DOCTYPE html><html><head><meta charset='utf-8'><style>*{box-sizing:border-box;margin:0;padding:0}body{background:#0d1117;color:#e6edf3;font-family:monospace;font-size:12px;height:100vh;display:flex;flex-direction:column;overflow:hidden}.header{background:#161b22;border-bottom:1px solid #30363d;padding:8px 14px;font-size:11px;color:#8b949e;display:flex;justify-content:space-between;align-items:center;flex-shrink:0}.title{color:#58a6ff;font-weight:bold;font-size:13px}.panels{display:flex;flex:1;overflow:hidden}.panel{flex:1;overflow:auto;padding:12px;border-right:1px solid #30363d}.panel:last-child{border-right:none}.label{font-size:10px;color:#8b949e;text-transform:uppercase;letter-spacing:.08em;margin-bottom:6px}pre{white-space:pre-wrap;word-break:break-word;line-height:1.5}</style></head><body><div class='header'><span class='title'>API Contract Reviewer</span><span>Example · SkillSlap</span></div><div class='panels'><div class='panel'><div class='label'>Input: OpenAPI excerpt</div><pre><span style='color:#8b949e'>POST /api/skills</span>
<span style='color:#8b949e'>requestBody:</span>
<span style='color:#8b949e'>  content:</span>
<span style='color:#8b949e'>    application/json:</span>
<span style='color:#8b949e'>      schema:</span>
<span style='color:#8b949e'>        type: object</span>
<span style='color:#8b949e'>        properties:</span>
<span style='color:#8b949e'>          title: {type: string}</span>
<span style='color:#8b949e'>          content: {type: string}</span></pre></div><div class='panel'><div class='label'>Output: Contract review</div><pre><span style='color:#f85149'>🔴 No required fields declared</span>
<span style='color:#8b949e'>Both title and content must be</span>
<span style='color:#8b949e'>required. Add:</span>
<span style='color:#8b949e'>  required: [title, content]</span>

<span style='color:#f85149'>🔴 No maxLength on content</span>
<span style='color:#8b949e'>Unbounded string → DoS via huge</span>
<span style='color:#8b949e'>payloads. Add maxLength: 50000</span>

<span style='color:#e3b341'>🟡 Missing 401 / 422 responses</span>
<span style='color:#8b949e'>Document error cases so clients</span>
<span style='color:#8b949e'>know what to expect on bad input.</span>

<span style='color:#e3b341'>🟡 No description on properties</span>
<span style='color:#8b949e'>Add description: fields for SDK</span>
<span style='color:#8b949e'>and docs auto-generation.</span></pre></div></div></body></html>
