Toward a roadmap for our API

Standardising the structure of our JSON reponses

One thing that would be good to clear up is the consistency in the datastructures we return. There’s a widely used convention in putting all primary data within a top-level field called data:, but we don’t use it. It also means you can nicely put any metadata or secondary data alongside the primary records. We have some inconsistency in this respect.

When rendering multiple objects in a response, we sometimes render the array as the response itself, and sometimes render the array inside a top-level field with the name of the object (which is maybe not a great idea, and it means the field containing the data is different for every endpoint).

So for example, the output of the Api::CustomersController#index action (here) currently looks like this:

[
  <customer 1>,
  <customer 2>,
  <customer 3>
]

Whereas the Api::OrdersController#index action (here) currently looks like this:

{
  orders: [     # Resources in a top-level field (good) with a changeable name (bad).
    <order 1>,
    <order 2>,
    <order 3>
  ],
  pagination: <pagination data>  # Secondary data can be added (good)
}

So the convention would be to return primary records in a data field, and use that consistently for both single and multiple records, eg:

{
  data: <single object or array of objects>,
  pagination: <pagination data (for example)>
}

This means secondary metadata can be added in any response. It could be pagination data, or it could be other things. For example, if a record has linked records such as adjustments on a line item, it’s common to return some links to other API endpoints where those records can be accessed.

Also; successful responses should contain the data field, error responses contain an errors field, but responses never contain both. I think we already do this errors bit fairly consistently. :+1:

How does that sound?

1 Like