Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
APIs & SDKsHelp
Overview
About Stripe payments
Upgrade your integration
Payments analytics
Online payments
OverviewFind your use caseUse Managed Payments
Use Payment Links
Use a prebuilt checkout page
Build a custom integration with Elements
Build an in-app integration
Payment methods
Add payment methods
    Overview
    Payment method integration options
    Manage default payment methods in the Dashboard
    Payment method types
    Cards
    Pay with Stripe balance
    Stablecoin payments
    Bank debits
      ACH Direct Debit
        Accept a payment
        Save bank details
        Migrating from the Charges API
        Migrating from another processor
        Blocked bank accounts
        SEC codes
      Bacs Direct Debit
      Pre-authorized debit in Canada
      Australia BECS Direct Debit
      New Zealand BECS Direct Debit
      SEPA Direct Debit
    Bank redirects
    Bank transfers
    Credit transfers (Sources)
    Buy now, pay later
    Real-time payments
    Vouchers
    Wallets
    Enable local payment methods by country
    Custom payment methods
Manage payment methods
Faster checkout with Link
Payment interfaces
Payment Links
Checkout
Web Elements
In-app Payments
Payment scenarios
Handle multiple currencies
Custom payment flows
Flexible acquiring
Orchestration
In-person payments
Terminal
Beyond payments
Incorporate your company
Crypto
Agentic commerce
Financial Connections
Climate
Understand fraud
Radar fraud protection
Manage disputes
Verify identities
United States
English (United States)
HomePaymentsAdd payment methodsBank debitsACH Direct Debit

Accept an ACH Direct Debit payment

Build a custom payment form or use Stripe Checkout to accept payments with ACH Direct Debit.

Use the Payment Element to embed a custom Stripe payment form in your website or application and offer payment methods to customers. For advanced configurations and customizations, refer to the Accept a Payment integration guide.

Before you use ACH direct debit in your Payment Element integration, learn about the following ACH direct debit-specific considerations:

  • Learn about mandate collection.
  • Choose how you verify bank accounts.

Mandate collection

When accepting ACH payments, you need to understand mandates.

Unless you use a direct API integration, Stripe handles mandate collection and storage for your business to make sure that regulatory requirements are met. When a customer accepts the mandate during the payment process, Stripe automatically stores this information and it becomes available for you to access from your Dashboard.

Set up Stripe
Server-side

To get started, create a Stripe account.

Use our official libraries for access to the Stripe API from your application:

Collect payment details
Client-side

Use the Payment Element to collect payment details on the client. The Payment Element is a prebuilt UI component that simplifies collecting payment details for various payment methods.

The Payment Element contains an iframe that securely sends payment information to Stripe over an HTTPS connection. Avoid placing the Payment Element within another iframe because some payment methods require redirecting to another page for payment confirmation.

The checkout page address must start with https:// rather than http:// for your integration to work. You can test your integration without using HTTPS, but remember to enable it when you’re ready to accept live payments.

Set up Stripe.js

The Payment Element is automatically available as a feature of Stripe.js. Include the Stripe.js script on your checkout page by adding it to the head of your HTML file. Always load Stripe.js directly from js.stripe.com to remain PCI compliant. Don’t include the script in a bundle or host a copy of it yourself.

Create an instance of Stripe with the following JavaScript on your checkout page:

Add the Payment Element to your checkout page

To add the Payment Element to your checkout page, create an empty DOM node (container) with a unique ID in your payment form:

You can manage payment methods from the Dashboard or manually list the payment methods you want to be available when you create the Payment Element.

You can customize the Payment Element to match the design of your site by passing the appearance object into options when creating the Elements provider.

Collect addresses

By default, the Payment Element only collects the necessary billing address details. Some behavior, such as calculating tax or entering shipping details, requires your customer’s full address. You can:

  • Use the Address Element to take advantage of autocomplete and localization features to collect your customer’s full address. This helps ensure the most accurate tax calculation.
  • Collect address details using your own custom form.

Verify bank accounts

For information on Financial Connections fees, see pricing details.

Bank account verification uses automatic verification to collect payment information through Financial Connections by default. No changes are required to use it. You can change your verification_method to instant to make all users verify their bank accounts with Financial Connections. See the Financial Connections docs to learn how to configure Financial Connections and access additional account data to optimize your ACH integration. For example, you can use Financial Connections to check an account’s balance before initiating the ACH payment.

Create a PaymentIntent
Server-side

Run custom business logic immediately before payment confirmation

Navigate to step 5 in the finalize payments guide to run your custom business logic immediately before payment confirmation. Otherwise, follow the steps below for a simpler integration, which uses stripe.confirmPayment on the client to both confirm the payment and handle any next actions.

When the customer submits your payment form, use a PaymentIntent to facilitate the confirmation and payment process. Create a PaymentIntent on your server with an amount and currency. To prevent malicious customers from choosing their own prices, always decide how much to charge on the server-side (a trusted environment) and not the client.

Included on a PaymentIntent is a client secret. Return this value to your client for Stripe.js to use to securely complete the payment process.

Submit the payment to Stripe
Client-side

Use stripe.confirmPayment to complete the payment using details from the Payment Element.

Provide a return_url to this function to indicate where Stripe redirects the user after they complete the payment. Your user might be initially redirected to an intermediate site, such as a bank authorization page, before being redirected to the return_url. Card payments immediately redirect to the return_url when a payment is successful.

If you don’t want to redirect for card payments after payment completion, you can set redirect to if_required. This only redirects customers that check out with redirect-based payment methods.

OptionalHandle post-payment events

Stripe sends a payment_intent.succeeded event when the payment completes. Use the Dashboard, a custom webhook, or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow.

Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events also helps you accept more payment methods in the future. Learn about the differences between all supported payment methods.

  • Handle events manually in the Dashboard

    Use the Dashboard to View your test payments in the Dashboard, send email receipts, handle payouts, or retry failed payments.

  • Build a custom webhook

    Build a custom webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.

  • Integrate a prebuilt app

    Handle common business events, such as automation or marketing and sales, by integrating a partner application.

Test your integration

Learn how to test scenarios with instant verifications using Financial Connections.

Send transaction emails in a sandbox

After you collect the bank account details and accept a mandate, send the mandate confirmation and microdeposit verification emails in a sandbox.

If your domain is {domain} and your username is {username}, use the the following email format to send test transaction emails: {username}+test_email@{domain}.

For example, if your domain is example.com and your username is info, use the format info+test_email@example.com for testing ACH Direct Debit payments. This format ensures that emails route correctly. If you don’t include the +test_email suffix, we won’t send the email.

Common mistake

You need to activate your Stripe account before you can trigger these emails while testing.

Test account numbers

Stripe provides several test account numbers and corresponding tokens you can use to make sure your integration for manually-entered bank accounts is ready for production.

Account numberTokenRouting numberBehavior
000123456789pm_usBankAccount_success110000000The payment succeeds.
000111111113pm_usBankAccount_accountClosed110000000The payment fails because the account is closed.
000000004954pm_usBankAccount_riskLevelHighest110000000The payment is blocked by Radar due to a high risk of fraud.
000111111116pm_usBankAccount_noAccount110000000The payment fails because no account is found.
000222222227pm_usBankAccount_insufficientFunds110000000The payment fails due to insufficient funds.
000333333335pm_usBankAccount_debitNotAuthorized110000000The payment fails because debits aren’t authorized.
000444444440pm_usBankAccount_invalidCurrency110000000The payment fails due to invalid currency.
000666666661pm_usBankAccount_failMicrodeposits110000000The payment fails to send microdeposits.
000555555559pm_usBankAccount_dispute110000000The payment triggers a dispute.
000000000009pm_usBankAccount_processing110000000The payment stays in processing indefinitely. Useful for testing PaymentIntent cancellation.
000777777771pm_usBankAccount_weeklyLimitExceeded110000000The payment fails due to payment amount causing the account to exceed its weekly payment volume limit.

Before test transactions can complete, you need to verify all test accounts that automatically succeed or fail the payment. To do so, use the test microdeposit amounts or descriptor codes below.

Test microdeposit amounts and descriptor codes

To mimic different scenarios, use these microdeposit amounts or 0.01 descriptor code values.

Microdeposit values0.01 descriptor code valuesScenario
32 and 45SM11AASimulates verifying the account.
10 and 11SM33CCSimulates exceeding the number of allowed verification attempts.
40 and 41SM44DDSimulates a microdeposit timeout.

Test settlement behavior

Test transactions settle instantly and are added to your available test balance. This behavior differs from livemode, where transactions can take multiple days to settle in your available balance.

Error codes

The following table details common error codes and recommended actions:

Error codeRecommended action
payment_intent_invalid_currencyEnter a supported currency.
missing_required_parameterCheck the error message for more information about the required parameter.
payment_intent_payment_attempt_failedThis code can appear in the last_payment_error.code field of a PaymentIntent. Check the error message for a detailed failure reason and suggestion on error handling.
payment_intent_authentication_failureThis code can appear in the last_payment_error.code field of a PaymentIntent. Check the error message for a detailed failure reason and suggestion on error handling. This error occurs when you manually trigger a failure when testing your integration.
payment_intent_redirect_confirmation_without_return_urlProvide a return_url when confirming a PaymentIntent.

OptionalAccess data on a Financial Connections bank account

For more information on Financial Connections fees, see pricing details.

You can only access Financial Connections data if you request additional data permissions when you create your Payment Intent.

After your customer successfully completes the Stripe Financial Connections authentication flow, the us_bank_account PaymentMethod returned includes a financial_connections_account ID that points to a Financial Connections Account. Use this ID to access account data.

Common mistake

Bank accounts that your customers link through manual entry and microdeposits don’t have a financial_connections_account ID on the payment method.

To determine the Financial Connections account ID, retrieve the Payment Intent and expand the payment_intent.payment_method attribute:

OptionalResolve disputes
Server-side

Customers can generally dispute an ACH Direct Debit payment through their bank for up to 60 calendar days after a debit on a personal account, or up to 2 business days for a business account. In rare instances, a customer might be able to successfully dispute a debit payment outside these standard dispute timelines.

When a customer disputes a payment, Stripe sends a charge.dispute.closed webhook event, and the PaymentMethod authorization is revoked.

In rare situations, Stripe might receive an ACH failure from the bank after a PaymentIntent has transitioned to succeeded. If this happens, Stripe creates a dispute with a reason of:

  • insufficient_funds
  • incorrect_account_details
  • bank_can't_process

Stripe charges a failure fee in this situation.

Future payments reusing this PaymentMethod return the following error:

This error contains a PaymentIntent in the requires_confirmation state. To continue with the payment, you must:

  1. Resolve the dispute with the customer to ensure future payments will not be disputed.
  2. Confirm authorization from your customer again.

To confirm authorization for the payment, you can collect mandate acknowledgement from your customer online with Stripe.js or confirm authorization with your customer offline using the Stripe API.

Caution

If a customer disputes more than one payment from the same bank account, Stripe blocks their bank account. Contact Stripe Support for further resolution.

OptionalPayment Reference

The payment reference number is a bank-generated value that allows the bank account owner to use their bank to locate funds. When the payment succeeds, Stripe provides the payment reference number in the Dashboard and inside the Charge object.

Charge StatePayment Reference Value
PendingUnavailable
FailedUnavailable
SucceededAvailable (for example, 091000015001234)

In addition, when you receive the charge.succeeded webhook, view the content of payment_method_details to locate the payment_reference.

The following example event shows the rendering of a successful ACH payment with a payment reference number.

View the contents of the destination_details to locate the refund reference associated with the refunded ACH payments.

The following example event shows the rendering of a successful ACH refund with a refund reference number. Learn more about refunds.

OptionalConfigure customer debit date
Server-side

You can control the date that Stripe debits a customer’s bank account using the target date. The target date must be at least three days in the future and no more than 15 days from the current date.

The target date schedules money to leave the customer’s account on the target date. You can cancel a PaymentIntent created with a target date up to three business days before the configured date.

Target dates that meet one of the following criteria delay the debit until next available business day:

  • Target date falls on a weekend, a bank holiday, or other non-business day.
  • Target date is fewer than three business days in the future.

This parameter operates on a best-effort basis. Each customer’s bank might process debits on different dates, depending on local bank holidays or other reasons.

Caution

You can’t set the verification method to microdeposits when using a target date, as the verification process could take longer than the target date, causing payments to arrive later than expected.

Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc