Best practices in designing RESTful API

REST is a philosophy not a standard, so following certain best practices will help you get right and identify usage issues upfront. Though the practices are exhaustive I will try to cover the most important ones.

Use HTTP verbs
Never build your API with just POST. Technically it does the job but clearly violates REST philosophy. Each HTTP verb has a meaning and usage semantics.

GET – Fetch information. This should not change the state of the system.
POST – Create content.
PUT – Update content.
DELETE – Delete
and more.

Always think as resources
RESTful API provides access to your system. Your system is a collection of resources. Thinking in terms of resources simplifies the signature of endpoints and makes usage more intuitive.

GET /users/info?id=
POST /posts/create
DEL /posts/delete?id=

GET /users/:id - Fetches user profile
POST /posts - Creates a new post
PUT /posts/:id - Updates a specific post
DEL /posts/:id - Deletes an existing post

Sub resources can be accessed as
GET /posts/:id/comments - Fetches comments for the specified post.
The usage of correct HTTP verbs convey the usage of endpoint. This mostly eliminates actions to be part of the endpoint and the API feels intuitive.
It makes more sense to use plural names for resources.
Once an endpoint is finished, put yourself in the developer’s shoes and read it yourself. It should feel right and natural. A peer-to-peer review of API signature is highly recommended because once your API signature is published you cannot make any further changes.
Use versioning, but don’t overuse
Versioning helps in faster API iterations and support of legacy APIs.
Don’t overuse versioning. Increment versioning only when your API is breaking an existing contract and not when new APIs are being added. It is a good practice to increment versioning when the complete set of APIs are updated.
Older API versions are supposed to be deprecated as soon as possible. Never put your clients in a situation where they should use multiple API versions.
If you end up changing your versions within 6 months then there is something fundamentally flawed with your API strategy.

Always, always, always use SSL and sleep peacefully. Do not add SSL support just the day before shipping to production. Start with SSL and test it all through the development phase.

JSON please!
JSON is the preferred data exchange format. It is readable, simple to parse and easy to convert to data models.

Explicitly support and expect Content-Type header be set to application/json

Prefer JSON for input rather than URL encoded parameters.
JSON request body helps to express more complex requests. For example the following example makes it easy in JSON input rather than in URL encoding. Also JSON parsing on Server side is straight forward.
POST /posts
“title”: “10 best food outlets in Singapore”,
“content”: “…”,
“tags”: [“food”, “life”, “singapore”]

When your API server returns a response (success/error) it is received, parsed and consumed by your clients. So design your response structures thinking in terms of clients and making it easy for them to consume.

Response is always a binary outcome. Either success or error, there is no middle ground. Period.
Define a success and error JSON structure upfront and stick to it.
All API responses should fit in either of these two structures. This will help clients to write a well defined parser.
An example success response

“ok”: true,
“result”: {…}
An example error response

“ok”: false,
“error”: {…}
Here ok is the decision branch between success and error response parsing (along with the correct HTTP status code).

simple structure
Define a simple structure by reducing hierarchy at root level. This will simplify parsing.
This structure is parsed by a top level response parsers and the contents of either result/error are delegated down the line. The top level parsers are not concerned about the contents inside the response.
Tell me more about errors
An error should tell more about itself. Don’t be cryptic.

Bad error response

“ok”: false,
“error”: {
“code”: 1809,
“message”: “Invalid API request”
Your error response should not frustrate your developer. Instead it should help identify the problem.

Good error response

“ok”: false,
“error”: {
“code”: 1809,
“message”: “Invalid query parameter user_id”,
“usage”: “https://docs.myapp.api/users/query”
message is not supposed to be shown to the User. It is internal to developer. If a user message is required provide it with a separate keyword and make sure it is i18n supported for different languages.
Optionally include server dumps in debug builds so that your developers know what and where went wrong. These are invaluable for bug reporting.
Use HTTP codes.
Convey correct HTTP codes with the respective responses. Don’t use 200 all across!
For example return 201 for successfully creating new content. Return 200 for successfully fetching the complete content.
Error responses should be responded with a valid HTTP status code. Don’t just return HTTP 500 for everything.

Use consistent keywords
Keywords are a set of keys used in REST API’s request and response communication.
Keeping the supported keyword set small is important for maintainable code.
Don’t introduce new keywords. See if existing keywords can convey the meaning.
For example don’t use count at one place and size at another. Be consistent.
Identify clients
A RESTful API is a means to access your system of resources. So identifying who is accessing is important.

Provide API keys to all your clients including your official in-house apps.
Each client should have a different API key.
Every request should have an API key as part of the request header. Return 4o3 HTTP code if it fails to do so.
If a client is compromised, black-list the specific API key and continue with a contingency plan.
API keys also helps in providing usage insights and volume of API request.
Authenticate or Authorise ?
Authentication is stating that you are who you are. Authorisation is allowing to do what you are supposed to do.

If you are a contained system which requires User to login/signup to perform certain tasks (like creating new content), then you are authenticating.

Authentication token should be generated (or regenerated) on successful authentication. The same should be returned to the client. This establishes a session. JSON Web Tokens are even more secured.
Subsequent API calls should specify this session token as part of request header. This helps in identifying the User who is performing the task.
Have a mechanism to revoke and regenerate session tokens.
Identify which resources needs authentication and document them.
Incase you are a system that serves 3rd party clients to access your Users on their behalf, then you should use OAuth.

Limit, sort and filter
Your API should provide developers just the data they need. This makes smart usage of the bandwidth.

When providing a list of items as response, limit them to a meaningful number and support sorting on different fields. Let clients request for more by supporting pagination. Support HATEOAS if you can!
Let client specify which fields they want want as part of response.

Fetch 5 posts with partial data
GET /posts?fields=title,date&limit=5&sort=date
Your API documentation should be as good as your code because your developer looks into the docs and understands how to use the API.

Docs should be clear and include usage examples.
They should be updated regularly to include any deprecated endpoints.
Also referring to a good RESTful API implementation is a recommended way to learn more. Some of the good REST API references to start with

facebook api

Though most of these items are a matter of common sense, I did see developers depart due to project pressures and poor understanding of concepts. Problem is – your API once released is like writing something on stone, you cannot change it and have to live with it finally ending up supporting it. Better get it right when the time is right.