> This page is for version v1 (default).
> For other versions, use one of these documentation indexes:
> - v1 (default): https://developers.truemed.com/v-1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.truemed.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.truemed.com/_mcp/server.

# Token lifecycle

> What each payment token state means, and how to get a customer back to a chargeable token.

A payment token is either chargeable or blocked on something the customer has to do. When it's
blocked, Truemed tells you which action is needed and where to send the customer. Your job is to
relay that action and wait for the token to come back.

This page is the reference for every way a token can stop working and how to recover it. For the
happy path, see [Recurring Charges](/guides/setup/api/subscriptions/subsequent-billing-periods).

## Token states

> **Note**
>
> These state names are a model for reasoning about tokens, not values returned by the API. There is no
> `status` field on a payment token—you infer the state from your charge results and the
> [`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook.

| State                     | What it means                                                                            | What to do                                                                                  |
| ------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Provisioning**          | The token was requested but the customer hasn't finished the survey and card entry.      | Wait for `payment_token_updated`. Don't attempt a charge—it returns `400` `SessionPending`. |
| **Active**                | The token is chargeable.                                                                 | Charge it each billing period.                                                              |
| **Needs customer action** | A charge came back `422` with a `next_action`.                                           | Send the customer to the `redirect_url`, then wait for `payment_token_updated`.             |
| **Deleted**               | You called [`delete_payment_token`](/api-reference/payment-tokens/delete-payment-token). | Nothing—this is terminal. Charging returns `NotFound`.                                      |

## How a charge maps to token state

One table for the whole picture: what you get back from
[`create_payment_session`](/api-reference/payment-sessions/create-payment-session) when charging a
token, and what it tells you about the token.

| Charge outcome                                     | HTTP response                       | `next_action`         | Token state           |
| -------------------------------------------------- | ----------------------------------- | --------------------- | --------------------- |
| Charge accepted                                    | `200` with the payment session `id` | omitted               | Active                |
| Card expired or declined                           | `422`                               | `UpdatePaymentMethod` | Needs customer action |
| Cart contains ineligible items with no backup card | `422`                               | `UpdatePaymentMethod` | Needs customer action |
| Items changed beyond what the LMN covers           | `422`                               | `TakeHealthSurvey`    | Needs customer action |
| The LMN on file has expired                        | `422`                               | `TakeHealthSurvey`    | Needs customer action |
| Customer hasn't finished card entry yet            | `400` `SessionPending`              | —                     | Provisioning          |
| Token was deleted                                  | `404` `NotFound`                    | —                     | Deleted               |

`SessionPending` is not permanent—it means the token exists but the initial payment hasn't been
captured, so there's no payment method to charge yet. Retry the charge once `payment_token_updated`
arrives.

A `200` means the charge was accepted for processing—it does not mean funds are secured. Fulfill only
after the `payment_session_complete` webhook reports `status: captured`, exactly as with a one-time
payment. See [Payment Lifecycle](/guides/setup/api/payment-sessions/payment-lifecycle).

## The 422 response

The body of a `422` is the same shape as a successful `create_payment_session` response, with
`next_action` and `redirect_url` populated:

```json
{
  "id": "c51f5d44-9f8d-4e9f-bc5f-929a6f9f2f51",
  "redirect_url": "https://app.truemed.com/...",
  "next_action": "UpdatePaymentMethod"
}
```

Read `next_action` to decide what to tell the customer, and `redirect_url` to decide where to send
them. Store the `id`—it's the payment session that failed, and it comes back to you as
`failed_payment_session_id` when the customer resolves the block.

## Why a charge fails

Two `next_action` values cover every recoverable failure.

### UpdatePaymentMethod

The customer's card can no longer cover the charge.

**Common causes**

* The HSA/FSA card on file has expired.
* The card was declined.
* The cart contains ineligible items and there's no credit or debit card on file to cover them.

**What the customer must do.** Visit the `redirect_url` and enter current card details. If the charge
failed because of ineligible items, they'll be asked for a regular credit or debit card as a backup
alongside their HSA/FSA card.

**Suggested message.** "Your payment method needs updating to keep your subscription active."

### TakeHealthSurvey

The customer's Letter of Medical Necessity no longer covers what they're buying.

**Common causes**

* The items in the subscription changed and fall outside the existing LMN.
* The existing LMN has expired.
* Truemed has determined the customer needs to retake the survey for another reason.

**What the customer must do.** Visit the `redirect_url` and complete the health survey again. A new
LMN is issued if they still qualify.

**Suggested message.** "Requalify with Truemed to keep using your HSA/FSA funds."

## What to tell the customer

Truemed doesn't email your customers—you do. Adapt this copy to your voice; it's a starting point,
not a requirement.

| `next_action`         | Suggested subject                     | Suggested body                                                                                                   |
| --------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `UpdatePaymentMethod` | Update your payment method            | Your HSA/FSA card couldn't be charged for this month's order. Update your card to keep your subscription active. |
| `TakeHealthSurvey`    | Requalify to keep using HSA/FSA funds | Your Letter of Medical Necessity no longer covers your subscription. Take a short health survey to requalify.    |

Include the `redirect_url` as the call to action in both cases. The link is specific to this customer
and this failure—don't reuse one across customers.

## Recover the subscription

#### The charge returns 422

Read `next_action` and `redirect_url` from the response body, and store the `id` of the failed
payment session.

#### Send the customer to the redirect_url

Either inline or by email, depending on whether they're on your site—see below.

#### The customer resolves the block

They update their card or retake the survey on Truemed's hosted pages.

#### Wait for payment_token_updated

The webhook carries the `payment_token` and the `failed_payment_session_id` of the charge that
triggered the recovery, so you can match it back to the billing period you were retrying.

#### Create a new payment session

Charge the token again with a **new** `create_payment_session` call. Don't try to resume the
failed session.

> **Warning**
>
> Retrying the charge before `payment_token_updated` arrives returns the same `422`. The webhook is the
> signal that the customer's action actually landed.

A customer can also resolve a block without ever touching your app—for instance by following a link
from an older email. Treat `payment_token_updated` as a stand-down signal: when it arrives, clear any
banner, dashboard warning, or scheduled reminder you raised for that token. Otherwise you'll keep
chasing customers who already fixed the problem.

### If the customer is on your site

Surface the `redirect_url` immediately, inside the flow they're already in. This applies when the
charge was triggered by something the customer just did—changing their plan, adding an item, or
checking out. Send them straight to Truemed and bring them back to your `success_url`.

This is also the right path for a subscription-management dashboard. See
[Update an active subscription](/guides/setup/api/subscriptions/update-an-active-subscription) for
generating an update link on demand rather than waiting for a charge to fail.

![Updating Payment Method Flow](/_fern-img/35a50b873eba594f679b79bb09cc931b65aa235c0584d85a88901f2b5e7fcb8d.webp)

### If the customer is not on your site

This is the recurring-charge case, and the one most integrations need to get right: the charge runs on
your billing schedule, so by definition the customer isn't present.

* Email the `redirect_url`, using `next_action` to pick the message.
* Don't re-drive the charge on a timer. Wait for `payment_token_updated`, then charge.
* If you retry on a schedule anyway, expect the same `422` every time until the customer acts.

![Re-qualification Flow](/_fern-img/02650e256c1a8faa9bbe8db8ec002615047209ef3b64f4edb9c2e62a9f7aae23.webp)

Most of these failures are avoidable. See
[Prevent failures before they happen](/guides/setup/api/subscriptions/subsequent-billing-periods#prevent-failures-before-they-happen)
for the monitoring job that catches expiring cards and LMNs before a charge breaks.

## When no webhook ever arrives

Provisioning a token can fail silently from your side: you call `create_payment_session` with
`tokenize: true`, the customer is redirected, and no `payment_token_updated` ever comes.

That means one of:

* The customer abandoned the health survey.
* The customer never entered card details.
* The customer didn't qualify for the items in their cart, so no LMN was issued.

**This isn't specific to subscriptions**—the same thing happens with any payment session where the
customer doesn't finish. Don't hold a subscription open indefinitely waiting for the webhook. Time it
out and prompt the customer to start over.

## Related guides

| Need                                         | Read this                                                                               |
| -------------------------------------------- | --------------------------------------------------------------------------------------- |
| Charge a token on your billing schedule      | [Recurring Charges](/guides/setup/api/subscriptions/subsequent-billing-periods)         |
| Let a customer change their card or items    | [Update a Subscription](/guides/setup/api/subscriptions/update-an-active-subscription)  |
| Monitor expirations and cancel subscriptions | [Partner Operations](/guides/setup/api/subscriptions/partner-administrative-operations) |
| Every payment session status                 | [Payment Lifecycle](/guides/setup/api/payment-sessions/payment-lifecycle)               |
| Webhook verification and retries             | [Webhooks](/guides/setup/api/resources/webhooks)                                        |
| Test the failure and recovery paths          | [Testing](/guides/setup/api/subscriptions/testing)                                      |