How To: Implement ACH Payments
Implementing ACH Payments
Implementing ACH payments depends largely on if youβre settling on-chain versus off-chain. Merchants who are settling on-chain to a contract may need to pass a transaction to the CoinflowPurchase component or to our ach checkout endpoint. Passing a transaction is not always required but it will allow Coinflow to run a transaction to complete the userβs purchase if thereβs on-chain logic to run once the funds have settled.
How It Works
- The merchant submits a transaction to Coinflow.
- The user initiates an ACH purchase.
- Coinflow initiates the ACH transfer and monitors the payment until it is received (typically 3 business days).
- Once the transfer is completed, Coinflow executes the on-chain transaction you provided using our USDC payer, fulfilling the purchase on behalf of the user.
How to Implement ACH via UI
The example below shows how to implement ACH using our React SDK. If needed, Coinflow also supports other frameworks and integrations.
- Generate a session key for the payer.
Request
1 curl --request GET \ 2 --url https://api-sandbox.coinflow.cash/api/auth/session-key \ 3 --header 'Authorization: YOUR_API_KEY' \ 4 --header 'accept: application/json' \ 5 --header 'x-coinflow-auth-user-id: user123' Response1 { 2 "key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcklkIjoidXNlcjEyMyIsIm1lcmNoYW50SWQiOiJ0ZXN0dGVzdCIsImlhdCI6MTc0MTgwNTk3MywiZXhwIjoxNzQxODkyMzczfQ.mau9HPQXZQ040-bkQ0tMg57N9IVTbEQZMtV4O9kgkjg" 3 }
-
π§ Session keys are valid for 30 minutes and must be refreshed afterwards.
- Tokenize the checkout parameters.
This encrypts the checkout parameters so bad actors cannot tamper with the checkout args.
1 curl --request POST \ 2 --url https://api-sandbox.coinflow.cash/api/checkout/jwt-token \ 3 --header 'Authorization: YOUR_API_KEY' \ 4 --header 'accept: application/json' \ 5 --header 'content-type: application/json' \ 6 --data ' 7 { 8 "webhookInfo": { 9 "example": "{\"description\":\"asdF\"}" 10 }, 11 "subtotal": { 12 "currency": "USD", 13 "cents": 500 14 }, 15 "email": "iamapayer@gmail.com", 16 "blockchain": "solana", 17 "settlementType": "USDC" 18 } 19 '
{ "checkoutJwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoi456C4oKW26LXguCjgOKYgueAleiAnN2j5IGM4LGn46CD5oOb4LCF44CQ7Iqy4YCF6KSz4KCI7KaczLDGkOuhgNqE44iA7rWwybDgp6DHgOCumeawgOSQqeSio0LgsJ3njaPmoYXItOa1ku6AjOyFieKmlOiTke67iOWCguWxiOmroOSNuO65suOou-mUremsreWZqOSytueBrOeBpOGgqOSZiOaxrOKhiOiRpOmitOGxiOG7vuuYnOeDmOeBjOChhuCglOuTiOunuOyYlOawmOqXtuujvuSyuuuSnOy7mOqglOSZqOahpOeVrOiwmOShsOKglOaphuGhjOuXjeiRhuaStOSZjFx1ZGQxY-K7k-uQlFx1ZDg2NO-kqOmUq-qHg-6Xqu-pmuySoeGxhuSVhueDquqYiOmHlOShmuGzmOKgnOaikeSuuFx1ZGExOOebvuKisuuguOiSqdOD4LCy4Y6B7IqZ5LO045Cb6qeM4o2D6Iyc7KOR4ZKt4ZyC6I2h6oCy44SMzZPSheyHmeixmOOyhsyE5IWC7oCo5LCO46uJ0rfvg6Dos6jMmOWqguiMi-qSjOu4nOqdkuivsuerpeWljOGmlemCi-6ZmeyFsOuItOCouuKDpeqCoeuAnOiImeGciuyNqeaIiuSxseWkrtek64S4XHVkODRi4YiN6LqnwqDngLjojJrhnIzsrYLpm43rqI3jjKbotoztmJjigYLlkoTihILoloXpi5HtkafijJHolZTogYLosoHnlZvmmonohYDnhbHooLTrjIXcr-mWou2GsOSwsuGchOm6g-qrmOGBmeieoOyfoemhiOWBsOGSqeWohOyzkO6rm-yhmeOQrOaAq-STqeGnpuSxteCoquWSgO6JkuqwnuGBmtys6Yax4rGQ5JS46rSH6ICF74iAIiwibWVyY2hhbnRJZCI6InRlc3R0ZXN0IiwiaWRlbXBvdGVuY3lLZXkiOiJJSzVlZWE3YzI3LWEyMjgtNDcyMC1iYTVkLWI1ZDA0ZDUzMzA3MCIsInN1YnRvdGFsIjp7ImN1cnJlbmN5IjoiVVNEIiwiY2VudHMiOjUwMH0sImlhdCI6MTc0Mjg1NTY3OCwiZXhwIjoxNzQyOTQyMDc4fQ.2dGfWnazfyHaz_uEWKM9RU-jh-tXUSMPFZJdNvmMPwo" }
- Implement the Coinflow Checkout Component.
1 <CoinflowPurchase 2 sessionKey={'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcklkIjoidXNlcjEyMyIsIm1lcmNoYW50SWQiOiJ0ZXN0dGVzdCIsImlhdCI6MTc0MTgwNTk3MywiZXhwIjoxNzQxODkyMzczfQ.mau9HPQXZQ040-bkQ0tMg57N9IVTbEQZMtV4O9kgkjg'} 3 merchantId={'testtest'} // Replace with your merchantId 4 env={'sandbox'} 5 onSuccess={(...args) => { 6 console.log('Purchase Success', args); // Redirect the user 7 }} 8 settlementType={SettlementType.USDC} 9 subtotal={{cents: 300, currency: Currency.USD}} // Amount purchase is in (exclude prop if user is to choose a custom amount) 10 email={'user@email.com'} // User's email address 11 jwtToken = {'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoi456C4oKW26LXguCjgOKYgueAleiAnN2j5IGM4LGn46CD5oOb4LCF44CQ7Iqy4YCF6KSz4KCI7KaczLDGkOuhgNqE44iA7rWwybDgp6DHgOCumeawgOSQqeSio0LgsJ3njaPmoYXItOa1ku6AjOyFieKmlOiTke67iOWCguWxiOmroOSNuO65suOou-mUremsreWZqOSytueBrOeBpOGgqOSZiOaxrOKhiOiRpOmitOGxiOG7vuuYnOeDmOeBjOChhuCglOuTiOunuOyYlOawmOqXtuujvuSyuuuSnOy7mOqglOSZqOahpOeVrOiwmOShsOKglOaphuGhjOuXjeiRhuaStOSZjFx1ZGQxY-K7k-uQlFx1ZDg2NO-kqOmUq-qHg-6Xqu-pmuySoeGxhuSVhueDquqYiOmHlOShmuGzmOKgnOaikeSuuFx1ZGExOOebvuKisuuguOiSqdOD4LCy4Y6B7IqZ5LO045Cb6qeM4o2D6Iyc7KOR4ZKt4ZyC6I2h6oCy44SMzZPSheyHmeixmOOyhsyE5IWC7oCo5LCO46uJ0rfvg6Dos6jMmOWqguiMi-qSjOu4nOqdkuivsuerpeWljOGmlemCi-6ZmeyFsOuItOCouuKDpeqCoeuAnOiImeGciuyNqeaIiuSxseWkrtek64S4XHVkODRi4YiN6LqnwqDngLjojJrhnIzsrYLpm43rqI3jjKbotoztmJjigYLlkoTihILoloXpi5HtkafijJHolZTogYLosoHnlZvmmonohYDnhbHooLTrjIXcr-mWou2GsOSwsuGchOm6g-qrmOGBmeieoOyfoemhiOWBsOGSqeWohOyzkO6rm-yhmeOQrOaAq-STqeGnpuSxteCoquWSgO6JkuqwnuGBmtys6Yax4rGQ5JS46rSH6ICF74iAIiwibWVyY2hhbnRJZCI6InRlc3R0ZXN0IiwiaWRlbXBvdGVuY3lLZXkiOiJJSzVlZWE3YzI3LWEyMjgtNDcyMC1iYTVkLWI1ZDA0ZDUzMzA3MCIsInN1YnRvdGFsIjp7ImN1cnJlbmN5IjoiVVNEIiwiY2VudHMiOjUwMH0sImlhdCI6MTc0Mjg1NTY3OCwiZXhwIjoxNzQyOTQyMDc4fQ.2dGfWnazfyHaz_uEWKM9RU-jh-tXUSMPFZJdNvmMPwo'} 12 />
π§ Merchants who are settling on-chain may need to make adjustments to the
transactionprop passed to Coinflow. Jump to section: βOn-Chain ACH Transactionsβ for more details.
How to Implement ACH via API
- Tokenize the payment data
Request
1 curl --request POST \ 2 --url https://api-sandbox.coinflow.cash/api/checkout/jwt-token \ 3 --header 'Authorization: YOUR_API_KEY' \ 4 --header 'accept: application/json' \ 5 --header 'content-type: application/json' \ 6 --data ' 7 { 8 "subtotal": { 9 "currency": "USD", 10 "cents": 500 11 }, 12 "email": "payer@gmail.com", 13 "blockchain": "solana", // Change according to the chain youre on. Merchants settling to Coinflow wallet do not need to pass blockchain 14 "settlementType": "USDC" 15 } 16 ' Response1 { 2 "checkoutJwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoi456C4oKW26LXgsuA2IHpoI3og4bEsOKGgseA5piB5Lew7ICj5IiQ4Y6A5ZiB4aKT5ZK144CJ6Z2n4KuO4YCB6oSQ6IG25qCB46CE74CA7oCF7YKGXCLlpKXmhoLhiq7gs5jlgrLshY7hsYLrlJvln4XpqprjoajhipDgu4nkrrLki5brhKDkiprqpazolIruk6XmlpLmsKzioYjkoqTvoYjRsOmQiOKylOWZluGjrOKghOuguOSjlOKEmOShsOGhhua4mOGZmOqQiOCjuOqoruWilOqToeaZluiRluqTlO2RmOKxtOGitOuTmO-RiOmzruC1qem5mO-grOGRpOeApOChqFx1ZGU5NOmSme-FquyEoMK-5ICAIiwibWVyY2hhbnRJZCI6Im1lbGxvIiwiaWRlbXBvdGVuY3lLZXkiOiJJS2ZjODY5ZmY4LTk1MTgtNDA0ZS1hYTI5LWEzNzk3ZjZiZjcwOSIsInN1YnRvdGFsIjp7ImN1cnJlbmN5IjoiVVNEIiwiY2VudHMiOjUwMH0sImlhdCI6MTc1MjY4NzY3NiwiZXhwIjoxNzUyNjg5NDc2fQ.Jv7VLntabr8id94FXgseErN_wpzsjDRmEFMmWdVqwes" 3 } - Get the total purchase amount including all fees.
Request
1 curl --request POST \ 2 --url https://api-sandbox.coinflow.cash/api/checkout/totals/mello \ 3 --header 'accept: application/json' \ 4 --header 'content-type: application/json' \ 5 --header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcklkIjoidXNlcjEyMyIsIm1lcmNoYW50SWQiOiJtZWxsbyIsImlhdCI6MTc1MjY4NzQ5NCwiZXhwIjoxNzUyNzczODk0fQ.4_azA_nfReFeCaRE4K3PCqtBqYqSKEBqKL-Qw-8E4d4' \ 6 --data ' 7 { 8 "subtotal": { 9 "currency": "USD", 10 "cents": 500 11 }, 12 "jwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoi456C4oKW26LXgsuA2IHpoI3og4bEsOKGgseA5piB5Lew7ICj5IiQ4Y6A5ZiB4aKT5ZK144CJ6Z2n4KuO4YCB6oSQ6IG25qCB46CE74CA7oCF7YKGXCLlpKXmhoLhiq7gs5jlgrLshY7hsYLrlJvln4XpqprjoajhipDgu4nkrrLki5brhKDkiprqpazolIruk6XmlpLmsKzioYjkoqTvoYjRsOmQiOKylOWZluGjrOKghOuguOSjlOKEmOShsOGhhua4mOGZmOqQiOCjuOqoruWilOqToeaZluiRluqTlO2RmOKxtOGitOuTmO-RiOmzruC1qem5mO-grOGRpOeApOChqFx1ZGU5NOmSme-FquyEoMK-5ICAIiwibWVyY2hhbnRJZCI6Im1lbGxvIiwiaWRlbXBvdGVuY3lLZXkiOiJJS2ZjODY5ZmY4LTk1MTgtNDA0ZS1hYTI5LWEzNzk3ZjZiZjcwOSIsInN1YnRvdGFsIjp7ImN1cnJlbmN5IjoiVVNEIiwiY2VudHMiOjUwMH0sImlhdCI6MTc1MjY4NzY3NiwiZXhwIjoxNzUyNjg5NDc2fQ.Jv7VLntabr8id94FXgseErN_wpzsjDRmEFMmWdVqwes" // JWT Token from step 1 13 } 14 ' Response{ "card": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidCreditCardFees": { "cents": 25, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "merchantPaidChargebackProtectionFees": { "cents": 0, "currency": "USD" }, "settlement": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidCreditCardFees": { "cents": 25, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "merchantPaidChargebackProtectionFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 1, "basis": { "currency": "USD", "cents": 500 } }, "ach": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 100, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 600, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "settlement": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 100, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 600, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 1, "basis": { "currency": "USD", "cents": 500 } }, "fasterPayments": { "subtotal": { "cents": 373, "currency": "GBP" }, "creditCardFees": { "cents": 200, "currency": "GBP" }, "chargebackProtectionFees": { "cents": 0, "currency": "GBP" }, "gasFees": { "cents": 0, "currency": "GBP" }, "total": { "cents": 573, "currency": "GBP" }, "merchantPaidGasFees": { "cents": 0, "currency": "GBP" }, "settlement": { "subtotal": { "cents": 500, "currency": "USD" }, "creditCardFees": { "cents": 269, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 769, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 0.744658, "basis": { "currency": "USD", "cents": 500 } }, "sepa": { "subtotal": { "cents": 430, "currency": "EUR" }, "creditCardFees": { "cents": 200, "currency": "EUR" }, "chargebackProtectionFees": { "cents": 0, "currency": "EUR" }, "gasFees": { "cents": 0, "currency": "EUR" }, "total": { "cents": 630, "currency": "EUR" }, "merchantPaidGasFees": { "cents": 0, "currency": "EUR" }, "settlement": { "subtotal": { "cents": 500, "currency": "USD" }, "creditCardFees": { "cents": 233, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 733, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 0.858423, "basis": { "currency": "USD", "cents": 500 } }, "pix": { "subtotal": { "cents": 2775, "currency": "BRL" }, "creditCardFees": { "cents": 31, "currency": "BRL" }, "chargebackProtectionFees": { "cents": 0, "currency": "BRL" }, "gasFees": { "cents": 0, "currency": "BRL" }, "total": { "cents": 2806, "currency": "BRL" }, "settlement": { "subtotal": { "cents": 500, "currency": "USD" }, "creditCardFees": { "cents": 6, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 506, "currency": "USD" } }, "exchangeRate": 5.5487, "basis": { "currency": "USD", "cents": 500 } }, "usdc": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "settlement": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 1, "basis": { "currency": "USD", "cents": 500 } }, "googlePay": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidCreditCardFees": { "cents": 25, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "merchantPaidChargebackProtectionFees": { "cents": 0, "currency": "USD" }, "settlement": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidCreditCardFees": { "cents": 25, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "merchantPaidChargebackProtectionFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 1, "basis": { "currency": "USD", "cents": 500 } }, "applePay": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidCreditCardFees": { "cents": 25, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "merchantPaidChargebackProtectionFees": { "cents": 0, "currency": "USD" }, "settlement": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidCreditCardFees": { "cents": 25, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "merchantPaidChargebackProtectionFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 1, "basis": { "currency": "USD", "cents": 500 } }, "credits": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "settlement": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 1, "basis": { "currency": "USD", "cents": 500 } }, "crypto": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" }, "settlement": { "subtotal": { "currency": "USD", "cents": 500 }, "creditCardFees": { "cents": 0, "currency": "USD" }, "chargebackProtectionFees": { "cents": 0, "currency": "USD" }, "gasFees": { "cents": 0, "currency": "USD" }, "total": { "cents": 500, "currency": "USD" }, "merchantPaidGasFees": { "cents": 0, "currency": "USD" } }, "exchangeRate": 1, "basis": { "currency": "USD", "cents": 500 } } } - Enable a customer to add a bank account.
curl --request POST \ --url https://api-sandbox.coinflow.cash/api/customer/v2/bankAccount \ --header 'Authorization: YOUR_API_KEY' \ --header 'content-type: application/json' \ --header 'x-coinflow-auth-user-id: user123' \ --data ' { "type": "checking", "email": "payer@gmail.com", "alias": "My Checking Account", "routingNumber": "0123456789", "account_number": "09876554321", "firstName": "Dwayne", "lastName": "Johnson", "address1": "201 E Randolph St", "city": "Chicago", "state": "IL", "zip": "60601" } ' - Get the customerβs tokenized bank account.
Request
1 curl --request GET \ 2 --url https://api-sandbox.coinflow.cash/api/customer/v2 \ 3 --header 'accept: application/json' \ 4 --header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcklkIjoidXNlcjEyMyIsIm1lcmNoYW50SWQiOiJtZWxsbyIsImlhdCI6MTc1MjY4NzQ5NCwiZXhwIjoxNzUyNzczODk0fQ.4_azA_nfReFeCaRE4K3PCqtBqYqSKEBqKL-Qw-8E4d4' Response{ "customer": { "_id": "684c5779677bd46e4455f085", "customerId": "user123", "blockchain": "user", "email": "payer@gmail.com", "availability": { "status": "Functional", "reason": "Initial", "editor": "system", "updatedAt": "2025-06-13T16:53:13.194Z" }, "chargebackProtectionEnabled": true, "merchant": "6840bca9c7cb21ee5baaae76", "failedAttemptSetting": "Standard", "verificationSetting": "Enforced", "exempt3DS": false, "createdAt": "2025-06-13T16:53:13.196Z", "__v": 0, "bankAccounts": [ { "alias": "My Checking Account", "token": "27ed7e14-076e-4c7f-8e65-fa321acce2b9", "routingNumber": "0123456789", "last4": "4321", "accountHash": "843d87649f2396062dd192243b367c30bd38e23a", "rtpEligible": true, "reference": "684c5779677bd46e4455f096" } ], "cards": [], "sepas": [], "fasterPayments": [] } } - Send an ACH Checkout
Request
1 curl --request POST \ 2 --url https://api-sandbox.coinflow.cash/api/checkout/ach/mello \ 3 --header 'accept: application/json' \ 4 --header 'content-type: application/json' \ 5 --header 'x-coinflow-auth-session-key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21lcklkIjoidXNlcjEyMyIsIm1lcmNoYW50SWQiOiJtZWxsbyIsImlhdCI6MTc1MjY4NzQ5NCwiZXhwIjoxNzUyNzczODk0fQ.4_azA_nfReFeCaRE4K3PCqtBqYqSKEBqKL-Qw-8E4d4' \ 6 --data ' 7 { 8 "subtotal": { 9 "cents": 500 10 }, 11 "jwtToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoi456C4oKW26LXgsuA2IHpoI3og4bEsOKGgseA5piB5Lew7ICj5IiQ4Y6A5ZiB4aKT5ZK144CJ6Z2n4KuO4YCB6oSQ6IG25qCB46CE74CA7oCF7YKGXCLlpKXmhoLhiq7gs5jlgrLshY7hsYLrlJvln4XpqprjoajhipDgu4nkrrLki5brhKDkiprqpazolIruk6XmlpLmsKzioYjkoqTvoYjRsOmQiOKylOWZluGjrOKghOuguOSjlOKEmOShsOGhhua4mOGZmOqQiOCjuOqoruWilOqToeaZluiRluqTlO2RmOKxtOGitOuTmO-RiOmzruC1qem5mO-grOGRpOeApOChqFx1ZGU5NOmSme-FquyEoMK-5ICAIiwibWVyY2hhbnRJZCI6Im1lbGxvIiwiaWRlbXBvdGVuY3lLZXkiOiJJS2ZjODY5ZmY4LTk1MTgtNDA0ZS1hYTI5LWEzNzk3ZjZiZjcwOSIsInN1YnRvdGFsIjp7ImN1cnJlbmN5IjoiVVNEIiwiY2VudHMiOjUwMH0sImlhdCI6MTc1MjY4NzY3NiwiZXhwIjoxNzUyNjg5NDc2fQ.Jv7VLntabr8id94FXgseErN_wpzsjDRmEFMmWdVqwes", // JWT from calling Get checkout JWT Token 12 "token": "27ed7e14-076e-4c7f-8e65-fa321acce2b9" // Tokenized bank account from calling Get Customer 13 } 14 ' Response{ "paymentId": "138fd1c7-60da-415b-a993-b13dbb92fe52" }
On-Chain ACH Transactions
When Do ACH Payments Settle for On-Chain Transactions?
To prevent fraud, Coinflow does not finalize credits, USDC, or bank transfers until the ACH payment has fully settled. Due to the delayed settlement of ACH payments, merchants using on-chain settlements must configure their smart contracts to handle separate wallets for initiating and receiving payments. This setup allows Coinflow to finalize the transaction on-chain after the ACH payment has settled.
Transactions on Solana
Solana transactions specify all accounts that are read from or written to during the transaction. For on-chain settlements, replace the userβs wallet (or the wallet making the USDC payment) in your transaction instructions with the placeholder key 22222222222222222222222222222222222222222222. Similarly, replace the USDC payerβs token account with the placeholder key 33333333333333333333333333333333333333333333.
For example, if your standard transaction instruction looks like this:
1 const transferIx = createTransferInstruction( 2 getTokenAddressSync(usersWallet, USDC_MINT), // spender token account 3 destinationTokenAccount, // destination token account 4 usersWallet, // Owner of spender token account 5 1 // amount 6 );
Modify it as follows for on-chain ACH settlement:
1 const transferIx = createTransferInstruction( 2 new PublicKey('33333333333333333333333333333333333333333333'), // spender token account 3 destinationTokenAccount, // destination token account 4 new PublicKey('22222222222222222222222222222222222222222222'), // Owner of spender token account 5 1 // amount 6 );
Coinflow will dynamically replace these placeholders with the appropriate signer and the signerβs token account, enabling the secure payment of USDC on behalf of the user.
π If you support both card and ACH payments, add the placeholders, and when you call redeem transaction, Coinflow will automatically replace the placeholders with the users wallet and their token account.
Transactions on EVM
Evm transactions inherently includes a have a msg.sender and a from field. Our system will automatically set that to our payer.

