---
name: design-rest-api
description: Designs a clean REST API before you build it - resource names, HTTP methods and status codes, request and response shapes, pagination, filtering, errors, versioning and auth - written down as a short contract the front end can rely on. Use when the user is planning API routes or endpoints, choosing status codes or an error format, or tidying an inconsistent API.
license: MIT
metadata:
  category: backend
  tags: "api,rest,architecture"
  author: johnny-bravo
  version: "1.0"
  updated: "2026-11-02"
  status: published
  aliases: "api design, api routes, endpoint naming, error format"
  source_url: "https://github.com/wshobson/agents/tree/7e2fb559cf4b824b27f1fec49fe88f7511066d26/plugins/backend-development/skills/api-design-principles"
  source_license: MIT
  copyright: "Copyright (c) 2024 Seth Hobson"
  original_author: "Seth Hobson (wshobson/agents, api-design-principles)"
  modified: "Adapted by TheSkillVault: narrowed to REST for app builders, rewritten as a design order with an original endpoint table and error shape; GraphQL sections dropped; added auth and safety notes, gotchas and done-when."
  imported_on: "2026-11-02"
---

# Design a REST API

A good API is boring and predictable. Decide the rules once, write them down, and every endpoint follows them.

## When to use
- You are about to build the backend for an app and want endpoints planned first.
- Your routes mix styles, such as `/getUsers` next to `/orders/list`.
- A front-end or mobile developer needs a contract to build against.

## When not to use
- You only need to call someone else's API. Read their docs instead.

## Steps
1. List the nouns your app stores: users, projects, invoices. Each becomes a plural resource such as `/projects`.
2. Map actions to methods: `GET` reads, `POST` creates, `PATCH` updates part, `PUT` replaces, `DELETE` removes.
3. Nest only one level for ownership: `/projects/{id}/tasks`. Go flat beyond that.
4. Pick status codes and stick to them (table below).
5. Define one error shape for every endpoint.
6. Add pagination to every list from day one, with a `limit` and a cursor or page.
7. Use query parameters for filters and sorting: `?status=open&sort=-created_at`.
8. Decide auth per route: public, signed-in, owner-only, admin.
9. Version the API (`/v1`) or commit to only additive changes.
10. Write it down as an OpenAPI file or a short Markdown table, and review it before coding.

| Situation | Status |
| --- | --- |
| Read or update worked | 200 |
| Created | 201 plus the new resource |
| Deleted, nothing to return | 204 |
| Bad input | 400 or 422 with field errors |
| Not signed in | 401 |
| Signed in, not allowed | 403 (or 404 to hide it exists) |
| Not found | 404 |
| Too many requests | 429 |

```json
{ "error": { "code": "validation_failed", "message": "Email is required", "fields": { "email": "required" } } }
```

## Gotchas
- Never trust an id from the URL alone. Check the signed-in user owns the record.
- Never return password hashes, tokens or internal fields. Use explicit response shapes.
- Verbs in paths (`/createUser`) drift fast. Let the method carry the verb.
- Unpaginated lists work in testing and fall over in production.

## Portability
Works with any framework: Next.js route handlers, Express, Hono, FastAPI or Rails. If you use GraphQL or tRPC instead, the same rules on naming, errors and auth still apply.

## Example prompt
"Design the REST endpoints for a simple project tracker with projects, tasks and comments. Include status codes and an error format."

## Done when
- Every endpoint has a method, path, auth rule, request and response shape.
- Errors share one format and lists are paginated.
- The contract is saved in the repo (OpenAPI or Markdown).

---
Adapted from "api-design-principles" in wshobson/agents (MIT, Copyright (c) 2024 Seth Hobson). See LICENSE.txt.
