---
title: "529→Roth IRA rollover eligibility (SECURE 2.0 §126)"
method: POST
path: "/v1/education/529-to-roth"
tags: ["Education"]
---

# 529→Roth IRA rollover eligibility (SECURE 2.0 §126)

`POST /v1/education/529-to-roth`

## Request

- Base URL: `https://api.numeratica.com`
- URL: `https://api.numeratica.com/v1/education/529-to-roth`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

How much of a 529 balance can be rolled into the beneficiary's Roth IRA under SECURE 2.0 §126? The rollover is gated: the account must be 15+ years old, contributions from the last 5 years are excluded, each year is capped at the Roth IRA contribution limit (less the beneficiary's other IRA contributions for the year) and by the beneficiary's earned income, and there is a $35,000 lifetime cap per beneficiary. Returns the maximum this year, which cap binds, and how many years to exhaust the lifetime limit. Deterministic; not tax advice.

## Request body

- Rollover529Request
  - `year` integer: For the IRA contribution limit; omit for 2026.
  - `beneficiary_age` integer, required: Drives the age-50 IRA catch-up.
  - `balance` number, required: Total 529 balance.
  - `account_age_years` integer, required: Years the 529 has been open (15+ required).
  - `recent_contributions` number: Contributions (+ earnings) from the last 5 years — ineligible to roll.
  - `lifetime_rolled_already` number: Prior rollovers counted against the $35k cap.
  - `other_ira_contributions` number: Beneficiary's other Trad/Roth IRA contributions this year.
  - `beneficiary_earned_income` number: Compensation; the rollover cannot exceed it.

## Response `200`

The rollover analysis

- Rollover529Response
  - `result_id` string
  - `engine_version` string
  - `inputs` Rollover529Request
    - `year` integer: For the IRA contribution limit; omit for 2026.
    - `beneficiary_age` integer, required: Drives the age-50 IRA catch-up.
    - `balance` number, required: Total 529 balance.
    - `account_age_years` integer, required: Years the 529 has been open (15+ required).
    - `recent_contributions` number: Contributions (+ earnings) from the last 5 years — ineligible to roll.
    - `lifetime_rolled_already` number: Prior rollovers counted against the $35k cap.
    - `other_ira_contributions` number: Beneficiary's other Trad/Roth IRA contributions this year.
    - `beneficiary_earned_income` number: Compensation; the rollover cannot exceed it.
  - `result` object
    - `eligible` boolean: The 15-year account-age rule is met.
    - `lifetime_cap` number: $35,000.
    - `lifetime_remaining` number: Cap − already rolled.
    - `annual_ira_limit` number: The year's Roth IRA contribution limit (incl. catch-up).
    - `annual_room` number: IRA limit − other IRA contributions.
    - `eligible_balance` number: Balance − recent (last-5-year) contributions.
    - `max_rollover_this_year` number: The binding minimum of all the caps.
    - `limiting_factor` 'account_age_under_15_years' | 'annual_ira_limit' | 'lifetime_cap' | 'eligible_balance' | 'earned_income'
    - `years_to_rollover_cap` integer: Whole years at this rate to exhaust the lifetime remaining (0 if none possible).
  - `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)
