# Wednesday, 28 November 2012

I've published an example of a self-documenting REST API to Github (source).

Why a self-documenting REST API?

A typical REST API sample is hosted at http://restdoc-sample.herokuapp.com/hello, using Heroku's embedded Tomcat Java example.

As a Developer, your initial questions may be:

  • "What does the 'hello' endpoint do?"
  • "Does the endpoint support GET, POST, PUT, DELETE?"
  • "What headers and message body payloads does this endpoint support?"

Fortunately, the RESTDoc project has already defined a specification for documenting REST APIs. The intent of RESTDocs is for each endpoint to support the OPTIONS method and return a structured RESTDoc for the particular API endpoint.

Getting back to the Heroku hosted sample, submitting a curl request for the 'hello' endpoint using the OPTIONS method returns the sample RESTDoc below.

curl -X OPTIONS http://restdoc-sample.herokuapp.com/hello

In addition to supporting the OPTIONS method, the github sample also supports appending '/describe' to any API endpoint to view RESTDocs in web browser. Example: http://restdoc-sample.herokuapp.com/hello/describe.

Standardizing on RESTDocs opens up a number of interesting possibilities. Since transitioning away from SOAP, the web development community has lost the ability to auto-generate object proxies for calling web services. Webhook and Enterprise Service Bus (ESB) platforms have lost the ability to auto-discover web service endpoints and their supported messages.

Self-describing REST APIs, using RESTDocs and the OPTIONS method, are a compelling solution for enabling the service oriented enterprise and integrating the cloud.

	{
	  "schemas" : {
	    "http://some.json/msg" : {
	      "type" : "inline",
	      "schema" : {
	        "type" : "object",
	        "properties" : {
	          "id" : {
	            "type" : "string"
	          },
	          "content" : {
	            "type" : "string"
	          }
	        }
	      }
	    }
	  },
	  // Headers can be described at the server level and/or per-method
	  "headers": {
	    "request": {
	      "Authorization": {
	        "description": "This server uses a custom authentication scheme. See http://myapi.com/docs/auth",
	        "required": true
	      }
	    },
	    "response": {
	      "X-RateLimit-Total": {
	        "description": "The number of API calls allowed per-hour"
	      },
	      "X-RateLimit-Remaining": {
	        "description": "Number of requests remaining until next refill"
	      },
	      "X-RateLimit-Reset": {
	        "description": "The time at which X-RateLimit-Remaining will be reset back to X-RateLimit-Total"
	      }
	    }
	  },
	  "resources": [
	    {
	      "id": "HelloMessage",
	      "description": "An example hello message",
	      "path": "/{locale}/{messageId}{?seasonal}", // representing query params with L3 URI templates
	      "params": { // URI parameters descriptions
	        "locale": {
	          "description": "A standard locale string, e.g. \"en_US.utf-8\"",
	          "validations": [ { "type": "match", "pattern": "[a-z]+(_[A-Z]+)?(\\\\.[a-z-]+)?" } ]
	        },
	        "messageId": {
	          "description": "A free-form message string",
	          "validations": [ { "type": "match", "pattern": "[a-z_]+" } ]
	        },
	        "seasonal": {
	          "description": "Whether the message is seasonal.",
	          "validations": [ { "type": "match", "pattern": "^(true|false|yes|no)$" } ]
	        }
	      },
	      "methods": {
	        "PUT": {
	          "description": "Update or create a message",
	          "statusCodes": { "201": "Created" },
	          "accepts": [   // Representations accepted by the method on this resource.
	            { "type": "text/plain" },
	            { "type": "application/json", "schema": "http://some.json/msg" }
	          ],
	          "headers": { // Request headers only, response headers are defined under 'response'
	            "X-User-Token": {
	              "description": "Used to identify the user creating the message"
	            }
	          },
	          "response": { // Response representations this resource/method provides
	            "types": [
	              { "type": "text/plain" },
	              { "type": "application/json", "schema": "http://some.json/msg" },
	            ],
	            "headers": {
	              "Location": {
	                "description": "The URL of the created message"
	              }
	            }
	          },
	          "examples": [
	            {
	              "path": "/en_US/greeting",
	              "body": "Hello, world!"
	            },
	            {
	              "path": "/en_US/greeting",
	              "headers": {"Content-Type": "application/json"},
	              "body": "{\"id\":\"greeting\",\"content\":\"Hello, world!\"}!"
	            }
	          ]
	        },
	        "GET": {
	          "description": "Retrieve a message",
	          "statusCodes": { 
	             "200": "Message retrieved successfully", 
	             "404": "Message not found"
	          }
	        }
	      }
	    },
	    {
	      // This resource has no human-readable documentation, but still provides some info on how to use it.
	      "id": "FallbackLocale",
	      "path": "/fallback/{locale}",
	      "params": {
	        "locale": { 
	          "validations": [ { "type": "match", "pattern": "[a-z]+(_[A-Z]+)?(\\\\.[a-z-]+)?" } ]
	        }
	      },
	      "methods": {
	        "GET": { "statusCodes": { "200": "OK" } },
	        "PUT": { "statusCodes": { "201": "Created" } }
	      }
	    }
	  ]
	}	
Wednesday, 28 November 2012 09:29:03 (Pacific Standard Time, UTC-08:00)
# Tuesday, 13 November 2012

Salesforce recently posted this tantalizing brainteaser question "When do you think Salesforce will reach 1B transactions per day?"

Analyzing the recent numbers from trust.salesforce.com reveals some interesting patterns and trends:

  • Peaks tend to occur most often on a Tuesday
  • Weekend traffic drops to about 1/3rd of weekday activity
  • The average growth between peaks is 0.52% per week
Extrapolating these numbers out reveals that Tuesday, December 18th, 2012 is the highest probability date to hit 1B transactions. But that date is pretty close to the holidays, so it's a tough call.

What is your prediction?

Tuesday, 13 November 2012 22:41:35 (Pacific Standard Time, UTC-08:00)