restembeddinghypermedia

Include / embed vs. link in RESTful APIs


So the general pattern for a RESTful API is to return a single object with embedded links you can use to retrieve related objects. But sometimes for convenience you want to pull back a whole chunk of the object graph at once.

For instance, let's say you have a store application with customers, orders, and returns. You want to display the personal information, all orders, and all returns, together, for customer ID 12345. (Presumably there's good reasons for not always returning orders and returns with customer personal information.)

The purely RESTful way to do this is something like:

  1. GET /
    • returns a list of link templates, including one to query for customers
  2. GET /customers/12345 (based on link template from /)
    • returns customer personal information
    • returns links to get this customer's orders and returns
  3. GET /orders?customerId=12345 (from /customers/12345 response)
    • gets the orders for customer 12345
  4. GET /returns?customerId=12345 (from /customers/12345 response)
    • gets the returns for customer 12345

But it'd be nice, once you have the customers URI, to be able to pull this all back in one query. Is there a best practice for this sort of convenience query, where you want to transclude some or all of the links instead of making multiple requests? I'm thinking something like:

GET /customers/12345?include=orders,returns

but if there's a way people are doing this out there I'd rather not just make something up.

(FWIW, I'm not building a store, so let's not quibble about whether these are the right objects for the model, or how you're going to drill down to the actual products, or whatever.)


Updated to add: It looks like in HAL speak these are called 'embedded resources', but in the examples shown, there doesn't seem to be any way to choose which resources to embed. I found one blog post suggesting something like what I described above, using embed as the query parameter:

GET /ticket/12?embed=customer.name,assigned_user

Is this a standard or semi-standard practice, or just something one blogger made up?


Solution

  • Being that the semantics of these types of parameters would have to be documented for each link relation that supported them and that this is more-or-less something you'd have to code to, I don't know that there's anything to gain by having a a standard way of expressing this. The URL structure is more likely to be driven by what's easiest or most prudent for the server to return rather than any particular standard or best practice.

    That said, if you're looking for inspiration, you could check out what OData is doing with the $expand parameter and model your link relation from that. Keep in mind that you should still clearly define the contract of your relation, otherwise client programmers may see an OData-like convention and assume (wrongly) that your app is fully OData compliant and will behave like one.