Guides / Prompting and shipping
How to Build a REST API: Design, Security and Deployment
Build a REST API step by step: resources and routes, HTTP methods and status codes, validation, authentication, pagination, rate limits, docs and deployment.
Mythex Team · · 5 min read
To build a REST API, list the resources your app manages (users, orders, bookings), give each a URL such as /orders and /orders/{id}, and use HTTP methods for actions: GET to read, POST to create, PATCH to update, DELETE to remove. Return JSON with meaningful status codes, validate every input, require authentication and per-record permission checks on the server, and paginate lists. Then document the endpoints and deploy the API behind HTTPS.
This guide covers the design decisions, a worked set of routes, prompts for an AI app builder, and the mistakes that cause security holes. If APIs are new to you, start with what an API is.
When you need a REST API
- Your web frontend needs to save and load data from a server
- A mobile app, partner or automation tool needs access to your data
- Other services send you events (webhooks)
- You're splitting work between a frontend and a backend team
REST is the most common style, but not the only one. REST vs GraphQL explains when a single flexible query endpoint fits better.
Design first: resources and routes
Write down the nouns in your app and what people do with them. For a simple booking app:
| Method | Route | What it does | Success code |
|---|---|---|---|
GET | /api/bookings | List the caller's bookings (paginated) | 200 |
POST | /api/bookings | Create a booking | 201 |
GET | /api/bookings/{id} | Get one booking | 200 |
PATCH | /api/bookings/{id} | Change some fields | 200 |
DELETE | /api/bookings/{id} | Cancel a booking | 204 |
GET | /api/health | Health check for monitoring | 200 |
These map onto create, read, update and delete; see what CRUD is. Conventions worth following:
- Plural nouns, no verbs in URLs:
/bookings, not/getBookings. - Nest only one level when it clarifies ownership:
/bookings/{id}/notes. - Actions that aren't CRUD can be sub-resources:
POST /bookings/{id}/cancelis clearer than a magic PATCH. - Consistent naming for fields, such as
created_ateverywhere.
Status codes and errors
Use standard HTTP codes so clients know what happened without parsing text:
| Code | Meaning | Use when |
|---|---|---|
| 200 | OK | Successful read or update |
| 201 | Created | A POST created something |
| 204 | No Content | Success with nothing to return |
| 400 | Bad Request | Input failed validation |
| 401 | Unauthorized | Not logged in or bad token |
| 403 | Forbidden | Logged in but not allowed |
| 404 | Not Found | Doesn't exist, or the caller mustn't know it exists |
| 409 | Conflict | Duplicate, or the slot is already booked |
| 429 | Too Many Requests | Rate limit hit |
| 500 | Server Error | Something broke on your side |
Return errors in one consistent JSON shape, for example {"error": {"code": "slot_taken", "message": "That time is no longer available."}}, and never include stack traces or database errors in responses.
Options and trade-offs
| Decision | Simple choice | Alternative |
|---|---|---|
| Where the API lives | API routes in your web framework | A separate API service, useful for several clients or a different language |
| Authentication | Session cookies for your own web app | Tokens (bearer tokens or API keys) for mobile apps and third parties |
| Pagination | ?page=2&limit=20 | Cursor-based (?after=...), steadier for large, changing lists |
| Versioning | None until you have outside users | /v1/ in the path once others depend on it |
| Docs | A README listing routes | An OpenAPI spec, which tools can turn into interactive docs and client code |
Step by step
- List resources and routes as above, including who may call each.
- Model the data in your database with the fields and relationships you need.
- Build read routes first, then create, update and delete.
- Validate input on every write with a schema library: required fields, types, lengths, allowed values. Reject unknown fields.
- Add authentication, then authorisation per record: loading
/bookings/42must check that booking 42 belongs to the caller, not just that someone is logged in. - Paginate every list and cap the page size.
- Rate-limit login and expensive routes. See rate limiting.
- Configure CORS only if browsers on other domains must call the API, and list those origins explicitly. How to fix CORS errors explains the errors you'll see.
- Write docs and tests for each route, including the failure cases.
- Deploy with secrets in environment variables, HTTPS, logs and a health check.
Prompts to give your AI builder
Scaffold:
Create a REST API for bookings with these routes: GET /api/health, GET /api/bookings (paginated, max 50 per page), POST /api/bookings, GET /api/bookings/:id, PATCH /api/bookings/:id, DELETE /api/bookings/:id. Store data in our database. Validate request bodies with a schema library and reject unknown fields. Return JSON errors as {"error": {"code", "message"}} with correct status codes (400, 401, 403, 404, 409). Keep secrets in environment variables.
Security:
Require login on every bookings route. On every read, update and delete, check on the server that the booking belongs to the current user; return 404 if it doesn't. Never accept user IDs or roles from the request body. Rate-limit POST /api/bookings to 20 per minute per user. Log errors on the server without returning stack traces.
Docs:
Write an OpenAPI description of these routes, and a short README with example requests and responses for each.
Testing your API
Test from outside the frontend, because attackers will:
- Each route works with valid input and returns the documented shape and code
- Missing or invalid fields return 400 with a clear message
- No token returns 401 on every protected route
- User A requesting user B's record by ID gets 404 or 403
- Lists are paginated; a huge
limitis capped - Duplicate or conflicting creates return 409, not 500
- Rate limits return 429
- Error responses contain no stack traces, SQL or secrets
- CORS allows only the origins you intend
Common mistakes
- Checking login but not ownership. The most common API hole: any logged-in user can read any record by changing the ID.
- Trusting the client. Prices, roles and user IDs from the request body can be edited.
- Returning whole database rows. Password hashes and internal fields leak. Choose what each response includes.
- Unbounded lists. One request for every record can slow the whole app.
200 OKwith an error message inside. Clients and monitoring can't tell it failed.- CORS set to allow everything on an API that uses cookies.
- No health check or logs, so you find out about outages from users.
For a broader pre-launch pass, see the security checklist for AI-built apps.
Building a REST API in Mythex
You can ask Mythex for an API as part of your app or as its own service. The docs recipe REST API backend has a starter prompt: name your framework and routes, ask for clear JSON errors, keep secrets in environment variables, and include a Dockerfile. Container backends in Node, Python, C#, Java and others publish through a Dockerfile, and Mythex handles the deploy from Publish (API backends). A project can run a website and an API server side by side, and you can switch between them in the preview. Store keys as project secrets, and if the API needs a database, ask for one in chat. For scheduled work around your API, see how to run background jobs.
Questions
What is a REST API?
A REST API is a way for programs to work with your app's data over HTTP. Each kind of data is a resource with its own URL, such as /orders, and standard methods act on it: GET to read, POST to create, PATCH or PUT to update, and DELETE to remove. Data is usually sent as JSON.
Which language should I build a REST API in?
Use what you or your team can maintain. Node.js with Express or Fastify, Python with FastAPI, and C# or Java frameworks all work well. The design rules for routes, status codes, validation and authentication matter more than the language.
How do I secure a REST API?
Require authentication on every non-public route, check on the server that the caller may access each specific record, validate all input, use HTTPS, rate-limit requests, and keep secrets in environment variables. Never trust IDs or roles sent by the client.
Do I need a separate backend for a REST API?
Not always. Frameworks like Next.js can serve API routes alongside pages. A separate API service makes sense when several clients (web, mobile, partners) use it, or when it needs its own language or scaling.