> 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.

# Create Payment Token

POST https://dev-api.truemed.com/api/v1/payment_tokens/create
Content-Type: application/json

Payment tokens can be created outside of the
[`create_payment_session`](/api-reference/payment-sessions/create-payment-session) API call. This is most
commonly used to support existing subscription customers, allowing them to move their subscriptions
to their HSA/FSA. Use [`create_payment_session`](/api-reference/payment-sessions/create-payment-session)
with `tokenize=True` to create a subscription as part of a checkout flow, such as the first order in a subscription,
or free trials.

For early access, contact your Truemed sales engineer.

# Overview

This endpoint supports creating a `payment_token` outside of the
[`create_payment_session`](/api-reference/payment-sessions/create-payment-session) flow,
and is commonly used to support giving the option to existing subscribers to pay with their
HSA/FSA. This endpoint can also be used to "store a payment method with Truemed" inside of a
user dashboard. Subscription free-trials are possible with this endpoint, though we recommend
using [`create_payment_session`](/api-reference/payment-sessions/create-payment-session) for trials
for consistency with the standard checkout experience.

This endpoint returns **the ID of a new `provision_token_request`, NOT a new `payment_token`**.
The `payment_token` itself will be available upon receipt of the
[`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook with the corresponding
`provision_token_request_id`. In order to support backfills in the case of unforeseen downtime
(a webhook that goes unacknowledged, or is missed), you can also query the status of the
`provision_token_request` directly as outlined in our
[`retrieve_provision_token_request`](/api-reference/payment-tokens/retrieve-payment-token-provision-request) docs.

Partners only receive valid `payment_tokens` via the
[`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook. A payment token can't be issued
until the user successfully completes the tele-health survey and/or enters payment information.
A callback is used to indicate the customer has completed token setup with Truemed.

The diagram below outlines the customer flow when using this endpoint:

The merchant partner calls `create_payment_token` and receives a `provision_token_request_id` and a `redirect_url`. Persist the `provision_token_request_id` on your customer record before redirecting the customer — it is what links the `payment_token_updated` webhook back to them.

The customer is redirected to the `redirect_url` and completes the tele-health survey and enters payment information.

The customer is redirected to the `success_url` provided by the merchant during the initial call to `create_payment_token`.

Truemed issues a [`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook including the newly provisioned `payment_token`. Link it to existing data in your backend using the `provision_token_request_id` you persisted before the redirect, or the `metadata` you sent on the `create_payment_token` call — the webhook echoes both. It does not carry the customer's email or name.

```mermaid
sequenceDiagram
    participant User
    participant Partner
    participant Truemed

    User->>Partner: Add HSA/FSA card option
    Partner->>Truemed: create_payment_token request
    Truemed-->>Partner: redirect_url response
    Partner-->>User: Redirect to redirect_url
    User->>Truemed: Complete eligibility survey
    Note over User: User eligible for HSA/FSA
    Truemed-->>User: Show payment method form
    User->>Truemed: Enter HSA/FSA card details
    Note over User: Payment method stored
    Truemed->>Partner: payment_token_callback webhook
    Truemed-->>User: Redirect to success_url
```

The webhook/callback is invoked at the same time the user is being redirected to the
`success_url` - we don't guarantee that it will be called before the redirect.

**The customer must be in the flow** when calling this endpoint, typically from within a
subscription management dashboard.

**Primary Use Cases for this Endpoint:**

* **Supporting existing customers**
  * You may have existing subscriptions customers that want to move their subscription over to
    their HSA/FSA card. Providing a "use your HSA/FSA via Truemed" button within a subscription
    management dashboard powered by this endpoint allows you to do that.
* **Store payment method with Truemed**
  * Allow customers to add an HSA to their account for future use
* **Free-trial support (non preferred)**
  * Allowing customers to qualify for a given subscription and store their payment info for
    future use.
  * ⚠️ **We recommend using `create_payment_session` with `tokenize=True` for free trials** as
    outlined in the main subscription guide to reflect the fact that the customer is "checking
    out", though at no-cost.

All subscription related fields here are to enhance the customer experience, you'll need your
own subscription management system.

## Request Notes

* **success\_url** (Required): Where to redirect the user to after the customer successfully
  completes the tele-health survey and their payment method(s) have been stored.
  * This is often used to display a confirmation screen, or similar
* **failure\_url** (Required): When the user opts to not complete the tele-health survey or selects
  "cancel" during the process, or when the user is ineligible to spend HSA/FSA funds on the items
  in the request.
  * We attempt to recover from incorrect CVV, or other card detail errors by prompting the user
    for retry
* **customer\_state** (Optional): The 2-letter ISO 3166-2:US code for a region, without the `US-`
  prefix. For example, California should be provided as `CA` and Rhode Island as `RI`.
  * If `customer_state` is provided, the state of residence question in the health survey will be
    prefilled with the full state name that corresponds to the ISO code.
* **metadata** (Optional): Will be echoed back in the
  [`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook and detail endpoint if present.
  * **Important**: This must be a string. If you want to include JSON, encode it as a string.
  * **Important**: DO NOT INCLUDE sensitive information in this field.
* **use\_iframe** (Optional): Optional query parameter that can be used to modify the response's
  `redirect_url` so it can be used and communicated with in an iframe.

## iFrame Support

If `use_iframe` is set to `true`, `redirect_url` will be iframe-compatible. When the customer
finishes, the iframe posts one completion message to your page:

```json
{ "success": true, "redirectUrl": "https://example.com/success" }
```

`redirectUrl` echoes the `success_url` or `failure_url` from your request, matching `success`. See
the [Embedded Checkout guide](/guides/setup/api/payment-sessions/i-frame-payment-session) for how to
render the flow, validate the message's origin, and handle it.

## Response Notes

### Success Case

**HTTP Status: 200:**

* **provision\_token\_request\_id**: A UUID that represents this creation request.
  * This ID is returned along with the provisioned `payment_token` in the
    [`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook.
  * You can query the status of this request using the
    [`retrieve_provision_token_request`](/api-reference/payment-tokens/retrieve-payment-token-provision-request) endpoint.
* **redirect\_url**: Contains a URI through which the customer can complete the `payment_token`.

### Bad Request

**HTTP Status: 400**

If a field is missing or the request otherwise can't be processed, we'll return a 400 with the
following fields:

* **error**: Can be one of:
  * `MissingField`: One of the required fields is not present in the request
  * `IdempotencyViolation`: An `idempotency_key` was reused with different request parameters or
    the customer email specified in the request already has a payment token provisioned. Check to
    see if a [`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook was already received for
    this customer. To update, use the [`update_payment_token`](/api-reference/payment-tokens/update-payment-token)
    endpoint.
  * `WaitingForVerification`: If the lmn verification process has started, you cannot attempt to
    call this endpoint again for the same customer email. If you receive this error, please wait
    for the [`payment_token_updated`](/api-reference/payment-tokens/payment-token-updated-webhook) webhook and then use the
    [`update_payment_token`](/api-reference/payment-tokens/update-payment-token) endpoint.
  * `ServerError`: There was an internal server error.
    * Requests can be retried as long as the `idempotency_key` is the same.
  * `ValidationError`: There was an issue with the request. Check the `message` field for the
    exact issue.
* **message**: Detailed string explaining the reason for the failure.

Reference: https://developers.truemed.com/api-reference/payment-tokens/create-payment-token

## Authentication

- `x-truemed-api-key` header (required) — Sales channel API key for merchant server-to-server authentication

## Servers

- `https://dev-api.truemed.com` (Development server, default)
- `https://api.truemed.com` (Production server)

## Request

### Body (application/json)

This endpoint expects a CreatePaymentTokenRequest.

- `customer_email` (string, required) — The customer's email
- `customer_name` (string, required) — The customer's full name
- `failure_url` (string, required) — Where Truemed sends the customer when they opt out of HSA/FSA, do not qualify in the survey, or cancel a payment method update. In an iframe, Truemed returns this URL in the completion message instead of navigating.
- `idempotency_key` (string, required) — A unique ID that allows safely retrying the request without performing the same operation twice
- `success_url` (string, required) — Where Truemed should redirect the customer after successfully completing checkout
- `customer_state` (string, optional, nullable) — Set this to pre-fill the answer to the State of Residence question in the health survey. The 2-letter ISO 3166-2:US code for a region, without the US- prefix
- `metadata` (string, optional, nullable) — A JSON string containing any custom key-value pairs. This string will be returned in the payment_session_complete webhook if provided
- `order_items` (list of PaymentTokenOrderItemSku, optional, nullable) — The initial list of items for this subscription. Required unless this sales channel is configured for full-catalog qualification, in which case it may be omitted.
- `use_iframe` (boolean, optional, default: false) — Set to true to render the survey and card entry inline on your own page instead of redirecting the customer. The returned redirect_url becomes an iframe src, and the result arrives as a postMessage rather than a redirect. See the Embedded checkout (iFrame) guide.

## Response

### 200

Successful response

- `provision_token_request_id` (string, required) — A UUID that represents this creation request
- `redirect_url` (string, required) — Contains a URI through which the customer can complete the payment token provisioning

## Errors

### 400 Bad Request Error

Bad Request

- `error` (enum, required)
  - Allowed values: `FeatureNotEnabled`, `IdempotencyViolation`, `InvalidRequestParameter`, `TotalAmountInvalid`, `ValidationError`, `WaitingForVerification`
- `message` (string, required)

### 404 Not Found Error

Not Found

- `error` (enum, required)
  - Allowed values: `NotFound`
- `message` (string, required)

### 405 Method Not Allowed Error

Method Not Allowed

- `error` (enum, required)
  - Allowed values: `MethodNotAllowed`
- `message` (string, required)

### 500 Internal Server Error

Internal Server Error

- `error` (enum, required)
  - Allowed values: `ServerError`
- `message` (string, required)

### 501 Not Implemented Error

Not Implemented

- `error` (enum, required)
  - Allowed values: `NotImplemented`
- `message` (string, required)

## Types

### PaymentTokenOrderItemSku

- `sku` (string, required) — The SKU of the item as configured in your catalog

## Examples

**Request**

```json
{
  "customer_email": "string",
  "customer_name": "string",
  "failure_url": "string",
  "idempotency_key": "string",
  "success_url": "string"
}
```

**Response**

```json
{
  "provision_token_request_id": "string",
  "redirect_url": "string"
}
```

**SDK Code**

```python
import requests

url = "https://dev-api.truemed.com/api/v1/payment_tokens/create"

payload = {
    "customer_email": "string",
    "customer_name": "string",
    "failure_url": "string",
    "idempotency_key": "string",
    "success_url": "string"
}
headers = {
    "x-truemed-api-key": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://dev-api.truemed.com/api/v1/payment_tokens/create';
const options = {
  method: 'POST',
  headers: {'x-truemed-api-key': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"customer_email":"string","customer_name":"string","failure_url":"string","idempotency_key":"string","success_url":"string"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```