Resource links vs. IDs for hierarchical resources


#1

We have a “hierarchy” of resources: An order has a to-many relationship with order lines, with an order line being a “fully contained” resource in the sense that an order line does not make sense outside of an order (i.e., doesn’t make sense on its own). An order line similarly contains another resource A, which similarly contains B, which similarly contains C. Each of them do not make sense outside of their “parent” resource.

We’re building an API over a legacy system, and in order to retrieve an order line, the server needs to know the order ID to effectively look it up. Therefore, to retrieve e.g. an order line, I can’t direct clients to /orderlines/<guid>, because that gives the server no information on which order it belongs to.

Currently, I have decided that order line IDs have the format <orderId>/<lineNumber>, e.g. "id": "AB1234567/1". This makes the order line ID globally unique. Furthermore, I have designed routing so that a specific order line can be retrieved from /orderlines/<orderId>/<lineNumber>. Similarly, A, B, and C resources have IDs <orderId>/<lineNumber>/<A_id> etc. and can be retrieved from /As/<orderId>/<lineNumber>/<A_id> etc. These are returned as self links on the resources.

Coincidentally then, the ID of each of the objects are then what is placed after the collection endpoint (/orderlines, /As, etc.), which seems to be best practice. However, this naïvely ignores the fact that the slashes in the ID should be URL encoded, e.g. an order line with ID AB1234567/1 should be accessible not under /orderlines/AB1234567/1 but under /orderlines/AB1234567%2F1. So I’m wondering if it’s necessary to make resources accessible under an endpoint with the format /<resource-type>/<resource-ID>. Could I choose to have an order line with ID foo and choose to place it under /orderlines/<orderId>/foo?

I also know I can do e.g. /orders/<orderId>/orderlines/<lineId>, but that quickly falls apart when requesting a C resource: /orders/<orderId>/orderlines/<lineId>/As/<A_id>/Bs/<B_id>/Cs/<C_id> (and of course, the real relationship names are longer than a single letter).

Are there other ways to solve this problem?

Are there other useful considerations for hierarchical resources?