A RESTful API design should be:
- Consistent
- Follows web and HTTP Standards
- Intuitive
- Well documented
As REST APIs become more common in many different backed systems. the importance of a clean REST API design standard is needed. The concept of REST is to separate the API structure into logical resources. REST APIs should adhere to consistent guidelines to make using them easy and intuitive. This document serves as a starting point to aide in consistent RESTful API design.
- Version your API in URL (e.g. /v1/) Preferably use URL method for versioning. It gives better discoverability of a resource by looking at the URL. Always update the API verion when there are breaking changes. Breaking changes include
- removing any part of the API
- a change in the response type (e.g integer to float)
- a change in the format of a response data for any call
- If possible use a subdomain for a shorter concise URL.
- GET api.example.com/v1/exmployees vs GET www.example.com/api/v1/employees
- Ensure CORS is enabled for public access
- Use root as a health-check endpoint. GET /v1 should return a response something similar to {"status": "running", "version": "abcxyz"}
- All request should be made over HTTPS (SSL) as a basic security implementation.
- Use nouns for resource naming
- Do not use file extensions in the URI
- BAD: GET /v1/employees.json
- GOOD: GET /v1/employees
- Resource names should always be plural
GET /v1/companies GET /v1/employees
- Keep using the plural name even for detail endpoints
GET /v1/employees/1
- Sometimes a relation may exist under another resource (sub-resource).
- Use the detail pattern for the parent resource followed by the child resource
GET /v1/employees/1/departments/ GET /v1/employees/1/departments/4
- Do not include trailing foward slashes in the URI. Adds no semantic value and may cause confusion
- Map your exceptions in an error payload. Each error payload should include a message/reason for the error. If applicable an error code, description and/or link to more information. Errors should include all information the client needs to move forward from the error.
- Use HTTP headers for Content Negotiation (serialization formats)
- Content-Type defines the request format. (Content-Type: application/json)
- Accept defines a list of acceptable response formats.
- Default Content-Type should be json. If json is the default the field names should be snake case.
- Allow HTTP Method Overrides. Some proxies do not support arbitrary HTTP methods or newer HTTP methods.
- Provide filtering, sorting, field selection and paging for collections
- For pagination use Link Header protocol. Combine this with a "X-Total-Count" header to indicate the total number of items returned.
- Limit which fields are returned by the API
GET /v1/employees?fields=id,first_name,last_name
- Use nouns for resource names
- Use UUID if possible instead of resource ids.
- Keeps business logic away from the consumer of the API
- It can be a security issue, this way is a preventive practice to aid in managing risks in case of developer mistakes
- Use standard (verb) HTTP methods for actions (GET, POST, PUT, DELETE etc)
- Use standard HTTP status codes
- 2xx (Success category)
- 3xx (Redirection Category)
- 4xx (Client Error Category)
- 5xx (Server Error Category)
- Sorting, filtering, searching and pagination should be done via the query params and the GET method
- Have aliases for common queries e.g GET /employees/new_hires
- Use hyphens instead of underscores where necessary in the URI. Never use camel case because of case sensitivity.
- Always use lowercase letters for URI paths
- Update (e.g PUT, PATCH) and create (e.g POST) should return the representation of the new resource
- This prevents (if necessary) the API consumer to hit the API again for the updated resource
- POST /v1/employees for creating a new employee should return a 201 response with
- a representation of the new employee created
- A Location header which points to the new URL of the resource
- For actions that don't require any response object like DELETE, return the appropriate code with an null response
- For DELETE /v1/employees/1 return 204 with response { data: null }
- If Rate Limiting is necessary, use HTTP code 429 for rate limiting exceeded
- Return the headers X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (although non standard they seem to be a widely used combination)
- Response should include details explaining the condition of the rate-limit
- Optional to include a Retry-After header within the 429 response
- Don't use unix timestamp for X-Rate-Limit-Reset, use number of seconds
- Use HATEOS (Hypermedia as the Engine of Application State) for better navigation through the API and this prevents the client from having to construct URIs.
- Be mindful about Idempotence. Safe methods like GET, HEAD, OPTIONS should return the same result every time and should only be used for retrieving data and not changing any data. Use the appropriate actions e.g DELETE, PUT for such.
- Keep Authorization and Authentication stateless. Don't use sessions to store authentication information for the API, each request should be self-sufficient.
- Gzip and/or deflate should be supported. This should be expressed in the Content-Encoding header.
- Envelope your data e.g { data: [{ ... }, { ... }]} This allows for relialby testing for response data, e.g if response['data'] does not exist, then check response['error'] to figure out why. This reduces the need of having to parse returned data to figure out if its an error or not consistently.
- When necessary include a form of caching. By either using Etag or Last-Modified
- Last-Modified takes a timestamp in any of the 3 specifications
- Frequently Asked Question 1
Response to frequently asked question 1
- Frequently Asked Question 2
Response to frequently asked question 2
- Frequently Asked Question 3
Response to frequently asked question 3
The REST API Design Guideline specification is authored by Ashton Paul
If you'd like to leave feedback, please open an issue on Github