What are the best practices to add metadata to a RESTful JSON response?

You have several means to pass metadata in a RESTful API:

  1. Http Status Code
  2. Headers
  3. Response Body

For the metadata.status, use the Http Status Code, that’s what’s for!
If metadata is refers to the whole response you could add it as header fields.
If metadata refers only to part of the response, you will have to embed the metadata as part of the object.DON’T wrap the whole response in an artifical envelope and split the wrapper in data and metadata.

And finally, be consistent across your API with the choices you make.

A good example is a GET on a whole collection with pagination. GET /items
You could return the collection size, and current page in custom headers. And pagination links in standard Link Header:

Link: <https://api.mydomain.com/v1/items?limit=25&offset=25>; rel=next

The problem with this approach is when you need to add metadata referencing specific elements in the response. In that case just embed it in the object itself. And to have a consistent approach…add always all metadata to response. So coming back to the GET /items, imagine that each item has created and updated metadata:

{
  items:[
    {
      "id":"w67e87898dnkwu4752igd",
      "message" : "some content",
      "_created": "2014-02-14T10:07:39.574Z",
      "_updated": "2014-02-14T10:07:39.574Z"
    },
    ......
    {
      "id":"asjdfiu3748hiuqdh",
      "message" : "some other content",
      "_created": "2014-02-14T10:07:39.574Z",
      "_updated": "2014-02-14T10:07:39.574Z"
    }
  ],
  "_total" :133,
  "_links" :[
     {
        "next" :{
           href : "https://api.mydomain.com/v1/items?limit=25&offset=25"
         } 
   ]
}

Note that a collection response is an special case. If you add metadata to a collection, the collection can no longer be returned as an array, it must be an object with an array in it. Why an object? because you want to add some metadata attributes.

Compare with the metadata in the individual items. Nothing close to wrapping the entity. You just add some attributes to the resource.

One convention is to differentiate control or metadata fields. You could prefix those fields with an underscore.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)