Key takeaways
- Use API v2 for the latest enhancements and for more meaningful results.
- Help reduce fraud by validating the owner of an account, matching the intended counterparty before moving funds.
- Help minimize returns by confirming an account is open and valid before transacting with the account.
- Comply with Nacha rules requiring account validation for web debits in real time without need for prenotes or micro-deposits.
- Help save time with immediate validation for account inquiries.
Try it yourself
If you want to use our Account Validation API, please contact us to learn more.
Everyone needs validation
With the Account Validation API, you can inquire about an account and a get real-time confirmation about the status of the account and whether the ownership data matches. By real-time, we mean like 5 seconds or less on average. This is a far contrast to pre-notes or micro deposits which can take days and possibly accrue cost if there a return involved for illegitimate accounts.
This service is priced per each successful transaction. Speak with your Embedded Banking Payments Advisor to learn more. You can see our Getting Started Guide to learn more about how to partner with KeyBank APIs.
How it works
Account validation is simple. You send an inquiry request to evaluate the account information from a draft account item, typically a check or an ACH item. KeyBank completes Account Ownership Authentication (AOA). This is an API service that enables payment processors to verify the information matches data in the National shared Database (NSD). It reviews the payer’s name, address, and other elements and responds with whether the payer is authorized to transact on the account.
When the Account Validation API reviews the request, the case, spacing, and punctuation are ignored when matching values. The response returns codes that inform you of whether or not this is a genuine account. Codes returns include:
- a condition code telling you the state of the account owner data provided.
- match codes that confirm the data is the found or not with a Y (Yes), N (No), C (Conditional), or U (Unknown).
- an overall match score is generated based on number of data points that did and did not match. If most of the match codes are Y, you will have a higher match score.
Make a request
To send a valid request, the following parameters are required:
secondaryID
: This is a unique identification assigned by KeyBank to each client of the API and identifies which client is making the call. This is not the same as your client credentials used to get an access token.routingNumber
: The routing number of the bank account holder.accountNumber
: The bank account number of the account owner.
Search by...
You can search by a person or a business, but not both.
A personal inquiry validates an account with the owner's full name. (firstName
+ lastName
)
A business inquiry validate an account with a business name, company name, or the full name of the individual. (businessName
)
More is better
To include more data points for verification, you can use the AcctOwner
object to inquire about a personal or business account. The information you provide in the request is reviewed for a match in the database. If you do not enter any information in a field, it will not be reviewed for a match and returns as a blank field. The more information you provide, the better the validation when comparing data with the NSD.
Assess the response
It is up to you and your business how you weigh the response codes returned and what it says about the validity of the account. KeyBank can only recommend guidelines on how to assess and interpret the response.
With the Account Validation API response, we recommend reviewing the following items in this sequence:
01
Check to see if the request was a good one
The response starts with the errorCode
, a three-digit code that lets you know if there are any errors present with the account information from a draftable account item or the evaluation of the request message fields.
If no errors are present, this field is filled with three zeroes. If you do not get magical three zeroes, go to the Account Validation API document to view specific error handling codes.
02
Review the account status
The account status object (AcctStatus
) returns a three-digit code for the current condition of the bank account. The primary status code (primaryStatusCode
) indicates if the account is open, closed, or not found. Each code has an associated message with additional details (primMessage
).
Account status codes
Code | Message |
---|---|
000 | Routing number and account number combination cannot be found |
012 | Account is closed |
096 | No positive or negative information in known about the account |
099 | Account is present in the participant’s master account file and has no other status code |
03
See if there are any conditions associated with the account information
Condition codes reflect the state of the account owner data provided. When a condition code is returned in the response payload (conditionCode
), users may still receive a partial response, such as an account status.
Condition codes
CONDITION CODE | DESCRIPTION |
---|---|
000 | Normal response - no system errors |
300 | Valid routing number, but not a participant |
301 | Valid participant, but not an account owner authentication contributor |
302 | Valid participant, but account owner authentication data is unavailable |
304 | No name field populated - first, last, or business name |
396 | No known information for the account number |
900/901 | No account owner response requested or provided |
04
Review how much of the information matched
Review the overall match score (overallMatchScore
) to see if the account validity is within acceptable limits. The overall match score is calculated on a scale of 1 to 100. This score is generated based on number of data points that did and did not match. If most of the match codes are Y, you will have a higher match score. If you have data points that return a C for a partial match or a N for no match, it will reduce the match score. Typical threshold recommendation for match score approval is 81 and above.
The system reviews the data points provided so the more details you provide in your inquiry, the better the analysis. Small discrepancies like incorrectly spelled words or the wrong phone number can affect the match score. Remember, case, punctuation, and spacing are ignored when verifying data. Review the AcctOwner
attributes provided in the request and responds with if they match the data in the NSD.
05
Dig into the details
The AcctOwner
response object can contain several fields that end in "Match". Each of these match fields contains a single-character code that signifies whether or not an account owner element was found. You can get a confirmation of Y (Yes), N (No), C (Conditional), or U (Unknown).
Match codes
CODE | DESCRIPTION | Applies to match fields |
---|---|---|
Y | Close or exact match | firstNameMatch , lastNameMatch , middleNameMatch , namePrefixMatch , nameSuffixMatch , stateMatch , ssnMatch (if the last four digits are provided in the request), idType , idState |
N | No match | |
C | Conditional match | nameMatch , businessNameMatch , addressMatch , cityMatch , zipCodeMatch , homePhoneMatch , workPhoneMatch , ssnMatch (if nine digits are provided in the request), dobMatch , idNoMatch |
U | No identifying data is available | Applies to all fields If you get a U with the |
Request and response example
- All requests require the
secondaryId
provided during KeyBank onboarding, routing number, and an account number. - If this is a personal inquiry, at a minimum search by
accountNumber
androutingNumber
withfirstName
andlastName
. - If this is a business inquiry, at a minimum search by
accountNumber
,routingNumber
, andbusinessName
.
Request
Response
"accountValidationRequest": { "AOARequest": { "Inquiry": { "serviceType": "Owner" "secondaryID": "KeyCli01", "additionalID": "", "routingNumber": "122199983", "accountNumber": "89455", "amount":"50", "serialNumber": "", "AcctOwner": { "firstName": " Paul", "lastName": "Wilson ", "middleName": "V", "namePrefix": "Mr", "nameSuffix": "Jr", "businessName": "Bizness by Paul", "addressLine1": "206 GOODWIN ST", "addressLine2": "", "city": "MERRIT", "state": "MI", "zipCode": "49667", "homePhone": "5555551234", "workPhone": "5555561234", "ssn": "9999", "dob": "19730801", "idType": "2", "idNo": "6788", "idState": "AL" }, "Client": { "ClientDt": "2022-03-04", "ClientTime": "14:45:05", "UserDef": "123xyz" } } }
"accountValidationResponse": { "AOAResponse": { "Result": { "errorCode": "000", "systemRecordId": "5934871120174384", "primaryId": "TROM122101", "secondaryId": "KeyCli01", "additionalId": "", "routingNumber": "122199983", "accountNumber": "89455", "feeAttrib": "HH", "amount":"50", "serialNumber":"", "AcctOwner": { "conditionCode": "000", "nameMatch": "Y", "firstNameMatch": "Y", "lastNameMatch": "Y", "middleNameMatch": "Y", "namePrefixMatch": "Y", "nameSuffixMatch": "Y", "businessNameMatch": "Y", "addressMatch": "Y", "cityMatch": "Y", "stateMatch": "Y", "zipCodeMatch": "Y", "homePhoneMatch": "Y", "workPhoneMatch": "Y", "ssnMatch": "N", "dobMatch": "Y", "idTypeMatch": "Y", "idNoMatch": "Y", "idStateMatch": "Y", "overallMatchScore": "100" },
"AcctStatus": { "primaryStatusCode": "099", "primMessage": "Open Valid" }, "Client": { "clientDate": "2022-03-04", "clientTime": "14:45:05", "userDefined": "123xyz" } } } }
What to expect
The data provided in the request is compared to the NSD. After evaluation, you get a response that indicates if there is a match or any discrepancies.
Review the response and interpret the information according to your needs and business rules. You can consider the response data in your decision-making process, along with other risk management information.
What's next?
- View our Getting Started Guide to get an overview of the onboarding process.
- Get better acquainted with our API and check out the Account Validation API reference material.