Skip to main content
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. For Quote–Policy mappings and JEXL transformations, see Conversion Rules.

Configuration-Driven

The Policy API works with the Configuration API. 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.

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. For how transactions place changes in time — effectiveDate vs transactionTimestamp, backdating, and booking ahead — see Effective Dates & the Policy Timeline. For a full worked example tracing 9 transactions through a realistic policy lifecycle, see the Lifecycle Walkthrough.

API Endpoints

Transactions (write)

Queries (read)

Contacts

Contacts are an unversioned link between a policy and a person in the company’s Directory. They are not part of any transaction: linking or unlinking creates no policy version and never changes coverage or pricing, and a contacts value inside transaction data is ignored. The current person IDs are also hydrated into every segment’s data.contacts on the read and list endpoints, for callers holding person.view, whichever version or effective date is requested.

Reporting

Validation

Configuration

Sandbox reset

deleteAll is a destructive Sandbox reset operation guarded by company.reset; it is safe to retry and returns the total rows removed.

Permissions

Example: Create a Policy

Request

POST /v1/policies/transaction/new-business
There are no top-level date parameters — the policy term comes solely from the policy’s own policyStartDate / policyEndDate root fields.

Response

201 Created

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 and take the canonical { "date": "2025-01-01", "timezone": "America/New_York" } object; timezone may be omitted and defaults to 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. 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, value, classification[, qualifier, earningSchedule]}, where classification must name a live entry in your company’s classification registry — and the platform computes the four read-only rollups (premium, taxes, fees, total) from them; caller-supplied rollup values are ignored and recomputed. The retired group / kind / earningBasis fields are ignored and discarded on input. See Pricing Component Identity
  • fullTermBillingInfo is optional — the term’s billing obligations per line item, { lines: [{ invoiceType, lineItem, direction, amount }] }, free of invoices, and derived by the platform on a cancel or reinstate when you omit it. See The Billing Aggregate. 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
  • 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

Policy validation and repair

Validate Policies runs stored-data checks including versionRegressions, which compares each selected version with its predecessor at matching segment dates. Findings identify paths and counts without exposing values. Versions without a comparable predecessor are reported as skipped. Staff and platform service identities can use POST /api/v1/companies/{companyId}/policies/repair for segmentHashes, joinHistory, or fieldValues. API keys cannot repair Policies. Hash and relationship scans default to dry run and return a cursor for bounded continuation. Field-value repairs require a reviewed manifest and matching pre/post fingerprints; stale data returns 409 without writing.