Quote hook

How to configure the quote hook, which allows your product to generate quotes

Overview

The first step in issuing an insurance policy is to create a quote to present to the customer. You need to decide on the rating factors, the information you need from the customer, the information on your own system you want to use, and the pricing logic to calculate the premium and benefits.

On Root, we call this the "get quote" hook, and it follows the following sequential steps:

  1. Quote parameters and rating factors are passed to the quote API endpoint from your system or the Root dashboard.
  2. This data is then fed to a validation function you specify, called validateQuoteRequest().
  3. Once validated, this data is fed to the getQuote() function where all the pricing logic lives.
  4. getQuote() returns a QuotePackage back through the API to your server to display to the customer.

The quote hook is designed to be light-weight, fast, and meant to be used to generate and display new quotes rapidly on a customer-facing front-end.

By defining the above functions in the product module code, you configure how the quote API endpoint will function for your product. (Read more about product module code).

📘

Underwriting engine

If you're using an underwriting engine, the results of the underwriting process will typically be passed as parameters to the quote hook.

Specifying quote parameters

The quote parameters, or request payload, typically contains all the input data required to calculate a premium and generate a quote based on the product specification.

This can be a combination of data captured from the user, and extra information that's already known on your system (perhaps it's an existing customer, so you already know their age or gender).

Below is an example payload for our Dinosure life insurance product.

{
  "type": "dinosure",
  "life_cover": 200000000, // This is in cents
  "age": 32,
  "cardio_fitness_level": "moderate",
  "smoker": false,
  "early_warning_network_benefit": true,
  "extraction_benefit": true,
  "consultants_benefit": false
}

The type field is standard for all product modules and tells the platform which product module to use when generating a quote. The value for the type field is the product module key, which was set when the product module was created.

All other fields are product-specific and you can determine which fields to include based on the product's specification.

The JSON data in the quote request payload is parsed and injected as the data parameter in the validateQuoteRequest() function for validation.

📘

Dashboard dependency

If the Root dashboard will be used to issue policies for your product, the quote request payload structure needs to match the quote schema used to capture information through the user interface.

Validating the quote parameters

Since you are configuring the quote endpoint for your product module, you also need to define the validation rules for what data is allowed. Root uses the popular and powerful Joi library to define these validations.

Joi validation schemas allow for both basic validation, such as checking data types, and also enforcing product-specific business rules, such as limiting the allowed age range for a specific input field.

Below is an example of the validateQuoteRequest() function used for the Dinosure life insurance quote request payload example. This function accepts the input data as its only argument, which will be in the same format as the quote request payload.

/**
 * Validates the quote request data.
 * @param {Record<string, any>} data The data received in the body of the
 *     <a href='https://docs.rootplatform.com/reference/getting-a-quote-2' target='_blank'>Create a quote</a> request
 *     (without the `type` property).
 * @return {{error: any; result: any}} The <a href='https://joi.dev/api/?v=12.1.0#validatevalue-schema-options-callback' target='_blank'>validation result</a>.
 *    If there are no errors, the `value` property will contain the validated data, which is passed to `getQuote`.
 * @see {@link https://docs.rootplatform.com/docs/quote-hook Quote hook}
 */
const validateQuoteRequest = (data) => {
  const validationResult = Joi.validate(
    data,
    Joi.object()
      .keys({
        life_cover: Joi.number().integer().min(100000*100).max(5000000*100).required(),
        age: Joi.number().integer().min(18).max(63).required(),
        cardio_fitness_level: Joi.valid(['couch potato', 'marathon runner']).required(),
        smoker: Joi.boolean().required(),
        early_warning_network_benefit: Joi.boolean().required(),
        extraction_benefit: Joi.boolean().required(),
        consultants_benefit: Joi.boolean().required(),
      })
      .required(),
  );
  return validationResult;
}

If no errors are thrown, Joi.validate() returns an object containing the validated data, typically exactly the same as the original data parameter, which is then automatically injected into the getQuote() function to calculate and generate the quote.

Generating a quote package

The getQuote() function is where the magic lives and the policy's premium and benefits are calculated.

This function takes the validated input data returned by validateQuoteRequest() as its only argument. It should return an array of QuotePackage objects. This can be useful, for example, where different quote packages include different benefits, or where one quote package is for monthly billing and another for annual billing.

Below is a skeleton example for the Dinosure life insurance product.

/**
 * Generates an array of quote packages from the quote request data.
 * @param {Record<string, any>} data The validated data returned by `validateQuoteRequest` as `result.value`.
 * @return {QuotePackage[]} The quote package(s) that will be returned by the
 *     <a href='https://docs.rootplatform.com/reference/getting-a-quote-2' target='_blank'>Create a quote</a> endpoint.
 * @see {@link https://docs.rootplatform.com/docs/quote-hook Quote hook}
 */
const getQuote = (data) => {
   // Do the math and logic to calculate the premium, benefits, etc.
   // using `data`, hardcoded rating tables, data stores, or external services/APIs
  const premium = ...;

  const quotePackage = new QuotePackage({
    // Below are standard fields for all products
    package_name: 'Dino protection', // The name of the "package" of cover
    sum_assured: data.life_cover, // Set the total, aggregated cover amount
    base_premium: premium, // Should be an integer, cents
    suggested_premium: premium, // Should be an integer, cents
    billing_frequency: 'monthly', // Can be monthly or yearly
    module: {
      // Save any data, calculations, or results here for future re-use.
      ...data, // We normally inject the full input data here
    },
    input_data: {...data},
  });
  return [quotePackage];
}

All the top-level fields under the QuotePackage object, such as sum_assured and suggested_premium, are standard across all product modules. See the API reference for the quote package object for an explanation of what each of these fields represents.

Custom, product-specific information is saved to the quote under the module object for later reference in the application and policy issuing hooks. You can customise the fields included under this object based on the product or integration requirements.

📘

Converting module properties to currencies on dashboard

If a property in the module data has one of the following keywords, it'll be converted to a currency value on the dashboard: premium, amount, income, assured, value and fund.

An example would be basic_income_per_month: 1990000will render as $ 19,900.00. Note the currency symbol is determined by the billing settings.

The quote package, or array of quote packages, returned by the getQuote() function is saved to the platform and then returned over the API. Each quote package has its own quote_package_id. All this happens synchronously when the <a href='doc:application-hook' target='_blank'>quote API endpoint (ref:getting-a-quote-2) is consumed.

Once the user has confirmed the quote, a quote package can then be passed to the getApplication() function where an application is created using a specific quote_package_id. Read more about the [application hook.

📘

Dashboard dependency: input_data

The input_data field should be set equal to the quote parameters as received over the API, unchanged and without any additional fields. This is typically achieved by assigning it like this: input_data: {...data} (although this assumes that the data object has not been changed in the getQuote() function).

This allows the quote schema on the dashboard to be pre-filled where possible. It is also required for compatibility with platform functionality currently in development.

Pricing and benefits

Typically, a policy's premium will be calculated at the quote stage. This may require the use of pricing lookup tables to find the correct premium based on the rating factors submitted in the quote request payload. For some products, policy benefits are also variable and need to be calculated using benefit lookup tables.

These tables can either be hard-coded directly in the product module code, or (if preferred) they can be saved in data stores which can be managed through the dashboard. An organisation's data stores can be accessed by the product module code, as explained in more detail in the data stores guide.

The premium calculation can also include the calculation of different charges like reinsurance premium, commission, other intermediary fees, risk premium, and so on. These charges need to be saved to the policy in a specific format. Read more about how to save these charges in the policy issue hook guide.

📘

Currency values are saved as integers in cents

All currency values are saved to the Root platform as integers in cents. This means that if the premium for a policy is $100.00 per month, it should be represented as 10000 in the product module code.

Calling external services

In some cases, the product module code may need to reference an external pricing or benefit engine maintained by the insurance provider or a third party. In other cases it might need to collect general IoT or risk data from an external source.

Provided that the external engine is exposed over an HTTP API, it can be consumed from within any product module code hook. Root enables the use of the fetch API for this purpose.

Dashboard quote workflow

This guide has covered how to configure the quote endpoint and pricing logic for your product, which receives the rating factors in the quote request payload on the quote API endpoint. This data needs to be captured and sent through to Root from your system, or it can be captured by an agent directly on the Root management dashboard.

If policies will be issued from the Root dashboard, you will need to configure the quote schema (workflow) for this product module. This involves specifying the input components (form elements) that will be displayed to the user on the dashboard's quote screen, and to which key in the quote request payload each input component corresponds.

1232

The dashboard quote screen for the Root Funeral product

This aspect is independent of the quote endpoint, and is not needed for API-only quotes and policy issuing. However, if used, it's critical to ensure the keys matchup between the schema and the quote validation rules.

Please see the schema guide for more details on configuring workflows for the dashboard.