collected wisdom on REST API best practice.
- 200 : OK – Eyerything is working
- 201 : OK – New resource has been created
- 204 : OK – The resource was successfully deleted
- 304 : Not Modified – The client can use cached data
- 400 : Bad Request – The request was invalid or cannot be served. The exact error should be explained in the error payload. E.g."The JSON is not valid"
- 401 : Unauthorized – The request requires an user authentication
- 403 : Forbidden – The server understood the request, but is refusing it or the access is not allowed.
- 404 : Not found – There is no resource behind the URI.
- 422 : Unprocessable Entity – Should be used if the server cannot process the enitity, e.g. if an image cannot be formatted or mandatory fields are missing in the payload.
- 500 : Internal Server Error – API developers should avoid this error. If an error occurs in the global catch blog, the stracktrace should be logged and not returned as response.
A resource, with no errors
{
"data": {"manufacturer": "Ford"},
"errors": null
}
An array of resources, with no errors
{
"data": [{"manufacturer": "Ford"}, {"manufacturer": "Nissan"}],
"errors": null
}
All exceptions should be mapped in an error payload. Here is an example how a JSON payload should look like.
{
"data": null,
"errors": [
{
"userMessage": "Sorry, the requested resource does not exist",
"internal": {
"message": "No car found in the database",
"code": 34
}
}
]
}
Some proxies support only POST and GET methods. To support a RESTful API with these limitations, the API needs a way to override the HTTP method.
Use the custom HTTP Header X-HTTP-Method-Override to overrider the POST Method.
Make the API Version mandatory and do not release an unversioned API. Use a simple ordinal number and avoid dot notation such as 2.5.
/v1/cars
/v1/cars/1
Use limit and offset. It is flexible for the user and common in leading databases. Pick a default limit appropriate for your setup and default offset=0. Once choosen dont alter it for different end points.
/v1/cars?limit=10&offset=0
Consider returning paging info when requesting a paged resource.
{
"data": [],
"paging": {
"total": 100,
"limit": 10,
"offset": 0,
"next_offset": 10,
"prev_offset": null
}
}