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?