GuidesRecipesAPI ReferenceChangelog
Guides

Verify External Bank Accounts

How do I create a bank account identity verification?

Overview

Verify external bank account ownership against a customer's KYC information. For general identity verification concepts, states, and return codes, see Identity Verification.

What is a bank account identity verification?

To process transfers on the Cybrid Platform, the customer connecting the external bank account must own that account and have completed KYC. The bank account identity verification confirms that the name on the external bank account matches the name provided during KYC.

Required

Bank account identity verifications are required before creating transfers on the Cybrid Platform.

ℹ️

Scope

Bank account verifications are currently only required for individual customers, not business customers.

Creating a bank account identity verification

Prerequisites:

  • The individual customer state is verified (the customer has completed KYC).
  • The external bank account state is unverified (created but not yet verified).

With these prerequisites met, create a bank account identity verification via POST /api/identity_verifications (API reference). The verification method depends on which Plaid integration you used to link the account (see Add Customer External Bank Accounts):

OptionPlaid account ownerVerificationRequired account_kind
Option 1: Plaid Link verificationCybridmethod: account_ownershipplaid
Option 2: Plaid Processor Token verificationPartnermethod: attested_ownershipplaid_processor_token
⚠️

Wait for unverified state

Do not attempt to create a bank account identity verification while the external bank account is in the storing state. Poll GET /api/external_bank_accounts/{external_bank_account_guid} and wait until the state transitions to unverified before proceeding. Attempting verification while in storing returns a 422 Invalid bank account to verify error. If the account remains in storing for an extended period, contact support with the latest response details.

Option 1: Plaid Link verification (account_ownership)

When the external bank account was created with Cybrid's Plaid integration (account_kind: plaid), create the identity verification with type: bank_account and method: account_ownership.

The account_ownership method does not require additional customer details because the information is verified against the Plaid-connected bank account.

{
  "type": "bank_account",
  "method": "account_ownership",
  "customer_guid": "customer_guid",
  "external_bank_account_guid": "external_bank_account_guid"
}

Option 2: Plaid Processor Token verification (attested_ownership)

When the external bank account was created with your own Plaid integration (account_kind: plaid_processor_token), create the identity verification with type: bank_account and method: attested_ownership.

The attested_ownership method requires you to provide the customer's name. You can retrieve this from the Plaid Identity API.

{
  "type": "bank_account",
  "method": "attested_ownership",
  "name": {
    "first": "John",
    "last": "Doe",
    "full": "John Doe"
  },
  "customer_guid": "customer_guid",
  "external_bank_account_guid": "external_bank_account_guid"
}
ℹ️

Optional address fields

The address object is optional for attested_ownership. When provided, only street, city, and country_code are required by the API. The subdivision and postal_code fields are always optional; include postal_code only for countries that use postal, zip, or post codes.

If you choose to include the address, pass it alongside the name block:

{
  "type": "bank_account",
  "method": "attested_ownership",
  "name": {
    "first": "John",
    "last": "Doe",
    "full": "John Doe"
  },
  "address": {
    "street": "123 Main St",
    "city": "New York",
    "subdivision": "NY",
    "postal_code": "10001",
    "country_code": "US"
  },
  "customer_guid": "customer_guid",
  "external_bank_account_guid": "external_bank_account_guid"
}

Checking verification state

After creating a bank account identity verification, check the state and outcome using GET /api/identity_verifications/{identity_verification_guid} (API reference).

Waiting state

All bank account identity verifications progress immediately from storing to waiting.

When auto-approved or auto-rejected:

  • The verification progresses from waiting to completed (see Completed state below).

When neither auto-approved nor auto-rejected:

  • The verification remains in waiting.
  • A Persona document submission inquiry is automatically created for the customer to provide a supplementary document.
  • Use GET /api/identity_verifications/{identity_verification_guid} (API reference) to retrieve the persona_inquiry_id.
  • Share the Persona URL with the persona_inquiry_id directly with the customer (e.g., https://withpersona.com/verify?inquiry-id=<persona_inquiry_id>).
    • Alternatively, use the persona_inquiry_id and the Persona SDK to integrate the supplementary document upload into your application. See Verify with Persona SDK.
    • The Cybrid web SDK does not support bank account identity verifications.
  • The customer must upload a bank statement with the following information:
    • Date of the statement (must be within the last 90 days)
    • Customer name
    • Customer address
    • Bank account number
    • Bank name and logo
  • If the customer takes no action, the verification remains in waiting for up to 24 hours before expiring.
❗️

Bank statement requirements

Only the first page of the bank statement is required. Transactional data may be redacted or blurred.

Pending state

When the customer browses to the Persona URL:

  • The verification progresses from waiting to pending.
  • If the customer takes no further action, the verification remains in pending for up to 24 hours before expiring.

Reviewing state

When the customer uploads the supplementary document via the Persona URL:

  • The verification progresses from pending to reviewing.
  • The Cybrid team is notified that the document has been uploaded.
  • The verification remains in reviewing until the Cybrid team determines the outcome (passed or failed).

Completed state

When auto-approved or auto-rejected, the verification progresses immediately from waiting to completed.

Passed outcome

When auto-approved, or approved by the Cybrid team while in reviewing:

  • The verification progresses to completed with a passed outcome.

Success

When outcome is passed, the verification is complete and the external bank account progresses to state: verified.

Failed outcome

When auto-rejected, or rejected by the Cybrid team while in reviewing, the verification progresses to completed with a failed outcome. The failure_codes array returns one of:

  • name_check_failure -- The KYC name does not match the name on the bank account.
  • address_check_failure -- The KYC address does not match the address on the bank account.
  • phone_number_check_failure -- The KYC phone number does not match. This does not prevent passing.
  • email_address_check_failure -- The KYC email address does not match. This does not prevent passing.
  • decision_timeout -- The verification timed out.

The external bank account remains unverified until a successful verification completes.

❗️

Failure

When outcome is failed, create a new bank account identity verification to retry.

Expired state

When the verification remains in waiting for 24 hours:

  • The Persona document submission inquiry link expires and can no longer accept uploads.
  • The verification progresses to expired.

The external bank account remains unverified until a successful verification completes.

❗️

Expiration

When state is expired, the verification did not complete. Create a new bank account identity verification to retry.

Sandbox testing with expected_behaviours

In the sandbox environment, include the expected_behaviours field in the POST /api/identity_verifications request body to control the outcome of bank account verification without completing the full verification flow.

Test the natural verification flow

To exercise the account_ownership path in sandbox without expected_behaviours, match the customer's Persona-verified name to Plaid's default sandbox identity (Alberta Charleson). See Verify an Individual Customer and Plaid: Testing identity.

ValueDescription
passed_immediatelyThe verification completes immediately with a passed outcome.
failed_immediatelyThe verification completes immediately with a failed outcome.
tax_id_not_checkedThe tax ID check is skipped during verification.

Example POST /api/identity_verifications request body using expected_behaviours:

{
  "type": "bank_account",
  "method": "account_ownership",
  "customer_guid": "customer_guid",
  "external_bank_account_guid": "external_bank_account_guid",
  "expected_behaviours": ["passed_immediately"]
}
❗️

Sandbox only

The expected_behaviours field is not permitted in production. Submitting it in a production request returns a 400 error: Parameter expected_behaviours not permitted in production.

Troubleshooting 422 errors

A 422 response with Invalid bank account to verify indicates the external bank account is not eligible for verification, not a payload formatting issue. Common causes:

  • The external bank account state is not unverified (most common).
  • The account_kind does not match the verification method:
    • account_ownership requires account_kind: plaid.
    • attested_ownership requires account_kind: plaid_processor_token.
  • The external bank account does not belong to the provided customer_guid.
  • The Plaid account does not return identity data (for example, missing or mismatched name).
ℹ️

Eligibility checks

The expected_behaviours: ["passed_immediately"] value does not bypass eligibility checks. It only controls the outcome of an otherwise valid verification.

Diagnostic steps

  1. Fetch the account using GET /api/external_bank_accounts/{external_bank_account_guid}.
  2. Confirm state is unverified, customer_guid matches, and account_kind is plaid or plaid_processor_token as expected.
  3. If all checks pass, review the Plaid identity data on the account for completeness.