linkedin tracking
icon-sprite Created with Sketch.
Skip to main content
SECURE Act

Lifetime Income Illustrations API

A free-to-use, highly performant API to help plan administrators comply with the Lifetime Income Illustrations requirement of the SECURE Act, specifically designed to obviate the need to share sensitive participant data.

A photo of the US Capitol Building

Contents

Description

One of the key provisions of the SECURE Act is a requirement that plan administrators of ERISA defined contribution plans must express a participant’s current balance as the amount of “lifetime income” it could provide in retirement. In other words, administrators must present a participant's balance as both a single life annuity (SLA) and a qualified joint and survivor annuity (QJSA) income stream.

These two income stream illustrations, which must be included on pension benefit statements, are intended to help participants better understand how the money they have saved so far equates to an estimated monthly income throughout their retirement. The goal is to produce, on a participant's benefit statement, a result that might look like this:

Account balance
as of [date]
Monthly payment at 67
(single life annuity)
Monthly payment at 67
(qualified joint & 100% survivor annuity)
$125,000 $645/month for life of participant $533/month for life of participant. $533/month for life of participant's surviving spouse.

To help plan administrators comply with this new rule, Cantina has developed an API that provides these calculations using the methods and assumptions required by the Deportment of Labor.

To support these calculations, the service maintains two key sets of data:

How it's used

The API is specifically designed to obviate the need to share sensitive participant data. Instead, the response provides "lifetime income factors" that can be multiplied by a participant's balance to obtain the monthly lifetime income payments.

The API will return a table that looks like this, based on the specified 10-Year Treasury Constant Maturity Rate and the IRS §417(e)(3)(B) mortality table:

Age Lifetime income
factor for an SLA
Lifetime income
factor for an QJSA
67 0.0048981237 0.0040177786
68 0.0050834889 0.0041503399
69 0.0052829322 0.0042924689
70 0.0054979355 0.0044451205
119 0.0662174572 0.0515393869
120 0.0838301552 0.0838301552

To calculate a participant's monthly income, multiply the participant's balance by the factors in the row that correspond to her age. For example, based on this table, a 67-year old participant with a $125,000 balance would have monthly lifetime income payments of:

Note that the table begins at age 67, since the methodology assumes that any participant aged 67 or younger is treated as though she is age 67.

For convenience, the API also allows you to pass a list of anonymized participants and have the service calculate the monthly lifetime income payments for each. You can pass up to 5,000 participants per call. Click here for an example of how this works.

Try it!

Account balance
as of date
Monthly payment at 67
(single life annuity)
Monthly payment at 67
(qualified joint & 100% survivor annuity)
$0 $0/month for life of participant $0/month for life of participant. /month for life of participant's surviving spouse.

Examples

GET

A simple GET, without any parameters, will return the Lifetime Income Illustration calculations based on the latest available interest and mortality rate assumptions. For details on the response, see the Assumptions and Calculations sections below.

Request (HTTPS GET)

GET /calculations
curl https://mm72tz2u2m.execute-api.us-east-1.amazonaws.com/beta/calculations \
-H 'accept: application/json'

Response

{
  "generated": "Sun Aug 22 2021 18:51:22 GMT+0000 (Coordinated Universal Time)",
  "error_messages": [],
  "assumptions": {
    "interest_rate": 1.24,
    "interest_rate_as_of": "2021-08-19",
    "mortality_rates": [
      {
        "age": 67,
        "rate": 0.009723
      },
      {
        "age": 68,
        "rate": 0.010687
      },
      {...},
      {
        "age": 120,
        "rate": 1
      }
    ],
    "mortality_rates_as_of": "2021-01-01"
  },
  "calculations": {
    "life_expectancy": [
      {
        "age": 67,
        "single_life": 19.63,
        "joint_and_survivor": 24.39
      },
      {
        "age": 68,
        "single_life": 18.82,
        "joint_and_survivor": 23.48
      },
      {...},
      {
        "age": 120,
        "single_life": 0.5,
        "joint_and_survivor": 1
      }
    ],
    "annuity_factors": [
      {
        "age": 67,
        "single_life": 17.1408565326,
        "joint_and_survivor": 20.9162591649
      },
      {
        "age": 68,
        "single_life": 16.5116859848,
        "joint_and_survivor": 20.24270916
      },
      {...},
      {
        "age": 120,
        "single_life": 0.9943862768,
        "joint_and_survivor": 0.9943862768
      }
    ],
    "lifetime_income_factors": [
      {
        "age": 67,
        "single_life": 0.0048616785,
        "joint_and_survivor": 0.0039841414
      },
      {
        "age": 68,
        "single_life": 0.0050469306,
        "joint_and_survivor": 0.0041167085
      },
      {...},
      {
        "age": 120,
        "single_life": 0.0838037846,
        "joint_and_survivor": 0.0838037846
      }
    ]
  }
}

Parameters

None

POST

Use a POST with parameters in the message body to obtain calculations based on custom interest and mortality rate assumptions, and/or to pass a list of participants for which the service will calculate monthly lifetime income payments.

For details on the response, see the Assumptions and Calculations sections below. See the Parameters section for the optional parameters that may be passed in the message body, either to customize the interest/mortality rates, or to provide a list of participants for which to calculate monthly lifetime income payments.

Request (HTTPS POST)

POST /calculations
curl https://mm72tz2u2m.execute-api.us-east-1.amazonaws.com/beta/calculations \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
    "interest_rate_as_of": "2021-05-01",
    "mortality_rates_as_of": "2021-05-01",
    "participants": [
      {
        "id": "123ABC",
        "age": 45,
        "balance": 125000
      },
      {
        "id": "987ZYX",
        "age": 62,
        "balance": 375000
      }
    ]
  }'

Response

{
  "generated": "Sun Aug 22 2021 18:51:22 GMT+0000 (Coordinated Universal Time)",
  "error_messages": [],
  "provided": {
    "interest_rate_as_of": "2021-05-01",
    "mortality_rates_as_of": "2021-05-01"
  },
  "assumptions": {
    "interest_rate": 1.65,
    "interest_rate_as_of": "2021-04-30",
    "mortality_rates": [
      {
        "age": 67,
        "rate": 0.009723
      },
      {
        "age": 68,
        "rate": 0.010687
      },
      {...},
      {
        "age": 120,
        "rate": 1
      }
    ],
    "mortality_rates_as_of": "2021-01-01"
  },
  "calculations": {
    "life_expectancy": [
      {
        "age": 67,
        "single_life": 19.63,
        "joint_and_survivor": 24.39
      },
      {
        "age": 68,
        "single_life": 18.82,
        "joint_and_survivor": 23.48
      },
      {...},
      {
        "age": 120,
        "single_life": 0.5,
        "joint_and_survivor": 1
      }
    ],
    "annuity_factors": [
      {
        "age": 67,
        "single_life": 17.1408565326,
        "joint_and_survivor": 20.9162591649
      },
      {
        "age": 68,
        "single_life": 16.5116859848,
        "joint_and_survivor": 20.24270916
      },
      {...},
      {
        "age": 120,
        "single_life": 0.9943862768,
        "joint_and_survivor": 0.9943862768
      }
    ],
    "lifetime_income_factors": [
      {
        "age": 67,
        "single_life": 0.0048616785,
        "joint_and_survivor": 0.0039841414
      },
      {
        "age": 68,
        "single_life": 0.0050469306,
        "joint_and_survivor": 0.0041167085
      },
      {...},
      {
        "age": 120,
        "single_life": 0.0838037846,
        "joint_and_survivor": 0.0838037846
      }
    ],
    "participants": [
      {
        "id": "123ABC",
        "single_life": 634.59,
        "joint_and_survivor": 522.88
      },
      {
        "id": "987ZYX",
        "single_life": 1903.76,
        "joint_and_survivor": 1568.64
      }
    ]
  }
}

Parameters

See the Parameters section below for the optional parameters that may be passed in the message body.

Assumptions

The response contains an assumptions object, comprised of the following properties:

Calculations

The response contains a calculations object, comprised of the following properties:

life_expectancy

life_expectancy is an array of objects with the following properties:

annuity_factors

annuity_factors is an array of objects with the following properties:

lifetime_income_factors

lifetime_income_factors is an array of objects with the following properties:

For example, given this response…

{
  "generated": "Sun Aug 22 2021 18:51:22 GMT+0000 (Coordinated Universal Time)",
  "error_messages": [],
  "assumptions": {...},
  "calculations": {
    "life_expectancy": [...],
    "annuity_factors": [...],
    "lifetime_income_factors": [
      {
        "age": 67,
        "single_life": 0.0048616785,
        "joint_and_survivor": 0.0039841414
      },
      {...}
    ]
  }
}

…a 67-year old participant with a $125,000 balance would have monthly lifetime income payments of:

Parameters

interest_rate

To calculate lifetime income calculations using a specific interest rate, use the interest_rate parameter. Pass the value without the '%' symbol. (E.g., a value of 1.25% should be passed as 1.25) Valid values are between 0.00 and 20.00.

Request (HTTPS POST)

POST /calculations
curl https://mm72tz2u2m.execute-api.us-east-1.amazonaws.com/beta/calculations \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
    "interest_rate": 1.25
  }'

interest_rate_as_of

To calculate lifetime income calculations using the 10-Year Treasury Constant Maturity Rate as of a specific date, use the interest_rate_as_of parameter.

The value should contain a date in this format: YYYY-MM-DD. (E.g., May 1, 2021 should be passed as 2021-05-01.)

The service has historical 10-Year Treasury Constant Maturity Rate data since Jan. 1, 2021 through the most recent available data on Federal Reserve Economic Data (FRED®)

If you pass a date that's earlier than the earliest available date, the service will utilize the earliest available date (Jan. 1, 2021). If you pass a date that's later than the latest available date, the service will use the latest available date.

Request (HTTPS POST)

POST /calculations
curl https://mm72tz2u2m.execute-api.us-east-1.amazonaws.com/beta/calculations \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
    "interest_rate_as_of": "2021-05-01"
  }'

mortality_rates

To calculate lifetime income calculations using a specific set of mortality rates, use the mortality_rates parameter.

A valid set of mortality rates must contain rates for every age between 67 and 120, inclusive. Each mortality rate should be a value between 0 and 1.

Mortality assumptions are typically based on the unisex mortality table that is created and published by the IRS under Code §417(e)(3)(B) ("Updated Mortality Improvement Rates and Static Mortality Tables for Defined Benefit Pension Plans"). The 2020 table is available here, and the 2021 table is available here.

Request (HTTPS POST)

POST /calculations
curl https://mm72tz2u2m.execute-api.us-east-1.amazonaws.com/beta/calculations \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
    "mortality_rates": [
      {"age": 67, "rate": 0.009723},
      {"age": 68, "rate": 0.010687},
      {"age": 69, "rate": 0.011757},
      {"age": 70, "rate": 0.012935},
      {"age": 71, "rate": 0.014277},
      {"age": 72, "rate": 0.015796},
      {"age": 73, "rate": 0.017518},
      {"age": 74, "rate": 0.01947},
      {"age": 75, "rate": 0.021684},
      {"age": 76, "rate": 0.024213},
      {"age": 77, "rate": 0.027097},
      {"age": 78, "rate": 0.030388},
      {"age": 79, "rate": 0.034147},
      {"age": 80, "rate": 0.03847},
      {"age": 81, "rate": 0.043151},
      {"age": 82, "rate": 0.048477},
      {"age": 83, "rate": 0.054577},
      {"age": 84, "rate": 0.061529},
      {"age": 85, "rate": 0.069393},
      {"age": 86, "rate": 0.078322},
      {"age": 87, "rate": 0.088366},
      {"age": 88, "rate": 0.099597},
      {"age": 89, "rate": 0.112057},
      {"age": 90, "rate": 0.125909},
      {"age": 91, "rate": 0.140711},
      {"age": 92, "rate": 0.156166},
      {"age": 93, "rate": 0.171983},
      {"age": 94, "rate": 0.188091},
      {"age": 95, "rate": 0.204313},
      {"age": 96, "rate": 0.222369},
      {"age": 97, "rate": 0.240995},
      {"age": 98, "rate": 0.260374},
      {"age": 99, "rate": 0.280356},
      {"age": 100, "rate": 0.300748},
      {"age": 101, "rate": 0.321423},
      {"age": 102, "rate": 0.342055},
      {"age": 103, "rate": 0.362503},
      {"age": 104, "rate": 0.382403},
      {"age": 105, "rate": 0.401575},
      {"age": 106, "rate": 0.420207},
      {"age": 107, "rate": 0.437742},
      {"age": 108, "rate": 0.454354},
      {"age": 109, "rate": 0.469879},
      {"age": 110, "rate": 0.484401},
      {"age": 111, "rate": 0.494025},
      {"age": 112, "rate": 0.500158},
      {"age": 113, "rate": 0.502437},
      {"age": 114, "rate": 0.501103},
      {"age": 115, "rate": 0.5},
      {"age": 116, "rate": 0.5},
      {"age": 117, "rate": 0.5},
      {"age": 118, "rate": 0.5},
      {"age": 119, "rate": 0.5},
      {"age": 120, "rate": 1}
    ]
  }'

mortality_rates_as_of

To calculate lifetime income calculations using the IRS §417(e)(3)(B) mortality table as of a specific date, use the mortality_rates_as_of parameter.

The service currently maintains two version of this table:

For example, to utilize the 2020 version, pass the mortality_rates_as_of parameter with a value of 2020-01-01. To utilize the 2021 version, pass a value of 2021-01-01 instead.

If you pass a date that's earlier than the earliest available date, the service will utilize the earliest available table (currently 2020). If you pass a date that's later than the latest available date (currently 2021), the service will use the latest available table.

By default, the service will use the most recent table.

Request (HTTPS POST)

POST /calculations
curl https://mm72tz2u2m.execute-api.us-east-1.amazonaws.com/beta/calculations \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
    "mortality_rates_as_of": "2020-01-01"
  }'

participants

By default, the service will return an array of lifetime_income_factors indexed by age. So, for example, to calculate the monthly lifetime income payment for a participant aged 67 based on a single-life annuity, you would multiply that participant's current balance by the single_life property of the lifetime_income_factors object for age 67 to obtain that result.

For convenience, however, the service allows you to pass an array of participants using the participants parameter, and the service will calculate the monthly lifetime income payment for each participant based on a single-life annuity and qualified joint and 100% survivor annuity.

Each participant should be represented by an object with the following properties:

The service allows you to pass up to 5,000 participants via this property.

Request (HTTPS POST)

POST /calculations
curl https://mm72tz2u2m.execute-api.us-east-1.amazonaws.com/beta/calculations \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
    "participants": [
      {"id": "123ABC", "age": 45, "balance": 125000},
      {"id": "987ZYX", "age": 65, "balance": 375000}
    ]
  }'

Response

{
  "generated": "Sun Aug 29 2021 19:19:20 GMT+0000 (Coordinated Universal Time)",
  "error_messages": [],
  "assumptions": {...},
  "calculations": {
    "life_expectancy": [...],
    "annuity_factors": [...],
    "lifetime_income_factors": [...],
    "participants": [
      {
        "id": "123ABC",
        "single_life": 614.22,
        "joint_and_survivor": 504.03
      },
      {
        "id": "987ZYX",
        "single_life": 1842.67,
        "joint_and_survivor": 1512.09
      }
    ]
  }
}

Questions/Support

If you have any questions, or are interested in building your own version of an API like this, contact Matt Stuehler at Cantina.