A process oriented approach
The web seems to work well enough, let's design API's the same way
But isn't REST just exposing my DB tables as resources?
Step 1 - Design your process
Step 2 - Design your process!
Step 3 - Design your process!!
Simple!
/coffeetypes GET
/cupsofcoffee GET, POST
/baristas GET
/orders GET, POST
GET /coffeetypes
GET /baristas
POST /cupsofcoffee { coffee_type: ... }
<- { self: /cupsofcoffee/xyz }
POST /orders { cupsofcoffee: [ xyz ], barista: ... }
What's missing?
State diagram, flow chart, use case, BPMN, words, whatever
Base design decisions on what the API user wants to achieve
Operations: Choose coffee type, order with barista, and pay
/coffeetypes GET
/quote GET
/orders (or /payments) GET, POST
Maybe /baristas? GET
This is essential
GET /coffeetypes
GET /quote?coffeetype=xyz&quantity=2
<- { _links: { place_order: /orders }, ... }
POST /orders { coffee: [ /coffeetypes/xyz: 2 ] }
Don't be afraid to manipulate multiple (or no!) DB tables for one resource
Can't we just use HTML?
Standard on how to format your (JSON) response, containing conventions to combat bike-shedding
http://stateless.co/hal_specification.html
{
"_links": {
"self": { "href": "/orders" },
"next": { "href": "/orders?page=2" }
},
"currentlyProcessing": 14,
"shippedToday": 20,
"_embedded": {
"order": [{
"_links": {
"self": { "href": "/orders/123" },
"basket": { "href": "/baskets/98712" },
"customer": { "href": "/customers/7809" }
},
"total": 30.00,
"currency": "USD",
"status": "shipped"
}]
}
}
{
"links": {
"self": "http://example.com/posts",
"next": "http://example.com/posts?page[offset]=2",
},
"data": [{
"type": "posts",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"links": {
"self": "http://example.com/posts/1",
"author": {
"self": "http://example.com/posts/1/links/author",
"related": "http://example.com/posts/1/author",
"linkage": { "type": "people", "id": "9" }
}
}
}],
"included": [{
"type": "people",
"id": "9",
"attributes": {
"first-name": "Dan",
"last-name": "Gebhardt",
"twitter": "dgeb"
},
"links": {
"self": "http://example.com/people/9"
}
}]
}
{
"ID": 1,
"Title": "Program crashes when pressing ctrl-p",
"Severity": 5,
"@links": {
"self": {
"href": "http://issue-tracker.org/issues/1"
},
"up": {
"href": "http://issue-tracker.org/projects/1",
"title": "Containing project"
},
}
"@actions": {
"project-create": {
"type": "json",
"href": "http://issue-tracker.org/mason-demo/projects",
"title": "Create new project",
"schemaUrl": "http://issue-tracker.org/mason-demo/schemas/create-project"
}
}
The original document:
{
"baz": "qux",
"foo": "bar"
}
The patch:
[
{ "op": "replace", "path": "/baz", "value": "boo" },
{ "op": "add", "path": "/hello", "value": ["world"] },
{ "op": "remove", "path": "/foo"}
]
The result:
{
"baz": "boo",
"hello": ["world"]
}
{
"title": "Example Schema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["firstName", "lastName"]
}
{
"logref": "42",
"message": "A payment method is needed for the creation of an
order. Please retrieve a bill for the selected products to
see which payment methods are available.",
"type": "BAD_REQUEST",
"_links": {
"help": {
"href": "http://shopping-api-docs.sandbox.paylogic.com/orders",
"type": "text/html"
}
}
}
I don't need to write any documentation. My API is discoverable.
If needed, allow client to filter them out (via header or query parameter)
Design ALL error messages your API can generate and document them!
And build in a mechanism for link deprecation
Want to work on a cool API? See http://www.paylogic.com/en/vacancy/
Questions?