Tax Forms
Use the taxForms, taxForm, and taxFormDownloadLink queries to retrieve an Individual's tax forms. You can list the forms available for each tax year, read the box-level values on a form, and download the rendered PDF.
Today, only HSA Benefits produce tax forms. The API is forward-compatible: filters that select other Benefit types return an empty list, not an error.
Which forms exist
| Form | formType | What it reports |
|---|---|---|
| 1099-SA | HSA_DISTRIBUTIONS | Distributions taken from the HSA during the tax year. |
| 5498-SA | HSA_CONTRIBUTIONS | Contributions to the HSA, plus the account's fair market value at year end. |
An Individual only has a 1099-SA for years in which they took distributions. The 5498-SA is produced for any year with contributions or a year-end balance.
Form lifecycle
Each form version carries a status:
PRELIMINARY— an early, informational version. Final values may differ.FILEABLE— the version filed (or fileable) with the IRS.CORRECTED— a correction to a previously fileable version.
Corrections do not modify an existing form. Each correction is a new version with its own id. The taxForms query groups each year's versions into requiredForms (filed, or to be filed, with the IRS) and informationalForms (not filed).
Availability
Forms become available once they are generated for a tax year. Generation follows IRS reporting timelines. Note that contributions designated for a tax year can continue through the following year's tax-filing deadline, so a 5498-SA's values may not be final until after that window closes. Querying a year before its forms are generated returns no forms for that year, not an error.
What you need
individualId— the Individual whose tax forms to retrieve. This is theidreturned by createIndividual or the individuals query.
List an Individual's tax forms
Forms are grouped by tax year, most recent year first.
query TaxForms($where: TaxFormsFilterInput!) {
taxForms(where: $where) {
... on TaxFormsResults {
annualTaxForms {
taxYear
requiredForms {
id
taxYear
formName
formType
status
formDate
validAsOfDate
}
informationalForms {
id
taxYear
formName
formType
status
formDate
validAsOfDate
}
}
}
... on BadRequestError {
message
code
retryable
}
... on InternalServerError {
message
code
retryable
}
}
}
Variables:
{
"where": { "individualId": "<individualId>" }
}
A successful response:
{
"data": {
"taxForms": {
"annualTaxForms": [
{
"taxYear": "2026",
"requiredForms": [
{
"id": "<taxFormId>",
"taxYear": "2026",
"formName": "1099-SA",
"formType": "HSA_DISTRIBUTIONS",
"status": "FILEABLE",
"formDate": "2027-01-21",
"validAsOfDate": "2026-12-31"
}
],
"informationalForms": [
{
"id": "<taxFormId>",
"taxYear": "2026",
"formName": "5498-SA",
"formType": "HSA_CONTRIBUTIONS",
"status": "PRELIMINARY",
"formDate": "2027-01-21",
"validAsOfDate": "2027-01-20"
}
]
}
]
}
}
}
Filters
All filters are optional. Omitted filters do not restrict the result.
| Filter | Behavior |
|---|---|
benefitTypes | Only forms arising from accounts of these Benefit types. Today only HSA produces forms. |
formTypes | Only forms of these types, e.g. [HSA_DISTRIBUTIONS]. |
taxYears | Only forms for these tax years, e.g. ["2026"]. |
Get a tax form's data
Fetch box-level values with the taxForm query, using an id returned by the list query. The shape of data depends on the form's formType.
query TaxForm($where: TaxFormFilterInput!) {
taxForm(where: $where) {
... on TaxFormDetail {
taxForm {
id
taxYear
formName
formType
status
}
data {
... on DistributionsTaxFormData {
grossDistribution {
currency
lowestDenominationAmount
amount
}
earningsOnExcessContributions {
currency
lowestDenominationAmount
amount
}
distributionCode
fmvOnDateOfDeath {
currency
lowestDenominationAmount
amount
}
}
... on ContributionsTaxFormData {
contributionsMadeInTaxYear {
currency
lowestDenominationAmount
amount
}
contributionsMadeInSubsequentYear {
currency
lowestDenominationAmount
amount
}
rolloverContributions {
currency
lowestDenominationAmount
amount
}
fmv {
currency
lowestDenominationAmount
amount
}
}
}
}
... on BadRequestError {
message
code
retryable
}
... on InternalServerError {
message
code
retryable
}
}
}
Variables:
{
"where": {
"individualId": "<individualId>",
"id": "<taxFormId>"
}
}
A successful response for a 1099-SA:
{
"data": {
"taxForm": {
"taxForm": {
"id": "<taxFormId>",
"taxYear": "2026",
"formName": "1099-SA",
"formType": "HSA_DISTRIBUTIONS",
"status": "FILEABLE"
},
"data": {
"grossDistribution": {
"currency": "USD",
"lowestDenominationAmount": 84250,
"amount": 842.5
},
"earningsOnExcessContributions": null,
"distributionCode": "1",
"fmvOnDateOfDeath": null
}
}
}
}
The box-level fields match the values printed on the member's form. Null money values render as $0.00 on the PDF. See DistributionsTaxFormData and ContributionsTaxFormData for per-box descriptions.
Download a tax form
Fetch a secure, expiring link to the rendered PDF with the taxFormDownloadLink query. The PDF is the member copy: the form pages the member would receive, including IRS instructions.
query TaxFormDownloadLink($where: TaxFormFilterInput!) {
taxFormDownloadLink(where: $where) {
... on TaxFormDownloadLinkResult {
taxForm {
id
taxYear
formName
}
downloadLink {
downloadUrl
requestHeaders
expires
}
}
... on BadRequestError {
message
code
retryable
}
... on InternalServerError {
message
code
retryable
}
}
}
Variables:
{
"where": {
"individualId": "<individualId>",
"id": "<taxFormId>"
}
}
A successful response:
{
"data": {
"taxFormDownloadLink": {
"taxForm": {
"id": "<taxFormId>",
"taxYear": "2026",
"formName": "1099-SA"
},
"downloadLink": {
"downloadUrl": "<downloadUrl>",
"requestHeaders": {
"<header name>": "<header value>"
},
"expires": "2026-06-03T22:15:00.000Z"
}
}
}
}
To retrieve the PDF, issue a GET request to downloadUrl and include every entry in requestHeaders as an HTTP header on the request.
Handle the link with care:
- The headers are sensitive. They may contain decryption material. Do not log them or expose them to anything but the download request.
- Links expire. The
expirestimestamp (ISO 8601) tells you when. Request a fresh link for each download rather than storing links.
Errors
Returns BadRequestError when:
- The Individual cannot be found. The
individualIdis unknown or does not belong to your organizations. - The tax form cannot be found. The
idis unknown or does not belong to the suppliedindividualId.
Unexpected failures return InternalServerError; these are safe to retry.
See also
- Statements — monthly account statements for an Individual.