Transaction Model
Every change to a policy is recorded as an immutable transaction. Transactions are the single source of truth — policy state is always derived from them, never authored directly.Configure
Define your fields, option sets, and exposure types via the Configuration API.
Endorse
POST /{policyId}/transaction/endorse modifies the policy — add exposures, change field values, adjust coverage.Transaction Types
NEW_BUSINESS
Creates the policy. The effective date is the policy start date. Produces one segment covering the full term.
ENDORSE
Modifies policy state from a given effective date. Accepts an array of field-level deltas. May split existing segments or merge them if the change aligns state across periods.
CANCEL
Sets
policyStatus to "Cancelled" from the cancellation date through end of term. Optionally accepts billing-only deltas (e.g., short-rate penalties).REINSTATE
Sets
policyStatus back to "Active" from the reinstatement date. Optionally accepts billing-only deltas (e.g., reinstatement fees).RENEW
Creates a new policy term linked to the previous via
previousPolicyId. Accepts a full fieldModelV1Data payload — the caller provides the complete initial state for the new term.Effective Date vs Transaction Timestamp
Each transaction has two timestamps:effectiveDate— when the policy state changes. For an endorsement, this is when the new coverage begins. For a cancellation, this is when coverage ends.transactionTimestamp— when the business decision was made. Defaults to the current time, but can be set explicitly for imports (e.g., aligning to a bordereau booking date).
Deltas
A delta is a single field-level change within a transaction. Endorsements carry one or more deltas that describe exactly what changed, where, and for what date range.Delta Structure
| Field | Type | Description |
|---|---|---|
path | string | Dot-notation path to the field being changed |
action | string | Modify, Add, or Remove |
value | any | The new value, value to add, or value to remove |
startDate | string | Start of the date range this change applies to |
endDate | string | End of the date range this change applies to |
Delta Actions
Modify
Replace a scalar value or an entire object. This is the most common action.Add
Append to a collection. Uses set semantics — objects are matched byid, primitives by equality. If the value already exists, the delta is a no-op.
Remove
Remove from a collection. Same matching rules as Add. If the value is not present, the delta is a no-op.Path Notation
Paths use dot-notation to target fields at any depth. Bracket syntax targets specific items in an array by theirid field.
| Path | Targets |
|---|---|
policy.deductible | A scalar field on the policy |
policy.exposures[exp-1].bedCount | A field on a specific exposure |
policy.exposures | The exposures collection itself (for Add/Remove of entire exposure objects) |
policy.fullTermPolicyBilling | A cross-segment invariant (same value in every segment of the version) |
policy.policyStatus | The policy status (used internally by Cancel/Reinstate) |
Modify on an indexed path (e.g.,
policy.exposures[exp-1]) replaces the entire exposure object. Add on a collection path (e.g., policy.exposures) appends an exposure. These are different operations targeting different levels.Example: Endorsement with Deltas
An endorsement effective April 1 that adds a new exposure and updates billing:fullTermPolicyBilling delta spans the full policy term (Jan 1 – Dec 31) because it’s a cross-segment invariant — the system applies it identically to every segment.
Segments
A segment is a maximal contiguous date range where the policy state is identical.Segment Properties
Every version’s segments satisfy three invariants:- No overlaps — segments never share a date
- Full coverage — segments span the entire policy term with no gaps
- No adjacent duplicates — adjacent segments with identical state are automatically merged
How Segments Change
- Create
- Endorse (split)
- Correction (merge)
A new policy starts with one segment covering the full term.
| # | Date Range | Exposures |
|---|---|---|
| 1 | Jan 1 – Dec 31 | Main Hospital (120 beds) |
Versions
Each transaction produces a new policy version. A version is a complete snapshot — it contains the full set of segments representing the policy at that point in the transaction history.| Property | Description |
|---|---|
policyVersion | Sequential integer (1, 2, 3, …) |
transactionId | The transaction that produced this version |
segments | Complete set of segments for this version |
startDate / endDate | Policy term boundaries |
How It Works
When you submit a transaction, the system:- Loads the previous version — gets the current segments
- Applies deltas — applies each delta to all segments whose date range overlaps the delta’s date range
- Normalizes — produces deterministic JSON and computes a hash for each resulting segment
- Merges — collapses adjacent segments with identical hashes into one
- Persists — stores the new version with its segments
No-op deltas are safe. Adding a value that already exists or removing one that’s already gone has no effect. This means a delta that spans a wide date range may change some segments and leave others untouched — the system handles it correctly.
Premiums and Rating
The API does not calculate premiums. When you submit a transaction, you supply field values and billing totals yourself. The system stores what you send — it does not rate, pro-rate, or re-aggregate. Policy financial data lives at two levels:Full-Term Billing
fullTermPolicyBilling is a cross-segment invariant — identical across every segment in a version. It contains the billing summary for the entire policy term: policyPremium, policyTaxes, policyFees, policyGrandTotal. Every endorsement should include a fullTermPolicyBilling delta spanning the full policy term to keep billing current.
Per-Segment Rating
Each segment can carry its own rating data viaPolicyRatingResponse (on the policy) and ExposureRatingResponse (on each exposure). These typically include:
annualPremium— the premium as if that segment’s state applied for the full yearproratedPremium— the actual premium contribution for that time slice
fullTermPolicyBilling is not necessarily the sum of prorated slices. Full-term billing can include flat premium minimums, surplus lines taxes, policy fees, or other adjustments that are independent of per-segment proration. The FullTermPolicyRatingResponse (a separate cross-segment field) captures these aggregate rating details.Worked Example
A medical facility policy (Greenfield Medical Center) for Jan 1 – Dec 31 with one exposure. This shows the core segment behaviors — splitting, maintaining, and merging — with the actual delta payloads. Each endorsement also includes afullTermPolicyBilling update (omitted from the segment tables since it’s the same in every segment).
1. NEW_BUSINESS — 1 segment
1. NEW_BUSINESS — 1 segment
Create the policy with initial state spanning the full term. Grand total: 89,750.Segments:
| # | Date Range | Exposures |
|---|---|---|
| 1 | Jan 1 – Dec 31 | Main Campus (120 beds, 3 physicians) |
2. ENDORSE Apr 1: add satellite clinic — 2 segments
2. ENDORSE Apr 1: add satellite clinic — 2 segments
A satellite clinic opens. The Segments:
The original segment split at April — different exposure count on each side.
Add action appends a new exposure to the collection. Grand total increases to 103,400 (+13,650) — the additional exposure adds risk for the remaining 9 months.| # | Date Range | Exposures |
|---|---|---|
| 1 | Jan 1 – Mar 31 | Main Campus |
| 2 | Apr 1 – Dec 31 | Main Campus + West Clinic |
3. ENDORSE Jun 1: add physician + specialty — 3 segments
3. ENDORSE Jun 1: add physician + specialty — 3 segments
A new surgeon joins the main campus. Neurology added as a covered specialty. Grand total increases to 111,800 (+8,400) — the additional physician and expanded specialty coverage increase risk.Segments:
The Apr–Dec segment from version 2 split at the June boundary.
| # | Date Range | Physicians | Specialties |
|---|---|---|---|
| 1 | Jan 1 – Mar 31 | Patel, Nguyen, Hoffman | Cardiology, Orthopedics, Surgery |
| 2 | Apr 1 – May 31 | Patel, Nguyen, Hoffman | Cardiology, Orthopedics, Surgery |
| 3 | Jun 1 – Dec 31 | Patel, Nguyen, Hoffman, Okafor | Cardiology, Orthopedics, Surgery, Neurology |
4. Backdated corrections — merge to 2 segments
4. Backdated corrections — merge to 2 segments
Internal audit reveals the physician change, bed reduction, and Neurology addition should all have been effective April 1, not June 1. A single endorsement corrects everything retroactively. Grand total decreases to 106,550 (-5,250) — the physician departure and bed reduction reduce risk, partially offset by Neurology covering a longer period.All four per-segment deltas span Apr 1 – Dec 31. The Jun–Dec segment already had beds=110, Nguyen removed, Okafor present, and Neurology — those deltas are no-ops there. Only Apr–May changes. After applying, Apr–May and Jun–Dec have converged to identical state. The system merges them:Segments:
| # | Date Range | Beds | Physicians | Specialties |
|---|---|---|---|---|
| 1 | Jan 1 – Mar 31 | 120 | Patel, Nguyen, Hoffman | Cardiology, Orthopedics, Surgery |
| 2 | Apr 1 – Dec 31 | 110 | Patel, Hoffman, Okafor | Cardiology, Orthopedics, Surgery, Neurology |
Four transactions, two segments. The Apr–May / Jun–Dec boundary vanished — not because a transaction was reversed, but because the correction converged the per-segment state on both sides.
fullTermPolicyBilling didn’t affect the merge — it’s the same in every segment.Cancellation and Reinstatement
Cancel and reinstate modify only thepolicyStatus field. They are simpler than endorsements but follow the same segment mechanics.
- Cancel sets
policyStatusto"Cancelled"from the cancellation date through end of term. This typically splits the existing segment at the cancellation boundary. - Reinstate sets
policyStatusback to"Active"from the reinstatement date. If this makes the reinstated segment identical to its predecessor, they merge. - Both optionally accept billing-only deltas (restricted to
fullTermPolicyBillingpaths) for short-rate penalties or reinstatement fees.
A cancel followed by a reinstate at the same date is invisible in the final segments — the policy returns to the same state it had before cancellation. Both transactions are preserved in the audit trail, but the derived segments are identical to the pre-cancellation version.
Transaction Deletion
Only the most recent transaction on a policy can be deleted. Deleting a transaction:- Produces a new version derived from the prior transaction’s state
- Preserves the audit trail — the deleted transaction is archived, not erased
- Is irreversible through the API once deleted (the transaction can be re-created manually)
