resturl-design

REST combined all records and one record


I am building REST endpoint that has invoices. I need to build both list of all invoices in 3 levels of description (detailed which is default, sums only and one with customers information).

I also need to build endpoint for individual invoices that will contain much more information in it.

I was thinking

GET /invoices               <-- detailed
GET /invoices?mode=sums     <-- sums
GET /invoices?mode=customer <-- sums
GET /invoices/TNTV002793849 <-- individual invoice

But I have seen others implement two different ones maybe

GET /invoices/detailed     <-- detailed
GET /invoices/sums         <-- sums
GET /invoices/customer     <-- sums
GET /invoice/TNTV002793849 <-- individual 

I already know from reading that all of these can count REST and if anything I need to make one with links so that it is HATEOAS which there is no real reason why I need it.

My question is more from practical point of view for example which is easier to implement, safer, and more common by convention.

I will probably use python with Flask for server and one client I write will be JQuery if that matters.


Solution

  • As you mentioned yourself, it doesn't really matter. So what follows is mostly an opinion.

    The caveat with using /invoice/TNTV002793849 and /invoices/ is that you have 2 different namespaces for the same concept. I think that's somewhat unusual and unexpected. It's nice to be able to remove the last portion of a url and get a logical parent.

    So I would opt to use the same top-level namespace. I would personally also use 'singular' for everything instead of plural form, but that is also just a mild preference.

    The question then remains is, if everything uses a prefix of 'invoices' should you have both /sums and /TNTV002793849. The biggest question is, could there be a collision? Could you have an invoice that is named sums. If this is true, then this is a hard no.

    If ?mode=sums and ?mode=customer modes are very much the same data as the parent /invoices, you might also want to use content-negotation. If they are drastically different, then I would feel that the ?mode= is not as appropriate, and would just have completely separate endpoints.

    So all of these together, would lead me to:

    GET /invoice               <-- full list of invoices
    GET /invoice/{id}          <-- a specific invoice
    GET /invoice-summary       <-- Some report
    GET /customer/{id}/invoice <-- All invoices for a specific customer
    

    I don't know all of these guesses specifically apply to you, but I hope there's enough here to give you confidence in your decisions.