Skip to content

Instantly share code, notes, and snippets.

@timurvafin
Last active August 29, 2015 14:04
Show Gist options
  • Save timurvafin/5a906f697e8fac944f79 to your computer and use it in GitHub Desktop.
Save timurvafin/5a906f697e8fac944f79 to your computer and use it in GitHub Desktop.
API Design Guide

REST API Design Guide

Introduction

JSON API is a specification based on http://jsonapi.org/format/.

Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119].

Document Structure

This section describes the structure of a JSON response.

Top Level

A JSON object MUST be at the root of every JSON API document. This object defines a document's "top level".

A document's top level MUST contain a representation of the resource or collection of resources primarily targeted by a request.

A document's top level MAY also have the following members:

  • "meta": meta-information about a resource, such as pagination.

No other members SHOULD be present at the top level of a document.

Resource Representations

Individual Resource Representations

An individual resource MUST be represented as a single "resource object".

The following post is represented as a resource object:

{
  "posts": {
    "id": "1",
    // ... attributes of this post
  }
}

Resource Collection Representations

A collection of any number of resources MUST be represented as an array of resource objects.

The following posts are represented as an array of resource objects:

{
  "posts": [{
    "id": "1"
    // ... attributes of this post
  }, {
    "id": "2"
    // ... attributes of this post
  }]
}

Resource IDs

Each resource object MUST contain a unique identifier, or ID, when available. An ID SHOULD be represented by an "id" key and its value MUST be a string which SHOULD only contain alphanumeric characters, dashes and underscores.

Resource foreign keys

Serialize foreign key references with a nested object, e.g.:

{
  "articles" : {
    "name": "service-production",
    "owner": {
      "id": "5d8201b0..."
    }
  }
}

Instead of e.g:

{
  "articles" : {
    "name": "service-production",
    "owner_id": "5d8201b0...",
  }
}

This approach makes it possible to inline more information about the related resource without having to change the structure of the response or introduce more top-level response fields, e.g.:

{
  "articles" : {
    "name": "service-production",
    "owner": {
      "id": "5d8201b0...",
      "name": "Alice",
      "email": "[email protected]"
    }
  }
}

Resource Relationships

Nest resource relationships in to the primary resource.

For example, the following post is associated with a single author and a collection of comments:

  {
    "id": "1",
    "title": "Rails is Omakase",
    "links": {
      "author": {
        "id": "1",
        "full_name": "John Smith"
      },
      "comments": [
        {
          "id": "1",
          "text": "..."
        },
        {
          "id": "2",
          "text": "..."
        }
      ]
    }
  }

URLs

Versioning

Version number MUST be present in the URL:

/v1/articles

URLs for Resource Collections

The URL for a collection of resources MUST be formed from the resource type.

For example, a collection of resources of type "photos" will have the URL:

/photos

URLs for Individual Resources

Collections of resources MUST be treated as sets keyed by resource ID. The URL for an individual resource MUST be formed by appending the resource's ID to the collection URL.

For example, a photo with an ID of "1" will have the URL:

/photos/1

### Relationship URLs

## Fetching Resources

A resource, or collection of resources, can be fetched by sending a `GET`
request to the URL described above.

Responses can be further refined with the optional features described below. 

### Pagination

A server **MAY** choose to support to paginate collection of resources.

`page`, `per_page` parameters **MUST** be specified in the query string to specify 
requested page number and number resources per page.

#### Response

A document's top level **MUST** have "meta" key to specify pagination information with
following elements:
* "total" - total number of resources in the paginated collection
* "per_page" - number of resources per page
* "page" - requested page number


### Filtering

A server **MAY** choose to support requests to filter resources according to
specific criteria.

Filtering **SHOULD** be supported by appending parameters to the base URL for
the collection of resources to be filtered.

For example, the following is a request for all comments associated with a
particular post:

```text
GET /comments?posts=1

With this approach, multiple filters MAY be applied to a single request:

GET /comments?posts=1&author=12

Inclusion of Linked Resources

A server MAY choose to support returning compound documents that include both primary and linked resource objects.

An endpoint MAY return resources linked to the primary resource(s) by default.

An endpoint MAY also support custom inclusion of linked resources based upon an include request parameter. This parameter SHOULD specify the path to one or more resources relative to the primary resource. If this parameter is used, ONLY the requested linked resources SHOULD be returned alongside the primary resource(s).

For instance, comments could be requested with a post:

GET /posts/1?include=comments

Multiple linked resources could be requested in a comma-separated list:

GET /posts/1?include=author,comments,comments.author

Creating, Updating and Deleting Resources

A server MAY allow resources that can be fetched to also be created, modified and deleted.

A server MAY allow multiple resources to be updated in a single request, as discussed below. Updates to multiple resources MUST completely succeed or fail. No partial updates are allowed.

Creating an Individual Resource

A request to create an individual resource MUST include a single primary resource object.

For instance, a new photo might be created with the following request:

POST /photos
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "photos": {
    "title": "Ember Hamster",
    "src": "http://example.com/images/productivity.png"
  }
}

Responses

201 Created

A server MUST respond to a successful resource creation request according to [HTTP semantics](http://tools.ietf.org/html/draft-ietf- httpbis-p2-semantics-22#section-6.3).

When one or more resources has been created, the server MUST return a 201 Created status code.

The response MUST also include a document that contains the primary resource(s) created.

HTTP/1.1 201 Created
Content-Type: application/vnd.api+json

{
  "photos": {
    "id": "1",
    "title": "Ember Hamster",
    "src": "http://example.com/images/productivity.png"
  }
}
Other Responses

Servers MUST use other HTTP error codes to represent errors. Clients MUST interpret those errors in accordance with HTTP semantics. Error details MAY also be returned, as discussed below.

Updating Resources

To update an individual resource, send a PUT request to the URL that represents the resource. The request MUST include a single top-level resource object.

For example:

PUT /articles/1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json

{
  "articles": {
    "id": "1",
    "title": "To TDD or Not"
  }
}

Responses

204 No Content

A server MUST return a 204 No Content status code if an update is successful and the client's current attributes remain up to date. This applies to PUT requests as well as POST and DELETE requests that modify links without affecting other attributes of a resource.

200 OK

If a server accepts an update but also changes the resource(s) in other ways than those specified by the request (for example, updating the updated_at attribute or a computed sha), it MUST return a 200 OK response as well as a representation of the updated resource(s) as if a GET request was made to the request URL.

Other Responses

Servers MAY use other HTTP error codes to represent errors. Clients MUST interpret those errors in accordance with HTTP semantics. Error details MAY also be returned, as discussed below.

Deleting Resources

An individual resource can be deleted by making a DELETE request to the resource's URL:

DELETE /photos/1

A server MAY optionally allow multiple resources to be deleted with a DELETE request to their URL:

DELETE /photos/1,2,3

Responses

204 No Content

A server MUST return a 204 No Content status code if a delete request is successful.

Other Responses

Servers MAY use other HTTP error codes to represent errors. Clients MUST interpret those errors in accordance with HTTP semantics. Error details MAY also be returned, as discussed below.

Errors

Error objects are specialized resource objects that MAY be returned in a response to provide additional information about problems encountered while performing an operation. Error objects SHOULD be returned as a collection keyed by "errors" in the top level of a JSON API document, and SHOULD NOT be returned with any other top level resources.

An error object MAY have the following members:

  • "id" - A unique identifier for this particular occurrence of the problem.
  • "code" - An application-specific error code, expressed as a string value.
  • "message" - general description, which can be used on client side, SHOULD be understandable for users
  • "validation" - SHOULD contain validation error messages for resource fields
{
  "errors":
  {
    "code": 4xx,
    "message": "...",
    "validation": [
      {
        "field_name": [
          "...",
          "..."
        ]
      },
      {
        "another_field_name": ["..."]
      }
    ]
  }
}

A server MUST return a 422 Unprocessable Entity status code in case of validation errors.

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