Status

Doc Status

Working Draft — Only experimental and ‘proof-of-concept’ apps should be built on this unstable draft.

Proposed IANA Registrations

application/prs.hal-forms+json

Repository

https://github.com/rwcbook/hal-forms

Sample Implementation

https://github.com/apiacademy/ndcoslo2015/tree/hal-forms

Last Updated

2021-03-03

Table of Contents

1. Summary

This document describes a simple media type designed to add runtime FORM support for the [HAL] media type. This is an independent backward-compatible extension of the HAL media type and MUST NOT be treated as standard HAL or as part of the HAL specification [HALSPEC].

1.1. Motivation

The HAL media type is a popular format for representing API responses. One of the possible reasons for this popularity is that HAL does not include detailed information about state transitions like filtered requests (e.g. search, sort, etc.) or write operations (e.g. create, edit, delete, etc.) as part of the specification. This feature keeps the complexity of HAL responses relatively low and easy to deal with. However, this also means one of the challenges of using HAL for APIs that support dynamic user inputs and/or varying work flow patterns is client applications must encode the detailed transition information (args, methods, work flow) directly in the client code. That means clients must be updated each time the input or work flow details change.

The HAL-FORMS media type is an attempt to meet this challenge by creating a format and processing pattern to support dynamic UI forms for HAL responses. This is a backward-compatible, non-standard extension. There is nothing in this format or process pattern that adds breaking changes to the HAL media type itself. Clients that implement this extension can still be valid HAL clients by degrading gracefully (e.g. not throwing errors) when HAL-FORMS documents are not returned by the server.

Note

The HAL-FORMS media type design follows many of the HAL media type conventions. For this reason, HAL-FORMS "looks like HAL." However, it is important to keep in mind that HAL-FORMS is not the same as HAL — the two should not be thought of as interchangeable in any way. Finally, HAL-FORMS documents SHOULD always be sent over HTTP using the application/prs.hal-forms+json media type identifer.

1.2. Updates

There is an open source repository [REPO] for this specification. Readers are encouraged to submit updates via the repository any time.

1.3. Compliance

An implementation (client or server) of this specification is not compliant if it fails to satisfy one or more of the MUST or REQUIRED elements. An implementation that satisfies all the MUST and REQUIRED elements as well as all the SHOULD and RECOMMENDED elements is said to be "unconditionally compliant"; one that satisfies all the MUST and REQUIRED elements but not all the SHOULD and RECOMMENDED elements is said to be "conditionally compliant."

Note
RFC2119 Words

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].

2. The HAL-FORMS Media Type

The HAL-FORMS media type is a simple JSON [RFC7159] document that contains information on the HTTP method, message content-type, and parameters to use when making a templated request to a HAL server. This media type can be used to provide dynamic state transition descriptions at runtime.

2.1. Example HAL-FORMS document

Here is a simple HAL-FORMS document example:

Example HAL-FORMS document.
{
  "_links" : {
     "self" : {
      "href" : "http://api.example.org/rels/create"
    }
 },
  "_templates" : {
    "default" : {
      "title" : "Create",
      "method" : "POST",
      "contentType" : "application/json",
      "properties" : [
        {"name" : "title", "required" : true, "value" : "", "prompt" : "Title", "regex" : "", "templated" : false},
        {"name" : "completed", "required" : false, "value" : "false", "prompt" : "Completed", "regex" : ""}
      ]
    }
  }
}

2.2. The HAL-FORMS Media Type Identifier String

The media type identifier string for HAL-FORMS documents is: application/prs.hal-forms+json This SHOULD be used as part of the HTTP accept header when making a request for a HAL-FORMS document. It SHOULD appear as the HTTP content-type header when sending a response that contains a HAL-FORMS document.

3. Properties of a HAL-FORMS Document

All HAL-FORMS documents MUST be valid JSON documents. A well-formed HAL-FORMS document has two top-level objects: _links and _templates. The following is a summary of the structure of the HAL-FORMS media type.

The _links collection contains a dictionary collection of link elements associated with the HAL-FORMS document.

Contains the collection of valid link elements in the HAL-FORMS document. This is a RECOMMENDED element. If this element is missing, is invalid, or cannot be parsed, the HAL-FORMS document SHOULD be treated as if it contains a _links collection which contains a single link element with the key of self and the value of the URL that was used to request the current HAL-FORMS document.

Every HAL-FORMS document SHOULD have at least one link element in the collection with a key value set to self. The _links collection MAY have additional link elements with other key values. HAL-FORMS clients SHOULD ignore any link elements with key values they do not understand. Clients MAY reject a HAL-FORMS document that does not contain a link element with the key value set to self.

The link element consists of a key and a set of properties.

  • key : The unique identifier of the link element. This is a REQUIRED property for each link element. If this property is missing, is set to an unrecognized value, or cannot be parsed, the associated link element SHOULD be ignored.

  • href : The URL associated with the key. This is a REQUIRED property. If this is missing, set to empty or cannot be parsed, the associated link element SHOULD be ignored.

Note
Additional properties MAY appear within a link element. HAL-FORMS clients SHOULD ignore any properties they do not understand and/or cannot parse.

3.2. The _templates Collection

The _templates collection describes the available state transition details including the HTTP method, message content-type, and arguments for the transition. This is a REQUIRED element. If the HAL-FORMS document does not contain this element or the contents are unrecognized or unparsable, the HAL-FORMS document SHOULD be ignored.

The _templates element contains a dictionary collection of template objects. A valid HAL-FORMS document has at least one entry in the _templates dictionary collection. Each template contains the following possible properties:

3.2.1. contentType

The value of contentType is the media type the client SHOULD use when sending a request body to the server. This is an OPTIONAL element. The value of this property SHOULD be set to "application/json" or "application/x-www-form-urlencoded". It MAY be set to other valid media-type values. If the contentType property is missing, is set to empty, or contains an unrecognized value, the client SHOULD act is if the contentType is set to "application/json". See Encoding Request Bodies for details.

3.2.2. key

The unique identifier for this template element. This is a REQUIRED element. For this release, the only pre-defined value for key is "default". If there is only one element in the collection the key value MUST be set to "default". Clients MAY ignore additional entries in the collection. If this element is missing, set to empty or is unparsable, this template object SHOULD be ignored.

3.2.3. method

The HTTP method the client SHOULD use when the service request. Any valid HTTP method is allowed. This is a REQUIRED element. If the value is empty or is not understood by the client, the value MUST be treated as an HTTP GET.

3.2.4. properties

An array of one or more anonymous property elements (see The property Element) that each describe a parameter for the associated state transition. This is an OPTIONAL element. If the array is missing or empty, the properties collection MUST be treated as an empty set of parameters — meaning that the transition is meant to be executed without passing any parameters.

3.2.5. target

Contains the identifier of the target URL for the client to use when submitting the completed HAL-FORMS template. For example, if the client should submit the completed template to the following URL: http://api.example.org/jobs/ then the target proprety would be target="http://api.example.org/jobs/".

This is an OPTIONAL property. If this property is not understood by the recipient, left blank, or contains an invalid URL string, it SHOULD be ignored.

The target property holds the same information as the _htarget query string property. If both the target prorperty and the _htarget query string value appear in the same message, the _htarget query string SHOULD be used and the target property SHOULD be ignored.

3.2.6. title

A human-readable string that can be used to identify this template. This is a valid JSON string. This is an OPTIONAL element. If it does not exist or is unparsable, consumers MAY use the key value of the template as the value for title.

3.3. The property Element

A JSON object that describes the details of the state transition element (name, required, readOnly, etc.). It appears as an anonymous array of properties as a child of the _templates element (See The _templates Element).

There is a set of property attributes that are considered core attributes. There are is also group of property attributes that are considered additional attributes. Any library supporting the HAL-FORMS specification SHOULD support all of the core attributes and MAY support some or all of the additional attributes.

3.3.1. Core property Attributes

The core property attributes cover the basics of describing a single value used for a state transition (write or filter parameter). Most all attributes are OPTIONAL and MAY be ignored by HAL-FORMS processors. Below is a list of all the core property attributes.

Note

Any library, tooling, or utility supporting the HAL-FORMS specification SHOULD support all of the core property attributes.

3.3.1.1. name

The property name. This is a valid JSON string. This is a REQUIRED element. If this attribute is missing or set to empty, the client SHOULD ignore this property object completely.

3.3.1.2. prompt

The human-readable prompt for the parameter. This is a valid JSON string. This is an OPTIONAL element. If this element is missing, clients MAY act as if the prompt value is set to the value in the name attribute.

3.3.1.3. readOnly

Indicates whether the parameter is read-only. This is a valid JSON boolean. This is an OPTIONAL element. If this element is missing, empty, or set to an unrecognized value, it SHOULD be treated as if the value of readOnly is set to ‘false’.

3.3.1.4. regex

A regular expression string to be applied to the value of the parameter. Rules for valid values are the same as the HTML5 pattern attribute [HTML5PAT]. This is an OPTIONAL element. If this attribute missing, is set to empty, or is unparseable , it SHOULD be ignored.

3.3.1.5. required

Indicates whether the parameter is required. This is a valid JSON boolean. This is an OPTIONAL element. If this attribute is missing, set to blank or contains an unrecognized value, it SHOULD be treated as if the value of required is set to ‘false’.

3.3.1.6. templated

Indicates whether the value element contains a URI Template [RFC6570] string for the client to resolve. This is a valid JSON boolean. This is an OPTIONAL element. If this element is missing, set to empty, or contains unrecognized content, it SHOULD be treated as if the value of templated is set to ‘false’.

3.3.1.7. value

The property value. This is a valid JSON string. This string MAY contain a URI Template (see templated for details). This is an OPTIONAL element. If it does not exist, clients SHOULD act as if the value property is set to an empty string.

3.3.2. Additional property Attributes

The additional property attributes provide greater controls for describing the rendering and validation of input controls for a state transition (write and filter parameters). All of the additional attributes are OPTIONAL and one or more of them MAY be ignored by HAL-FORMS processors. Below is a list of all the additional property attributes.

Note

Any library, tooling, or utility supporting the HAL-FORMS specification MAY support some or all of the additional property attributes.

3.3.2.1. cols

The cols attribute specifies the expected maximum number of characters per line to display when rendering the input box. This attribute applies to the associated property element when that property element’s type attribute is set to textarea. The cols attribute is a non-negative integer greater than zero. If the cols attribute is missing or contains an invalid value, it can be assumed to be set to the value of 40. If the type attribute of the associated property element is not set to textarea, this attribute SHOULD be ignored. This is an OPTIONAL attribute and it MAY be ignored. The cols attribute SHOULD appear along with the rows attribute.

3.3.2.2. max

The max attribute specifies the maximum numeric value for the value setting of a property element. This attribute MAY appear along with the min attribute. This is an OPTIONAL property and it MAY be ignored.

3.3.2.3. maxLength

The maxLength attribute specifies the maximum number of characters allowed in the value property. This attribute MAY appear along with the minLength attribute. This is an OPTIONAL property and it MAY be ignored.

3.3.2.4. min

The min attribute specifies the minimum numeric value for an value setting of a property element. This attribute MAY appear along with the max attribute. This is an OPTIONAL property and it MAY be ignored.

3.3.2.5. minLength

The minlength attribute specifies the minimum number of characters required in a value property. this attribute MAY appear along with the maxLength attribute. This is an OPTIONAL property and it MAY be ignored.

3.3.2.6. options

The options element contains a set of possible values accessible either byValue (e.g. inline) or byReference (e.g. via link.href) and can be used to provide a constrained list of possble values for a property field. See The options Element for details.

Support for the options object of a property element is OPTIONAL. If the client does not understand or cannot parse the options element, the options element SHOULD be ignored and the corresponding property SHOULD be treated as a simple text input element.

3.3.2.7. placeholder

The placeholder attribute specifies a short hint that describes the expected value of an input field (e.g. a sample value or a short description of the expected format). This is an OPTIONAL field and MAY be ignored.

3.3.2.8. rows

The rows attribute specifies the expected maximum number of lines to display when rendering the input box. This attribute applies to the associated property element when that property element’s type attribute is set to "textarea". The cols attribute is a non-negative integer greater than zero. If the cols attribute is missing or contains an invalid value, it can be assumed to be set to the value of 5. If the type attribute of the associated property element is not set to "textarea", this attribute SHOULD be ignored. This is an OPTIONAL attribute and it MAY be ignored. The rows attribute SHOULD appear along with the cols attribute.

3.3.2.9. step

The step attribute specifies the interval between legal numbers in a value property. For example, if step="3", legal numbers could be -3, 0, 3, 6, etc.

3.3.2.10. type

The type attribute controls the data type of the property value. It is an enumerated attribute. The type can also used to determine the interface control to display for user input. This is an OPTIONAL element. If the type value is not supported by the document consumer, contains a value not understood by the consumer, and/or is missing, the the document consumer SHOULD assume the type attribute is set to the default value: "text" and render the display input as a simple text box.

Possible settings for the type value adn teh expected contents to be returned inthe are: hidden, text, textarea, search, tel, url, email, password, date, month, week, time, datetime-local, number, range, color.

For hints on how to render and process various type values as well as for guidance on how each type value affects to the contents of the associated value property, see [HTML5TYPE].

3.4. The options Element

The options element contains an enumerated list of possible values for a property. This can be used to provide a UI similar to HTML controls such as:

  • SELECT & OPTIONS

  • INPUT.type="radio"

  • INPUT.type="checkbox"

  • INPUT.type="search" (w/ type-ahead suggestions)

The options control can also be used in machine-to-machine interactions where it is important to provide the client information about the possible values for a property.

The options element contains a set of possible values accessible either by value (e.g. options.inline) or by reference (e.g. via options.link.href) and can be used to provide a constrained list of possble values for a property field. If, when first loaded, the HAL-FORMS template has a pre-set value in the corresponding property.options.selectedValues array attribute, the UI MAY render the form with selected value(s) already chosen.

Whatever value is ultimately selected gets placed into the property.options.selectedValues array attribute. When sending the results of the completed HAL-FORMS to the server, content property.options.selectedValues is serialized in a manner compliant with the media type value in the contentType attribute (e.g. appilcation/json, application/x-www-form-urlencded, etc.).

Note
Support for the options element of a property element is OPTIONAL. If the client does not understand or cannot parse the options element, the options element SHOULD be ignored and the corresponding property SHOULD be treated as a simple text input element.

3.4.1. Overview of the options Element

Below is an overview of the property.options element as it appears within a HAL-FORMS document. Details describing the meaning and use of all the elements of the design appears in the sections that follow.

{
  "_templates" : {
    "default" : {
      ...
      "contentType" : "application/json|application/x-www-form-ulencoded",
      "properties" : [
        {
          "name" : "...",
          "prompt" : "...",
          "options" : {
            "selectedValues" : ["...", "...", ...],
            "inline" : ["...", "..." , ...] | [{"prompt" : "...", "value" : "..."}, {...}, ...],
            "link" : {
              "href" : "...",
              "templated" : "true|false",
              "type" : "application/json|text/csv..."
            },
            "promptField" : "...",
            "valueField" : "...",
            "minItems" : 0,
            "maxItems" : 1
          }
        }
      ]
    }
  }
}

Not all the elements of the options object shown above are valid at the same time.

3.4.2. options Attributes

Below is the list of options attribute. HAL-FORMS compliant applications that support the options element SHOULD support all the attributes listed here.

3.4.2.1. inline

The inline attribute is a JSON array that contains the list of possible values. The inline attribute is OPTIONAL. If the inline attribute is missing or unparseable and the link (see link) attribute is missing or unparseable, then the options element SHOULD be ignored.

In it’s simplest form, the inline attribute holds a set of anonymous JSON dictionary objects in the form {'"prompt": "...", "value" : ""} (see A Simple Inline Array of Values). The inline contents can also be an array of unique name-value pairs (see An Inline Array of Name/Value Pairs).

Note
If both inline and link elements appear in the same options object, the inline element SHOULD be used and the link element SHOULD NOT be used.

The link attribute is a JSON dictionary object that contains an href which points to an external HTTP resource which contains the collection of possible values for a property'. The +link attribute is OPTIONAL. If the link attribute is missing or unparseable and the inline (see inline) attribute is missing or unparseable, then the options element SHOULD be ignored.

The link attribute has the following child attributes:

  • href : The URL associated with the key. This is a REQUIRED property. If this is missing, set to empty or cannot be parsed, the associated link element SHOULD be ignored.

  • type : A string used as a hint to indicate the media type expected when dereferencing the target resource. This is an OPTIONAL attribute. The type value SHOULD be set to application/json or text/csv. It MAY be set to some other value. If the type attribute is missing or unparseable, it SHOULD be assumed to be set to application/json. Client applications SHOULD use the value of the type attribute to populate the HTTP Accept header.

  • templated : A boolean value that SHOULD be set to true when link.href contains a URI Template [RFC6570]. This is an OPTIONAL attribute. If it is missing or unparseable, the value of templated SHOULD be treated as set to false.

The value returned when dereferencing a link element SHOULD be either a simple array (see An External Array of Values) or a custom collection (see An External Array of Name/Value Pairs). The exact format of the returned collection will vary based on the value of the HTTP Accept header sent with the request.

When responding to an options.link request, the server MAY return additional fields (e.g. more than prompt and value fields). These additional fields SHOULD be ignored by the client application.

Note
If both inline and link elements appear in the same options object, the inline element SHOULD be used and the link element SHOULD NOT be used.
3.4.2.3. maxItems

Indicates the maximum number of items to return in the selectedValues attribute. The client application MAY use this as a UI hint and/or to perform a client-side validation. The maxItems attribute is OPTIONAL. When it is missing or unparseable, the application SHOULD treat the maxItems value as unbounded (e.g. there is no upper limit on the number of items that can be selected and returned).

3.4.2.4. minItems

Indicated the minimum number of items to return in the selectedValues attribute. The client application MAY use this as a UI hint and/or to perform a client-side validation. The minItems attribute is OPTIONAL. When it is missing or unparseable, the application SHOULD treat the minItems value as 0 (e.g. there is no minimum number of items to be selected and returned).

Note
Document authors need to take care that property.required and property.options.minItems settings do not conflict (e.g. property.required:true and options.minItems:0).
3.4.2.5. promptField

This attribute contains the name of the JSON dictionary element in the array returned via the inline or link elements to use as the prompt when rendering the options UI. This is an OPTIONAL attribute. If this attribute is missing or unparseable the application SHOULD assume the promptField value is set to "prompt".

See Reference Fields for an example.

3.4.2.6. selectedValues

This is a JSON array that holds the set of values selected from the list of possible values supplied by the inline and link attributes. This is an OPTIONAL element. If it is missing or unparseable, the application SHOULD assume it is an empty JSON array.

This attribute MAY be populated when the HAL-FORMS is first requested. In that case, the application can use the value of the selectedValues array to pre-populate the user interface.

When sending the results of selecting multiple values in the options.selectedValues array from the client to the server, the rules associated with the _templates.contentType SHOULD be applied. When the _templates.contentType is set to application/json, the contents of the options.selectedValues array SHOULD be serialized as a simple JSON array:

{
  ...
  shipping=["FedEx", "DHL"]
  ...
}

When the contentType is set to application/x-www-form-urlencoded, the contents of the options.selectedValues array SHOULD be serialized as a set of repeating name/value pairs:

shipping=FedEx&shipping=DHL

See Multiple Return Values for an example.

3.4.2.7. valueField

This attribute contains the name of the JSON dictionary element in the array returned via the inline or link elements to use as the value when rendering the options UI and filling in the selectedValues attribute. This is an OPTIONAL attribute. If this attribute is missing or unparseable the application SHOULD assume the valueField value is set to "value".

See Reference Fields for an example.

3.4.3. Additional Considerations

Here are some additional considerations when implementing support for the property.options element.

3.4.3.1. Missing Prompts

In cases where the possible value collection from (inline or link elements) only supplies a list of value elements, the client SHOULD operate as if a prompt element was supplied and set that prompt value to equal the contents of the corresponding value element.

3.4.3.2. Supporting JSON and CSV

Compliant applications SHOULD support both application/json and text/csv as valid response types for options.link implementations. Clients MAY support other values. If no options.link.type attribute exists, the client application SHOULD default to application/json. Whether the options.link.type value appears or not, client applications SHOULD send an Accept header when making a request to the server with the supplied URL. If no Accept header is sent by the client, the server SHOULD assume the client expects an Accept header set to application/json and respond accordingly.

3.4.4. options Examples

Not all the elements of the options object shown above are valid at the same time. There are a number of possible "renditions" of the options object. This spec covers the following:

  • A Simple Inline Array of Values

  • An Inline Array of Name/Value Pairs

  • An External Array of Values

  • An External Array of Name/Value Pairs

  • Reference Fields

  • Multiple Return Values

3.4.4.1. A Simple Inline Array of Values

Below is a simple rendition of the options control using the Inline Array style. Note that, in the example below control’s default value would be set to "FedEx".

{
  "_templates" : {
    "default" : {
      ...
      "properties" : [
        {
          "name" : "shipping",
          "prompt" : "Select Shipping Method",
          "options" : {
            "selectedValues" : ["FedEx"],
            "inline" : ["FedEx","UPS","DHL"]
          }
        }
      ]
    }
  }
}

A corresponding HTML.SELECT rendering looks like this:

<label for="shipping">Select Shipping Method</label>
<select name="shipping">
  <option selected="true">FedEx</option>
  <option>UPS</option>
  <option>DHL</option>
</select>
3.4.4.2. An Inline Array of Name/Value Pairs

Below is an example of the options control using an Inline Array of Name/Value Paris.

{
  "_templates" : {
    "default" : {
      ...
      "properties" : [
        {
          "name" : "shipping",
          "type" : "radio",
          "prompt" : "Select Shipping Method",
          "options" : {
            "selectedValues" : ["FedEx"],
            "inline" : [
              {"prompt" : "Federal Express", "value" : "FedEx"},
              {"prompt" : "United Parcel Service", "value" : "UPS"},
              {"prompt" : "DHL Express", "value" : "DHL"}
            ]
          }
        }
      ]
    }
  }
}

A corresponding HTML.INPUT.type="radio" rendering looks like this:

<p>
  <input type="radio" id="fedex" name="shipping" value="FedEx" checked="true">
  <label for="fedex">Federal Express</label><br>

  <input type="radio" id="ups" name="shipping" value="UPS">
  <label for="ups">United Parcel Service</label><br>

  <input type="radio" id="dhl" name="shipping" value="DHL">
  <label for="dhl">DHL Express</label>
</p>
3.4.4.3. An External Array of Values

The source of possible values for a options control can also be an external resource. This resource is reachable using an HTML.GET against a supplied URL (which MAY be templated) and and OPTIONAL options.link.type property that holds a valid registered media type (e.g. application/json, text/csv, etc.).

By default, the response value is a Simple Array rendered in application/json as a JSON array.

{
  "_templates" : {
    "default" : {
      ...
      "properties" : [
        {
          "name" : "shipping",
          "type" : "radio",
          "prompt" : "Select Shipping Method",
          "options" : {
            "selectedValues" : ["FedEx"],
            "link" : {
              "href" : "http://api.examples.org/shipping-options",
              "templated" : "false",
              "type" : "application/json"
            }
          }
        }
      ]
    }
  }
}

The client SHOULD dereference the URL using HTTP.GET. The exchange (including the response) looks like this:

*** REQUEST
GET /shipping-options HTTP/2.0
Host: api.example.org
Accept: application/json

*** RESPONSE
HTTP/2.0 200 OK
Content-Type: application/json
Content-Length: nn

["Fedex","UPS","DHL"]

A CR-LF delimited set of values MAY be returned if the options.link.type attribute is set to text/csv

*** REQUEST
GET /shipping-options HTTP/2.0
Host: api.example.org
Accept: text/csv

*** RESPONSE
HTTP/2.0 200 OK
Content-Type: text/csv
Content-Length: nn

Fedex
UPS
DHL
3.4.4.4. An External Array of Name/Value Pairs

The external resource MAY return a collection of name/value pairs.

{
  "_templates" : {
    "default" : {
      ...
      "properties" : [
        {
          "name" : "shipping",
          "type" : "dropdown",
          "prompt" : "Select Shipping Method",
          "options" : {
            "selectedValues" : ["FedEx"],
            "link" : {
              "href" : "http://api.examples.org/shipping-options",
              "templated" : "false",
              "type : "application/json"
            }
          }
        }
      ]
    }
  }
}

The client SHOULD dereference the URL using HTTP.GET. The exchange (including the response) looks like this:

*** REQUEST
GET /shipping-options HTTP/2.0
Host: api.example.org
Accept: application/json

*** RESPONSE
HTTP/2.0 200 OK
Content-Type: application/json
Content-Length: nn

[
  {"prompt" : "Federal Express", "value" : "FedEx"},
  {"prompt" : "United Parcel Service", "value" : "UPS"},
  {"prompt" : "DHL Express", "value" : "DHL"}
]

The set of name/value pairs MAY be returned in text/csv format when the options.link.type property is set to text/csv.

*** REQUEST
GET /shipping-options HTTP/2.0
Host: api.example.org
Accept: text/csv

*** RESPONSE
HTTP/2.0 200 OK
Content-Type: text/csv
Content-Length: nn

Federal Express,FedEx
United Parcel Service,UPS
DHL Express,DHL
3.4.4.5. Reference Fields

The options element also supports the use of options.promptField and options.valueField as custom property names or Reference Fields instead of using the default names "prompt" and "value". In this case, the promptField value contains the name of the field in the source collection (inline or link) to be used for prompts and the valueField value contains the name of the field in the source collection to be used for values.

{
  "_templates" : {
    "default" : {
      ...
      "properties" : [
        {
          "name" : "shipping",
          "type" : "radio",
          "prompt" : "Select Shipping Method",
          "options" : {
            "selectedValues" : ["FedEx"],
            "inline" : [
              {"shipName" : "Federal Express", "shipCode" : "FedEx"},
              {"shipName" : "United Parcel Service", "shipCode" : "UPS"},
              {"shipName" : "DHL Express", "shipCode" : "DHL"}
            ],
            "promptField" : "shipName",
            "valueField" : "shipCode"
          }
        }
      ]
    }
  }
}

Reference Fields MAY be used when returning an array of JSON objects if the options.accept attribute is set to application/json

*** REQUEST
GET /shipping-options HTTP/2.0
Host: api.example.org
Accept: application/json

*** RESPONSE
HTTP/2.0 200 OK
Content-Type: application/json
Content-Length: nn

[
  {"shipName" : "Federal Express", "shipCode" : "FedEx"},
  {"shipName" : "United Parcel Service", "shipCode" : "UPS"},
  {"shipName" : "DHL Express", "shipCode" : "DHL"}
]
3.4.4.6. Multiple Return Values

You can signal the minimum and maximum number of items that can be selected using the options.minItems and options.maxItems attributes. By default, these attributes are options.minItems=0 and options.maxItems is unbounded (e.g. there are no limits). Client applications SHOULD validate the number of seleted values using these attributes. This can apply whether the source list comes from inline or link. These attributes are OPTIONAL and MAY be ignored by the client.

{
  "_templates" : {
    "default" : {
      ...
      "properties" : [
        {
          "name" : "shipping",
          "type" : "checkbox",
          "prompt" : "Select Shipping Method",
          "options" : {
            "selectedValues" : ["FedEx"],
            "inline" : [
              {"shipName" : "Federal Express", "shipCode" : "FedEx"},
              {"shipName" : "United Parcel Service", "shipCode" : "UPS"},
              {"shipName" : "DHL Express", "shipCode" : "DHL"}
            ],
            "minItems" : 1,
            "maxItems" : 2
            "promptField" : "shipName",
            "valueField" : "shipCode"
          }
        }
      ]
    }
  }
}

When sending the results of selecting multiple values in the options.selectedValues array from the client to the server, the rules associated with the contentType SHOULD be applied. When the contentType is set to application/json, the contents of the options.selectedValues array SHOULD be serialized as a simple JSON array:

{
  ...
  shipping=["FedEx", "DHL"]
  ...
}

When the contentType is set to application/x-www-form-urlencoded, the contents of the options.selectedValues array SHOULD be serialized as a set of repeating name/value pairs:

shipping=FedEx&shipping=DHL

4. The HAL-FORMS Query String Registry

The HAL-FORMS media type supports a set of OPTIONAL query string parameters. These can be passed when requesting HAL-FORMS documents in order to provide additional information (e.g. document identifiers, etc.) to the server when a client requests a HAL-FORMS document. For example, the server can use these parameter values to validate the HAL-FORMS request and/or use them to determine how to pre-populate the HAL-FORMS document before returning it to the client.

Below is the list of query string values defined for this release of the specification. One or more of these parameters MAY appear in the URLs used to request HAL-FORMS documents. They can appear in the query string in any order. One or more (possibly all) these parameters MAY be ignored by servers receiving the HAL-FORMS request.

4.1. _hdoc

Contains the identifier (usually a URL) of the HAL document from which this request was derived. For example if the HAL document had a URL of http://api.example.org/users/123 then the _hdoc query parameter would be _hdoc=http%3A%2F%2Fapi.example.org%2Fusers%2F123.

4.2. _hkey

Contains the key value of the HAL-FORMS template the client wishes to receive. For example, if the HAL-FORMS template key is default then the _hkey parameter would be _hkey=default.

4.3. _hmethod

Contains the HTTP method to be used when populating the HAL-FORMS method value in the _template. For example, if the client wishes to execute an HTTP POST with the template, the _hmethod parameter would be: _hmethod=post.

4.4. _hrel

Contains the key of the HAL _link element that identified the URL for the HAL-FORMS document. For example, if the HAL document had a _link element that looked like this:

"http://api.example.org/rels/filter": {
  "href": "http://api.example.org/task-list/",
  "title": "Filter Tasks",
  "templated": false
}

…then the _hrel parameter would be _hkey=http%3A%2F%2Fapi.example.org%2Frels%2Ffilter.

4.5. _hsource

Contains the identifier of the source record to use when pre-populating the HAL-FORMS document. For example, if the client wishes to edit the resource identified by the URL http://api.example.org/users/123 then the _hsource parameter would be _hsource=http%3A%2F%2Fapi.example.org%2Fusers%2F123.

4.6. _htarget

Contains the identifier of the target URL for the client to use when submitting the completed HAL-FORMS template. For example, if the client should submit the completed template to the following URL: http://api.example.org/jobs/ then the _htarget parameter would be _htarget=http%3A%2F%2Fapi.example.org%2Fjobs%2F.

Note

Additional HAL-FORMS query string parameters MAY be added over time. Implementers are also allowed to create their own HAL-FORMS query string parameters for local use as long as they do not overwrite or redefine existing query string parameters. Implementers are encouraged to use their own unique prefix value to reduce the chance their custom query parameters will conflict with other existing or future parameter names.

5. Encoding Requests

Once the client application has used the HAL-FORMS document to render a UI for accepting inputs (and the user has supplied the inputs), that same document SHOULD be used to encode a request to send to the server to execute the state transition described by the HAL-FORMS document. There are two ways in which HAL-FORMS documents can be used to construct parameterized requests. The first is by encoding request URLs for HTTP GET, DELETE, and HEAD requests. The second is by encoding request bodies for HTTP PUT, POST, and PATCH requests.

5.1. Encoding Request URLs

When clients are instructed to send a request without a body (e.g. GET, HEAD, DELETE), clients SHOULD use the list of property object’s name and value attributes to construct a valid URL using the W3C Mutate Action URL Algorithm [HTML5MUT] to produce a valid query string. Below is a simple HAL-FORMS document that uses the GET method and the resulting updated URL.

// HAL RESPONSE
{
  "_links": {
    "self": {
      "href": "http://api.example.org/task-list/",
      "title": "Reload",
      "templated": false
    },
    "http://api.example.org/rels/filter": {
      "href": "http://api.example.org/task-list/",
      "title": "Filter Tasks",
      "templated": false
    },
  }
}

// HAL FORMS DOCUMENT
{
  "_links" : {
    "self" : {
      "href" : "http://api.example.org/rels/filter"
    }
  },
  "_templates" : {
    "default" : {
      "title" : "Filter",
      "method":"GET",
      "properties": [
        {"name":"title", "value":"", "prompt":"Title"},
        {"name":"completed", "value":"", "prompt":"Completed", "regex":"^(true|false)$"}
      ]
    }
  }
}

// RESULTING URL
http://api.example.org/task-list/?title=sample&completed=false
Note

The HAL media type already defines support for parameterized HTTP GET queries using URITemplates. However, the HAL-FORMS document can be treated as an alternate implementation for GET queries that include additional constraints such as prompts, regular expression validators, etc.

5.2. Encoding Request Bodies

When clients are instructed to send a request with a body (e.g. PUT, POST, PATCH), there are several possible content-types to use. Compliant applications MUST support encoding bodies using application/json and SHOULD support encoding bodies using application/x_www-form-urlencoded. Clients MAY support other content-types not listed in this document.

5.2.1. Sending application/json Bodies

When sending bodies encoded as application/json, clients SHOULD construct a simple JSON dictionary object that contains a set of name-value pairs that match the property objects in the HAL-FORMS document. For example, using the Example HAL-FORMS document (see above) as a guide, a client would construct a JSON dictionary object that looks like the following:

{
  "title" : "A Sample HAL Forms Response",
  "completed" : false
}

5.2.2. Sending application/x-www-form-urlencoded Bodies

When sending bodies encoded as application/x-www-form-urlencoded, clients SHOULD construct a body that is in compliance with the guidance in the W3C FORMS Encoding Algorithm [HTML5ENC]. A sample (using the Example HAL-FORMS document) follows:

title=A+Sample+HAL+Forms+Response&completed=false

5.2.3. Sending Bodies for Other Media Types

Providers who supply responses that contain contentType values not covered in this specification SHOULD publish documentation instructing clients on the proper way to construct request bodies from HAL-FORMS documents.

6. Suggested Process Flow for HAL-FORMS Documents

While it is completely up to providers and consumers to determine how they wish to use the HAL-FORMS media type, the following is a suggested process flow for runtime use of HAL-FORMS documents on the Web.

  1. Servers emit HAL responses that contain rel values which are valid URLs that return HAL-FORMS documents.

  2. Clients parse the HAL response and (either on-demand or in pre-fetch mode) request the HAL-FORMS documents.

  3. When a HAL-FORMS document is returned by the server, clients use this information to render an input UI for humans when needed.

  4. Clients collect the completed user inputs and, based on the value of contentType, craft a valid request to send to the server and execute that request.

What follows is an illustrated example of this process flow.

6.1. Starting With a Typical HAL Response.

A client application can start with a typical HAL response and use information in the representation to see if HAL-FORMS documents are available. Below is a HAL response w/ URLs for rel values. These MAY point to HAL-FORMS documents.

A Typical HAL Response with URLs for rel values
**** REQUEST
GET /task-list/ HTTP/1.1
Host: api.example.org
Accept: application/vnd.hal+json

**** RESPONSE
HTTP/1.1 200 OK
Content-Type: application/vnd.hal+json
Date: Wed, 01 Jun 2016 14:50:30 GMT

{
  "_links": {
    "self": {
      "href": "http://api.example.org/task-list/",
      "title": "Reload",
      "templated": false
    },
    "http://api.example.org/rels/create": {
      "href": "http://api.example.org/task-list/",
      "title": "Add Task",
      "templated": false
    },
    "http://api.example.org/rels/tasks": [
      {
        "href": "http://localhost:8181/1a14qx7qc81",
        "title": "Yard Work"
      },
      {
        "href": "http://localhost:8181/1d4jwe1ewt7",
        "title": "Home Work"
      },
      {
        "href": "http://localhost:8181/1e2ll5wa383",
        "title": "School Work"
      }
    ]
  }
}

6.2. Requesting a HAL-FORMS Document

After parsing the HAL response, a HAL-FORMS compliant client app MAY use the rel URLs to make requests for HAL-FORMS documents. In the case of this example, the http://api.example.org/rels/create is used to see if there is a HAL-FORMS document available.

Requesting a HAL-FORMS document
**** REQUEST
GET /rels/create HTTP/1.1
Host: api.example.org
Accept: application/prs.hal-forms+json

**** RESPONSE
HTTP/1.1 200 OK
Content-Type: application/prs.hal-forms+json
Date: Wed, 01 Jun 2016 14:59:30 GMT

{
  "_links" : {
     "self" : {
      "href" : "http://api.example.org/rels/create"
    }
 },
  "_templates" : {
    "default" : {
      "title" : "Create",
      "method" : "POST",
      "contentType" : "application/json",
      "properties" : [
        {"name" : "title", "required" : true, "value" : "", "prompt" : "Title", "regex" : "", "templated" : false},
        {"name" : "completed", "required" : false, "value" : "false", "prompt" : "Completed", "regex" : ""}
      ]
    }
  }
}

6.3. Sending a HAL-FORMS Body Request

After receiving the HAL-FORMS response and rendering the UI, the client application can — once the user supplies inputs and executes the "submit" action — use the instructions in the HAL-FORMS document to compose a request and send it to the URL indicated in the HAL document response (as follows):

Sending a HAL-FORMS body request
**** REQUEST
POST /task-list/ HTTP/1.1
Host: api.example.org
Accept: application/json

{
  "title" : "A Sample HAL-FORMS Response",
  "completed" : false
}

**** RESPONSE
HTTP/1.1 201 OK
Content-Type: application/vnd.hal+json
Date: Wed, 01 Jun 2016 15:03:30 GMT
...

7. Extending the HAL-FORMS Document

Authors can extend the HAL-FORMS media type as long as the following rules are observed:

  1. No existing properties or objects are removed.

  2. No existing properties or objects or the list of valid values are altered in a way that is non-backward compatible (e.g. changes MUST NOT break existing implementations that adhere to this specification).

  3. All new properties or objects are treated as OPTIONAL (e.g. no new REQUIRED elements are introduced in an extension).

Warning

Authors should be aware that a future version of this specification MAY add new elements and should take care that any extensions are implemented in a way that reduces the likelihood that a future version of this specification is in conflict with your extension.

8. References

9. Acknowledgements

Thanks to everyone who helped contribute to this specification including: Carlos Beltrame, Josh Cohen, Oliver Drotbohm, Pete Johanson, Mike Kelly, Dilip Krishnan, Evert Pot, Greg Turnquist.