> ## Documentation Index
> Fetch the complete documentation index at: https://docs.grailpay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Validate Bank Accounts

## Overview

Before initiating a transaction or linking a manually entered bank account, it's important to ensure the account and
routing number combination is valid. GrailPay offers a dedicated endpoint that validates these details in real-time to
reduce the risk of failed transactions and ACH returns.

This validation is especially useful during onboarding or when updating a user's financial information, as it helps
ensure the account is active and properly formatted for ACH.

<Note>
  This endpoint only supports manually entered bank accounts. For accounts linked through Bank Link or Plaid,
  validation is handled as part of the linking process.
</Note>

***

## Use Cases

You might use this endpoint when:

* Collecting account details via a custom onboarding form
* Adding a bank account outside the registration flow
* Verifying bank details before submitting a transaction
* Implementing safeguards to reduce return-related fraud
* Performing name matching verification against account holder information

***

## Account Intelligence Versions

The response payload varies depending on which version of account intelligence you select. We recommend using **V3** for the most comprehensive validation insights.

<Warning>
  **V1 Deprecation Notice:** Version 1 account intelligence is deprecated and will be removed in a future release.
  Please migrate to V3 for enhanced decisioning insights.
</Warning>

### Version 3 (Recommended)

V3 provides comprehensive decisioning insights including transaction history, name matching, and duplicate detection.

For complete request and response schema, refer to:

* [Validate Account & Routing V3](https://api.grailpay.com/api/documentation#/Bank%20Accounts/77650b67f45408f8ec5d610ec96239d2)

<Note>
  To enable name matching, set `name_match: true` in the `actions.account_intelligence` object of your request payload.
  When name matching is enabled, the `person` object with `first_name` and `last_name` is required.
  If you are not using name matching, the `person` object is optional.
</Note>

#### V3 Response Fields

To learn more about our V3 Response fields, refer to the [Account Intelligence V3 Documentation](/docs/risk/bank-accounts/account-intelligence).

***

### Version 2

V2 returns a confidence score with a human-readable confidence level.

```json theme={"system"}
{
  "account_intelligence": {
    "confidence_score": 0.81,
    "confidence_level": "very high",
    "version": "v2"
  }
}
```

#### V2 Response Fields

| Field              | Type    | Description                                                                  |
| ------------------ | ------- | ---------------------------------------------------------------------------- |
| `confidence_score` | decimal | Overall confidence score (0.0 - 1.0)                                         |
| `confidence_level` | string  | Human-readable confidence level (e.g., `very high`, `high`, `medium`, `low`) |

***

### Version 1 (Deprecated)

<Warning>
  V1 is deprecated. Please migrate to V3.
</Warning>

V1 returns a simple validity status.

```json theme={"system"}
{
  "account_intelligence": {
    "validity": "valid",
    "version": "v1"
  }
}
```

#### V1 Response Fields

| Field      | Type   | Description                                               |
| ---------- | ------ | --------------------------------------------------------- |
| `validity` | string | Validation result: `valid`, `invalid`, or `not_validated` |

***

## Testing

You can test the validation endpoint in our [Sandbox Environment](/docs/technical/sandbox). Use the following test routing numbers to simulate different
validation outcomes when choosing v3 as the Account Intelligence version in the actions object of your request payload:

<CodeGroup>
  ```json Low Risk ( valid account with name match ) theme={"system"}
  {
      "account_number": "1234567890",
      "routing_number": "000000001"
  }
  ```

  ```json Medium Risk ( name match not available ) theme={"system"}
  {
      "account_number": "1234567890",
      "routing_number": "000000002"
  }
  ```

  ```json High Risk ( negative history ) theme={"system"}
  {
      "account_number": "1234567890",
      "routing_number": "000000003"
  }
  ```

  ```json Simulates 503 error (service unavailable) theme={"system"}
  {
      "account_number": "1234567890",
      "routing_number": "999999999"
  }
  ```
</CodeGroup>

### Version 2 Testing

When using `v2` as the Account Intelligence version in the `actions` object of your request payload, the same routing
numbers can be used to simulate different validation outcomes. Version 2 responses include a confidence score and
confidence level, but do not include the detailed insights provided in Version 3.

* `000000001` — High confidence score (e.g., 0.81) with a confidence level of `very_high`
* `000000002` — Medium confidence score (e.g., 0.65) with a confidence level of `medium`
* `000000003` — Low confidence score (e.g., 0.30) with a confidence level of `low`

### Version 1 Testing

When using `v1` as the Account Intelligence version in the `actions` object of your request payload, the same routing
numbers can be used to simulate different validation outcomes. Version 1 responses only indicate whether the account
is `valid`, `invalid`, or `not_validated` — no confidence score or level is provided.

* `000000001` — Returns `valid`
* `000000002` — Returns `invalid`
* `000000003` — Returns `not_validated`

***

## Next Steps

After successful validation, you can proceed to [Add the Bank Account](/docs/technical/bank-accounts/add-bank-account)
to the user profile, or use the validated details to initiate a transaction.

For complete request and response schema, refer to:

* [Validate Account & Routing V3](https://api.grailpay.com/api/documentation#/Bank%20Accounts/77650b67f45408f8ec5d610ec96239d2)

***
