On-Ramping USD via ACH Pulls (Plaid)
On-Ramping USD via ACH Pulls (Plaid)
This guide explains how to integrate Unblock’s ACH pull flow so your US users can move USD from their bank accounts into your app using Plaid.
🤔 What is ACH Pull?
An ACH Pull lets a user permit Unblock to withdraw funds from a linked bank account. Plaid manages the secure bank connection. Your system never handles bank login credentials.
➡️ USD On-Ramp Flow with ACH Pull
- Create ACH profile for the user in Unblock
- Create the bank link via API and receive a Plaid Link URL
- Load Plaid Link so the user can confirm the bank accounts to link
- Verify link status until it is
ACTIVE(poll the API or use thelinkBankAccountwebhook) - Initiate the ACH pull for a USD amount from a specific linked account
- Monitor webhooks as the transfer and conversion progress
⚙️ Integration Steps
Step 1: Ensure User Is Ready and Create ACH Profile
The user must be verified as FULL_USER.
API reference:
Create a user profile for linking bank accounts
https://docs.dtr.org/reference/post_user-linked-bank-account-profile
curl --request POST \
--url https://sandbox.getunblock.com/user/linked-bank-account/profile \
--header 'Authorization: API-Key <YOUR_API_KEY>' \
--header 'unblock-session-id: <USER_SESSION_ID>' \
--header 'content-type: application/json' \
--data '
{
"currency": "USD",
"investment_objective": "INCOME",
"annual_income_range": "UNDER_25K"
}Step 2: Create Bank Link and Get Plaid Link URL
Start the bank linking process by calling Unblock
This request returns a Plaid Link URL.
You must load this URL on your frontend in the next step.
API reference:
Link bank account
https://docs.dtr.org/reference/put_user-linked-bank-account-link
curl --request PUT \
--url https://sandbox.getunblock.com/user/linked-bank-account/link \
--header 'Authorization: API-Key <YOUR_API_KEY>' \
--header 'unblock-session-id: <USER_SESSION_ID>' \
--header 'content-type: application/json' \
--data '
{
"currency": "USD",
}The response includes a Plaid Link URL used to confirm this account
Step 3: Load Plaid Link and Confirm the Account
Open the Plaid Link URL returned in Step 2 on your frontend.
Plaid handles authentication and consent.
Your system does not receive bank credentials.
If the user selects an invalid account (not of type "Checking"), the link fails and the bank account status becomes FAILED. In that case regenerate the Plaid Link URL again and provide it to the user.
Step 4: Verify the Link Status
After Plaid confirmation, the linked bank account moves from PENDING to a final status. You can:
- Option A – Webhook (recommended): Subscribe to
linkBankAccountwebhooks (see Webhooks for linked bank account status below). Whendata.statusisACTIVE, the account is ready for ACH pulls. You also receivedata.uuid(the linked bank account UUID) and, on failure,data.error. - Option B – Polling: Poll the GET linked bank account endpoint until the account
statusisACTIVE.
API reference:
Get linked bank account info
https://docs.dtr.org/reference/get_user-linked-bank-account
Unlink if needed:
https://docs.dtr.org/reference/delete_user-linked-bank-account-unlink
curl --request GET \
--url https://sandbox.getunblock.com/user/linked-bank-account \
--header 'Authorization: API-Key <YOUR_API_KEY>' \
--header 'unblock-session-id: <USER_SESSION_ID>'Successful response example
{
"profile_uuid": "5594401c-0072-4df2-be9c-d491c0754c21",
"status": "ACTIVE",
"linked_bank_accounts": [
{
"uuid": "abcdef01-1234-5678-90ab-cdef01234567",
"status": "ACTIVE",
"currency": "USD",
"account_number": "******7890",
"routing_number": "021000021",
"account_type": "CHECKING",
"bank_name": "Chase Bank"
}
]
}Step 5: Initiate an ACH Pull
Once the linked bank account status is ACTIVE, initiate the ACH pull for the desired USD amount.
You must specify which linked bank account to pull from using source_account_uuid. For some merchants, ip_address (IPv4 or IPv6) is required. When required and missing, the request is rejected. Sending ip_address when not required is optional. Note: only 3 ACH pulls per day are allowed per user (see ACH Pull Limits).
API reference:
Withdraw funds from linked bank account
https://docs.dtr.org/reference/post_user-linked-bank-account-pull
curl --request POST \
--url https://sandbox.getunblock.com/user/linked-bank-account/pull \
--header 'Authorization: API-Key <YOUR_API_KEY>' \
--header 'unblock-session-id: <USER_SESSION_ID>' \
--header 'content-type: application/json' \
--data '
{
"currency": "USD",
"amount": 100.00,
"source_account_uuid": "<LINKED_BANK_ACCOUNT_UUID>",
"ip_address": "203.0.113.42"
}The response includes a process_uuid that you can use for tracking.
Key Considerations for USD ACH On-Ramps
Prerequisites
- User must be a
FULL_USER - Required applicant data:
- Date of birth
- Country
- Phone
- TIN (SSN)
The user must accept the Terms & Conditions through the SDK
or submit third_party_end_user_agreement_hashes using POST /user.
The ACH profile must be created before starting the bank linking flow.
API reference:
Create a user profile for linking bank accounts
https://docs.dtr.org/reference/post_user-linked-bank-account-profile
Multiple Linked Bank Accounts
A user can link multiple bank accounts.
To remove a linked bank account, use the unlink endpoint with the specific account_uuid:
API reference:
Unlink bank account
https://docs.dtr.org/reference/delete_user-linked-bank-account-unlink
DELETE /user/linked-bank-account/unlink
{
"account_uuid": "<ACCOUNT_UUID>"
}You can link additional accounts by repeating the linking flow.
Bank Linking and Unlinking Limits
Users are limited in how many times they can link or unlink bank accounts within a 24-hour period:
- Maximum 3 bank link events per 24 hours
- Maximum 3 bank unlink events per 24 hours
If a user exceeds these limits, API requests may return a "LINK LIMIT EXCEEDED" error.
ACH Pull Limits
Users are limited to 3 ACH pulls per day (rolling 24-hour period). If a user exceeds this limit, the pull request may be rejected. Plan your UI and user messaging accordingly (e.g. inform users when they are close to the limit or after a pull is rejected).
Webhooks for linked bank account status
When a user links or unlinks a bank account (e.g. after completing Plaid), Unblock sends linkBankAccount webhooks so you can react to status changes without polling.
Payload shape:
{
"type": "linkBankAccount",
"subType": "statusUpdate",
"uuid": "<user-uuid-or-company-uuid>",
"data": {
"uuid": "<linked-bank-account-uuid>",
"status": "ACTIVE",
"error": "<optional; when status is FAILED>"
}
}| Field | Description |
|---|---|
type | "linkBankAccount" |
subType | "statusUpdate" |
uuid | User UUID (or company UUID for corporates) — entity that owns the linked bank account. |
data.uuid | Linked bank account UUID. |
data.status | ACTIVE, CHECK_COMPLETED, PENDING, FAILED, or DISABLED. |
data.error | Present when status is FAILED; contains the failure reason. |
Typical flow:
- Right after the user completes Plaid, the account is
PENDING. - When the provider confirms the link, you receive a webhook with
status: "ACTIVE"— the account is then ready for ACH pulls (Step 5). - If the user selected an invalid account (e.g. not Checking), you receive
status: "FAILED"and can usedata.errorand regenerate the Plaid Link URL.
Configure your webhook endpoint via our API. Full reference: Webhooks.
Settlement Time
ACH transfers take several business days to complete.
You will receive webhook events such as:
OUTSIDE_TRANSFER_RECEIVED
These confirm when funds clear and when the conversion process begins.
Error Handling
A FAILED status on the linked bank account usually means that user has selected an invalid account. In that case generate the Plaid Link URL again so the user can link a correct one.
Private Sandbox Testing
Plaid step
- Select the bank account that ends with
0000
Manual bank account details
Use the following values when creating the bank link:
{
"currency": "USD",
}Updated 9 days ago
