Overview

The Account Intelligence V3 endpoint is part of GrailPay’s broader Account Intelligence system. It helps assess whether a user’s bank account is valid, active, and safe to use. With a single API call, the endpoint returns a confidence_score along with key insights based on the account and identity data you provide. This enables your team to make smarter, risk-informed decisions during onboarding, funding, and payout processes — enhancing safety, reducing fraud, and improving overall user experience. In the request payload, you’ll find an identity object that supports two mutually exclusive options: individual or organization. Use the organization object when validating business-related information, and the individual object when validating a person. If both are provided in the same request, the system will return an error. While only the account and routing numbers are required to perform a basic validation, we strongly encourage you to send as much information as possible. The more complete the data, the more accurate and meaningful the resulting confidence score and insights will be. Actions By default, every call to the Account Intelligence endpoint will validate the account and routing number provided. However, depending on the services you wish to use, you may request additional checks by specifying them in the actions object. The actions object allows you to include optional features in your validation request. Currently, we support one additional action: Name Match. This feature checks whether the name provided in the identity object matches the name on file for the bank account. To enable Name Match, include it in the actions block of your request payload, as shown in the example below.
This API is only available for U.S. bank accounts.

Endpoint

POST /api/v3/accounts/validate

Request Body

{
  "bank_account": {
    "account_number": "1234567890",
    "routing_number": "021000021",
    "account_type": "checking"
  },
  "location": {
    "address": {
      "street_1": "123 Main St",
      "street_2": "Apt 4B",
      "city": "New York",
      "state": "NY",
      "zip": "10001"
    },
    "gps": {
      "latitude": 43.069456,
      "longitude": -77.297012
    },
    "ip_address": "192.168.1.1"
  },
  "identity": {
    "individual": {
      "first_name": "John",
      "last_name": "Doe",
      "middle_name": "James",
      "prefix": "Mr.",
      "suffix": "Jr.",
      "email": "[email protected]",
      "phone_number": "+11234567890",
      "device_id": "abc123xyz789"
    },
    "organization": {
      "name": "Acme, Inc.",
      "alternate_name": "Acme Corp",
      "email": "[email protected]",
      "phone_number": "+11234567890",
      "device_id": "abc123xyz789"
    },
    "actions": {
      "name_match": true
    }
  }
}

Request Fields

FieldTypeRequired
bank_accountobjectyes
bank_account.account_numberstringyes
bank_account.routing_numberstringyes
bank_account.account_typestring [checking, savings]no
locationobjectno
location.addressobjectno
location.address.street_1stringyes, if address object included
location.address.street_2stringno
location.address.citystringyes, if address object included
location.address.statestringyes, if address object included
location.address.zipstringyes, if address object included
location.gpsobjectno
location.gps.latitudedecimalyes, if gps object included
location.gps.longitudedecimalyes, if gps object included
location.ip_addressstringno
identityobjectno
identity.individualobjectno
identity.individual.first_namestringyes, if individual object included
identity.individual.last_namestringyes, if individual object included
identity.individual.middle_namestringno
identity.individual.prefixstringno
identity.individual.suffixstringno
identity.individual.emailstringno
identity.individual.phone_numberstringno
identity.individual.device_idstringno
identity.organizationobjectno
identity.organization.namestringyes, if organization object included
identity.organization.alternate_namestringno
identity.organization.emailstringno
identity.organization.phone_numberstringno
identity.organization.device_idstringno
actionsobjectno
actions.name_matchbooleanno

Response

Sucess ( 200 )
{
  "confidence_score": 0.27,
  "decisioning_insights": {
      "valid_routing_number": true,
      "days_since_first_seen": 128,
      "positive_transactions_seen": true,
      "negative_transactions_seen": false,
      "paid_transactions_seen": true,
      "phone_number_present": true,
      "days_since_last_transaction": 14,
      "name_match": "yes",
      "account_duplicate": false
  }
}

Errors & Warnings

Error ( 400 )
{
  "status": false,
  "message": "Invalid Input.",
  "data": null
}
Error ( 401 )
{
  "status": false,
  "message": "Missing or invalid access token.",
  "data": null
}
Error ( 415 )
{
  "status": false,
  "message": "Unsupported Media Type. Please use application/json.",
  "data": null
}
Error ( 429 ) )
{
  "status": false,
  "message": "Rate Limit Exceeded",
  "data": null
}
Error ( 500
{
  "status": false,
  "message": "Internal Server Error. Please try again later.",
  "data": null
}

Usage Recommendations

  • Always pass complete and accurate data to maximize validation accuracy.
  • Use the confidence_score and decisioning_insights data to drive onboarding decisions.
  • Check the name_match, negative_transactions_seen fields closely if the confidence_score is low.
  • You can display insights like valid_routing_number to users or use them for internal routing logic.