REST API and interface design conventions for production applications. Use when: designing API endpoints, creating route handlers, defining request/response schemas, handling API errors, adding pagination, versioning APIs, or reviewing API architecture.
From cksnpx claudepluginhub cardinalconseils/claude-starter --plugin cksThis skill is limited to using the following tools:
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Domain expertise for designing consistent, predictable REST APIs. Covers resource naming, HTTP verbs, status codes, error formats, pagination, filtering, versioning, rate limiting, validation, and documentation.
/users not /getUsers/users, /orders, /products/users/:id/orders (orders belonging to a user)/order-items not /orderItems| Verb | Purpose | Idempotent | Request Body |
|---|---|---|---|
| GET | Read resource(s) | Yes | No |
| POST | Create resource | No | Yes |
| PUT | Replace resource entirely | Yes | Yes |
| PATCH | Update resource partially | Yes | Yes |
| DELETE | Remove resource | Yes | No |
| Code | When to Use |
|---|---|
| 200 OK | Successful GET, PUT, PATCH, or DELETE |
| 201 Created | Successful POST that creates a resource |
| 204 No Content | Successful DELETE with no response body |
| 400 Bad Request | Malformed request syntax |
| 401 Unauthorized | Missing or invalid authentication |
| 403 Forbidden | Authenticated but insufficient permissions |
| 404 Not Found | Resource does not exist |
| 409 Conflict | Resource state conflict (duplicate email, version mismatch) |
| 422 Unprocessable Entity | Valid syntax but semantic validation failed |
| 429 Too Many Requests | Rate limit exceeded |
| 500 Internal Server Error | Unhandled server error |
Use a consistent envelope for all errors:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Email is required" },
{ "field": "age", "message": "Must be a positive integer" }
]
}
}
code: machine-readable, UPPER_SNAKE_CASEmessage: human-readable summarydetails: array of field-level errors (optional)?cursor=abc123&limit=20 -- stable under inserts/deletes?page=2&limit=20 -- simpler but drifts with mutations{ data: [...], pagination: { hasMore, nextCursor, total } }?status=active&role=admin?sort=created_at:desc/v1/users, /v2/users429 with Retry-After header (seconds until reset)X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset| Rationalization | Reality |
|---|---|
| "We can clean up the API later" | API contracts are promises to consumers. Breaking changes after launch require versioning. |
| "Let's just use POST for everything" | HTTP verbs communicate intent. GET for reads, POST for creates, PUT/PATCH for updates, DELETE for deletes. |
| "Error messages don't matter" | Vague errors waste debugging time. "Invalid request" vs "email field is required" -- which helps? |
| "We don't need pagination yet" | Unpaginated list endpoints will time out or OOM as data grows. Add pagination from the start. |
| "Versioning is over-engineering" | One breaking change without versioning breaks every consumer simultaneously. |
/getUser, /deleteOrder)