# Accept a bank transfer

Use the Checkout Sessions or Payment Intents API to accept bank transfer payments.

If your integration uses invoices, see [Send an invoice with bank transfer instructions](https://docs.stripe.com/invoicing/bank-transfer.md).

The first time you accept a bank transfer payment, Stripe generates a virtual bank account for the customer, which you can then share with them directly. All future bank transfer payments from this customer get sent to this bank account. In some countries, Stripe also provides you with a unique transfer reference number that your customer can include with each transfer to match the transfer against outstanding payments. Some countries have limits on the number of virtual bank account numbers that you can create for free.
![](https://b.stripecdn.com/docs-statics-srv/assets/without-invoices-diagram-1.a17fe04695ef532427f25a9e1276ee2e.svg)

Bank transfer payments overview

## Handling underpayments and overpayments

With bank transfer payments, it’s possible that the customer sends you more or less than the expected payment amount. If the customer sends too little, Stripe partially funds an open Payment Intent. Invoices won’t be partially funded and remain open until incoming funds cover the full invoice amount.

If the customer sends more than the expected amount, Stripe attempts to reconcile the incoming funds against an open payment and keep the remaining excess amount in the customer balance. Learn more about [how Stripe handles reconciliation](https://docs.stripe.com/payments/customer-balance/reconciliation.md).
![](https://b.stripecdn.com/docs-statics-srv/assets/without-invoices-diagram-2.464fe916d5822422144c8aea0f31ed45.svg)
![](https://b.stripecdn.com/docs-statics-srv/assets/without-invoices-diagram-3.b1992851a5f3492d14eaa35e336b0e9f.svg)

## Handling multiple open payments or invoices

You might have multiple open payments or invoices which can be paid with a bank transfer. In the default setup, Stripe attempts to [automatically reconcile](https://docs.stripe.com/payments/customer-balance/reconciliation.md) the bank transfer by using information like the transfer’s reference code or the amount transferred.

You can disable automatic reconciliation and [manually reconcile](https://docs.stripe.com/payments/customer-balance/reconciliation.md#cash-manual-reconciliation) payments and invoices yourself. You can override the automatic reconciliation behavior on a per-customer basis by setting [reconciliation mode](https://docs.stripe.com/api/customers/create.md#create_customer-cash_balance-settings-reconciliation_mode) to manual.

# Checkout


Bank transfer is a [single-use](https://docs.stripe.com/payments/payment-methods.md#usage) payment method for Checkout where customers pay with a bank transfer using payment instructions presented. When selecting to pay, the user is redirected to a hosted page which displays bank transfer instructions and the status of the transfer payment.

Bank transfer is also a *delayed notification payment method* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods), which means that funds aren’t immediately available after payment.

> Bank transfers aren’t available on Checkout Sessions that didn’t include an existing [Customer](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer) or [customer-configured Account](https://docs.stripe.com/api/checkout/sessions/create.md#create_checkout_session-customer_account) as part of the session creation request.

## Determine compatibility

**Supported business locations**: Europe (SEPA area), UK, JP, MX, US

**Supported currencies**: `eur, gbp, jpy, mxn, usd`

**Presentment currencies**: `eur, gbp, jpy, mxn, usd`

**Payment mode**: Yes

**Setup mode**: No

**Subscription mode**: No

A Checkout Session must satisfy all of the following conditions to support Bank Transfer payments:

- *Prices* (Prices define how much and how often to charge for products. This includes how much the product costs, what currency to use, and the interval if the price is for subscriptions) for all line items must be in the same currency. If you have line items in different currencies, create separate Checkout Sessions for each currency.

- You can only use one-time line items (Bank Transfer Checkout Sessions don’t support recurring *subscription* (A Subscription represents the product details associated with the plan that your customer subscribes to. Allows you to charge the customer on a recurring basis) plans).

## Accept a payment

> Build an integration to [accept a payment](https://docs.stripe.com/payments/accept-a-payment.md?integration=checkout) with Checkout before using this guide.

Use this guide to enable Bank Transfer.

### Create or retrieve a customer

You must associate an object that represents your customer to reconcile each bank transfer payment. If you have an existing customer, you can skip this step. Otherwise, create a new one.

> #### Use the Accounts v2 API to represent customers
> 
> The Accounts v2 API is generally available for Connect users, and in public preview for other Stripe users. If you’re part of the Accounts v2 preview, you need to specify a [preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) in your code.
> 
> To join the Accounts v2 preview, go to [Account previews and features](https://dashboard.stripe.com/settings/previews) in your Dashboard and enable **Reusable payment methods for Global Payouts**.
> 
> For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects.

Create a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/create.md#v2_create_accounts-configuration-customer) or [Customer](https://docs.stripe.com/api/customers/create.md) when your customer creates an account with your business, or when saving a payment method. Associate the object’s ID with your own internal representation of a customer.

Create a new customer or retrieve an existing one to associate with this payment.

#### Accounts v2

```curl
curl -X POST https://api.stripe.com/v2/core/accounts \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-08-26.preview" \
  --json '{
    "contact_email": "jenny.rosen@example.com",
    "display_name": "Jenny Rosen",
    "configuration": {
        "customer": {}
    },
    "include": [
        "configuration.customer"
    ]
  }'
```

#### Customers v1

```curl
curl https://api.stripe.com/v1/customers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "name=Jenny Rosen" \
  --data-urlencode "email=jenny.rosen@example.com"
```

### Enable Bank Transfer as a payment method

When creating a new [Checkout Session](https://docs.stripe.com/api/checkout/sessions.md), you need to:

1. Set `customer` or `customer_account`
2. [Enable bank transfers](https://dashboard.stripe.com/settings/payment_methods) in your Dashboard. Stripe automatically displays bank transfers to eligible customers using [dynamic payment methods](https://docs.stripe.com/payments/payment-methods/dynamic-payment-methods.md). If you currently specify `payment_method_types`, see the [migration guide](https://docs.stripe.com/payments/dashboard-payment-methods.md).
3. Make sure all your `line_items` use the same currency

#### Accounts v2

#### US

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer_account={{CUSTOMERACCOUNT_ID}}" \
  -d "line_items[0][price_data][currency]=usd" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=2000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=us_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

#### UK

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer_account={{CUSTOMERACCOUNT_ID}}" \
  -d "line_items[0][price_data][currency]=gbp" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=2000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=gb_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

#### EU

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer_account={{CUSTOMERACCOUNT_ID}}" \
  -d "line_items[0][price_data][currency]=eur" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=2000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=eu_bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][eu_bank_transfer][country]=FR" \
  --data-urlencode "success_url=https://example.com/success"
```

Set [payment_method_options[customer_balance][bank_transfer][eu_bank_transfer][country]](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-customer_balance-bank_transfer-eu_bank_account-country) to one of  to display the localized IBAN to the customer.

#### JP

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer_account={{CUSTOMERACCOUNT_ID}}" \
  -d "line_items[0][price_data][currency]=jpy" \
  -d "line_items[0][price_data][product_data][name]=Tシャツ" \
  -d "line_items[0][price_data][unit_amount]=19000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=jp_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

#### MX

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer_account={{CUSTOMERACCOUNT_ID}}" \
  -d "line_items[0][price_data][currency]=mxn" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=18000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=mx_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

#### Customers v1

#### US

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer={{CUSTOMER_ID}}" \
  -d "line_items[0][price_data][currency]=usd" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=2000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=us_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

#### UK

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer={{CUSTOMER_ID}}" \
  -d "line_items[0][price_data][currency]=gbp" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=2000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=gb_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

#### EU

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer={{CUSTOMER_ID}}" \
  -d "line_items[0][price_data][currency]=eur" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=2000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=eu_bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][eu_bank_transfer][country]=FR" \
  --data-urlencode "success_url=https://example.com/success"
```

Set [payment_method_options[customer_balance][bank_transfer][eu_bank_transfer][country]](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-customer_balance-bank_transfer-eu_bank_account-country) to one of  to display the localized IBAN to the customer.

#### JP

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer={{CUSTOMER_ID}}" \
  -d "line_items[0][price_data][currency]=jpy" \
  -d "line_items[0][price_data][product_data][name]=Tシャツ" \
  -d "line_items[0][price_data][unit_amount]=19000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=jp_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

#### MX

```curl
curl https://api.stripe.com/v1/checkout/sessions \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d "customer={{CUSTOMER_ID}}" \
  -d "line_items[0][price_data][currency]=mxn" \
  -d "line_items[0][price_data][product_data][name]=T-shirt" \
  -d "line_items[0][price_data][unit_amount]=18000" \
  -d "line_items[0][quantity]=1" \
  -d mode=payment \
  -d "payment_method_options[customer_balance][funding_type]=bank_transfer" \
  -d "payment_method_options[customer_balance][bank_transfer][type]=mx_bank_transfer" \
  --data-urlencode "success_url=https://example.com/success"
```

### Redirect to Stripe hosted bank transfer instructions page

> Unlike card payments, the customer isn’t always redirected to the [success_url](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-success_url) with bank transfer payment.

After *submit* (Submitting an order indicates that the customer intends to pay. Upon submission, the order can no longer be updated and is ready for payment) the Checkout form successfully,

- If the customer already has a balance high enough to cover the request amount, the payment immediately succeeds and the customer is redirected to the [success_url](https://docs.stripe.com/api/checkout/sessions/object.md#checkout_session_object-success_url).
- If the customer balance isn’t high enough to cover the request amount, the customer is redirected to the [hosted_instructions_url](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-display_bank_transfer_instructions-hosted_instructions_url). The page has the instructions to guide your customer through completing the transfer.

Stripe allows customization of customer-facing UIs on the [Branding Settings](https://dashboard.stripe.com/account/branding) page. The following brand settings can be applied to the hosted instructions page:

- **Icon**—your brand image and public business name
- **Brand color**—used as the background color

### Fulfill your orders

Because bank transfer is a *delayed notification payment method* (A payment method that can't immediately return payment status when a customer attempts a transaction (for example, ACH debits). Businesses commonly hold an order in a pending state until payment is successful with these payment methods), you need to use a method such as *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) to monitor the payment status and handle order *fulfillment* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected). Learn more about [setting up webhooks and fulfilling orders](https://docs.stripe.com/checkout/fulfillment.md).

The following events are sent when the payment status changes:

| Event Name                                                                                                                                   | Description                                                                                               | Next steps                                                 |
| -------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| [checkout.session.completed](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.completed)                             | The customer has successfully submitted the Checkout form and is redirected to `hosted_instructions_url`. | Wait for the customer to make the bank transfer.           |
| [checkout.session.async_payment_succeeded](https://docs.stripe.com/api/events/types.md#event_types-checkout.session.async_payment_succeeded) | The customer has successfully made the bank transfer. The `PaymentIntent` transitions to `succeeded`.     | Fulfill the goods or services that the customer purchased. |

## Optional: Send payment instruction emails

You can enable Bank Transfer payment instruction emails from the [Dashboard](https://dashboard.stripe.com/settings/emails). After you enable payment instruction emails, Stripe sends your customer an email when:

- A PaymentIntent is confirmed but the customer doesn’t have sufficient balance.
- The customer sends a bank transfer but doesn’t have sufficient funds to complete the pending payments.

A Bank Transfer payment instruction email contains the amount due, the bank information for transferring funds, and a link to the Stripe hosted instruction page.

> In a sandbox, payment instruction emails are only sent to email addresses linked to the Stripe account.

## Test your integration

You can test your integration by simulating an incoming bank transfer using the API, Dashboard, or a beta version of the Stripe CLI.

> #### Accounts v2 considerations
> 
> The Accounts v2 API is generally available for Connect users, and in public preview for other Stripe users. If you’re part of the [Accounts v2 preview](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md), you need to [specify a preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) in your code.
> 
> To simulate an incoming bank transfer for a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-configuration-customer), use the Test Helpers endpoint with the `Account` ID as the path parameter instead of the `Customer` ID, for example `v1/test_helpers/customers/acct_xxxxx/fund_cash_balance`.

#### Dashboard

To simulate a bank transfer using the Dashboard in a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes), go to the customer’s page in the Dashboard. Under **Payment methods**, click **Add** and select **Fund cash balance (test only)**.

#### API

To simulate a bank transfer using the API:

#### US

```bash
curl https://api.stripe.com/v1/test_helpers/customers/{{CUSTOMER_ID}}/fund_cash_balance \
  -X POST \
  -u <<YOUR_SECRET_KEY>>: \
  -d "reference"="REF-4242" \
  -d "amount"="1000" \
  -d "currency"="usd"
```

#### UK

```bash
curl https://api.stripe.com/v1/test_helpers/customers/{{CUSTOMER_ID}}/fund_cash_balance \
  -X POST \
  -u <<YOUR_SECRET_KEY>>: \
  -d "reference"="REF-4242" \
  -d "amount"="1000" \
  -d "currency"="gbp"
```

#### EU

```bash
curl https://api.stripe.com/v1/test_helpers/customers/{{CUSTOMER_ID}}/fund_cash_balance \
  -X POST \
  -u <<YOUR_SECRET_KEY>>: \
  -d "reference"="REF-4242" \
  -d "amount"="1000" \
  -d "currency"="eur"
```

#### JP

```bash
curl https://api.stripe.com/v1/test_helpers/customers/{{CUSTOMER_ID}}/fund_cash_balance \
  -X POST \
  -u <<YOUR_SECRET_KEY>>: \
  -d "amount"="1000" \
  -d "currency"="jpy"
```

#### MX

```bash
curl https://api.stripe.com/v1/test_helpers/customers/{{CUSTOMER_ID}}/fund_cash_balance \
  -X POST \
  -u <<YOUR_SECRET_KEY>>: \
  -d "reference"="123456" \
  -d "amount"="1000" \
  -d "currency"="mxn"
```

#### Stripe CLI

To simulate a bank transfer with the Stripe CLI:

1. [Install the Stripe CLI](https://docs.stripe.com/cli.md).

2. Log in to the CLI using the same account you logged in to the Stripe Dashboard with.

   ```bash
   stripe login
   ```

3. Simulate an incoming bank transfer for an existing customer.

   #### US

   ```bash
   stripe test_helpers customers fund_cash_balance "{{CUSTOMER_ID}}" \
     --amount=1099 \
     --reference=DVGBG97TZ6ZV \
     --currency=usd
   ```

   The `reference` parameter is optional and simulates the value that the customer filled out for the bank transfer’s reference field.

   #### UK

   ```bash
   stripe test_helpers customers fund_cash_balance "{{CUSTOMER_ID}}" \
     --amount=1099 \
     --reference=DVGBG97TZ6ZV \
     --currency=gbp
   ```

   The `reference` parameter is optional and simulates the value that the customer filled out for the bank transfer’s reference field.

   #### EU

   ```bash
   stripe test_helpers customers fund_cash_balance "{{CUSTOMER_ID}}" \
     --amount=1099 \
     --reference=DVGBG97TZ6ZV \
     --currency=eur
   ```

   The `reference` parameter is optional and simulates the value that the customer filled out for the bank transfer’s reference field.

   #### JP

   ```bash
   stripe test_helpers customers fund_cash_balance "{{CUSTOMER_ID}}" \
     --amount=1000 \
     --currency=jpy
   ```

   #### MX

   ```bash
   stripe test_helpers customers fund_cash_balance "{{CUSTOMER_ID}}" \
     --amount=1099 \
     --reference=123456 \
     --currency=mxn
   ```

   The `reference` parameter is optional and simulates the value that the customer filled out for the bank transfer’s reference field.

## See also

- [Checkout fulfillment](https://docs.stripe.com/checkout/fulfillment.md)
- [Customizing Checkout](https://docs.stripe.com/payments/checkout/customization.md)

