.claude/skills/api-design-standards/SKILL.md
Use when designing or reviewing RESTful HTTP APIs, endpoint routing, status codes, pagination, error responses, or OpenAPI specs in .NET projects.
npx skillsauth add klod68/littlerae api-design-standardsInstall 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.
| Field | Value |
|---|---|
| Name | RESTful API Design Standards |
| Domain | Web API, HTTP, REST |
| Level | Feature |
| Tags | api, rest, http, endpoints, pagination, openapi |
Activate this skill when the task involves:
These rules layer on top of base architectural standards. On conflict, these win.
<!-- SHARED:rules/api-design.md -->Apply these rules in addition to _base.md for projects exposing HTTP APIs (Minimal API or MVC controllers).
/orders, /users/{id}/addresses — never /getOrders or /createUser./products, /categories./order-items, /shipping-addresses — never camelCase or snake_case in URIs./users/{id}/orders — never /users/{id}/orders/{orderId}/items/{itemId}. Access items directly: /order-items/{itemId}./api/v1/orders — version in the path, not headers, unless the project has an explicit versioning strategy that overrides this default.| Method | Semantics | Idempotent | Safe | Typical Status |
|--------|-----------|------------|------|----------------|
| GET | Read resource(s) | Yes | Yes | 200 OK |
| POST | Create resource | No | No | 201 Created + Location header |
| PUT | Full replace of resource | Yes | No | 204 No Content |
| PATCH | Partial update | No | No | 204 No Content |
| DELETE | Remove resource | Yes | No | 204 No Content or 404 Not Found |
GET for operations with side effects.POST is the only method for non-idempotent operations — never overload GET with query parameters that trigger actions.PUT replaces the entire resource — if only updating partial fields, use PATCH.?page=1&pageSize=20 (offset-based) or ?cursor=abc&limit=20 (cursor-based).{
"items": [...],
"page": 1,
"pageSize": 20,
"totalCount": 142,
"totalPages": 8
}
?status=active&category=electronics.sort parameter with +/- prefix: ?sort=-createdAt,+name (descending by date, ascending by name).q parameter: ?q=wireless+headphones.ProblemDetails format — never plain strings or custom error shapes.400 Bad Request with a ValidationProblemDetails body including field-level errors.422 Unprocessable Entity with a descriptive ProblemDetails.type, title, status, and detail — instance is optional.{
"type": "https://api.example.com/errors/insufficient-stock",
"title": "Insufficient Stock",
"status": 422,
"detail": "Product SKU-123 has only 3 units available; 10 were requested.",
"instance": "/api/v1/orders"
}
null fields are omitted from JSON output (JsonIgnoreCondition.WhenWritingNull) — never send explicit null for absent optional fields."2024-12-15T14:30:00Z" — never local time or Unix timestamps.{ "amount": 49.99, "currency": "USD" } — never bare numbers._links for discoverable related actions only when the project adopts HATEOAS — not mandatory for internal APIs.self, collection-level next/prev for paginated resources.PUT and DELETE are naturally idempotent — no extra work needed.POST operations that must be idempotent (payment, order creation), accept an Idempotency-Key header.RateLimiter middleware.429 Too Many Requests with a Retry-After header.[ProducesResponseType] or .Produces<T>() for all possible status codes — not just the happy path.[Description] or [EndpointSummary] for OpenAPI metadata.[Example] attributes or Swashbuckle filters — never rely on default serialization output.| Anti-Pattern | Fix |
|---|---|
| Verb in URI (/getOrders, /createUser) | Use nouns + HTTP methods: GET /orders, POST /users |
| Unbounded collection endpoint | Add pagination with default + max page size |
| Domain entity as response body | Map to dedicated response DTO |
| Custom error format per endpoint | Use RFC 7807 ProblemDetails everywhere |
| 200 OK for everything | Use semantically correct status codes |
| CamelCase in URIs | Use kebab-case: /order-items |
| Version in Accept header only | Default to URL prefix: /api/v1/ |
| Hardcoded page size | Move to settings class with documented default and max cap |
| Stack traces in error responses | Use ProblemDetails without internal details |
| Local timestamps in responses | Always use ISO 8601 UTC |
api-contracts.md — Interface-first design, return type abstractions, contract versioningminimal-api.md — Minimal API endpoint organization, handlers, filters, validationauth.md — Authentication, authorization, OAuth/OIDC, secrets managementresult-error-handling.md — Result object pattern, error constants, exception boundariestools
Use when cross-cutting concerns (logging, metrics, validation, authorization) are tangled into command handlers or service methods, when building database command pipelines with reorderable concerns, or when HTTP client pipelines or message handlers need composable, independently-replaceable processing stages. Covers ICommandInterceptor interface, InterceptorPipeline with reverse-chain construction, zero-cost Empty sentinel to skip overhead when no interceptors are registered, and ConfigureAwait(false) discipline for library code. Domain: Architecture, Cross-Cutting Concerns. Level: Intermediate. Tags: interceptor, pipeline, middleware, decorator, cross-cutting-concerns.
development
Use when writing integration tests for Razor Pages, MVC, or Minimal API applications to validate routing, middleware, page rendering, and HTTP behavior without a browser or live server, or when adding fast smoke tests to a CI pipeline. Covers WebApplicationFactory<Program> setup with public partial class Program, in-memory test server, AngleSharp HTML parsing, CSS selector assertions, redirect and status code testing, and a shared static fixture pattern for minimal per-test startup overhead. Domain: Testing, ASP.NET Core. Level: Intermediate. Tags: integration-testing, webapplicationfactory, razor-pages, anglesharp, http-testing.
development
Use when designing indexes for new tables, diagnosing slow queries that are not using indexes efficiently, reviewing index fragmentation and maintenance, or when the current indexing strategy results in key lookups, table scans, or missing index warnings. Covers clustered index key selection (narrow, unique, ever-increasing), non-clustered index design for query patterns, covering indexes with INCLUDE columns, filtered indexes for subset queries, composite index column ordering, DMV-based monitoring for missing and unused indexes, and rebuild vs reorganize maintenance thresholds. Domain: Database, Performance. Level: Intermediate. Tags: index, sql-server, covering-index, filtered-index, performance, dmv, maintenance.
development
Use when building a searchable in-memory catalog or registry for documentation sites, admin panels, or type/API browsers where you need keyword matching, fuzzy search, and ranked results without an external search engine or database. Covers RegistryService with weighted scoring across name, description, keywords, and method names; Levenshtein fuzzy matching; synonym expansion; category and subcategory filtering; and singleton DI registration for datasets of hundreds to low thousands of items. Domain: Search, Data Access Patterns. Level: Intermediate. Tags: search, registry, fuzzy-matching, in-memory, catalog, filtering.