Add Customer External Bank Accounts
How do I connect a customer's bank account using Plaid Link?
Overview
Connect customer bank accounts to the Cybrid platform using Plaid Link. This secure front-end SDK allows customers to authenticate with their financial institution and link their accounts for funding and withdrawal operations.
We strongly recommend reviewing the official Plaid Link documentation for the most up-to-date details for your specific platform (Web, iOS, Android, or React Native).
Prerequisites
- You have an active Cybrid account and API keys.
- You have created a
customer_guidfor the user who will be linking their bank account. See our guide on creating a customer.
Step 1: Generate a Plaid Link Token
First, generate a plaid_link_token by creating a workflow.
This token is used to initialize the Plaid Link SDK in the next step.
Create a workflow with the type set to plaid and the kind to link_token_create. The Cybrid API will then
asynchronously request a plaid_link_token from Plaid. You must poll the workflow endpoint using the returned
workflow_guid until the plaid_link_token becomes available.
Workflow Notes
- Ensure that the
customer_guidprovided is associated with theexternal_bank_account_guid- 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": "2025-01-01T12:00:00.000Z",
"updated_at": "2025-01-01T12:00:00.000Z"
}Poll GET /api/workflows/{workflow_guid}, until the state is completed and the 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": "2025-01-01T12:00:00.000Z",
"updated_at": "2025-01-01T12:00:05.000Z"
}Workflow States
| State | Description |
|---|---|
storing | The Platform is storing the workflow details in the private store |
completed | The Platform has created the workflow and generated the link token |
failed | The 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. You must 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.
Step 2: Initialize Plaid Link SDK
Use the generated plaid_link_token to initialize the Plaid Link SDK on your client-side application. The handler
below includes callbacks for success, exit events, 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 LoggingWe recommend implementing clear logging for each callback in your application
Handling the onSuccess Callback
onSuccess CallbackThe onSuccess callback is triggered when the customer successfully links an account. It returns a public_token and
metadata object containing the account id. You will use both of these in the next step.
One Account per WorkflowA customer can only link one external bank account per workflow. To link multiple accounts, you must create a unique workflow for each one.
Step 3: Create an External Bank Account
With the public_token and account id (inside accounts object) from the onSuccess callback, you can now
create an external bank account on the Cybrid platform.
Call the POST /api/external_bank_accounts endpoint with the Plaid-specific parameters.
POST /api/external_bank_accounts
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
{
"name": "External Bank Account Name",
"account_kind": "plaid",
"customer_guid": "{customer_guid}",
"asset": "USD",
"plaid_public_token": "{plaid_public_token}",
"plaid_account_id": "{plaid_account_id}"
}For a detailed walkthrough, see our recipe for adding a customer's verified external bank account.
Payment Rail RoutingWhen a bank account is linked via Plaid, the ABA routing number is captured and stored. When initiating a transfer, specify the
payment_railparameter (achorwire) to process the payment using the appropriate routing. Note that some US banks have different routing numbers for ACH vs wire transactions. If wire transfers fail due to routing issues with a Plaid-linked account, you may need to use the counterparty external bank accounts method to explicitly specify routing details for the intended payment rail.
FBO Account LimitationsIf a bank account is opened for a customer via Cybrid (such as an FBO account), the customer cannot be provided with online banking credentials to link that account to other platforms via Plaid. Only accounts where the customer has their own online banking access can be linked via Plaid Link.
Handling Plaid Link Updates (Update Mode)
Bank connections can expire, requiring the customer to re-authenticate with their financial institution. When this
happens, the external bank account's state will change to refresh_required.
From GET /api/external_bank_accounts/{guid}
{
"guid": "{external_bank_account_guid}",
"name": "My Checking Account",
"asset": "USD",
"account_kind": "plaid",
"bank_guid": "{bank_guid}",
"customer_guid": "{customer_guid}",
"state": "refresh_required",
"failure_code": null,
"created_at": "2024-12-15T10:30:00.000Z",
"updated_at": "2025-01-01T12:00:00.000Z"
}
Transactions DisabledNo transactions can be performed with an external bank account in the
refresh_requiredstate.
To resolve this, you must guide the customer through Plaid's Update Mode:
- Detect the
refresh_requiredstate by pollingGET /api/external_bank_accounts/{external_bank_account_guid}and checking thestatefield. - Create a workflow with
POST /api/workflowsusingkind: "link_token_update"and theexternal_bank_account_guidthat needs to be refreshed, and read theplaid_link_tokenfrom the response. - Initialize Plaid Link with the
plaid_link_tokenin update mode. - The customer re-authenticates with their financial institution through the Plaid Link flow.
- Update the external bank account state by calling
PATCH /api/external_bank_accounts/{external_bank_account_guid}withstateset tocompleted.
Manual State Update RequiredThe platform does not automatically update the external bank account state after the customer re-authenticates. Your application must explicitly call
PATCH /api/external_bank_accounts/{external_bank_account_guid}with{ "state": "completed" }to transition the account out of therefresh_requiredstate.
POST /api/workflows
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
{
"type": "plaid",
"kind": "link_token_update",
"language": "en",
"link_customization_name": "default",
"external_bank_account_guid": "{external_bank_account_guid}",
"redirect_uri": "https://yourapp.com/api/plaid-redirect-uri"
}After the customer completes the Plaid Link update flow, call the patch external bank account endpoint to finalize the refresh:
PATCH /api/external_bank_accounts/{external_bank_account_guid}
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
{
"state": "completed"
}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.
To test the full update mode flow, you can force an external bank account into the refresh_required state using the
patch external bank account endpoint:
PATCH /api/external_bank_accounts/{external_bank_account_guid}
Content-Type: application/json
Authorization: Bearer YOUR_TOKEN
{
"state": "refresh_required"
}This allows you to simulate an expired bank connection and verify your application handles the update mode flow correctly.
Updated 11 days ago
