API Best Practices

So you’re writing a Rails API?

Time to consider best practices for writing an API.

Naming Conventions

When structuring your endpoints, ensure you are using plural nouns instead of singular ones or verbs. Eg — /cars/711 instead of /car/711 even though it is just returning one car.

And don’t use /getAllCars.

Be consistent.

Documentation

Documentation for an API is critical for those implementing your API. There’s a number of services that can assist in helping with documentation for a RESTful API, like Swagger. Benefits of Swagger include:

  • Documentation is clear and can be read by developers and layman alike. With a friendly UI, your end users can visualize and have input on the API if it’s still being developed.
  • Additionally, the documentation is machine readable. So the same code generated in the Swagger docs can be used in your processes.

Here’s some example of Swagger output from setlist.fm’s API documentation. Notice that the example below also utilizes versioning (v 1.0). More on that below.

Test, test, test

Make sure to test all routes and all exceptions. You’ve put in the artist name and it returns a 200 status. But what if the end user doesn’t put in the required param. Did you test for that? Test for everything.

Here are some tips on writing specs: http://www.betterspecs.org/

For a Rails app, consider using a gem such as SimpleCov to help ensure your API is fully tested.

Handle exceptions well

So you query for an id that doesn’t exist and you get a nice 500 line error response back. Is that helpful for your end user?

Consider condensing that down to a few lines of code that will actually be helpful:

rescue_from ActiveRecord::RecordNotFound do |exception|
json_response({ message: exception.message }, :not_found)
end

Success messages

In addition to have succinct and meaningful messages for exceptions, let’s also make sure success messages are meaningful. Instead of just a 201 success status being returned from a put request, we can do this:

def update
if @album.update!(album_params)
render status: 200, json: {
message: "Your album has been updated successfully."
}
end
end

Authentication and Authorization

You need authentication to prevent potentially malicious or unintentionally harmful put or post requests from hitting your database. You may also want to restrict some end points for certain users — like an admin. HTTP authentication comes in different flavors — token, basic, and digest.

I have familiarity with the jwt gem. You can check out this tutorial which I found helpful to implement in your API project: https://www.sitepoint.com/introduction-to-using-jwt-in-rails/

Serialization

For the uninitiated, serialization is the process of translating data structures (like objects) into a format that can be stored or transmitted and reconstructed later. This is great for different computing environments as the bits can be reread as basically a clone of the original data through deserialization.

The gem ‘activemodelserializers’ can be used to do just that.

Versioning

If you are updating your API for improvements with breaking changes and your customer base is already using an older version of the API, versioning is going to be your go-to for preventing angry customers.

No gem necessary. Just make sure you note the files and namespace in the config/routes.rb file correctly. I found this article to be as good as any on versioning in a Rails API: https://chriskottom.com/blog/2017/04/versioning-a-rails-api/

Rate Limiting

To prevent abuse of the API, rate limiting can be incorporated in order to throttle usage in a time period.

Rack Attack and Rack Throttle are two gems that you can use for this job.

Show your support

Clapping shows how much you appreciated Jennifer Kinsey’s story.