lambda2 / rapis

A specification proposal for API's
MIT License
55 stars 10 forks source link


RAPIS
A REST API Standard

A 21th century way for designing Rest API's

Join the chat at https://gitter.im/lambda2/rapis

This specification is a possible way to design a REST API, regardless of the language, format (json, xml, etc...) or used libraries . If you don't agree on this specifications, there is other ways to structure your REST API !. All contributions are welcome, please help me 🙏.

Table of contents

  1. Specification
  2. TODO
  3. Please contribute
  4. Sources and thanks
  5. Other ways to structure your REST API

1. Specification

1.1 Design

The API must embrace RESTful design principles. It must be resource-based, and each resource representation must contain enough information to modify or delete the resource on the server, provided it has permission to do so.

1.2 Formatting

1.3 Security

1.4 Verbs

Verb Description
GET Used for retrieving resources.
POST Used for creating resources.
PATCH / PUT Used for updating resources.
DELETE Used for deleting resources.

Fallback header

The HTTP client that doesn't support PUT, PATCH or DELETE requests must send a POST request with an X-HTTP-Method-Override header specifying the desired verb.

The server must correctly handle this header. When it is set, it take precedence over the original request method.

Location header

When a resource is created (with a POST request), the response must contain a Location header with the link of the new resource.

Response on update and create actions

When a resource is created or modified (e.g., with a POST, PUT or PATCH request), the response must contain the created or updated representation of the resource.

1.5 Status codes

The API must uses descriptive HTTP response codes to indicate the success or failure of request.

Codes in the 2xx range must indicate a success, codes in the 4xx range must indicate an error that failed given the information provided (e.g., a required parameter was omitted, a charge failed, etc.), and codes in the 5xx range must indicate a server-side error (e.g., the server is unavailable).

The server must respond with the following status codes, according to the situation:

Http Code Meaning
200 OK Request succeeded. Response included
201 Created Resource created. URL to new resource in Location header
204 No Content Request succeeded, but no response body
303 See other The resource is in another location. See Asynchronous processing.
304 Not Modified The response is not modified since the last call. Returned by the cache.
400 Bad Request Could not parse request
401 Unauthorized No authentication credentials provided or authentication failed
403 Forbidden Authenticated user does not have access
404 Not Found Page or resource not found
405 Method Not Allowed The request HTTP method is not allowed for the authenticated user
410 Gone The endpoint is no longer available. Useful for old API versions
415 Unsupported Media Type POST/PUT/PATCH request occurred without a application/json content type
422 Unprocessable Entry A request to modify or create a resource failed due to a validation error
429 Too Many Requests Request rejected due to rate limiting
500 Internal Server Error An internal server error occurred
502 Bad Gateway The server was acting as a gateway or proxy and received an invalid response from the upstream server
503 Service Unavailable The server is currently unable to handle the request.

1.6 Errors

GET /unicorns/4 HTTP/1.1

HTTP/1.1 404 Not Found
Content-Type: application/json

{
   "error": "Not Found",
   "message": "Unable to found unicorn with id '4'"
}
POST /unicorns HTTP/1.1

{
  "unicorn": {
    "color": "purple"
  }
}

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
   "error": "Validation failed",
   "messages": ["name cannot be blank"]
}

1.7 Parameters

Resource creation or update parameters must be wrapped in an object as the singular name of the resource.

POST /unicorns HTTP/1.1
Accept: application/json
Content-Type: application/json
Host: api.example.com

{
  "unicorn": {
    "name": "John",
    "color": "purple",
    "country_id": 1
  }
}

HTTP/1.1 201 Created
Content-Type: application/json

{
  "unicorn": {
    "id": 4,
    "name": "John",
    "color": "purple",
    "created_at": "2016-07-25T12:19:33Z"
  }
}

1.8 Custom HTTP headers

All non-standard HTTP headers must begin by a X-.

For example, for rate limiting, the X-Rate-Limit-Limit, X-Rate-Limit-Remaining and X-Rate-Limit-Reset headers should be used.

1.9 Versioning

The API must be versioned, and must not have breaking changes without version change.

GET /unicorns HTTP/1.1
Accept: application/vnd.example-app.v3.1+json
Content-Type: application/json
Host: api.example.org

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 477
Content-Type: application/json
X-Version: 3.1

{
  [...]
}

1.10 Pagination

Requests for collections should be paginated, and return a limited number of results.

In this case, the client must be able to change the requested page using the page[number] parameter.

The client should also be able to change the number of items returned per page using the page[size] parameter.

A lot of services uses the page and the per_page parameters to set the page number and the number of items per page. The server should be able to support both of theses parameters.

A paginated response should have:

GET /unicorns?page[size]=2 HTTP/1.1
Content-Type: application/json
Host: api.example.org

HTTP/1.1 200 OK
Content-Type: application/json
Link: <https://api.example.org/unicorns?page[number]=2&page[size]=2>; rel="last", <https://api.example.org/unicorns?page[number]=2&page[size]=2>; rel="next"
X-Page: 1
X-Per-Page: 2
X-Total: 4

[
  {
    "id": 1,
    "name": "Charles",
    "color": "yellow",
    "created_at": "2016-07-25T12:19:33Z"
  },
  {
    "id": 2,
    "name": "Zoe",
    "color": "green",
    "created_at": "2016-07-25T12:19:33Z"
  }
]

1.11 Filtering

The client should be able to filter resource collections using the filter parameter. In this case, only the fields matching the given filter(s) will be returned.

The value of the filter parameter must be a hash of the filter name as a key, and a comma-separated list of the requested values as a value.

GET /unicorns?filter[color]=yellow HTTP/1.1
Content-Type: application/json
Host: api.example.org

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "id": 1,
    "color": "yellow"
  },
  {
    "id": 3,
    "color": "yellow"
  }
]

1.12 Sorting

The client should be able to sort resource collections according to one or more fields using the sort parameter. The value for sort must represent sort fields.

Sorting on multiple fields should be done by allowing comma-separated sort fields. In this case, sort fields should be applied in the order specified.

The sort order for each sort field must be ascending unless it is prefixed with a minus (-), in which case it must be descending.

GET /unicorns?sort=color,-name HTTP/1.1
Content-Type: application/json
Host: api.example.org

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "id": 2,
    "name": "Zoe",
    "color": "green",
    "created_at": "2016-07-25T12:19:33Z"
  },
  {
    "id": 4,
    "name": "John",
    "color": "purple",
    "created_at": "2016-07-25T12:19:33Z"
  },
  {
    "id": 3,
    "name": "Mike",
    "color": "yellow",
    "created_at": "2016-07-25T12:19:33Z"
  },
  {
    "id": 1,
    "name": "Charles",
    "color": "yellow",
    "created_at": "2016-07-25T12:19:33Z"
  }
]

If the server does not support sorting as specified in the query parameter sort, it must return a 400 Bad Request status code.

1.13 Searching

The client should be able to search on resource collections fields using the search parameter. In this case, only the fields matching the given search(s) will be returned.

The value of the search parameter must be a hash of the search field as a key, and the query as a value.

GET /unicorns?search[name]=e HTTP/1.1
Content-Type: application/json
Host: api.example.org

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "id": 1,
    "name": "Charles",
    "color": "yellow",
    "created_at": "2016-07-25T12:19:33Z"
  },
  {
    "id": 2,
    "name": "Zoe",
    "color": "green",
    "created_at": "2016-07-25T12:19:33Z"
  },
  {
    "id": 3,
    "name": "Mike",
    "color": "yellow",
    "created_at": "2016-07-25T12:19:33Z"
  }
]

A global search on a resource collection should be implemented using directly a value instead of a hash for the search parameter.

1.14 Embedding

The client should be able to include data related to (or referenced) from the resource being requested using the embed parameter. The value of the embed parameter must be a comma separated list of fields to be embedded. Dot-notation must be used to refer to sub-fields.

GET /unicorns?embed=country.name HTTP/1.1
Content-Type: application/json
Host: api.example.org

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "id": 1,
    "name": "Charles",
    "color": "yellow",
    "created_at": "2016-07-25T12:19:33Z",
    "country": {
      "name": "Australia"
    }
  },
  {
    "id": 2,
    "name": "Zoe",
    "color": "green",
    "created_at": "2016-07-25T12:19:33Z",
    "country": {
      "name": "Italy"
    }
  },
  {
    "id": 3,
    "name": "Mike",
    "color": "yellow",
    "created_at": "2016-07-25T12:19:33Z",
    "country": {
      "name": "U.S.A"
    }
  },
  {
    "id": 4,
    "name": "John",
    "color": "purple",
    "created_at": "2016-07-25T12:19:33Z",
    "country": {
      "name": "France"
    }
  }
]

1.15 Selecting

The client should be able to select only specific fields in the response using the fields parameter. In this case, only the requested fields will be returned.

The value of the fields parameter must be a hash of the resource name as a key, and a comma-separated list of the fields names to be returned as a value.

GET /unicorns?fields[unicorns]=id,color HTTP/1.1
Content-Type: application/json
Host: api.example.org

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "id": 1,
    "color": "yellow"
  },
  {
    "id": 2,
    "color": "green"
  },
  {
    "id": 3,
    "color": "yellow"
  },
  {
    "id": 4,
    "color": "purple"
  }
]

If the server does not support selection as specified in the query parameter fields, it must return a 400 Bad Request status code.

1.16 Caching

Server should generate a ETag header containing a hash or checksum of the representation. This value should change whenever the output representation changes.

1.17 Asynchronous processing

When a resource creation or update is asynchronously processed, the request should return a 202 Accepted status code with a link in the Content-Location header which should redirect to the resource when the job processing is done.

POST /movies HTTP/1.1
Accept: application/json
Content-Type: application/json
Host: api.example.com

{
  "movie": {
    "name": "Charlie the Unicorn",
    "source": "https://www.youtube.com/watch?v=CsGYh8AacgY"
  }
}

HTTP/1.1 202 Accepted
Content-Type: application/json
Content-Location: https://api.example.com/movies/jobs/42

{}

When the job process is done, requesting the link in the Content-Location header should return a 303 See other status code with the created resource link in Location header.

GET /movies/jobs/42 HTTP/1.1
Accept: application/json

HTTP/1.1 303 See other
Content-Type: application/json
Location: https://api.example.com/movies/3

2. TODO

There still a lot to do:

3. Please contribute

All suggestions, questions and ideas are welcome ! You can reach me on gitter, or fork this project and make a Pull Request !

4. Sources and thanks

5. Other ways to structure your REST API

There is many other specifications. This guide is not intended to be the one, it's just a good way, from my point of view and experience, to design a REST API.