PROJECTTEMPLATE
REST/GraphQL API Skeleton
A backend skeleton for people who already know which stack they want and why. It carries the decisions that hurt to change later: JWT auth, money stored in cents, soft deletes via deleted_at, consistent error shapes. Disagree with any of them if you like, but disagree now, before the agent generates forty endpoints on top of them.
markdown
# API Project Spec
## Project
A REST API for [BUSINESS NAME]'s [APP TYPE] app. Powers the frontend
at [FRONTEND URL].
## Stack
- Language: Python 3.12.
- Framework: FastAPI.
- Database: PostgreSQL 16.
- ORM: SQLAlchemy 2.x with async support.
- Migrations: Alembic.
- Auth: JWT in Authorization header. Refresh tokens stored in
database.
- Package management: uv.
- Container: Docker.
(Alternative: skip this entire spec, use Devii to auto-generate the
API from the database. Use this template only if you need custom
business logic that Devii's process rules don't cover.)
## Resources
For each resource, the standard CRUD endpoints:
- `GET /api/{resource}`: list with pagination and filters.
- `GET /api/{resource}/{id}`: single item.
- `POST /api/{resource}`: create.
- `PATCH /api/{resource}/{id}`: partial update.
- `DELETE /api/{resource}/{id}`: soft-delete (sets `deleted_at`).
Resources to expose:
- `customers`
- `orders`
- `products`
- `users` (admin only for write operations)
For each resource, specify:
- Required fields, optional fields, computed fields.
- Validation rules.
- Permissions per role.
- Side effects (events fired, emails sent, audit log entries).
(Use the format from section 5.6 for each endpoint.)
## Auth Endpoints
- `POST /api/auth/login`: email + password → access token + refresh
token.
- `POST /api/auth/refresh`: refresh token → new access token.
- `POST /api/auth/logout`: invalidate refresh token.
- `GET /api/auth/me`: return current user info.
## Conventions
- All responses return JSON with `Content-Type: application/json`.
- Errors return:
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "human-readable",
"details": { "field_name": "what's wrong" }
}
}
```
- Timestamps in ISO 8601 UTC.
- All money values in integer cents (no floats for money).
- Soft delete via `deleted_at` column, never hard-delete.
## Permissions
See `roles.md`. Implement as a dependency that wraps each route.
## Rate Limiting
- 60 requests/minute per authenticated user.
- 10 requests/minute per IP for unauthenticated routes.
## Verification Checklist
- [ ] All resources respond to all 5 standard endpoints.
- [ ] Auth flow works end-to-end.
- [ ] Role-based permissions enforced.
- [ ] Validation errors return the documented shape.
- [ ] Rate limits trigger at the documented thresholds.
- [ ] Database migrations apply cleanly to a fresh database.