Using a dynamic form

Please make sure you read the Conventions before continuing with this guide.

Prerequisites

You will need an X-API-KEY and a Basic Access Authentication token generated from your username and password.

How to know if I can use a dynamic form

When working on the sales flow, the product that you select may contain a property named dynamicFormId if the property exists and contains a value other than null, it means that the product can use a dynamic form to request person information.

Why should I use a dynamic form?

Dynamic form fields that are captured can be associated with key(s) in the peopleLookup collection. This will allow you to augment the amount of information you associate with each passenger (or sender/receiver when purchasing a parcel), and enable easy pre-population of form data based on previous interactions.

You can get the dynamic form definition using the /accounts/dynamic-forms/:dynamicFormId endpoint with the dynamicFormId of the product. The product can be retrieved from /inventory/products/:productId

How do I use the information contained in the dynamic form object to build my own forms to be compatible with the Betterez sales flow?

We have identified certain fields that are required during our sales process, or for the purpose of lookups: documentType, documentNumber,firstName, lastName, email, phone, and fullName. This is defined "mappedStandardBtrzFields", and you can map multiple dynamic form fields to a single standard field. The exception being documentType and documentNumber. These fields are reserved for unique data you would like to capture and search on. For example a document type might be "Passport", and the documentNumber might be a unique number from a person's passport. These should be defined using /inventory/document-types. Any validation added to the document type should be checked on the client side to reduce failures.

The mappingSeparators object should be respected for any fields in mappedStandardBtrzFields that are associated with multiple dynamic fields.

If, peopleLookupEnabled is true, you can check the peopleLookupFields object to see which fields should be used for the lookup. These fields should be required, and be as unique as possible.

Finally there is the definition object, which should inform you as to how to construct your data capture. "x-" keys are ones we use for constructing our own forms based on the dynamicForm object, but can be ignored.

Definition example

Click to expand
{
  "dynamicforms": {
      "_id": "63e9d9c9f94f8d072b35ezz2",
      "accountId": "yourAccountId",
      "name": "PassengerCapture",
      "mappedStandardBtrzFields": {
          "documentType": {
              "key": "documentType",
              "value": "documentType"
          },
          "documentNumber": {
              "key": "documentNumber",
              "value": "documentNumber"
          },
          "email": [
              {
                  "key": "customEmail",
                  "value": "customEmail"
              }
          ],
          "firstName": [
              {
                  "key": "customFirstName",
                  "value": "customFirstName"
              },
              {
                  "key": "customSecondFirstName",
                  "value": "customSecondFirstName"
              }
          ],
          "lastName": [
              {
                  "key": "customlastName",
                  "value": "customlastName"
              },
              {
                  "key": "customSecondLastName",
                  "value": "customSecondLastName"
              }
          ],
          "fullName": [
              {
                  "key": "customFirstName",
                  "value": "customFirstName"
              },
              {
                  "key": "customLastName",
                  "value": "customLastName"
              }
          ],
          "phone": [
              {
                  "key": "customPhone",
                  "value": "customPhone"
              }
          ]
      },
      "mappingSeparators": {
          "documentType": " ",
          "documentNumber": " ",
          "email": " ",
          "firstName": " ",
          "lastName": " ",
          "fullName": " ",
          "phone": " "
      },
      "peopleLookupEnabled": true,
      "peopleLookupFields": {
          "documentType": true,
          "documentNumber": true,
          "email": false,
          "firstName": false,
          "lastName": false,
          "fullName": false,
          "phone": false
      },
      "peopleLookupTrigger": "documentNumber",
      "definition": {
          "id": "passengerFields",
          "type": "object",
          "required": [
              "documentType",
              "documentNumber",
              "customFirstName",
              "customLastName"
          ],
          "properties": {
              "documentType": {
                  "type": "string",
                  "x-btrz-data": {
                      "collection": "document_types",
                      "key": "_id",
                      "value": "lexiconKeys.name",
                      "ord": "ord",
                      "default": ""
                  },
                  "x-btrz-row-index": 0
              },
              "dateOfBirth": {
                  "type": "string",
                  "format": "date-time",
                  "x-btrz-date": {
                      "from": "new Date()"
                  },
                  "x-btrz-row-index": 3
              },
              "documentNumber": {
                  "type": "string",
                  "x-btrz-row-index": 0
              },
              "customFirstName": {
                  "type": "string"
              },
              "customSecondFirstName": {
                  "type": "string"
              },
              "customLastName": {
                  "type": "string"
              },
              "customSecondLastName": {
                  "type": "string"
              },
              "gender": {
                  "type": "string",
                  "enum": [
                      "M",
                      "F"
                  ]
              },
              "customPhone": {
                  "type": "string"
              },
              "customEmail": {
                  "type": "string",
                  "x-btrz-row-index": 3
              }
          }
      },
      "createdAt": {
          "value": "2023-05-25T19:44:32.846Z",
          "offset": 0
      },
      "updatedAt": {
          "value": "2023-06-12T23:57:21.364Z",
          "offset": 0
      }
  }
}

Decoding Dynamic Form JSON Fields

Definition
properties
This section encapsulates the definition of custom fields. Each key corresponds to a unique custom field.

required
Specify the mandatory custom fields for this form. The user interface (UI) should validate and ensure their completion.

MappedStandarBtrzFields
This property facilitates the mapping between custom and standard Betterez fields.
The keys represent custom fields, and their corresponding values denote the standard Betterez fields they align with. This mapping is crucial for seamless integration into the sales flow.

MappingSeparators
This property defines the separators to be used in aggregated fields. For instance, in the "fullName" field, which may consist of "firstName" and "lastName," the specified separator (comma, space, etc.) should be used.

MappedProductBtrzFields
This property illustrates the mapping to more specific fields for different types of products.
For example, in the case of a "parcel," it provides a mapping for fields like "address," "city," "country," "province," and "zipCode."
However, for reservations, focusing on the fields in MappedStandardBtrzFields is sufficient.

MappingProductSeparators
This property define the separators to be used in aggregated fields specific to certain product types, similar to MappingSeparators but tailored for product-specific fields.

There are some properties that require special attention to define the UI behaviour:

peopleLookupEnabled
If enabled, the form should work with people lookup endpoints. It's important to note that at the API level, this field is not validated. Nevertheless, it serves as a useful indicator to determine whether the form will interact with lookup endpoints or not.

peopleLookupFields
This property defines which fields are used to look up a person when people lookup is active. The UI should prevent querying for a person if any of the specified fields in the GET /people-lookups request is missing.

peopleLookupTrigger
This property defines the field used to trigger the GET /people-lookups request.

availableForParcel
If set to true, this dynamic form will be available exclusively for parcels. When set to false, the form is valid for reservation products. This setting makes certain standard fields mandatory in the parcel sales flow.

captureAddressInfo
This property is only applicable when working with parcels. It enables the mapping of custom fields to specific standard parcel Betterez fields.
This mechanism is similar to the mapping process with standard Betterez fields. However, in this case, it is specifically applied to associating custom fields with standard Betterez fields for the "parcel" product type.