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

# Cancel Payment Session

POST https://dev-api.truemed.com/payments/v1/payment_session/{business_id}/cancel

The `cancel` API exists so that merchant partners can manage cart lifecycles.
In an ideal world, the customer experience would roughly be outlined by:

The customer browses your store and adds items to their shopping cart.

The customer clicks the "Checkout with Truemed" button to begin the payment process.

The partner calls `create_payment_session`, and an inventory lock is placed on the items in the cart to ensure they can be fulfilled when payment is captured.

The customer completes the survey and enters payment information in the Truemed interface.

The merchant listens for the Partner webhook callback and fulfills the inventory locked above.

## Deviations from the Happy Path

In the flow above, there are a few steps the customer can take that would void the
existing session.

The customer could:

* **Navigate away from Truemed during the survey, and modify their cart.** This
  dictates a new idempotency key (e.g.: a new `payment_session`). As part of clean up
  and to ensure the customer can't navigate back to the now outdated survey link, the
  old payment session must be canceled.
* **Take too long to complete the survey and finalize payment.** The merchant may wish
  to cancel the `payment_session` and release the lock on inventory as it appears the
  customer is no longer interested in making the purchase.

## Customer Experience for Canceled Sessions

If this API is used to cancel a pending session, the customer will be shown a page
indicating that the checkout session has timed out and a link will be provided to
"Go back to checkout" which will return them to the `failure_url` provided in
`create_payment_session`.

The page presented by the `failure_url` should be generic and display a relevant
message asking the customer to checkout again if it has been too long.

"Too long" is defined by our merchant partners depending on their inventory management.
We recommend 48-72 hours as customers will sometimes move funds into their HSA prior to
completing checkout.

# API Overview

The `cancel_payment_session` endpoint can be called after `create_payment_session` has
been called, but before the customer has entered their payment information, for either
`kind=authorization` or `kind=one_time_payment`.

The failure or success status is communicated to the partner via a webhook
`payment_session_complete` as before.

## Request Notes

There are no required fields for the request body, you simply call the endpoint with
the `payment_session_id` in the URL. The cancel API can be called repeatedly without an
idempotency key and the same result will be returned.

**Important** - you will only get a single callback queued on successful cancelation
(albeit, invoked multiple times in the case of failures) as outlined in Partner webhook,
even if you call the cancel endpoint multiple times.

## Response Notes

### Success Case

HTTP Status: `200`

Note: `order_items.sku` - the partner's SKU for the item. The value of this field will
be the SKU provided by the partner in the [`create_payment_session`](/api-reference/payment-sessions/create-payment-session)
request. If the partner does not provide a SKU value for an item on creation of the payment, this
key will not be present.

### Failure Case

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:
  * `InvalidPaymentId` - the `payment_session_id` does not exist.
  * `ServerError` - There was an internal server error. Requests can be retried.
  * `SessionCaptured` - The session has already been captured via a call to
    `/payment_session/{payment_session_id}/capture` and can no longer be canceled. In
    this case, to return funds to the customer, you'll need to issue a refund.
  * `SessionAuthorized` - The session has already been authorized. The user has
    completed the survey and entered their credit card information. In this case, the
    session should be voided via the Void Session API, and the customer should be
    informed that their order has been canceled.
* `message` - Details on the above conditions.

Reference: https://developers.truemed.com/api-reference/payment-sessions/cancel-payment-session

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

### Path parameters

- `business_id` (string, required) — The payment session ID to cancel.

## Response

### 200

Successful response

- `order_items` (list of PaymentSessionOrderItem, required) — A list of order items.
- `status` (enum, required) — The status field of the payment_session. When the payment session is pending, it will be marked as `canceled`.
  - Allowed values: `pending`, `canceled`, `processing`, `rejected`, `authorized`, `authorization_expired`, `authorization_voided`, `partially_captured`, `captured`
- `metadata` (string, optional, nullable) — Optional field echoed back if present in the call to create_payment_session.

## Errors

### 400 Bad Request Error

Bad Request

- `error` (enum, required)
  - Allowed values: `SessionAuthorized`, `SessionCaptured`, `TotalAmountInvalid`, `ValidationError`
- `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

### PaymentSessionOrderItem

- `amount_details` (PaymentSessionAmountDetails, required) — Optional itemized discounts and charges for this item.
- `name` (string, required) — The name of the item.
- `quantity` (integer, required) — The number of this item in the cart.
- `sku` (string, required) — The SKU (Stock Keeping Unit) for this item.
- `amount` (integer, optional, nullable) — The total amount for this line item in cents. Either amount or price must be provided.
- `item_id` (string, optional, nullable) — A unique identifier for this order item within the payment.
- `price` (integer, optional, nullable) — The unit price in cents for the item. Either amount or price must be provided.

### PaymentSessionAmountDetails

- `additional_charges_details` (list of PaymentSessionAmountDetail, optional, nullable) — An array of individual additional charge line items with names and amounts.
- `discounts_details` (list of PaymentSessionAmountDetail, optional, nullable) — An array of individual discount line items with names and amounts.
- `total_additional_charges` (integer, optional, nullable) — The total amount of additional charges (e.g., shipping, tax), in cents.
- `total_discounts` (integer, optional, nullable) — The total amount of discounts applied, in cents.

### PaymentSessionAmountDetail

- `amount` (integer, required) — The amount in cents for this discount or charge.
- `name` (string, required) — The name or description of the discount or charge.

## Examples

**Response**

```json
{
  "order_items": [
    {
      "amount_details": {
        "additional_charges_details": [
          {
            "amount": 1,
            "name": "string"
          }
        ],
        "discounts_details": [
          {
            "amount": 1,
            "name": "string"
          }
        ],
        "total_additional_charges": 1,
        "total_discounts": 1
      },
      "name": "string",
      "quantity": 1,
      "sku": "string",
      "amount": 1,
      "item_id": "string",
      "price": 1
    }
  ],
  "status": "pending",
  "metadata": "string"
}
```

**SDK Code**

```python
import requests

url = "https://dev-api.truemed.com/payments/v1/payment_session/business_id/cancel"

headers = {"x-truemed-api-key": "<apiKey>"}

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

print(response.json())
```

```javascript
const url = 'https://dev-api.truemed.com/payments/v1/payment_session/business_id/cancel';
const options = {method: 'POST', headers: {'x-truemed-api-key': '<apiKey>'}};

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