A good API is not just easy to use but also hard to misuse.
-
Version your API
- Path: /v1/users
- Subdomain: api.v1.example.com/users
-
URI must be nouns, not verbs
- /cars
- /users
- /books/{id}
-
GET requests must never alter system/resource state (GET is readonly)
-
All nouns are plurals
- GET /users
- DELETE /users/{id}
- GET /users/{id}/reviews
- POST /users/{id}/reviews
- PUT /users/{id}/reviews/{rid}
-
Map relations by sub-resources
- GET /users/{id}/reviews
- PUT /users/{id}/reviews/{rid}
-
Allow for collections filtering, sorting and paging
- GET /users?sort[]=-age&sort[]=+name
- GET /users/{id}/reviews?published=1
- GET /books?format[]=epub&format[]=mobi
- Allow only SSL (HTTPS) requests
- Use a standard and stateless authentication method:
- API Key / Token (as part of the
Authorization
header) - Basic Authentication (Basic Auth)
- API Key / Token (as part of the
- The OAuth protocol is not stateless, because it requires the user to pass credentials one time, and then maintain state of the user’s authorization on the server side, these are not considerations of the underlying HTTP protocol.
- If the authentication is unsuccessful, the status code
403
(Forbidden) is returned.
- Content-type: application/json
HTTP Verb | HTTP Path | CRUD | Method | Description | Response codes |
---|---|---|---|---|---|
GET | /users | Index | getUsers | Used for retrieving a list of resources. | 200 (OK), 404 (Not Found) |
GET | /users/{id} | Read | getUserById | Used for retrieving a single resources. | 200 (OK), 404 (Not Found) |
POST | /users | Create | insertUser | Used for creating resources. | 201 (Created), 404 (Not Found), 409 (Conflict) if resource already exists. |
PUT | /users/{id} | Update | updateUser | Used for replacing the entire resources or collections. | 200 (OK), 204 (No Content). 404 (Not Found) |
PATCH | /users/{id} | Partial update | updateUser | Used for updating resources with partial data. | 200 (OK), 204 (No Content), 404 (Not Found) |
DELETE | /users/{id} | Delete | deleteUser | Used for deleting resources. | 200 (OK), 404 (Not Found) |
Status codes indicate the result of the HTTP request.
- 1XX - informational
- 2XX - success
- 3XX - redirection
- 4XX - client error
- 5XX - server error
Return meaningful status codes:
Code | Name | What does it mean? |
---|---|---|
200 | OK | All right! |
201 | Created | If resource was created successfully. |
400 | Bad Request | 4xx Client Error |
401 | Unauthorized | You are not logged in, e.g. using a valid access token |
403 | Forbidden | You are authenticated but do not have access to what you are trying to do |
404 | Not found | The resource you are requesting does not exist |
405 | Method not allowed | The request type is not allowed, e.g. /users is a resource and POST /users is a valid action but PUT /users is not. |
409 | Conflict | If resource already exists. |
422 | Unprocessable entity | Validation failed. The request and the format is valid, however the request was unable to process. For instance when sent data does not pass validation tests. |
500 | Server error | 5xx Server Error. An error occured on the server which was not the consumer's fault. |
Send a 500 Internal Server Error
response.
HTTP Statuscode: 500
Content:
{
"error": {
"message": "Application Error"
}
}
Content with error details:
{
"error": {
"code": 5001,
"message": "Database connection failed"
}
}
Sending invalid JSON will result in a 400 Bad Request
response.
HTTP Statuscode: 400
Content:
{
"error": {
"code": 400,
"message": "Problems parsing JSON"
}
}
Sending invalid fields will result in a 422 Unprocessable Entity
response.
HTTP Statuscode: 422
Content:
{
"error": {
"code": 422,
"message": "Validation failed",
"errors": [
{
"field": "email",
"message": "Missing email"
}
]
}
}
// Get base url
var url = $('head base').attr('href')
A GET request:
$.ajax({
url: url + "users/1",
type: "GET",
cache: false,
contentType: 'application/json',
dataType: 'json'
}).done(function (data) {
alert('Successfully');
console.log(data);
}).fail(function (xhr) {
var message = 'Server error';
if (xhr.responseJSON && xhr.responseJSON.error.message) {
message = xhr.responseJSON.error.message;
}
alert(message);
});
A POST request with payload:
var data = {
username: "max",
email: "[email protected]"
};
$.ajax({
url: url + "users",
type: "POST",
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(data)
}).done(function (data) {
alert("Success");
console.log(data);
}).fail(function (xhr) {
if (xhr.status === 422) {
// Show validation errors
var response = xhr.responseJSON;
alert(response.error.message);
$(response.error.errors).each(function (i, error) {
console.log("Error in field [" + error.field + "]: " + error.message);
});
} else {
var message = 'Server error';
if (xhr.responseJSON && xhr.responseJSON.error.message) {
message = xhr.responseJSON.error.message;
}
alert(message);
}
});
-
Controller name: UserController
-
REST-API methods (json request and response)
- getUsers
- getUser
- insertUser
- updateUser
- deleteUser
-
REST-API methods for sub-resources (json request and response)
- geUserReviews
- getUserReview
- insertUserReview
- updateUserReview
- deleteUserReview