
Policy documents, straight from the quote
Endorsement steps decide which schedules, forms and clauses belong on a policy. A Mustache or Handlebars template then reads the quote response to pick the sections and fill them in, for any line of business
Price, respond, render
Swallow doesn't hold your document layouts. It hands you a response with every decision already made, so your template only has to show it
Rules that pick the forms
Each item is a rule with a form code as its value. The rules that fire land in the response's endorsements list with the step key, the rule name, the values it saw, the code and its description
{
"id": "policy_forms",
"key": "policy_forms",
"step": "endorsements",
"name": "Policy forms",
"def": [],
"items": [
{
"id": "telematics",
"name": "Telematics fitted",
"exp": "{{telematics}} == true",
"value": "END_TELEMATICS",
"description": "Telematics data condition applies."
},
{
"id": "hazardous_goods",
"name": "Carries hazardous goods",
"exp": "{{hazardous_goods}} == true",
"value": "END_HAZ_GOODS",
"description": "ADR hazardous goods extension applies."
},
{
"id": "young_drivers",
"name": "Drivers under 25",
"exp": "{{drivers_under_25}} > 0",
"value": "END_YOUNG_DRIVER",
"description": "Young driver excess and named-driver condition apply."
},
{
"id": "vehicle_schedule",
"name": "More than 20 vehicles",
"exp": "{{vehicle_count}} > 20",
"value": "SCHED_VEHICLES",
"description": "Vehicles listed in a separate schedule."
}
]
}{
"quote_reference": "<uuid>",
"version_reference": "<uuid>",
"result": 17502.8,
"valid": true,
"input": {
"vehicle_count": 24,
"telematics": true,
"hazardous_goods": false,
"drivers_under_25": 2,
"region": "north_west"
},
"output": {
"risk_premium": 15627.5,
"ipt": 1875.3,
"compulsory_excess": 500,
"result": 17502.8,
"valid": true
},
"refers": [],
"exclusions": [],
"excesses": [
{
"step": "fleet_excesses",
"name": "Young driver excess",
"drivers_under_25": 2,
"exp": "{{drivers_under_25}} > 0",
"result": true,
"value": 250
}
],
"endorsements": [
{
"step": "policy_forms",
"name": "Telematics fitted",
"telematics": true,
"exp": "{{telematics}} == true",
"result": true,
"description": "Telematics data condition applies.",
"value": "END_TELEMATICS"
},
{
"step": "policy_forms",
"name": "Drivers under 25",
"drivers_under_25": 2,
"exp": "{{drivers_under_25}} > 0",
"result": true,
"description": "Young driver excess and named-driver condition apply.",
"value": "END_YOUNG_DRIVER"
},
{
"step": "policy_forms",
"name": "More than 20 vehicles",
"vehicle_count": 24,
"exp": "{{vehicle_count}} > 20",
"result": true,
"description": "Vehicles listed in a separate schedule.",
"value": "SCHED_VEHICLES"
}
]
}Three of the four rules fired. The fleet carries no hazardous goods, so END_HAZ_GOODS is missing and its section won't print. The API page has the full response
The response is the template data
Turn the form codes into flags, then hand the whole response to your template. Flags show or hide sections, partials hold each form's wording and output fields fill in the figures
import Mustache from "mustache";
// The response from POST /sw/quotes/:project_reference,
// or a saved quote from GET /sw/quotes/:quote_reference
const quote = await res.json();
// Turn the form codes into flags the template can test
const forms = Object.fromEntries(
quote.endorsements
.filter((e) => e.step === "policy_forms")
.map((e) => [e.value, true])
);
const html = Mustache.render(schedule, { ...quote, forms }, partials);<h1>Fleet policy schedule</h1>
<p>Policy {{quote_reference}} · {{input.vehicle_count}} vehicles</p>
<table>
<tr><td>Premium</td><td>{{output.risk_premium}}</td></tr>
<tr><td>Insurance Premium Tax</td><td>{{output.ipt}}</td></tr>
<tr><td>Total payable</td><td>{{result}}</td></tr>
<tr><td>Compulsory excess</td><td>{{output.compulsory_excess}}</td></tr>
</table>
{{#forms.SCHED_VEHICLES}}{{> vehicle_schedule}}{{/forms.SCHED_VEHICLES}}
{{#forms.END_TELEMATICS}}{{> telematics_condition}}{{/forms.END_TELEMATICS}}
{{#forms.END_HAZ_GOODS}}{{> hazardous_goods}}{{/forms.END_HAZ_GOODS}}
{{#forms.END_YOUNG_DRIVER}}{{> young_driver}}{{/forms.END_YOUNG_DRIVER}}
<h2>Endorsements</h2>
{{#endorsements}}
<p><strong>{{value}}</strong> {{name}}. {{description}}</p>
{{/endorsements}}The same syntax works in Mustache and Handlebars. Liquid, Jinja or a PDF generator that takes JSON work the same way
- Premium
- 15,627.50
- Insurance Premium Tax
- 1,875.30
- Total payable
- 17,502.80
- Compulsory excess
- 500
Every step feeds the document
Endorsements choose the sections. The rest of the model supplies what goes in them, and whether a document should go out at all
| Step | Document part | How it's used |
|---|---|---|
endorsements | Forms, schedules and clauses | Each rule that fires adds a code, and the template uses the codes to choose which sections and wordings appear |
excesses | Excess schedule | Rules that add excesses for a risk, such as young drivers or high-value items. Total them into an output field to print the figure |
exclusion · refer | Whether to issue at all | A declined quote comes back with valid false, so no document goes out. A referred one can wait for an underwriter first |
calculation | Premium breakdown | Net premium, tax, fees, commission and instalments, each as an output field and printed to the penny |
collection | Wording lookups | Tables of territory clauses, insurer details, regulatory text or limits by product, looked up per risk instead of hard-coded in the template |
transform | Display values | Labels, dates and text shaped for the document, such as a policy period or a cover description |
Documents that match the price
The rules about cover live in one place, get tested with the rating and go live as one version