---
title: "Simulate a dynamic retirement-spending strategy"
method: POST
path: "/v1/retirement/withdrawal-strategy"
tags: ["Retirement"]
---

# Simulate a dynamic retirement-spending strategy

`POST /v1/retirement/withdrawal-strategy`

## Request

- Base URL: `https://api.numeratica.com`
- URL: `https://api.numeratica.com/v1/retirement/withdrawal-strategy`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Projects retirement spending under a chosen dynamic-withdrawal rule across Monte Carlo market paths, reporting the year-by-year spending distribution, success probability, spending volatility, and ending-balance percentiles. Strategies: fixed_real (constant real, the "4% rule"), fixed_pct (percent of current balance), guardrails (Guyton-Klinger), vpw (Variable Percentage Withdrawal), and floor_and_ceiling. Shares the Monte Carlo return model and deterministic RNG. Calculation engine output, not financial advice. Deterministic given a seed.

## Request body

- WithdrawalStrategyRequest
  - `annual_fee_rate` number, double: All-in annual cost drag as a decimal (0.01 = 1%): advisory fee plus fund expense ratios, applied as a reduction to the expected return. Omitted or 0 means the projection is GROSS of fees, which leaves result_id unchanged. Costs compound: a 1% load moves long-horizon outcomes by a large margin (see the Concepts page).
  - `current_age` integer, required: Start of decumulation; spending begins now.
  - `end_age` integer, required
  - `current_balance` number, required
  - `initial_rate` number, required: First-year withdrawal rate (used by all strategies except vpw).
  - `strategy` 'fixed_real' | 'fixed_pct' | 'guardrails' | 'vpw' | 'floor_and_ceiling', required
  - `expected_return` number: Required unless glide_path is given.
  - `return_volatility` number: Required unless glide_path is given.
  - `inflation` number
  - `num_simulations` integer
  - `seed` integer: Optional; generated and echoed back if absent (for reproducibility).
  - `glide_path` object[]: Optional age-varying return assumptions (same shape as the Monte Carlo endpoint).
    - `age` integer
    - `expected_return` number
    - `return_volatility` number
  - `guard_width` number: guardrails: band half-width vs the initial rate (default 0.20).
  - `guard_adjust` number: guardrails: spending cut/raise step (default 0.10).
  - `vpw_real_return` number: vpw: assumed real return for the amortization factor (default 0.03).
  - `floor_mult` number: floor_and_ceiling: lower bound × initial real withdrawal (default 0.85).
  - `ceiling_mult` number: floor_and_ceiling: upper bound × initial real withdrawal (default 1.20).

## Response `200`

Dynamic-withdrawal projection

- WithdrawalStrategyResponse
  - `result_id` string
  - `engine_version` string
  - `seed` integer
  - `inputs` WithdrawalStrategyRequest
    - `annual_fee_rate` number, double: All-in annual cost drag as a decimal (0.01 = 1%): advisory fee plus fund expense ratios, applied as a reduction to the expected return. Omitted or 0 means the projection is GROSS of fees, which leaves result_id unchanged. Costs compound: a 1% load moves long-horizon outcomes by a large margin (see the Concepts page).
    - `current_age` integer, required: Start of decumulation; spending begins now.
    - `end_age` integer, required
    - `current_balance` number, required
    - `initial_rate` number, required: First-year withdrawal rate (used by all strategies except vpw).
    - `strategy` 'fixed_real' | 'fixed_pct' | 'guardrails' | 'vpw' | 'floor_and_ceiling', required
    - `expected_return` number: Required unless glide_path is given.
    - `return_volatility` number: Required unless glide_path is given.
    - `inflation` number
    - `num_simulations` integer
    - `seed` integer: Optional; generated and echoed back if absent (for reproducibility).
    - `glide_path` object[]: Optional age-varying return assumptions (same shape as the Monte Carlo endpoint).
      - `age` integer
      - `expected_return` number
      - `return_volatility` number
    - `guard_width` number: guardrails: band half-width vs the initial rate (default 0.20).
    - `guard_adjust` number: guardrails: spending cut/raise step (default 0.10).
    - `vpw_real_return` number: vpw: assumed real return for the amortization factor (default 0.03).
    - `floor_mult` number: floor_and_ceiling: lower bound × initial real withdrawal (default 0.85).
    - `ceiling_mult` number: floor_and_ceiling: upper bound × initial real withdrawal (default 1.20).
  - `result` object
    - `strategy` string
    - `success_probability` number: Fraction of paths that fund spending to end_age.
    - `spending_volatility` number: Median across paths of the stddev of annual real-spending growth.
    - `median_first_year_spending` number: Real (today's) dollars.
    - `median_lifetime_spending` number: Median across paths of total real spending.
    - `spending_path` object[]: Per-year real-spending percentiles.
      - `age` integer
      - `p10` number
      - `p50` number
      - `p90` number
    - `ending_balance` object: Ending-balance percentiles (nominal).
      - `p10` number
      - `p25` number
      - `p50` number
      - `p75` number
      - `p90` number
    - `num_simulations` integer
    - `seed` integer
  - `disclaimer` string

## Other responses

- `400`: Invalid request
- `401`: Missing or invalid API key.
- `405`: Method not allowed
- `429`: The key's per-minute request budget is exceeded. Retry after the delay in the Retry-After header.
- `503`: A dependency (e.g. the key store) is temporarily unavailable, or the request exceeded its compute deadline. Retryable.

---

[API](https://skmtc.dev/numeratica/apis/numeratica-financial-planning-calculations-api.md) · [All operations](https://skmtc.dev/numeratica/apis/numeratica-financial-planning-calculations-api/llms.txt) · [OpenAPI document](https://skmtc.dev/numeratica/apis/numeratica-financial-planning-calculations-api/revisions/075bcfbd1ebf?raw)
