GUIDES

Requirement sets

Write each consumer's insurance rules as a versioned requirement set, and every surface check and verdict for that consumer is measured against the version in force. A requirement set is named by a key (default default). A consumer can carry several side by side, and an insured takes one engagement per key, so add a key when a consumer needs different rules for different insureds. Each engagement reads the version its key has bound to it.

Creating a version

Create the consumer first with PUT /consumers/{consumer_ref}. POST /consumers/{consumer_ref}/requirement-sets returns 404 for a consumer it does not know.

POST /consumers/{consumer_ref}/requirement-sets takes JSON:

Field What it is
key Which of the consumer's requirement sets this version belongs to: lowercase letters, digits, - and _, up to 64 characters. A key not seen before starts a new one. Omitted, default
rules The rules, shaped as below
source_text The SOP as plain text, up to 200,000 characters, parsed into a draft. Send rules or source_text, one of the two
name, reverification_cadence, expiry_lead_days, review_states Stored on the version. reverification_cadence defaults to quarterly, expiry_lead_days to 30
publish, applies_to, grace_period_days, effective_on Publish in the same call. applies_to is required when publish is true. Not accepted with source_text

The response is 201 with the version object. Every version starts as a draft. Version numbers count per key: each requirement set starts at version 1, and (consumer_ref, key, version) names one version. The {version} routes below take an optional requirement_set query parameter, the key. Left off, they read the consumer's single set, or the one named default.

To parse an SOP file, send multipart/form-data with a source_document (PDF or DOCX) or a source_text field, plus an optional key. The draft carries parse_confidence per rule and ambiguities[], the places the SOP is too loose to enforce as written. Each ambiguity is an object: text, plus coverage_type, field and source (page, quote) when the parser can tell. The parser also keeps, for each rule, the source passage it read (page, quote), so the editor can show it next to the rule. Review the draft, then publish it. A multipart call with publish set returns 422.

A rule names a coverage type, the requirement, and two proof tests. Example:

{ "coverage_type": "auto_liability",
  "requirement": {"kind": "limit_min", "label": "combined_single_limit", "min": 1000000},
  "document_class_required": "coi", "verification_required": "broker",
  "require_own_coverage": false, "reverification_cadence": "monthly", "severity": "hard" }
Field Values
document_class_required The weakest document class you accept, from weakest to strongest: coi, endorsement, dec_page, policy. Default coi. A line below it reads unverified with reason document_class_below_required
verification_required Who has to confirm the line: none, broker, or carrier. Default broker. broker accepts a broker or carrier confirmation, carrier accepts only a carrier, and a carrier_feed confirmation counts as carrier. An unconfirmed line reads unverified with reason verification_pending
severity hard (default) or soft. hard rules decide status. soft results do not change it

A rule that fails to compile, such as an unknown coverage_type or state code, is dropped and listed in compile_errors on the version. A version with compile_errors cannot be published.

Rule keys

Insurance Verified assigns the rule_key, and it is the key you see on every surface check and verdict. On a plain rule, a rule_key you send is replaced.

The shape is <coverage_type>.<requirement kind>, plus a suffix where the kind can repeat with different parameters.

Requirement kind Key Example
line_required <coverage_type>.line_required auto_liability.line_required
limit_min <coverage_type>.limit_min.<limit label> general_liability.limit_min.each_occurrence
endorsement <coverage_type>.endorsement.<name> auto_liability.endorsement.additional_insured
occurrence_form <coverage_type>.occurrence_form.<value> general_liability.occurrence_form.occurrence
expiry_min_days <coverage_type>.expiry_min_days cargo.expiry_min_days
carrier_naic_allowlist <coverage_type>.carrier_naic_allowlist workers_comp.carrier_naic_allowlist
certificate_text <coverage_type>.certificate_text.<field>.<hash> general_liability.certificate_text.description_of_operations.3f9a2c
policy_form_accepted <coverage_type>.policy_form_accepted auto_liability.policy_form_accepted
Certificate holder certificate.holder certificate.holder

coverage_type is the canonical spelling: general_liability, auto_liability, workers_comp, occupational_accident, cargo, physical_damage, umbrella_excess, professional_eo, cyber, pollution, other. The short forms gl, al, auto, wc, oa, occ_acc, and umbrella are accepted and normalized to these.

An any_of rule keeps the rule_key you send. Left out, it defaults to the alternatives' coverage types joined by _or_, plus .any_of: workers_comp_or_occupational_accident.any_of.

What the certificate must show

The certificate holder is one rule for the whole set. Send it with "scope": "document" and no coverage_type:

{ "scope": "document", "severity": "hard",
  "requirement": {"kind": "certificate_text", "field": "certificate_holder",
                  "match": "includes", "value": "Dropoff Logistics LLC"} }
What you require Shape Checked against
Certificate holder The rule above, once per set The certificate's holder box, once per engagement. A miss fails the surface check with reason certificate_holder_mismatch. A source does not confirm this rule
Description of operations certificate_text with field: "description_of_operations" on a coverage line That line's certificate, description of operations box
Anything else certificate_text with field: "other" on a coverage line The certificate's full text: description of operations plus any free text read from it

match is includes (default) or equals. Case, punctuation, and spacing are ignored.

Auto policy form

policy_form_accepted names the auto policy forms a consumer accepts. It applies to auto_liability and physical_damage lines. On any other coverage type, the rule is dropped and listed in compile_errors with code policy_form_wrong_coverage.

{ "coverage_type": "auto_liability", "severity": "hard",
  "requirement": {"kind": "policy_form_accepted", "accepted": ["commercial"]} }

accepted lists any of commercial, personal_business_use, and personal, and defaults to ["commercial"]. Accepting personal also accepts personal_business_use. Insurance Verified reads a line's policy_form from the phrases printed on the document. A carrier's name alone does not set it.

What the paper states Rule reads Surface check
A form in accepted pass pass
A form outside accepted fail with reason policy_form_not_accepted fail
No form, on any document class unverified with reason policy_form_unconfirmed pass. The source confirms the form during verification

When one rule covers several ways to comply

Construct Shape Behavior
Alternatives any_of: [ {coverage_type, requirement, …}, … ] in place of one coverage_type and requirement The rule takes the best result among its alternatives, and satisfied_by names the alternative that produced it. The common case is workers' compensation or occupational accident
State conditions where: {"state_in": […]} or {"state_not_in": […]}, on a rule or on one alternative Applies only when the insured's state matches, and reads not_applicable otherwise. The state comes from insured_state on POST /​documents, else from the end of the address set with PUT /​insureds/​{insured_ref}. With no state on file, the rule reads unverified with reason state_unknown
Review states review_states on the set, default ["OH","ND","WA","WY"] When occupational accident wins an any_of rule for an insured in one of these states, the result keeps its outcome and carries state_review_required in flags and reasons

A not_applicable result does not change the status.

Publishing

POST /consumers/{consumer_ref}/requirement-sets/{version}/publish takes applies_to, grace_period_days (default 14), and an optional effective_on. Only a draft with no compile_errors publishes. Anything else returns 409. The prior published version of the same key becomes superseded.

applies_to What changes
new Engagements created from now on for this key bind to this version. Existing engagements keep the version they have, including an engagement with no version yet
all_active Every active engagement following this key is rebound to this version, and Insurance Verified re-issues its surface check against the new rules in the same call

A consumer's other keys, and their engagements, are untouched. GET /consumers/{consumer_ref}/requirement-sets lists every version across every key with its key, version, and status: draft, published, or superseded.

Before publishing all_active, call POST /consumers/{consumer_ref}/requirement-sets/{version}/preview with the same applies_to. It changes nothing and returns the impact:

Field What it is
counts Engagements per bucket: newly_failing, newly_insufficient, unchanged, improved
examples Up to 50 engagement ids per bucket
rule_failure_counts Per rule_key, how many engagements fail it under the new version
lines_needing_confirmation, lines_needing_confirmation_count Coverage lines whose confirmation is below the new rule's verification_required, up to 50 ids, and the total

With applies_to: new, every bucket is empty. The publish response has the same shape plus engagements_rebound. Publishing queues requirement_set.published with consumer_ref, requirement_set (the key), version, applies_to, grace_period_days, effective_on, and impact, which holds the same counts.

Publishing opens no verification request. A request opens on a later cycle, one per coverage line per consumer, once the engagement's whole surface check passes.

Grace

When you publish all_active, each rebound engagement the impact places in newly_failing or newly_insufficient gets grace_until, set to the publish time plus grace_period_days. Read it on the engagement: GET /engagements/{engagement_id} returns grace_until alongside the surface check and the verdict.

grace_until is informational. The re-issued surface check carries the status the new rules produce, and no status changes when grace_until passes. The grace_until field on a verdict object is null.

A parent's coverage line counts toward a child's rule only when the child has no line of that coverage type and the parent line's extends_to_children is true. While it is null, the rule reads unverified with reason parent_extension_unconfirmed. Set require_own_coverage: true on a rule to count only the insured's own lines.

Next