curl --request POST \
--url https://go.aiinsurance.io/api/v1/companies/{companyId}/policies/{policyId}/transaction/cancel \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"cancellationDate": "2025-06-15"
}
'{
"policyId": "550e8400-e29b-41d4-a716-446655440001",
"policyVersion": 2,
"transactionId": "550e8400-e29b-41d4-a716-446655440040",
"startDate": "2025-01-01",
"endDate": "2025-12-31",
"createdAt": "2025-06-15T10:30:00.000Z",
"primaryInsuredName": "Mercy General Hospital",
"primaryInsuredId": "550e8400-e29b-41d4-a716-446655440010",
"policyNumber": "POL-2025-000123",
"policyStartDate": {
"date": "2025-01-01",
"timezone": "America/New_York"
},
"policyEndDate": {
"date": "2025-12-31",
"timezone": "America/New_York"
},
"fullTermPricingInfo": {
"premium": 42500,
"taxes": 0,
"fees": 500,
"total": 43000,
"pricingComponents": [
{
"label": "Policy Premium",
"classification": "policy-premium",
"qualifier": "",
"earningSchedule": "pro-rata",
"value": 42500
},
{
"label": "Cancellation Fee",
"classification": "cancellation-fee",
"qualifier": "",
"earningSchedule": "immediate",
"value": 500
}
]
},
"fullTermBillingInfo": null,
"fullTermPolicyRatingResult": null,
"segments": [
{
"startDate": "2025-01-01",
"endDate": "2025-06-14",
"transactionType": "CANCEL",
"data": {
"policyStatus": "active",
"cancellationEffectiveOnDate": {
"date": "2025-06-15",
"timezone": "America/New_York"
},
"annualPremium": 85000,
"fullTermPricingInfo": {
"premium": 42500,
"taxes": 0,
"fees": 500,
"total": 43000,
"pricingComponents": [
{
"label": "Policy Premium",
"classification": "policy-premium",
"qualifier": "",
"earningSchedule": "pro-rata",
"value": 42500
},
{
"label": "Cancellation Fee",
"classification": "cancellation-fee",
"qualifier": "",
"earningSchedule": "immediate",
"value": 500
}
]
}
}
},
{
"startDate": "2025-06-15",
"endDate": "2025-12-31",
"transactionType": "CANCEL",
"data": {
"policyStatus": "cancelled",
"cancellationEffectiveOnDate": {
"date": "2025-06-15",
"timezone": "America/New_York"
},
"annualPremium": 85000,
"fullTermPricingInfo": {
"premium": 42500,
"taxes": 0,
"fees": 500,
"total": 43000,
"pricingComponents": [
{
"label": "Policy Premium",
"classification": "policy-premium",
"qualifier": "",
"earningSchedule": "pro-rata",
"value": 42500
},
{
"label": "Cancellation Fee",
"classification": "cancellation-fee",
"qualifier": "",
"earningSchedule": "immediate",
"value": 500
}
]
}
}
}
]
}Cancel Policy Transaction
Cancels a policy as of a given date via a CANCEL transaction. The policy must be active at the cancellation date.
cancellationDate (= the transaction effective date) is sugar the server expands into
per-segment, segment-scoped deltas on framework-required fields. policyStatus flips to
cancelled from the cancellation date through end of term (splitting the segment at the
boundary), and a single cancellationEffectiveOnDate is recorded uniformly across the
whole term — the same value on both sides of the boundary. policyStatus alone marks
which side a segment is on. There is no policyEarlyTerminationDate and no status-enum
machinery.
A cancel never reprices — the pricing contract is DERIVED
The server computes what the cancelled term’s pricing contract must be, per charge. Every
pricing component the policy already carries stays present, keeps its label,
classification, qualifier and earningSchedule, and drops to its own earned amount
through the cancellation date. A charge modelled as immediately earned (earningSchedule: "immediate" — a non-refundable policy fee) therefore keeps its whole
value and is untouched by the cancellation; a pro-rata charge keeps the part the term has
run through. Nothing is relabelled and nothing is merged: a charge’s
<classification, qualifier> pair is its identity across policy versions, and the
platform’s revenue recognition and invoice binding both attribute money by it.
A bare { "cancellationDate": ... } body is the normal request, and it always
succeeds. Omit fullTermPricingInfo and the derived contract is used.
If you DO send fullTermPricingInfo, it is validated against that derived contract
component by component, to the exact cent:
- every component the policy already carries must be present, at exactly the derived value
and with the derived
earningSchedule; - an UNRECOGNIZED
<classification, qualifier>pair is an addition — money the cancellation itself creates, such as a short-rate penalty or a cancellation fee — and it MUST carryearningSchedule: "immediate", because it is recognized on the cancellation date rather than scheduled over coverage that is ending. An addition may name any live classification (including a premium one, for a short-rate penalty) and may be negative (a clawback).
Companies that tax through InsCipher. Where the company’s InsCipher lifecycle tax
sourcing is enabled, the server asks InsCipher what the state actually refunds on this
cancellation and appends its answer to the derived contract as additions of its own —
one immediate component per corrected tax, under that tax’s classification with a
reserved qualifier of the form inscipher-PC v3 (FC for a cancellation effective on
the policy’s first day; a state suffix where the charge is split by state). Their values
make the written total move by exactly what the state returns; the floors are untouched.
A supplied fullTermPricingInfo must include them, at the derived cents, like every other
derived component — which is one more reason to omit the container. If InsCipher cannot
answer while tax money is at stake, the cancellation is refused (502
inscipher-tax-calculation-failed, or 422 inscipher-lifecycle-tax-unpriceable
naming the gap) rather than booked on the floors alone.
Re-valuing, re-basing or dropping an existing component is rejected with a 400 naming it.
To CHANGE what the policy is priced at, book an endorsement at the same effective date
and then cancel: transactions sharing an effective date are applied in booking order
(ascending policyVersion), so the endorsement’s figures are what the cancellation floors
against. The same composition works after a reinstatement — reinstate, then endorse — to
reprice the restored term going forward.
Three optional derived channels are whole-object overwrites of a policy-root full-term container — necessarily whole-term, so none carries dates nor an element-level form:
fullTermPricingInfo— the full-term pricing contract, validated as described above.fullTermBillingInfo— the Billing Aggregate, the term’s billing obligations per line item. Omit it and the platform derives it, scaling thereceivablelines down to the earned floor with largest-remainder cent allocation and leavingpayablelines exactly as they are — commission clawback is contractual, so there is no defensible default. State it explicitly to override that; either way a stated aggregate is checked against the receivable checksum and the per-line vocabulary rules.fullTermPolicyRatingResult— the canonical policy-level rating result. Unvalidated and unconstrained: it is the rater’s own output, not the money the platform books.
Policy invoices. Optionally send invoicePlan, a fully explicit
keep/void/create plan. Nothing is defaulted or inferred. If cancellation
moves a billed policy’s pricing target, a conserving plan is required.
Required permission: policy.cancel
curl --request POST \
--url https://go.aiinsurance.io/api/v1/companies/{companyId}/policies/{policyId}/transaction/cancel \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"cancellationDate": "2025-06-15"
}
'{
"policyId": "550e8400-e29b-41d4-a716-446655440001",
"policyVersion": 2,
"transactionId": "550e8400-e29b-41d4-a716-446655440040",
"startDate": "2025-01-01",
"endDate": "2025-12-31",
"createdAt": "2025-06-15T10:30:00.000Z",
"primaryInsuredName": "Mercy General Hospital",
"primaryInsuredId": "550e8400-e29b-41d4-a716-446655440010",
"policyNumber": "POL-2025-000123",
"policyStartDate": {
"date": "2025-01-01",
"timezone": "America/New_York"
},
"policyEndDate": {
"date": "2025-12-31",
"timezone": "America/New_York"
},
"fullTermPricingInfo": {
"premium": 42500,
"taxes": 0,
"fees": 500,
"total": 43000,
"pricingComponents": [
{
"label": "Policy Premium",
"classification": "policy-premium",
"qualifier": "",
"earningSchedule": "pro-rata",
"value": 42500
},
{
"label": "Cancellation Fee",
"classification": "cancellation-fee",
"qualifier": "",
"earningSchedule": "immediate",
"value": 500
}
]
},
"fullTermBillingInfo": null,
"fullTermPolicyRatingResult": null,
"segments": [
{
"startDate": "2025-01-01",
"endDate": "2025-06-14",
"transactionType": "CANCEL",
"data": {
"policyStatus": "active",
"cancellationEffectiveOnDate": {
"date": "2025-06-15",
"timezone": "America/New_York"
},
"annualPremium": 85000,
"fullTermPricingInfo": {
"premium": 42500,
"taxes": 0,
"fees": 500,
"total": 43000,
"pricingComponents": [
{
"label": "Policy Premium",
"classification": "policy-premium",
"qualifier": "",
"earningSchedule": "pro-rata",
"value": 42500
},
{
"label": "Cancellation Fee",
"classification": "cancellation-fee",
"qualifier": "",
"earningSchedule": "immediate",
"value": 500
}
]
}
}
},
{
"startDate": "2025-06-15",
"endDate": "2025-12-31",
"transactionType": "CANCEL",
"data": {
"policyStatus": "cancelled",
"cancellationEffectiveOnDate": {
"date": "2025-06-15",
"timezone": "America/New_York"
},
"annualPremium": 85000,
"fullTermPricingInfo": {
"premium": 42500,
"taxes": 0,
"fees": 500,
"total": 43000,
"pricingComponents": [
{
"label": "Policy Premium",
"classification": "policy-premium",
"qualifier": "",
"earningSchedule": "pro-rata",
"value": 42500
},
{
"label": "Cancellation Fee",
"classification": "cancellation-fee",
"qualifier": "",
"earningSchedule": "immediate",
"value": 500
}
]
}
}
}
]
}Authorizations
API key authentication. Send your raw API key as the Authorization header value with NO scheme prefix — Authorization: YOUR-API-KEY. Do NOT prefix it with Bearer or ApiKey, and do not use an X-API-Key header; those are not accepted.
Path Parameters
Company identifier
Policy identifier
Body
The date the cancellation takes effect in ISO 8601 format. Must fall within the policy term, and the policy must be active at this date.
When the business decision was made. Defaults to the current time if omitted. Set explicitly for imports (e.g., aligning to a bordereau booking date).
OPTIONAL — omit it and the server derives the whole contract (recommended).
When supplied, it must be the derived contract plus additions: every component
the policy already carries, present at exactly its earned amount through the
cancellation date and with its existing earningSchedule, plus any NEW
<classification, qualifier> pairs (short-rate penalties, cancellation fees)
carrying earningSchedule: "immediate". Each component is
{label, value, classification[, qualifier, earningSchedule]} as documented
on the New Business Transaction endpoint — classification must name a
LIVE entry in your company's classification registry, on every component, for
every company (refusals are 400, InvalidFieldModelV1Data here). The four
rollups (premium, taxes, fees, total) are computed by the platform and
any you send are ignored. Compared to the exact cent — there is no tolerance.
The retired legacy fields (group/kind/earningBasis) are ignored and
discarded on input — never validated, never stored on a newly written
component — so a stored component that still echoes them can be posted back
unchanged. Omitting the container avoids the question entirely.
Optional whole-object overwrite of the policy-root Billing Aggregate — the term's billing obligations per line item. Structure is validated; it is not compared against the derived pricing contract.
Show child attributes
Show child attributes
Optional whole-object overwrite of the policy-root canonical rating result.
A fully explicit, detached policy-invoice batch. Existing invoices not named in voidInvoices are kept. The complete kept-plus-created set must conserve every bound component of the policy's current pricing contract.
Show child attributes
Show child attributes
Response
Policy cancelled successfully
Response returned by policy transaction endpoints. Contains the policy version produced by the transaction, including all derived segments.
Policy identifier
Sequential version number produced by this transaction
Identifier of the transaction that produced this version
Policy term start date (ISO 8601)
Policy term end date (ISO 8601)
When the transaction was created (ISO 8601)
Plain-text primary-insured name, read from the policy's own
primaryInsuredName field — the source of truth for the primary insured.
Reported as of the END of
the term, so a policy whose insured changed mid-term returns the later name;
segments[] carries the per-segment history. Null only when the version
carries no policy data.
Id of the entity behind primaryInsuredName. Null when the policy's
configuration does not populate it.
The policy number, read from the policy's own policyNumber field — the
source of truth, invariant across the whole term. Null only when the version
carries no policy data.
Policy term start date as the structured date object, read from the policy's
own policyStartDate field — the source of truth, invariant across the whole
term. This is not startDate above: that is the ISO
span this version covers, which a cancellation makes shorter than the term.
Null only when the version carries no policy data.
Show child attributes
Show child attributes
Policy term end date as the structured date object, read from the policy's own
policyEndDate field — the source of truth, invariant across the whole term.
This is not endDate above: that is the ISO
span this version covers. Null only when the version carries no policy data.
Show child attributes
Show child attributes
The policy's full-term pricing contract, hoisted as a read-once convenience
(also duplicated in every segment): pricingComponents plus the four
server-computed, read-only rollups — premium, taxes and fees (each
the sum of the components whose classification reports into it) and
total (premium + taxes + fees). All four
are always present. The retired brokerCommission / programCommission
rollups are no longer computed; a version stored before their retirement
may still return the two keys until the per-tenant data sweeps.
Each newly written component carries
{label, value, classification, qualifier, earningSchedule} —
<classification, qualifier> is its identity, and label is cosmetic.
The legacy vocabulary is retired: a component stored before the
retirement may still echo the group / kind / earningBasis keys
until the per-tenant data sweeps remove them — treat those as historical
output, never as identity, and do not rely on their presence.
The policy's Billing Aggregate for the term, hoisted as a read-once convenience (also duplicated in every segment). Null when the policy states no billing obligations.
Show child attributes
Show child attributes
Derived canonical policy-level rating result for the full term, hoisted as a
read-once convenience (also duplicated in every segment). Element-level rating
output (crossSegmentRatingOutputs) stays inline at its host and is not hoisted.
Derived segments for this policy version. Each segment represents a maximal contiguous date range where policy state is identical. Adjacent segments with identical data are automatically merged.
Show child attributes
Show child attributes
