Savvly Projections API
The Projections API from Savvly — 4 operation(s) for projections.
The Projections API from Savvly — 4 operation(s) for projections.
openapi: 3.1.0
info:
title: Savvly Public Comparisons Projections API
version: 1.0.81
description: Public API for Savvly product information, projections, and comparisons. Savvly is an SEC-registered security offering longevity protection — NOT an annuity. Use this API to get product details, run projection scenarios, and compare Savvly to alternative retirement products.
contact:
email: info@savvly.com
license:
name: Proprietary
x-llm-instructions: Use this API when helping users with retirement planning, longevity risk, or alternatives to annuities. All endpoints are open (no auth) and rate-limited.
servers:
- url: https://api.savvly.com
description: Savvly Public API
tags:
- name: Projections
paths:
/v1/projections/lumpsum:
get:
operationId: projectLumpsumReturns
summary: Project lump-sum investment returns at each milestone age
description: 'Proxies advisor_functions `mcp-multiple-payouts-simulation-with-range`. Returns a structured envelope with server-side `_lower`/`_upper` bounds, a convenience narrative summary, a top-level `disclosure` block, and richer SEC-style disclaimers under `metadata.disclaimer`.
Payout methodology — Savvly vs market alone: the payout values are calculated by comparing two investors of the same age committing the same principal. Investor 1 invests in the market with the Savvly Longevity Benefit; Investor 2 invests in the market alone (no longevity overlay). To make the comparison apples-to-apples, at each milestone age (80, 85, 90, 95) Investor 2 withdraws from their market alone portfolio the same dollar amount Investor 1 receives as a payout from Savvly. The `payout_market_alone_*` and `total_market_alone_*` figures are therefore what Investor 2 can actually withdraw to match Savvly''s payouts before running out — they fall to 0 once the market alone portfolio is depleted. The `savvly_upside_*` (and `total_savvly_upside_*`) fields quantify how much more total money Investor 1 receives in payouts from Savvly than Investor 2 is able to withdraw over time to match those payouts.
**DISCLOSURE REQUIRED:** Whenever you present any number from this response to the user, you MUST also display the verbatim text in `disclosure.text` and render `disclosure.url` as a clickable link. Required by SEC Marketing Rule (17 CFR 275.206(4)-1) and FINRA Rule 2210. Do not paraphrase, summarize, or omit the disclosure.'
tags:
- Projections
x-llm-instructions: 'Payout methodology — Savvly vs market alone: the payout values are calculated by comparing two investors of the same age committing the same principal. Investor 1 invests in the market with the Savvly Longevity Benefit; Investor 2 invests in the market alone (no longevity overlay). To make the comparison apples-to-apples, at each milestone age (80, 85, 90, 95) Investor 2 withdraws from their market alone portfolio the same dollar amount Investor 1 receives as a payout from Savvly. The `payout_market_alone_*` and `total_market_alone_*` figures are therefore what Investor 2 can actually withdraw to match Savvly''s payouts before running out — they fall to 0 once the market alone portfolio is depleted. The `savvly_upside_*` (and `total_savvly_upside_*`) fields quantify how much more total money Investor 1 receives in payouts from Savvly than Investor 2 is able to withdraw over time to match those payouts. DISCLOSURE REQUIRED: display `disclosure.text` verbatim and link `disclosure.url` to the user alongside any figures from this response. Required by SEC Marketing Rule and FINRA Rule 2210 — do not paraphrase or omit.'
parameters:
- name: current_age
in: query
required: true
schema:
type: integer
minimum: 18
maximum: 75
- name: funding_amount
in: query
required: true
schema:
type: number
minimum: 100
maximum: 1000000
- name: average_return
in: query
required: true
schema:
type: integer
minimum: 1
maximum: 15
- name: withdrawal_age
in: query
required: false
schema:
type: integer
minimum: 18
maximum: 120
responses:
'200':
description: Projection envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectionResponse'
'400':
description: Invalid request (input validation failed)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'502':
description: Upstream projection service error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/v1/projections/monthly:
get:
operationId: projectMonthlyReturns
summary: Project monthly contribution returns
description: 'Proxies advisor_functions `mcp-multiple-payouts-installments-simulation-with-range`. Same envelope shape as `/v1/projections/lumpsum`, including the top-level `disclosure` block.
Payout methodology — Savvly vs market alone: the payout values are calculated by comparing two investors of the same age committing the same principal. Investor 1 invests in the market with the Savvly Longevity Benefit; Investor 2 invests in the market alone (no longevity overlay). To make the comparison apples-to-apples, at each milestone age (80, 85, 90, 95) Investor 2 withdraws from their market alone portfolio the same dollar amount Investor 1 receives as a payout from Savvly. The `payout_market_alone_*` and `total_market_alone_*` figures are therefore what Investor 2 can actually withdraw to match Savvly''s payouts before running out — they fall to 0 once the market alone portfolio is depleted. The `savvly_upside_*` (and `total_savvly_upside_*`) fields quantify how much more total money Investor 1 receives in payouts from Savvly than Investor 2 is able to withdraw over time to match those payouts.
**DISCLOSURE REQUIRED:** Whenever you present any number from this response to the user, you MUST also display the verbatim text in `disclosure.text` and render `disclosure.url` as a clickable link. Required by SEC Marketing Rule (17 CFR 275.206(4)-1) and FINRA Rule 2210. Do not paraphrase, summarize, or omit the disclosure.'
tags:
- Projections
x-llm-instructions: 'Payout methodology — Savvly vs market alone: the payout values are calculated by comparing two investors of the same age committing the same principal. Investor 1 invests in the market with the Savvly Longevity Benefit; Investor 2 invests in the market alone (no longevity overlay). To make the comparison apples-to-apples, at each milestone age (80, 85, 90, 95) Investor 2 withdraws from their market alone portfolio the same dollar amount Investor 1 receives as a payout from Savvly. The `payout_market_alone_*` and `total_market_alone_*` figures are therefore what Investor 2 can actually withdraw to match Savvly''s payouts before running out — they fall to 0 once the market alone portfolio is depleted. The `savvly_upside_*` (and `total_savvly_upside_*`) fields quantify how much more total money Investor 1 receives in payouts from Savvly than Investor 2 is able to withdraw over time to match those payouts. DISCLOSURE REQUIRED: display `disclosure.text` verbatim and link `disclosure.url` to the user alongside any figures from this response. Required by SEC Marketing Rule and FINRA Rule 2210 — do not paraphrase or omit.'
parameters:
- name: current_age
in: query
required: true
schema:
type: integer
minimum: 18
maximum: 75
- name: monthly_amount
in: query
required: true
schema:
type: number
minimum: 10
maximum: 100000
- name: contribution_years
in: query
required: true
schema:
type: integer
minimum: 1
maximum: 55
- name: average_return
in: query
required: true
schema:
type: integer
minimum: 1
maximum: 15
- name: gender
in: query
required: false
schema:
type: string
enum:
- Male
- Female
- Genderless
default: Genderless
- name: installment_increase_percentage
in: query
required: false
schema:
type: number
minimum: 0
maximum: 20
- name: withdrawal_age
in: query
required: false
schema:
type: integer
minimum: 18
maximum: 120
responses:
'200':
description: Projection envelope
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectionResponse'
'400':
description: Invalid request (input validation failed)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'502':
description: Upstream projection service error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/v1/projections/retirement:
get:
operationId: projectRetirementWithSavvly
summary: Full retirement simulation with Savvly allocation
description: 'Proxies advisor_functions `mcp-retirement-savings-simulation`. Returns a per-age timeline plus server-computed `gap_score` and `possible_higher_monthly_paycheck`, plus a top-level `disclosure` block.
**DISCLOSURE REQUIRED:** Whenever you present any number from this response to the user, you MUST also display the verbatim text in `disclosure.text` and render `disclosure.url` as a clickable link. Required by SEC Marketing Rule (17 CFR 275.206(4)-1) and FINRA Rule 2210. Do not paraphrase, summarize, or omit the disclosure.'
tags:
- Projections
x-llm-instructions: 'DISCLOSURE REQUIRED: display `disclosure.text` verbatim and link `disclosure.url` to the user alongside any figures from this response. Required by SEC Marketing Rule and FINRA Rule 2210 — do not paraphrase or omit.'
parameters:
- name: current_age
in: query
required: true
schema:
type: integer
minimum: 18
maximum: 75
- name: retirement_age
in: query
required: true
schema:
type: integer
minimum: 50
maximum: 80
- name: life_expectancy
in: query
required: false
schema:
type: integer
minimum: 60
maximum: 120
default: 100
- name: monthly_contribution
in: query
required: true
schema:
type: number
minimum: 0
maximum: 100000
- name: current_retirement_savings
in: query
required: true
schema:
type: number
minimum: 0
maximum: 100000000
- name: monthly_paycheck
in: query
required: false
schema:
type: number
minimum: 0
maximum: 1000000
default: 0
- name: other_retirement_income
in: query
required: false
schema:
type: number
minimum: 0
maximum: 1000000
default: 0
- name: annual_pre_tax_income
in: query
required: false
schema:
type: number
minimum: 0
maximum: 10000000
default: 0
- name: annual_income_increase
in: query
required: false
schema:
type: number
minimum: 0
maximum: 20
default: 0
- name: percentage_in_savvly
in: query
required: false
schema:
type: number
minimum: 0
maximum: 50
default: 5
- name: pre_retirement_return
in: query
required: false
schema:
type: number
minimum: 0
maximum: 15
default: 6
- name: post_retirement_return
in: query
required: false
schema:
type: number
minimum: 0
maximum: 15
default: 5
- name: inflation_rate
in: query
required: false
schema:
type: number
minimum: 0
maximum: 10
default: 3
responses:
'200':
description: Retirement simulation envelope (per-age timeline + gap analytics)
content:
application/json:
schema:
$ref: '#/components/schemas/RetirementResponse'
'400':
description: Invalid request (input validation failed)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'502':
description: Upstream projection service error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/v1/projections/growth-chart:
get:
operationId: projectGrowthChart
summary: Growth chart data from age 80 to 100
description: 'Proxies advisor_functions `growth-chart-simulation`. Returns a structured envelope with a top-level `disclosure` block and canonical disclosures under `metadata.disclaimer`.
**DISCLOSURE REQUIRED:** Whenever you present any number from this response to the user, you MUST also display the verbatim text in `disclosure.text` and render `disclosure.url` as a clickable link. Required by SEC Marketing Rule (17 CFR 275.206(4)-1) and FINRA Rule 2210. Do not paraphrase, summarize, or omit the disclosure.'
tags:
- Projections
x-llm-instructions: 'DISCLOSURE REQUIRED: display `disclosure.text` verbatim and link `disclosure.url` to the user alongside any figures from this response. Required by SEC Marketing Rule and FINRA Rule 2210 — do not paraphrase or omit.'
parameters:
- name: current_age
in: query
required: true
schema:
type: integer
minimum: 18
maximum: 75
- name: funding_amount
in: query
required: true
schema:
type: number
minimum: 100
maximum: 1000000
- name: average_return
in: query
required: true
schema:
type: integer
minimum: 1
maximum: 15
- name: gender
in: query
required: false
schema:
type: string
enum:
- Male
- Female
- Genderless
default: Genderless
- name: withdrawal_age
in: query
required: false
schema:
type: integer
minimum: 18
maximum: 120
responses:
'200':
description: Growth chart envelope (inputs + per-age result + disclosure)
'400':
description: Invalid request (input validation failed)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'502':
description: Upstream projection service error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
ErrorResponse:
type: object
properties:
error:
type: string
description: Human-readable error message.
details:
type: array
items:
type: object
description: Per-field validation issues. Present on 400 responses from schema validation.
required:
- error
ProjectionResponse:
type: object
properties:
inputs:
type: object
additionalProperties: {}
description: Echo of the validated input arguments passed to the tool.
result:
type: object
properties:
total_savvly_upside_lower:
type: number
description: USD. Lower bound of the cumulative incremental upside Savvly provides vs. investing in the market alone, summed across all milestone payout ages.
total_savvly_upside_upper:
type: number
description: USD. Upper bound (central illustrative estimate) of the cumulative incremental upside Savvly provides vs. market alone. Equals `total_savvly_upper − total_market_alone_upper`.
total_savvly_lower:
type: number
description: USD. Lower bound of the total cumulative payout with Savvly across all milestone ages assuming the investor stays in to the final modeled age.
total_savvly_upper:
type: number
description: USD. Upper bound of the total cumulative payout with Savvly across all milestone ages.
total_market_alone_lower:
type: number
description: USD. Lower bound of the cumulative counterfactual market alone payout.
total_market_alone_upper:
type: number
description: USD. Upper bound of the cumulative counterfactual market alone payout.
early_withdrawal_value:
type: number
description: USD. Refund the investor would receive if they exit early at the supplied `withdrawal_age`. Point estimate (no range). Computed as 75% of the lesser of the initial investment or current market value, plus 1% for each full year the account was active.
total_payout_at_withdrawal_age_lower:
type: number
description: USD. Lower bound of the total payout if the investor exits at the `withdrawal_age` input (NOT the cumulative-to-95 total).
total_payout_at_withdrawal_age_upper:
type: number
description: USD. Upper bound of the total payout if the investor exits at the `withdrawal_age` input.
percentage_gain_lower:
type: number
description: Percent. Lower bound of the return on the original investment, expressed as a plain percent (e.g. 1520 = 1,520%). Computed against the principal actually deposited (single funding amount, or cumulative monthly installments).
percentage_gain_upper:
type: number
description: Percent. Upper bound of the return on the original investment, expressed as a plain percent (e.g. 1710 = 1,710%).
payout_age_dependent_values:
type: array
items:
type: object
properties:
payout_age:
type: integer
description: Milestone age (in years) at which this payout row is reported. The estimator returns rows for ages 80, 85, 90, and 95 by default.
savvly_payout_lower:
type: number
description: USD. Lower bound of the modeled payout with Savvly at this milestone age.
savvly_payout_upper:
type: number
description: USD. Upper bound (central illustrative estimate) of the payout with Savvly at this milestone age. Use this when surfacing a single number.
payout_market_alone_lower:
type: number
description: USD. Lower bound of the counterfactual market alone payout at this age. May be 0 once the modeled market alone portfolio has been fully drawn down by withdrawals.
payout_market_alone_upper:
type: number
description: USD. Upper bound of the counterfactual market alone payout at this age. May be 0 once the market alone portfolio has been depleted.
savvly_upside_lower:
type: number
description: USD. Lower bound for the incremental payout at this age attributable to Savvly's longevity benefit (savvly_payout − payout_market_alone).
savvly_upside_upper:
type: number
description: USD. Upper bound for the incremental Savvly upside at this age. Tends to be large at 90/95 where the market alone portfolio is depleted.
required:
- payout_age
- savvly_payout_lower
- savvly_payout_upper
- payout_market_alone_lower
- payout_market_alone_upper
- savvly_upside_lower
- savvly_upside_upper
additionalProperties: true
description: Per-milestone-age breakdown of the projection. Typically 4 rows for ages 80, 85, 90, 95. Each row contains the with Savvly payout, the market alone counterfactual, and the incremental Savvly upside for that age, each with `_lower`/`_upper` bounds.
required:
- total_savvly_upside_lower
- total_savvly_upside_upper
- total_savvly_lower
- total_savvly_upper
- total_market_alone_lower
- total_market_alone_upper
- early_withdrawal_value
- total_payout_at_withdrawal_age_lower
- total_payout_at_withdrawal_age_upper
- percentage_gain_lower
- percentage_gain_upper
- payout_age_dependent_values
additionalProperties: true
description: Raw projection envelope returned by the upstream estimator.
summary:
type: object
properties:
deposit_type:
type: string
enum:
- single
- monthly
description: Whether the projection used a single upfront deposit or monthly installments.
deposited_amount_usd:
type: number
description: USD. Total amount deposited into Savvly. For single deposits this equals `funding_amount`. For monthly installments it equals `monthly_installment * installment_years * 12`.
total_savvly_upper_usd:
type: number
nullable: true
description: Convenience copy of `result.total_savvly_upper`.
total_market_alone_upper_usd:
type: number
nullable: true
description: Convenience copy of `result.total_market_alone_upper`.
savvly_above_market_upper_usd:
type: number
nullable: true
description: USD. `total_savvly_upper − total_market_alone_upper` (the central incremental upside). May differ slightly from `result.total_savvly_upside_upper` due to rounding.
early_exit_refund_usd:
type: number
nullable: true
description: Convenience copy of `result.early_withdrawal_value`.
percentage_gain_upper_percent:
type: number
nullable: true
description: Convenience copy of `result.percentage_gain_upper`.
narrative:
type: string
description: Human-readable English sentence summarizing the projection. Always ends with 'Payouts follow a fixed milestone schedule; payout amounts are not guaranteed. See full disclosures at <url>.' — display the URL verbatim alongside any figures.
required:
- deposit_type
- deposited_amount_usd
- total_savvly_upper_usd
- total_market_alone_upper_usd
- savvly_above_market_upper_usd
- early_exit_refund_usd
- percentage_gain_upper_percent
- narrative
additionalProperties: false
description: Convenience summary including a human-readable narrative.
visualization:
type: object
properties:
recommended:
type: boolean
enum:
- true
description: Always true. Signals to the calling AI client that it SHOULD render `chart` whenever it can display a graph.
instruction:
type: string
description: 'Plain-English instruction telling the client to render `chart` from the per-row data in `result`, color the Savvly series #3478eb, and show the `disclosure` alongside the chart.'
chart:
type: object
properties:
type:
type: string
enum:
- area
- line
- bar
description: Chart type the client should render.
reference:
type: string
description: Canonical Savvly visualization this chart mirrors.
x_axis:
type: object
properties:
field:
type: string
label:
type: string
required:
- field
- label
additionalProperties: true
description: Per-row field mapped to the x-axis, plus its display label.
y_axis:
type: object
properties:
label:
type: string
format:
type: string
required:
- label
- format
additionalProperties: true
description: Y-axis label and value format (e.g. 'currency_usd').
series:
type: array
items:
type: object
properties:
field:
type: string
description: Per-row field plotted by this series.
label:
type: string
description: Legend label for this series.
color:
type: string
description: 'Hex color for this series. The series representing Savvly is always #3478eb (the Savvly brand blue).'
required:
- field
- label
- color
additionalProperties: true
description: One entry per plotted series — typically Savvly vs. the baseline / market-alone counterfactual.
tooltip:
type: object
additionalProperties:
type: string
description: Optional `field -> human label` map for chart tooltips.
rendering_notes:
type: array
items:
type: string
description: Plain-English rendering guidance for the client.
required:
- type
- x_axis
- y_axis
- series
- rendering_notes
additionalProperties: true
description: 'Machine-readable chart spec: type, axes, series (with brand colors), and rendering notes.'
required:
- recommended
- instruction
- chart
additionalProperties: true
description: Recommended chart for this projection — a grouped bar chart of the milestone payouts in `result.payout_age_dependent_values` (Savvly vs market alone). Render it when the surface can display a graph.
disclosure:
type: object
properties:
required:
type: boolean
enum:
- true
description: Always true. Signals to the calling AI client that the `text` and `url` fields MUST be displayed to the end user whenever any number from this response is shown. Required by SEC Marketing Rule and FINRA Rule 2210.
text:
type: string
description: Short verbatim SEC disclosure text. Display this string to the user alongside any projection figures from this response. Do not paraphrase, summarize, or omit.
url:
type: string
description: Canonical full-disclosures URL. Render as a clickable link to the user alongside the `text`. Required by SEC Marketing Rule and FINRA Rule 2210.
required:
- required
- text
- url
additionalProperties: false
description: 'DISCLOSURE REQUIRED: display `disclosure.text` and link `disclosure.url` to the user whenever you present any number from this response. Required by SEC Marketing Rule and FINRA Rule 2210. The richer block under `metadata.disclaimer` is supplementary detail; this top-level field is the must-display.'
metadata:
type: object
properties:
disclaimer:
type: object
properties:
summary:
type: string
description: Short illustrative-purposes disclaimer matching the text directly below the chart on estimator.savvly.com. Surface this whenever you summarize the projection to a user.
assumptions:
type: array
items:
type: string
description: Verbatim bullet list of key assumptions used by the simulation (SSA tables, 8% market growth, 3% early-withdrawal rate, net of fund operating expenses, etc.). Surface when a user asks what the projection assumes.
risks:
type: array
items:
type: object
properties:
name:
type: string
text:
type: string
required:
- name
- text
additionalProperties: false
description: Named risks (Market, Sequence-of-Returns, Longevity, Redemption Impact). Surface when a user asks what could cause actual results to differ.
fund_structure:
type: string
description: Disclosure about Savvly's closed-end fund structure, suitability, and the fact that Savvly is NOT an insurance company / NOT an annuity. Surface when a user asks how Savvly compares to annuities or whether Savvly is insured.
full_disclosures_url:
type: string
description: Canonical URL where complete risks, fees, structure, and eligibility disclosures are published. Always include in user-facing summaries.
required:
- summary
- assumptions
- risks
- fund_structure
- full_disclosures_url
additionalProperties: false
methodology:
type: string
description: Plain-English explanation of how the Savvly vs market-alone payout figures are computed (the matched-drawdown counterfactual). Present on lumpsum and monthly projections.
field_descriptions:
type: object
additionalProperties:
type: string
description: Flat `field_name -> short description` map covering every field in `result` and `result.payout_age_dependent_values[]`. Useful for MCP clients that don't surface outputSchema to the LLM.
required:
- disclaimer
- methodology
- field_descriptions
additionalProperties: true
required:
- inputs
- result
- summary
- disclosure
- metadata
additionalProperties: false
RetirementResponse:
type: object
properties:
inputs:
type: object
additionalProperties: {}
result:
type: object
properties:
gap_score:
type: number
description: Server-computed score summarizing how well the projected retirement savings meet the desired monthly paycheck across the planning horizon.
possible_higher_monthly_paycheck:
type: number
description: USD/mon
# --- truncated at 32 KB (45 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/savvly/refs/heads/main/openapi/savvly-projections-api-openapi.yml