Skip to content

Term life: API

The endpoints, the flow that binds a policy, the lifecycle and the error paths. The entities and fields are in Term life: data model, and the rules that apply on every call are in Conventions.

classDiagram
    class TermLifeCoverage {
        +UUID id
        +string policyNumber
        +DateTime inceptionDate
        +DateTime expiryDate
        +PolicyStatus status
        +int freeCoverLimit
        +int totalSumInsured
        +TermLifeType termLifeType
        +TermLifeRider[] coverRiders
        +create() TermLifeCoverage
        +retrieve(id) TermLifeCoverage
        +endorse(id) TermLifeCoverage
    }
    class LifeInsured {
        +UUID id
        +string firstName
        +string lastName
        +Date dob
        +int annualSalary
        +int sumInsured
    }
    class Beneficiary {
        +UUID id
        +string name
        +float share
    }
    TermLifeCoverage --> LifeInsured : covers
    TermLifeCoverage --> Beneficiary : pays

termLifeCoverage carries a multi-valued beneficiary reference. The beneficiary records themselves are created and maintained through core parties, because a beneficiary is a party like any other and can be named on more than one policy.

Beneficiaries are created and maintained through core parties, not here.

EndpointScopeWhat it does
POST /termLifeCoverageadminBind a policy against an existing life insured
GET /termLifeCoveragedeveloperList, filterable by policyNumber
GET /termLifeCoverage/{id}developerRetrieve one policy
PUT /termLifeCoverage/{id}adminReplace a policy
POST /termLifeCoverage/{id}:endorseadminAmend a policy in force, including adding or removing a rider
POST /termLifeCoverage/{id}:canceladminSurrender the policy
POST /termLifeCoverage/{id}:renewadminIssue a new coverage record for a new term
POST /lifeInsuredadminCreate a life insured
GET /lifeInsureddeveloperList
GET /lifeInsured/{id}developerRetrieve one
PUT /lifeInsured/{id}adminReplace one

A death claim goes to POST /claim like any other claim. See Claims.

sequenceDiagram
    participant Client as Client App
    participant Gateway as API Gateway
    participant Life as Term Life Service
    participant Party as Party Service
    Client->>Gateway: POST /lifeInsured {firstName, dob, occupation, annualSalary}
    Gateway->>Life: createLifeInsured(payload)
    Life-->>Gateway: 201 {lifeInsuredId}
    Client->>Gateway: POST /termLifeCoverage {policyholderId, lifeInsuredId, sumInsured, riders, termLifeType}
    Gateway->>Life: createTermLifeCoverage(payload)
    Life->>Party: validate policyholderId
    Life->>Life: validate riders against termLifeRiders enum
    Life->>Life: Persist with policyStatus=in force
    Life-->>Gateway: 201 {policyNumber, status: in force}
    Gateway-->>Client: 201 Created
stateDiagram-v2
    [*] --> InForce : POST /termLifeCoverage
    InForce --> InForce : :endorse (rider added/removed under endorsementType)
    InForce --> Cancelled : :cancel (surrender)
    InForce --> Lapsed : non-payment
    InForce --> Extended : :endorse with endorsementType=policy extension
    Extended --> InForce : extension term begins
    Cancelled --> [*]
    Lapsed --> [*]

This diagram is normative. A transition it does not draw is not one an implementation may make.

Two things this lifecycle does not contain, and both surprise people.

There is no underwriting. No quote, no decision, no declined state, no awaiting-medicals state. The record begins at in force, so everything between an application and a bound policy happens before the standard sees it. This is a genuine gap rather than a scope decision, and nothing in the standard closes it today.

There is no settled state. A death claim does not move the policy. It runs through Claims on the shared claim lifecycle, exactly as a motor or travel claim does.

flowchart TD
    A[POST /termLifeCoverage] --> B{LifeInsured exists?}
    B -->|No| E1[404 - lifeInsured not found]
    B -->|Yes| C{Riders all in termLifeRiders enum?}
    C -->|No| E2[400 - unknown rider]
    C -->|Yes| D{termLifeType in termLifeType enum?}
    D -->|No| E3[400 - unknown term life type]
    D -->|Yes| F{Inception < expiry?}
    F -->|No| E4[400 - invalid policy term]
    F -->|Yes| G[Persist with policyStatus=in force]
    G --> H[201 Created]