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

# ACH via Stripe

> Let customers securely make payments using ACH via Stripe on your website or mobile application.

## Get started with ACH via Stripe

### Before you begin

If this is your first payment method, make sure to follow the [Get started guide](https://primer.io/docs/get-started/overview.md) to begin processing payments with Primer.

> [!NOTE]
>
> ACH via Stripe needs to be enabled for your account. Contact your account manager or Primer Support before you offer this payment method.

### Configure in the Dashboard

1. **Add Stripe to your Dashboard**\
   Go to the [Integrations](https://dashboard.primer.io/integrations) section of the Dashboard and look for `Stripe`.\
   Follow the instructions to connect your Stripe account to your Primer Dashboard. Make sure `ACH` is selected for your Stripe connection.

2. **Activate ACH on the Checkout**\
   Go to the [Checkout](https://dashboard.primer.io/checkout) section of the Dashboard and activate the ACH payment method.

3. **Configure a Workflow to process payments made with Stripe ACH**\
   Go to [Workflows](https://dashboard.primer.io/workflows-v1), and ensure there is a workflow with the **Authorize payment** action configured to process APM payments.

### Prepare the client session

ACH via Stripe leverages the following parameters to process a payment.

Pass them when creating the client session.

| Parameter Name | Required | Description |
| - | - | - |
| [currencyCode](https://primer.io/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session.md#body-currency-code) | ✓ | 3-letter currency code in ISO 4217 format. For Stripe ACH only USD is supported. |
| [amount](https://primer.io/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session.md#body-amount) or [order](https://primer.io/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session.md#body-order.) | ✓ | The client session must have a non-zero amount. Set `amount`, or let it be calculated from `order.lineItems` and `order.shipping.amount`. |
| [customerId](https://primer.io/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session.md#body-customer-id) | ✓ | Identifies the customer. The payment fails without it. |
| [customer](https://primer.io/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session.md#body-customer) ↳ billingAddress | ✓ | The account holder's billing address. `addressLine1`, `city`, `state`, `postalCode` and `countryCode` are required. Stripe rejects the payment if any of them is missing. |
| [metadata](https://primer.io/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session.md#body-metadata) | ✓ | The shopper's device info, used to record the mandate: `metadata.deviceInfo.ipAddress` and `metadata.deviceInfo.userAgent`. Stripe rejects the payment without them. |
| [paymentMethod](https://primer.io/docs/api-reference/v2.4/api-reference/client-session-api/create-a-client-session.md#request.body.paymentMethod) | | Only needed to vault the bank account. See [Vault the bank account](#vault-the-bank-account). |

```json theme={"dark"}
{
  "currencyCode": "USD",
  "customerId": "customer-123",
  "order": {
    "countryCode": "US",
    "lineItems": [{ "itemId": "item-1", "description": "Item", "amount": 1000, "quantity": 1 }]
  },
  "customer": {
    "billingAddress": {
      "addressLine1": "354 Oyster Point Blvd",
      "city": "South San Francisco",
      "state": "CA",
      "postalCode": "94080",
      "countryCode": "US"
    }
  },
  "metadata": {
    "deviceInfo": {
      "ipAddress": "203.0.113.10",
      "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ..."
    }
  }
}
```

> [!WARNING]
>
> If Stripe rejects the payment after the shopper accepts the mandate, for example because `metadata.deviceInfo` or part of the billing address is missing, the payment stays `PENDING` and the shopper sees a success screen. Test your client session in sandbox and check that payments settle.

### Vault the bank account

To save the bank account for future payments, set `vaultOnAgreement` when creating the client session. The bank account is vaulted when the shopper accepts the mandate.

```json theme={"dark"}
"paymentMethod": {
  "vaultOnAgreement": true,
  "paymentType": "FIRST_PAYMENT"
}
```

`paymentType: "FIRST_PAYMENT"` is optional. Set it if you plan to charge the saved bank account without the shopper present, for example for subscriptions.

Paying with a saved bank account doesn't open Stripe's modal or ask the shopper to accept the mandate again.

### Payment status

ACH payments take several business days to settle. After the shopper accepts the mandate, the payment is `PENDING` and the checkout shows a success screen. The payment moves to `SETTLED` or `FAILED` when Stripe reports the outcome, for example if the account has insufficient funds. Use [payment status webhooks](https://primer.io/docs/api-reference/get-started/configure-webhooks.md) to get the final status.

## Add ACH via Stripe into your website or mobile app

When using [Primer Checkout](https://primer.io/docs/sdk/primer-checkout-web/sdk-reference-overview.md), set [`stripe.publishableKey` and `stripe.mandateData`](https://primer.io/docs/sdk/primer-checkout-web/sdk-options-reference#stripe-options) in the SDK options. ACH is not shown without them.

> [card] [Drop-in UI](https://primer.io/docs/connections/payment-methods/ach/stripe-dropin)
>
> Use our customizable drop-in UI to quickly add payment methods to your checkout.

> [card] [Headless Checkout](https://primer.io/docs/connections/payment-methods/ach/stripe-headless)
>
> Have the freedom to build your own UI using our headless checkout.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.