ACH Sale Transaction

Process ACH payments to debit funds from customer bank accounts

ACH Sale Transactions

An ACH Sale transaction debits funds from a customer's bank account. This is the primary method for accepting ACH payments.

Endpoint

POST /v1/transactions

Request Format

Using a Token (Recommended)

If you have an existing ACH token, use it directly:

{
  "type": "sale",
  "merchantId": "mid_abc123",
  "amount": 5000,
  "currency": "USD",
  "payment": {
    "token": "tkn_xyz789"
  }
}

Token Field Inheritance: If the token was created with firstName, lastName, accountBusinessName, or achMandate, those values are automatically used for the transaction. You don't need to include them in the request.

Overriding Token Fields: If you include firstName, lastName, accountBusinessName, or achMandate in the request, those values will be used for the transaction and the token will be updated with the new values.

Using Raw Bank Account Details

Alternatively, you can pass bank account details directly:

{
  "type": "sale",
  "merchantId": "mid_abc123",
  "amount": 5000,
  "currency": "USD",
  "payment": {
    "bankAccount": {
      "type": "personalChecking",
      "account": "123456789",
      "routing": "987654321",
      "bankCountry": "USA"
    }
  },
  "firstName": "John",
  "lastName": "Doe",
  "billingAddress": {
    "address": "123 Main St",
    "city": "New York",
    "region": "NY",
    "postal": "10001",
    "country": "USA"
  }
}

Request Fields

Required Fields

FieldTypeDescription
typestringMust be "sale"
merchantIdstringThe merchant processing the payment
amountintegerAmount in cents (e.g., 5000 = $50.00)
currencystringMust be "USD" for ACH
payment.tokenstringToken from tokenization (preferred)
payment.bankAccountobjectRaw bank account details (alternative to token)

Bank Account Fields (when not using token)

FieldTypeDescription
bankAccount.typestringAccount type (see below)
bankAccount.accountstringAccount number (4-17 digits)
bankAccount.routingstringRouting number (9 digits)
bankAccount.bankCountrystringMust be "USA"

Account Types

ValueDescription
personalCheckingIndividual checking account
personalSavingsIndividual savings account
corporateCheckingBusiness checking account
corporateSavingsBusiness savings account

Customer Information (Required for Personal Accounts)

For personal account types (personalChecking, personalSavings):

FieldTypeRequiredDescription
firstNamestringIf not on tokenCustomer's first name
lastNamestringIf not on tokenCustomer's last name
billingAddress.addressstringNoStreet address
billingAddress.citystringNoCity
billingAddress.regionstringNoState/Province
billingAddress.postalstringNoZIP/Postal code
billingAddress.countrystringNoISO 3166-1 alpha-3 country code

Business Name (Required for Corporate Accounts)

For corporate account types (corporateChecking, corporateSavings):

FieldTypeRequiredDescription
accountBusinessNamestringIf not on tokenBusiness name on the account

Note: When using a token, firstName, lastName, and accountBusinessName are only required if they weren't provided when the token was created. If included in the request, they will override the token's stored values.

Optional Fields

FieldTypeDescription
feeintegerPlatform fee in cents
referencestringYour internal reference ID
descriptionstringTransaction description
achMandatestringCustomer's ACH authorization text (required for some processors if not on token)

Response Format

Pending Response (Typical for ACH)

{
  "id": "txn_01abc123def456",
  "type": "sale",
  "amount": 5000,
  "fee": 0,
  "currency": "USD",
  "merchantId": "mid_abc123",
  "authorization": {
    "status": "P",
    "processorCode": "00",
    "processorMessage": "ACH transaction submitted",
    "approvedAmount": 0
  },
  "payment": {
    "type": "personalChecking",
    "last4": "6789",
    "bin": "987654321"
  },
  "processor": {
    "id": "pfmCon_xyz789",
    "name": "Payrix",
    "routingSource": "plan"
  },
  "firstName": "John",
  "lastName": "Doe",
  "createdOn": "2024-01-15T10:30:00Z"
}

Response Fields

FieldTypeDescription
idstringUnique transaction ID
typestringTransaction type (sale)
amountintegerAmount in cents
authorization.statusstringSingle character status code (P, A, D, E)
authorization.processorCodestringProcessor-specific code
authorization.processorMessagestringProcessor message
authorization.approvedAmountintegerAmount approved in cents
payment.typestringAccount type (e.g., personalChecking)
payment.last4stringLast 4 digits of account number
payment.binstringBank routing number
processorobjectProcessor routing information

Transaction Statuses

StatusCodeDescription
PendingPTransaction submitted to ACH network
ApprovedATransaction successfully processed
DeclinedDTransaction was declined
ErrorEAn error occurred

Example: Personal Account Sale

{
  "type": "sale",
  "merchantId": "mid_abc123",
  "amount": 7500,
  "currency": "USD",
  "payment": {
    "bankAccount": {
      "type": "personalChecking",
      "account": "123456789",
      "routing": "987654321",
      "bankCountry": "USA"
    }
  },
  "firstName": "Jane",
  "lastName": "Smith",
  "description": "Monthly subscription",
  "reference": "INV-2024-001"
}

Example: Corporate Account Sale

{
  "type": "sale",
  "merchantId": "mid_abc123",
  "amount": 150000,
  "currency": "USD",
  "payment": {
    "bankAccount": {
      "type": "corporateChecking",
      "account": "987654321",
      "routing": "123456789",
      "bankCountry": "USA"
    }
  },
  "accountBusinessName": "Acme Corporation",
  "description": "Q1 Invoice Payment",
  "reference": "PO-2024-100"
}

Example: Sale with Tokenization

Create a multi-use token for future recurring payments by adding ?tokenize=true to the endpoint:

POST /v1/transactions?tokenize=true
{
  "type": "sale",
  "merchantId": "mid_abc123",
  "amount": 5000,
  "currency": "USD",
  "payment": {
    "bankAccount": {
      "type": "personalChecking",
      "account": "123456789",
      "routing": "987654321",
      "bankCountry": "USA"
    }
  },
  "firstName": "John",
  "lastName": "Doe"
}

The response will include a payment.token field that can be used for future transactions.

Webhooks

ACH transactions go through the ACH network and may take 1-3 business days to settle. Use webhooks to track status changes:

EventDescription
transaction.pendingTransaction submitted to ACH network
transaction.approvedTransaction settled successfully
transaction.declinedTransaction was declined or returned
transaction.erroredAn error occurred during processing

Important: Always rely on webhooks for final transaction status. Do not assume a pending ACH transaction will be approved.

Error Messages

These are Preczn API errors returned when a request fails validation or processing. The error and message fields correspond to the API response format documented in the ACH Error Reference.

Bank Account Validation Errors

ErrorMessageCauseSolution
Bad RequestRouting number is requiredMissing routing fieldInclude the routing field in bankAccount
Bad RequestRouting number must be exactly 9 digitsRouting number length incorrectVerify the routing number is exactly 9 digits
Bad RequestRouting number is invalid 'USA' bank routing numberFails ABA checksum validationVerify the routing number with customer's bank
Bad RequestAccount number is requiredMissing account fieldInclude the account field in bankAccount
Bad RequestAccount number must be between 4 and 17 digitsAccount number length invalidVerify account number is 4-17 digits
Bad RequestAccount type is requiredMissing type fieldInclude the type field in bankAccount
Bad RequestAccount type must be one of: PersonalChecking, PersonalSavings, CorporateChecking, CorporateSavingsInvalid account typeUse a valid account type value
Bad RequestBank country is requiredMissing bankCountry fieldInclude bankCountry: "USA"
Bad RequestBank country must be one of: USAUnsupported countryACH only supports US bank accounts

Customer Information Errors

ErrorMessageCauseSolution
Bad RequestPersonal ACH accounts require firstName and lastNamePersonal account missing name fieldsInclude both firstName and lastName fields
Bad RequestCorporate ACH accounts require accountBusinessName or firstName and lastNameCorporate account missing identificationInclude accountBusinessName or both firstName and lastName
Bad RequestACH mandate is required for Braintree ACH transactionsBraintree requires authorization textInclude achMandate field

Token Errors

ErrorMessageCauseSolution
Bad Requestpayment.token must be a valid token IDInvalid or expired tokenVerify the token ID is correct and exists

Transaction Errors

ErrorMessageCauseSolution
Bad RequestAmount is requiredMissing amount fieldInclude amount in cents
Bad RequestAmount must be greater than 0Zero or negative amountProvide a positive amount
Bad RequestCurrency is requiredMissing currency fieldInclude currency: "USD"

Configuration Errors

ErrorMessageCauseSolution
Bad RequestACH transaction not supported for this PlanMerchant's plan lacks ACH processorContact support to enable ACH

For a complete list of errors, see the ACH Error Reference.