Virtual account deposit not received? Why deposits get delayed, held, or returned

Why a virtual account deposit is late, on hold, or returned: arrival windows, payin statuses, RFIs, wrong rails, and how to trace a wire or SWIFT payment.

A virtual account deposit that hasn't shown up is usually one of four things: it's still inside the rail's settlement window, it's held for compliance review, a bank returned it because the details didn't match, or the payer used a rail the account doesn't accept. The deposit's status and the payer's bank reference tell you which one.

Start with the status, not the support ticket.

Key takeaways

  • ACH and wire deposits can take up to 5 business days, and anything sent after the cut-off starts counting from the next business day.
  • A deposit on_hold is waiting on compliance review. Answer the request for information the same day: an unanswered hold can end in a refund to the sender.
  • Returns usually trace back to details that don't match: a wrong account number, a beneficiary name that isn't the account holder, or a closed account.
  • A US virtual account takes USD over ACH, wire, and SWIFT. Not SEPA, not Pix, and at BlindPay, not RTP.
  • To find a missing wire, ask the payer for the bank reference: the IMAD for a domestic wire, the UETR for SWIFT.

What usually goes wrong with a virtual account deposit?

Most missing deposits fit one of eight patterns, and each has a different fix. Match the symptom first, then act.

SymptomLikely causeWhat to do
Payer sent it today, nothing showsStill in the settlement window, or sent after the cut-offWait out the rail's window before escalating
Nothing after 5 business daysWrong account or routing number, or the transfer never left the payer's bankAsk the payer for the bank reference and trace it
Deposit shows as on_holdFlagged for compliance reviewWatch for a request for information and answer it within 24 hours
Deposit shows as refundedReturned to the sender after a mismatch or an unanswered holdFind the reason, fix it, ask the payer to resend
Less money arrived than was sentIntermediary or receiving bank fees on a wire or SWIFT paymentReconcile it as a bank fee, not an underpayment
Foreign payer asks for an IBANUS virtual accounts have no IBANSend the SWIFT details and ask for USD
Payer sent an instant RTP paymentRTP isn't a rail into a BlindPay virtual accountAsk for ACH or wire, or use an RTP payin's own instructions
A $0.01 deposit appearsA platform verifying the account with a micro-depositReconcile it, it's expected

New to the account itself? Start with what is a virtual account.

Why hasn't the deposit arrived yet?

Most of the time, it's still on the rail. Bank transfers settle on business days, every rail has a daily cut-off, and a transfer sent after the cut-off is processed the next business day. Weekends, US federal holidays, and international banking holidays don't count.

These are the network windows from BlindPay's cut-off times reference:

RailCut-off (ET)Typical network settlement
ACH9:00 PM1 to 3 business days
Same-Day ACH3:00 PMSame business day
Domestic wire3:00 PMSame business day
International SWIFT10:30 AMUp to 5 business days

Those are network times, not end-to-end ETAs. For ACH and wire deposits, BlindPay's own arrival window is up to 5 business days (payins). A SWIFT payment sent at 4:00 PM ET on the Friday before a US holiday can lose several calendar days before anyone has a reason to worry.

Check the payer's side too. Banks cap daily ACH and wire amounts, and a transfer over the cap can sit at the sending bank waiting for approval. From your side, that looks like a slow rail.

Rule of thumb: don't open a trace until the rail's full window has passed. Until then, the most useful thing your product can show is an expected arrival date.

Which statuses will a virtual account deposit go through?

Every deposit into a BlindPay virtual account creates a payin, and the payin's status tells you where the money is. There are five statuses, and three of them are final. Because the deposit itself creates the payin, no payin at all usually means the money hasn't reached the account.

StatusWhat it meansFinal?What to show your customer
processingThe deposit is arriving, or stablecoins are being converted and sentNo"Payment received, processing"
on_holdHeld for manual risk or compliance reviewNo"Under review, we may ask for details"
completedStablecoins delivered to the linked walletYes"Funds available"
failedThe payin didn't go throughYes"Payment failed" plus the next step
refundedThe deposit went back to the senderYes"Returned to sender" plus the reason

For a finer view, each tracking_* object on the payin has its own step: processing, on_hold, pending_review, pending_refund_review, or completed. tracking_transaction covers the fiat leg and carries a separate status that stays null until the bank side resolves to completed or failed.

The webhooks follow the same shape. payin.new fires when the deposit creates the payin, payin.update fires on intermediate steps like an arrival check or a manual review, and payin.complete fires when the payin is sent, refunded, or failed. So payin.complete doesn't mean success. Read the status (webhook events). Signature checks and duplicate handling are in stablecoin API webhooks.

Why is a deposit on hold?

A deposit lands on_hold when transaction monitoring flags it for manual review. It's a pause, not a rejection: if compliance clears it, the payin continues and the stablecoins go out.

The triggers BlindPay lists include unusual activity patterns, amounts that are large compared with the customer's history, sanctions or watchlist screening matches, and an open request for information on the customer (compliance holds).

If the flag can't be cleared internally, BlindPay emails your team (or sends a Slack message) with a request for information, or RFI. It asks for the relationship between the sender and your customer, the purpose of the payment, and the expected outcome. Per on-hold transactions, if the RFI isn't answered within 24 hours, the transaction may be refunded to the sender. A hold can last up to 30 days, and a timeout without a decision fails the transaction.

Don't mix this up with a customer-level RFI. When KYC or KYB review needs more documents, the customer moves to compliance_request, can't send or receive funds until it's resolved, and gets 27 days to respond (information requests). Different trigger, different clock.

The best prevention is boring: keep an invoice or contract on file for each large payer, and make sure the business description from onboarding matches what flows through the account. Virtual account requirements covers what the review looks at.

Why do deposits get returned to the sender?

A deposit comes back when a bank in the chain or the compliance review can't accept it. The usual reasons are wrong details, a name mismatch, a closed or restricted account, unmet compliance requirements, or a rail the account doesn't take.

  • Wrong account or routing number. ACH returns carry a reason code: R03 means the receiving bank couldn't locate the account, R04 means the account number is invalid, R02 means it's closed. A wire with a bad account number comes back the same way, just slower.
  • Beneficiary name doesn't match. A named virtual account is in your customer's name. The payer should use that exact name as the beneficiary, not your platform's brand or a trading nickname. Receiving banks can reject wires where the name and the account don't line up.
  • The account isn't live, or isn't anymore. A BlindPay virtual account has no rail numbers until it's approved, so any details a payer has from before approval are wrong. Payments to an account that's closed or restricted fail or get refunded.
  • Compliance requirements aren't met. This includes the hold from the section above where nobody answered the RFI.
  • The payer used a rail the account doesn't take. RTP isn't one: at BlindPay, no virtual account carries an RTP rail, and an rtp payin always uses the shared memo-code account. SEPA needs an IBAN, which a US account doesn't have. SWIFT works, but only once the account is approved, since there's no memo-code fallback for SWIFT (payins).

When a deposit is refunded, the money goes back to the sender, not to the wallet. Fiat refunds reach the payer once the banking network returns the funds, which depends on each bank's processing time, and fees may apply. Your customer's client can get back less than they sent.

How do you trace a missing wire or SWIFT payment?

Trace with the payer's bank reference, not the amount. Every rail has one, and it's the only thing a bank's operations team can search by.

  1. Confirm the window has passed. Up to 5 business days for ACH, wire, and SWIFT, counted from the first business day after the cut-off.
  2. Check the details against the right rail. The account object carries separate ACH and wire details. A payer who copied the ACH numbers into a wire form, or the reverse, may have sent the money somewhere else.
  3. Get the reference. For ACH, the 15-digit trace number. For a domestic wire, the Fedwire IMAD (Input Message Accountability Data). For SWIFT, the UETR, a 36-character reference that follows a payment end to end.
  4. Ask for the MT103 on SWIFT payments. It shows the beneficiary name (field 59), the amount and currency, the charge code (field 71A: OUR, SHA, or BEN), and the intermediary banks.
  5. Have the payer's bank trace it. With the UETR, the sending bank can see which bank in the chain is holding the payment and why.
  6. Send everything to your provider. Include the virtual account id, the expected amount, the date sent, and the reference.
  7. If it was returned, resend with corrected details once the return has credited the payer.

Where the days go on a SWIFT payment, hop by hop, is in why are cross-border payments slow.

What does a held SWIFT deposit look like, start to finish?

Here's one deposit through two endings. Amounts and timings are illustrative, not quotes.

Setup. A client in Germany pays a 4,800 USD invoice to your customer's US virtual account by SWIFT, with the SHA charge option.

  1. Day 0. The client's bank sends the payment late in the afternoon, so it starts moving the next business day.
  2. Day 3. An intermediary bank deducts 30 USD. 4,770 USD lands on the virtual account. The payin is created (payin.new) and moves to processing.
  3. Day 3, an hour later. Monitoring flags it: first payment from this sender, and about four times the customer's usual deposit. The payin goes on_hold (payin.update), and your team gets an RFI email.

Ending A: you answer the same day. You send the invoice and the service contract. Compliance releases the hold, the 4,770 USD converts to USDC, and because the deposit is over $100, BlindPay's fee is deducted from the delivered amount at transaction time (transaction_fee_amount). payin.complete arrives with status completed. Your ledger books 4,800 invoiced, 30 bank fee, the BlindPay fee, and the net USDC received. Done.

Ending B: nobody answers for 24 hours. The transaction may be refunded. The payin ends refunded, and the 4,770 USD travels back through the banking network, possibly minus more fees. The client gets a partial refund days later and has to pay again. Same money, two weeks lost.

The difference between the two endings is one email. Put RFIs on someone's on-call rota.

How each fee in that chain works, including where the BlindPay fee lands below and above $100, is in virtual account fees.

Where does BlindPay fit?

BlindPay issues US virtual accounts in your customer's own name. They receive ACH, wire, and SWIFT, depending on the account type, and every deposit converts to USDC or USDT and settles to the wallet linked to the account. The account doesn't hold a balance. The money ends up in the wallet.

Each deposit is a payin with a status, tracking steps, and payin.* webhooks, so "where is my money" has an API answer. Holds come with an RFI to your team.

What it doesn't do: IBANs, SEPA, or RTP into the dedicated account. If your payers are in Europe, they pay by SWIFT in USD. The full account behavior is in virtual accounts, and the flow from bank deposit to wallet is in accept bank transfers and settle in stablecoins.

What to do next

Map all five payin statuses to customer-facing messages, and name an owner for on_hold RFIs, before your next account goes live. Then build the failure screens on a development instance: a payin with a request_amount of $666.00 forces failed, and $777.00 forces refunded. You'll see both in production eventually. Better to see them first in a sandbox.

This article is for general information only and is not legal, tax, or financial advice.

FAQ