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

# Webhooks and fulfillment

> How to use the payment session webhook as the fulfillment boundary, and keep fulfillment idempotent across retries.

The `payment_session_complete` webhook is the fulfillment boundary for Truemed payments. Return URLs
help you show the right customer experience, but your backend should update and fulfill orders from
webhook statuses.

## What to listen for

Subscribe to [`payment_session_complete`](/api-reference/payment-sessions/payment-session-completed-webhook)
in the [Developer Dashboard](https://dev.truemed.com/developers/webhooks).

The webhook payload includes the fields your order system needs:

| Field              | Use it to                                                                           |
| ------------------ | ----------------------------------------------------------------------------------- |
| `payment_id`       | Match the webhook to the payment session `id` returned by `create_payment_session`. |
| `status`           | Decide whether to wait, fulfill, cancel, capture, or void.                          |
| `authorize_amount` | Confirm the amount authorized on the customer's card.                               |
| `capture_amount`   | Confirm the amount captured once funds are secured.                                 |
| `metadata`         | Rehydrate your internal checkout, cart, or order reference if you sent one.         |
| `order_items`      | Reconcile item-level fulfillment, refunds, or capture amounts.                      |

## Example payload

A `captured` event for an immediate-capture session. All amounts are integers in cents
(`12500` = \$125.00).

```json
{
  "payment_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "status": "captured",
  "created_at": "2026-01-15T09:30:00Z",
  "authorize_amount": 12500,
  "capture_amount": 12500,
  "captures": [
    { "id": "a17b4e02-6c39-4f8d-b2a5-1e9d3c7f0a64", "capture_amount": 12500, "captured_at": "2026-01-15T09:31:12Z" }
  ],
  "order_items": [
    {
      "item_id": "line_item_1",
      "name": "Recovery Bundle",
      "sku": "recovery-bundle",
      "price": 12500,
      "quantity": 1,
      "total": 12500,
      "total_refundable": 12500,
      "quantity_refundable": 1
    }
  ],
  "metadata": "cart_12345"
}
```

The `captures` array and `capture_amount` reflect partial captures—there is no separate
`partially_captured` status. For an `authorization` session, `capture_amount` is absent until you
capture, and `order_items` carry `total_capturable` / `quantity_capturable` instead of the
refundable fields. `payment_token` (`tm_token_...`) appears only if you created the session with
`tokenize: true` or a `payment_token`.

## Fulfillment rules

| Status       | Customer communication                                        | Fulfillment behavior                                   |
| ------------ | ------------------------------------------------------------- | ------------------------------------------------------ |
| `processing` | Tell the customer the order was placed and is being reviewed. | Do not fulfill yet.                                    |
| `captured`   | Confirm the order is paid.                                    | Fulfill the order.                                     |
| `rejected`   | Tell the customer the payment could not be completed.         | Cancel the order or ask for another payment method.    |
| `authorized` | Tell the customer the order was authorized.                   | Capture or void later; do not treat as captured funds. |

> **Warning**
>
> Do not fulfill from `success_url`. A customer can return to your site while the payment is still
> `processing`.

## Webhook handler checklist

1. Verify the request using the [webhooks guide](/guides/setup/api/resources/webhooks).
2. Find the internal order by `payment_id` or by the `metadata` you sent when creating the session.
3. Store the latest webhook `status` on the order.
4. Make fulfillment idempotent so webhook retries do not duplicate shipments, emails, or credits.
5. Return a `2xx` response after the event is stored or handled.

## Retry behavior

Truemed retries failed webhook deliveries with backoff for up to 7 days. Treat each webhook as
at-least-once delivery: your endpoint can receive the same status more than once.

Use your internal order state to make each action idempotent:

| Action                   | Idempotency check                                                 |
| ------------------------ | ----------------------------------------------------------------- |
| Mark order as processing | Safe to repeat if the order is already processing.                |
| Fulfill order            | Only run if the order has not already been fulfilled.             |
| Cancel order             | Only run if the order has not already been fulfilled or canceled. |
| Capture an authorization | Only run if the remaining authorized amount is still capturable.  |

## Related guides

| Need                                                                   | Read this                                                                                 |
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| First working payment flow                                             | [Accept Your First Payment](/guides/setup/api/payment-sessions/accept-your-first-payment) |
| Full status reference                                                  | [Payment Lifecycle](/guides/setup/api/payment-sessions/payment-lifecycle)                 |
| General webhook verification                                           | [Webhooks](/guides/setup/api/resources/webhooks)                                          |
| [Manual capture](/guides/overview/glossary#manual-capture) fulfillment | [Manual/Delayed Capture](/guides/setup/api/payment-sessions/manual-delayed-capture)       |