Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Link to another resource in a REST API: by its ID, or by its URL?

I am creating some APIs using apiary, so the language used is JSON.

Let's assume I need to represent this resource:

{
    "id" : 9,
    "name" : "test",
    "customer_id" : 12,
    "user_id" : 1,
    "store_id" : 3,
    "notes" : "Lorem ipsum example long text"
}

Is it correct to refer to other resources by their IDs (12, 1, 3), or I should specify the URL of these resources (i.e. /customers/12, /users/1, /stores/3)?

I am not using HATEOAS and I am a bit confused.

like image 433
MeV Avatar asked Jun 22 '15 13:06

MeV


People also ask

What is the URL used for with REST API?

The base URL is the internet host name for the REST API. The resource path is the address to the API resource. Query parameters are name/value pairs passed to the REST API after a ? in the endpoint URL. Query parameters pass inputs to a REST API and are often used to filter, sort, or specify the output format.

How do you reference other resources in JSON?

This Account resource and every other JSON resource will always have an href property, which is the fully qualified canonical URL where that resource resides. Whenever you see an href property, you know you can access that resource by executing a GET request to the resource's URL.


2 Answers

DO include absolute entity URIs in your responses (such as /customers/12 or even http://www.example.com/customers/12).

DO NOT include just an entity's ID (such as 12) in a response, because that way you're forcing clients to put together resource URIs themselves. In order to do that, they would need to have prior knowledge of what URIs there are, and you're losing control over the URI space on the server side.

(Having the client put together an URI is OK if the server instructs the client how, e.g. by sending a URI template along with the ID; but if it did that, it could just as well send the resulting URI.)

See also:

  • Article "REST APIs must be hypertext-driven" by Roy T. Fielding (the originator of REST). Take note especially of these two bullet points:
  • "A REST API should be entered with no prior knowledge beyond the initial URI (bookmark)."
  • "A REST API must not define fixed resource names or hierarchies (an obvious coupling of client and server). Servers must have the freedom to control their own namespace. Instead, allow servers to instruct clients on how to construct appropriate URIs[.]"
  • HAL, which specifies a standard way to put links to related resources into your responses.

  • JSON API — "a specification for building APIs in JSON"

  • The above advice is not just for IDs of other resources (i.e. "foreign keys" such as your customer_id); you'd also turn the resource's own id into a so-called "self link"; see the SO question "What is the importance of the self link in hypermedia APIs?".

Example:

Your original resource could be re-designed as follows:

{
  "type": "foobar",
  "id": "9",
  "links": {
    "self": "//example.com/foobars/9"
  },
  "cashier": {
    "type": "user",
    "id": "1",
    "links": {
      "self": "//example.com/users/1"
    }
  },
  "customer": {
    "type": "customer",
    "id": "12",
    "links": {
      "self": "//example.com/customers/12"
    }
  },
  "name" : "test",
  "notes" : "Lorem ipsum example long text",
  "store": {
    "type": "store",
    "id": "3",
    "links": {
      "self": "//example.com/stores/3"
    }
  }
}

A few things to note:

  • Each resource (the main object being transferred, but also sub-resources) has some self-descriptive meta-data attached to it, such as type, id, links.
  • Sub-resources can include partial or complete data. As long as the self-link is there, the client knows where to get the complete resource.
  • The type might seem somewhat redudant; often, you implicitly know what kind of object to expect. This property can help in validation, and also gives you the opportunity to distinguish between object type and role (e.g. cashier is-a user in the above example).
like image 160
stakx - no longer contributing Avatar answered Oct 02 '22 15:10

stakx - no longer contributing


I have had a look of other popular APIs (Facebook, Spotify) and I believe the following one is the best way to do it:

{
   "id" : 9,
   "name" : "test",
   "customer" : {
      "id": 12,
      "href": "/customers/12"
   },
   "user" : {
      "id": 1,
      "href": "/users/1"
   },
   "store" : {
      "id": 3,
      "href": "/stores/3"
   },
   "notes" : "Lorem ipsum example long text"
}
like image 27
MeV Avatar answered Oct 02 '22 15:10

MeV