skills/mav-bp-api-design/SKILL.md
API design conventions for projects with API surfaces. Covers REST and GraphQL standards, versioning, error formats, pagination, documentation as code, and backwards compatibility. Applied when designing, implementing, or reviewing APIs.
npx skillsauth add thermiteau/maverick mav-bp-api-designInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Ensure all APIs are consistent, predictable, well-documented, and backwards compatible by default. Applies to REST, GraphQL, and any other API surface.
Before applying these standards, load the project-specific API design implementation:
digraph lookup {
"docs/maverick/skills/api-design/SKILL.md exists?" [shape=diamond];
"Read and use alongside these standards" [shape=box];
"Invoke upskill" [shape=box];
"Read generated skill" [shape=box];
"docs/maverick/skills/api-design/SKILL.md exists?" -> "Read and use alongside these standards" [label="yes"];
"docs/maverick/skills/api-design/SKILL.md exists?" -> "Invoke upskill" [label="no"];
"Invoke upskill" -> "Read generated skill";
"Read generated skill" -> "Read and use alongside these standards";
}
docs/maverick/skills/api-design/SKILL.mddo-upskill skill with:
@app\.route|@router\.|app\.get\(|app\.post\(|@RestController|@Query|@Mutation|openapi|swagger**/routes.*, **/controllers/**, **/resolvers/**, **/openapi.*, **/swagger.*/users, /orders, /invoices/line-items, /payment-methods/users/{userId}/orders/users/{id}/orders, not /users/{id}/orders/{orderId}/items/{itemId}/details)| Method | Purpose | Idempotent | Safe | Example |
| -------- | ------------------------ | ---------- | ---- | ---------------------------- |
| GET | Read resource(s) | Yes | Yes | GET /users/123 |
| POST | Create resource | No | No | POST /users |
| PUT | Full replacement | Yes | No | PUT /users/123 |
| PATCH | Partial update | Yes* | No | PATCH /users/123 |
| DELETE | Remove resource | Yes | No | DELETE /users/123 |
*PATCH is idempotent when using merge-patch semantics. Document which patch format you use.
Use the correct status code category:
| Range | Meaning | Common Codes |
| ----- | ------------- | ---------------------------------------------------------------------------- |
| 2xx | Success | 200 OK, 201 Created, 204 No Content |
| 3xx | Redirection | 301 Moved Permanently, 304 Not Modified |
| 4xx | Client error | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity, 429 Too Many Requests |
| 5xx | Server error | 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable |
Rules:
POST that creates a resource returns 201 with a Location headerDELETE returns 204 on success (no body)200 for an error — use the appropriate 4xx/5xx code404 for resources that do not exist, not an empty 200409 for conflicts (duplicate creation, concurrent modification)User, OrderItemfirstName, createdAtInput: CreateUserInput, UpdateOrderInputConnection and edge types with Edge for relay-style paginationPick one approach per project and apply it consistently:
| Strategy | Format | When to use |
| --------------- | ------------------- | ------------------------------------------------- |
| URL path | /v1/users | Public APIs, clear separation, easy to route |
| Accept header | Accept: application/vnd.api.v2+json | Internal APIs, content negotiation preferred |
Rules:
All API errors must use a consistent structure:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "The request body contains invalid fields.",
"details": [
{
"field": "email",
"reason": "Must be a valid email address."
}
],
"correlationId": "req-abc-123"
}
}
Rules:
code is a machine-readable string constant (not an HTTP status code)message is a human-readable description safe to show to end usersdetails is an optional array with field-level or sub-error contextcorrelationId is a request trace identifier for debuggingUse for large, frequently changing datasets:
{
"data": [...],
"pagination": {
"nextCursor": "eyJpZCI6MTAwfQ==",
"hasMore": true
}
}
cursor and limit query parameterslimit to a sensible value (e.g., 20) with a documented maximumUse only for small, stable datasets or when random page access is required:
{
"data": [...],
"pagination": {
"page": 2,
"pageSize": 20,
"totalCount": 157,
"totalPages": 8
}
}
page and pageSize query parameterstotalCount and totalPages in the response429 Too Many Requests when the limit is exceededX-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1704067200
Retry-After: 30
All input validation must happen at the API boundary before business logic executes. See mav-bp-application-security for comprehensive input validation and sanitisation standards.
Key rules:
PUT and DELETE operations must be idempotent by designPOST operations that must be idempotent (e.g., payment creation), require an Idempotency-Key headerDeprecation or Sunset header to responsesWhen reviewing code, flag these patterns:
| Pattern | Issue | Fix |
| -------------------------------------------------- | ---------------------------------- | ------------------------------------------------------ |
| Verbs in URL paths (/getUser, /createOrder) | REST anti-pattern | Use nouns with HTTP methods |
| 200 OK returned for error conditions | Incorrect status code | Use appropriate 4xx/5xx codes |
| No input validation on request handlers | Security and data integrity risk | Validate at the boundary |
| Stack traces or internal paths in error responses | Information disclosure | Use standard error format, log details server-side |
| Inconsistent field naming (camelCase vs snake_case)| Breaks predictability | Pick one convention and apply everywhere |
| Missing pagination on list endpoints | Performance risk at scale | Add cursor or offset pagination |
| Breaking change without version bump | Backwards compatibility violation | Bump version or make the change additive |
| No rate limiting on public endpoints | Abuse and availability risk | Implement rate limiting with appropriate headers |
| No idempotency on payment/financial endpoints | Duplicate processing risk | Require idempotency keys |
| API docs maintained separately from code | Documentation drift | Generate docs from source (OpenAPI, introspection) |
development
--- name: do-test description: Write or update tests for a code change. Operates in two modes: `unit` (module-scoped, fast, deterministic) and `integration` (crosses module / service / database boundaries). Intended to be invoked once per testable change from inside a do-issue-* or do-epic phase. Mode is required. argument-hint: mode: unit or integration user-invocable: true disable-model-invocation: false --- **Depends on:** mav-bp-unit-testing, mav-bp-integration-testing, mav-local-verificati
development
Implement a focused code change. Use this skill as the wrapper for any implementation work so the Maverick workflow report captures what was done and so the agent applies the project's coding standards before editing. Intended to be invoked once per task from inside a do-issue-* or do-epic phase, not standalone.
testing
How to stack a PR on top of an unmerged sibling branch, and how to retarget it to the repo's default branch once the sibling merges. Prevents orphan-merge incidents when a dependent story is ready before its parent.
development
Claim, lease, heartbeat, and release protocols for when multiple Claude Code instances may act on the same issue or epic concurrently. GitHub labels and marker comments are the coordination surface; local state is a cache.