DEV Community

Mert Simsek
Mert Simsek

Posted on

Naming and Creating API Endpoints

In this article, we're going to cover some standards and recommendations to create API endpoints. I hope, it will be very helpful for you and it will be helping to change your perspective about creating API endpoints, of course in a positive way.

First of all, we need to think about everything your API should handle somethings. Initially, that would be CRUD (create, read, update, delete) operations for your resources. If we had a customer endpoint, it would be like the following obviously.

Customer

  • Create
  • Read
  • Update
  • Delete
  • List
  • Image

The customer will also need to have an image uploaded via the API. In this instance, we will allow one image for a customer and a new image overrides the previous.

API Endpoint Approach

Let's talk about some theories. There're are no right answers at this point but some approaches have some cons than others. As we are developers, we have found to be the most beautiful and point the pros and cons of each.

GET Entities

  • GET /customers - List of customers, in some logical simply, for that specific list.
  • GET /customers/x - Just entity X. X might be an ID, hash, slug, username as long as it's unique to one resource.
  • GET /customers/x,y,z - The consumer demands multiple resources.

Friendly Reminder About Auto-Increment
In the above examples, X might be an auto-incrementing ID as many developers will admit. The significant thing is that anyone with access to your API will know exactly how many entities you have. This situation can be information for people.Someone could also write a script which hits /customers/1, then /customers/2 and /customers/3, scraping all entities in this way.

You could use a unique identifier. A universally unique identifier seems like a logical thing to do. You can find some libraries about it on the internet.

DELETE Entities

If you would rather delete entities? It's the easiest.

  • DELETE /customers/x - Delete a single customer.
  • DELETE /customers/x,y,z - Delete a bunch of customers.
  • DELETE /customers/x/image - Delete the image of customer.

POST vs PUT

What about creating and updating? I know lots of people who try to pair the POST and PUT to specific CRUD action is uncertain. In general speaking, PUT is used if you know the entire URL beforehand. For example, create could be a PUT if you're creating one image for a customer.

PUT /customers/1/image HTTP/1.1
Host: mertblog.net
Content-Type: image/jpeg

It would be a proper instance of when to use a PUT because. You already know the entire URL and you are able to do it time and time again. If we have multiple images for a customer, POSTing could be a good solution.

POST /customers/1/images

It's a tricky difference, but don't try and tie an HTTP method to one CRUD action only.

Plural, Singular or Both?

You can decide to make all endpoints singular, but there is an issue with this. Confusing. I would rather create a plural for everything as it is the most obvious:

  • /customers - If I run a GET on this, I will get a collection of customers.
  • /customers/7 - Obviously, I'm just interested in customer 45.
  • /customers/7,14 - customers 7, 14 and I got it, thank you.

Another solid reason for using the plural harmonious is that it accepts for harmonious named subentities:

  • /customers
  • /customers/7
  • /customers/7
  • /customers/7/venues
  • /customers/7/venues/2
  • /venues/2

Harmonious is key.

Verb or Noun?

Most of the time, APIs consist of a series of endpoints that described actions:

POST /sendUserMessage
id=5&message=hello

As you can imagine, this is not how things are done with REST. Furthermore, developers figure out the following approach to be more RESTful because it uses a subentity:

POST /users/5/send-message
{"message":"Hello"}

But unfortunately, this is still using a verb in the URL. A verb is an action - a doing term and our API only needs one verb - the HTTP Method. All other verbs need to stay out of the URL.

A noun is a place or a thing. Entities are things and a URL becomes the address on the Internet where a thing lives.

This instance would be drastically more RESTful.

POST /users/5/messages
{"message":"Hello"}

Tremendous. We have been creating a new message that belongs to a user. The best part about keeping it nice and RESTful like this is that other HTTP actions can be made to the identical URL:

  • GET /users/mert/messages
  • PATCH /users/mert/message/xdMRqwerty
  • DELETE /users/mert/message/xdMRqwerty

This is all much easier to document and much easier to understand for both humans and software which is RESTful.

Organizing Endpoints

Controllers

We are supposed to list customers, venues, users or categories? Straightforward. One controller for each type of entity:

  • CategoriesController
  • EventsController
  • UsersController
  • VenuesController

All of those should be an entity and each entity needs a controller. Subentities might sometimes just be a method. For instance, settings are a subentity of users. They can go in UsersController. But this is optional and flexible.

Routes

At this point, you should want to avoid having multiple endpoints doing painfully similar things with copy and paste logic. Your consumers will be mad that different endpoints provide the same entities but in a slightly different format.

Methods

When you have listed all of the routes you will demand your application, go and make suitable controller methods. Make them all empty and have one of them return "Hi there!" and check the output. You just wrote an API.

Conclusion

When you have a relatively extensive list the first step is to make a basic list of actions. This is planning an entity class. I tried to bring in that thinking all verbs should stay out of the URL. Another idea is using the plural. That provides the harmonious all of the entities. I hope, I could change your perspective about building APIs.

Top comments (4)

Collapse
 
cescquintero profile image
Francisco Quintero 🇨🇴

I agree and practice these ideas/tips daily.

Something I also do is something like an actions namespace:

  • /users/:uuid/actions/deactivate
  • /users/:uuid/actions/archive

For example where these actions have their own meaning and UI handling.

Collapse
 
_mertsimsek profile image
Mert Simsek

Thanks for your reply! Your approach has some cons and pros but it might be a good solution UI handling.

Collapse
 
elcotu profile image
Daniel Coturel

Good post!

Collapse
 
_mertsimsek profile image
Mert Simsek

Thanks!