Search code examples
restrestful-url

REST API: Resource hierarchy and multiple URI


I work with a banking database, which is structured like this:

Table      Primary Key   Unique Keys          Foreign Keys
-------------------------------------------------------------
BANK       ID            BIC           
CUSTOMER   ID            CUSTNO, PASS, CARD   BANK
ACCOUNT    ID            IBAN                 BANK, CUSTOMER

I want to design a clean REST API, but I run into following problems:

  1. Should I put resources in a hierarchy, or rather flat? The problem with the hierarchy might be that the client only knows the ACCOUNT ID, but does not know the CUSTOMER ID, so how is he supposed to get the resource?
/banks/{id}/customers/{id}/accounts{id}
or
/banks/{id}
/customers/{id}
/accounts{id}
  1. The primary key in each table is the database ID. It is an internal ID and has no business meaning. Is it correct to use it as the default URI of the resource?

  2. Each object has its own set of unique keys. For example, CUSTOMER can be identified by his CUSTNO, PASS or CARD. Each client only has a subset of these keys. Should I define a sub-resource per key or provide a lookup service that will give the proper URI back?

/customers/id/{id}
/customers/custno/{custno}
/customers/pass/{pass}
/customers/card/{card}
or
/lookup/customer?keyType=card&keyValue=AB-303555
 (gives back customer {id})

I am asking what is the truly RESTful way, what is best practice. I haven't found proper answers yet.


Solution

  • I am asking what is the truly RESTful way, what is best practice.

    REST doesn't care what spellings you use for your identifiers.

    /ef726381-dd43-4017-9778-83cee2bbbd93
    

    is a perfectly RESTful URI, suitable for any use case.

    Outside of some purely mechanical concerns, general purpose consumers treat a URI as a single opaque unit. There's no notion of a consumer extracting semantic information from the URI -- which means that any information encoded into the identifier is done at the server's discretion and for its use alone.

    For cases where information known to the client needs to be included in the target-uri of the request, we have URI Templates, which are a sort of generalization of a GET form in HTML. So a way to think about your problem is to consider what information the client has, and how they would put that information into a form.

    HTML's form processing rules are pretty limiting -- general URI templates have fewer constraints.

    /customers/id/{id}
    /customers/custno/{custno}
    /customers/pass/{pass}
    /customers/card/{card}
    

    Having multiple resources sharing common information is normal in REST -- your resource model is not your data model. So this could be fine. It's even OK to have multiple resources that share representations. You could have them stand alone, or you could have them share a Content-Location, or a canonical link relation, or you could simply have those resources redirect to the canonical resource.

    It's all good.

    So you mean if a UUID can be a valid URI, then a table autonumber key can be too?

    Yes, exactly.

    Note that if you want the lifetime of the URI to extend beyond the lifetime of your current implementation, then you need to design your identifiers with that constraint in mind. See Cool URIs Don't Change.

    The clients don't care what the URI is, they just want the link to work again when they need it.