blog.negative9.net/contents/articles/pragmatic-api-design/index.md

234 lines
7.1 KiB
Markdown
Raw Normal View History

2018-03-11 11:15:42 +00:00
---
title: Pragmatic API Design
author: geoff-doty
date: 2016-08-12
template: 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)](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32)
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 <code>/resources/</code>|<b>List</b> the URIs and perhaps other details of the collection's members.|<b>Replace</b> the entire collection with another collection|<b>Create</b> a new entry in the collection. The new entry's URI is assigned automatically and is usually returned by the operation|<b>Delete</b> the entire collection|
|Element <code>/resources/item</code>|<b>Retrieve</b> a representation of the addressed member of the collection, expressed in an appropriate Internet media type|<b>Replace</b> the addressed member of the collection, or if it doesn't exist, <b>create</b> it|Not generally used. Treat the addressed member as a collection in its own right and <b>create</b> a new entry in it|<b>Delete</b> 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