ACH Transfers
An Automated Clearing House (ACH) transfer is an electronic funds transfer between two accounts at different banks. It allows for for credits (sending money) and debits (receiving money), and is generally cheaper when compared to other available methods, but also most-often slower. This guide will examine the process of sending money to another account using ACH (also known as a credit), though you can also receive money from an account (a debit) using this same method.
This guide uses the following endpoints
To create an ACH transfer you will need to
1. Get the Account ID
The first step in creating an ACH transfer is to obtain the ID of the account the funds will be transferred from.
Both a savings and checking account have been pre-created in the Developer Sandbox for testing purposes; however, you can also create and use your own bank accounts if you prefer.
To retrieve an account ID, make a GET
request to the account
endpoint.
curl -u $API_KEY_ID:$API_SECRET_KEY https://api.treasuryprime.com/account
This will return a list of of Account objects. In order to make an ACH transfer, you will need the account ID which is stored in the id
property of each account object.
{
"data": [
{
"account_type": "savings",
"bank_id": "bank_treasuryprime",
"updated_at": "2021-02-01T16:32:34Z",
"currency": null,
"routing_number": "000000000",
"account_number": "123000012345",
"id": "acct_qda4pJZfpzn4fc",
"created_at": "2021-01-13T15:05:14Z",
"userdata": null
},
{
"account_type": "checking",
"bank_id": "bank_treasuryprime",
"updated_at": "2021-02-01T16:32:34Z",
"currency": null,
"routing_number": "000000000",
"account_number": "123000067890",
"id": "acct_wVwR87rxhMRdwD",
"created_at": "2021-01-13T15:05:13Z",
"userdata": null
}
],
"total_estimated": 10
}
2. Get the Counterparty ID
The next piece of data required for an ACH is the ID of the Counterparty (the person or entity on the other side of that transaction) or put more simply: Who the funds are being transferred to. If you have not yet created a Counterparty in your Developer Sandbox, read the next section for instructions on how to accomplish this. Otherwise, feel free to skip ahead to Retrieve an existing Counterparty.
Create a Counterparty
Creating a Counterparty requires making a POST
request to the counterparty
endpoint, and passing along the name of person or entity who owns the account, as well as three pieces of data required for ACH:
- The ACH specific bank account number
- The account type (checking or savings)
- The routing number
curl -u $API_KEY_ID:$API_SECRET_KEY https://api.treasuryprime.com/counterparty \
-H 'Content-Type: application/json' \
-d '{
"name_on_account": "Adam Smith",
"ach": {
"account_number": "12345678",
"account_type": "checking",
"routing_number": "87654321"
}
}'
Assuming no errors are encountered, the response will contain a Counterparty object containing an id
property representing the counterparty ID.
{
"created_at": "2021-02-25T01:23:24Z",
"updated_at": "2021-02-25T01:23:24Z",
"ach": {
"account_number": "12345678",
"account_type": "checking",
"routing_number": "87654321"
},
"wire": null,
"name": "Adam Smith",
"name_on_account": "Adam Smith",
"id": "cp_v1p3ay8w4b0x",
"userdata": null
}
Retrieve an Existing Counterparty
To find the IDs of any existing Counterparty objects, make a GET
request to the counterparty
endpoint
curl -u $API_KEY_ID:$API_SECRET_KEY https://api.treasuryprime.com/counterparty
This will return a list of all existing Counterparty objects you have created (or empty if none are found). Each Counterparty object contains an id
property representing the counterparty ID.
{
"data": [
{
"created_at": "2021-02-25T01:23:24Z",
"updated_at": "2021-02-25T01:23:24Z",
"ach": {
"account_number": "12345678",
"account_type": "checking",
"routing_number": "87654321"
},
"wire": null,
"name": "Adam Smith",
"name_on_account": "Adam Smith",
"id": "cp_v1p3ay8w4b0x",
"userdata": null
},
...
]
}
3. Create the ACH Transfer
With the Account ID, and Counterparty ID, the ACH transfer can now be made. But first a final note on two additional properties. The direction
property specifies whether this transfer is a credit or debit (in this case a credit since money is being sent), and the sec_code
which specifies the type of transfer according to the ACH Network. More details on those topics can be found in the ACH documentation.
The protocol that underlies the ACH network is batch-oriented and does not provide success responses (only error responses). As a result, ACH transfers follow a particular workflow as they are processed by the network. You can track a transfer's progress by checking the status attribute on the ACH object.
Enough details, let's make the transfer!
curl -u $API_KEY_ID:$API_SECRET_KEY https://api.treasuryprime.com/ach \
-H 'Content-Type: application/json' \
-d '{
"account_id": "acct_1234567890",
"amount": "100.00",
"counterparty_id": "cp_0987654321",
"direction": "credit",
"sec_code": "ppd"
}'
If no errors were encountered, a new ACH Object is returned. To find out when the transfer is complete requires watching for status updates which will be covered next.
{
"description": null,
"amount": "100.00",
"service": "standard",
"counterparty_id": "cp_0987654321",
"bankdata": null,
"bank_id": "bank_treasuryprime",
"account_id": "acct_1234567890",
"addenda": [],
"org_id": "org_treasuryprime",
"batch_key": null,
"effective_date": "2021-02-25",
"updated_at": "2021-02-25T01:32:57Z",
"status": "pending",
"id": "ach_5merj00eudnp",
"error": null,
"sec_code": "ppd",
"direction": "credit",
"created_at": "2021-02-25T01:32:57Z",
"userdata": null
}
4. Get Status Updates
There are two ways to find out when the status of the ACH transfer has changed:
Manually Checking for Status Updates
By making a GET
request to the ach
endpoint and passing in the id
of the ACH transfer you'd like the status for. This will return an ACH object with the latest status.
curl -u $API_KEY_ID:$API_SECRET_KEY https://api.treasuryprime.com/ach/:id
Note the status
has been changed to "sent".
{
"description": null,
"amount": "100.00",
"service": "standard",
"counterparty_id": "cp_0987654321",
"bankdata": null,
"bank_id": "bank_treasuryprime",
"account_id": "acct_1234567890",
"addenda": [],
"org_id": "org_treasuryprime",
"batch_key": null,
"effective_date": "2021-02-25",
"updated_at": "2021-01-04T20:30:27Z",
"status": "sent",
"id": "ach_5merj00eudnp",
"error": null,
"sec_code": "ppd",
"direction": "credit",
"created_at": "2021-02-25T01:32:57Z",
"userdata": null
}
Listening for Status Updates with Webhooks
By registering a webhook to respond to the ach.update
event, you can be notified of changes in the status of the ACH transfer when they occur.
curl https://api.treasuryprime.com/webhook \\
-u "$API_KEY_ID:$API_SECRET_KEY" \\
-H 'Content-Type: application/json' \\
-d '{
"event": "ach.update",
"url": "https://example.application.com/notify"
}'
Once the ach.update
webhook notification is received, follow the steps outlined above to obtain the latest status of the transfer, or simply make a GET
request to the URL specified in the url
property of the data object.
{
"event": "ach.update",
"op": "update",
"id": "ach_01123456789",
"url": "https://api.treasuryprime.com/ach/ach_01123456789"
}
Updated 6 months ago
Once the ACH Transfer object reaches a status of "sent", then the transfer is complete! Congratulations on making your first ACH transfer. If you'd like to dig deeper, check out the ACH API documentation. And since you're already on a hot-streak, why not try out Issuing Debit Cards?