> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paywithsoap.com/llms.txt
> Use this file to discover all available pages before exploring further.

# checkout.hold

> Webhook event triggered when a withdrawal occurs to prevent double spending.

## Payload Structure

```typescript theme={null}
interface WebhookEvent {
  event_id: string;
  data: {
    id: string; // id of the checkout you originally created
    line_items: Array<{
      product_id: string;
      quantity: number;
      total_amount_cents: number;
      product_name: string;
      product_url: string;
      product_price_cents: number;
      sku: string;
    }>;
    line_items_total_amount_cents: number | null;
    type: "withdrawal"; // only sent on withdrawals
    charge: {
      id: string;
      amount_cents: number;
      transaction_type: "debit";
      status: "held";
      from_status: "created";
      failure_code: string | null;
      failure_message: string | null;
    };
    customer: {
      id: string;
    };
    subscription: {
      id: string;
      interval: "day" | "week" | "month" | "year";
      interval_count: number;
      line_items: Array<{
        product_id: string;
        sku: string;
        product_name: string;
        product_url: string;
        quantity: number;
        price_cents: number;
        total_amount_cents: number;
      }>;
      line_items_total_amount_cents: number | null;
    } | null; // null for non-subscription checkouts
  };
  type: "checkout.hold";
}
```

## Example Payload

Withdrawals are driven by `balance_amount_cents` or `fixed_amount_cents` rather than products, so `line_items` is empty and `line_items_total_amount_cents` is `null` on this event. See [`checkout.succeeded`](/api-reference/api-v1/webhooks/checkout-succeeded) for a payload with populated line items.

```json theme={null}
{
  "event_id": "ev_tDaWu5aTVa2kbvDjGe55rxZpaMEmVFWB",
  "data": {
    "id": "chk_SUuEdtXWK3wmui6c4guq5xdLke21uvRt",
    "line_items": [],
    "line_items_total_amount_cents": null,
    "type": "withdrawal",
    "charge": {
      "id": "ch_96rVNn94oKSRDZ69fQsUQbaigaice9Tx",
      "amount_cents": 100,
      "transaction_type": "debit",
      "status": "held",
      "from_status": "created",
      "failure_code": null,
      "failure_message": null
    },
    "customer": {
      "id": "cus_vi57KegYgcRqcGHqip8q6UZiqtrwMT870"
    },
    "subscription": null
  },
  "type": "checkout.hold"
}
```

## You must respond with status

2xx: if the customer has available funds

Not 2xx: if the customer has insufficient funds

## Updating Your Internal Ledger

You can choose to debit the customer's balance immediately or wait until you receive the `checkout.succeeded` event.

It is recommended to debit immediately and then skip the `checkout.succeeded` event.
