Skip to main content
Version: 8.2.x

Hypermedia Controls in Cortex

Hypermedia controls provide information on what is required to change the state of a resource and the links to invoke the change. See Martin Fowler’s article on the Richardson REST Maturity Model for a more detailed definition of hypermedia controls.

Cortex has four key hypermedia controls:

  • Lists
  • Forms
  • Selectors
  • Structured Messages

Lists​

A list is a collection resource that returns ordered links to other resources. Cortex lists contain an element link for each resource in the list.

lineitems are a list resource that contain links to each lineitem in the shopper’s cart. In the lineitems resource, each lineitem is represented as an element link with a type set to carts.line-items:

{
"self": {
"type": "carts.line-items",
"uri": "/carts/mobee/gi3tmzrumu4dmljwmzstoljummywcllbme2diljumuzwkolehe2wmzrxme=/lineitems",
"href": "https://cortex.elasticpath.com/cortex/carts/mobee/gi3tmzrumu4dmljwmzstoljummywcllbme2diljumuzwkolehe2wmzrxme=/lineitems"
},
"messages": [],
"links": [
{
"rel": "element",
"type": "carts.line-item",
"href": "https://cortex.elasticpath.com/cortex/carts/mobee/gi3tmzrumu4dmljwmzstoljummywcllbme2diljumuzwkolehe2wmzrxme=/lineitems/g42wenjxgrtgmllgha4ggljumrtdkllcgzswkllfgy2gkm3fmu4gendgmu="
},
{
"rel": "element",
"type": "carts.line-item",
"href": "https://cortex.elasticpath.com/cortex/carts/mobee/gi3tmzrumu4dmljwmzstoljummywcllbme2diljumuzwkolehe2wmzrxme=/lineitems/mq4wgoddhaztallggiyteljugm4geljymq4tgljtgnsdayrxga4gmnjvgi="
},
{
"rel": "cart",
"type": "carts.cart",
"href": "https://cortex.elasticpath.com/cortex/carts/mobee/gi3tmzrumu4dmljwmzstoljummywcllbme2diljumuzwkolehe2wmzrxme="
}
]
}

Pagination​

Lists can be paginated when large numbers of links return. Cortex paginated lists follow this format:

  • An element link for each resource on a page
  • A next link to retrieve the next page of links
  • A previous link to retrieve the previous page of links
  • A type set to elasticpath.collections.pagination, which indicates the list is paginated
  • A pagination object with the following fields:
    • current: The current page number
    • page-size: The number of links on each page, excluding the next/previous pagination links
    • pages: The total number of pages
    • results: The total number of links, excluding the next/previous pagination links
    • results-on-page: The number of links on the current page, excluding the next/previous pagination links

An item keyword search returns a paginated list resource that links to each item found by the keyword search:

{
"self": {
"type": "searches.keyword-search-result",
"uri": "/searches/mobee/keywords/items/qkugwzlzo5xxezdtuvww65tjmwuxaylhmuwxg2l2mwqtk=/1",
"href": "https://cortex.elasticpath.com/cortex/searches/mobee/keywords/items/qkugwzlzo5xxezdtuvww65tjmwuxaylhmuwxg2l2mwqtk=/1"
},
"messages": [],
"links": [
{
"rel": "element",
"type": "items.item",
"href": "https://cortex.elasticpath.com/cortex/items/mobee/qgqvhltnmjptoobzgaytem27onvxk="
},
{
"rel": "element",
"type": "items.item",
"href": "https://cortex.elasticpath.com/cortex/items/mobee/qgqvhltnmjptqojqgezdgnc7onvxk="
},
{
"rel": "element",
"type": "items.item",
"href": "https://cortex.elasticpath.com/cortex/items/mobee/qgqvhltnmjptsmbrgiztink7onvxk="
},
{
"rel": "element",
"type": "items.item",
"href": "https://cortex.elasticpath.com/cortex/items/mobee/qgqvhltnmjptknrxha4tamk7onvxk="
},
{
"rel": "element",
"type": "items.item",
"href": "https://cortex.elasticpath.com/cortex/items/mobee/qgqvhktnmjpteobzgmydgmy="
},
{
"rel": "next",
"type": "searches.keyword-search-result",
"href": "https://cortex.elasticpath.com/cortex/searches/mobee/keywords/items/qkugwzlzo5xxezdtuvww65tjmwuxaylhmuwxg2l2mwqtk=/2"
}
],
"pagination": {
"current": 1,
"page-size": 5,
"pages": 3,
"results": 11,
"results-on-page": 5
}
}

Forms​

Forms are a hypermedia control that creates new resources. Forms are generally rendered on the UI as input fields or submit buttons. With forms, you can discover:

  • The properties required to create a resource
  • The link to invoke the creation of a resource

Cortex forms follow this format:

  • A type that indicates the properties that will be created in the resource
  • Properties that define the data required to create a resource Properties are optional, as some resources don’t require data to create them
  • Links, called action links, invoke the creation of a resource If an action link doesn’t exist on the form, the resource cannot be created

Example: Adding Item to Cart​

The items resource’s addtocartform form link enables you to add the item to a cart, which means a new cart lineitem resource is created for the item. The form’s type application/vnd.elasticpath.cart.lineitem indicates the form creates a cart lineitem resource:

{
"rel": "addtocartform",
"type": "carts.add-to-default-cart-form",
"href": "https://cortex.elasticpath.com/cortex/carts/items/mobee/qgqvhklbnruwk3s7onvxk=/form"
}

Retrieving the addtocartform form link returns the form resource, which lists the properties and actions available for the form. In this example, the form contains:

  • quantity - this property indicates the item’s quantity must be specified before the item can be added to cart
  • addtodefaultcartaction - this action link adds the item to the shopper’s cart
{
"self": {
"type": "carts.add-to-default-cart-form",
"uri": "/carts/items/mobee/qgqvhklbnruwk3s7onvxk=/form",
"href": "https://cortex.elasticpath.com/cortex/carts/items/mobee/qgqvhklbnruwk3s7onvxk=/form"
},
"messages": [],
"links": [
{
"rel": "addtodefaultcartaction",
"type": "carts.add-to-default-cart-form",
"href": "https://cortex.elasticpath.com/cortex/carts/items/mobee/qgqvhklbnruwk3s7onvxk=/form"
}
],
"configuration": {},
"quantity": 1
}

To add the item to the cart, construct a POST request using the form fields as the request body and the URL defined by the action link:

POST /cortex/carts/items/mobee/qgqvhklbnruwk3s7onvxk=/form
Content-Type: application/json
{
"quantity" : 1
}

If the action succeeds, Cortex returns status code 201 CREATED and a Location header with a reference to the newly created resource. If the action succeeds but results in modifying an existing resource rather than creating a new resource, then Cortex returns status code 200 OK and a Location header with a reference to the modified resource.

201 CREATED
Location: https://cortex.elasticpath.com/cortex/carts/mobee/gi3tmzrumu4dmljwmzstoljummywcllbme2diljumuzwkolehe2wmzrxme=/lineitems/g42wenjxgrtgmllgha4ggljumrtdkllcgzswkllfgy2gkm3fmu4gendgmu=

Forms can be used with the FollowLocation request parameter to reduce the number of calls required to retrieve a newly created resource. Followlocation instructs Cortex to retrieve the resource referenced in the Location header and return it in the response body.

Selectors​

Selectors are a hypermedia control that change a resource’s state. Selectors provide a list of predefined options that a shopper can choose from. Once a choice is made through the selector, the resource’s state updates accordingly. Selectors are generally rendered on the UI as radio button groups, combo boxes, or check boxes.

With selectors, you can discover:

  • The options available for a resource
  • The options already selected for a resource
  • The selection-rule that determines how many options can be selected at once
  • The links to make the selection

Cortex selectors follow this format:

  • A name property that identifies which options the selector handles
  • A selection-rule property that identifies the number of options that can be selected at once
  • A choice link for options that can be selected
  • A chosen link for options that are already selected

Cortex choice and chosen follow this format:

  • A description link that links to a description of the option
  • A selectaction link that when followed selects the option The link appears only on choice resources as chosen resources are already selected

Example: Selecting a Billing Address​

The billingaddressinfo resource contains a selector that allows shoppers to select their billing address for an order. The selector provides a list of addresses shoppers have previously saved to their account from which the shopper can choose from.

{
"rel": "selector",
"type": "orders.billingaddress-info-selector",
"href": "https://cortex.elasticpath.com/cortex/orders/mobee/mvrtszjrgvsdcllemuzwiljugrsdgllbhbsdoljrmq3wmzjxgu4tmztggq=/billingaddressinfo/selector"
}

Structured Messages​

Structured messages are returned in the messages array in a Cortex response and are used to communicate the following types of conditions:

  • Input validation errors

    • Request Methods: POST, PUT

      HTTP Response Status Code: 400 Bad Request

  • Business state errors

    • Request Methods: POST, PUT, DELETE

      HTTP Response Status Code: 409 Conflict

  • Blocking conditions

    • Request Method: GET

      HTTP Response Status Code: 200 OK

    • Request Method: POST

      HTTP Response Status Code: 409 Conflict

  • Informational messages:

    • Request Methods: GET

      HTTP Response Status Code: 200 OK

Structured messages are created by validation constraints and business rules in the service layer, and by advisors in the API prototype layer. Structured messages are very flexible and can be used to represent a variety of conditions based on the type of the message and how it was generated.

Message Fields​

type​

The type of the message.

"type": "error"

id​

A unique identifier for the message condition.

"id": "field.required"

debug-message​

A text description of the error as a debugging convenience. It is not suitable for presentation to end users. See Localizing Structured Messages.

"debug-message": "given-name is required"

data​

A set of name/value pairs to convey message-specific data.

"data": {
"field-name": "given-name"
}

blocks​

Optional field. The action that is blocked by the message condition.

"blocks": {
"rel": "submitorderaction"
}

linked-to​

Optional field. A resource for users to act upon to resolve the condition.

"linked-to": {
"uri": "/orders/{scope}/{id}/emailinfo",
"href": "https://{host}/{context}/orders/...",
"type": "controls.info"
}

Example Structured Message​

Here is an example the messages returned when attempting to register a new account with an invalid password and email address.

400 Bad Request

{
"links": [],
"messages": [
{
"type": "error",
"id": "field.invalid.size",
"debug-message": "Password must be between 8 to 255 characters inclusive",
"data": {
"field-name": "password",
"min": "8",
"max": "255"
}
},
{
"type": "error",
"id": "field.invalid.email.format",
"debug-message": "not a well-formed email address",
"data": {
"field-name": "email",
"invalid-value": "bar"
}
}
],
"entity": {}
}

Error Messages​

Structured messages with a type field of error are generated in Cortex from field validation errors, business state errors, and non-resolvable blocking conditions.

Field Validation Errors​

Field validation errors are generated from service layer constraint violations. Their characteristics are:

  • They are returned on POST and PUT operations with Status Code 400 Bad Request
  • The type is error
  • The id begins with field.
  • The data field always contains a field-name entry, and may contain other entries depending on the error
  • There are no blocks or linked-to fields

Example:

{
"type": "error",
"id": "field.invalid.size",
"debug-message": "Password must be between 8 to 255 characters inclusive",
"data": {
"field-name": "password",
"min": "8",
"max": "255"
}
}

See Field Validation Errors for a list of messages returned by Cortex.

Business State Errors​

Business state errors are generated by service layer business rules. Their characteristics are:

  • They are returned on POST, PUT and DELETE operations with Status Code 409 Conflict
  • The type is error
  • The data field may contain entries that provide additional business context
  • There may be blocks or linked-to fields if the error is resolvable by the user

Example:

{
"type": "error",
"id": "cart.item.not.available",
"debug-message": "Item '{item-code}' is not available for purchase.",
"linked-to": {
"uri": "/availabilities/carts/{scope}/{id}/lineitems/{id}",
"href": "http://{host}/{context}/availabilities/carts/{scope}/{id}/lineitems/{id}",
"type": "availabilities.availability-for-cart-line-item"
},
"data": {
"item-code": "physical_product_with_fixed_inventory_sku"
}
}

See Business State Errors for a list of messages returned by Cortex.

NeedInfo Messages​

Structured messages with a type field of needinfo are generated in Cortex from resolvable blocking conditions. A needinfo message indicates that additional information needs to be provided by the user. Their characteristics are:

  • They are returned on GET operations with Status Code 200 OK, or on POST operations with Status Code 409 Conflict
  • The type is needinfo
  • The data field may contain entries that provide additional business context
  • The blocks field indicates that action that is blocked
  • The linked-to field indicates the action the user needs to take to resolve the condition

The following example indicates that a billing address is required in order to submit an order.

{
"type": "needinfo",
"id": "need.billing.address",
"debug-message": "Billing address is required",
"data": {
},
"blocks": {
"rel": "submitorderaction"
},
"linked-to": {
"uri": "/orders/{scope}/{id}/billingaddressinfo",
"href": "https://{host}/{context}/orders/{scope}/{id}/billingaddressinfo",
"type": "orders.billingaddress-info"
}
}

Informational Messages​

Structured Messages with a custom type field are generated in Cortex as a result of an advisor. Custom structured messages can be actionable or non-actionable.

Cortex provides two out of the box informational type fields, information and promotion.

Actional Informational Messages​

Custom structured messages with a linked-to field are actionable. They have the following characteristics:

  • They are returned on GET operations with Status Code 200 OK
  • The type may be information, promotion, or another custom type
  • The data field may contain entries that provide additional business context
  • The linked-to field is present if the message is actionable

Example:

{
"type": "promotion",
"id": "promo.buy.more.get.one.free",
"debug-message": "If you purchase 2 more 'AA-12358' items, you get 1 for free.",
"data": {
"item-code" : "AA-12358",
"threshold" : "3",
"quantity" : "1"
},
"linked-to": {
"uri": "/items/{scope}/{id}/addtocartform",
"href": "https://{host}/{context}/items/{scope}/{id}/addtocartform",
"type": "carts.line-item"
}
}

Non-Actionable Informational Messages​

Custom structured messages without a linked-to field are non-actionable. Otherwise, they have the same characteristics as an actionable custom structured message.

{
"type": "promotion",
"id": "promo.free.shipping",
"debug-message": "Get free shipping if you buy $5.37 more",
"data": {
"amount": "$5.37",
}
}

Localizing Structured Messages​

A front-end developer is responsible for localizing and presenting structured messages to the user. The debug-message field is provided as a developer convenience and is not suitable for presentation to end users.

To localize a structured message:

  • Use the message id and the user’s locale to lookup a localized message template
  • Localize values in the data field if required
  • Substitute placeholders in the localized message template with the localized values from the data field

Localization Example​

Let’s use the following message as an example of localization into English.

{
"type": "error",
"id": "field.required",
"debug-message": "given-name attribute is required",
"data": {
"field-name": "given-name"
}
}
  1. Lookup a localized message template for id=field.required and locale=en. For example, the template might be:

    localized-template = "{field-name} is required"
  2. Localize the field-name data value of given-name to match what the field in called in the user interface (e.g. "First name")

    localized-field-name = "First name"
  3. Substitute the {field-name} placeholder with the localized data value.

    localized-message = "First name is required"