Invoices and Payments

This article explains how to trigger billing, pay, and invoices in Socotra.

Overview

What will I learn?

By the end of this walkthrough, you will have an understanding of:

  • When billing is triggered.

  • The basics of installment lattices, installments, invoices, and payments.

  • How to create a quote for a new business, bill it, and pay a generated invoice.

What will I need?

You will need the following:

For more information about using Postman, see: Set up Postman to use the Socotra API

What is the billing life cycle?

In Socotra, the billing life cycle is a set of processes that handles calculating charges and building invoices for insurance policies.

The billing life cycle also handles receiving and distributing payments towards invoices.

Walkthrough the billing life cycle

The billing life cycle has six sequential stages:

  1. Quote is issued (via API)

  2. System generates an installment lattice

  3. System generates installments

  4. System generates invoice(s)

  5. Payment is created (via API)

  6. Payment is posted to invoice(s) (via API)

We’ll cover each step in the subsections below.

Stage 1: Quote is issued (via API)

The first stage of the billing life cycle occurs when a quote is issued.

Note: For more information on how to issue a quote, see: Execute a quote to bind in Socotra EC

Before a quote is issued, all of the requested insurance coverages are priced. That means that all of the charges related to the insurance coverage are calculated. Several types of charges can apply to insurance coverage, including:

  • premiums

  • taxes

  • fees

  • credits

  • ceded premiums

  • non-financial charges

  • surcharges

When the quote is issued, all of the pricing information is sent to the Socotra billing service.

At this point, the billing service’s main priority is to create one or more invoices for the insurance policy term. To accomplish that, it uses a data structure called an installment lattice.

Stage 2: System generates an installment lattice

After receiving all of the pricing information from the quote, the next stage of the billing life cycle is for the system to generate an installment lattice.

  • An installment lattice is a data structure that divides an insurance policy term into one or more frames.

  • A frame is a data object that represents a single subdivision of an insurance policy term.

The number of frames an installment lattice contains depends on the installment plan used in the quote/policy.

Let’s consider the following example: A person buys a homeowner’s insurance policy, and the term’s expected duration is 12 months. When the billing life cycle creates an installment lattice for the term, the number of frames it contains depends on the installment plan.

Installment plan

# of months in term

# of frames

Quarterly

12

4

Monthly

12

12

Monthly 10

12

10

The code block below shows an installment lattice for an insurance policy term that lasts 12 months and has a “Monthly 10” installment plan.

{
    "locator": "01J5E66WEQV8GGKSH5RTQAYCTB",
    "settingsLocator": "01J5E66WEK8SNY0QWJPSBKAVWG",
    "createdAt": "2024-08-16T18:11:46.092575Z",
    "createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
    "accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
    "termStartTime": "2024-01-01T00:00:00Z",
    "termEndTime": "2025-01-01T00:00:00Z",
    "termLocator": "01J5E660YXGBBNT26TQESCZHQF",
    "quoteLocator": "01J5E660YXGBBNT26TQESCZHQF",
    "policyLocator": "01J5E660YXGBBNT26TQESCZHQF",
    "currency": "USD",
    "timezone": "America/New_York",
    "effectiveTime": "2024-01-01T00:00:00Z",
    "frames": [
        {
            "installmentStartTime": "2024-01-01T00:00:00Z",
            "installmentEndTime": "2024-01-31T05:00:00Z",
            "coverageStartTime": "2024-01-01T00:00:00Z",
            "coverageEndTime": "2024-03-06T06:32:44Z",
            "normalizedWeight": 0.181818181818,
            "coverageDuration": 2.170088112306,
            "generateTime": "2023-12-17T05:00:00Z",
            "dueTime": "2024-01-01T04:59:59.999Z",
            "installmentDuration": 0.974462365591
        },
        {
            "installmentStartTime": "2024-01-31T05:00:00Z",
            "installmentEndTime": "2024-02-29T05:00:00Z",
            "coverageStartTime": "2024-03-06T06:32:44Z",
            "coverageEndTime": "2024-04-09T03:21:49Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.102639125348,
            "generateTime": "2024-01-17T05:00:00Z",
            "dueTime": "2024-02-01T04:59:59.999Z",
            "installmentDuration": 0.998238783834
        },
        {
            "installmentStartTime": "2024-02-29T05:00:00Z",
            "installmentEndTime": "2024-03-31T04:00:00Z",
            "coverageStartTime": "2024-04-09T03:21:49Z",
            "coverageEndTime": "2024-05-11T20:49:05Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.079178750996,
            "generateTime": "2024-02-15T05:00:00Z",
            "dueTime": "2024-03-01T04:59:59.999Z",
            "installmentDuration": 1.001761216166
        },
        {
            "installmentStartTime": "2024-03-31T04:00:00Z",
            "installmentEndTime": "2024-04-30T04:00:00Z",
            "coverageStartTime": "2024-05-11T20:49:05Z",
            "coverageEndTime": "2024-06-14T14:16:22Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.102639536041,
            "generateTime": "2024-03-17T04:00:00Z",
            "dueTime": "2024-04-01T03:59:59.999Z",
            "installmentDuration": 0.999148745520
        },
        {
            "installmentStartTime": "2024-04-30T04:00:00Z",
            "installmentEndTime": "2024-05-31T04:00:00Z",
            "coverageStartTime": "2024-06-14T14:16:22Z",
            "coverageEndTime": "2024-07-17T07:43:38Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.073313644962,
            "generateTime": "2024-04-16T04:00:00Z",
            "dueTime": "2024-05-01T03:59:59.999Z",
            "installmentDuration": 1.000851254480
        },
        {
            "installmentStartTime": "2024-05-31T04:00:00Z",
            "installmentEndTime": "2024-06-30T04:00:00Z",
            "coverageStartTime": "2024-07-17T07:43:38Z",
            "coverageEndTime": "2024-08-20T16:27:16Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.108504330944,
            "generateTime": "2024-05-17T04:00:00Z",
            "dueTime": "2024-06-01T03:59:59.999Z",
            "installmentDuration": 0.999148745520
        },
        {
            "installmentStartTime": "2024-06-30T04:00:00Z",
            "installmentEndTime": "2024-07-31T04:00:00Z",
            "coverageStartTime": "2024-08-20T16:27:16Z",
            "coverageEndTime": "2024-09-22T18:38:11Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.090909261748,
            "generateTime": "2024-06-16T04:00:00Z",
            "dueTime": "2024-07-01T03:59:59.999Z",
            "installmentDuration": 1.000851254480
        },
        {
            "installmentStartTime": "2024-07-31T04:00:00Z",
            "installmentEndTime": "2024-08-31T04:00:00Z",
            "coverageStartTime": "2024-09-22T18:38:11Z",
            "coverageEndTime": "2024-10-25T12:05:27Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.064515992135,
            "generateTime": "2024-07-17T04:00:00Z",
            "dueTime": "2024-08-01T03:59:59.999Z",
            "installmentDuration": 1.000000000000
        },
        {
            "installmentStartTime": "2024-08-31T04:00:00Z",
            "installmentEndTime": "2024-09-30T04:00:00Z",
            "coverageStartTime": "2024-10-25T12:05:27Z",
            "coverageEndTime": "2024-11-28T06:32:44Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.117302294902,
            "generateTime": "2024-08-17T04:00:00Z",
            "dueTime": "2024-09-01T03:59:59.999Z",
            "installmentDuration": 0.999148745520
        },
        {
            "installmentStartTime": "2024-09-30T04:00:00Z",
            "installmentEndTime": "2025-01-01T00:00:00Z",
            "coverageStartTime": "2024-11-28T06:32:44Z",
            "coverageEndTime": "2025-01-01T00:00:00Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.090908950617,
            "generateTime": "2024-09-16T04:00:00Z",
            "dueTime": "2024-10-01T03:59:59.999Z",
            "installmentDuration": 3.026388888889
        }
    ],
    "reversalLattice": false
}

Pay close attention to the structure of each of the objects in the frames array. The code block below focuses on the first frame in the array.

// The JSON has been annotated with comments
// for documentation purposes.

// If you intend to use this JSON for any reason,
// you will likely need to remove the comments.
...
"frames": [
    {
        // When the installment period begins.
        "installmentStartTime": "2024-01-01T00:00:00Z",

        // When the installment period ends.
        "installmentEndTime": "2024-01-31T05:00:00Z",

        // When the coverage period begins.
        "coverageStartTime": "2024-01-01T00:00:00Z",

        // When the coverage period ends.
        "coverageEndTime": "2024-03-06T06:32:44Z",

        // The weight of the frame in comparison to other frames.
        "normalizedWeight": 0.181818181818,

        // The duration of the coverage in the time unit used by the quote.
        // In this case, ~2.17 months
        "coverageDuration": 2.170088112306,

        // The date and time the billing system will generate an invoice.
        "generateTime": "2023-12-17T05:00:00Z",

        // What the due date of the invoice should be when generated.
        "dueTime": "2024-01-01T04:59:59.999Z",

        // The duration of the installment period.
        "installmentDuration": 0.974462365591
    },
    ...

Remember that a frame represents a subdivision of an insurance policy term. It contains two ways of describing the subdivision:

  • The subdivision as an installment period

  • The subdivision as a coverage period

The parameters prepended with installment determine the installment period. This is the period of time when the installment is issued to the customer. Additionally, the generateTime is when the invoice is generated, and the dueTime is when installment payment is due.

The parameters prepended with coverage determine the coverage period.

Notice in the code block above that the installmentEndTime and the coverageEndTime aren’t the same. This is because this installment lattice was generated for a policy that’s billed on a “monthly 10” installment schedule. That means the policy is billed in 10 installments for a 12-month period. This is where the concept of normalizedWeight comes into play.

Let’s add the next frame from the lattice into our analysis:

    ...
    "frames": [
        {
            "installmentStartTime": "2024-01-01T00:00:00Z",
            "installmentEndTime": "2024-01-31T05:00:00Z",
            "coverageStartTime": "2024-01-01T00:00:00Z",
            "coverageEndTime": "2024-03-06T06:32:44Z",
            "normalizedWeight": 0.181818181818,
            "coverageDuration": 2.170088112306,
            "generateTime": "2023-12-17T05:00:00Z",
            "dueTime": "2024-01-01T04:59:59.999Z",
            "installmentDuration": 0.974462365591
        },
        {
            "installmentStartTime": "2024-01-31T05:00:00Z",
            "installmentEndTime": "2024-02-29T05:00:00Z",
            "coverageStartTime": "2024-03-06T06:32:44Z",
            "coverageEndTime": "2024-04-09T03:21:49Z",
            "normalizedWeight": 0.090909090909,
            "coverageDuration": 1.102639125348,
            "generateTime": "2024-01-17T05:00:00Z",
            "dueTime": "2024-02-01T04:59:59.999Z",
            "installmentDuration": 0.998238783834
        },
        ...
}

In the code block above, the first frame…

  • Has an installmentDuration lasting approximately one month.

  • Has a coverageDuration lasting approximately two months

  • Has a normalizedWeight of .18 – approximately twice the other frames

Meanwhile, the second frame…

  • Has an installmentDuration lasting approximately one month

  • Has a coverageDuration lasting approximately one month

  • Has a normalizedWeight of .09 – approximately half the first frame.

With an installment lattice created and populated with frames, the system then generates the installments that will be used for building invoices.

Stage 3: System generates installments

Once the installment lattice has been created, the system automatically generates a set of installments based on the frames in the lattice.

The code block below shows examples of two installments generated from the example frames above:

[
    {
        "locator": "01J5E66WFYVZ8X9Q98W7MRDMJ2",
        "installmentLatticeLocator": "01J5E66WEQV8GGKSH5RTQAYCTB",
        "accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
        "currency": "USD",
        "timezone": "America/New_York",
        "installmentFrameIndex": 0,
        "quoteLocator": "01J5E660YXGBBNT26TQESCZHQF",
        "policyLocator": "01J5E660YXGBBNT26TQESCZHQF",
        "transactionLocator": "01J5E660YXGBBNT26TQESCZHQF",
        "installmentStartTime": "2024-01-01T00:00:00Z",
        "installmentEndTime": "2024-01-31T05:00:00Z",
        "coverageStartTime": "2024-01-01T00:00:00Z",
        "coverageEndTime": "2024-03-06T06:32:44Z",
        "installmentDuration": 0.974462365591,
        "coverageDuration": 2.170088112306,
        "generateTime": "2023-12-17T05:00:00Z",
        "dueTime": "2024-01-01T04:59:59.999Z",
        "invoiceLocator": "01J5E66WTJCBYJ9P3KNPYA1KF6",
        "createdAt": "2024-08-16T18:11:46.092575Z",
        "createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
        "updatedAt": "2024-08-16T18:11:46.092575Z",
        "updatedBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
        "installmentItems": [
            {
                "locator": "01J5E66WFY059MB4B5EXWT884Z",
                "installmentLocator": "01J5E66WFYVZ8X9Q98W7MRDMJ2",
                "chargeLocator": "01J5E66VBVQHEDJQSTNGSY77KS",
                "elementLocator": "01J5E66VBMACX1D1K00K0YYZNE",
                "elementStaticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
                "chargeType": "coverage_b_premium",
                "chargeCategory": "premium",
                "amount": 29.84,
                "invoiceItemLocator": "01J5E66WTJP601E481JJ6TJAHG",
                "createdAt": "2024-08-16T18:11:46.092575Z",
                "createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
            },
            {
                "locator": "01J5E66WFYK2Q5PGGZC3FS5FRQ",
                "installmentLocator": "01J5E66WFYVZ8X9Q98W7MRDMJ2",
                "chargeLocator": "01J5E66VBVSW4RT1YEVGA9R8QC",
                "elementLocator": "01J5E66VBKYGJZT44JYPCNA3T6",
                "elementStaticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
                "chargeType": "coverage_a_premium",
                "chargeCategory": "premium",
                "amount": 149.19,
                "invoiceItemLocator": "01J5E66WTJ0XD6B9NVY2S8C9PG",
                "createdAt": "2024-08-16T18:11:46.092575Z",
                "createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
            }
        ]
    },
    {
        "locator": "01J5E66WFY09W2W2T74DZEFG8Q",
        "installmentLatticeLocator": "01J5E66WEQV8GGKSH5RTQAYCTB",
        "accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
        "currency": "USD",
        "timezone": "America/New_York",
        "installmentFrameIndex": 1,
        "quoteLocator": "01J5E660YXGBBNT26TQESCZHQF",
        "policyLocator": "01J5E660YXGBBNT26TQESCZHQF",
        "transactionLocator": "01J5E660YXGBBNT26TQESCZHQF",
        "installmentStartTime": "2024-01-31T05:00:00Z",
        "installmentEndTime": "2024-02-29T05:00:00Z",
        "coverageStartTime": "2024-03-06T06:32:44Z",
        "coverageEndTime": "2024-04-09T03:21:49Z",
        "installmentDuration": 0.998238783834,
        "coverageDuration": 1.102639125348,
        "generateTime": "2024-01-17T05:00:00Z",
        "dueTime": "2024-02-01T04:59:59.999Z",
        "invoiceLocator": "01J5E66X9B6YSHRQ9KMKG98ATB",
        "createdAt": "2024-08-16T18:11:46.092575Z",
        "createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
        "updatedAt": "2024-08-16T18:11:46.092575Z",
        "updatedBy": "f700dff5-2a34-4fac-9c32-aa4287068d45",
        "installmentItems": [
            {
                "locator": "01J5E66WFYBB62CTHZBAKTS39H",
                "installmentLocator": "01J5E66WFY09W2W2T74DZEFG8Q",
                "chargeLocator": "01J5E66VBVSW4RT1YEVGA9R8QC",
                "elementLocator": "01J5E66VBKYGJZT44JYPCNA3T6",
                "elementStaticLocator": "01J5E660YXV5ZQC2MM6CW5DW8Q",
                "chargeType": "coverage_a_premium",
                "chargeCategory": "premium",
                "amount": 75.81,
                "invoiceItemLocator": "01J5E66X9B9YDCF6TGJ99S9854",
                "createdAt": "2024-08-16T18:11:46.092575Z",
                "createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
            },
            {
                "locator": "01J5E66WFYJG0JW53ZDKGDTJW8",
                "installmentLocator": "01J5E66WFY09W2W2T74DZEFG8Q",
                "chargeLocator": "01J5E66VBVQHEDJQSTNGSY77KS",
                "elementLocator": "01J5E66VBMACX1D1K00K0YYZNE",
                "elementStaticLocator": "01J5E660YX6ZEJSYTVN9XAXF14",
                "chargeType": "coverage_b_premium",
                "chargeCategory": "premium",
                "amount": 15.16,
                "invoiceItemLocator": "01J5E66X9BRMH53HB5YDC09Z3N",
                "createdAt": "2024-08-16T18:11:46.092575Z",
                "createdBy": "f700dff5-2a34-4fac-9c32-aa4287068d45"
            }
        ]
    },
    ...

The installments contain the charges for insurance coverage provided during the coverageDuration (the span of time between the coverageStartTime and the coverageEndTime).

After the system has generated the installments, the next step is to generate invoices.

Stage 4: System generates invoice(s)

The next stage of the billing life cycle is for the system to generate one or more invoices.

The billing system generates invoices on the generateTime (found on either the frame or the installment). The number of invoices created upon issuance of a quote depends on whether there is any retroactive coverage.

For example, if someone buys a policy for homeowner’s insurance on March 1, and coverage also begins on March 1, then the system generates just one invoice. However, if the policy provides retroactive coverage to January 1, then the system generates the initial invoice, as well as invoices for previous frames.

The code block below shows an example of an invoice.

[
    {
        "locator": "01J604B4VBYAFQ1NF04PRF50YD",
        "accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
        "state": "open",
        "invoiceItems": [
            {
                "locator": "01J604B4VBFF29WKEFHFXP21BV",
                "chargeType": "coverage_a_premium",
                "chargeCategory": "premium",
                "amount": 150.00,
                "remainingAmount": 150.00,
                "invoiceLocator": "01J604B4VBYAFQ1NF04PRF50YD",
                "installmentItemLocators": [
                    "01J604B421BYA71V49AK4AB713"
                ],
                "timezone": "America/New_York",
                "quoteLocator": "01J6049YN0YK3EY28J090NEW5Y",
                "policyLocator": "01J6049YN0YK3EY28J090NEW5Y",
                "transactionLocator": "01J6049YN0YK3EY28J090NEW5Y",
                "elementStaticLocator": "01J6049Z4415XFRVGA4EJ72ZMM"
            },
            {
                "locator": "01J604B4VBRFX5W0VWJWY7TYVF",
                "chargeType": "coverage_b_premium",
                "chargeCategory": "premium",
                "amount": 30.00,
                "remainingAmount": 30.00,
                "invoiceLocator": "01J604B4VBYAFQ1NF04PRF50YD",
                "installmentItemLocators": [
                    "01J604B421S190JDXJ0EK9GWAM"
                ],
                "timezone": "America/New_York",
                "quoteLocator": "01J6049YN0YK3EY28J090NEW5Y",
                "policyLocator": "01J6049YN0YK3EY28J090NEW5Y",
                "transactionLocator": "01J6049YN0YK3EY28J090NEW5Y",
                "elementStaticLocator": "01J6049Z44CH4TFBBQPN22DHG8"
            }
        ],
        "generatedTime": "2024-08-23T17:25:28.541Z",
        "dueTime": "2024-09-07T03:59:59.999Z",
        "currency": "USD",
        "startTime": "2024-08-23T00:00:00Z",
        "endTime": "2024-09-22T04:00:00Z",
        "timezone": "America/New_York",
        "totalAmount": 180.00,
        "totalRemainingAmount": 180.00
    }
]

Stage 5: Payment is created (via API)

When a customer sends a payment to their insurer, the next stage of the billing life cycle is to create a record of the payment.

To do that, we’ll use the Create Payment endpoint (/billing/:tenantLocator/payments). The targets array in the request body contains the invoices to apply payment to, with the containerLocator being the unique identifier of the invoice.

{
    "accountLocator": "01J5E5RNSWR0QVPCFF2XT83CFK",
    "amount": 180.00,
    "data": {
        "payerFirstName": "Example",
        "payerLastName": "User",
        "note": "payment"
    },
    "targets": [
        {
            "containerLocator": "01J604B4VBYAFQ1NF04PRF50YD",
            "containerType": "invoice"
        }
    ],
    "useDefaultFinancialInstrument": true,
    "transactionNumber": "abc123",
    "type": "StandardPayment"
}

Note that creating the payment does not apply it to the invoice. To apply the payment, you must post the payment.

Stage 6: Payment is posted to invoice (via API)

The final stage is to post the payment. Posting a payment applies it to an invoice.

Every invoice has two parameters tracking the amount on the invoice:

  • totalAmount - The original amount of the invoice

  • totalRemainingAmount - The amount left to pay on the invoice

To post a payment, we’ll use the Post Payment endpoint (/billing/:tenantLocator/payments/:paymentLocator/post). This applies the payment to the totalRemainingAmount of the invoice.

When the totalRemainingAmount reaches 0, the invoice is marked as “settled”.