Here, I've gathered best practices and guides with only tweaking their examples to match our specific project.
NOTE: Backend routes are different than front-end routes. The Restful API is about the backend routes, not the routes one sees in the web application.
- A URL identifies a resource.
- URLs should include nouns, not verb
- Use plural nouns only for consistency (no singular nouns). Use HTTP verbs (GET, POST, PUT, DELETE) to operate on the collections and elements. You shouldn’t need to go deeper than resource/identifier/resource.
- URL v. header:
- If it changes the logic you write to handle the response, put it in the URL.
- If it doesn’t change the logic for each response, like OAuth info, put it in the header.
- Specify optional fields in a comma separated list.
from: https://github.com/WhiteHouse/api-standards
Non-standard headers should follow with X-
:
- not
call-type
, if any, butX-REQUEST-TYPE
.
- List of Apps:
GET http://www.example.gov/api/v1/apps
- Filtering is a query:
GET http://www.example.com/api/v1/apps?type=free&sort=desc
GET http://www.example.com/api/v1/apps?category=games&year=2011
- A single app in JSON format:
GET http://www.example.com/api/v1/apps/1234
- All comments in this app:
GET http://www.example.com/api/v1/apps/1234/comments
- Specify optional fields in a comma separated list:
GET http://www.example.com/api/v1/apps/1234?fields=comments,date,draft
- Add a new comment to a particular app:
POST http://example.com/api/v1/apps/1234/comments
from: https://github.com/WhiteHouse/api-standards
- Non-plural noun:
http://www.example.com/app
http://www.example.com/app/1234
- Verb in URL:
http://www.example.com/apps/delete
- Filter outside of query string
http://www.example.com/apps/1234/screenshots/mobile
from: https://github.com/WhiteHouse/api-standards
An error response should consist of the following:
The appropriate HTTP error status code and any other relevant headers; A human readable message in the appropriate format (including a link to the documentation); A Link header to a meaningful state transition if appropriate. An example from the twilio api:
GET https://api.twilio.com/2010-04-01/Accounts.json
results in:
401 Unauthorized
WWW-Authenticate: Basic realm="Twilio API"
{
"status": 401,
"message": "Authenticate",
"code": 20003,
"more_info": "http:\/\/www.twilio.com\/docs\/errors\/20003"
}
from: http://blog.luisrei.com/articles/rest.html
or
HTTP/1.1 429 Too Many Requests
{
"id": "rate_limit",
"message": "Account reached its API rate limit.",
"url": "https://docs.service.com/rate-limits"
}
from: https://github.com/interagent/http-api-design Versions
Never release an API without a version number.
Versions should be integers, not decimal numbers, prefixed with v
. For example:
Good: v1
, v2
, v3
Bad: v-1.1
, v1.2
, 1.3
Maintain APIs at least one version back.
Example: http://example.com/api/v1/apps
Response body:
{
"metadata": {
"resultset": {
"count": 123,
"offset": 0,
"limit": 10
}
},
"results": [
{
"id": "1234",
"packageId": "com.oovoo",
"title": "oovoo",
"tags": [
{"id": "125", "name": "Communication"},
{"id": "834", "name": "Chat"}
],
"created": "1231621302"
},
{
"id": 2351,
"packageId": "com.coursera"
"title": "Coursera App",
"tags": [
{"id": "125", "name": "Education"},
],
"created": "126251302"
}
]
}
Example: http://example.com/api/v1/apps/1234
Response body:
{
"id": "1234",
"packageId": "com.oovoo",
"title": "oovoo",
"tags": [
{"id": "125", "name": "Communication"},
{"id": "834", "name": "Chat"}
],
"created": "1231621302"
},
from: https://github.com/WhiteHouse/api-standards
In data models with nested parent/child resource relationships, paths may become deeply nested, e.g.:
/developers/{developer_id}/apps/{app_id}/comments
Limit nesting depth by preferring to locate resources at the root path. Use nesting to indicate scoped collections. Even though childs may be arbitrarily nested, it's good to keep the depth limited to 2, if possible. Longer URLs are more difficult to work with.
So the above one would be better to be called this way:
/developers/{developer_id}/apps
/apps/{app_id}/comments
/apps/{app_id}/screenshots/{screenshot_id}?screen=mobile