Monday, December 17, 2018

Consuming Hypermedia APIs vs The Other Guys

API consumption has come a long way in the last few years. The industry has seen traditional commerce APIs revolve around catalog navigation, search, product information, checkout, etc. However, the industry is constantly changing and growing for the better. With the movement toward hypermedia REST level 3 APIs the ecommerce industry has once again adopted a modern trend in API layers and sparked the progression to these new technologies.

For readers who have only consumed REST level 3 APIs, it is worth noting that a lot of ecommerce vendors still have not adopted hypermedia APIs into practice and are working on legacy Level 1/2 API layers.

API consumption can be broken down into three segments:

  • Readability
  • Invocation
  • Operation

Readability

APIs need to be readable for developers – allowing them to understand the actions they’re performing in anticipation of the next possible requests they can make. When these APIs are presented strictly through some documentation, how is flow and adoption maintained by external developers? If they’re reading through documentation, it will have to document all the possible flows that a developer may hit and hope that enough documentation was provided to cover all the edge cases. Swagger specifications can only get developers so far with technical API documentation, as the various options/parameters must still be relayed in some sort of manner, so they can be understood and then memorized by developers for later consumption.

Consider the alternatives of a REST Level 3 API. The API layer itself begins at the top-most root layer, of which returns all the possible services that can be subsequently invoked. The principal of hypermedia APIs is that developers don’t need to memorize what they’re attempting to use, only that they want to perform a particular action that is part of a pre-defined flow.

Memorization of lengthy documentation becomes a thing of the past and it becomes clear that a Level 3 API is much more readable and easier to consume simply by invoking the various levels returned such that documentation required by developers can be very minimal.

Invocation

Here’s an example of the common flow for checkout (for sake of the example, ignore the credential tokens passed in headers):

Add product to cart
POST
https:///wcs/resources/store//cart
Body: {“x_inventoryValidation”:”true”,”orderId”:”.”,”orderItem”:[{“quantity”:”1″,”productId”:””}],”x_calculateOrder”:”1″}
Create billing/shipping address & info
POST
https:///wcs/resources/store//person/@self/contact
Body:{“country”:”Canada”,”state”:”Ontario”,”addressLine”:[“123 Street St”,””],”nickName”:””,”email1″:”test@test.com”,”firstName”:”Shaun”,”lastName”:”Mahar”,”zipCode”:”M4B1b7″,”city”:”Toronto”,”phone1″:”123-123-123″,”addressType”:”ShippingAndBilling”}
Set shipping address & info for order
PUT
https:///wcs/resources/store//cart/@self/shipping_info
Body: {“x_calculationUsage”:”-1,-2,-3,-4,-5,-6,-7″,”orderId”:”.”,”addressId”:””,”x_calculateOrder”:”1″,”x_allocate”:”***”,”x_backorder”:”***”,”x_remerge”:”***”,”x_check”:”*n”}
Set payment method & amount
POST
https:///wcs/resources/store//cart/@self/payment_instruction
Body: {“orderId”:””,”piAmount”:””,”billing_address_id”:””,”payMethodId”:”COD”}
Prepare cart for Checkout
PUT
https:///wcs/resources/store//cart/@self/precheckout
Body: {“orderId”:”.”}
Submit order
POST
https:///wcs/resources/store//cart/@self/checkout
{“orderId”:”.”}

Memorizing the possible arbitrary parameters and invocation URLs of the above requests can be quite difficult. A front-end consumer of these APIs may be completely unaware of what order these calls must be invoked in, and which parameters are mandatory — unless they’re thoroughly documented. Consider `x_calculateOrder` and `x_calculationUsage` as examples of these arbitrary parameters. Order calculation in this particular API is used to calculate the total charges for the order, and will only be invoked if `x_calculateOrder` is set to ‘1’. Rather than using a boolean, or checking whether or not the parameter is even passed, the API uses a string representation of 0/1 – hence passing 0 will not invoke a re-calculation whereas a 1 will, and a null value will fail the request altogether. Imagine how confusing this may be to understand and adopt from a front-end perspective. Now consider `x_calculationUsage`, which is a comma-delimited string of the calculation code representation for the type of calculation to be performed on the order (tax, shipping, order, etc). Rather than accepting an array of these values in with meaningful codes, the API requires a formatted string representation of the parameter with numeric values that correspond to identifiers only provided within documentation. A better option to this process would be to have optional body parameters for each independent calculation usage code, and meaningful identifiers that correspond to the calculation usage requested. Having these mandatory parameters without defaults and true type representations can cause further confusion during adoption of these services.

Now assuming the front-end figures out the order and makes these calls in the sequence required, there’s still the matter of consuming the responses of these APIs and passing in the required information back to the next subsequent call to be made. In the Level1/2 behavior, this process becomes a burden for the consumer as any data pertaining to the context of the order/user must be managed by the client rather than the server at a point and time basis.

Taking a closer look at the step “Create billing/shipping address & info”, added address information returns an ID in the response corresponding to the address ID. The developer (as the client) has to pass that address ID into “Set shipping address & info for order”, despite just creating the address as part of the order. Any requirements/failures in requests to these APIs are only indicative to the client through response codes/messages, which only helps after the fact of the request actually being made and not prior. An accumulation of these small processes take time away from front-end development that could be spent elsewhere, but rather it’s spent on tasks to simply understand an API structure and then ensure the invocation is formed correctly.

Contrasted to a Level 3 API, the entire checkout process becomes chained together in a structured flow that a front-end can consume simply by invoking the top-level requests required, then following the chain of responses to achieve the purpose intended by the client flow. Particularly to entering address information, we receive advisor messages to advise client developers, indicating that certain information is required for the checkout process.

Consuming Hypermedia APIs vs The Other Guys_figure 1Figure. 1

These messages can be consumed by the client when consuming the checkout flow to display some appropriate feedback from the API layer for a front-end to understand why a subsequent request may fail. An example following below, as an advisor message is presented directly within the purchase form to indicate the submit action for an order is blocked due to required payment information missing from the order. This in turn lets the front-end know an action must be performed before the request may even be processed and avoids the client having to submit a request simply for the sake of acting on a response code, which would be the traditional method in a Level 1/2 API structure.

Consuming Hypermedia APIs vs The Other Guys_figure 2Figure. 2

Guiding a front-end through API consumption helps for faster adoption and encourages less error-prone design through guessing outcomes of an API based on the actions a front-end may perform.

Consider the next step, to add and select an address as part of the checkout flow. Compared to what is seen in the Level1/2 API structure, the possible options available in a Level 3 response is to create an address through an address submission form. It is clear from the following example how the API tells exactly what parameters it needs and what the subsequent actions/steps to perform are after completing the necessary step.

Consuming Hypermedia APIs vs The Other Guys_figure 3Figure. 3

Then, the URL to invoke to select a particular address. Once again, this eliminates the guess work required by the client to process this flow in a structured and expected manner.

Consuming Hypermedia APIs vs The Other Guys_figure 4Figure. 4

Operation

A REST API’s goal is to be able to perform actions without having any dependency on the client invoking it. If the client must compensate for features which the service cannot perform, then the service itself may be lacking a certain feature to begin with. Think for example the ability to iterate through and display multiple products within an ecommerce API, or even retrieving the current cart and proceeding through a checkout flow. Both of these flows appear to be fairly straight-forward, however differences between API structure can affect the front-end’s consumption of the services.

Reflecting on the following examples:

Set payment method & amount
POST
https:///wcs/resources/store//cart/@self/payment_instruction
Body: {“orderId”:””,”piAmount”:””,”billing_address_id”:””,”payMethodId”:”COD”}
Prepare cart for Checkout
PUT
https:///wcs/resources/store//cart/@self/precheckout
Body: {“orderId”:”.”}
Submit order
POST
https:///wcs/resources/store//cart/@self/checkout
{“orderId”:”.”}

It’s clear that in this phase of the checkout flow, a user is setting a payment method for an order, preparing their cart for checkout (by means of validating inventory availability), then submitting their order. Notice that the order ID is required to be passed for every step within this process. In addition to this putting burden on the front-end to manage the current order identifier and propagate it to all subsequent requests in the checkout, it also would not make sense to require it in the design of a single-cart checkout flow. This is where the API’s capability to maintain user context will greatly improve the structure of this service. Additionally, either of these flows were to return an HTTP status code other than a 200OK, hence the step has failed and the step was not completed. This level of assumption is exactly what the front-end must make in this Level 1/2 REST API behavior.

However, in a REST Level 3 API design, the API would be able to understand the current shopper’s context and maintain the order information for the shopper as they proceed through a checkout flow. Looking at the full order response of our Level 3 API from Figure 5 below, we can see the entire response already contains these pre-constructed URLs which a client may invoke in order to retrieve or persist additional information pertaining to a certain order. These URLs already associate the context of the current shopper’s order with the shopper token that will be passed into the API requesting this information.

Consuming Hypermedia APIs vs The Other Guys_figure 5Figure. 5

These common scenarios of the API handling the association between an order identifier and shopper token spark the question of “why would it be done any other way”?. Well the fact of the matter is that following a hypermedia API design enables back-end services to maintain the user context in a solution where the client does not have to retain this information for themselves, but solely rely on consuming the flow presented by the service itself for the current user.

The examples above illustrated shifting the developer mindset to a modern Level 3 API. These are strong influences ensuring services are adoptable by developers in a timely fashion, with no dependency on the front-end’s capabilities.

 

The post Consuming Hypermedia APIs vs The Other Guys appeared first on Get Elastic Ecommerce Blog.



from
https://www.getelastic.com/consuming-hypermedia-api

No comments:

Post a Comment