REST API Design Best Practices

Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
Great read! I'll have all new REST API devs read this before letting them loose haha.
One change i would make though is regarding documentation. As this is a 'best practice' guide i would not suggest OpenAPI specifically as there are many ways to document API's. I think the important lesson is to just document the endpoint in a way that makes sense in the dev environment.
Nice
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

Design APIs that are:
Easy to read and work with
Hard to misuse
Complete and concise
Use nouns to represent resources, not verbs
Good: /items, /employees
Bad: /createItems, /getEmployees
Use plural nouns for collections (e.g., /orders not /order)
Use hyphens for readability (e.g., inventory-management) instead of underscores
Implement logical grouping for nested resources
/customers/{id}/ordersAvoid going deeper than collection/resource/collection
Don't mirror database structure in URLs to prevent exposing unnecessary information
Always version your APIs to prevent breaking changes
Options:
Path versioning: /v1/store, /v2/store (more common)
Query parameter: ?version=2
Implement pagination for large datasets
Use cursor based pagination (more efficient, similar to what stripe does)
Example: /items?lastItemId=1000&limit=20
Allow filtering through query parameters
/users?lastName=Smith&age=30Support field selection to limit response data
Example: /products?fields=id,name,price
Can be faster since less data needs to be fetched from the database and serialised before sending over the network
Enable sorting with clear parameters
/posts?sort=+author,-datePublishedEnsure operations are idempotent where appropriate
Multiple identical requests should result in the same state
Particularly important for DELETE, PUT operations
For sensitive operations, consider using idempotency keys. Stripe does this for charge operations.
Use status code 202 for long-running operations, says the operation is accepted but not completed
Provide status endpoint for tracking progress e.g. GET /orders/123/status
Include status endpoint URL in Location header (e.g. Location: /orders/123/status), helps clients to know where to get the status of the operation. This follows the HATEOAS principle (Hypermedia as the Engine of Application State) which states that the API should tell the client what it can do next.
Consider supporting operation cancellation e.g. DELETE /orders/123/cancel
Support partial content retrieval for large resources e.g. video files. This is useful for large files that you don't want to download all at once, think Netflix movies... They would be HUGE if you downloaded the whole thing at once.
HEAD /files/big-video.mp4
Response headers:
Accept-Ranges: bytes
Content-Length: 100000000
Content-Type: video/mp4
GET /files/big-video.mp4
Range: bytes=0-1048575 # Request first 1MB
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1048575/100000000
Content-Length: 1048576
[... first 1MB of data ...]
GET /files/big-video.mp4
Range: bytes=1048576-2097151 # Request second 1MB
Implement SSL/TLS encryption -> Use HTTPS.
Use proper authentication and authorization -> OAuth, JWT, etc.
Apply rate limiting to prevent DoS attacks
Be careful with error messages to avoid information leakage -> Best to always craft a good error message: No inner details, clear what's wrong and what to do next.
Return appropriate HTTP status codes
Provide clear error messages
Include enough information for debugging without exposing sensitive details
Use 204 for successful empty responses
Use OpenAPI (formerly Swagger) for API documentation
Document:
Endpoint structure
Request/response formats
Authentication requirements
Error codes and messages
Consider implementing HATEOAS for better API navigation
Include related resource links in responses, you can also include self links, they would describe other things you can do with the resource. If you created a post, they would include links to edit the post, delete the post, etc.
Example:
{
"orderId": "12345",
"status": "pending",
"total": 99.99,
"links": {
"self": {
"href": "/orders/12345",
"method": "GET"
},
"update": {
"href": "/orders/12345",
"method": "PUT"
},
"cancel": {
"href": "/orders/12345/cancel",
"method": "POST"
},
"payment": {
"href": "/orders/12345/payment",
"method": "POST"
},
"customer": {
"href": "/customers/789",
"method": "GET"
}
}
}
For each method, you provide the type of operation PLUS href and method for each operation.
Each thing should be self documenting. For POST with body, you can include contentType and schema, example:
"create": {
"href": "/orders",
"method": "POST",
"contentType": "application/json",
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array"
}
}
}
}