We use Rest APIs for exposing application interfaces through a web service.
Let's look at few Rest API Guidelines :
1. Logical Resources
3. Plural Endpoint name
4. Dealing with relations
5. Beyond CRUD
6. Value Objects /Entity
7. Resource Names
8. Documentation
9. GET – Only for Read
10. Use SSL
11. Path Params & Query Params
12. Aliases for common Queries
13. Updates & creation should return a resource representation
14. Use JSON format
15. Field Names
16. Rate Limiting
17. Pretty & gzip
18. Caching
19. Friendly URLs
20. Errors
21. Verbose Messages
22. Limiting Fields
23. Pagination
24. HTTP status codes.
25. Role base access & Security
26. Versioning
Let's look at few Rest API Guidelines :
1. Logical Resources
The key principles of REST involve separating your API into logical resources. These resources are manipulated using HTTP requests where the method (GET, POST) has specific meaning.
API should define accessing resource using a Noun and not verb. That makes it only 2 URLs per resource.
E.g.
GET /tickets - Retrieves a list of tickets
GET /tickets/12 - Retrieves a specific ticket.
2. Use appropriate HTTP methods
Map Appropriate method to service based on its operation type.
For example
Create(C) - POST
Read (R) - GET
Update (U) - PUT for complete update and PATCH for Partial Update
Delete(D) - DELETE for deleting
3. Plural Endpoint name
Endpoint need to be defined as plural and not singular.
So you would have:
GET /tickets to retrieve a list of tickets and not GET /ticket.
This also enables to have both /tickets and /tickets/{ticket_ID} under single controller.
4. Dealing with relations
Use URLS to depict the relations between resources
For example:
GET /tickets/12/messages - Retrieves list of messages for ticket #12
GET /tickets/12/messages/5 - Retrieves message #5 for ticket #12
5. Beyond CRUD
There could be Use cases where action does not fit into crud operation. In such cases, use action=<specific_action> as a query parameter.
6. Value Objects /Entity
Do not define entity for a given purpose or service rather use relevant portion of entity E.g. ClientVO, SaveClientVO etc.
7. Resource Names
The logical resources name should be with respect to the consumer of the API and not our business model (E.g. not Segment but Policy or Certificate).
8. Documentation
An API is only as good as its documentation. Have descriptive documentation.
9. GET – Only for Read
Never ever have an update in GET Method! GET should be used only for read APIs.
10. Use SSL
Always use SSL and do not redirect non-SSLs to SSL urls instead throw the exception.
11. Path Params & Query Params
Use Path Params to identify a specific resource or resources.
Example:
GET /cars
GET /cars/{id}
POST /cars
GET /cars/{id}
POST /cars
While use Query Parameters to sort/filter/search.
GET /tickets?sort=-priority
GET /tickets?state=closed&sort=-updated_at
12. Aliases for common Queries
If possible, consider building set of conditions into meaningful RESTful paths. For example,
To Query recently closed tickets, we would generally have :
GET /tickets?state=closed&sort=-updated_at
We can enhance the API experience by having following for this :
GET /tickets/recently_closed
13. Updates & creation should return a resource representation
To prevent an API consumer from having to hit the API again for an updated representation, have the API return the updated (or created) representation as part of the response.
14. Use JSON format
Stick with JSON as much as possible unless specific client requirement is for XML format.
15. Field Names
Use camel case for field names.
16. Rate Limiting
To prevent abuse, it is standard practice to add some sort of rate limiting to an API.
Following headers need to be included:
· X-Rate-Limit-Limit - The number of allowed requests in the current period
· X-Rate-Limit-Remaining - The number of remaining requests in the current period
· X-Rate-Limit-Reset - The number of seconds left in the current period
17. Pretty & gzip
Make sure API response is pretty print by default and gzip is supported.
18. Caching
HTTP provides a built-in caching framework. There are two approaches :
ETag: When generating a response, include a HTTP header ETag containing a hash or checksum of the representation. This value should change whenever the output representation changes. Now, if an inbound HTTP requests contains a If-None-Match header with a matching ETag value, the API should return a 304 Not Modified status code instead of the output representation of the resource.
Last-Modified: This basically works like to ETag, except that it uses timestamps. The response header Last-Modified contains a timestamp in RFC 1123 format which is validated against If-Modified-Since.
19. Friendly URLs
URL should be friendly to the developer and be explorable via a browser address bar
20. Errors
The API should return 400 series HTTP status codes for client issues & 500 series HTTP status code for server issues.
21. Verbose Messages
Messages returned in the payload should be as verbose as possible.
22. Limiting Fields
Use a fields query parameter that takes a comma separated list of fields to include. For example, the following request would retrieve just enough information to display a sorted listing of open tickets:
GET /tickets?fields=id,subject,customer_name,updated_at&state=open&sort=-updated_at
23. Pagination
Limit the number of records returned in the response. Consumer can use offset, limit params to get specific data. It is a good practice to always return some metadata with each paginated response ( for example, total records size).
24. HTTP status codes.
The API should always return sensible HTTP status codes. Listed below are commonly used codes :
· 200 OK - Response to a successful GET. Can also be used for a POST that doesn't result in a creation.
· 201 Created - Response to a POST that results in a creation. Should be combined with a Location header pointing to the location of the new resource
· 204 No Content - Response to a successful request that won't be returning a body (like a DELETE request)
· 304 Not Modified - Used when HTTP caching headers are in play
· 400 Bad Request - The request is malformed, such as if the body does not parse
· 401 Unauthorized - When no or invalid authentication details are provided. Also useful to trigger an auth popup if the API is used from a browser
· 403 Forbidden - When authentication succeeded but authenticated user doesn't have access to the resource
· 404 Not Found - When a non-existent resource is requested ·
· 405 Method Not Allowed - When an HTTP method is being requested that isn't allowed for the authenticated user ·
· 410 Gone - Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions
· 415 Unsupported Media Type - If incorrect content type was provided as part of the request
· 422 Unprocessable Entity - Used for validation errors
· 429 Too Many Requests - When a request is rejected due to rate limiting
25. Role base access & Security
API should always have an authorization in place to check for role based access to data( based on its sensitivity & confidentiality).
For example,
Let’s say we have an API GET /student/{student_id}
Now , GET /student/12
should be only accessible to a user who belongs to Group/Role that can access the student_id =12( for example, student with student_id=12, administrators etc) and will not be accessible to student with student_id=13 or other users who do not belong to Group/Role.
This could be also applicable to POST requests where authorization check must be carried out ( in addition to default authentication check for POST) to make sure user has appropriate access to make the changes.
26. Versioning
API should always be versioned (not an optional thing). This makes it easy to deal with multiple clients requiring different/customized versions of same API.
There are four ways to version your API; URI versioning, Request Parameter versioning, Custom header versioning & Media Type versioning.
Describe each way of versioning Rest Services: <Coming soon a special blog on this>
27. API Hierarchy
Consolidate all API under one domain and then build a hierarchy which should be self-explanatory to Consumer of the API.