Documentation Index
Fetch the complete documentation index at: https://docs.aiinsurance.io/llms.txt
Use this file to discover all available pages before exploring further.
System objects are five built-in object shapes that FMV1 fields can be typed as. Unlike custom objects (which you define in your configuration spreadsheet), system objects have a fixed structure across every company and are recognized natively by the rating engine, snapshots, and bind logic.
You will encounter system objects whenever a field’s fieldType in your configuration is one of:
Object: Address
Object: CoverageLimit
Object: Currency
Object: Date
Object: QuoteBindError
Required-completeness rule
If a system-object field is provided in a create/update payload, every sub-field listed below is required. Partial values are rejected with HTTP 400 and a problem code naming the offending sub-field:
{
"error": {
"code": "InvalidFieldModelV1Data",
"message": "Field 'mailingAddress' is missing required sub-field 'county'"
}
}
The rule only fires when the parent field is provided. Omitting the field entirely is unchanged — system-object fields can still be optional at the field-definition level.
What counts as missing: null, undefined, or empty string (""). Numeric 0 and Boolean false are valid values. Whitespace-only strings (e.g. " ") currently slip past this validator — trim sub-field strings client-side before submitting.
Custom objects keep their existing rules. Sub-fields of a custom object follow each sub-field’s own requiredCondition from your configuration; only system objects are strict-by-default.
This rule applies to every FMV1 external write endpoint:
POST / PUT exposures, events, quotes
POST Basic Policies
- All segmented policy transactions (
new-business, endorse, renew)
POST / PUT custom objects (including a system-object sub-field nested inside a custom object)
Address
Structured postal address. Used wherever a property, mailing, or risk location appears in your field model.
| Sub-field | Type | Description |
|---|
street | string | Street number and route (e.g. "350 5th Avenue") |
city | string | City or locality |
state | string | State or first-order administrative region. US: 2-letter postal code |
county | string | County or second-order administrative area |
country | string | Country name |
zipCode | string | Postal / zip code as a JSON string. Always quoted ("02140", never 02140) |
{
"mailingAddress": {
"street": "350 5th Avenue",
"city": "New York",
"state": "NY",
"county": "New York County",
"country": "United States",
"zipCode": "10001"
}
}
zipCode must be a JSON string, never a number. JSON numbers cannot represent leading zeros — 02140 parses as 2140, silently corrupting the ZIP. The API rejects numeric zipCode values with 400:{
"error": {
"code": "InvalidAddressZipCode",
"message": "Field 'mailingAddress.zipCode' must be a string. JSON numbers cannot preserve leading-zero ZIP codes (e.g. \"02109\" parses as 2109); send the value as a string. Got number 2109."
}
}
This is the most common failure when payloads are generated from spreadsheets, OpenAPI codegen with the wrong type, or LLMs that “helpfully” unquote numeric-looking strings — always quote ZIP codes in your payload.
If your upstream data does not include county, call GET /api/external/companies/{companyId}/resolve-address first to derive a complete address before submitting.
CoverageLimit
A single coverage limit pair: a name and a monetary amount.
| Sub-field | Type | Description |
|---|
coverageLimitName | string | Display name (e.g. "Per Occurrence", "Aggregate") |
coverageLimitAmount | number | Limit value in the policy’s currency. 0 is valid (e.g. excluded peril) |
{
"perOccurrenceLimit": {
"coverageLimitName": "Per Occurrence",
"coverageLimitAmount": 1000000
}
}
Currency
A monetary value with its currency code.
| Sub-field | Type | Description |
|---|
value | number | Numeric amount. 0 is a valid value |
code | string | ISO 4217 currency code (e.g. "USD", "GBP", "EUR"). Empty strings are rejected |
{
"annualPremium": {
"value": 12500,
"code": "USD"
}
}
Date
A calendar date with an explicit timezone. The API accepts two input shapes and stores both in the canonical DMY form.
| Sub-field | Type | Description |
|---|
day | integer | Day of month, 1-based (1–31) |
month | integer | Month, 1-based (1=January, 12=December) |
year | integer | Four-digit calendar year |
timezone | string | IANA timezone identifier (e.g. "America/New_York", "UTC") |
{
"policyEffectiveDate": {
"day": 15,
"month": 3,
"year": 2026,
"timezone": "America/New_York"
}
}
You may also submit the ISO form on input — the API canonicalizes it to the DMY form before storage:
{
"policyEffectiveDate": {
"date": "2026-03-15",
"timezone": "America/New_York"
}
}
timezone is required in both shapes. Responses always use the DMY form.
QuoteBindError
A single bind-time error surfaced on a quote that failed to bind. The bind endpoint populates quoteBindErrors (an Object List of these) on the quote when bind fails; you generally do not write this directly.
| Sub-field | Type | Description |
|---|
message | string | Human-readable description of the bind failure |
{
"quoteBindErrors": [
{ "message": "Effective date is in the past" },
{ "message": "Coverage limit exceeds underwriter authorization" }
]
}
Cardinality
Any of these system objects can appear as a single value or as a list, depending on how the field is configured. List-cardinality fields enforce the same required-completeness rule per array element — each item must be a complete system object.
{
"additionalLocations": [
{
"street": "1 Main St",
"city": "Cambridge",
"state": "MA",
"county": "Middlesex County",
"country": "United States",
"zipCode": "02140"
},
{
"street": "500 Boylston St",
"city": "Boston",
"state": "MA",
"county": "Suffolk County",
"country": "United States",
"zipCode": "02116"
}
]
}