Skip to content

dft street manager doc 0005 api design documentation

stevenalexander edited this page Feb 16, 2018 · 3 revisions

API design and documentation

Author(s) - Steven Alexander

GDS have published API data and technical standards, our service should follow these were possible:

General guidelines for RESTful URLs

  • A URL identifies a resource. (A resource is a representation of some part of a business or problem domain)
  • URLs should include nouns, not verbs.
  • Use plural nouns only for consistency (no singular nouns).
  • Use HTTP verbs (GET, POST, PUT, DELETE) to operate on the collections and elements.
  • You shouldn’t need to go deeper than resource/identifier/resource.
  • Put the version number at the base of your URL, for example http://example.com/1.0/path/to/resource.
  • URL v. header:
    • If it changes the logic you write to handle the response, put it in the URL.
    • If it doesn’t change the logic for each response, like OAuth info, put it in the header.
  • Specify optional fields in a comma separated list.
  • Formats should be in the form of api/v2/resource/{id}.json
  • For resources consisting of multiple words use this form api/accounts/mortgage-invoices/1234 with hyphens and all lowercase rather than camelCase

Good URL examples

Bad URL examples

Content types

Where supported, content which can be returned in multiple types should be negotiated using the 'Accept' HTTP header, e.g.

GET http://example.org/api/magazine/1234
Accept: text/json

Should return a JSON representation of the resource.

GET http://example.org/api/magazine/1234
Accept: application/xml

Should return an XML representation of the resource.

HTTP Verbs

HTTP verbs, or methods, should be used in compliance with their definitions under the HTTP/1.1 standard. The action taken on the representation will be contextual to the media type being worked on and its current state. Here's an example of how HTTP verbs map to create, read, update, delete operations in a particular context:

  • GET: Obtains either a list of items of a single item and never changes data.
    • This should always be a safe operation, that is, a GET does not affect the data it acts on.
  • POST: Creates an object: inputs should be in the request body, not the url. The response body should then include the created object.
  • PUT: Updates data
  • DELETE: Deletes data

Response

  • No values in keys
  • No internal-specific names (e.g. "node" and "UserAuthBaseImpl") - values returned should meaningfully describe the objects involved
  • Metadata should only contain direct properties of the response set, not properties of the members of the response set

Good examples

No values in keys:

  "Organisations": [
    {
      "id": "125",
      "name": "Farms Ltd"
    }, {
      "id": "834",
      "name": "Pigs and Chickens"
    }
  ]

Bad examples

Values in keys:

  "tags": [
    {"125": "Farms Ltd"}, 
    {"834": "Pigs and Chickens"}
  ]

HTTP Status Codes

Generally, HTTP status codes can be used to infer the result of the operation using this guide: 2XX = OK, 3XX = moved, 4XX = client error, 5XX = server error.

When defining an API endpoint, be clear in the documentation supplied as to which status codes your resource can return and in which situations. Bear in mind that many clients' default behaviour is to treat any non-200 status code as an error, so while 201 and 204 may be relevant for object creation and deletion, ensure this is clearly annotated for third party clients.

Look at http://httpstatus.es for succinct descriptions of the various HTTP status codes.

It is important that you use the correct classification of response. Remember if a dependency fails, let you consumer know that was what happened, don't just return blank 500 responses for all faults.

Error Handling

Error responses should include the relevant HTTP status code, and a meaningful message in the case of an exception. Avoid exposing implementation details or other data in the error message.

For example, if a request is sent to a POST endpoint that does not have the correct JSON format, an appropriate response should be like:

Status: 400 (BAD_REQUEST)
Response Body:
{
  error: "unable to parse request body as JSON"
}

Try and use the most relevant status code rather than just returning 400 for all requests that failed. For example, a request that fails syntactic validation (can't parse as JSON) should return a 400 BAD_REQUEST but a request that fails semantic validation (future date of birth supplied) should return a 422 UNPROCESSABLE_ENTITY.

Versions

Major changes and product releases should coincide with a major version revision, and minor changes and updates should coincide with a minor version revision. API calls made without the version number included will default to accessing the latest version of the API e.g. if version 2.0 is the latest API version: http://example.org/api/resource/123 will access resource/123 on version 2.0 of the API http://example.org/api/1.1/resource/123 will access resource/123 on version 1.1 of the API Activity monitoring should be used to determine when to decommission an API. When an old version of the API has not been used at all for a significant period of time it should be removed. Note: for now all APIs will be versioned at 1.0 only

Record limits

If no limit is specified, return results with a default limit (this should be set to 20 and defined on the API documentation). To get records 51 through 75 do this: http://example.org/api/magazines?limit=25&offset=50 offset=50 means, ‘skip the first 50 records’ limit=25 means, ‘return a maximum of 25 records’ Ensure that paging/limiting parameters are consistently named across the API, e.g. "limit" vs "pageSize", "offset" vs "startAt". Information about record limits and total available count should also be included in the response. Example:

{
    "metadata": {
        "resultset": {
            "count": 227,
            "offset": 25,
            "limit": 25
        }
    },
    "results": [ ]
}

Health checks

All web and api components should support a /healthcheck and /status endpoint which will return 200 if component is in health state. The health check should check dependencies (e.g. try SELECT 1 from database or call /status on API dependencies) and the status should just return 200 if component is up. This gives a consistent way to check instances are available and healthy that can be used as part of monitoring and CI.

See here for details.

Documentation

As external users will be integrating their systems with our APIs we need to document all publicly exposed endpoints in a form which can be understood by other developers.

Swagger will be used to generate documentation for the API using comments and class definitions in the API code. The Swagger documentation will either be published as static html or hosted directly on the APIs.

Useful links

Clone this wiki locally