Insurance requirements
An insurance requirement is a set of minimum coverages a party must carry: which coverages are required, the minimum limits, and the endorsements (additional insured, waiver of subrogation, and so on). Parties are checked against their requirement. Under project compliance they are also checked against each project's requirement.
| Operation | Scope |
|---|---|
GET /insurance_requirements |
read |
GET /insurance_requirements/:id |
read |
POST /insurance_requirements |
read_write |
PATCH /insurance_requirements/:id |
read_write |
DELETE /insurance_requirements/:id |
read_write |
GET /coverage_types |
read |
The requirement entity
{
"id": 42,
"name": "Standard Subcontractor",
"default": true,
"individual": false,
"certificate_holder": "Example Builders\n1 Plaza\nAustin, TX 78701",
"description_of_operations": null,
"additional_insured_name": null,
"coverages": {
"gl": {
"required": true,
"per_occurance_minimum": 1000000,
"general_aggregate_minimum": 2000000,
"products_completed_operations_minimum": 2000000,
"additional_insured": true,
"subrogation_waiver": false,
"primary_non_contributory": false,
"review": false,
"...": "every other General Liability field"
},
"wc": {
"required": true,
"statutory_limits": true,
"employers_liability_each_accident_minimum": 1000000,
"employers_liability_disease_each_employee_minimum": 1000000,
"employers_liability_disease_policy_minimum": 1000000,
"subrogation_waiver": true,
"...": "every other Workers Compensation field"
},
"auto": { "required": false, "...": "..." },
"eo": { "required": true, "aggregate_limit_minimum": 1000000, "deductible_maximum": 10000 }
},
"created_at": "2026-01-10T12:00:00Z",
"updated_at": "2026-09-02T08:30:00Z"
}
coverages is one map keyed by coverage prefix, with one entry for every coverage type, each entry an object of that type's requirement fields. The prefixes are the same as on certificates (gl, auto, wc, umb, pl, im, gk, cg, oh, pollution, re, ava, db, pa, br, ti, cl, am, ab, and any other coverage type HoundDog defines, such as eo in the example). The set of coverage types can grow: discover the types and their keys with GET /coverage_types (below) instead of hardcoding them.
The keys inside an entry are the type's requirement fields, as GET /coverage_types lists them. For the types that have been part of HoundDog from the start, each key is the stored requirement column with its <prefix>_ removed, historic spellings included: General Liability's gl_per_occurance_minimum is coverages.gl.per_occurance_minimum, and Workers Compensation's wc_employers_liability_each_accident_minimum is coverages.wc.employers_liability_each_accident_minimum. Typical shapes:
required(boolean): the coverage must be present...._minimum(integer, dollars): a limit must be at least this...._maximum: a deductible or retention must be at most this.additional_insured,subrogation_waiver,primary_non_contributory(boolean): the endorsement must be shown.review(boolean): a submission that does not clearly meet this coverage goes to manual review instead of failing.
Some rules combine fields: the auto combined single limit can be met by the combined single limit or by all three split limits, and the auto vehicle types (any, owned, scheduled, hired, non-owned) are checked together. The compliance engine applies them; the fields are the inputs. GET /coverage_types marks those fields with the comparison custom. Two other rules are account- or engine-level and no comparison expresses them: an umbrella making up General Liability or auto shortfalls when the account allows it (the account settings apply_umb_to_gl_limits and apply_umb_to_auto_limits), and Assault & Battery satisfied through a General Liability policy that includes it (gl_ab_included on the certificate). The General Liability limit fields therefore stay greater.
Fields of features your account does not use are present with an empty value.
GET /insurance_requirements
The account's requirements in the collection envelope.
The requirements of your individuals are included and carry "individual": true.
GET /insurance_requirements/:id
One requirement.
POST /insurance_requirements
Creates a requirement. Body: name (required), default, certificate_holder, description_of_operations, additional_insured_name, coverages. Fields you omit keep their stored defaults, inside coverages too: an entry sets only the keys it carries.
{
"name": "Electrical",
"coverages": {
"gl": { "required": true, "per_occurance_minimum": 1000000, "additional_insured": true },
"wc": { "required": true, "employers_liability_each_accident_minimum": 500000 }
}
}
coveragesis checked when you write: a prefix that is not a coverage type, or a key that is not a field of that type (both asGET /coverage_typeslists them), is 422validation_failednaming it (for examplecoverages.gl.per_occurrence_minimum); so is a value of the wrong type for its field.- Creating a requirement with
default: truemakes it the account's only default requirement. The default requirement for individuals is a separate default and is untouched.
Response 201 with the entity.
PATCH /insurance_requirements/:id
Updates the fields you send. Inside coverages, each entry updates only the keys it carries; a coverage you leave out is untouched, and a value equal to what a read serves is left exactly as stored, so a read's body sent back changes nothing. Every party on the requirement
(directly or through a project)
is rechecked against it, so statuses can change and requests can start or complete. default: true has the same effect as on the create. On an account connected to JobTread, a rename is refused with 422 validation_failed naming name: contact HoundDog support to rename a requirement the JobTread integration tracks.
A requirement of your individuals carries what the dashboard's individual requirement form carries: its name, Personal Auto (pa) and the active coverage types eligible for individuals. Any other coverage type, and default, certificate_holder, description_of_operations and additional_insured_name, are not part of it: sent as null or as the value it holds (as a read serves them) they change nothing, and any other value is 422 naming coverages.<prefix> or the field. A read's body sent back is accepted.
Response 200 with the entity.
DELETE /insurance_requirements/:id
Deletes a requirement. 422 validation_failed when it is in use by a party, is the account's only requirement, or is the default (the same refusals as the dashboard).
It is also refused while a project uses it.
It is also refused while a compliance profile uses it.
Response 204.
GET /coverage_types
Every coverage type a requirement or a certificate can carry, with its requirement fields, in the collection envelope. Inactive types (no longer offered for new requirements, still read on existing ones) are included with "active": false.
{
"data": [
{
"prefix": "gl",
"name": "General Liability",
"active": true,
"individual_eligible": false,
"fields": [
{ "key": "required", "name": "General Liability Coverage", "type": "boolean", "comparison": "present", "requirement_suffix": "Required", "certificate_key": "present" },
{ "key": "per_occurance_minimum", "name": "Per Occurrence Limit", "type": "numeric", "comparison": "greater", "requirement_suffix": "At Least", "certificate_key": "limits_each_occurance" },
{ "key": "review", "name": "Review", "type": "boolean", "comparison": "setting", "requirement_suffix": null, "certificate_key": null }
]
},
{
"prefix": "eo",
"name": "Errors and Omissions",
"active": true,
"individual_eligible": false,
"fields": [
{ "key": "required", "name": "Errors and Omissions Coverage", "type": "boolean", "comparison": "present", "requirement_suffix": "Required", "certificate_key": "present" },
{ "key": "aggregate_limit_minimum", "name": "Aggregate Limit", "type": "numeric", "comparison": "greater", "requirement_suffix": "At Least", "certificate_key": "aggregate_limit" },
{ "key": "deductible_maximum", "name": "Deductible", "type": "numeric", "comparison": "lesser", "requirement_suffix": "At Most", "certificate_key": "deductible" },
{ "key": "review", "name": "Review", "type": "boolean", "comparison": "setting", "requirement_suffix": null, "certificate_key": null }
]
}
],
"total": 2,
"has_more": false,
"next_page": null
}
| Field | Meaning |
|---|---|
prefix |
The key of the type in coverages, on requirements and certificates |
name |
The type's display name |
active |
false for a type no longer offered for new requirements |
individual_eligible |
The type can be required of individuals |
fields[].key |
The key of the field in a requirement's coverages.<prefix> |
fields[].name |
The field's display name |
fields[].type |
boolean, numeric or text: the type of the value you write (and read). For a type HoundDog defines, it is how HoundDog reads the value: a field HoundDog defines as text, and any matches field, is text; any other field read as a number (a greater or lesser field, or one defined as a number) is numeric (whole numbers); the rest are boolean |
fields[].comparison |
How the certificate's value is checked against the requirement's (below) |
fields[].requirement_suffix |
The dashboard's wording for the comparison (At Least, At Most, Required, Matches, ...); null for a setting |
fields[].certificate_key |
The certificate value the field is checked against: the stored field name with <prefix>_ removed; null when the field is not compared with a certificate value. certificate_key names where the compared certificate value lives in coverages.<prefix>: present, additional_insured and subrogation_waiver at the entry's top level; the limit amounts in limits (every column whose name contains limit, except the General Liability general_aggregate_limit_applies_* boxes); everything else in fields (the type's other certificate fields, the GL aggregate-applies boxes and ab_included among them). On a certificate, a limit's key in limits follows the limits key rule (limits_each_occurance is limits.each_occurance) |
comparison is one of:
| Value | The requirement is met when |
|---|---|
present |
The coverage is on the certificate and in force (the required field of every type) |
greater |
The certificate's value is at least the requirement's |
lesser |
The certificate's value is at most the requirement's |
required |
The certificate shows it (a box or endorsement) |
matches |
The certificate's value equals the requirement's |
forbidden |
The certificate does not show it (for example wc.no_owner_exclusions) |
custom |
The compliance engine applies a combined rule (for example the auto combined single limit, met by the CSL or by all three split limits, and the auto vehicle types) |
setting |
Not compared with the certificate: it changes how the engine checks or routes the coverage (for example auto.type_accept_any_checked and the wc.accept_* options) |
none |
Recorded on the requirement; the compliance engine does not check it |
review is a setting too: it sends a submission that does not clearly meet the coverage to manual review.