Transfer Sandbox
Use Sandbox to test your transfer integration
While all newly created teams can use Transfer in Sandbox by default, some older teams may need to be manually enabled. If you receive an error indicating that the product is not enabled for your account when attempting to use Transfer in the Sandbox environment, contact Support or your Plaid Account Manager to request access.
Introduction to Sandbox
Sandbox is Plaid's environment for testing using fake data. For more details about getting started with Sandbox environment, including how to skip the Link flow in Sandbox with /sandbox/item/public_token/create, and testing non-Transfer-specific functionality such as Item errors, see Sandbox.
Simulating money movement, events, and webhooks
When creating transfers in Sandbox, see the /transfer/authorization/create documentation on how to generate approved or declined authorization responses.
Any cutoff times applied in Production will also apply in the Sandbox environment. For example, creating a same-day ACH transfer in Sandbox after 3:30 pm ET will automatically update the transfer to standard ACH.
In the Sandbox environment, no real banks are involved and no events are triggered automatically. By default, all transfers, refunds, and sweeps created in Sandbox remain at the pending status until you actively change them. This can be most easily accomplished through the Plaid Dashboard, where you can simulate next steps and common failure scenarios for any transfer that you've created in the Sandbox environment.

If you would like to change the status of a transfer through the API, you can call the following endpoints to simulate events and fire transfer webhooks manually.
| Action to simulate | Simulation endpoint |
|---|---|
| Transfer events | /sandbox/transfer/simulate |
| Refund events | /sandbox/transfer/refund/simulate |
| Ledger withdrawals sweep events | /sandbox/transfer/ledger/withdraw/simulate |
| Ledger deposits sweep events | /sandbox/transfer/ledger/deposit/simulate |
| Ledger pending-to-available funds movements | /sandbox/transfer/ledger/simulate_available |
| Webhooks | /sandbox/transfer/fire_webhook |
When you change the status of a Sandbox transfer, either through the Dashboard or the API, the corresponding webhook will not fire. You must use the /sandbox/transfer/fire_webhook API to send a Transfer webhook in Sandbox.
For a full list of transfer simulations available in Sandbox, see Sandbox endpoints.
For a general overview of the Plaid Sandbox environment, see Sandbox overview.
Automatic Sandbox simulations
In addition to manual simulations, the Sandbox environment supports automatic state transitions for transfers, refunds, and sweeps (deposits and withdrawals) when using specific test amounts. These special amounts trigger predefined state transitions without requiring manual intervention through the Dashboard or API.
Once you initiate a transfer with any of these specific amount values, the transfer's stages will be immediately simulated. The appropriate webhooks for Sandbox transfer events will be fired, and you can fetch the events through /transfer/event/sync. You can also view the events' progression on your Transfer Dashboard, on the details page for the specific transfer.
In Production, transfer state changes can take minutes to hours depending on processing time. Sandbox simulations provide immediate state transitions for testing purposes.
Transfer state transitions
Creating Sandbox transfers with the specified amounts via /transfer/create will result in automatic state transitions.
| Amount | State Transition Path |
|---|---|
| $11.11 | pending → posted → settled → funds available (ACH debits only) |
| $22.22 | pending → failed |
| $33.33 | pending → posted → settled → funds available (ACH debits only) → returned (R01) |
| $44.44 | pending → posted → settled → funds available (ACH debits only) → returned (R02) |
| $55.55 | pending → posted → settled → funds available (ACH debits only) → returned (R16) |
| $66.66 | pending → posted → settled → returned |
Refund state transitions
Creating Sandbox refunds with the specified amounts via /transfer/refund/create will result in automatic state transitions.
| Amount | State Transition Path |
|---|---|
| $1.11 | pending → posted → settled |
| $2.22 | pending → failed |
| $3.33 | pending → posted → settled → returned |
Sweep State Transitions
Creating Sandbox sweeps with the specified amounts via /transfer/ledger/deposit and /transfer/ledger/withdraw will result in automatic state transitions.
| Amount | State Transition Path |
|---|---|
| $111.11 | pending → posted → settled → funds available (deposits only) |
| $222.22 | pending → failed |
| $333.33 | pending → posted → settled → funds available (deposits only) → returned |
| $444.44 | pending → posted → settled → returned |
Testing Plaid Ledger flow of funds
While testing Plaid Ledger in Sandbox, you can always call the following endpoints at any time to verify expected behavior:
/transfer/getto validate the transfer status change/transfer/sweep/getto validate the deposit/withdrawal status change/transfer/ledger/getto validate the Ledger balance change
Wire transfers
In Sandbox, all customers are enabled for wire transfers in order to facilitate testing. Having access to wire transfers in Sandbox does not mean you are enabled for wires in Production. To request access to wire transfers in Production, contact your Account Manager.
Issuing payouts with a Plaid Ledger
Adding funds to the Plaid Ledger
All new Plaid Ledgers have a starting balance of $100 in Sandbox. Once this is depleted, or if you wish to simulate a larger transfer, you will need to fund the Ledger before testing the payout.
- Call
/transfer/ledger/depositto create a sweep that adds funds to a Plaid Ledger balance. The funds will immediately show up in thependingbalance. - Call
/sandbox/transfer/ledger/deposit/simulatewithsweep.postedas theevent_type. - Call
/sandbox/transfer/ledger/deposit/simulatewithsweep.settledas theevent_type. This will move your sweep tosettledstatus. - Call
/sandbox/transfer/ledger/simulate_availablein order to simulate the passage of time and transition the funds frompendingtoavailable.
Issuing a payout
- Call
/transfer/authorization/createwithtype=creditand your desired network. To simulate an insufficient funds failure, call/transfer/authorization/createwith an amount larger than your current available balance. - Call
/transfer/create. This will immediately create a transfer and decrement the available balance.
Receiving payments via Plaid Ledger
- Call
/transfer/authorization/createwithtype=debit. - Call
/transfer/create. This will immediately create a transfer and increment your pending balance in the Plaid Ledger. - Call
/sandbox/transfer/simulatewithpostedas theevent_type. - Call
/sandbox/transfer/simulatewithsettledas theevent_type. This will move your transfer tosettledstatus. The funds will remain inpendinguntil the hold is elapsed. - Call
/sandbox/transfer/ledger/simulate_availableto simulate the passage of time and convert the Ledger balance toavailable. If you are a Transfer for Platforms customer, this will convert all pending balances in all Plaid Ledgers. - Call
/transfer/ledger/withdrawto create a sweep that withdraws funds from the Plaid Ledger balance. The endpoint will immediately decrement the available balance and create a sweep withpendingstatus. - Call
/sandbox/transfer/ledger/withdraw/simulatewithsweep.postedas theevent_type. - Call
/sandbox/transfer/ledger/withdraw/simulatewithsweep.settledas theevent_type. This will move your sweep tosettledstatus.
In Production, transfer and sweep status will be updated automatically to reflect the real processing status, and the pending balance will automatically become available after the client-specific hold day.
Simulating a return with Plaid Ledger
- Follow steps 1-3 in Receiving payments via Plaid Ledger section to create a debit and move it to
posted. - (Optional) To simulate a return after the funds were made available, follow steps 4-5 as well. If you would like to simulate a return before the funds were made available, omit this step.
- Call
/sandbox/transfer/simulatewithreturnedas theevent_type. This will move the transfer status to returned and decrement pending balance, which you can verify by calling/transfer/ledger/get.
Testing Instant Payouts
Testing Instants Payouts works the same way as testing ACH Transfers.
To test the /transfer/capabilities/get endpoint in Sandbox, log in using the user_good user Sandbox account (see Sandbox simple test credentials for more information), and use the first 2 checking and savings accounts in the "First Platypus Bank" institution (ending in 0000 or 1111), which will return true. Any other account will return false. If using a custom Sandbox user, set numbers.ach_routing to 322271627 in order to return true.
Setting balances
You can customize the starting balance and certain other data for a linked account by using a Sandbox custom user. The easiest way to set a custom balance is to use a test user in the custom users repo. Using one of the example files, modify the starting balance, then follow the instructions in the repo's README to add the user to your Sandbox.
Simulating recurring transfers
In the Sandbox environment, recurring transfers can be simulated by using a test_clock object.
A test_clock is a mock clock that has a virtual_time field, indicating the current timestamp on this test clock. You can attach a test_clock to a recurring_transfer in Sandbox by providing a test_clock_id when calling /transfer/recurring/create.
You can advance the virtual_time on a test_clock to a higher value by calling /sandbox/transfer/test_clock/advance, but you can never decrease the virtual_time.
When a test clock is advanced, all active recurring transfers attached to this clock will generate new originations as if the time had elapsed in Production. For instance, assuming a test clock is attached to a weekly recurring transfer, if the test clock is advanced by 14 days, you should see two new transfers being created.
Note that advancing a test clock does not change the status of the transfer objects created by a recurring transfer. Transfers will stay in pending status unless you call /sandbox/transfer/simulate to simulate a transfer status update.
Sample Sandbox recurring transfer scenarios
Create a test clock using
/sandbox/transfer/test_clock/create, with avirtual_timeof"2022-11-14T07:00:00-08:00", which is 2022-11-14 7AM PST (Monday).Create a weekly recurring transfer on every Tuesday using
/transfer/recurring/createwith thetest_clock_idreturned from step 1. The recurring schedule starts on 2022-11-15, and ends on 2022-11-30.Advance the test clock to
"2022-11-15T23:59:00-08:00", which is the end of day 2022-11-15 PST (Tuesday).Since we advanced the test clock to the last minute of Tuesday and the recurring transfer is also scheduled on every Tuesday, we expect to see 1 transfer being created. Inspect the recurring transfer created in step 2 with
/transfer/recurring/get. Confirm thetransfer_idsfield now has 1 element, and thestatusfield is"active".Advance the test clock to
"2022-11-29T23:59:00-08:00", which is the end of day 2022-11-29 PST (Tuesday).Inspect the recurring transfer created in step 2 with
/transfer/recurring/get. Confirm that thetransfer_idsfield now has 3 elements, and thestatusfield is now"expired".Advance the test clock to
"2022-12-06T23:59:00-08:00", which is the end of day 2022-12-06 PST (Tuesday).Inspect the recurring transfer created in step 2 with
/transfer/recurring/get. Confirm that thetransfer_idsfield still has 3 elements, and the status field remains"expired".
Testing Transfer for Platforms end-user onboarding
In Sandbox, Transfer for Platforms customers must use /transfer/platform/originator/create instead of the /partner/customer/create and /partner/customer/enable endpoints that they would use in Production.
/transfer/platform/originator/create, /transfer/platform/requirement/submit, and /transfer/platform/document/submit will all succeed on valid requests. /transfer/platform/person/create will succeed and return a random person_id.
In addition to working with originator_ids created by /transfer/platform/originator/create, /transfer/originator/get will return the following static responses based on which client_id is passed as the originator_client_id:
client_id | Response |
|---|---|
111111111111111111111111 | approved |
222222222222222222222222 | denied |
333333333333333333333333 | under_review |
444444444444444444444444 | more_information_required |