<!-- skill: REST API | version: 1.0.0 | description: Build REST APIs with Node + Express — routes, validation, errors, versioning | category: Web -->

## Instructions
- One router file per resource (`routes/users.js`), all mounted in `index.js`. Never put everything in one file.
- Use nouns + HTTP verbs: `GET /users`, `POST /users`, `GET /users/:id`, `PUT /users/:id`, `DELETE /users/:id`. No verbs in paths.
- Validate every input at the boundary (check types, required fields) and return `400 {error: "..."}` on bad input.
- Consistent envelope: success returns the object/array directly; errors always `{error: "human message"}` with the right status (400/404/500).
- JSON bodies only, `express.json()` with a size limit. Paginate lists (`?limit=&offset=`, cap at 100).
- Version from day one: mount under `/api/v1` (or `/v1`). Log method+path+status per request.

## Examples
- Notes API: CRUD over a JSON file store with `GET /api/notes?limit=20`.
- Health + version: `GET /api/health` → `{ok:true, version:"1.2.0"}`.

## Workflows
1. Define resources + routes table on paper first (method, path, body, response).
2. Scaffold `index.js` + one router per resource + a tiny `store.js` (JSON file is fine to start).
3. Implement routes with validation; test each with `curl` before moving on.
4. Add centralized error middleware last (catches async throws).
5. Document endpoints in README (method, path, example body) as you go.

## Templates
```js
// routes/notes.js — one resource, full CRUD pattern
const express = require('express');
const router = express.Router();
let notes = [];
router.get('/', (req, res) => res.json(notes.slice(0, Math.min(+req.query.limit || 20, 100))));
router.post('/', (req, res) => {
  if (!req.body.text?.trim()) return res.status(400).json({ error: 'text required' });
  const n = { id: Date.now().toString(36), text: req.body.text, at: new Date().toISOString() };
  notes.unshift(n);
  res.json(n);
});
module.exports = router;
```

## Tools
- Test with `curl -s localhost:3000/api/notes | python3 -m json.tool`.
- SARAH `shell_run` for tests; `file_write` one router per file.

## Advanced
- Auth: Bearer JWT middleware (`Authorization` → verify → `req.user`), refresh tokens in httpOnly cookies, logout = blacklist/rotate. Never roll your own crypto.
- Abuse control: `express-rate-limit` per IP + stricter on login (5/min), `helmet` headers, CORS allowlist (never `*` with credentials).
- Validation: `zod` schemas at the boundary (`schema.parse(req.body)` in try/catch → 400 with issues).
- Pagination: cursor-based (`?after=id&limit=`) for growing feeds; offset only for admin tables.
- Docs: OpenAPI YAML maintained alongside routes (or generated via `swagger-jsdoc`), plus a `/api/openapi.json` endpoint.
- Testing: `supertest` hit every route (200 + 400 + 404 cases); `pino` structured logs with request ids.
- Troubleshooting: 413 → raise `express.json` limit deliberately; hanging requests → missing `await` or unreturned promise; CORS errors → check preflight (OPTIONS) handling.

## Documentation
- Express routing: https://expressjs.com/en/guide/routing.html
- REST conventions: https://restfulapi.net
