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.- Configure your insurance program — define fields, option sets, exposure types
- Create policies via
POST /transaction/new-business - Manage the lifecycle — endorse, cancel, reinstate, renew
- 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 optionalinvoicePlan: 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
policyStartDate / policyEndDate root fields.
Response
201 Created
Key Points
- Term bounds come solely from the policy’s own
policyStartDate/policyEndDateroot fields — there are no top-level date parameters. They are ordinaryDatefields and take the canonical{ "date": "2025-01-01", "timezone": "America/New_York" }object;timezonemay be omitted and defaults toAmerica/New_York datacontains all policy-level fields at its top level — including any embedded exposure fields your configuration defines (e.g.primaryInsured/additionalExposuresin 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-requiredreferencedExposurescalculated 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, infieldModelV1Data.policypolicyStatus("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,policyStartDateandpolicyEndDateare on the response root and on every segment’spolicy, 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/primaryInsuredIdfields fullTermPricingInfois optional (a policy may carry no pricing info). SendpricingComponents— each{label, value, classification[, qualifier, earningSchedule]}, whereclassificationmust 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 retiredgroup/kind/earningBasisfields are ignored and discarded on input. See Pricing Component IdentityfullTermBillingInfois optional — the term’s billing obligations per line item,{ lines: [{ invoiceType, lineItem, direction, amount }] }, free of invoices, and derived by the platform on acancelorreinstatewhen you omit it. See The Billing Aggregate.fullTermPolicyRatingResultis optionaltransactionTimestampis 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
effectiveDatemust fall within the term (policyStartDate <= effectiveDate <= policyEndDate) — outside the term it is rejected with400. For howeffectiveDaterelates totransactionTimestampand to each delta’sstartDate, see Effective Dates & the Policy Timeline
Policy validation and repair
Validate Policies runs stored-data checks includingversionRegressions, 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.