Pre-Validation Strategies
Validating your data before submission reduces rejections, speeds up processing, and ensures your credit reporting stays accurate and compliant.
1. Why Pre-Validate?
Credit bureaus reject entire files if they contain invalid records. Pre-validation catches problems before they reach the bureau, saving time and preventing reporting gaps.
Reduction in rejection rates with client-side pre-validation
Processing times when files contain zero errors
Compliance maintained with consistent, accurate data
Tip
Pre-validating before submission typically reduces rejection rates by 80%+. Implement both client-side checks and server-side validation via the API for best results.
2. Required Field Matrix
Different account types have different required fields. Use this matrix to ensure you are populating the correct fields for each record type.
| Field | Installment | Revolving | Mortgage | Open |
|---|---|---|---|---|
| Account Number | Required | Required | Required | Required |
| Account Status | Required | Required | Required | Required |
| Current Balance | Required | Required | Required | Required |
| Credit Limit | N/A | Required | N/A | N/A |
| Highest Credit | Required | Conditional | Required | Required |
| Scheduled Payment | Required | Conditional | Required | N/A |
| Payment History | Required | Required | Required | Required |
3. Client-Side Validation Patterns
Implement these checks in your application before calling the API to catch the most common errors instantly.
// Common validation functions for Metro 2 data
function validateSSN(ssn: string): boolean {
// Must be exactly 9 digits, no dashes
const cleaned = ssn.replace(/\D/g, '');
if (cleaned.length !== 9) return false;
// Cannot be all zeros or start with 9 (ITIN range)
if (cleaned === '000000000') return false;
if (cleaned.startsWith('9')) return false;
return true;
}
function validateDate(dateStr: string): boolean {
// Must be YYYY-MM-DD format
const regex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
if (!regex.test(dateStr)) return false;
// Must not be in the future
return new Date(dateStr) <= new Date();
}
function validateAccountNumber(accountNum: string): boolean {
// 1-30 alphanumeric characters, no special characters
const regex = /^[A-Za-z0-9-]{1,30}$/;
return regex.test(accountNum);
}
function validatePaymentHistory(profile: string): boolean {
// Must be exactly 24 characters
if (profile.length !== 24) return false;
// Valid characters: 0-4, D, E, G, L, B (space for no history)
const validChars = /^[0-4DEGLB ]{24}$/;
return validChars.test(profile);
}
function validateAccountStatus(status: string): boolean {
const validStatuses = [
'05', '11', '13', '61', '62', '63', '64', '65',
'71', '78', '80', '82', '83', '84', '93', '94',
'95', '96', '97', 'DA', 'DF'
];
return validStatuses.includes(status);
}4. Common Validation Errors
These are the top 10 validation errors we see from integrators. Addressing these in your client-side checks eliminates the vast majority of rejections.
#1: SSN contains dashes or is wrong length
Fix: Strip non-numeric characters. Must be exactly 9 digits.
#2: Date format is MM/DD/YYYY instead of YYYY-MM-DD
Fix: The API requires ISO 8601 date format (YYYY-MM-DD).
#3: Account Status does not match Payment History
Fix: Status 11 (current) requires position 1 of Payment History to be '0'.
#4: Payment History Profile is not 24 characters
Fix: Pad with spaces on the right for accounts with less than 24 months of history.
#5: Missing Date of First Delinquency for delinquent accounts
Fix: Required when Account Status is 71, 78, 80, 82, 83, 84, or 97.
#6: Credit Limit reported for non-revolving accounts
Fix: Credit Limit is only valid for Portfolio Type 'R' (revolving).
#7: Consumer name contains lowercase characters
Fix: All name fields must be uppercase. Apply .toUpperCase() before submission.
#8: Account number exceeds 30 characters
Fix: Truncate or hash long account numbers to fit the 30-character limit.
#9: Amount Past Due is zero but Account Status shows delinquency
Fix: Amount Past Due must be greater than zero for delinquent statuses.
#10: Date Opened is after Date Reported
Fix: Date Opened must be on or before the current reporting date.
5. Using the Validation Endpoint
After client-side checks, use the /v1/records/validate endpoint for full Metro 2® format validation. This catches field-level and cross-field rules that are impractical to replicate client-side.
POST /v1/records/validate
Content-Type: application/json
Authorization: Bearer test_sk_abc123def456
{
"accountNumber": "ACCT-10042",
"portfolioType": "I",
"accountType": "01",
"accountStatus": "11",
"currentBalance": 12500,
"paymentHistoryProfile": "000000000000000000000000",
"consumer": {
"name": { "firstName": "JOHN", "lastName": "DOE" },
"ssn": "123456789",
"dateOfBirth": "1985-06-15"
}
}
// Response
{
"valid": true,
"warnings": [],
"errors": [],
"fieldResults": {
"accountNumber": { "status": "pass" },
"accountStatus": { "status": "pass" },
"paymentHistoryProfile": { "status": "pass" },
"consumer.ssn": { "status": "pass" }
}
}6. Batch Validation Strategies
When validating hundreds or thousands of records, use the batch validation endpoint to check multiple records in a single request.
POST /v1/records/validate/batch
Content-Type: application/json
Authorization: Bearer test_sk_abc123def456
{
"records": [
{ "accountNumber": "ACCT-001", ... },
{ "accountNumber": "ACCT-002", ... },
{ "accountNumber": "ACCT-003", ... }
]
}
// Response
{
"totalRecords": 3,
"validCount": 2,
"invalidCount": 1,
"results": [
{ "accountNumber": "ACCT-001", "valid": true, "errors": [] },
{ "accountNumber": "ACCT-002", "valid": true, "errors": [] },
{
"accountNumber": "ACCT-003",
"valid": false,
"errors": ["SSN must be exactly 9 digits"]
}
]
}Batch Limits
- • Maximum 500 records per batch request
- • For larger datasets, split into chunks and validate in parallel
- • Rate limit: 10 batch requests per minute per API key