DEV Community

Cover image for REST API Design Rules
Ezekiel
Ezekiel

Posted on • Edited on

REST API Design Rules

Why is it important to write clean REST-API Designs

In today's interconnected world, well-designed REST APIs are the backbone of efficient and scalable applications.

Writing clean REST API designs is crucial for several reasons:

  • Enhanced Usability: A well-designed API is intuitive and easy to use, making it accessible to developers of all skill levels. This simplifies integration and reduces the learning curve.

  • Improved Maintainability: Clean code promotes maintainability by making it easier to identify and fix bugs, add features, and scale the API. This ensures long-term stability and reduces development costs.

  • Increased Security: A well-structured API with proper authentication and authorization mechanisms helps prevent unauthorized access, data breaches, and other security vulnerabilities.

  • Enhanced Performance: A clean design optimizes performance by using efficient data structures, avoiding unnecessary calls, and minimizing latency. This provides a seamless user experience and improves overall application performance.

  • Reduced Development Time: Well-defined API specifications and clear documentation enable faster development by eliminating guesswork and reducing the need for extensive testing. This saves valuable development time and resources.

  • Improved Scalability: A clean design allows for easy scalability by providing a modular architecture that can be easily expanded to handle increased traffic or new features. This ensures the API can grow with the application's needs.

  • Increased Reusability: A well-designed API can be reused across multiple applications, reducing duplication and promoting consistency. This simplifies development and saves time and effort.

  • Improved Documentation: Clean designs are easier to document, making it clear to developers how the API works and how to use it effectively. This reduces confusion and improves adoption.

URI Rules

The structure of a url is as follows

scheme :// authority / path [?query][#fragment]

for instance

https://soccer.api.org/teams/dortmund/players?name=Rona#2

There are two types of resources

  1. Collection resources: contains a collection of resources. It can be likened to a database relation

  2. Singleton resources: contains a single resource. It can be likened to a database record.


When designing Rest-Api's

1 Collection resources should be plural

+ soccer.api.org/teams/dortmund
- soccer.api.org/team/dortmund
Enter fullscreen mode Exit fullscreen mode

2 Singleton resources should be singular and can be replaced by the unique id representing the resource in the database system behind the api

+soccer.api.org/teams/dortmund/players/58c1aaae-205a-11ef-aeea-a64c74618950
Enter fullscreen mode Exit fullscreen mode

3 No trailing forward slashes in your URI's

+soccer.api.org/teams/dortmund/players
-soccer.api.org/teams/dortmund/players/
Enter fullscreen mode Exit fullscreen mode

4 Use hyphens instead of underscores to improve readability of API's

+ api.blog.com/blogs/this-is-my-blog
- api.blog.com/blogs/this_is_my_blog
Enter fullscreen mode Exit fullscreen mode

5 Lowercase letters are prefered to Uppercase letters in URI paths

+ api.example.com/my-api/my-resource
- api.example.com/My-Api/My-Resource
Enter fullscreen mode Exit fullscreen mode

6 No file extensions in URI's

+ api.example.com/api/resource
- api.example.com/api/resource.json
Enter fullscreen mode Exit fullscreen mode

7 CRUD function names should not be used in URI's

+ DELETE api.example.com/api/resource
- GET api.example.com/api.resource/delete
Enter fullscreen mode Exit fullscreen mode

8 The query component of the URI's can only be used in collection resources

+ GET /users?role=admin
Enter fullscreen mode Exit fullscreen mode

9 The query component of a URI should be used to paginate collection results

+ GET /users?pageSize=25&pageStartIndex=50
Enter fullscreen mode Exit fullscreen mode

HTTP Method Rules

HTTP METHOD Uses
POST To create a new resource. similar to create
GET To get the representation of a resource. similar to read
PUT To update a resource by replacing the whole resource
DELETE To delete a resource
PATCH To update a resource by changing the part of the resource that is required without replacing the entire resource.
HEAD To get only the response head not the body
OPTIONS To get all available options for a particular resource

PUT can be used for both creating and updating a resource. However, following best practices, it's generally recommended to use POST for creating new resources and PUT for fully replacing existing ones.


Versioning

Versioning an api can be important for:

Maintaining backward compatibility: Versioning allows you to introduce new features without breaking existing integrations that rely on older API versions. Users can continue using the familiar endpoints while those seeking new features can adopt the versioned API.

Ensuring a consistent and well-designed API: Consistent naming conventions across versions contribute to a user-friendly experience. Changing endpoints disrupts this experience, and versioning helps avoid it.


Conclusion

Now that you're armed with these REST API design rules, it's time to put them into action! Share your API creations in the comments below, and let's build a world of well-designed and developer-friendly APIs together.

Top comments (23)

Collapse
 
adaptive-shield-matrix profile image
Adaptive Shield Matrix

Don't write REST-Apis.
Just write regular APIs with GET and POST.
The REST standard is outdated and a historical fossil.
No one can remember if you PUT, PATCH or POST changes.

REST suffers heavily if you want to design your business process: how do you start/initiate a process. Is it PUT, PATCH or POST, is it a separate Resource (or an virtual resource that does not exist as separate entity in your db to satisfy REST guidelines?) or an update to an existing one? -> There are no right answers and trying to fit your business process into a REST-API feels like trying to trying fit a sphere into a square hole -> it just doesn't fit.

Just write good docs using swagger.io/tools/swagger-ui/ or other/similar tools.
Good docs are 100x more important than adhering to an easily misunderstood, wrongly interpreted, outdated standard that no-one uses in the real world (or implements it wrongly).

Use

  • GET - for reads, allows leveraging browser build-in caching
  • POST - for writes, modifications and deletion
Collapse
 
dko1905 profile image
Daniel

Write REST-APIs
Using a custom, in-house API-convention makes APIs unnecessarily complex and knowing if POST is used for creating, updating or deleting items could depend on the API. This uncertainty will slow down developers and make APIs harder to understand.

Don't write REST-Apis.
Just write regular APIs with GET and POST.
The REST standard is outdated and a historical fossil.

The HTTP-standard, TCP-standard and even the x86 CPU-architecture are all old standards. That doesn't mean, that they are obsolete. I would even go so far to say, that older standards have proven their resilience and practicality by still being around today.

No one can remember if you PUT, PATCH or POST changes.

I think of REST-methods as being aligned with the CRUD-model. Each CRUD-operation directly corresponds to one HTTP-method.

CRUD HTTP
Create POST
Read GET
Update PUT
Delete DELETE

Additional HTTP-methods, like PATCH, exist to allow partial updates and other complex mutations, and remembering how to use these 5 standard HTTP-methods in REST-APIs is not very hard.

Good docs are 100x more important than adhering to an easily misunderstood, wrongly interpreted, outdated standard that no-one uses in the real world (or implements it wrongly).

Good docs are always good but many developers make assumptions before reading the documentation (if they read it). Assumptions like POST-operations won't accidentally delete data. The assumptions are not that the API strictly follows the REST-standard but that it is REST-like. These REST-like APIs can be found everywhere in the real world. Just take a look at the API-calls by dev.to.

Collapse
 
bukajsytlos profile image
bukajsytlos

first of all, these "REST" guidelines are not RESTful. they are HTTP API guidelines

Collapse
 
micha_maj_1cbf21bc8a63e1 profile image
MichaΕ‚ Maj

When I think about RESTful APIs, I compare them to OOP. It is common practice to combine OOP with functional programming, which is why what you are saying reminds me of combining REST with a SOAP approach. But you still need to know their rules.

Collapse
 
schmoris profile image
Boris

Is there any disadvantage of using singular for endpoints that return a single entity guaranteed and plural for collection endpoints, e.g.:

/api/v1/users/name/:name but also /api/v1/user/ident/:ident

I guess consistency is key, but maybe there's something I don't see yet :-)

Collapse
 
ezekiel_77 profile image
Ezekiel

Hey there! Thanks for the comment, that's a tricky one! You're right, consistency is king in the API world, but there's always room for debate

Here's the thing: some folks like plural nouns for collections /users because it's super clear they hold a bunch of stuff. Plus, it kinda aligns with how developers expect things to work (think lists and arrays).

On the flip side, singular nouns for single things /user can be shorter and feel more specific, especially for resource names that are already longwinded. But the downside is it might be a little confusing at first for developers expecting a whole bunch of stuff back.

Honestly, there's no one-size-fits-all answer. The best bet is probably to stick with plural for collections /users and singular for single things /user just to keep things clear and consistent across your entire API. That way, developers won't have to scratch their heads wondering what's what.

Of course, if you have a really good reason to go against the grain (like super short resource names), just make sure everything is consistent! And hey, document your approach clearly in your API docs to avoid any future head-scratching.

Thanks again for bringing this up, it's definitely a point to consider when designing your API!

Collapse
 
syeo66 profile image
Red Ochsenbein (he/him) • Edited

I think it might start to get hard if you have to decide what the plural of 'person' is. Is it 'persons' or 'people'?

Collapse
 
ezekiel_77 profile image
Ezekiel

πŸ˜‚

Well in most systems its usually users not persons or people

Thread Thread
 
syeo66 profile image
Red Ochsenbein (he/him)

Not every person is a user.

Collapse
 
shyam_10 profile image
Shyam raj

I think you forget about versioning. Versioning is so much important in api design with backward compatibility , because if we want to add a new feature to the api, the end points should not change (consistent naming represents a well designed api). If the endpoints changes it will affect user experience. So by adding versioning(with new feature) the users who dont need the new features can still use the old api end point, and also those who needs new features can use the versioned api

Collapse
 
ezekiel_77 profile image
Ezekiel

Thanks for your insightful comment! You're absolutely right, versioning is a crucial aspect of REST API design, and I apologize for not including it in the initial post.

Collapse
 
peteraba profile image
Peter Aba

There are more "complete" guidelines out there which take care of a lot of edge cases. For example the Zalando API Guideline. I'd usually start with something like this and define my own rules on top of it for anything that might be used out in the wild.

Collapse
 
algorodev profile image
Alex Gonzalez

Great article! I just recommend you to finish your articles with a conclusion.

Collapse
 
ezekiel_77 profile image
Ezekiel

⭐ That's a fantastic suggestion! I'll definitely craft a conclusion to solidify the key takeaways

Collapse
 
honza_moravec_16974f10c32 profile image
Honza Moravec

yeah you did it πŸ¦ΎπŸ€–

Collapse
 
suyash_patil profile image
Suyash Patil • Edited

Great explanation, and I got to know where am I lacking to make a perfect rest API. Still I'm a beginner in the world of API's but this helps a lot.

Collapse
 
thienvu2103 profile image
Le Dinh Thien Vu

Hi folks, I have a minor question.
For example. I have a collection Groups, and 1 user can join/leave the a group. so what should an API be?
Is it PATCH? localhost:8080/v1/groups/join and localhost:8080/v1/groups/leave ?
or just a localhost:8080/v1/groups and the query param will be a flag to determine join or leave?

Collapse
 
ezekiel_77 profile image
Ezekiel

There is also another type of resource called Controller Resources which is used to perform actions that cannot be logically mapped to any of the http methods

So for the localhost:8080/v1/groups/<groupid>/leave will be a POST as well as the join endpoint

Collapse
 
aneroid profile image
Anirudh Dutt • Edited

If the user is triggering the join or leave action, then it should be a PUT request: PUT /v1/groups/{groupId}/join

PUT is safe to repeat without further side-effects (aka idempotent). A user joining a group they have already joined doesn't "extra-join" them.

Similarly, leaving the group would be: PUT /v1/groups/{groupId}/leave

Collapse
 
arnoldschan profile image
Arnold Samuel Chan

Great article!
I personally use django restframework, and CRUD endpoints are ready out of the box. Anyone know is there any alternative library for javascript? Express feels like Python's flask, and everything feels manual.

Collapse
 
ezekiel_77 profile image
Ezekiel • Edited
Collapse
 
sirthaven profile image
Jakub Serafin

I don't like this kind of articles. it has bunch of advices, but without supporting them with any explanation why. Without this those are not best practices, but just bunch of magic rituals and spells.

Collapse
 
mrsharpp profile image
Amir Alam • Edited

exactly, just blindly following the rules without any understanding

Some comments may only be visible to logged-in visitors. Sign in to view all comments.