7.1 KiB
title | author | date | template |
---|---|---|---|
Pragmatic API Design | geoff-doty | 2016-08-12 | article.jade |
Launch like a start-up, scale like an enterprise
Introduction
The API design should be organized around REST principles, however to maintain both user and developer sanity it should be pragmatic, thus we call it RESTful design, as it may not conform to all the full REST architecture design tenets.
This document summaries RESTful design tenets.
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, however this was once a browser support issue
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
/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