# 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](https://root-bind-api.readme.io/docs/getting-started#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](https://root-bind-api.readme.io/docs/getting-started#how-to-use-the-prefill-report)
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.*
## 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 *four* pieces of information. * its current `value` * whether its current value is `valid` * a user-facing `message` which explains *why* the current value is invalid (on an empty quote most of these will be "can't be blank" ) * Individual `requirements` which intend to provide market-specific validation rules, dependent on their `kind` and associated `metadata` ```json "profileAttribute": { "value": string, "valid": boolean, "message": string, "requirements": Requirement[], } ``` #### 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](https://root-bind-api.readme.io/docs/estimated-quote-requirements) . 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: false`property). 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 ```json { "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](https://root-bind-api.readme.io/reference/createprefill), 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](https://root-bind-api.readme.io/reference/getprefill) 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 ```json json { "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\`] c 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. ```json { "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.