# Reimbursement

A reimbursement pays a user back from their own HSA or FSA for expenses Sail has already classified as eligible. This page explains what a reimbursement needs before Sail creates one, how its status changes from creation to a successful payout, and the two distinct ways it can fail.

## What a reimbursement is

A reimbursement is a request to pay a user back from their own benefit account for a set of expenses. Sail doesn't fund it, and neither does your application. It draws from a `benefit_account` connection, the same connection type covered in [Account Connections](/docs/concepts/account-connections), and it only ever returns money the user already has in that account.

<Callout type="info">
  **Scope required**

  Creating, getting, or listing reimbursements needs the `benefit_account` key scope. Creating one also needs the `benefit_account` product on the funding account's connection.
</Callout>

## Preconditions

Two things must be true before Sail accepts a request to create a reimbursement.

* Every included expense must carry an `eligible` [Section 213(d) classification](/docs/concepts/expense-classification). An expense that's `ineligible`, still `itemization_required`, or `lmn_required` can't be reimbursed until it resolves to `eligible`.
* The funding account's cash balance must cover the sum of the included expenses. Sail checks that total against the account's available balance, not against each expense individually.

An expense can only belong to one reimbursement at a time. Including an expense that isn't `eligible`, or one that's already part of an in-flight reimbursement, returns a `409 conflict` error instead of creating a new reimbursement.

## Creating a reimbursement

A reimbursement request names the expenses to pay back and the account to pay them from: an array of expense IDs plus the funding `account_id`, matching the [`ReimbursementCreateRequest`](/reference/reimbursements/post-users-user-id-reimbursements) shape. Sail responds with a `Reimbursement` object, identified by an ID like `reimb_8c1f`, whose `amount` field reports the sum of the included expenses as a decimal USD value (for example, `1050.50` for $1,050.50).

## The status lifecycle

A reimbursement moves through four statuses on its way to a successful payout:

* `pending`: Sail has created the reimbursement and is about to contact the funding account's administrator.
* `submitted`: Sail has submitted the included expenses to the administrator.
* `processing`: the administrator is processing the submitted claim.
* `completed`: the administrator has finished processing the claim, and the money has moved out of the account back to the user. `completed` reflects money actually moving, not just the administrator approving the claim.

Once a reimbursement reaches `completed`, its expenses move to a `reimbursed` status, and a receipt document becomes available through [Get Reimbursement](/reference/reimbursements/get-users-user-id-reimbursements-reimbursement-id)'s `receipt_url` field, which stays empty until then.

## Why a reimbursement fails

A `failed` status covers two distinct causes, both surfaced the same way today:

* **Failed to submit**: something went wrong on Sail's side before the claim reached the administrator. Sail doesn't automatically retry, but you can resubmit the same expenses and account as a new reimbursement request.
* **Failed after submission**: the administrator denied the claim. Sail returns a reason alongside the failure. Denial reasons aren't a fixed set, since administrators' review processes vary and are still evolving. For example, an administrator can ask for a Letter of Medical Necessity on an expense Sail classified as `eligible`, since each administrator applies its own documentation standards when it reviews a claim. A `failed` reason is context on that decision, not a fixed, retryable error code.

  <Callout type="info">
  **LMN required after submission**

    Support for resolving a Letter of Medical Necessity request through Sail is on the way. We'll update these docs as soon as it's live.
  </Callout>

## How you find out the result

Sail sends a `reimbursement.status_changed` webhook on every status transition, naming the `reimbursement_id`, the `previous_status`, the new `status`, and a `failure_reason` when the new status is `failed`. See [Receiving New Data](/docs/concepts/receiving-new-data) for how to verify and deduplicate any webhook delivery, reimbursements included.

The current status is also available any time from [Get Reimbursement](/reference/reimbursements/get-users-user-id-reimbursements-reimbursement-id) or [List Reimbursements](/reference/reimbursements/get-users-user-id-reimbursements), so polling either endpoint on any cadence stays a valid alternative to only listening for the webhook.

## Next steps

* To confirm eligibility and balance, create a reimbursement, and track it to completion, see [Create and Track a Reimbursement](/docs/guides/create-and-track-a-reimbursement).
* To see the three ways Sail connects to an account, including the `benefit_account` connections a reimbursement draws from, see [Account Connections](/docs/concepts/account-connections).
* To see how an expense reaches `eligible` in the first place, see [Expense Classification](/docs/concepts/expense-classification).