Skip to main content
Bank connection flows are the hardest part of a payments integration to test. Your application has to handle OAuth redirects that leave and re-enter your page, credential logins with several kinds of MFA challenges, connection errors, and users who skip bank login entirely and type in their account details. None of that is practical to test against a real bank. The Straddle sandbox solves this with a family of test institutions called FinBank. Each one exercises a different connection path with published credentials, so you can walk every branch of your integration, including the failure branches, without real bank credentials.
This guide covers the bank connection paths inside the Bridge widget. To simulate charge, payout, and return outcomes after a connection is made, see sandbox simulations for Pay by Bank.

Before you start

Make sure you have:
  • A sandbox account and API key
  • A customer created in the sandbox
  • The Bridge widget on your page, with mode="sandbox" on the <straddle-bridge> element
  • A Bridge token from POST /v1/bridge/sessions, sent to https://sandbox.straddle.com

Set a redirect URL for OAuth

OAuth connections send the user to a bank-hosted page and back again, so the widget needs somewhere to return to. Pass redirect_url when you create the bridge token:
The URL must be an absolute https URL. You don’t need to pre-register it with Straddle or with the bank. redirect_url is required. If you omit it, POST /v1/bridge/sessions returns a validation error and Straddle doesn’t create the token.

Choose a test institution

Search for the institution by name in the widget’s bank search, the same way a real user would. These two are the institutions Straddle tests against, and every scenario in this guide is written for them. Bank search also returns other FinBank variants, which exist to test products outside the scope of a paykey. If you select one and the connection fails with Institution is not available for connection., that institution does not expose the account ownership and balance data Straddle needs, and the fix is to pick one of the two above.

Test credentials

FinBank has two separate families of test credentials, and mixing them up is the second most common cause of a failed sandbox test. Authentication profiles test sign-in behavior: success, errors, and MFA challenges. The password is always go, except when you are triggering a specific error code, where the password is the code. These work at either supported institution. Other password values for demo fail as ordinary invalid credentials rather than producing an institution error. Account profiles test what the connection returns: account types, owner names, and balances. Here the username and password are the same value, the profile id itself. The account holder name is what Straddle matches against your customer’s name, so these are the profiles to use when you are testing verification outcomes rather than sign-in behavior.

Test the OAuth flow

Finbank OAuth requires registration before its profiles will accept a sign-in. If OAuth sign-ins fail for every profile, contact Straddle support before debugging your integration.
  1. Create a bridge token with a redirect_url.
  2. In the widget, search for Finbank OAuth and select it.
  3. Complete the bank-hosted login with an account profile, for example profile_02 / profile_02.
  4. Approve the connection and return to the widget.
When the redirect returns, the widget resumes at account selection without restarting the session. After the user selects an account, Straddle creates a paykey and fires a paykey.created.v1 webhook.

Test the credential login flow

Search for FinBank Profiles - A and sign in with one of the profiles above. The widget shows the login fields inside Bridge, but the username and password never reach Straddle. You are testing your handling of the form, the challenges, and the error states. Use an authentication profile when you are testing the form itself, and an account profile when you want a particular set of accounts or a particular account holder name.

MFA challenges

Each tfa_ profile presents a different challenge type. Two of them recognize a special answer that changes what happens next; the rest accept anything.

Connection errors

On any error, and on a canceled login, the widget shows a retry option and no paykey is created. Your application should not receive a paykey callback in these cases.

Test manual entry

Choose manual entry in the widget and provide a routing and account number. The paykey is created synchronously with source bank_account. The routing number must be nine digits and pass the ABA checksum, so an arbitrary number is rejected. Use a real routing number for testing, for example 021000021 (JPMorgan Chase). The account number must be 8 to 12 digits. With routing number 021000021 and an account number such as 5550193847, Straddle creates the paykey with status active. Don’t use 123456789: the sandbox treats it as a rejection number, even though it’s in that range. Manual paykeys carry no balance. Verification still runs and still weighs the account holder against your customer, but because the bank returns no owner data on this path, the result carries no names on the account, no matched name, and no correlation score. You get the decision without the evidence behind it. There is no micro-deposit verification step. A valid manual entry creates the paykey immediately, with nothing for the user to confirm later.

Test name matching

Straddle compares the account holder name the bank returns against your customer’s name, and that comparison decides whether the paykey activates or goes to review. A paykey from a bank login goes to review only when the names don’t match, so the way to test review is to connect a profile whose holder name differs from your customer’s name. These profiles return a known holder name: Use the customer’s name to pick the outcome:

Trigger the review scenario

To put a bank-login paykey into review, follow these steps:
  1. Create a customer whose name doesn’t match the profile’s holder name, for example "name": "Homer Smith".
  2. Create a bridge token for that customer. Leave sandbox_outcome unset, or set it to standard, so that the name comparison decides the outcome.
  3. In the widget, search for FinBank Profiles - A and sign in with profile_02 / profile_02.
  4. Select the savings account and select Link account. The widget ends on Account details received instead of Account linked, and your application receives the paykey with status review, reason require_review, and source watchtower.
  5. Create a charge against the paykey. The charge goes to on_hold with reason risk_review until the review is decided.
  6. Retrieve the review with GET /v1/paykeys/{id}/review. The verification_details.breakdown.name_match object shows names_on_account, matched_name, customer_name, and correlation_score, so you can test how your application presents the evidence behind a review.
  7. Decide the review with PATCH /v1/paykeys/{id}/review, using {"status": "active"} to approve or {"status": "rejected"} to reject. Approving activates the paykey and releases the held charge without a separate release call. Both decisions fire a paykey.event.v1 webhook.
The review data comes from the bank’s real holder names. To see how your application handles a review with no matching evidence at all, connect the same profile with a customer whose name shares nothing with it, such as Jess Sea.

Force a specific paykey outcome

To skip the name comparison and force a paykey to active or rejected, set sandbox_outcome in the config object. For the widget paths, set sandbox_outcome on the bridge token. Every paykey created in that widget session inherits it:
For manual entry, set sandbox_outcome in the POST /v1/bridge/bank_account request instead. Bridge tokens don’t support review, because a bank-login paykey goes to review only on a name mismatch. To test review on the widget paths, trigger the review scenario with a mismatched customer name instead. That way the review carries the bank’s real holder names. A forced outcome skips the name comparison, so the paykey’s review data shows placeholder names, not the names the bank returned. Outside the sandbox, the API rejects sandbox_outcome as invalid.

Test account balances

FinBank Profiles - A returns a fixed balance per profile, so you can test balance checks against a known figure rather than whatever a test account happens to hold. Use profile_1151 to test a charge that exceeds the available balance, and profile_1153 for an account already overdrawn. To test a balance the bank refuses to return, sign in as tfa_multi / go and connect the savings or checking account. Balance retrieval fails with error 185. Your integration should treat the missing balance as unknown rather than as zero. Balances are cached for up to an hour. Refreshing a paykey inside that window returns the same figure and makes no new call to the bank, so a balance that looks stale during testing is usually the cache rather than a bug. Manual entry paykeys have no balance at all. A charge against one with balance checks set to required ends with status failed and reason insufficient_funds, because Straddle can’t retrieve a balance for the account.

What to verify

However the bank was connected, verify the same things on your side:
  • Source. Paykeys created through the widget’s bank login paths have source straddle. Manual entry paykeys have source bank_account.
  • Webhooks. A successful connection fires paykey.created.v1. Status changes fire their own events, so your handlers should process the full paykey lifecycle.
  • Name matching. When the bank-returned account owner matches the customer’s name, the paykey activates. A mismatch places it in review, and Straddle holds payments against it until the review is decided. Approving the review activates the paykey and releases held charges. Rejecting it moves the paykey to rejected and fires a webhook. On the bank login paths the review shows the names on the account and a correlation score; on manual entry it shows the decision alone.
  • Balance checks. Test the low-balance and retrieval-failure accounts with balance checks set to enabled and to required.