REST API Convention Summary
Post By kanra
Blogs REST API Convention Summary

In this article I tried to consolidate all the best practices for designing REST APIs. Note that all these results are based on my personal works after designing couple web API projects, and they are not official conventions that you should follow.

REST APIs use Uniform Resource Identifiers (URIs) to address resources.

HTTP request/method has its basic CRUD operations:

  • POST – Create a new record, submit an entity
  • GET – Retrieve existing list of records or one record
  • PUT – Update/Replace an existing whole/entire record, or an existing entire list of records, such as update a record or a list of record resource
  • PATCH – Update partial data of an existing record (edit user profile: change only User name), or update an array resource (add/delete records of the array resource)
  • DELETE – Delete existing list of records or an entity
  • HEAD – Get only header information
  • OPTION – Get allowable HTTP headers and allowable HTTP methods that an API supports
  • CONNECT – requests that a proxy establish a HTTP tunnel to a destination server, and if successful, blindly forward data in both directions until the tunnel is closed
  • TRACE – performs a message loop-back test along the path to the target resource
Method Safe Idempotent
POST NO NO
GET YES YES
PUT NO YES
PATCH NO YES/NO
DELETE NO YES
HEAD YES YES
OPTION YES YES
CONNECT NO NO
TRACE YES YES
Safe

Request methods are considered “safe” if they are read-only; the client does not request, and does not expect, any state change (resource change) on the origin server as a result of applying a safe method to a target resource. So, the GETHEADOPTIONS, and TRACE methods are defined to be safe since they are just reading information, but other methods such as POST will add new record and so the server state (DB resource) changes.

Idempotent
  • It is a property of HTTP methods.
  • A request method is considered idempotent if the intended effect on the server State by multiple identical requests with that method is the same as the effect for a single such request. The effect is produced on the state of the resource on the server but not about the response status code received by the client.
  • APIs should be idempotent. They ensure safe retries by making repeated requests to produce the same result, especially for POST operations.
  • DELETE method, which is defined as idempotent. A client performs a DELETE request to delete a resource from the server. The server processes the request, the resource gets deleted and the server returns 204. Then the client repeats the same DELETE request and, as the resource has already been deleted, the server returns 404. Despite the different status code received by the client, the effect produced by a single DELETE request is the same effect of multiple DELETE requests to the same URI.
  • PATCH can be idempotent. If just change the name property of a object resource, you might send something like {"name": "foo"} as a payload and that would indeed be idempotent since executing this request any number of times would yield the same result: The resources name attribute is now “foo”.
  • PATCH can be NOT idempotent. When apply change an array resource, the sub-sequence changes will makes it NON idempotent.
    PATCH /users
    [{ "op": "add", "username": "newuser", "email": "newuser@example.org" }]

    After repeated applying, the “users” resource will be changed again and again, even though we issued the exact same PATCH against the exact same endpoint.

 

 

URI Components

 

https://api.domain.com/namespace/v1/resource-name/collection?product_id=123&type=shoe
  • https:// – Scheme, Protocol
  • api.domain.com – Domain name, DNS
  • /namespace/resource-name/v1/collection – Path
  • /namespace – Such as /api, or not necessary
  • /v1 – Version
  • /resource-name – Resource category name, such as /product-management
  • /collection – Specific resource name, or collection of resource, such as /products, /customers
  • product_id=123&type=shoe – Query

 

Rules
  1. URI MUST be specified in all lower case
  2. Use hyphens - to separate words or path parameters (no spaces or underscores _)
  3. Use underscores _ to separate words in query parameter names but not as part of the base URI

 

Collection Resources

Rules
  1. Nouns MUST be used
  2. Resource names MUST be plural, or appropriate noun if resource is non-standard
  3. Resource names MUST be lower-case and hyphens
  4. Sub resource can use be under /resource-category-name
Examples:
/customers
/leaves
/fishes
/tree-nuts 
/customer-management/types      - under /customer-management  
/customer-types                 - just use plural-nouns

Singleton Resource

Rules
  1. Use Collection resource URI and identify a single resource by its id
  2. Further sub-resource by concatenating further path
  3. Filtering using query parameter
/customers/{customerId} 
/customers/{customerId}/accounts/{accountId} 
/customers?customer_type=use_this_type&sort=date
Examples:
// List of customers
GET /customers

// Filtering is a query:
GET /customers?year=2011&sort=desc

// Get one customer by ID
GET /customers/12345

// get a device by id
GET https://api.example.com/api/v2/device-management/managed-devices/123 

// Get all orders of this customer
GET /customers/12345/orders

// filering
GET /customers/12345/orders?year=2011&type=shoe

// special resource
GET http://api.example.com/user-management/users/admin

Action Resources

Rules
  1. Use Collection resource URI or Singleton resource URL
  2. Use HTTP request methods CRUD, to indicate actions
  3. Use Verb to denote Controller resources that are like executable functions

 

Examples:
// Add a new customer
POST /customers

// Update a customer with id (payload is entire entity)
// {"username":"Jason","email":"jason@email.com"}
PUT /customers/12345

// Update list of customer (payload is an entire list)
// [{"username":"Jason","email":"jason@email.com"}, {}, ...]
PUT /customers

// Delete a customer
DELETE /customers/12345

// Add a new order to a customer
POST /customers/12345/orders

// Update a customer order
PUT /customers/12345/orders/67890

// Update JUST customer name with id (payload is partially data) 
// {"username":"Jason"}
PATCH /customers/12345

// Update list of customer (payload is partially operation data) 
// [{ "op": "add", "username": "newuser", "email": "newuser@example.org" }]
PATCH /customers

// Action-only endpoints using POST
POST http://api.example.com/cart-management/users/{id}/cart/checkout
POST http://api.example.com/song-management/users/{id}/playlist/play

 

 

Request/Response Message Format

 

For request and response body field names or query parameter names, the naming MUST be consistent, and SHOULD be either camelCase OR snake_case:

Examples:
{
    // this_is_snake_case (use this)
    "document_id" : 1837,       // object id using int
    "products": ["11","22"],    // array using plural nouns 
    "is_student": true,         // boolean
    "has_candy": true,          // boolean
}

{
    // thisIsCamelCase
    "documentId" : 1837
    "products": ["11","22"]
}
  • products – Fields that represent arrays SHOULD be named using plural nouns
Since SQL database is using snake_case normally, the data come back from DB is in snake_case and can be just send out, so using snake_case is a good choice.

Request Headers

Request Headers:

Header Default Value
Accept application/json

Response Convention

Status codes:

  • 2xx, OK, request went well and response is sent
  • 3xx, Resource was moved and then let client know it
  • 4xx, Client request error, if the request cannot be fulfilled because of a client error (like requesting a resource that does not exist)
  • 5xx, Server-side error, something wrong on the API side (like an exception happened)

 

 

 



AUTHOR : kanra
EMAIL : karawakara@gmail.com
Working on Networking, Web Development, Software Development, Server-side deployment. Having fun on doing experiments on new technologies.