agentleFS
luckysluckys/agent-skills/skills/rest-api-best-practices/SKILL.md

rest-api-best-practices

Skill5 starsChanged 30 days agoMITView on GitHub

Use when designing or reviewing REST resources, methods, status codes, errors, pagination, filtering, versioning, authorization, idempotency, or public compatibility. Expose domain capabilities while preserving existing HTTP contracts; use the domain and infrastructure skills for implementation rules.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

48 rules. About 0 are common, 21 are distinctive, and 27 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈21

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 27

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill when the main question is how to design, review, or improve a REST API — from URL structure to error formats to security.

    line 12
  2. Distinctive:

    Start from what the consumer needs, not from what the database looks like.

    line 16
  3. Distinctive:

    Use HTTP as designed — methods, status codes, and headers carry meaning.

    line 17
  4. Distinctive:

    Use resource nouns; model a non-CRUD domain action as a task subresource when the contract calls for it.

    line 27
  5. Distinctive:

    PUT for full replacement (idempotent)

    line 32
  6. Distinctive:

    DELETE for removal (idempotent)

    line 34
  7. Distinctive:

    Keep paths flat where possible — at most two levels of nesting.

    line 37
  8. Distinctive:

    Use query parameters for filtering, sorting, and pagination.

    line 38
  9. Very specific:

    Use task URLs (POST /orders/{id}/cancel) for domain operations that aren't simple CRUD.

    line 39
  10. Distinctive:

    Use HTTP headers for metadata (pagination, rate limits).

    line 44
  11. Distinctive:

    Use the right 4xx or 5xx status code — never return 200 for errors.

    line 47
  12. Distinctive:

    Follow RFC 9457 (Problem Details, which obsoletes RFC 7807) when the team needs a standard.

    line 49
  13. Very specific:

    Default to URL versioning (/v1/).

    line 52
  14. Distinctive:

    Treat a breaking change as a reason to bump the version, not to patch silently.

    line 53
  15. Very specific:

    Default to cursor-based for large or real-time datasets.

    line 70
  16. Very specific:

    Avoid exposing raw CRUD when the domain has real business operations.

    line 77
  17. Distinctive:

    Use plural nouns for collection endpoints.

    line 81
  18. Very specific:

    Avoid transport-operation names such as /getUsers.

    line 82
  19. Distinctive:

    Never expose stack traces, SQL errors, or internal paths in error responses.

    line 86
  20. Very specific:

    Use Accept and Content-Type headers for content negotiation.

    line 88
  21. Distinctive:

    Put secrets in headers, never in query parameters.

    line 89
  22. Distinctive:

    Always use HTTPS — never plain HTTP for API traffic.

    line 90
  23. Distinctive:

    Every status code is intentional and precise.

    line 95
  24. Distinctive:

    Every endpoint maps directly to a database table with full CRUD.

    line 108
  25. Distinctive:

    No versioning strategy — breaking changes deployed silently.

    line 109
  26. Distinctive:

    No request ID header — errors cannot be correlated in logs.

    line 112
  27. Distinctive:

    No documentation or documentation that doesn't match reality.

    line 113
  28. Very specific:

    Read references/retry-contracts.md when defining idempotency, unknown outcomes, or compatibility of published behavior.

    line 117
  29. Very specific:

    Read references/url-design.md for URL structure, naming conventions, nesting rules, versioning, and task-based URLs.

    line 119
  30. Very specific:

    Read references/http-semantics.md for HTTP method semantics, idempotency, safety, status code selection, and key headers.

    line 120
  31. Very specific:

    Read references/request-response-design.md for filtering, sorting, pagination (offset and cursor), content negotiation, and response shape.

    line 121
  32. Very specific:

    Read references/error-handling.md for RFC 9457 Problem Details, centralized mapping, status policy, redaction, domain failure translation, …

    line 122
  33. Very specific:

    Read references/security.md for authentication (JWT, API keys, OAuth 2.0), authorization, rate limiting, CORS, and HTTPS enforcement.

    line 123
  34. Very specific:

    Read references/api-design-philosophy.md for REST architectural constraints, the CRUD anti-pattern, task-based API design, and HATEOAS.

    line 124
  35. Very specific:

    Read references/observability.md for request IDs, structured logging, metrics, distributed tracing, health endpoints, and alerting.

    line 125
  36. Very specific:

    Read references/documentation.md for what to document per endpoint, working examples, OpenAPI 3.x spec structure, keeping docs executable …

    line 126
  37. Very specific:

    Read references/caching.md for Cache-Control directives, ETag/Last-Modified validation, conditional writes (optimistic concurrency), cache …

    line 127
  38. Very specific:

    Read references/testing-apis.md for the API test pyramid, contract testing (OpenAPI, Pact), what to test beyond the happy path, and test …

    line 128
  39. Very specific:

    Read references/language-examples.md for an index of language-specific implementation examples.

    line 129
  40. Very specific:

    Read references/typescript-examples.md for REST API implementation in TypeScript (Express, NestJS).

    line 130
  41. Very specific:

    Read references/python-examples.md for REST API implementation in Python (FastAPI, Django REST Framework).

    line 131
  42. Very specific:

    Read references/go-examples.md for REST API implementation in Go (net/http, Chi).

    line 132
  43. Very specific:

    Read references/php-examples.md for REST API implementation in PHP (Laravel, Symfony).

    line 133
  44. Very specific:

    Read references/java-examples.md for REST API implementation in Java (Spring Boot 3.x).

    line 134
  45. Very specific:

    Read references/rust-examples.md for REST API implementation in Rust (axum).

    line 135
  46. Very specific:

    Use ddd-best-practices when the API surface should reflect a Bounded Context or align with domain language.

    line 139
  47. Very specific:

    Use design-patterns-best-practices for internal patterns within the API implementation (Repository, Service Layer, etc.).

    line 140
  48. Very specific:

    Use oop-best-practices for controller and service design within the API layer.

    line 141

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

REST API Best Practices

Use this skill when the main question is how to design, review, or improve a REST API — from URL structure to error formats to security.

Working Style

  1. Start from what the consumer needs, not from what the database looks like.
  2. Use HTTP as designed — methods, status codes, and headers carry meaning.
  3. Express domain capabilities, not data operations.
  4. Make errors as informative as successes.
  5. Design for change: version early, break compatibility deliberately.

Design Workflow

  1. Define the resources.
    • What are the concepts the consumer needs to interact with?
    • Name them with nouns, in plural form.
    • Use resource nouns; model a non-CRUD domain action as a task subresource when the contract calls for it.
  2. Choose the right HTTP method.
    • GET for retrieval (safe, idempotent, cacheable)
    • POST for creation or non-idempotent operations
    • PUT for full replacement (idempotent)
    • PATCH for partial update
    • DELETE for removal (idempotent)
  3. Design the URL.
    • Keep paths flat where possible — at most two levels of nesting.
    • Use query parameters for filtering, sorting, and pagination.
    • Use task URLs (POST /orders/{id}/cancel) for domain operations that aren't simple CRUD.
  4. Define response shapes.
    • Choose a consistent field naming convention (camelCase or snake_case) and stick to it.
    • Return only what the consumer needs.
    • Use HTTP headers for metadata (pagination, rate limits).
  5. Define error responses.
    • Use the right 4xx or 5xx status code — never return 200 for errors.
    • Return a structured error body with a machine-readable code and a human-readable message.
    • Follow RFC 9457 (Problem Details, which obsoletes RFC 7807) when the team needs a standard.
  6. Add versioning.
    • Default to URL versioning (/v1/).
    • Treat a breaking change as a reason to bump the version, not to patch silently.

Heuristics

Resource Naming

Nouns, plural, lowercase, kebab-case for multi-word: /user-profiles, /order-items.

HTTP Method Semantics

GET is safe and must never change state. POST creates or triggers actions. PUT replaces the entire resource. PATCH patches specific fields. DELETE removes.

Status Code Choice

2xx = success. 4xx = client error. 5xx = server error. Never return 200 for a failed operation.

Error Format

One consistent error envelope for all failures. Machine-readable code field, human-readable message, optional errors array for field-level validation details.

Pagination

Default to cursor-based for large or real-time datasets. Offset-based is fine for small, bounded collections. Always include a Link header with navigation links.

Retry safety

A key belongs to one logical intent and remains stable across retries. Define atomic claim, payload binding, replay authorization, in-flight behavior, and retention before calling a write retry-safe.

CRUD vs. Task-Based Design

Avoid exposing raw CRUD when the domain has real business operations. Prefer POST /orders/{id}/cancel over PATCH /orders/{id} with { "status": "cancelled" }.

Day-to-Day Rules

  • Use plural nouns for collection endpoints.
  • Avoid transport-operation names such as /getUsers; an intentional task subresource such as /orders/{id}/cancel is valid.
  • Return 201 Created (not 200) after a successful POST that creates a resource.
  • Include a Location header pointing to the new resource after 201.
  • Return 204 No Content when there is nothing meaningful to return in the body.
  • Never expose stack traces, SQL errors, or internal paths in error responses.
  • Paginate every collection endpoint — never return an unbounded list.
  • Use Accept and Content-Type headers for content negotiation.
  • Put secrets in headers, never in query parameters.
  • Always use HTTPS — never plain HTTP for API traffic.

Good Signals

  • URL paths read like a sentence: GET /orders/{id}/items.
  • Every status code is intentional and precise.
  • Errors have a machine-readable code the client can branch on.
  • Pagination is consistent across all collection endpoints.
  • Breaking changes require a version bump.
  • The API surface reflects domain language, not table names.

Warning Signs

  • Verbs in URL paths: /getUser, /createOrder, /deleteItem.
  • 200 OK returned for validation errors or business failures.
  • Error bodies expose stack traces or raw SQL.
  • Collections returned without pagination.
  • Inconsistent field naming: sometimes userId, sometimes user_id.
  • Every endpoint maps directly to a database table with full CRUD.
  • No versioning strategy — breaking changes deployed silently.
  • API key or token passed as a query parameter.
  • Response objects nested more than two levels deep.
  • No request ID header — errors cannot be correlated in logs.
  • No documentation or documentation that doesn't match reality.

References

  • Read references/retry-contracts.md when defining idempotency, unknown outcomes, or compatibility of published behavior.
  • Read references/url-design.md for URL structure, naming conventions, nesting rules, versioning, and task-based URLs.
  • Read references/http-semantics.md for HTTP method semantics, idempotency, safety, status code selection, and key headers.
  • Read references/request-response-design.md for filtering, sorting, pagination (offset and cursor), content negotiation, and response shape.
  • Read references/error-handling.md for RFC 9457 Problem Details, centralized mapping, status policy, redaction, domain failure translation, and validation errors.
  • Read references/security.md for authentication (JWT, API keys, OAuth 2.0), authorization, rate limiting, CORS, and HTTPS enforcement.
  • Read references/api-design-philosophy.md for REST architectural constraints, the CRUD anti-pattern, task-based API design, and HATEOAS.
  • Read references/observability.md for request IDs, structured logging, metrics, distributed tracing, health endpoints, and alerting.
  • Read references/documentation.md for what to document per endpoint, working examples, OpenAPI 3.x spec structure, keeping docs executable with contract testing, and changelog practices.
  • Read references/caching.md for Cache-Control directives, ETag/Last-Modified validation, conditional writes (optimistic concurrency), cache layers, and invalidation strategies.
  • Read references/testing-apis.md for the API test pyramid, contract testing (OpenAPI, Pact), what to test beyond the happy path, and test isolation.
  • Read references/language-examples.md for an index of language-specific implementation examples.
  • Read references/typescript-examples.md for REST API implementation in TypeScript (Express, NestJS).
  • Read references/python-examples.md for REST API implementation in Python (FastAPI, Django REST Framework).
  • Read references/go-examples.md for REST API implementation in Go (net/http, Chi).
  • Read references/php-examples.md for REST API implementation in PHP (Laravel, Symfony).
  • Read references/java-examples.md for REST API implementation in Java (Spring Boot 3.x).
  • Read references/rust-examples.md for REST API implementation in Rust (axum).

Related Skills

  • Use ddd-best-practices when the API surface should reflect a Bounded Context or align with domain language.
  • Use design-patterns-best-practices for internal patterns within the API implementation (Repository, Service Layer, etc.).
  • Use oop-best-practices for controller and service design within the API layer.

Source Influences

This skill is synthesized from:

  • REST API Design Rulebook by Mark Masse
  • RESTful Web APIs by Leonard Richardson & Mike Amundsen
  • RFC 9457 — Problem Details for HTTP APIs
  • RFC 9110 — HTTP Semantics
  • Fran Iglesias — API REST series (franiglesias.github.io)
  • Derek Comartin — "CRUD APIs are Poor Design" (codeopinion.com)
  • Postman REST API Best Practices
  • Building Microservices by Sam Newman

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.