Pragmatic API Design

Written by Geoff Doty

The API design should be organized around REST principles, however to maintain both user and developer sanity it should also be pragmatic, thus we call it RESTful design, as it may not conform to all the REST architecture design tenets.

Launch like a start-up, scale like an enterprise

API’s should have predictable, resource-oriented URLs and to use HTTP-based response codes to indicate API errors. Leveraging built-in HTTP features, like HTTP authentication and HTTP verbs, allows off-the-shelf HTTP clients to work out-of-the-box.

NOTE: cross-origin resource sharing only applies to browsers, and allows you to interact API’s directly from a client-side web application

By default, all API responses should return JSON, including errors

Authentication / Authorization

Basic Authentication

  • username:password should be key:password

Case for Bearer Tokens (JWT)

Authorization based on RFC 6750 Bearer Tokens, a subset of the OAuth 2 framework. The bearer token is a Javascript Web Token (JWT)

The Authentication / Authorization process first requires you have authenticated against the trusts API resource, then you use that Token to authorize future API requests.

Example

POST /tokens
{
    "username": "<your username>",
    "password": "<your password>"
}

This will return the JWT security token that will be used for the remainder of the requests

{
    "token": "mF_9.B5f-4.1JqM"
}

You authenticate to the API by providing one of your API keys in the request. You can manage your API keys from your account. You can have multiple API keys active at one time.

Your API keys carry many privileges, so be sure to keep them secret!

Authorization to the API occurs via a Javascript Web Token (JWT). Provide your API JWT token as the Authorization HTTP Header

GET /resource HTTP/1.1
Host: api.assistrxlabs.com
Authorization: Bearer mF_9.B5f-4.1JqM

All API requests must be made over HTTPS. Calls made over plain HTTP will fail. You must provide the Authorization header for all requests.

Authentication

You authenticate to the API by providing one of your API keys in the request. You can manage your API keys from your account. You can have multiple API keys active at one time. Your API keys carry many privileges, so be sure to keep them secret!

Authentication to the API occurs via HTTP Basic Auth. Provide your API key as the basic auth username. You do not need to provide a password.

All API requests must be made over HTTPS. Calls made over plain HTTP will fail. You must authenticate for all requests.

Endpoints

To make the API as explorable as possible, accounts have test-mode API keys as well as live-mode API keys. These keys can be active at the same time. Data created with test-mode credentials will never hit the credit card networks and will never cost anyone money.

Example Endpoints

Development

https://api.example.com/v1/

Production

https://api.example.com/v1/

RESTful Verbs (pragmatic)

Core RESOURCES should map HTTP VERBS to CRUD operations

  • GET = read resource
  • POST = create resource
  • PUT = replace resource
  • DELETE = delete resource (or mark as deleted – never really delete)
Resource GET PUT POST DELETE
. read update create remove
Collection /resources/ List the URIs and perhaps other details of the collection’s members. Replace the entire collection with another collection Create a new entry in the collection. The new entry’s URI is assigned automatically and is usually returned by the operation Delete the entire collection
Element /resources/item Retrieve a representation of the addressed member of the collection, expressed in an appropriate Internet media type Replace the addressed member of the collection, or if it doesn’t exist, create it Not generally used. Treat the addressed member as a collection in its own right and create a new entry in it Delete the addressed member of the collection

NOTE: PATCH could update a resource, save for browser limitations

URL Structure

  • first part of api should be version v1, v2 and not 1.2, or v1.5 ect…
  • Additional URLs for
    • api.example.com
    • developers.example.com
    • documents.example.com

For Example

https://api.example.com/v1/users

NOTE: as your developing an API, you can use ‘/v0’ as your living API version

URI Resources

  • no verbs
  • plural resource names
  • /[api version]/[resource]/[identifier]
    • /v1/cases/id/
    • /v1/jobs/id/
Resource Relationships (optional)
  • resource/id/resource
    • /v1/jobs/id/applicants/
    • /v1/jobs/id/applicants/id

Actions

  • verbs not nouns
    • /convert?from=EUR&to=CNY&amount=100
    • /search?q=???
    • /count
/search?q=item1+item2

this can be on a resource:

/v1/docs/search?q=hash

or on an item

/v1/docs/1234/search?q=sample

Response Objects

{
    "data": []
    "pagination": {}
}

Error Handling (extended)

Code Description
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error

Common Codes

Code Result Summary
200 OK Success
400 Bad Request Often missing a required parameter
401 Unauthorized No valid API key provided.
402 Request Failed Parameters were valid but request failed.
404 Not Found The requested item doesn’t exist.
500
501 Not Implemented something went wrong on API’s end.

Not all errors map cleanly onto HTTP response codes, but you should not throw out the HTTP responses codes, but rather extend.

  • {code: , message:, link:}
    • code = extended http error ie 401-10 or 40110
    • message = error message
    • link = url to documentation

standard js error/exception object

{name: "", message: ""}

Error Suppression

  • suppress error codes per request
    • suppress_response_code = FALSE

Partial Responses

?fields=name,date,street

Pagination

All top-level API resources have support for bulk fetches — “list” API methods. For instance you can list people, list places, and list things. These list API methods share a common structure.

The API utilizes cursor-based pagination, using the parameter offset. Pass offset to dictate where in the list you would like to begin (see below).

  • limit
  • offset

Examples

https://api.example.com/v0/users?offset=0&limit=10

Return Data Formats

?format=json

or

.json

Variable Naming

lowerCamelCase (ie follow javascript style for json api)

Reserved Words

count as a reserved word

/v1/docs/count

Fake Response Method

  • ?method=put
  • ?method=delete