Tax topography — the marginal-rate map

The whole tax landscape in one call: sweep an income variable and plot the true marginal rate on the next dollar — surfacing the Social Security tax torpedo, IRMAA cliffs, the ACA cliff, NIIT, and LTCG stacking in a single curve. It's the map the other tax guides each zoom into.

1 · Make the call

Send a base income picture plus the variable to sweep to /v1/tax/marginal-map. Here: a single retiree with $35k of Social Security, sweeping IRA withdrawals from $0 to $100k, with the Medicare IRMAA surcharge on.

curl -X POST https://api.numeratica.com/v1/tax/marginal-map \
  -H "Authorization: Bearer nmr_sk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tax_year": 2025, "filing_status": "single",
    "ordinary_income": 20000, "social_security_benefits": 35000,
    "sweep_variable": "ordinary", "sweep_start": 0, "sweep_stop": 100000, "sweep_step": 1000,
    "include_irmaa": true, "medicare_beneficiaries": 1
  }'

2 · The response

One point per grid step — each with the true marginal_rate and an additive components breakdown (the parts sum to the rate) — plus the discrete cliffs (IRMAA tier crossings, the ACA cliff) reported separately so the curve stays readable. (A few of the 101 grid points shown.)

{
  "result_id": "marginalmap_79fe856295250351",
  "engine_version": "marginal-map-1.0.0",
  "result": {
    "points": [
      { "income": 0,     "agi": 27475, "marginal_rate": 0.218,
        "components": { "ordinary": 0.116, "ss_inclusion": 0.102 } },
      { "income": 18000, "agi": 60775, "marginal_rate": 0.222,
        "components": { "ordinary": 0.12, "ss_inclusion": 0.102 } },   /* 12% bracket × 1.85 */
      { "income": 20000, "agi": 64475, "marginal_rate": 0.407,
        "components": { "ordinary": 0.22, "ss_inclusion": 0.187 } },   /* the torpedo: 22% × 1.85 */
      { "income": 27000, "agi": 76750, "marginal_rate": 0.22,
        "components": { "ordinary": 0.22, "ss_inclusion": 0 } },       /* SS fully taxed — back to bracket */
      { "income": 70000, "agi": 119750, "marginal_rate": 0.24,
        "components": { "ordinary": 0.24 } }
    ],
    "cliffs": [
      { "income": 57000, "kind": "irmaa", "annual_jump": 1052.40 },    /* MAGI crosses $106k (tier 1) */
      { "income": 84000, "kind": "irmaa", "annual_jump": 1591.20 }     /* MAGI crosses $133k (tier 2) */
    ]
  },
  "disclaimer": "Calculation engine output for informational purposes only; not tax or financial advice."
}

The torpedo isn't a special case — each swept dollar pulls up to 85¢ more of the benefit into tax (§86), which is why a 22% bracket behaves like 40.7% in the band ($20k–$25k of withdrawals here). Then two IRMAA cliffs land as MAGI crosses the 2025 single tiers: +$1,052/yr at ~$56k and +$1,591/yr at ~$83k.

3 · Render it

Plot the curve and mark the cliffs — self-contained inline SVG, no chart library, no build step.

Rendered output
<div style="font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#1a2230;max-width:600px">
  <div style="font-size:14px;color:#5b6675;margin-bottom:6px">Effective marginal rate on the next dollar · single retiree, $35k Social Security, sweeping IRA withdrawals (2025)</div>
  <svg viewBox="0 0 560 280" width="100%" style="max-width:600px;height:auto" role="img" aria-label="Effective marginal rate vs IRA-withdrawal income">
    <!-- axes -->
    <line x1="50" y1="30" x2="50" y2="240" stroke="#e6e9ef"/>
    <line x1="50" y1="240" x2="530" y2="240" stroke="#e6e9ef"/>
    <!-- 22% stated-bracket reference -->
    <line x1="50" y1="148" x2="530" y2="148" stroke="#e6e9ef" stroke-dasharray="4 4"/>
    <g font-size="15" fill="#9aa3b0" text-anchor="end">
      <text x="44" y="244">0%</text><text x="44" y="152">22%</text><text x="44" y="72">41%</text>
    </g>
    <g font-size="15" fill="#9aa3b0" text-anchor="middle">
      <text x="50" y="256">$0</text><text x="290" y="256">$50k</text><text x="530" y="256">$100k</text>
      <text x="290" y="272" fill="#5b6675">IRA-withdrawal income swept</text>
    </g>
    <!-- IRMAA cliffs (reported separately from the curve) -->
    <line x1="319" y1="44" x2="319" y2="240" stroke="#dc2626" stroke-dasharray="3 3"/>
    <g font-size="15" font-weight="600" fill="#dc2626"><text x="322" y="56">IRMAA 1</text><text x="322" y="68">+$1,052/yr</text></g>
    <line x1="448" y1="44" x2="448" y2="240" stroke="#dc2626" stroke-dasharray="3 3"/>
    <g font-size="15" font-weight="600" fill="#dc2626"><text x="452" y="56">IRMAA 2</text><text x="452" y="68">+$1,591/yr</text></g>
    <!-- marginal-rate curve -->
    <polyline fill="none" stroke="#1d4ed8" stroke-width="2.5"
      points="50,148 136,147 141,136 146,69 170,69 175,131 180,148 376,148 381,142 386,139 530,139"/>
    <!-- annotations -->
    <circle cx="146" cy="69" r="3.5" fill="#b45309"/>
    <text x="152" y="62" font-size="15" font-weight="600" fill="#b45309">SS tax torpedo — 40.7%</text>
    <text x="524" y="133" font-size="15" font-weight="600" fill="#1a2230" text-anchor="end">24% bracket</text>
  </svg>
  <div style="color:#5b6675;font-size:12px;margin-top:6px">Stated bracket is 22% (dashed) · the torpedo and the two IRMAA cliffs are the hidden costs · result_id marginalmap_79fe856295250351 · not tax advice</div>
</div>

Related zoom-ins: the Social Security tax torpedo and the IRMAA bracket planner.

← All guides