Skip to content

Instantly share code, notes, and snippets.

@edwin-bluekite
Created October 28, 2013 18:01
Show Gist options
  • Save edwin-bluekite/7201551 to your computer and use it in GitHub Desktop.
Save edwin-bluekite/7201551 to your computer and use it in GitHub Desktop.
Bluekite REST API Design Guidlines (Draft)

Bluekite REST API Design Guidlines (Draft)

URI's

Bluekite REST APIs use Uniform Resource Identifiers (URIs) to address resources. URI designs range from masterpieces that clearly communicate the API’s resource model like: http://api.staging.bluekite.com/api/v1/countries?token=009342334

URI Format

The guidlines presented in this section pertain to the format of a URI. [RFC 3986](http://www.rfc-editor.org/rfc/rfc3986.txt) defines the generic URI syntax as shown below:
URI = scheme "://" authority "/" path [ "?" query ] [ "#" fragment ]

Guideline #1

Use forward slash separator (/) to indicate a hierarchical relationship

Example

https://api.payments.bluekite.com/api/v1/gt/services/tigo-post-pay

URI Format guidlines

Guideline #2

A trailing forward slash (/) should not be included in URIs. Bluekite REST APIs not expect a trailing slash and not include them in the links that they provide to clients.

The following two URIs equal:

https://api.payments.bluekite.com/api/v1/gt/services/tigo-post-pay
https://api.payments.bluekite.com/api/v1/gt/services/tigo-post-pay/

Guidline #3

Hyphens (-) are used to improve the readability of URIs for long path URI segments

Example

https://api.payments.bluekite.com/api/v1/gt/services/tigo-post-pay

Underscore (_) character is not used becouse it can get partially obscured or completely hidden by this underlining by an applications font.

Guidline #4

Lowercase letters are used in URI paths since capital letters can sometimes cause problems. RFC 3986 defines URIs as case-sensitive.

  • This URI is OK
https://api.payments.bluekite.com/api/v1/gt/services/tigo-post-pay
  • RFC 3986 specification considers this URI equal to previous
https://API.PAYMENTS.BLUEKITE.COM/api/v1/gt/services/tigo-post-pay
  • This may not be equal to previous ones
https://api.payments.bluekite.com/api/v1/gt/services/Tigo-Post-Pay

This guidline is not applied for schema and host components

Guidline #5

Avoid including file extensons in URIs

Instead, we prefer rely on the media type, as communicated through the Content-Type header, to determine how to process the body’s content.

URI Design

Guidline #6

We use subdomain names for our APIs Subdomain names (e.g., tickets.restapi.org) of an API should identify its service owner. The full domain name of an API should add a sub-domain named api. For example:

http://api.bluekite.com/accounts/123/pay

Guidline #7

Consistent subdomain names should be used for a developer portal

If an API provides a developer documentation portal, by convention it should have a subdomain labeled developer.

For example:

http://developer.tickets.bluekite.com

Request methods

Guidline #8

Don't use GET and POST to tunnel other request methods

Always make proper use of the HTTP verbs RFC 2616

  • GET
  • HEAD
  • POST
  • PUT
  • PATCH
  • OPTIONS
  • DELETE

Guidline #9

Use GET to retrieve a representation of a resource

curl -v api.staging.bluekite.com/api/v1/countries?token=XXXXXXXXXXXX HTTP/1.1
* About to connect() to api.staging.bluekite.com port 80 (#0)
*   Trying 107.23.18.142...
* Connected to api.staging.bluekite.com (107.23.18.142) port 80 (#0)
> GET /api/v1/countries?token=XXXXXX HTTP/1.1
> User-Agent: curl/7.29.0
> Host: api.staging.bluekite.com
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.1.19
< Date: Thu, 10 Oct 2013 21:03:19 GMT
< Content-Type: application/json; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Status: 200 OK
< Link: 
< X-UA-Compatible: IE=Edge,chrome=1
< ETag: "ba441b0199e228e448229c43fc29b877"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: 1325d7d285f602dab3c2304ef5ad0173
< X-Runtime: 0.044831
< X-Rack-Cache: miss
[
	{
            "name": "Guatemala",
            "code": "gt",
            "weight": 0
        },
        {
            "name": "El Salvador",
            "code": "sv",
            "weight": 0
        },
	{
            "name": "Iceland",
            "code": "is",
            "weight": 0
        },
	{
            "name": "Nicaragua",
            "code": "ni",
            "weight": 0
        }
]

Guidline #10

Use HEAD verb to retrive headers

curl --head api.staging.bluekite.com/api/v1/countries?token=XXXXXXXX
HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Thu, 10 Oct 2013 21:05:58 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Status: 200 OK
Link: 
X-UA-Compatible: IE=Edge,chrome=1
ETag: "ba441b0199e228e448229c43fc29b877"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 72609f3198615a07f965f4954f5c39ad
X-Runtime: 0.102487
X-Rack-Cache: miss

Guidline #11

Use PUT to update an already stored resource

The PUT request message have to include a representation of a resource that the client wants to update. However, the body of the request may or may not be exactly the same as a client would receive from a subsequent GET request to the resource.

PUT /countries 

Guidline #12

Use POST to create a new resource The POST request’s body contains the suggested state representation of the new resource added.

POST  /gt/services/empresa-electrica-de-guatemala/accounts/

Guidline #13

Use POST to execute actions.

Clients use the POST method to invoke the function-oriented controller resources. A POST request message may include both headers and a body as inputs to a controller resource’s function.

Our REST API's use POST, along with a targeted controller resource, to trigger all operations that cannot be intuitively mapped to one of the other core HTTP methods.

POST  /gt/services/empresa-electrica-de-guatemala/accounts/12312/pay

Guidline #14

Use DELETE to remove a resource

Once a DELETE request has been processed for a given resource, the resource can no longer be found by clients. Therefore, any future attempt to retrieve the resource’s state representation, using either GET or HEAD, must result in a 404 (“Not Found”) status returned by the API.

DELETE  /gt/ticket//12312

The DELETE method has very specific semantics in HTTP, which must not be overloaded. For example, if an API wishes to provide an “archive” action or some other state-changing interaction, it should employ a special resource action and direct its clients to use POST instead of DELETE to interact.

Guidline #15

Use OPTIONS to retrieve metadata that describes a resource’s available interactions.

OPTIONS /repos/:user/:repo/issues
{
  "POST": {
    "description": "Create an issue",
    "parameters": {
      "title": {
        "type": "string"
        "description": "Issue title.",
        "required": true
      },
      "body": {
        "type": "string",
        "description": "Issue body.",
      },
      "assignee": {
        "type": "string",
        "description" "Login for the user that this issue should be assigned to."
      },
      "milestone": {
        "type": "number",
        "description": "Milestone to associate this issue with."
      },
      "labels": {
        "type": "array/string"
        "description": "Labels to associate with this issue."
      }
    },
    "example": {
      "title": "Found a bug",
      "body": "I'm having a problem with this.",
      "assignee": "octocat",
      "milestone": 1,
      "labels": [
        "Label1",
        "Label2"
      ]
    }
  }
}

HTTP Response codes

Our REST APIs use the Status header as part of an HTTP response message to inform clients of their request’s overarching result. RFC 2616 defines the Status-Line syntax as shown below:

Status 404 Not Found

Guidline #16

Use 200("Ok") indicate nonspecific success

In most cases, 200 is the code the client hopes to see. It indicates that the REST API successfully carried out whatever action the client requested.

Guidline #17

Use 201("Created") indicate successful resource creation

Our REST API's responds with the 201 status code whenever new resource is created at the client's request.

Guidline #18

Use 202("Accepted") indicate successful start of an asynchronous action.

A 202 HTTP response indicates that the request will be handled asynchronously. This response status code tells the client that the request appears valid, but it still may have problems once it’s finally processed. A callback URL could by included in the request body.

Guidline #19

Use 204("No Content") indicates the response body is intentionally empty.

The 204 status code is sent out in response to a PUT, POST, or DELETE request, when the response body es empty.

Guidline #20

Don't 302("Found") HTTP 1.1 introduced status codes 303 (“See Other”) and 307 (“Temporary Redirect”), either of which should be used instead of 302.

Guidline #21

Use 303("See Other") is used to redirect to a diferent URI

A 303 response indicates that a resource has finished its work, but instead of sending a potentially unwanted response body, it sends the client the URI of a response resource.

Guidline #22

Use 304("Not Modified") to preserve bandwith

Is similar to 204 (“No Content”) in that the response body must be empty. The distinction is that 204 is used when there is nothing to send in the body, whereas 304 is used when there is state information associated with a resource but the client already has the most recent version of the representation.

Guidline #23

Use 307 (“Temporary Redirect”) used to tell clients to resubmit the request to another URI

The client should resubmit the request to the URI specified by the response message’s Location header.

Guidline #24

Use 401 (“Unauthorized”) used when there is a problem with the client’s credentials

A 401 error response indicates that the client tried to operate on a protected resource without providing the proper authorization credentials.

Guidline #25

Use 404 (“Not Found”) when a client’s URI cannot be mapped to a resource.

Guidline #26

500 (“Internal Server Error”) used to indicate API malfunction

500 is the generic REST API error response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment