GuidesRecipesAPI ReferenceChangelog
Guides

Add Customer External Bank Accounts

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