Skip to content
Select theme

Account Intelligence

The Account Intelligence v3 endpoint is part of GrailPay’s real-time bank account validation system. It allows you to determine whether a user’s bank account is valid, active, and safe to use — helping you reduce fraud, prevent returns, and accelerate decision-making.

Account Intelligence is a single endpoint offered in two versions, Lite and Standard. Lite returns a fast validity verdict from the account and routing numbers alone. Standard, the default, returns a score and the explainable insights behind it. You choose the version in the request body, not by the path you call. See Versions.

With a single API call, Standard returns a confidence_score along with detailed decisioning_insights based on the identity and bank account data you provide. These insights can be used to drive onboarding, funding, and payout workflows with higher accuracy and lower risk.

When constructing a Standard request, you’ll pass an identity object that contains either an individual or an organization. These two are mutually exclusive — the request will fail if both are included. Use organization for validating business entities and individual for people.

While the only required fields are account and routing numbers, we strongly recommend providing as much identity data as possible on Standard requests. More complete input data results in more meaningful confidence scores and more actionable insights.

For complete request and response definitions, visit the Account Intelligence OpenAPI Documentation.


Both versions of Account Intelligence are served by the same endpoint, POST /api/v3/accounts/validate. Which one you receive is set by version in the actions object of the request body. A request that omits version resolves to Standard.

LiteStandard (default)
actions.versionlitestandard, or omitted
InputAccount number and routing numberAccount and routing numbers required; full identity data recommended
OutputA valid verdict of likely, unlikely, or indeterminate, with supplemental_dataA confidence_score from 0.00 to 1.00 and decisioning_insights
Best forA fast, low-friction validity signal with no identity dataComposable insights that can drive tailored workflows

Lite answers one question: is this account likely valid? It runs checks on the routing and account numbers across GrailPay’s data sources and returns a categorical verdict. No identity data is required.

To request Lite, set version to lite in the actions object:

{
"actions": {
"version": "lite"
}
}

Send version on its own. Lite does not accept identity data or the name_match and taxpayer_number_match actions, and a Lite request that includes them is rejected with a 422 validation error.

Standard returns a calibrated confidence score plus explainable decisioning insights from a single API call. Account and routing numbers are required, and supplying full identity data yields more meaningful results. Standard also supports the optional name_match and taxpayer_number_match actions.

Standard is the version you receive when version is set to standard or left out of the request.


The sandbox reserves a small set of routing numbers that return a fixed result. Use them to build and test against each outcome so you can see how real results will behave. These reserved routing numbers apply across the Risk API, including both the Account Intelligence and Transaction Intelligence models.

Sandbox base URL: https://risk-api-sandbox.grailpay.com

Each Version Has Its Own Test Routing Numbers

Section titled “Each Version Has Its Own Test Routing Numbers”

Lite and Standard each reserve their own routing numbers, and a reserved number returns its fixed result only on a request for the version it belongs to. Sent to the other version, it is not a test scenario, and the request is processed as it would be for any other routing number.

For example, 000000001 returns the low-risk, full-match result on a Standard request. On a request with actions.version set to lite, the same routing number is processed as a regular Lite request.

Selection is driven by the routing_number alone. The account number can be any value that passes request validation — numeric, 17 digits or fewer, and not all zeros.

For example, on a Standard request, 000000001 paired with any valid account number returns the full-match result. Pairing that same account number with 000000003 returns the high-risk result. Lite works the same way: 000000100 paired with any valid account number returns a likely verdict.

These routing numbers return a fixed result on Standard requests, meaning actions.version is set to standard or omitted.

Routing NumberScenarioHTTP Status
000000001Low risk, full match200
000000002Medium risk, match not available200
000000003High risk, negative history200
000000004Close taxpayer match200

Each one returns the following values:

Routing Numberconfidence_scorename_matchname_match_scoretaxpayer_number_match
0000000010.91yes0.98yes
0000000020.53not_available0.0not_available
0000000030.12no0.14no
0000000040.65not_available0.0close_match

These routing numbers return a fixed result on requests with actions.version set to lite. Each one returns a 200 with the valid verdict and supplemental_data.codes entry shown. There is one routing number for each supplemental code Lite returns today, plus one for the no-code case.

Routing Numbervalidsupplemental_data.codes
000000100likelyEmpty
000000101unlikely01 Invalid Input Format
000000102unlikely02 Invalid Routing Number
000000103unlikely03 Invalid Account Number Format
000000104unlikely04 Account Number Not Eligible for ACH
000000106indeterminate06 No Account Information Found
000000107unlikely07 Potential Risk Indicator
000000108likely08 Frequently Observed Active Account

The last two digits of the routing number match the supplemental code it returns, and 000000100 returns none. Code 05 is not returned today, so it has no test routing number.

These behave the same way on both versions.

Routing NumberScenarioHTTP Status
empty / missingValidation-style errors422
999999999Upstream unavailable503
Any other valueFalls through to live sandbox decisioninglive

By default, every call to this endpoint performs core validation checks on the routing and account numbers. The optional actions object in your request does two things: it selects the Account Intelligence version, and on Standard requests it enables additional validation layers that enrich the results further.

Currently, the following actions are supported:

  • version: Selects the Account Intelligence version, lite or standard. Defaults to standard when omitted. See Versions.
  • name_match: Compares the provided name in the identity object with the account holder’s name on file. Standard only.
  • taxpayer_number_match: Compares the provided taxpayer identifier in the identity object with the account holder’s tax ID on file. Standard only.

To enable either match action, include it in the actions object of your request payload:

{
"actions": {
"version": "standard",
"name_match": true,
"taxpayer_number_match": true
}
}

Each enabled action runs an additional identity check that contributes directly to the confidence score and surfaces a corresponding attribute in the decisioning_insights object. Enabling name_match returns name_match and name_match_score; enabling taxpayer_number_match returns taxpayer_number_match.

For full request and response examples, see the Account Intelligence API reference.


What the endpoint returns depends on the version you request. Standard returns a confidence_score alongside a set of structured decisioning_insights. Together, these give you both a single risk signal and the explainable attributes behind it, so you can plug them directly into your own models or rules-based decisioning. Lite returns a valid verdict and a supplemental_data object instead. Standard responses do not include valid or supplemental_data; both are specific to Lite.

The confidence_score, returned by Standard, is a number between 0.00 and 1.00 representing the likelihood that an ACH debit or credit will be processed successfully without an operational return. Higher is better — a score of 0.95 indicates high confidence that the account is open, active, and able to transact, while a score of 0.30 indicates significant risk of an ACH return.

The score is produced by a proprietary machine learning model trained on millions of historical ACH transactions and their outcomes. The model takes the account and routing number, enriches it with third-party data sources and GrailPay’s own first-party intelligence, and returns a calibrated probability.

As a general guide, the score maps to the following confidence levels:

Confidence LevelScore Range
Very High0.90 – 1.00
Good0.70 – 0.89
OK0.40 – 0.69
Risky0.00 – 0.39

The decisioning_insights object, returned by Standard, contains explainable attributes returned alongside the score. Each attribute is designed to be consumed directly by your risk engine — as an input to your own models or as a building block for rules-based logic.

AttributeWhat It MeansWhy It MattersTypical InterpretationPossible Values
valid_routing_numberConfirms the routing number belongs to a legitimate, active financial institution.An invalid routing number will generally cause the payment to fail.true = valid routing number. false = do not process without review.Boolean, true / false
name_matchCompares the provided account owner’s name to the name associated with the account.Helps confirm the person or business owns the account.yes = positive. no = name does not appear to match the account owner; review for possible incorrect information or identity concerns. not_available = no comparison possible.String: yes, no, not_available. Returned only when name_match is enabled in the request actions object.
name_match_scoreMeasures how closely the names match on a scale from 0.00 to 1.00.Provides additional detail beyond a simple yes/no result.Near 1.00 = strong match. Around 0.80 = minor differences. Lower scores = weak match.Number, 0.00 to 1.00. Returns 0.00 when no name was supplied, or when no identity data source could evaluate the name.
days_since_first_seenHow long the account has existed in GrailPay’s data network.Older accounts generally provide more confidence.Higher values = more established. -1 = no history available.Integer. -1 if unknown.
days_since_last_transactionNumber of days since the account was last active.Active accounts tend to be lower risk than dormant accounts.Lower values = recently active. Higher values = less recent activity.Integer. -1 if unknown.
positive_transactions_seenIndicates successful historical transactions.Past successful payments increase confidence.true = positive history.Boolean, true / false
negative_transactions_seenIndicates returned payments or other negative events.Past issues may increase risk.true = review more closely.Boolean, true / false
paid_transactions_seenShows whether previously returned transactions were later resolved.Shows that past payment issues were actively addressed and resolved, which may reduce the concern associated with previous returns.true = past issues resolved.Boolean, true / false
phone_number_presentIndicates a phone number is associated with the account.Adds another identity signal.true = slightly stronger identity confidence.Boolean, true / false
account_duplicateShows whether the account has been seen before in GrailPay’s network.Prior history provides additional context.true = existing account history.Boolean, true / false
taxpayer_number_matchCompares the provided SSN/EIN with records associated with the account.Strong identity verification signal.yes = strong match. close_match = minor discrepancy. no = significant concern. not_available = comparison unavailable.String: yes, no, close_match, not_available. Returned only when taxpayer_number_match is enabled in the request actions object.

A Lite response returns valid, a categorical verdict on the account.

ValueWhat It Means
likelyThe account is likely valid and safe to transact.
unlikelyThe account is unlikely to be valid; review before processing.
indeterminateThere is not enough signal to determine validity.

The supplemental_data object carries additional context about how the verdict was reached. It is always present on a Lite response, and its codes array is always present but may be empty, so you can iterate over it without a null check. Today a response carries at most one code.

Each entry in codes has a two-character code and a description. Match on the code value. The description is display text and may be reworded without notice. Ignore codes you do not recognize so that new codes cannot break your integration.

CodeDescription
01Invalid Input Format
02Invalid Routing Number
03Invalid Account Number Format
04Account Number Not Eligible for ACH
05No Name Information Found
06No Account Information Found
07Potential Risk Indicator
08Frequently Observed Active Account

Code 02 indicates a well-formed nine-digit routing number that does not belong to a recognized institution. Code 05 is reserved and is not returned today.

Codes 01 and 03 are returned on a 200 response, not as validation errors. A malformed request is rejected with a 422 before any check runs. These two codes cover input that passes request validation but that one of our data sources still judges malformed or invalid.


Account Intelligence is a continuously improving system, and its accuracy depends on real-world outcome data from your integration. The Feedback endpoint allows you to report return events that occurred despite receiving an acceptable risk score, closing the loop between prediction and outcome.

Submitting feedback is a critical part of getting the most out of Account Intelligence. Feedback data is used for analytics, model evaluation, and ongoing training — directly improving the accuracy of future risk scores across your account portfolio. Integrations that consistently submit feedback benefit from more precise, tailored risk assessments over time.

For complete request and response definitions, visit the Account Intelligence Feedback OpenAPI Documentation.

You should submit feedback when:

  • A transaction results in an unexpected return despite receiving a low-risk Account Intelligence score
  • You want to improve the accuracy of future risk evaluations for your account portfolio
  • You need to report false negatives for internal tracking and model monitoring

When submitting feedback, your request payload should include details about the account, the return event, and a reference to the original Account Intelligence evaluation. Required fields ensure we can accurately link your feedback to the original prediction, while optional fields provide additional context that strengthens model analysis.

The following fields are required to link your feedback to the original Account Intelligence evaluation and the associated return event.

FieldTypeDescription
account_numberstringThe account number from the original evaluation
routing_numberstringThe routing number from the original evaluation
outcome_statusstringThe outcome status of the transaction. Possible values: settled, returned
return_codestringThe ACH return code received (e.g., R01, R02, R03)
name_match_requestedbooleanWhether name matching was enabled in the original request

Additionally, you must include one of the following to link to the original prediction:

FieldTypeDescription
inference_request_idUUIDThe request ID returned by GrailPay in the original Account Intelligence response (preferred)
inference_timestamptimestampThe UTC timestamp of the original request, if the request ID is unavailable

The following fields are not required but provide additional context that strengthens model analysis when available.

FieldTypeDescription
returned_attimestampWhen the return was received
transaction_initiated_attimestampWhen the transaction was initiated (client-side)
sec_codestringThe SEC code of the transaction (e.g., WEB, CCD, PPD)
amountdecimalThe transaction amount
directionstringTransaction direction: credit or debit

  • Use Lite when you need a fast validity signal and have no identity data, and Standard when you want a score and insights to drive your decisioning.
  • On Standard requests, always pass complete and accurate identity data to maximize result quality.
  • Use the confidence_score and decisioning_insights to guide onboarding and risk workflows.
  • Review fields such as name_match, valid_routing_number, and negative_transactions_seen closely when the score is low.
  • On Lite responses, match on the supplemental code rather than its description, and ignore codes you do not recognize.
  • Submit feedback promptly after a return event occurs to ensure accurate timestamps and traceability.
  • Always include the inference_request_id when available for precise linkage to the original prediction.
  • Provide optional fields like amount, sec_code, and direction when possible to enrich the feedback data.

If you’re encountering any issues, please reach out to support@grailpay.com.


Maintained by EkLine