Collect via ACH
Pull funds from bank accounts directly into Passport using the ACH network.
A Collect via ACH transaction allows you to pull funds from a bank account into a Passport account using the ACH (Automated Clearing House) network. This method is commonly used to collect fees, commissions, or other payments from customers, or to fund a Passport account from your own external bank account.
Passport supports three source types for ACH Collect transactions:
- External Account (Own Account): Pull funds from a pre-linked external bank account into a Passport account.
- One-Time: Pull funds from a third-party bank account provided at the time of the transaction, without pre-linking it to Passport.
As per NACHA rules, you must have valid authorization from the account holder before initiating any ACH debit. Ensure authorizations are retained and available upon request.
How it Works
Step 1: Initiate the Collect Transaction
To create a Collect via ACH, make a POST request to the /v1/customer/id/{id}/transaction endpoint with the required parameters. It is essential to pass the source object in your request which determines the type of ACH Collect being initiated.
| Parameter | Required | Description |
|---|---|---|
method | ✓ | Set to ACH for ACH transactions. |
source.account.id | ✓ | The account to be debited. Structure varies based on collect type. See source types below. |
destination.account.id | ✓ | The Passport Account where funds will be credited. |
amount | ✓ | Amount to collect, in USD. |
Source Types
The Passport system supports three ways to specify the source of funds for an ACH Collect. Select the one that applies to your transaction.
-
Collect from External Account (Own Account): Use this when pulling funds from a bank account that has already been linked to Passport as an External Account. This is the standard method for funding a Passport account from your own bank account or a customer's pre-linked account. Pass the pre-linked External Account identifier in the
sourceobject:Parameter Required Description source.externalAccount.idorsource.externalAccount.externalId✓ Unique identifier of the External Account linked with Passport. destination.externalAccount.idordestination.externalAccount.externalId✓ The Passport Account where funds will be credited -
Collect from a One-Time Source: Use this when pulling funds from a third-party bank account that is not pre-linked to Passport. The account details are provided directly in the transaction request. Only Business Customers can initiate a One-Time ACH Collect. Pass the account details directly in the
sourceobject:One-Time Collect must be enabled at the Program Manager level via the Allow Collect from One-Time Source configuration before it can be used.
Parameter Required Description source.externalAccount.accountNumber✓ The bank account number to be debited. source.externalAccount.routingNumber✓ The 9-digit routing number of the account. source.externalAccount.holderName✓ Name of the bank account holder as it appears on bank records. source.externalAccount.type✓ Type of bank account. Possible values: SAVING,CHECKING.source.externalAccount.holderType✓ Type of account holder. Possible values: CONSUMER,CORPORATE.destination.account.id✓ The Passport account's unique identifier where funds will be credited.
Processing Details
You can also pass, the processingDetail object which carries additional processing instructions for your ACH Collect transaction. While optional as a whole, certain fields within it may be required depending on your Program Manager configuration.
More refernce for processingDetail
| Parameter | Required | Description |
|---|---|---|
| processingDetail.processingMode | Recommended | Processing mode for the transaction. Possible values: FORWARD (default) that is transaction is processed in the last batch of the day. Settlement occurs on the next business day or SAME_DAY i.e. transaction is processed in the next available batch. Settlement occurs on the same business day, provided the transaction is submitted before the last batch cutoff. Transactions submitted after the cutoff settle the next business day. |
| processingDetail.companyName | Recommended | The payee name populated in the NACHA file. If not provided, the default value configured at the Program Manager level is used. |
| processingDetail.companyDescription | Recommended | A short description of the transaction purpose populated in the NACHA file. Common examples: Gas bill, Reg. Salary, PURCHASE. If not provided, the default configured value is used. |
| processingDetail.authType | Conditional | The authorization type under which the debit was obtained. Possible values: WRITTEN, PHONE, ONLINE. Mandatory if no default is configured at the Program Manager level. |
| processingDetail.addenda | Recommended | Additional reference information to be passed alongside the ACH transaction. |
Step 2: Store & Check the Outcome
Finally, for every successfully created Collect transaction, store the id/ externalId - The unique Transaction ID assigned by Passport or your own reference ID, if provided at the time of creation.
Once the transaction is submitted, our system performs a series of validations before processing the request. These validations check for:
- Missing or invalid required fields
- Incorrect parameter formats or values
- Program Manager configuration or permission issues
If any validation fails, the request is rejected immediately and an error response is returned. You must correct the issue and resubmit the request.
If all validations pass, the transaction is submitted for processing. You can determine the outcome by retrieving the transaction via GET /v1/customer/id/{id}/transaction/id/{id} or by subscribing to the Transaction webhook. Check the status field in the response to understand the current state of the transaction.
Transaction Statuses
The table below describes the possible statuses of an ACH Collect transaction and the reasons associated with each.
| Status | Description | Reason |
|---|---|---|
SCHEDULED | Default status on creation. | ON_USER_REQUEST |
PENDING | Transaction is on hold due to an inactive or blocked source or destination account. | EXTERNAL_ACCOUNT_BLOCKED, EXTERNAL_ACCOUNT_INACTIVE, ACCOUNT_INACTIVE, ACCOUNT_BLOCKED, ACCOUNT_CLOSURE_INITIATED, ACCOUNT_CLOSED, CUSTOMER_SUSPENDED |
PROCESSING | Transaction has been picked up for processing. | PROCESSING_IN_TRANSIT |
COMPLETED | Funds have been successfully realized and credited to the destination account after the good funds period. | PROCESSED_BY_SYSTEM, ACH direct collect processed |
FAILED | Transaction could not be processed within the allowed processing interval, or a return was received from the bank. | Collect processing interval lapsed, <return-description> (<return-code>) |
CANCELLED | Transaction was cancelled upon user request. | ON_CUSTOMER_REQUEST, INCORRECTLY_CREATED, OTHERS |
Best Practices
| Practice | Description |
|---|---|
| Retain Authorization Records | Per NACHA requirements, maintain proof of authorization for every ACH debit you initiate. You may be required to produce this within 10 days of a request. |
| Use the Correct Auth Type | Suggested to pass processingDetail.authType to accurately reflect how authorization was obtained — WRITTEN, PHONE, or ONLINE. |
| Validate Account Details | For One-Time Collects, verify the account and routing numbers before submitting the transaction to reduce the risk of returns. |
| Set Meaningful Descriptors | Suggested to populate processingDetail.companyName and processingDetail.companyDescription so that the debit is clearly identifiable on the account holder's bank statement. |
| Use Webhooks | Subscribe to transaction webhooks to stay informed about transaction outcomes asynchronously, without polling. |
| Test Your Integration | Use Passport's sandbox environment to test all collect scenarios, including failures and returns, before going live. |
See Also
- Collect via WIRE
To confirm
- Confirm if ACH Collect is not supported for Consumer accounts
- One-Time Collect requires a PM-level configuration to be turned on. It's unclear whether this is on by default for all Program Managers or needs to be explicitly requested.
Updated about 11 hours ago