Building an API is different than building a regular HTML application. There are no HTML views to worry about, but instead you should take extra care of response statuses, response format and documentation, since your application will be used by other developers.
To generate a Rails application with only the elements necessary for an API application, use the --api
flag, e.g., rails new my_application --api
.
Use the --api
flag only if you're sure that your application will be exclusively an API. If you'll have an admin backend, or use the view layer in some capacity, the Rails API mode will not suffice, and it's best to use the standard rails new
command.
We write our APIs using the JSON format, more specifically, we use the JSON API standard. This allows those who consume our APIs to know what to expect regarding the document structure, and they can use libraries which enable them to build their clients faster and easier.
Check out this example API application that uses a combination of gems used for simplifying our APIs.
We use a few gems that make our lives easier when writing APIs.
json_api_responders simplifies the code in controllers.
Responding with a status 200
(OK) if the object is valid and with 422
(Unprocessable Entity) would usually look like this:
if resource.valid?
render json: resource, status: 200
else
render error: errors, status: 422
end
json_api_responders
's method respond_with
enables you to simplify the code:
respond_with resource
So far we've used the jsonapi-rails, which takes care of serialization/deserialization of Ruby objects into/out of JSON objects. It's done according to the JSON API standard, so you don't have to think about those details.
Another alternative is fast_jsonapi. Netflix's gem proved it can do serialization faster. You can check out the benchmark specs if you're interested.
- Testing is always important when building software, but doubly so when writing an API since we can use tests to generate documentation.
- Generates documentation from the RSpec tests in the API Blueprint format.
You can generate documentation from your controller or request specs. It's very important that you cover all the possible cases and return codes, e.g., a valid response, response when there are errors, and any other outcome of the action. Also, document pagination, enumerations, filtering parameters, sorting parameters, and anything else that may be used to refine the results of the API call.
Take special care to document crucial parts of your API, such as authentication and session management.
Generating documentation should be a part of the Continuous Integration process so that you can be sure your documentation is always up-to-date. You can use a service like Apiary to host the documentation.
APIs must be versioned from the start. That way, in case of large changes, clients can still use the older version of the API while adjusting their application to the new API specification. Otherwise, if the API is not versioned, changes to the API would break the client's applications frequently, and the client would have to take a lot of care to track the changes.
Namespace different API versions in the URL, e.g., a new version of api/v1/resource
would look like api/v2/resource
. Also, make sure that your application code, that is, your controllers, serializers, tests, and documentation, are also namespaced.
It's often possible that the API call provides a huge number of results—it could be hundreds of thousands of records. That's impractical if the client needs only a small part of the results. That's why we can limit the number of results returned with pagination, which allows the client to choose which part of the results they want to see in the request, for example, results 500-600 out of 10000.
Pagination is required for every index action, and should be described in the documentation with information on which query parameters are used, what the default and max page size is, etc.
If the JSON API standard is used, clients have to set the content-type
to application/vnd.api+json
in their request headers. In other cases, when using the JSON format, application/json
will suffice.
Some of the more commonly used HTTP status codes are:
200 OK
—request has succeeded201 Created
—new resource has been created204 No Content
—no content needs to be returned (e.g., when deleting a resource)
400 Bad Request
—request is malformed in some way (e.g., wrong formatting of JSON)401 Unauthorized
—authentication failed403 Forbidden
—user does not have permissions for the resource404 Not Found
—resource could not be found422 Unprocessable Entity
—resource hasn't be saved (e.g., validations on the resource failed)
500 Internal Server Error
—something exploded in your application
There are many more HTTP status codes. You can go here to read the whole specification.