> ## 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.

# Object Primitives

> Built-in object types used as field values across FMV1 create/update payloads (Address, CoverageLimit, Currency, Date, QuoteBindError).

Object primitives are five built-in object shapes that FMV1 fields can be typed as. Unlike custom objects (which you define in your configuration spreadsheet), object primitives have a **fixed structure across every company** and are recognized natively by the rating engine, snapshots, and bind logic.

You will encounter object primitives 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 an object-primitive 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:

```json theme={null}
{
  "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 — object-primitive 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 object primitives 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 an object-primitive 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`) |

```json theme={null}
{
  "mailingAddress": {
    "street": "350 5th Avenue",
    "city": "New York",
    "state": "NY",
    "county": "New York County",
    "country": "United States",
    "zipCode": "10001"
  }
}
```

<Warning>
  **`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`:

  ```json theme={null}
  {
    "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.
</Warning>

If your upstream data does not include `county`, call [`GET /api/external/companies/{companyId}/resolve-address`](/api-v1-reference/address-tools/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) |

```json theme={null}
{
  "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 |

```json theme={null}
{
  "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"`) |

```json theme={null}
{
  "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:

```json theme={null}
{
  "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 |

```json theme={null}
{
  "quoteBindErrors": [
    { "message": "Effective date is in the past" },
    { "message": "Coverage limit exceeds underwriter authorization" }
  ]
}
```

***

## Cardinality

Any of these object primitives 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 object primitive.

```json theme={null}
{
  "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"
    }
  ]
}
```

***

## Related

* [Address resolution endpoint](/api-v1-reference/address-tools/resolve-address) — derive a complete `Address` (including `county`) from a freeform input string.
* [V1 API Changelog](/api-v1-reference/changelog) — the strict-validation rule was rolled out on 2026-04-28.
