Search code examples
microservicesdomain-driven-designinvoicepurchase-order

Defining right API endpoint REST/RPC


I am developing an API in a microservice for Invoice entity that takes in input a list of Purchase Order Item (i.e. PO Item) identifiers for ex. PO# + productIdentifier together can be used to identify a POItem uniquely. The response of the API is the invoiced quantity of each PO Item.

Input Model -

input GetInvoicedQuantityForPOItemsRequest {
    poItemIdentifierList : POItemIdentifierList
}

Structures

list POItemIdentifierList {
    
 member : POItemIdentifier

}

structure POItemIdentifier {

   purchaseOrderNumber : String,

   productIdentifier : Long

}

Invoiced Quantity of a POItem = SUM of Quantity of Invoice Items created from that PO Item.

Note : A single PO can be used to create multiple Invoices. An Invoice can be created from multiple POs.

I am quite new to REST and so far we have been using RPC endpoints in our legacy service. But now i am building a new service where i am defining endpoints in REST format (for ex. CreateInvoice has been changed to POST /invoice) and I need some suggestions from Stack Overflow community what would be the right approach for defining the REST endpoint of this API or should we keep it in RPC format itself.

RPC endpoint for this API in legacy system : POST /getInvoicedQuantityForPOItems

Our first attempt on REST for this is : POST /invoice/items/invoicedQuantityForPOItems. But this URI does not look like a Noun it is a Verb.


Solution

  • this URI does not look like a Noun it is a Verb.

    REST doesn't care what spelling conventions you use for your resource identifiers.

    Example: this URI works exactly the same way that every other URI on the web works, even though "it looks like a verb"

    The explanation is that, in HTTP, the semantics of the request are not determined by parsing the identifier, but instead by parsing the method token (GET, POST, PUT, etc). So the machines just don't care about the spelling of the identifier (besides purely mechanical concerns, like making sure it satisfies the RFC 3986 production rules).

    URI are identifiers of resources. Resources are generalizations of documents. Therefore, human beings are likely to be happier if your identifier looks like the name of a document, rather than the name of an action.

    Where it gets tricky: HTTP is an application protocol whose application domain is the transfer of files over a network. The methods in HTTP are about retrieving documents and metadata (GET/HEAD) or are about modifying documents (PATCH/POST/PUT). The notion of a function, or a parameterized query, doesn't really exist in HTTP.

    The usual compromise is to make the parameters part of the identifier for a document, then use a GET request to fetch the current representation of that document. On the server, you parse the identifier to obtain the arguments you need to generate the current representation of the document.

    So the identifier for this might look something like

    /invoicedQuantityForPOItems?purchaseOrder=12345&productIdentifiers=567,890
    

    An application/x-www-form-urlencoded representation of key value pairs embedded in the query part of the URI is a common spelling convention on the web, primarily because that's how HTML forms work with GET actions. Other identifier conventions can certainly work, though you'll probably be happier in the long term if you stick to a convention that is easily described by a URI template.