GuidesRecipesAPI ReferenceChangelog
Guides

Add Customer External Bank Accounts

How do I connect a customer's bank account using Plaid?

Overview

Connect customer bank accounts to the Cybrid Platform using one of two Plaid-based approaches:

  • Option 1: Plaid Link (Cybrid) — Cybrid generates a Plaid Link token; you drive the Plaid Link SDK in your application. Best for the typical embedded experience with no Plaid account of your own.
  • Option 2: Plaid Processor Token (Partner) — You own the Plaid account and generate a processor token in your Plaid integration, then submit it to Cybrid. Best when you already have a Plaid integration and want full control over the Plaid Link experience.

For a high-level comparison, see Plaid Integration.

Prerequisites

  • An active Cybrid account and API credentials.
  • A customer_guid for the user who will link their bank account. See Create a Customer.
  • For Option 1: a redirect_uri (web) or android_package_name (Android) registered with Cybrid.
  • For Option 2: a Plaid account with the ability to generate processor tokens.
ℹ️

Environments

Examples use the sandbox base URL https://bank.sandbox.cybrid.app. For production, use https://bank.production.cybrid.app.

Option 1: Plaid Link (Cybrid)

Cybrid generates the Plaid Link token. You initialize Plaid Link in your application and submit the resulting public_token back to Cybrid to create the external bank account.

Review the official Plaid Link documentation for up-to-date platform-specific details (Web, iOS, Android, or React Native).

Step 1: Generate a Plaid Link token

Create a workflow with type: plaid and kind: link_token_create. Cybrid asynchronously requests a plaid_link_token from Plaid. Poll the workflow endpoint until the token is available.

ℹ️

Workflow notes

  • The customer_guid is the customer who will link their bank account.
  • All redirect URIs must be registered with Cybrid.
POST /api/workflows
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "type": "plaid",
  "kind": "link_token_create",
  "language": "en",
  "link_customization_name": "default",
  "customer_guid": "customer_guid",
  "redirect_uri": "https://yourapp.com/api/plaid-redirect-uri"
}
{
  "guid": "workflow_guid",
  "bank_guid": "bank_guid",
  "customer_guid": "customer_guid",
  "type": "plaid",
  "state": "storing",
  "failure_code": null,
  "created_at": "2026-01-01T12:00:00.000Z",
  "updated_at": "2026-01-01T12:00:00.000Z"
}

Poll GET /api/workflows/{workflow_guid} until state is completed and plaid_link_token is populated:

{
  "guid": "workflow_guid",
  "bank_guid": "bank_guid",
  "customer_guid": "customer_guid",
  "type": "plaid",
  "state": "completed",
  "failure_code": null,
  "plaid_link_token": "plaid_link_token",
  "created_at": "2026-01-01T12:00:00.000Z",
  "updated_at": "2026-01-01T12:00:05.000Z"
}

Workflow states

StateDescription
storingThe Platform is storing the workflow details in the private store.
completedThe Platform has created the workflow and generated the link token.
failedThe workflow was not completed successfully (check failure_code for details).

OAuth and redirect URIs

Many financial institutions use an OAuth flow, which redirects the customer to their bank's portal for authentication. Register your application's redirect URIs with Cybrid for each environment (sandbox and production). Contact Cybrid support to register your URIs.

For more information, see Plaid's documentation on OAuth redirect URIs.

⚠️

Sandbox redirect URIs

Sandbox only supports HTTPS redirect URIs. Separate registrations are required for sandbox and production environments.

Android apps

For Android applications, register your app's package name (e.g., com.yourcompany.yourapp) with Cybrid in addition to a redirect URI. Use the android_package_name field when creating the Plaid workflow:

POST /api/workflows
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "type": "plaid",
  "kind": "link_token_create",
  "language": "en",
  "link_customization_name": "default",
  "customer_guid": "customer_guid",
  "redirect_uri": "https://yourapp.com/api/plaid-redirect-uri",
  "android_package_name": "com.yourcompany.yourapp"
}

Step 2: Initialize Plaid Link SDK

Use the generated plaid_link_token to initialize the Plaid Link SDK in your client application. The handler below includes callbacks for success, exit, and other events.

const handler = Plaid.create({
  token: 'GENERATED_LINK_TOKEN', // The plaid_link_token from Step 1
  onSuccess: (public_token, metadata) => {
    // A Plaid public_token and account metadata are returned
    // Use these values to create an external bank account in Step 3
    // https://plaid.com/docs/link/web/#onsuccess
  },
  onLoad: () => {},
  onExit: (err, metadata) => {
    // Handle the case where the user exits the flow
    // https://plaid.com/docs/link/web/#onexit
  },
  onEvent: (eventName, metadata) => {
    // Optionally subscribe to events during the Plaid flow
    // https://plaid.com/docs/link/web/#onevent
  },
});
⚠️

Callback logging

Implement clear logging for each callback in your application.

ℹ️

Sandbox environment

In the Cybrid Sandbox, the generated plaid_link_token automatically initializes the Plaid Link SDK in its sandbox mode, so you can test without using real personal information.

Sandbox requires a matching Persona name

Match the customer's Persona-verified name to Plaid's default sandbox identity (Alberta Charleson) before linking the Plaid account. Without a name match, the downstream bank account identity verification does not auto-pass and fails into Persona document submission. See Verify an Individual Customer for the exact values to enter.

Handling callbacks

onSuccess

Fires when the customer successfully links an account. Returns a public_token and a metadata object containing the account id. You use both values in the next step.

ℹ️

One account per workflow

A customer can only link one external bank account per workflow. To link multiple accounts, create a unique workflow for each.

onExit

Fires when the customer leaves the flow without linking an account, with optional err and metadata arguments. To diagnose drop-off causes, log only scrubbed or redacted details or non-sensitive fields such as request IDs, metadata.status, and high-level error codes or messages. Do not persist raw metadata or account/institution details in application logs.

ℹ️

Empty exit metadata

When a returning customer exits during Plaid's SMS verification step — before selecting an institution or entering credentials — metadata.institution is null and metadata.accounts is []. metadata.status may also return "" instead of a step name like choose_device. This is a known Plaid edge case where exit metadata cannot be populated from cached state.

Share error details with Cybrid

When troubleshooting SDK issues, capture and share callback error details — err, request IDs, metadata.status, and high-level error codes — with Cybrid support. These details help diagnose integration issues faster.

Step 3: Create the external bank account

With the public_token and account id (inside the accounts array of metadata) from the onSuccess callback, call POST /api/external_bank_accounts with the Plaid-specific parameters.

POST /api/external_bank_accounts
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "name": "Customer Checking Account",
  "account_kind": "plaid",
  "customer_guid": "customer_guid",
  "asset": "USD",
  "plaid_public_token": "plaid_public_token",
  "plaid_account_id": "plaid_account_id"
}
{
  "guid": "external_bank_account_guid",
  "name": "Customer Checking Account",
  "account_kind": "plaid",
  "customer_guid": "customer_guid",
  "asset": "USD",
  "state": "storing",
  "created_at": "2026-01-01T16:05:40.757Z"
}

For a detailed walkthrough, see the recipe Adding a Customer's Verified External Bank Account.

Option 2: Plaid Processor Token (Partner)

If you have your own Plaid account, generate a Plaid Processor Token in your Plaid integration and submit it to Cybrid. See Plaid's processor token documentation for details on generating tokens; use modern_treasury as the processor value.

Submit the token to Cybrid via POST /api/external_bank_accounts with account_kind: plaid_processor_token:

POST /api/external_bank_accounts
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN

{
  "name": "Customer Checking Account",
  "account_kind": "plaid_processor_token",
  "customer_guid": "customer_guid",
  "asset": "USD",
  "plaid_processor_token": "processor-production-xxxxx-xxxxx",
  "plaid_institution_id": "ins_123456",
  "plaid_account_mask": "0000",
  "plaid_account_name": "Plaid Checking"
}
{
  "guid": "external_bank_account_guid",
  "name": "Customer Checking Account",
  "account_kind": "plaid_processor_token",
  "customer_guid": "customer_guid",
  "asset": "USD",
  "plaid_institution_id": "ins_123456",
  "plaid_account_mask": "0000",
  "plaid_account_name": "Plaid Checking",
  "state": "storing",
  "created_at": "2026-01-01T16:05:40.757Z"
}

Payment rail routing

ℹ️

ACH vs. wire routing

When a bank account is linked via Plaid, the ABA routing number is captured and stored. When initiating a transfer, specify the payment_rail parameter (ach or wire) to process the payment using the appropriate routing. Some US banks have different routing numbers for ACH versus wire transactions. If wire transfers fail due to routing issues with a Plaid-linked account, use the counterparty external bank accounts method to explicitly specify routing details for the intended payment rail.

Refresh expired connections

Plaid bank connections expire periodically and require the customer to re-authenticate. When this happens, the external bank account's state transitions to refresh_required. To restore the connection, follow the steps in Refresh External Bank Accounts.

Next steps