Plaid logo
Docs
ALL DOCS

Transfer

  • Transfer Overview
  • Transfer Application
  • Creating transfers
  • Monitoring transfers
  • Plaid Ledger flow of funds
  • Transfer Dashboard
  • Refunds
  • Recurring transfers
  • Transfer UI
  • Platform Payments
  • Errors and troubleshooting
  • Testing in Sandbox
  • Legacy Flow of funds
Plaid logo
Docs
Close search modal
Ask Bill!
Ask Bill!
Hi! I'm Bill! You can ask me all about the Plaid API. Try asking questions like:
  • Can you show code for getting a credit card APR in Ruby?
  • Which countries does Investments support?
  • Why is /transactions/sync/ better than /get?
Note: Bill isn't perfect. He's just a robot platypus that reads our docs for fun. You should treat his answers with the same healthy skepticism you might treat any other answer on the internet. This chat may be logged for quality and training purposes. Please don't send Bill any PII -- he's scared of intimacy. All chats with Bill are subject to Plaid's Privacy Policy.
Plaid.com
Log in
Get API Keys
Open nav

Errors and Troubleshooting

Common errors and troubleshooting tips

ACH Returns

After an ACH payment has been posted, it can be returned and clawed back from your account for a number of reasons. For example, a bank could determine that there are insufficient funds to complete the transfer, or a consumer can contact their bank and flag the transaction as unauthorized. If a debit transfer results in an ACH return, the funds will be automatically clawed back in a return sweep. If a credit transfer experiences an ACH return, the funds will be returned to your Ledger available balance.

Note that an ACH return is distinct from an ACH reversal. An ACH reversal is performed only to correct an erroneous transfer and will only be done at the request of the originator (i.e. you).

If an ACH transfer is returned, its status will be returned. All returned ACH transactions will have an ACH return code. By reading the code, you can troubleshoot returned transactions. For a full list of ACH return codes, see ACH Return Codes.

Return CodeDescriptionNotesTroubleshooting
R01Insufficient fundsAvailable balance is not sufficient to cover the dollar amount of the debit entry.If you are submitting the transfer on a Friday, we recommend using Same-Day ACH to decrease the likelihood of the user's account balance dipping below the transfer amount over the weekend.
R03No account or unable to locate accountThe account number structure is valid, but the account number does not correspond to an existing account, or the name on the transaction does not match the name on the account.Prompt the user to link another account via Plaid Link and use this newly linked account to create the transfer.
R09Uncollected fundsAvailable balance is sufficient, but the collected balance is not sufficient to cover the entryRetry the transaction a few days later after any large "holds" on the user's account have been released.
R10Customer advises not authorizedMember advises not authorized, notice not provided, improper source document, or amount of entry not accurately obtained from source document.Make sure you add proper WEB debit authorization language to your "pay with bank" UX to protect against exposure of returns of over 60 days. Unlike other ACH return codes, you cannot resubmit a payment after encountering an R10 error.

A returned transfer can be retried up to 2 times. When you try to reprocess a returned transfer, the description field in your /transfer/create request must be "Retry 1" or "Retry 2" to indicate that it's a retry of a previously returned transfer. Note that retries are only allowed for transfers returned as R01 or R09.

RTP Failures

Plaid performs various checks within /transfer/authorization/create to fail upfront and as early as possible if the RTP or FedNow transfer won't succeed. However, due to the asynchronous nature of the RTP and FedNow payment networks, it is still possible for transfers to fail after authorization due to a rejection by the receiving bank or an issue in the payment network. Failures in the real-time networks are fairly rare (<1%), and often indicate that the consumer bank account itself is in an unusable state.

If the RTP transfer failed, the status will be failed and an error code will be present in the return_code transfer property. For the following failure codes, further attempts to use this bank account for payouts via the real-time network are unlikely to succeed. Instead, we recommend that you prompt your user to link a different bank account via Plaid Link.

Return CodeDescriptionNotes
AC03Creditor account is invalidAccount number is not recognized as valid by the receiving bank.
AC04Account closedThe account is closed and no longer active.
AC06Account is blockedReceiving bank has placed a block on the account, for various operational or legal reasons.
E997Timeout clock has expiredThe timeout for processing this transaction was exceeded in the FedNow network. You can safely retry the payment with a different idempotency key.

Error codes

For a list of error codes specific to transfer, and their meaning, see Transfer error codes.

Handling 500 errors in transfer creation

Due to unexpected circumstances, you may rarely encounter a 500 HTTP error when creating a transfer via /transfer/authorization/create or /transfer/create. In this case, it's possible that the authorization or transfer was created successfully, but the response was not received. It is highly recommended to utilize the idempotency_key field in /transfer/authorization/create so that retries in this scenario are safe to perform and will not result in duplicate authorizations. Retrying /transfer/create with the same authorization_id is guaranteed to only ever produce a single transfer.

Whether you retry the request to /transfer/create or not, it's possible that the first request succeeded, and so your integration should be prepared to consume events from /transfer/event/sync that you may not have seen the transfer_id for previously. It is recommended you have a recovery process in place, either by logging these instances for manual review and reconciliation, or automatically reconciling by pulling the transfer details via /transfer/get and using the transfer.metadata property to utilize any client-side data you attached to the transfer for reference. Another way to determine if a transfer creation succeeded after receiving a 500 error from /transfer/create is to follow up with a call to /transfer/get using the authorization_id you received from /transfer/authorization/create. If the transfer was actually created, you will receive a successful response containing the transfer details. If it wasn't, you will receive a 404 HTTP error with the NOT_FOUND error code.

Was this helpful?
Developer community
GitHub
GitHub
Stack Overflow
Stack Overflow
YouTube
YouTube
Discord
Discord