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

# Overview

> Transaction-based policy management with temporal versioning

The FMV1 Policy API manages policies through immutable transactions. Each transaction (new business, endorsement, cancellation, reinstatement, renewal) produces a new policy version with a complete set of time-based segments.

## Configuration-Driven

The Policy API works with the [Configuration API](/api-reference/configuration/overview). The same field definitions you configure — policy fields, exposure fields, option sets — are the fields you write when creating policies through transactions.

1. **Configure** your insurance program — define fields, option sets, exposure types
2. **Create policies** via `POST /transaction/new-business`
3. **Manage the lifecycle** — endorse, cancel, reinstate, renew
4. **Query state** — get a policy at any point in time, see full audit trail

## Core Concepts

### Transactions

Policies are modified through immutable transactions. Each transaction records what changed and produces a new policy version.

Every transaction may also carry an optional `invoicePlan`: a fully explicit
keep/void/create plan for the policy's invoice set. Omit it to create no invoices.
If a pricing change restates a policy that already has active invoices, the plan
is required and must conserve every pricing component against the new contract;
the policy version and invoice batch commit atomically.

| Transaction      | Description                                                       |
| ---------------- | ----------------------------------------------------------------- |
| **New Business** | Creates a new policy with initial state                           |
| **Endorse**      | Modifies an existing policy (add/remove exposures, change fields) |
| **Cancel**       | Cancels a policy from a given date                                |
| **Reinstate**    | Reinstates a previously cancelled policy                          |
| **Renew**        | Renews a policy for a new term                                    |

### Segments

A segment is a date range where policy state is identical. Segments are **derived from final state** — they are not one-to-one with transactions. Adjacent segments with identical data are automatically merged.

For example, three transactions can produce a single segment if the net effect returns the policy to a uniform state across the term.

### Versions

Each transaction produces a new version with a complete set of segments representing the full policy timeline. You can query any historical version.

For a deeper explanation of these concepts, see [Concepts](/api-reference/policies/concepts). For how transactions place changes in time — `effectiveDate` vs `transactionTimestamp`, backdating, and booking ahead — see [Effective Dates & the Policy Timeline](/api-reference/policies/effective-dates). For a full worked example tracing 9 transactions through a realistic policy lifecycle, see the [Lifecycle Walkthrough](/api-reference/policies/lifecycle-walkthrough).

## API Endpoints

### Transactions (write)

| Method | Endpoint                                               | Description                                                                                                         |
| ------ | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| POST   | `/v1/policies/transaction/new-business`                | Create a new policy                                                                                                 |
| POST   | `/v1/policies/{policyId}/transaction/endorse`          | Endorse an existing policy                                                                                          |
| POST   | `/v1/policies/{policyId}/transaction/cancel`           | Cancel a policy                                                                                                     |
| POST   | `/v1/policies/{policyId}/transaction/reinstate`        | Reinstate a cancelled policy                                                                                        |
| POST   | `/v1/policies/transaction/renew`                       | Renew a policy for a new term                                                                                       |
| POST   | `/v1/quotes/{quoteId}/bind`                            | Bind a quote into a policy in one call — dispatches on quote type *(quote-addressed, hence the `/v1/quotes/` path)* |
| POST   | `/v1/financials/policies/{policyId}/invoices/batch`    | Apply an explicit atomic keep/void/create plan outside a policy transaction                                         |
| PATCH  | `/v1/policies/{policyId}/transactions/{transactionId}` | Set a transaction's user-visible `displayAuthor` label (display metadata only)                                      |
| DELETE | `/v1/policies/{policyId}/transactions/{transactionId}` | Delete most recent transaction                                                                                      |

### Queries (read)

| Method | Endpoint                                               | Description                                                             |
| ------ | ------------------------------------------------------ | ----------------------------------------------------------------------- |
| GET    | `/v1/policies/list`                                    | List policies (latest version per policy, with segment scope filtering) |
| GET    | `/v1/policies/versions`                                | List policy versions across all policies                                |
| GET    | `/v1/policies/{policyId}/versions/{version}`           | Get a specific policy version with segments                             |
| GET    | `/v1/policies/{policyId}/versions`                     | List versions for a single policy                                       |
| GET    | `/v1/policies/{policyId}/transactions`                 | Transaction audit trail                                                 |
| GET    | `/v1/policies/{policyId}/transactions/{transactionId}` | Get a single transaction with deltas                                    |

### Reporting

| Method | Endpoint                          | Description                          |
| ------ | --------------------------------- | ------------------------------------ |
| GET    | `/v1/policies/bordereau`          | List bordereau rows (paginated JSON) |
| GET    | `/v1/policies/bordereau/download` | Download bordereau as CSV            |
| POST   | `/v1/policies/bordereau/export`   | Export bordereau to Google Sheets    |

### Validation

| Method | Endpoint                           | Description                                 |
| ------ | ---------------------------------- | ------------------------------------------- |
| GET    | `/v1/policies/{policyId}/validate` | Validate a single policy's data consistency |
| GET    | `/v1/policies/validate`            | Validate multiple policies in batch         |

### Configuration

| Method | Endpoint                            | Description             |
| ------ | ----------------------------------- | ----------------------- |
| GET    | `/v1/entities/policy/configuration` | Get field configuration |

## Permissions

| Operation                                                                            | Permission               |
| ------------------------------------------------------------------------------------ | ------------------------ |
| List, Get, Configuration, History, Reporting (Earned Premium, Bordereau), Validation | `company.policy:read`    |
| New Business, Renew, Bind Quote                                                      | `company.policy:create`  |
| Endorse, Cancel, Reinstate                                                           | `company.policy:update`  |
| Update Policy Invoices                                                               | `company.payment:update` |
| Delete Transaction                                                                   | `policy:delete`          |

## Example: Create a Policy

### Request

```json POST /v1/policies/transaction/new-business theme={null}
{
  "data": {
    "policyStatus": "active",
    "annualPremium": 85000,
    "policyStartDate": { "year": 2025, "month": 1, "day": 1, "timezone": "America/New_York" },
    "policyEndDate": { "year": 2026, "month": 1, "day": 1, "timezone": "America/New_York" },
    "fullTermPricingInfo": {
      "pricingComponents": [
        { "label": "Policy Premium", "group": "Policy Invoice", "kind": "Premium", "value": 85000 },
        { "label": "Policy Fee", "group": "Policy Invoice", "kind": "Fees", "value": 500 }
      ]
    },
    "additionalExposures": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440011",
        "exposureType": "MedicalFacility",
        "bedCount": 120
      }
    ]
  }
}
```

There are no top-level date parameters — the policy term comes solely from the policy's own `policyStartDate` / `policyEndDate` root fields.

### Response

```json 201 Created theme={null}
{
  "policyId": "550e8400-e29b-41d4-a716-446655440001",
  "policyVersion": 1,
  "transactionId": "550e8400-e29b-41d4-a716-446655440002",
  "startDate": "2025-01-01",
  "endDate": "2026-01-01",
  "createdAt": "2025-01-15T10:30:00.000Z",
  "primaryInsuredName": "Mercy General Hospital",
  "primaryInsuredId": "550e8400-e29b-41d4-a716-446655440010",
  "policyNumber": "POL-2025-000123",
  "policyStartDate": { "year": 2025, "month": 1, "day": 1, "timezone": "America/New_York" },
  "policyEndDate": { "year": 2026, "month": 1, "day": 1, "timezone": "America/New_York" },
  "fullTermPricingInfo": {
    "premium": 85000,
    "taxes": 0,
    "fees": 500,
    "brokerCommission": 0,
    "programCommission": 0,
    "pricingComponents": [
      { "label": "Policy Premium", "group": "Policy Invoice", "kind": "Premium", "earningBasis": null, "value": 85000 },
      { "label": "Policy Fee", "group": "Policy Invoice", "kind": "Fees", "earningBasis": null, "value": 500 }
    ]
  },
  "fullTermPolicyRatingResult": null,
  "segments": [
    {
      "startDate": "2025-01-01",
      "endDate": "2026-01-01",
      "data": {
        "policyStatus": "active",
        "policyStartDate": { "year": 2025, "month": 1, "day": 1, "timezone": "America/New_York" },
        "policyEndDate": { "year": 2026, "month": 1, "day": 1, "timezone": "America/New_York" },
        "primaryInsuredId": "550e8400-e29b-41d4-a716-446655440010",
        "primaryInsuredName": "Mercy General Hospital",
        "annualPremium": 85000,
        "fullTermPricingInfo": { "...": "..." },
        "additionalExposures": [
          {
            "id": "550e8400-e29b-41d4-a716-446655440011",
            "exposureType": "MedicalFacility",
            "bedCount": 120
          }
        ]
      }
    }
  ]
}
```

### Key Points

* **Term bounds come solely from the policy's own `policyStartDate` / `policyEndDate` root fields** — there are no top-level date parameters. They are ordinary `Date` fields, so either generic shape works: `{ "date": "2025-01-01", "timezone": "America/New_York" }` or `{ "year": 2025, "month": 1, "day": 1, "timezone": "America/New_York" }`
* **`data`** contains all policy-level fields at its top level — including any embedded exposure fields your configuration defines (e.g. `primaryInsured` / `additionalExposures` in the default configuration). Their shape is whatever your tenant configuration says; they are validated per-field like any other field. From those embedded values the framework-required `referencedExposures` calculated field derives the flat list of Exposure ids the policy references — see [Framework-Required Rows](/api-reference/configuration/overview#framework-required-rows). Before 2026-08-05 these same fields sat one level deeper, in `fieldModelV1Data.policy`
* **`policyStatus`** (`"active"` / `"cancelled"`) is a segment-scoped policy field, so it varies across the term — read it per segment
* **The whole-term policy facts live at the response root.** `policyNumber`, `policyStartDate` and `policyEndDate` are on the response root and on every segment's `policy`, and nowhere else
* **The primary insured is derived, not sent.** It comes from the policy's own exposures; read it back from the response's root **`primaryInsuredName`** / **`primaryInsuredId`** fields
* **`fullTermPricingInfo`** is optional (a policy may carry no pricing info). Send `pricingComponents` — each `{label, group, kind, value[, earningBasis]}` — and the platform computes the five read-only rollups (`premium`, `taxes`, `fees`, `brokerCommission`, `programCommission`) from them; caller-supplied rollup values are ignored and recomputed. **`fullTermPolicyRatingResult`** is optional
* **`transactionTimestamp`** is optional — defaults to the current time if omitted. When set explicitly on a later transaction it must be `>=` the latest already on the policy (the audit axis only moves forward); effective dates may still backdate freely. See [Effective Dates & the Policy Timeline](/api-reference/policies/effective-dates#precedence-and-monotonicity)
* **A transaction's `effectiveDate` must fall within the term** (`policyStartDate <= effectiveDate <= policyEndDate`) — outside the term it is rejected with `400`. For how `effectiveDate` relates to `transactionTimestamp` and to each delta's `startDate`, see [Effective Dates & the Policy Timeline](/api-reference/policies/effective-dates)
