> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go.aiinsurance.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Structured Field Values

> The Address, AddressV2, Date and StringOrNumber field types and their JSON values.

`Address`, `AddressV2`, `Date` and `StringOrNumber` each define their own JSON value shape. These shapes are shared across companies; a tenant configuration selects a field's type and does not redefine that type's members.

Read a field's `typeInfo.kind` from its configuration before writing its value. The API validates values against that declared field type on create and update, including values nested in custom objects and policy transactions. Invalid values receive a `400` response with the affected field path.

`Address` and `AddressV2` are independent field types with different shapes. A company may configure both. Custom objects such as `NumberLimit` instead define their members in the tenant's `objects` configuration.

## Address

Structured postal address as a single flat set of components. Used wherever a property, mailing, or risk location appears in your field model.

`Address` is a permanent field type with its own flat storage contract. It is not an alternate input shape for [`AddressV2`](#addressv2).

**Required sub-fields:** none. A partial address (e.g. `street` + `city`, no `county`) is valid — `Address` sub-fields are all optional, so partial address values are accepted. (Whether an address must exist at all is governed by the embedding field's own required condition.)

| Sub-field | Type   | Required | Description                                                                  |
| --------- | ------ | -------- | ---------------------------------------------------------------------------- |
| `street`  | string | no       | Street number and route (e.g. `"350 5th Avenue"`)                            |
| `city`    | string | no       | City or locality                                                             |
| `state`   | string | no       | State or first-order administrative region. US: 2-letter postal code         |
| `county`  | string | no       | County or second-order administrative area                                   |
| `country` | string | no       | Country name                                                                 |
| `zipCode` | string | no       | 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>

***

## AddressV2

A postal address modelled as an authoritative **entered** address plus an optional **geocode** computed from it.

`AddressV2` is **not** a superset of `Address` — the sub-fields are renamed and re-nested. A payload written for `Address` is not a valid `AddressV2`, and vice versa. Check the field's configured type before writing it; see the warning at the top of this page.

**Read one half or the other, never a blend.** `enteredAddress` is what a person typed or confirmed, and is the half to render as the address. `geocode` carries provider output only — county, coordinates, precision. There is deliberately no `county` in `enteredAddress` and no street text in `geocode`.

**Required sub-fields:** none at the top level; all three are optional, as is every sub-field of `enteredAddress`. The one requiredness rule sits inside `geocode`: if you send a `geocode` object at all, `status` and `source` must both be present and non-empty.

| Sub-field        | Type   | Required | Description                                                                                                                                                                     |
| ---------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enteredAddress` | object | no       | The address components as entered or confirmed (table below)                                                                                                                    |
| `entryMethod`    | string | no       | How the address was entered: `"autocomplete"` or `"manual"`. An input modality, not a quality signal — a manually entered address is geocoded exactly like an autocompleted one |
| `geocode`        | object | no       | Provider output for the entered address, or `null` when none has been recorded (table below)                                                                                    |

### `enteredAddress`

| Sub-field     | Type   | Required | Description                                                                            |
| ------------- | ------ | -------- | -------------------------------------------------------------------------------------- |
| `address1`    | string | no       | Street number and route (e.g. `"350 5th Avenue"`)                                      |
| `address2`    | string | no       | Unit, suite, floor or apartment designator (e.g. `"Apt 4"`). Does not affect geocoding |
| `city`        | string | no       | City or locality                                                                       |
| `state`       | string | no       | State or first-order administrative region. US: 2-letter USPS code                     |
| `zipCode`     | string | no       | Postal / zip code as a JSON string. Always quoted (`"02140"`, never `02140`)           |
| `countryCode` | string | no       | Country code or name supplied by the integration; no code list is enforced             |

There is no `county` here. County is provider output and lives on `geocode`.

### `geocode`

Never typed or edited by a user. `null` when no geocode has been recorded.

| Sub-field                 | Type   | Required | Description                                                                                                                                                                                                          |
| ------------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`                  | string | **yes**  | `"matched"` (a usable result), `"unmatched"` (the provider ran and returned nothing usable — re-running returns the same nothing), or `"failed"` (errored, timed out, or never ran — the only status worth retrying) |
| `source`                  | string | **yes**  | `"resolved"` (the platform called a geocoding provider) or `"provided"` (the caller supplied the result and it was stored as given)                                                                                  |
| `provider`                | string | no       | Name of the provider that produced the result. `null` for a caller-supplied geocode                                                                                                                                  |
| `placeId`                 | string | no       | Provider-specific identifier for the matched place, when the provider returns one                                                                                                                                    |
| `county`                  | string | no       | County or second-order administrative area as returned by the provider                                                                                                                                               |
| `location`                | object | no       | `{ latitude, longitude }` in decimal degrees, or `null` when the provider returned no geometry. Kept as a pair so a consumer never reads one coordinate without the other                                            |
| `granularity`             | string | no       | How precisely the coordinates locate the address, and therefore how far `county` can be trusted. Meaningful only when `status` is `"matched"`                                                                        |
| `geocodedFromFingerprint` | string | no       | Opaque marker of the entered components this result was computed from. Treat as opaque; do not parse it                                                                                                              |
| `geocodedAt`              | string | no       | ISO-8601 timestamp of when the geocode was produced                                                                                                                                                                  |

`granularity`, most precise first:

| Value                    | What the coordinates are pinned to                                                                                                                                                    |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `premise`                | A specific building or parcel. The county is that parcel's own                                                                                                                        |
| `route or address range` | The right street, interpolated between known house numbers. Accurate to a block                                                                                                       |
| `postal code`            | The ZIP centroid. No street survived the match, and a ZIP can straddle two counties, so the county is inferred from wherever the centroid lands. A PO Box with a valid ZIP lands here |
| `locality`               | The city or town centroid. The weakest county claim on the ladder                                                                                                                     |

### Writing an `AddressV2` field

Send `enteredAddress`. The platform geocodes server-side on save and fills `geocode` for you:

```json theme={null}
{
  "mailingAddress": {
    "enteredAddress": {
      "address1": "350 5th Avenue",
      "address2": "Suite 1200",
      "city": "New York",
      "state": "NY",
      "zipCode": "10001",
      "countryCode": "US"
    },
    "entryMethod": "manual"
  }
}
```

Reading the same field back returns the geocode alongside it:

```json theme={null}
{
  "mailingAddress": {
    "enteredAddress": {
      "address1": "350 5th Avenue",
      "address2": "Suite 1200",
      "city": "New York",
      "state": "NY",
      "zipCode": "10001",
      "countryCode": "US"
    },
    "entryMethod": "manual",
    "geocode": {
      "status": "matched",
      "source": "resolved",
      "provider": "google",
      "placeId": "ChIJ...",
      "county": "New York County",
      "location": { "latitude": 40.7484, "longitude": -73.9857 },
      "granularity": "premise",
      "geocodedFromFingerprint": "...",
      "geocodedAt": "2026-08-14T14:32:07.412Z"
    }
  }
}
```

Four behaviours worth knowing before you write one:

* **Geocoding never gates the write.** A provider miss or outage is recorded as an `"unmatched"` or `"failed"` geocode, not a `4xx` or `5xx` on your save.
* **You can supply your own geocode.** Send it with `source: "provided"` and it is stored as given, with no provider lookup. A `geocode` sent with any other `source` is discarded and replaced by the platform's own result.
* **An unchanged entered address keeps its geocode verbatim.** `address2` is excluded from the components the geocode is computed from, so adding a suite number to an already-matched address does not re-geocode it or lose its match.
* **Only top-level `AddressV2` fields are geocoded on save.** An `AddressV2` value nested inside a custom object is stored as you send it.

<Warning>
  **`zipCode` must be a JSON string, never a number** — same reason as on `Address`. JSON numbers cannot represent leading zeros, so `02140` parses as `2140` and silently corrupts the ZIP. On `AddressV2` the path is `enteredAddress.zipCode`, and a numeric value is rejected with `400` as an ordinary shape violation:

  ```json theme={null}
  {
    "error": {
      "code": "InvalidFieldModelV1Data",
      "message": "Field 'mailingAddress.enteredAddress.zipCode' expected string, got number"
    }
  }
  ```
</Warning>

***

## Date

A calendar day pinned to an IANA time zone — the day a person wrote on the policy, not an instant. One canonical form, stored and returned as-is.

**Required sub-field:** `date`. `timezone` is optional on a write (it defaults to `America/New_York`) and is always present in a response.

| Sub-field  | Type   | Required | Description                                                                                                                                            |
| ---------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `date`     | string | yes      | The calendar day as `YYYY-MM-DD`, zero-padded. Must name a real calendar day — `"2026-02-30"` is rejected with `400`                                   |
| `timezone` | string | no       | IANA time zone identifier (e.g. `"America/New_York"`, `"UTC"`). `"UTC"` and its alias `"Etc/UTC"` are accepted; an unknown zone is rejected with `400` |

```json theme={null}
{
  "inspectionDate": {
    "date": "2026-03-15",
    "timezone": "America/New_York"
  }
}
```

This shape is accepted on **every** FMV1 write path — entity CRUD (exposures, events, quotes, custom objects) and policy transactions alike — and responses always use it.

The policy term dates are no exception: the root `policyStartDate` / `policyEndDate` on policy transactions are ordinary `Date` fields and accept this canonical object. See the [policy transaction endpoints](/api-reference/policies/overview).

The policy endorsement `deltas` channel stores each value exactly as sent, so for a `Date` field it accepts **only** this shape, with both sub-fields stated — see the [API changelog](/api-reference/changelog) entry of 2026-09-04.

***

## StringOrNumber

A discriminated value that is *either* a string *or* a number, chosen per-row. The two typed slots are mutually exclusive — the inactive one is `null`.

**Required sub-fields:** `kind`. The `text` / `number` slots are optional (the inactive slot is `null`).

| Sub-field | Type   | Required | Description                                                             |
| --------- | ------ | -------- | ----------------------------------------------------------------------- |
| `kind`    | string | yes      | Discriminator: `"text"` or `"number"` — selects which slot is populated |
| `text`    | string | no       | The string value when `kind` is `"text"`; `null` otherwise              |
| `number`  | number | no       | The numeric value when `kind` is `"number"`; `null` otherwise           |

```json theme={null}
{
  "deductibleOrWaiver": {
    "kind": "number",
    "number": 5000,
    "text": null
  }
}
```

***

## Cardinality

Any of these field types can appear as a single value or as a list, depending on how the field is configured. List-cardinality fields enforce the same field-type validation **per array element** — each item must satisfy its type's value contract.

```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

* [V1 API Changelog](/api-reference/changelog) — the strict-validation rule was rolled out on 2026-04-28 and corrected to field-type requiredness on 2026-06-26.
