Server-Side Bank Account Tokenization
Tokenize existing bank account data for recurring ACH payments
Server-Side Bank Account Tokenization
If you already have bank account data in your system, Preczn provides two server-side methods to tokenize that data for recurring ACH payments. Unlike credit card data (which falls under PCI scope), many businesses already store bank account information, making this a common integration path.
For collecting new bank account details directly from customers, see ACH PaymentFields Integration.
Tokens allow you to charge a customer's bank account multiple times without transmitting their account details on every request.
Tokenization Methods
Method 1: Tokenize During Transaction
Include tokenize=true as a query parameter when processing an ACH sale to automatically create a multi-use token:
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"
}Response includes the multi-use token:
{
"id": "txn_abc123",
"type": "sale",
"amount": 5000,
"currency": "USD",
"merchantId": "mid_abc123",
"authorization": {
"status": "P",
"processorCode": "00",
"processorMessage": "ACH transaction submitted",
"approvedAmount": 5000
},
"payment": {
"token": "tkn_xyz789",
"type": "personalChecking",
"last4": "6789",
"bin": "987654321"
},
"processor": {
"id": "pfmCon_xyz789",
"name": "Payrix",
"routingSource": "plan"
},
"firstName": "John",
"lastName": "Doe",
"createdOn": "2024-01-15T10:30:00Z"
}Method 2: Direct Tokenization via Token Endpoint
Create a token without processing a transaction. This is useful for saving payment methods in user profiles:
POST /v1/tokens
{
"type": "bankAccount",
"merchantId": "mid_abc123",
"bankAccount": {
"type": "personalChecking",
"account": "123456789",
"routing": "987654321",
"bankCountry": "USA"
},
"firstName": "John",
"lastName": "Doe"
}Response:
{
"id": "tkn_xyz789",
"merchantId": "mid_abc123",
"token": "tkn_xyz789",
"type": "bankAccount",
"bankAccount": {
"type": "personalChecking",
"account": "6789",
"routing": "987654321",
"bankCountry": "USA"
},
"firstName": "John",
"lastName": "Doe",
"createdOn": "2024-01-15T10:30:00Z"
}Token Request Fields
Required Fields
| Field | Type | Description |
|---|---|---|
type | string | Must be "bankAccount" |
merchantId | string | The merchant ID to associate the token with |
bankAccount.type | string | Account type: personalChecking, personalSavings, corporateChecking, or corporateSavings |
bankAccount.account | string | Bank account number (4-17 digits) |
bankAccount.routing | string | Bank routing number (9 digits) |
bankAccount.bankCountry | string | Bank country code (currently only "USA" is supported) |
Optional Fields
| Field | Type | Description |
|---|---|---|
firstName | string | Account holder's first name (recommended for personal accounts) |
lastName | string | Account holder's last name (recommended for personal accounts) |
email | string | Account holder's email address |
phone | string | Account holder's phone number |
billingAddress | object | Account holder's billing address |
accountBusinessName | string | Business name for corporate accounts |
achMandate | string | Customer's authorization text for ACH debits. Required for some processors (e.g., Braintree) |
Tip: Including customer information (
firstName,lastName,accountBusinessName,achMandate) when creating a token means you won't need to provide them on every subsequent transaction using that token.
Using Tokens for Recurring Payments
Once you have a multi-use token, use it for subsequent transactions:
POST /v1/transactions
{
"type": "sale",
"merchantId": "mid_abc123",
"amount": 5000,
"currency": "USD",
"payment": {
"token": "tkn_xyz789"
}
}Token Types
Single-Use Tokens
Tokens created via ACH PaymentFields are single-use by default. They can only be used for one transaction.
Multi-Use Tokens
Tokens created via:
- Direct tokenization endpoint (
POST /v1/tokens) - Transaction with
?tokenize=truequery parameter
These tokens can be used for multiple transactions (recurring payments, subscriptions, etc.).
Personal Account Requirements
For personal accounts (personalChecking, personalSavings), include the firstName and lastName fields:
{
"type": "bankAccount",
"merchantId": "mid_abc123",
"bankAccount": {
"type": "personalChecking",
"account": "123456789",
"routing": "987654321",
"bankCountry": "USA"
},
"firstName": "John",
"lastName": "Doe"
}Corporate Account Requirements
For corporate/business accounts (corporateChecking, corporateSavings), include the accountBusinessName field:
{
"type": "bankAccount",
"merchantId": "mid_abc123",
"bankAccount": {
"type": "corporateChecking",
"account": "123456789",
"routing": "987654321",
"bankCountry": "USA"
},
"accountBusinessName": "Acme Corporation"
}ACH Mandate for Braintree
When using Braintree as your processor, you must include an ACH mandate (authorization text):
{
"type": "bankAccount",
"merchantId": "mid_abc123",
"bankAccount": {
"type": "personalChecking",
"account": "123456789",
"routing": "987654321",
"bankCountry": "USA"
},
"achMandate": "I authorize Acme Corp to debit my bank account for the amount specified."
}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.
Validation Errors
| Error | Message | Cause | Solution |
|---|---|---|---|
| Bad Request | Routing number is required | Missing routing number | Include bankAccount.routing |
| Bad Request | Routing number must be exactly 9 digits | Invalid routing number format | Verify the routing number is exactly 9 digits |
| Bad Request | Account number is required | Missing account number | Include bankAccount.account |
| Bad Request | Account number must be between 4 and 17 digits | Invalid account number length | Verify account number is 4-17 digits |
| Bad Request | Account type is required | Missing account type | Include bankAccount.type |
| Bad Request | Bank country must be one of: USA | Unsupported country | Only US bank accounts are supported |
| Bad Request | ACH mandate is required for Braintree ACH transactions | Missing mandate for Braintree | Include achMandate field |
For a complete list of errors, see the ACH Error Reference.
Best Practices
- Discard raw bank details after tokenization - Never store account or routing numbers in your system; rely solely on the token
- Include customer info when creating tokens - Adding
firstName,lastName, oraccountBusinessNameduring tokenization means you won't need to include them on every transaction - Store tokens with customer records - Associate token IDs with customer profiles in your database for easy retrieval
- Use Method 2 for saved payment methods - When customers save a payment method without an immediate purchase, use the direct token endpoint
- Provide customer controls - Allow customers to view (masked), update, or remove their saved payment methods
Updated 2 days ago
