Create ACH Payment
curl --request POST \
--url https://api.example.com/payments \
--header 'Content-Type: application/json' \
--data '
{
"data": {},
"data.requestId": "<string>",
"data.type": "<string>",
"data.attributes": {},
"data.attributes.paymentType": "<string>",
"data.attributes.merchantId": "<string>",
"data.attributes.miscData": "<string>",
"data.attributes.StandardEntryClassCode": "<string>",
"data.attributes.bank": {
"data.attributes.bank.bankName": "<string>",
"data.attributes.bank.accountType": "<string>",
"data.attributes.bank.accountName": "<string>",
"data.attributes.bank.accountNumber": "<string>",
"data.attributes.bank.routingNumber": "<string>"
},
"data.attributes.transaction": {
"data.attributes.transaction.amount": "<string>",
"data.attributes.transaction.currency": "<string>",
"data.attributes.transaction.invoice": "<string>"
}
}
'import requests
url = "https://api.example.com/payments"
payload = {
"data": {},
"data.requestId": "<string>",
"data.type": "<string>",
"data.attributes": {},
"data.attributes.paymentType": "<string>",
"data.attributes.merchantId": "<string>",
"data.attributes.miscData": "<string>",
"data.attributes.StandardEntryClassCode": "<string>",
"data.attributes.bank": {
"data.attributes.bank.bankName": "<string>",
"data.attributes.bank.accountType": "<string>",
"data.attributes.bank.accountName": "<string>",
"data.attributes.bank.accountNumber": "<string>",
"data.attributes.bank.routingNumber": "<string>"
},
"data.attributes.transaction": {
"data.attributes.transaction.amount": "<string>",
"data.attributes.transaction.currency": "<string>",
"data.attributes.transaction.invoice": "<string>"
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
data: {},
'data.requestId': '<string>',
'data.type': '<string>',
'data.attributes': {},
'data.attributes.paymentType': '<string>',
'data.attributes.merchantId': '<string>',
'data.attributes.miscData': '<string>',
'data.attributes.StandardEntryClassCode': '<string>',
'data.attributes.bank': {
'data.attributes.bank.bankName': '<string>',
'data.attributes.bank.accountType': '<string>',
'data.attributes.bank.accountName': '<string>',
'data.attributes.bank.accountNumber': '<string>',
'data.attributes.bank.routingNumber': '<string>'
},
'data.attributes.transaction': {
'data.attributes.transaction.amount': '<string>',
'data.attributes.transaction.currency': '<string>',
'data.attributes.transaction.invoice': '<string>'
}
})
};
fetch('https://api.example.com/payments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/payments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
],
'data.requestId' => '<string>',
'data.type' => '<string>',
'data.attributes' => [
],
'data.attributes.paymentType' => '<string>',
'data.attributes.merchantId' => '<string>',
'data.attributes.miscData' => '<string>',
'data.attributes.StandardEntryClassCode' => '<string>',
'data.attributes.bank' => [
'data.attributes.bank.bankName' => '<string>',
'data.attributes.bank.accountType' => '<string>',
'data.attributes.bank.accountName' => '<string>',
'data.attributes.bank.accountNumber' => '<string>',
'data.attributes.bank.routingNumber' => '<string>'
],
'data.attributes.transaction' => [
'data.attributes.transaction.amount' => '<string>',
'data.attributes.transaction.currency' => '<string>',
'data.attributes.transaction.invoice' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/payments"
payload := strings.NewReader("{\n \"data\": {},\n \"data.requestId\": \"<string>\",\n \"data.type\": \"<string>\",\n \"data.attributes\": {},\n \"data.attributes.paymentType\": \"<string>\",\n \"data.attributes.merchantId\": \"<string>\",\n \"data.attributes.miscData\": \"<string>\",\n \"data.attributes.StandardEntryClassCode\": \"<string>\",\n \"data.attributes.bank\": {\n \"data.attributes.bank.bankName\": \"<string>\",\n \"data.attributes.bank.accountType\": \"<string>\",\n \"data.attributes.bank.accountName\": \"<string>\",\n \"data.attributes.bank.accountNumber\": \"<string>\",\n \"data.attributes.bank.routingNumber\": \"<string>\"\n },\n \"data.attributes.transaction\": {\n \"data.attributes.transaction.amount\": \"<string>\",\n \"data.attributes.transaction.currency\": \"<string>\",\n \"data.attributes.transaction.invoice\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/payments")
.header("Content-Type", "application/json")
.body("{\n \"data\": {},\n \"data.requestId\": \"<string>\",\n \"data.type\": \"<string>\",\n \"data.attributes\": {},\n \"data.attributes.paymentType\": \"<string>\",\n \"data.attributes.merchantId\": \"<string>\",\n \"data.attributes.miscData\": \"<string>\",\n \"data.attributes.StandardEntryClassCode\": \"<string>\",\n \"data.attributes.bank\": {\n \"data.attributes.bank.bankName\": \"<string>\",\n \"data.attributes.bank.accountType\": \"<string>\",\n \"data.attributes.bank.accountName\": \"<string>\",\n \"data.attributes.bank.accountNumber\": \"<string>\",\n \"data.attributes.bank.routingNumber\": \"<string>\"\n },\n \"data.attributes.transaction\": {\n \"data.attributes.transaction.amount\": \"<string>\",\n \"data.attributes.transaction.currency\": \"<string>\",\n \"data.attributes.transaction.invoice\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/payments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": {},\n \"data.requestId\": \"<string>\",\n \"data.type\": \"<string>\",\n \"data.attributes\": {},\n \"data.attributes.paymentType\": \"<string>\",\n \"data.attributes.merchantId\": \"<string>\",\n \"data.attributes.miscData\": \"<string>\",\n \"data.attributes.StandardEntryClassCode\": \"<string>\",\n \"data.attributes.bank\": {\n \"data.attributes.bank.bankName\": \"<string>\",\n \"data.attributes.bank.accountType\": \"<string>\",\n \"data.attributes.bank.accountName\": \"<string>\",\n \"data.attributes.bank.accountNumber\": \"<string>\",\n \"data.attributes.bank.routingNumber\": \"<string>\"\n },\n \"data.attributes.transaction\": {\n \"data.attributes.transaction.amount\": \"<string>\",\n \"data.attributes.transaction.currency\": \"<string>\",\n \"data.attributes.transaction.invoice\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Invalid routing number",
"source": {
"pointer": "/data/attributes/bank/routingNumber"
}
}
]
}
{
"errors": [
{
"status": "401",
"title": "Unauthorized",
"detail": "Invalid or expired app token"
}
]
}
{
"errors": [
{
"status": "422",
"title": "Unprocessable Entity",
"detail": "Payment processing failed - insufficient funds"
}
]
}
Payments
Create ACH Payment
Process an ACH (Automated Clearing House) bank transfer payment
POST
/
payments
Create ACH Payment
curl --request POST \
--url https://api.example.com/payments \
--header 'Content-Type: application/json' \
--data '
{
"data": {},
"data.requestId": "<string>",
"data.type": "<string>",
"data.attributes": {},
"data.attributes.paymentType": "<string>",
"data.attributes.merchantId": "<string>",
"data.attributes.miscData": "<string>",
"data.attributes.StandardEntryClassCode": "<string>",
"data.attributes.bank": {
"data.attributes.bank.bankName": "<string>",
"data.attributes.bank.accountType": "<string>",
"data.attributes.bank.accountName": "<string>",
"data.attributes.bank.accountNumber": "<string>",
"data.attributes.bank.routingNumber": "<string>"
},
"data.attributes.transaction": {
"data.attributes.transaction.amount": "<string>",
"data.attributes.transaction.currency": "<string>",
"data.attributes.transaction.invoice": "<string>"
}
}
'import requests
url = "https://api.example.com/payments"
payload = {
"data": {},
"data.requestId": "<string>",
"data.type": "<string>",
"data.attributes": {},
"data.attributes.paymentType": "<string>",
"data.attributes.merchantId": "<string>",
"data.attributes.miscData": "<string>",
"data.attributes.StandardEntryClassCode": "<string>",
"data.attributes.bank": {
"data.attributes.bank.bankName": "<string>",
"data.attributes.bank.accountType": "<string>",
"data.attributes.bank.accountName": "<string>",
"data.attributes.bank.accountNumber": "<string>",
"data.attributes.bank.routingNumber": "<string>"
},
"data.attributes.transaction": {
"data.attributes.transaction.amount": "<string>",
"data.attributes.transaction.currency": "<string>",
"data.attributes.transaction.invoice": "<string>"
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
data: {},
'data.requestId': '<string>',
'data.type': '<string>',
'data.attributes': {},
'data.attributes.paymentType': '<string>',
'data.attributes.merchantId': '<string>',
'data.attributes.miscData': '<string>',
'data.attributes.StandardEntryClassCode': '<string>',
'data.attributes.bank': {
'data.attributes.bank.bankName': '<string>',
'data.attributes.bank.accountType': '<string>',
'data.attributes.bank.accountName': '<string>',
'data.attributes.bank.accountNumber': '<string>',
'data.attributes.bank.routingNumber': '<string>'
},
'data.attributes.transaction': {
'data.attributes.transaction.amount': '<string>',
'data.attributes.transaction.currency': '<string>',
'data.attributes.transaction.invoice': '<string>'
}
})
};
fetch('https://api.example.com/payments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/payments",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'data' => [
],
'data.requestId' => '<string>',
'data.type' => '<string>',
'data.attributes' => [
],
'data.attributes.paymentType' => '<string>',
'data.attributes.merchantId' => '<string>',
'data.attributes.miscData' => '<string>',
'data.attributes.StandardEntryClassCode' => '<string>',
'data.attributes.bank' => [
'data.attributes.bank.bankName' => '<string>',
'data.attributes.bank.accountType' => '<string>',
'data.attributes.bank.accountName' => '<string>',
'data.attributes.bank.accountNumber' => '<string>',
'data.attributes.bank.routingNumber' => '<string>'
],
'data.attributes.transaction' => [
'data.attributes.transaction.amount' => '<string>',
'data.attributes.transaction.currency' => '<string>',
'data.attributes.transaction.invoice' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/payments"
payload := strings.NewReader("{\n \"data\": {},\n \"data.requestId\": \"<string>\",\n \"data.type\": \"<string>\",\n \"data.attributes\": {},\n \"data.attributes.paymentType\": \"<string>\",\n \"data.attributes.merchantId\": \"<string>\",\n \"data.attributes.miscData\": \"<string>\",\n \"data.attributes.StandardEntryClassCode\": \"<string>\",\n \"data.attributes.bank\": {\n \"data.attributes.bank.bankName\": \"<string>\",\n \"data.attributes.bank.accountType\": \"<string>\",\n \"data.attributes.bank.accountName\": \"<string>\",\n \"data.attributes.bank.accountNumber\": \"<string>\",\n \"data.attributes.bank.routingNumber\": \"<string>\"\n },\n \"data.attributes.transaction\": {\n \"data.attributes.transaction.amount\": \"<string>\",\n \"data.attributes.transaction.currency\": \"<string>\",\n \"data.attributes.transaction.invoice\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/payments")
.header("Content-Type", "application/json")
.body("{\n \"data\": {},\n \"data.requestId\": \"<string>\",\n \"data.type\": \"<string>\",\n \"data.attributes\": {},\n \"data.attributes.paymentType\": \"<string>\",\n \"data.attributes.merchantId\": \"<string>\",\n \"data.attributes.miscData\": \"<string>\",\n \"data.attributes.StandardEntryClassCode\": \"<string>\",\n \"data.attributes.bank\": {\n \"data.attributes.bank.bankName\": \"<string>\",\n \"data.attributes.bank.accountType\": \"<string>\",\n \"data.attributes.bank.accountName\": \"<string>\",\n \"data.attributes.bank.accountNumber\": \"<string>\",\n \"data.attributes.bank.routingNumber\": \"<string>\"\n },\n \"data.attributes.transaction\": {\n \"data.attributes.transaction.amount\": \"<string>\",\n \"data.attributes.transaction.currency\": \"<string>\",\n \"data.attributes.transaction.invoice\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/payments")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"data\": {},\n \"data.requestId\": \"<string>\",\n \"data.type\": \"<string>\",\n \"data.attributes\": {},\n \"data.attributes.paymentType\": \"<string>\",\n \"data.attributes.merchantId\": \"<string>\",\n \"data.attributes.miscData\": \"<string>\",\n \"data.attributes.StandardEntryClassCode\": \"<string>\",\n \"data.attributes.bank\": {\n \"data.attributes.bank.bankName\": \"<string>\",\n \"data.attributes.bank.accountType\": \"<string>\",\n \"data.attributes.bank.accountName\": \"<string>\",\n \"data.attributes.bank.accountNumber\": \"<string>\",\n \"data.attributes.bank.routingNumber\": \"<string>\"\n },\n \"data.attributes.transaction\": {\n \"data.attributes.transaction.amount\": \"<string>\",\n \"data.attributes.transaction.currency\": \"<string>\",\n \"data.attributes.transaction.invoice\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Invalid routing number",
"source": {
"pointer": "/data/attributes/bank/routingNumber"
}
}
]
}
{
"errors": [
{
"status": "401",
"title": "Unauthorized",
"detail": "Invalid or expired app token"
}
]
}
{
"errors": [
{
"status": "422",
"title": "Unprocessable Entity",
"detail": "Payment processing failed - insufficient funds"
}
]
}
Endpoint
POST https://api.digitzs.com/payments
Overview
Use this endpoint to process ACH payments directly from a customer’s bank account. This method does not require creating a customer account or storing payment method tokens.ACH payments typically take 3-5 business days to settle. Funds are not immediately available.
Authentication
| Header | Value | Required |
|---|---|---|
x-api-key | Your API key from onboarding | Yes |
Authorization | Bearer {appToken} | Yes |
appId | Your application ID | Yes |
Content-Type | application/json | Yes |
Request Body
Container for API data
UUID for idempotency. If provided, must be in valid UUID format. Optional but recommended for preventing duplicate transactions.
Must be
"payments"Container for payment attributes
Must be
"ACH" for ACH paymentsThe merchant account identifier
Optional JSON string containing additional metadata like email, IP addresses, or custom data
Must be
"WEB" for internet-initiated ACH transactionsBank account information
Show Bank object properties
Show Bank object properties
Name of the financial institution
Type of account - must be
"checking" or "savings"Full name of the account holder
Bank account number
9-digit bank routing number. Must be a valid routing number even in test environment.
Transaction details
Show Transaction object properties
Show Transaction object properties
Payment amount in cents (e.g., “3635” for $36.35)
Three-letter currency code (ISO 4217). Currently only
"USD" is supported.Invoice or reference number for the transaction
Example Request
{
"data": {
"requestId": "f8d0fedd-fad0-4c53-bb8d-44a4cd28573b",
"type": "payments",
"attributes": {
"paymentType": "ACH",
"merchantId": "merchant_123456",
"miscData": "{\"email\":\"customer@example.com\",\"originIp\":\"192.168.1.1\",\"customerIp\":\"203.0.113.0\"}",
"StandardEntryClassCode": "WEB",
"bank": {
"bankName": "Wells Fargo",
"accountType": "checking",
"accountName": "John Doe",
"accountNumber": "1234567890",
"routingNumber": "026009593"
},
"transaction": {
"amount": "3635",
"currency": "USD",
"invoice": "INV-2024-001"
}
}
}
}
Response
Success Response (201 Created)
Contains URLs related to the resource
Show properties
Show properties
URL of the current endpoint
Container for response data
Show properties
Show properties
Resource type - will be
"payments"Unique payment transaction identifier
Show properties
Show properties
Payment type -
"ACH"Show Transaction details
Show Transaction details
Response code -
"0" indicates successHuman-readable response message
Transaction amount in cents
Currency code
Invoice reference number
Example Response
{
"links": {
"self": "https://api.digitzs.com/payments"
},
"data": {
"type": "payments",
"id": "pay_ach_abc123xyz",
"attributes": {
"paymentType": "ACH",
"transaction": {
"code": "0",
"message": "Success",
"amount": "3635",
"currency": "USD",
"invoice": "INV-2024-001"
}
}
}
}
Code Examples
curl -X POST https://api.digitzs.com/payments \
-H "x-api-key: your-api-key" \
-H "Authorization: Bearer your-app-token" \
-H "appId: your-app-id" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "payments",
"attributes": {
"paymentType": "ACH",
"merchantId": "merchant_123456",
"StandardEntryClassCode": "WEB",
"bank": {
"bankName": "Wells Fargo",
"accountType": "checking",
"accountName": "John Doe",
"accountNumber": "1234567890",
"routingNumber": "026009593"
},
"transaction": {
"amount": "3635",
"currency": "USD",
"invoice": "INV-2024-001"
}
}
}
}'
const axios = require('axios');
async function createACHPayment() {
const response = await axios.post(
'https://api.digitzs.com/payments',
{
data: {
type: 'payments',
attributes: {
paymentType: 'ACH',
merchantId: 'merchant_123456',
StandardEntryClassCode: 'WEB',
bank: {
bankName: 'Wells Fargo',
accountType: 'checking',
accountName: 'John Doe',
accountNumber: '1234567890',
routingNumber: '026009593'
},
transaction: {
amount: '3635',
currency: 'USD',
invoice: 'INV-2024-001'
}
}
}
},
{
headers: {
'x-api-key': 'your-api-key',
'Authorization': 'Bearer your-app-token',
'appId': 'your-app-id',
'Content-Type': 'application/json'
}
}
);
console.log('Payment ID:', response.data.data.id);
return response.data;
}
createACHPayment();
import requests
def create_ach_payment():
url = "https://api.digitzs.com/payments"
headers = {
"x-api-key": "your-api-key",
"Authorization": "Bearer your-app-token",
"appId": "your-app-id",
"Content-Type": "application/json"
}
payload = {
"data": {
"type": "payments",
"attributes": {
"paymentType": "ACH",
"merchantId": "merchant_123456",
"StandardEntryClassCode": "WEB",
"bank": {
"bankName": "Wells Fargo",
"accountType": "checking",
"accountName": "John Doe",
"accountNumber": "1234567890",
"routingNumber": "026009593"
},
"transaction": {
"amount": "3635",
"currency": "USD",
"invoice": "INV-2024-001"
}
}
}
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
payment_id = response.json()["data"]["id"]
print(f"Payment ID: {payment_id}")
return response.json()
create_ach_payment()
<?php
function createACHPayment() {
$url = "https://api.digitzs.com/payments";
$headers = [
"x-api-key: your-api-key",
"Authorization: Bearer your-app-token",
"appId: your-app-id",
"Content-Type: application/json"
];
$payload = json_encode([
"data" => [
"type" => "payments",
"attributes" => [
"paymentType" => "ACH",
"merchantId" => "merchant_123456",
"StandardEntryClassCode" => "WEB",
"bank" => [
"bankName" => "Wells Fargo",
"accountType" => "checking",
"accountName" => "John Doe",
"accountNumber" => "1234567890",
"routingNumber" => "026009593"
],
"transaction" => [
"amount" => "3635",
"currency" => "USD",
"invoice" => "INV-2024-001"
]
]
]
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 201) {
$data = json_decode($response, true);
$paymentId = $data["data"]["id"];
echo "Payment ID: " . $paymentId . "\n";
return $data;
} else {
throw new Exception("Error creating payment: " . $response);
}
}
createACHPayment();
?>
require 'net/http'
require 'json'
require 'uri'
def create_ach_payment
uri = URI('https://api.digitzs.com/payments')
request = Net::HTTP::Post.new(uri)
request['x-api-key'] = 'your-api-key'
request['Authorization'] = 'Bearer your-app-token'
request['appId'] = 'your-app-id'
request['Content-Type'] = 'application/json'
request.body = {
data: {
type: 'payments',
attributes: {
paymentType: 'ACH',
merchantId: 'merchant_123456',
StandardEntryClassCode: 'WEB',
bank: {
bankName: 'Wells Fargo',
accountType: 'checking',
accountName: 'John Doe',
accountNumber: '1234567890',
routingNumber: '026009593'
},
transaction: {
amount: '3635',
currency: 'USD',
invoice: 'INV-2024-001'
}
}
}
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
if response.code == '201'
data = JSON.parse(response.body)
payment_id = data['data']['id']
puts "Payment ID: #{payment_id}"
data
else
raise "Error creating payment: #{response.body}"
end
end
create_ach_payment
Error Responses
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Invalid routing number",
"source": {
"pointer": "/data/attributes/bank/routingNumber"
}
}
]
}
{
"errors": [
{
"status": "401",
"title": "Unauthorized",
"detail": "Invalid or expired app token"
}
]
}
{
"errors": [
{
"status": "422",
"title": "Unprocessable Entity",
"detail": "Payment processing failed - insufficient funds"
}
]
}
Common Error Scenarios
Invalid routing number
Invalid routing number
Error: 400 Bad RequestSolution: Verify the routing number is a valid 9-digit ABA routing number. The test environment requires real routing numbers.
Invalid account type
Invalid account type
Error: 400 Bad RequestSolution: Ensure accountType is either “checking” or “savings” (lowercase).
Missing required fields
Missing required fields
Error: 400 Bad RequestSolution: Verify all required fields are present: paymentType, merchantId, StandardEntryClassCode, bank object, and transaction object.
Payment processing failed
Payment processing failed
Error: 422 Unprocessable EntitySolution: The payment was rejected by the bank. Common reasons include insufficient funds, closed account, or invalid account information.
Important Notes
Real Routing Numbers Required: Even in the test environment, you must use valid bank routing numbers. Invalid routing numbers will be rejected.
Settlement Time: ACH payments take 3-5 business days to settle. The payment will appear as “pending” during this time.
Idempotency: Use the optional
requestId field with a UUID to prevent duplicate payments if your request is accidentally submitted multiple times.Best Practices
- Validate Bank Information: Verify routing and account numbers before submitting to reduce failed payments
- Store Payment IDs: Save the returned payment ID for status checking and reconciliation
- Handle Async Nature: ACH is asynchronous - implement webhooks or polling to track payment status
- Collect Customer Consent: Ensure you have proper authorization to debit the customer’s account
- Use miscData Field: Store additional context like customer email, IP addresses for fraud prevention and customer support
Next Steps
Get Payment Status
Check the status of your ACH payment
Refund Payment
Learn how to refund an ACH payment
⌘I

