Getting Started

How to get started developing with Root Embedded Insurance

Overview

Root built a flexible suite of APIs to allow developers to build the best insurance buying experience for their customers. Although our APIs have flexibility to be used with whatever product or service our partners offer (i.e. car dealers, financial institutions, etc.), we recommend implementation to reflect something similar to the flow below.

We believe we are the insurance experts and you are experts of your customers so together building the best insurance buying experience is closer than you think.

What you'll be doing

The bulk of the time spent with our API will be building an insurance quote. A quote contains 3 key components:

  1. A profile/information about the customer, i.e. what people [drivers] and vehicles will be covered.
  2. coverages, i.e. what level of financial protection the customer wants insurance to cover in the event of a claim 1.
  3. premium, i.e. what this policy would cost1.

Once you and your customer have crafted an appealing quote your customer then needs to complete these two steps to make the quote a legal binding policy.

  1. Agree to a set of legal documents which set out the terms of the policy.
  2. Provide payment information.

At this point, the customer's policy is bound.

Concepts to Understand

Prefill

Prefill

When building the profile for a quote there is a feature in our APIs called prefill.

Why use prefill

There is a whole lot of information needed for quoting, which can be tedious and add unnecessary friction in the insurance buying process. Prefill allows us to gather a large majority of this information on the customer's behalf, creating an experience where the customer only has to review data rather than manually enter it.

In the Quote Relationship Diagram below notice Quote and Prefill are separated entity structures that can be related to each other. However, just because a prefill report was requested and created does not mean the prefill information has to be attached to the quote being built. This means to add the prefill information you will need to update the quote with the prefill information obtained. More details on how to use the prefill report are noted below

Quote Kind

Quote Kind

There are three kinds of quotes that will exist in our APIs.

  1. none
  2. estimated quote
  3. bindable quote

As the quote is built up the kind of quote will change accordingly. A quote with type none indicates a quote that's in progress, but has not yet received a premium amount. This is typically due to a lack of profile information (i.e. no drivers/vehicles or little validation on the profile).

Once a quote has enough information to generate a premium it will be in an estimated quote kind. An estimated quote is the time a customer will spend modifying their profile/coverage selection and be able to see the modification effect on the premium. An estimated quote is NOT a quote a customer can bind a policy with.

Finally, once a customer shows an intent on binding their quote, the quote will change to a bindable quote. Depending on the embedded experience indicating intent is handled differently (review embedded flow of choice to see more details). Indicating intent will allow Root to run a final series of reports, most notably MVR. The premium typically will not change from an estimated quote to a bindable quote when there is nothing of interest on these final reports.

Quote Relationship Diagram

Quote Relationship Diagram

Note: Not all attributes on each entity are represented here.

entity

Deciding Which Embedded Experience

Regardless of the embedded experience you are building towards (hosted or fully embedded), both recommended flows begin the same.

Initial Sequence Diagram

initial flow

1. Creating an Empty Quote

A quote will collect and maintain all the information needed to eventually bind a policy.

POST: https://{environment}.joinroot.com/bind_api/v3/quoting/quote

πŸ“˜

If planning to utilize prefill functionality, a customer consent timestamp attribute is required on the quote. This can be provided during initial quote creation or in a subsequent quote update.

This will return an empty quote payload. The empty quote will automatically create a single driver and vehicle. Since binding a policy requires at least 1 driver and 1 vehicle, both have been created already for you.

All attributes in the profile will come back as individual objects containing 3 pieces of information.

  • its current value
  • whether its current value is valid
  • a message why the current value is invalid (on an empty quote most of these will be "can't be blank" )
"profileAttribute": { "value": string "valid": boolean "message": string }

Utilizing API response fields to create estimated and bindable quotes

Although profile response attributes have been modeled to indicate whether they are required for quoting, some assumptions can be made.

In general, estimated quote (RC1) requirements are shared between all states/markets and can be viewed here .

In order to make the quote "bindable" from an estimation, you'll need to provide the remaining profile/driver/vehicle-related field values that indicate they are invalid (using the valid: falseproperty). Some fields are required depending on changing, market-specific information and are not documented here for this reason.

Additional Items to pay attention to here

  • quote.id - this is going to be the main id you use to reference through the quoting flow
  • quote.coverage - this is going to be empty, but will store all coverage information
  • quote.profile - this is going to contain all the information we have about your customer
  • quote.profile.policyholderDriverId - this is going to be your PNI and must match a driver.id of an existing driver.
  • quote.profile.customerConsentTimestamp - this is required to request prefill and to eventually produce a bindable quote. It is our way of knowing a customer consent to Root pulling 3rd party reports.
  • quote.profile.drivers[0].id - if this driver is intended to be the PNI, this id will match the policyholderDriverId . Additionally, in following steps when updating driver data, ensure this id is maintain so we know which driver you are intending to update.
  • quote.profile.drivers[0].prefillDriverId - in the following steps when updating driver data based on prefill driver data obtained, ensure this prefillDriverId is provided so we know this is covering a driver already identified. If a driver were to come back on a prefill report and the customer does not actively add them to the policy they will not be covered.
  • quote.profile.drivers[0].telematicsUserId - if you are utilizing our telematics scoring product ensure this telematicsUserId is provided so we know to link this driver to their driving data.

Example Empty Quote Payload

{ "quote": { "coverages": { "policy": [], "vehicles": [] }, "expiresOnOrBefore": null, "fullTermPayment": null, "id": "57925f42-c5e8-43ec-8861-766b8911adc0", "kind": "none", "monthlyTermPayments": null, "profile": { "address1": { "value": null, "valid": false, "message": "can't be blank" }, "city": { "value": null, "valid": false, "message": "can't be blank" }, "customerConsentTimestamp": { "value": null, "valid": false, "message": "can't be blank" }, "eDelivery": { "value": true, "valid": true, "message": null }, "email": { "value": null, "valid": false, "message": "can't be blank" }, "homeownerStatus": { "value": null, "valid": false, "message": "can't be blank" }, "phoneNumber": { "value": null, "valid": true, "message": null }, "policyholderDriverId": { "value": null, "valid": false, "message": "can't be blank" }, "rideshare": { "value": null, "valid": true, "message": null }, "state": { "value": null, "valid": false, "message": "can't be blank" }, "zip": { "value": null, "valid": false, "message": "can't be blank" }, "address2": { "value": null, "valid": true, "message": null }, "ratingMunicipality": { "value": null, "valid": true, "message": null }, "drivers": [ { "id": { "value": "12af081c-97b5-48bb-bf86-7b1a1cf5246a", "valid": true, "message": null }, "dob": { "value": null, "valid": false, "message": "can't be blank" }, "firstName": { "value": null, "valid": false, "message": "can't be blank" }, "lastName": { "value": null, "valid": false, "message": "can't be blank" }, "licenseNumber": { "value": null, "valid": false, "message": "can't be blank" }, "licenseState": { "value": null, "valid": false, "message": "can't be blank" }, "status": { "value": "Covered", "valid": true, "message": null }, "prefillDriverId": { "value": null, "valid": true, "message": null }, "telematicsUserId": { "value": null, "valid": true, "message": null }, "accidentPreventionCourse": { "value": null, "valid": true, "message": null }, "activeDutyMilitary": { "value": null, "valid": true, "message": null }, "ageWhenLicensed": { "value": null, "valid": true, "message": null }, "collegeGraduate": { "value": null, "valid": true, "message": null }, "gender": { "value": null, "valid": true, "message": null }, "goodStudent": { "value": null, "valid": true, "message": null }, "maritalStatus": { "value": null, "valid": true, "message": null }, "nameSuffix": { "value": null, "valid": true, "message": null }, "nationalGuardMember": { "value": null, "valid": true, "message": null }, "occasionalDriver": { "value": null, "valid": true, "message": null }, "refresherPreventionCourse": { "value": null, "valid": true, "message": null }, "yearsLicensedSelection": { "value": null, "valid": true, "message": null } } ], "driverVehicleAssignments": [], "vehicles": [ { "status": { "value": "Covered", "valid": true, "message": null }, "vin": { "value": null, "valid": false, "message": "can't be blank" }, "antiTheftEquipment": { "value": null, "valid": true, "message": null }, "garagingAddress1": { "value": null, "valid": true, "message": null }, "garagingAddress2": { "value": null, "valid": true, "message": null }, "garagingCity": { "value": null, "valid": true, "message": null }, "garagingState": { "value": null, "valid": true, "message": null }, "garagingZip": { "value": null, "valid": true, "message": null }, "make": { "value": null, "valid": true, "message": null }, "model": { "value": null, "valid": true, "message": null }, "purchaseDate": { "value": null, "valid": true, "message": null }, "vinEtching": { "value": null, "valid": true, "message": null }, "year": { "value": null, "valid": true, "message": null } } ] }, "status": "collecting_data" } }

2. Creating a Prefill Request

πŸ“˜

If you do not intend to use prefill to improve the insurance buying experience for customers please skip to step #4.

Once a quote has been rated with a kind of bindable_quote or finalized_quote, you may additionally utilize "Prefill" Reports to surface additional drivers and vehicles related to the PNI.

A subset of PII from the quoted profile is required in order to request a prefill, which will begin asynchronously retrieve information from Root's report vendors to resurfaced within the API.

POST: https://{environment}.joinroot.com/bind_api/v3/quoting/quote/{quote_id}/prefill

If successful this will return a 201 created. At this point you can attempt to retrieve the prefill report.

3. Retrieving Prefill Report

Attempting to retrieve results from an incomplete prefill will return a 204 No Content status code. Reports generally finish within several seconds but can take up to 35 seconds, so we suggest polling every two seconds until receiving a 200 indicating completion.

GET: https://{environment}.joinroot.com/bind_api/v3/quoting/quote/{quote_id}/prefill

Prefill Report Response

🚧

Drivers dob and driver's license (DL) will be returned obfuscated.

Example response

{ "prefillReport": { "drivers": [ { "dob": "1985-**-**", "firstName": "Root", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "isRequestedDriver": true, "lastName": "Rooterson", "licenseNumber": "*****456", "licenseState": "OH" }, { "dob": "2000-**-**", "firstName": "Insurance", "id": "cfc64e20-a1a1-11ed-a8fc-0242ac120002", "isRequestedDriver": false, "lastName": "Person", "licenseNumber": "*****654", "licenseState": "OH" } ], "vehicles": [ { "make": "Toyota", "model": "Rav4", "vin": "4S3BJ6321N6900903", "year": 2012 }, { "make": "Audi", "model": "TT", "vin": "TRUSC28N341016582", "year": 2004 } ] } }

How to use the prefill report

The prefill report is a great foundation for building a customer's profile on their behalf. Once retrieved, use the prefill report to build the request quote.profile.drivers and quote.profile.vehicles arrays. Since a driver's dob and licenseNumber on the prefill report are obfuscated, it is important to provide the prefill driver's id (prefillReport.drivers[0].id) when building a quote.profile.drivers[0].prefillDriverId.

The driver used to request the prefill report should be included in the list of drivers found in the report. Typically your requested driver would be the PNI of the policy. To determine which driver in the report was used to request the report check the isRequestedDriver boolean on each driver object.

How Root will be able to ingest [obfuscated] prefill data:

  1. Root receives a quote update request with a profile of the drivers
  2. Iterates through all drivers
    1. if the driver includes a prefillDriverId then Root looks for an existing prefill report
      1. if the report is found and prefillDriverId matches an id on the report, Root will merge the request driver data (provided) with the prefill driver data (from the prefill report). This way obfuscated data [dob/licenseNumber] can be submitted back to Root via the quote update request. Root will store the non-obfuscated data which will ensure the profile maintains its validity for quoting.

As this step can be a little complicated, please feel free to reach out to Root support for more details.

4. Submitting an Update Quote

Depending your desired customer experience there are a few design choices to make before starting with step 4.

  • Will the customer review Personal Identifiable Information or prefill report data prior to seeing a quote?
  • Is the goal to show an estimated quote quote to the customer before they interact with insurance at all?
  • Will you need multiple UI elements to gather all the required insurance information? In many instances, it is unreasonable to collect all of the profile information in one go. Depending on your business you may have common information you may readily have information like first and last name, but you might need a separate UI to gather vehicle information.

Assuming a design decision has been made at this point there is enough information to submit an updated quote.

PUT: https://{environment}.joinroot.com/bind_api/v3/quoting/quote/{quote_id}

Additional Items to pay attention to here

  • Ensure any prefill driver data added to a driver, include the prefillDriverId as well.
  • Review and address any invalid attributes on the quote.profile at this time.

Example of quote update using prefill

Here is an example quote update request payload based on using the empty quote and prefill examples above.

Notice how the profile.driver[0].id is the same id as returned from the initial quote created and still matches the profile.policyholderDriverId. The driver profile.driver[0] has a prefillDriverId matching the first driver from the prefill report (as does the second driver). Lastly, dob and licenseNumber are both using the obfuscated data from the prefill report. However, since the prefillDriverId exists for both Root will know how to gather the non-obfuscated data.

{ "profile": { "drivers": [ { "id": "12af081c-97b5-48bb-bf86-7b1a1cf5246a", "dob": "1985-**-**", "firstName": "Root", "prefillDriverId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "lastName": "Rooterson", "licenseNumber": "*****456", "licenseState": "OH" }, { "dob": "2000-**-**", "firstName": "Insurance", "prefillDriverId": "cfc64e20-a1a1-11ed-a8fc-0242ac120002", "lastName": "Person", "licenseNumber": "*****654", "licenseState": "OH" } ], "vehicles": [ { "make": "Toyota", "model": "Rav4", "vin": "4S3BJ6321N6900903", "year": 2012 }, { "make": "Audi", "model": "TT", "vin": "TRUSC28N341016582", "year": 2004 } ], "address1": "80 E Rich St", "city": "Columbus", "customerConsentTimestamp": "2023-02-21T09:46:33.000-05:00", "eDelivery": true, "email": "root@joinroot.com", "homeownerStatus": "own", "phoneNumber": "555-555-5555", "policyholderDriverId": "12af081c-97b5-48bb-bf86-7b1a1cf5246a", "state": "OH", "zip": "43215" } }

Footnotes:

  1. Implementation of this part only applies to the fully embedded experience.

What’s Next

Continue to the appropriate embedded experience

Did this page help you?