Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

There are two default responses. One is for responses which return a singular object, and one is for response which return multiple objects. If a response is known to return one and only one object, you should use the scalar response object. If a response may contain zero or more objects, you should always use the Vector response object. There are cases where you should return a 404 if no objects are found, but there are also cases where an empty list (with the response metadata) is also useful, namely queries. In general, a scalar response should always return a non-empty object, because an empty object should always be a 404. This makes client code which is merely performing an existence check a bit simpler.

Scalar Response:

{
        "type": "object", 
        "properties": {
            "result": {
                "type": "object",
                "required":true
            },
            "metadata": {
                "type": "object",
                "required":false
            }
        }
    }

Vector/Array Response:

{
        "type": "object", 
        "properties": {
            "results": {
                "type": "array",
                "required":true
            },
            "metadata": {
                "type": "object",
                "required":false
            },
            "range": {
                "type": "object",
                "required":false
            }
        }
    }}

Response Ranges, Pagination, and Intervals:

There are several possibilites to use for "range" metadata. They keywords I've used are somewhat arbitrary, but I just wanted to show the several ways you can represent a "range" or responses. In practice, I believe the first slice format is easiest to use across different types (timestamps, integers) and easy translate to database notation (even if it requires a tiny bit of math). The alternatives have the benefit that they make more sense if you are using timestamps or strings. The interval type could potentially use ISO 8601 interval notation instead.

Pagination

"range":{
        "type": "pagination":,
        "page": 2,
        "per_page": 20,
        "pages": 24      # Optionaloptional
    }

Slice

"range": {
        "type":"slice",
        "offset":200,
        "max",: 20, # optional, alternatively     # optional, alternatively "count"
        "length":400 #optional
    # optional
}

Slice Alternative 1:

"range": {
        "type":"slice",
        "offset": 200,
        "limit",: 220, #optional
   # optional
    "length": 400 #optional
   # optional
}

Slice Alternative 2:

"range": {
        "type": "slice",
        "start": 200,
        "stop": 220, 220 #optional
   # optional
    "length": 400 #optional
   # optional
}

Interval

"range":{
        "type":"interval",
        "from":"2014-12-01",
        "to":"2015-01-01",
        "latest":"2015-03-01" #optional
  #  optional
}

Errors:

HTTP responses with error details should use a 4XX status code to indicate a client-side failure (such as invalid authorization, or an invalid parameter), and a 5XX status code to indicate server-side failure (such as an uncaught exception).

...

Because of this, the response body should include enough information for the client to recognize the source of the error. When you include a response entity, your client can evaluate the status code (first and foremost), and then it can attempt to evaluate the response. If it discover the error response isn't what it expected, the client can make additional assumptions about the error response in general, such as treating a 404 as a server error.

Schema

{
        "type": "object", 
        "properties": {
            "exception": {
                "type": "string",
                "required":true
            },
            "message": {
                "type": "string",
                "required":false # Might be required
            },
            "cause": {
                "type": "string",
                "required":false # Might be required
            }
        }
    }
Example
{
        "exception":"ClientException",
        "message":"Description of the error.",
        "cause":"[Detailed Stack Trace]"
    }

Examples

...

GET /users/bvan

Resource not Found        
    Status: 404
    Content-Type: application/json
    {
        "exception":"UserNotFound" 
        "message":"The user 'bvan' does not exist"
    }

...

Internal Application Error

    Status: 500

    Content-Type: application/json
    {
        "exception":"DatabaseException" 
        "message":"Unable to acquire a connection to the database"
        "cause":"[stack trace]"
    }

Intermediary -> Application Error

    Status: 500

    Content-Type: text/html

    <html>
      <body>
        Your application is configured correctly but isn't responding.
      </body>
    </html>

Applications not confiured or Application Server Down

    Status: 404
    Content-Type: text/html

    <html>
      <body>
        I don't think you configured your application is running or confgiured
      </body>
    </html>

...