Skip to main content

Income Navigator V2 API Reference

API Overview

Introduction

This document provides information on how to interact with the Nova Credit API to obtain an Income Navigator V2 report.

The best way to get the Income Navigator report using Nova Credit's API is to have your applicants use NovaConnect, an easy-to-use and secure JavaScript module. Visit our Quickstart Guide for all details on how to get Nova Credit API credentials and integrate NovaConnect into your app or website today.

Framework and Protocol

The Nova Credit API is organized around REST. It uses resource-oriented URLs, HTTP response codes, and native HTTP functionality such as authentication and verbs. Note that our APIs are served over HTTPS; HTTP is not supported in production.

Delivery Formats

JSON is the default response format.

Endpoints

Our API host is api.novacredit.com. (See Quickstart Guide for environment information.)

Our resource URL patterns are:

EndpointDescription
GET /connect/accesstokenRetrieves an access token for an applicant's Income Navigator report
GET /connect/income-navigator/v2/jsonRetrieves an applicant's Income Navigator report in JSON form
GET /connect/income-navigator/v2/filesRetrieves a list of files associated with an application, even if there is no report
GET /connect/income-navigator/v2/files/<filepath>Retrieves a file associated with an applicant's Income Navigator report
GET /connect/statusRetrieves the status of an applicant's Income Navigator report
GET /connect/bank-accounts/<bankAccountId>/ach-detailsRetrieves ACH details for a given bank account after report generation

Visit our Quickstart Guide to see details on how to call these endpoints with examples.

Data Types & Formats

Data Types

TypeDescription
StringExtended character set, numbers and punctuation symbols. This includes non-ASCII language-specific characters such as ß, à, ç, é, and more (all encoded as utf8).
IntegerA rounded numerical value.
FloatA 64-bit floating decimal point format.
BoolA boolean-flag indicating true or false.
ObjectNested JSON level with more field-values.
ArrayA value or type array contains a zero or positive amount of elements. The elements can be of any type.

Data Formats

FormatDescription
Timestamp(String) UTC ISO 8601 data and time format. Full specs according to RFC 3339. Example: 1982-09-26T32:20:50.52Z
Full Date(String) UTC ISO 8601 date format. Full date format in YYYY-MM-DD. Example: 1982-09-26
Short Date(String) UTC ISO 8601 date format. Shorter format in YYYY-MM. Example: 1982-09
UUID(String) Universally Unique Identifier according to RFC 4122
URI(String) Uniform Resource Identifier according to RFC 3986
Full Version(String) Semantic versioning. http://semver.org/

Report Body

Report Structure

The Income Navigator report has the following high level keys in the JSON:

  • meta {object}
  • product {object}
  • sources {array}
  • identities {array}
  • employment {array}
  • income {object}
  • account_details {array}

Example of the JSON structure:

{
"meta": {
...
},
"product": {
...
},
"sources": [
...
],
"identities": [
...
],
"employment": [
...
],
"income": {
...
},
"account_details": [
...
]
}

If there is no data to return in that node, it will not be returned.

Within each node, all fields will be returned. If there is no data to be returned for that field, it will be null.

meta

Information specific to the report that's been returned.

FieldFormatNotes
public_tokenUUIDThe unique identifier of this report
user_argsString or nullThe input of the userArgs function in NovaConnect.
created_atTimestampThe date the consumer's data was retrieved
api_versionFull versionThe API version used to generate this report
external_idString or nullThe unique applicant identifier of the report from your system.
statusStringThe status for this report. If a report is available, the status will be SUCCESS
substatusString or nullThe substatus for the report. See substatuses.
nova_report_revisionString or nullThe revision name for this report. This field will be null if this report has never been revised.

Example:

"meta": {
"public_token": "ff0886a4-f3ff-11e6-bc64-92361f002671",
"user_args": "235234224",
"created_at": "2024-01-13T11:07:46.51Z",
"api_version": "2.0.0",
"external_id": "d167c6bb-225c-461c-be63-f0bc3a1f62ea",
"status": "SUCCESS",
"substatus": null,
"nova_report_revision": null
}

product

Details of the product the applicant applied for. Please refer to the Client-Side Integration section in the Quickstart Guide.

FieldFormatNotes
nameStringProduct name
product_idUUIDThe unique identifier for the product
inquiry_typeStringSee product inquiry_type values

Example:

{
"product": {
"name": "Village Communities",
"product_id": "9cf178e0-760e-11e7-abf3-5da9d338ae4b",
"inquiry_type": "TENANT"
}
}

sources []

A list of data sources used to build the applicant's report.

FieldFormatNotes
source_idStringSee source_id
source_typeStringSee source_types
statusStringThe final status for the source. See status

Example:

{
"sources": [
{
"source_id": "USA_FIN",
"source_type": "BANK_TRANSACTION",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "MANUAL",
"status": "SUCCESS"
}
]
}

identities []

The applicant's personal identity information reported from each data source.

FieldFormatNotes
source_idStringThe identifier for the source that reported the identity information. See sources
source_record_idUUID or nullThe identifier for an individual record within a source
first_nameString or null
last_nameString or null
full_nameString or null
emailsArray of String
matchingObjectSee matching

Example snippet of identities a report with a bank source:

{
"identities": [
{
"source_id": "CONSUMER_INPUT",
"source_record_id": null,
"first_name": "raymond",
"last_name": "Marshal",
"full_name": "raymond Marshal",
"emails": ["raymond@email.com"],
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "USA_FIN"
}
],
"unmatched_sources": []
}
}
},
{
"source_id": "USA_FIN",
"source_record_id": null,
"first_name": null,
"last_name": null,
"full_name": "RAYMOND MARSHAL MARINA MARSHAL",
"emails": []
},
{
"source_id": "USA_FIN",
"source_record_id": null,
"first_name": null,
"last_name": null,
"full_name": "RAYMOND MARSHAL",
"emails": []
}
]
}

Example snippet of identities a report with a paystub source:

{
"identities": [
{
"source_id": "CONSUMER_INPUT",
"source_record_id": null,
"first_name": "Emelia",
"last_name": "Gutierrez",
"full_name": "Emelia Gutierrez",
"emails": ["emelia@email.com"],
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "OCROLUS"
}
],
"unmatched_sources": []
}
}
},
{
"source_id": "OCROLUS",
"source_record_id": "4724127c-a3aa-4c71-b07e-6d287878b439",
"first_name": null,
"last_name": null,
"full_name": "EMELIA GUTIERREZ",
"emails": []
}
]
}

matching

Information about sources which have matching and conflicting values to a particular identity.

matching is returned in an object broken out by field, only certain fields are matched between sources. If only one identity item exists, there will be no matching field. Information about matching sources is stored wrapped in the MatchingField format, which indicates where each value was sourced from. The matching node will only be displayed on the identity with source_id of CONSUMER_INPUT.

FieldFormatNotes
full_nameObjectMatched and unmatched sources for the full name of the applicant

Example identities matching field object for case where there is a full name match:

{
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "5f19d40f-3c19-4a7d-ad7b-cc28dac40c4d"
}
],
"unmatched_sources": []
}
}
}

Example identities matching field object for case where there is no full name match:

{
"matching": {
"full_name": {
"matched_sources": [],
"unmatched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "c31bf8c7-c25b-4d2c-a4bc-61f79fd46e65"
}
]
}
}
}
MatchingField

An object containing information about which sources have a matching value for a field and which sources contain conflicting values for the same field. A source is an object containing a source_id and a source_record_id if there are multiple source records.

FieldFormatNotes
matched_sourcesArrayList of sources which have a value that matches this identity. See sources
unmatched_sourcesArrayA list of sources which have a value that conflicts with this identity. See sources
Example matching field object for case where there is a field match:

{
"matched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "5f19d40f-3c19-4a7d-ad7b-cc28dac40c4d"
}
],
"unmatched_sources": []
}

Example matching field object for case where there is no field match:

{
"matched_sources": [],
"unmatched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "c31bf8c7-c25b-4d2c-a4bc-61f79fd46e65"
}
]
}

employment []

Employment information specific to the applicant whose report is being accessed.

FieldFormatNotes
source_idStringThe identifier for the source that reported the employment information. See sources
source_record_idUUID or nullThe identifier for an individual record within a source
employer_nameString or nullName of the applicant's employer
employer_address_line_1String or nullAddress line 1 where the applicant's employer is located
employer_address_line_2String or nullAddress line 2 where the applicant's employer is located
employer_cityString or nullCity where the applicant's employer is located
employer_stateString or nullState where the applicant's employer is located
employment_typeString or nullType of employment. See employment type
employment_statusString or nullStatus of the applicant's employment. See employment status
job_titleString or nullTitle of the applicant's job
hire_dateFull Date or nullEmployee hire date as stated on the employment source
estimated_hire_dateFull Date or nullAn estimate of the employee hire date. Only has a non-null value when hire_date is null
matchingObjectSee matching

Example:

{
"employment": [
{
"source_id": "OCROLUS",
"employer_name": "Microsoft",
"employer_address_line_1": "1 Microsoft Way",
"employer_address_line_2": null,
"employer_city": "Redmond",
"employer_state": "Washington",
"employment_type": "fulltime",
"employment_status": "active",
"job_title": "Product Manager",
"hire_date": "2017-04-19",
"estimated_hire_date": null,
"matching": {
"employer_name": {
"matched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "edba0b20-22e5-11eb-916b-452b88954927"
}
],
"unmatched_sources": []
}
}
}
]
}

matching

Information about sources which have matching and conflicting values to a particular employment.

matching is returned in an object broken out by field, only certain fields are matched between sources. If only one employment item exists, there will be no matching field. Information about matching sources is stored wrapped in the MatchingField format, which indicates where each value was sourced from.

FieldFormatNotes
employer_nameObjectMatched and unmatched sources for an employer name

Example employment matching field object for case where there is an employer name match:

{
"matching": {
"employer_name": {
"matched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "5f19d40f-3c19-4a7d-ad7b-cc28dac40c4d"
}
],
"unmatched_sources": []
}
}
}

Example employment matching field object for case where there is no employer name match:

{
"matching": {
"employer_name": {
"matched_sources": [],
"unmatched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "c31bf8c7-c25b-4d2c-a4bc-61f79fd46e65"
}
]
}
}
}
MatchingField

An object containing information about which sources have a matching value for a field and which sources contain conflicting values for the same field. A source is an object containing a source_id and a source_record_id if there are multiple source records.

FieldFormatNotes
matched_sourcesArrayList of sources which have a value that matches this employer.
unmatched_sourcesArrayA list of sources which have a value that conflicts with this employer.

Example matching field object for case where there is a field match:

{
"matched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "5f19d40f-3c19-4a7d-ad7b-cc28dac40c4d"
}
],
"unmatched_sources": []
}

Example matching field object for case where there is no field match:

{
"matched_sources": [],
"unmatched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "c31bf8c7-c25b-4d2c-a4bc-61f79fd46e65"
}
]
}

income

Income information specific to the applicant whose report is being accessed. Not included in reports if income information is not found.

FieldFormatNotes
summaryObjectSee summary
financial_accountsArraySee financial accounts
paystubsArraySee paystubs
payrollArraySee payroll
revised_report_valuesObjectSee revised_report_values

Example of structure:

{
"income": {
"summary": {
...
},
"financial_accounts": [
...
],
"paystubs": [
...
],
"payroll": [
...
],
/* Only in regenerated reports */
"revised_report_values": {
...
}
}
}

summary

A summary of the applicant's annual income.

FieldFormatNotes
annual_gross_incomeFloatAnnualized gross income, rounded to 2 decimal places
annual_net_incomeFloatAnnualized net income, rounded to 2 decimal places

Example:

{
"income": {
"summary": {
"annual_gross_income": 12345.67,
"annual_net_income": 11234.56
}
}
}

financial_accounts []

Income information derived from financial account data.

FieldFormatNotes
source_idsArrayThe identifiers for the sources that reported the income information. See sources
model_versionStringThe identifier for the income model version
model_typeStringSee model types
descriptionsArrayDescriptions of active inflow streams, ordered by size of inflow stream over the past 3 months (max 3 inflow stream descriptions)
is_consistentBooleanIncome has been received for the last 3 complete months
net_recentIntegerNet (take home) income over the past three complete calendar months annualized
gross_recentIntegerGross income over the past three complete calendar months annualized
net_annualIntegerNet (take home) income over the past twelve complete calendar months
gross_annualIntegerGross income over the past twelve complete calendar months
matched_incomeObjectSee matched_income
historyArraySee history
primary_account_detectedBooleanRepresents whether any connected account was determined to be a primary account. This field is only available for Income Model Suite version 2.0. Please contact your Nova Credit account representative if you are interested in enabling this field.
job_irregularity_riskStringSee job_irregularity_risk. This field is only available for Income Model Suite version 2.0. Please contact your Nova Credit account representative if you are interested in enabling this field.
inflowsArraySee inflows. This field is only available for Income Model Suite version 2.0. Please contact your Nova Credit account representative if you are interested in enabling this field.
matched_income_sourcesArraySee matched_income_sources. This field is only available for Income Model Suite version 2.0. Please contact your Nova Credit account representative if you are interested in enabling this field.

Example:

{
"income": {
"financial_accounts": [
{
"source_ids": ["USA_FIN"],
"model_version": "1.1.0",
"model_type": "NOVA_INCOME",
"descriptions": ["GUSTO PAY", "NAPOLI PIZZERIA DIR DEP"],
"is_consistent": true,
"net_recent": 20000,
"gross_recent": 24000,
"net_annual": 20000,
"gross_annual": 24000,
"matched_income": {
"stated_employer": "Napoli Pizzeria",
"stated_annual_income": 18000,
"description": "NAPOLI PIZZERIA USA 6787 836XNLNKSEYCQ8B -",
"net_income": 15480,
"gross_income": 18923
},
"history": [
{
"year": 2019,
"gross": [ 2500, 5000, ... ],
"net": [ 2250, 4500, ... ]
},
]
},
]
}
}
matched_income

An object that describes the income stream that best matches the stated employer name provided by the applicant. If no income stream matches, this object will not be returned.

matched_income will only be available and filled out if statedEmployerName was provided by the applicant, and a match was found.

FieldFormatNotes
stated_employerString or nullStated employer name provided by the applicant
stated_annual_incomeInteger or nullStated annual income provided by the applicant
descriptionString or nullDescription for the matched income stream
net_incomeInteger or nullNet income for the matched income stream
gross_incomeInteger or nullGross income for the matched income stream

Example:

{
"matched_income": {
"stated_employer": "Napoli Pizzeria",
"stated_annual_income": 18000,
"description": "NAPOLI PIZZERIA USA 6787 836XNLNKSEYCQ8B -",
"net_income": 15480,
"gross_income": 18923
}
}
history []

An array with each element containing information about the value of the income history.

history is returned in an array of objects (one object per year, from most recent to least). There are multiple histories that the history node reports and are denoted by separate keys in each history object. History arrays will be segmented by month. The first element is the month of December and the last is January. If no data is available for a given month the value will be null

FieldFormatNotes
yearIntegerThe history's given year
grossArraySums of gross income over 1-month periods. Current month may be partial value
netArraySums of take-home income over 1-month periods. Current month may be partial value

Example:

{
"history": [{
"year": 2019,
"gross": [ 2500, 5000, ... ],
"net": [ 2250, 4500, ... ]
}],
},
inflows []

An array with each element containing information about inflows which have been marked as income. An inflow is a group of transactions that represents a single income stream (e.g., from a single employer).

If no inflows marked as income were found, this array may be empty.

inflows will only be available as a property if at least version 2.0.0 of the Income Model Suite was utilized.

FieldFormatNotes
inflow_idStringA unique identifier for the inflow
descriptionStringA short description of the inflow
deposited_annual_incomeNumberSum of all deposits for the inflow over the last twelve months. If fewer than twelve months are available, the data from the available months will be annualized.
deposited_recent_incomeNumberSum of all deposits for the inflow over the last three months annualized

Example:

{
"inflows": [
{
"inflow_id": "3222a843-9768-406b-907c-b2f9a3dc669e",
"description": "CLERICAL-TECHNIC PAYROLL PPD ID: ******7683",
"deposited_annual_income": 31403.93,
"deposited_recent_income": 34520.64
},
{
"inflow_id": "1a84f67b-0ed1-450a-a78e-0e101755cc09",
"description": "IRS TREAS 310 TAX REF PPD ID: ******6170",
"deposited_annual_income": 3115,
"deposited_recent_income": 0
},
{
"inflow_id": "804636ca-8630-4609-93c0-5f6c07331a8e",
"description": "STATEOFMICHIGAN PMT/REFUND PPD ID: 014-INCTAX",
"deposited_annual_income": 716,
"deposited_recent_income": 0
}
]
}
matched_income_sources []

An array with each element containing information about any stated employer names provided by the applicant which were determined to match with an inflow.

If no matches between stated employer names and inflows could be found, this array may be empty.

Each stated employer may match with more than one inflow, but each inflow will only ever have a maximum of one stated employer match.

matched_income_sources will only be available as a property if at least version 2.0.0 of the Income Model Suite was utilized, and statedEmployerNames was provided by the applicant.

FieldFormatNotes
stated_employerStringThe name of the stated employer that was determined to match an inflow
matched_inflow_idStringThe unique identifier of the inflow that was determined to match the stated employer. See inflows

Example:

{
"matched_income_sources": [
{
"stated_employer": "Clerical Technic",
"matched_inflow_id": "3222a843-9768-406b-907c-b2f9a3dc669e"
}
]
}

paystubs []

Income information derived from paystub data.

FieldFormatNotes
source_idStringThe identifier for the source that reported the paystub information. See sources
source_record_idUUIDThe identifier for an individual record within a source
source_filepathStringThe file path used for downloading an applicants paystub file
employee_nameString or nullName of applicant
employee_address_line_1String or nullAddress line 1 of applicant
employee_address_line_2String or nullAddress line 2 of applicant
employee_cityString or nullCity of applicant
employee_stateString or nullState of applicant
employee_zipString or nullPostal code of applicant
pay_period_startFull Date or nullStart date of the paystub pay period
pay_period_endFull Date or nullEnd date of the paystub pay period
pay_dateFull Date or nullDate the pay was issued
pay_frequencyString or nullSee pay_frequency table
paystub_providerString or nullProvider of paystub
hire_dateFull Date or nullEmployee hire date as stated on the paystub
net_total_earnings_amount_currentFloat or nullNet total earnings from current pay period
net_total_earnings_amount_ytdFloat or nullNet total earnings from year to date pay period
gross_total_earnings_amount_currentFloat or nullGross total earnings from current pay period
gross_total_earnings_amount_ytdFloat or nullGross total earnings from year to date pay period
regular_pay_earnings_amount_currentFloat or nullRegular (base) pay earnings from current pay period
regular_pay_earnings_amount_ytdFloat or nullRegular (base) pay earnings from year to date pay period
bonus_earnings_amount_currentFloat or nullBonus earnings from current pay period period
bonus_earnings_amount_ytdFloat or nullBonus earnings from year to date pay period
overtime_earnings_amount_currentFloat or nullOvertime earnings from current pay period
overtime_earnings_amount_ytdFloat or nullOvertime earnings from year to date pay period
commission_earnings_amount_currentFloat or nullCommission earnings from current pay period
commission_earnings_amount_ytdFloat or nullCommission earnings from year to date pay period
paid_time_off_earnings_amount_currentFloat or nullPaid time off earnings from current pay period
paid_time_off_earnings_amount_ytdFloat or nullPaid time off earnings from year to date pay period
vacation_earnings_amount_currentFloat or nullVacation earnings from current pay period
vacation_earnings_amount_ytdFloat or nullVacation earnings from year to date pay period
paid_time_off_deductions_amount_currentFloat or nullPaid time off deductions from current pay period
paid_time_off_deductions_amount_ytdFloat or nullPaid time off deductions from year to date pay period
vacation_deductions_amount_currentFloat or nullVacation deductions from current pay period
vacation_deductions_amount_ytdFloat or nullVacation deductions from year to date pay period
medicare_tax_deductions_amount_currentFloat or nullMedicare tax deductions from current pay period
medicare_tax_deductions_amount_ytdFloat or nullMedicare tax deductions from year to date pay period
social_security_deductions_amount_currentFloat or nullSocial security tax deductions from current pay period
social_security_deductions_amount_ytdFloat or nullSocial security tax deductions from year to date pay period
fica_tax_deductions_amount_currentFloat or nullFICA tax deductions from current pay period
fica_tax_deductions_amount_ytdFloat or nullFICA tax deductions from year to date pay period
insightsObjectSee insights
consistency_checksObjectSee consistency_checks
irregularity_detectionObjectSee irregularity_detection

Example:

{
"income": {
...
"paystubs": [
{
"source_id": "OCROLUS",
"source_record_id": "c33632a0-1d6a-11eb-806e-1f1356d092eb",
"source_filepath": "f3f0d372-a0f7-402f-835e-67ce6db2a75f/866c943a-8e0b-45c6-b381-53712c2809a2.pdf",
"employee_name": "PAYTON STUBBINS",
"employee_address_line_1": "123 FRANKLIN ST",
"employee_address_line_2": "APT 4",
"employee_city": "CHAPEL HILL",
"employee_state": "NC",
"employee_zip": "27517",
"pay_period_start": "2017-07-10",
"pay_period_end": "2017-07-23",
"pay_date": "2017-08-04",
"pay_frequency": "SEMI_MONTHLY",
"paystub_provider": "ADP",
"hire_date": null,
"net_total_earnings_amount_current": 1040.23,
"net_total_earnings_amount_ytd": 18396.25,
"gross_total_earnings_amount_current": 1627.74,
"gross_total_earnings_amount_ytd": 28707.21,
"regular_pay_earnings_amount_current": 1515.84,
"regular_pay_earnings_amount_ytd": 24743.49,
"bonus_earnings_amount_current": 40.69,
"bonus_earnings_amount_ytd": 325.27,
"overtime_earnings_amount_current": "0",
"overtime_earnings_amount_ytd": 442.54,
"commission_earnings_amount_current": null,
"commission_earnings_amount_ytd": null,
"paid_time_off_earnings_amount_current": "0",
"paid_time_off_earnings_amount_ytd": 1459.97,
"vacation_earnings_amount_current": 71.21,
"vacation_earnings_amount_ytd": 952.9,
"paid_time_off_deductions_amount_current": null,
"paid_time_off_deductions_amount_ytd": null,
"vacation_deductions_amount_current": null,
"vacation_deductions_amount_ytd": null,
"medicare_tax_deductions_amount_current": 22.12,
"medicare_tax_deductions_amount_ytd": 394.81,
"social_security_deductions_amount_current": 94.58,
"social_security_deductions_amount_ytd": 1688.15,
"fica_tax_deductions_amount_current": null,
"fica_tax_deductions_amount_ytd": null,
"insights": {
"annual_gross_income": 12345.67,
"annual_net_income": 11234.56
},
"consistency_checks": {
"START_DATE_BEFORE_END_DATE": {
"boolean_value": true
},
"GROSS_PAY_YTD_GREATER_THAN_OR_EQUAL_TO_GROSS_PAY_CURRENT": {
"boolean_value": true
},
"NET_PAY_LESS_THAN_OR_EQUAL_TO_GROSS_PAY": {
"boolean_value": true
},
"COMPONENT_EARNINGS_LESS_THAN_OR_EQUAL_TO_TOTAL_GROSS_PAY": {
"boolean_value": true
},
"EMPLOYEE_NAME_EXISTS": {
"boolean_value": true
},
"EMPLOYER_NAME_EXISTS": {
"boolean_value": true
},
"START_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"END_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"PAY_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"START_DATE_EXISTS": {
"boolean_value": true
},
"END_DATE_EXISTS":{
"boolean_value": true
},
"PAY_DATE_EXISTS": {
"boolean_value": true
},
"GROSS_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTS": {
"boolean_value": true
},
"NET_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTS": {
"boolean_value": true
}
},
"irregularity_detection": {
"status": "DETECTED",
"reasons": [
{
"reason": "Edited Content Detected",
"severity": "Low Risk"
}
],
"file_type": "pdf",
"genuine_pdf": null,
"version": "3.0"
}
}
]
},
}
insights

An object containing various insights from the paystub.

FieldFormatNotes
annual_gross_incomeFloat or nullAnnualized gross income based on paystub information, rounded to 2 decimal places
annual_net_incomeFloat or nullAnnualized net income based on paystub information, rounded to 2 decimal places

Example:

{
"insights": {
"annual_gross_income": 12345.67,
"annual_net_income": 11234.56
}
}
consistency_checks

An object containing various consistency checks for the paystub. Each check contains an object with a a boolean_value representing whether the check has passed or not.

FieldNotes
START_DATE_BEFORE_END_DATEIndicates whether the start date of the pay period is before the end date of the pay period
GROSS_PAY_YTD_GREATER_THAN_OR_EQUAL_TO_GROSS_PAY_CURRENTIndicates whether the year to date gross earnings are greater than or equal to the gross earnings for the pay period
NET_PAY_LESS_THAN_OR_EQUAL_TO_GROSS_PAYIndicates whether the net earnings or less than or equal to the gross earnings
COMPONENT_EARNINGS_LESS_THAN_OR_EQUAL_TO_TOTAL_GROSS_PAYIndicates whether the sum of the earnings components is less than or equal to the total gross pay
EMPLOYEE_NAME_EXISTSIndicates whether the employee name was able to be determined from the paystub
EMPLOYER_NAME_EXISTSIndicates whether the employer name was able to be determined from the paystub
START_DATE_IS_VALID_DATEIndicates whether the start date of the pay period is an actual date on the Gregorian calendar
END_DATE_IS_VALID_DATEIndicates whether the end date of the pay period is an actual date on the Gregorian calendar
PAY_DATE_IS_VALID_DATEIndicates whether the pay date is an actual date on the Gregorian calendar
START_DATE_EXISTSIndicates whether the start date of the pay period was able to be determined from the paystub
END_DATE_EXISTIndicates whether the end date of the pay period was able to be determined from the paystub
PAY_DATE_EXISTSIndicates whether the pay date was able to be determined from the paystub
GROSS_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTSIndicates whether the gross total earnings was able to be determined from the paystub
NET_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTSIndicates whether the net total earnings was able to be determined from the paystub

Example:

{
"consistency_checks": {
"START_DATE_BEFORE_END_DATE": {
"boolean_value": true
},
"GROSS_PAY_YTD_GREATER_THAN_OR_EQUAL_TO_GROSS_PAY_CURRENT": {
"boolean_value": true
},
"NET_PAY_LESS_THAN_OR_EQUAL_TO_GROSS_PAY": {
"boolean_value": true
},
"COMPONENT_EARNINGS_LESS_THAN_OR_EQUAL_TO_TOTAL_GROSS_PAY": {
"boolean_value": true
},
"EMPLOYEE_NAME_EXISTS": {
"boolean_value": true
},
"EMPLOYER_NAME_EXISTS": {
"boolean_value": true
},
"START_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"END_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"PAY_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"START_DATE_EXISTS": {
"boolean_value": true
},
"END_DATE_EXISTS": {
"boolean_value": true
},
"PAY_DATE_EXISTS": {
"boolean_value": true
},
"GROSS_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTS": {
"boolean_value": true
},
"NET_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTS": {
"boolean_value": true
}
}
}
irregularity_detection

If Irregularity Detection is enabled, this node will contain details about any irregularities detected.

FieldFormatNotes
statusStringSee irregularity_detection_status values
reasonsArraySee irregularity_detection_reasons values
file_typeString or nullSee irregularity_detection_file_types values
genuine_pdfBoolean or nullTrue only if document is exceptionally genuine, not provided otherwise
versionStringThe version of the fraud algorithm used to generate the results

Example irregularity_detection field with status NOT_DETECTED and the genuine_pdf flag:

{
"irregularity_detection": {
"status": "NOT_DETECTED",
"reasons": [],
"file_type": "pdf",
"genuine_pdf": true,
"version": "3.0"
}
}

Example irregularity_detection field with status REVIEW:

{
"irregularity_detection": {
"status": "REVIEW",
"reasons": [
{
"reason": "Edited Content Detected",
"severity": "Low Risk"
}
],
"file_type": "pdf",
"genuine_pdf": null,
"version": "3.0"
}
}

Example irregularity_detection field with status DETECTED and multiple reasons:

{
"irregularity_detection": {
"status": "DETECTED",
"reasons": [
{
"reason": "Edited Content Detected",
"severity": "High Risk"
},
{
"reason": "Unusual Document Source Detected",
"severity": "Medium Risk"
}
],
"file_type": "pdf",
"genuine_pdf": null,
"version": "3.0"
}
}
irregularity detection reasons []

Specific reasons supporting the provided irregularity_detection status.

FieldFormatNotes
reasonStringSee the irregularity_detection_reason table
severityStringSee the irregularity_detection_severity table

payroll []

Income information derived from payroll data.

FieldFormatNotes
source_idStringThe identifier for the source that reported the payroll information. See sources
provider_nameStringName of the provider of payroll
annual_salary_rateFloat or nullEmployee annual salary rate as reported by the payroll provider. Will be null if not provided
estimated_gross_annual_incomeFloatEstimate of the gross annual income
estimated_net_annual_incomeFloatEstimate of the net annual income
pay_period_startFull Date or nullStart date of the current payroll pay period
pay_period_endFull Date or nullEnd date of the current payroll pay period
pay_frequencyStringSee pay_frequency table
statementsArraySee statements

Example:

{
"income": {
...
"payroll": [
{
"source_id": "USA_ATOMIC",
"provider_name": "ADP",
"annual_salary_rate": 45000.54,
"estimated_gross_annual_income": 47500.38,
"estimated_net_annual_income": 30000.12,
"pay_period_start": "2020-06-13",
"pay_period_end": "2020-06-27",
"pay_frequency": "WEEKLY",
"statements": [
{
"pay_date": "2020-06-30",
"gross_total_earnings_amount_current": 1225,
"gross_total_earnings_amount_ytd": 13625,
"net_total_earnings_amount_current": 840,
"net_total_earnings_amount_ytd": 8840
},
{
"pay_date": "2020-06-15",
"gross_total_earnings_amount_current": 1175,
"gross_total_earnings_amount_ytd": 12400,
"net_total_earnings_amount_current": 800,
"net_total_earnings_amount_ytd": 8000
}
]
}
]
}
}
statements []

A list of statement details

FieldFormatNotes
pay_dateFull DateDate the pay was issued
gross_total_earnings_amount_currentFloat or nullGross total earnings from current pay period
gross_total_earnings_amount_ytdFloat or nullGross total earnings from year to date pay period
net_total_earnings_amount_currentFloat or nullNet total earnings from current pay period
net_total_earnings_amount_ytdFloat or nullNet total earnings from year to date pay period

Example:

[
{
"pay_date": "2020-06-15",
"gross_total_earnings_amount_current": 1175,
"gross_total_earnings_amount_ytd": 12400,
"net_total_earnings_amount_current": 800,
"net_total_earnings_amount_ytd": 8000
}
]

revised_report_values

Income estimations that have been calculated manually by the Nova Credit Helpdesk in order to address a consumer's dispute. Only included when the report is regenerated due to it needing a correction to the income estimates.

Example revised_report_values field object when consumer has connected at least one bank account with sufficient transactions:

{
"revised_report_values": {
"gross_annual": 45000,
"net_annual": 32000,
"gross_recent": 49000,
"net_recent": 35000
}
}

Example revised_report_values field object when consumer has connected a payroll provider, or uploaded paystubs:

{
"revised_report_values": {
"gross_annual": 45000,
"net_annual": 32000
}
}

Income information computed by the Nova Credit Helpdesk.

FieldFormatNotes
gross_annualFloatGross income over the past twelve complete calendar months
net_annualFloatNet (take home) income over the past twelve complete calendar months
gross_recentFloatGross income over the past three complete calendar months annualized. Only included when the consumer has connected bank accounts.
net_recentFloatNet (take home) income over the past three complete calendar months annualized. Only included when the consumer has connected bank accounts.

account_details []

An array with each instance containing details about an account. The array can have zero objects, and there is no upper bound. To retrieve ACH info associated with an account_id, use the ACH Details Endpoint.

FieldFormatNotes
source_idUUIDThe identifier for the source that reported the account details
account_idUUIDUnique identifier for the account
owner_full_nameString or nullFull name of the owner of the account
institution_nameString or nullName of institution such as Chase or Bank of America
account_nameStringName of the account within the bank
account_typeString or nullType of the account within the bank. See account types
date_openedFull Date or nullDate the account was opened
truncated_account_numberString or nullIf available, the last four digits of the account number
responsibilityString or nullSee responsibility
addressesArraySee addresses
current_balanceFloat or nullCurrent balance of the account

Example:

{
"account_details": [{
"source_id": "USA_FIN",
"account_id": "36139831-0a91-4d1f-bc3e-edc908a978c6",
"owner_full_name": "John Doe",
"institution_name": "CHASE",
"account_name": "INVESTMENT ACCOUNT",
"account_type": "INVESTMENT",
"date_opened": "2015-05-01",
"truncated_account_number": "1234",
"responsibility": "INDIVIDUAL",
"addresses": [
{
"address_id": "80421b7e-7918-4963-b5fb-85055c2994b7",
"address": "225 Valencia St.",
"street": "Valencia St.",
"city": "San Francisco",
"zipcode": "94103",
"state": "CA"
}
],
"current_balance": 23422
},
...
],
}

addresses []

Addresses is a history of contact information attached to this account. Addresses are returned in an array, can have zero objects, and there is no upper bound.

FieldFormatNotes
address_idUUIDUnique identifier for the address
addressStringThe full mailing address of the account owner
streetStringThe street address where the account owner is located
cityStringThe city where the account owner is located
zipcodeStringThe zip code where the account owner is located
stateStringThe state where the account owner is located

Example:

{
"addresses": [{
"address_id": "80421b7e-7918-4963-b5fb-85055c2994b7",
"address": "225 Valencia St., San Francisco, CA 94103",
"street": "Valencia St.",
"city": "San Francisco",
"zipcode": "94103",
"state": "CA"
}],
},

Tables

account_type

Values of the account_type field.

Value
CASH_EQUIVALENT
CREDIT_CARD
INVESTMENT
INSTALLMENT
MORTGAGE
OTHER

employment_status

Values of the employment[].employment_status field.

Value
active
terminated

employment_type

Values of the employment[].employment_type field.

Value
contract
fulltime
parttime

inquiry_type

The human-readable labels are shown when creating and viewing products in the Nova Credit Dashboard. The value column shows the values that are returned in the JSON.

Human-readable labelValue
MonitoringMONITORING
Credit CardCREDIT_CARD
Vehicle AutoVEHICLE_AUTO
Vehicle OtherVEHICLE_OTHER
MortgageMORTGAGE
PersonalPERSONAL
StudentSTUDENT
UtilityUTILITY
CommercialCOMMERCIAL
ConsumerCONSUMER
Tenant ScreeningTENANT
OtherOTHER

model_type

Values of the model_type field.

ValueDescription
NOVA_INCOMEThe Nova Credit Income Model

pay_frequency

Values of the pay_frequency field.

Value
null
MONTHLY
BI_WEEKLY
WEEKLY
SEMI_MONTHLY

irregularity_detection_status

Values of the status field in the irregularity_detection node.

ValueDescription
NOT_DETECTEDNo irregularities were detected on the file
DETECTEDIrregularities were detected on the file
REVIEWMinor fraud indications detected, manual review recommended

irregularity_detection_file_type

Values of the file_type field in the irregularity_detection node.

Value
pdf
image
unsupported

irregularity_detection_reason

Values of the reason field in the irregularity_detection reasons node.

Value
Serial Fraud Detected
Edited Content Detected
Suspicious Modification Detected
Browser/Os Processed
No Textual Document Detected
Unusual Document Source Detected
Screenshot Detected
PDF/Image Converted
Suspicious Format Detected
Editing Software Detected
Others

irregularity_detection_severity

Values of the severity field in the irregularity_detection reasons node.

Value
High Risk
Medium Risk
Low Risk

job_irregularity_risk

Values of the job_irregularity_risk field.

ValueDescription
LOW_RISKThere is low risk that a consumer has recently experienced a disruption in income
MEDIUM_RISKThere is medium risk that a consumer has recently experienced a disruption in income
HIGH_RISKThere is high risk that a consumer has recently experienced a disruption in income
NOT_ENOUGH_DATAThere is insufficient data to determine if a consumer has recently experienced a disruption in income

responsibility

Values of the responsibility field.

ValueDescription
INDIVIDUALThe individual is solely responsible for the account
JOINTThe individual is jointly responsible for the account

source_id

A human-readable identifier for the source, unique within the context of the report.

ValueDescription
MANUALData was manually entered by the applicant
OCROLUSData was sourced from an uploaded paystub
USA_AKOYAData was sourced from a bank connection through Akoya
USA_ARGYLEData was sourced from a payroll provider through Argyle
USA_ATOMICData was sourced from a payroll provider through Atomic
USA_FINData was sourced from a bank connection through Finicity
USA_MXData was sourced from a bank connection through MX
USA_RAIData was sourced through Resistant AI

source_type

Values of the source_type field.

ValueDescription
BANK_TRANSACTIONData was sourced from a bank connection
EMPLOYMENTData was sourced from an uploaded paystub
FRAUDData was sourced from fraud analysis
PAYROLLData was sourced from a payroll provider
MANUALData was manually entered by the applicant

status

  • Terminal means that this status is final and will not change
  • Report Available means that a report can be retrieved for the Visit
  • Webhook means that there is a webhook available for this status
StatusDescriptionTerminal?Report Available?Webhook?
INVITEDThe applicant has been sent an invite, such as through the Invite API or in the Nova Dashboard
INITIALIZEDThe /connect/initialization endpoint has been used
PENDINGA visit has been initialized upon opening the NovaConnect widget
SUCCESSThe data source has successfully provided information on the applicant
EXPIREDThe visit has expired before the applicant was able to complete the flow. This will be sent if no completion 72 hours after initial widget opened, invite sent, or initialization endpoint called
NOT_AUTHENTICATEDThe applicant was unable to verify their identity.
NON_CONTRIBUTING_APPLICANTThe applicant selected to not contribute income.
ERRORAn error occurred and the Income Navigator Report could not be compiled. If there isn't a detailed substatus, send a message to your Nova Credit Representative with the publicToken
SUPPLIER_UNRESPONSIVEThe applicant has encountered a data supplier outage while going through the widget. They may need to go through NovaConnect again at a later time

substatus

Additional insight on certain cases that occur when fetching or parsing a report.

These substatuses may accompany a report with a SUCCESS status.

ValueIncome Model Suite Version 1.1 & 1.2**Income Model Suite Version 2.0 **
ACCOUNT_TOO_NEW
  • The account(s) linked do not have any inflow transactions that are older than 3 months.
  • The income node will be attached.
  • The account(s) linked do not have any inflow transactions that are older than 1 month.
  • The income node will be attached and have null values.
NO_RECENT_USABLE_INFORMATION
  • There are no transactions or accounts for this report.
  • The income node will not be attached.
  • The account(s) linked do not have any inflow transactions.
  • The income node will not be attached.
NO_USABLE_INCOME_INFORMATION
  • There are no income streams for this report with sufficient confidence scores or the income data cannot be grouped into streams.
  • The income node will not be attached.
  • There are no inflows that can be classified as income.
  • The income node will be attached and have 0 values.

Note: Contact your account team to determine which description applies based on your income model version

These substatuses may accompany a webhook with a NON_CONTRIBUTING_APPLICANT status:

ValueDescription
COAPPLICANT_GUARANTOR_PROVIDINGThe applicant selected to not contribute income because their co-applicant or guarantor will provide income instead.

These substatuses may accompany a webhook with an ERROR status:

ValueDescription
INCOMPATIBLE_ACCOUNT_TYPES_SUBMITTEDThe user only submitted debt accounts (e.g. credit card).
INCOMPLETE_INFORMATIONThe source did not provide critical fields
INVALID_PREFILLS_PII_MISSINGPrefills required for the IN Report are missing.
INVALID_PREFILL_KEYA prefill field has been passed in that is not supported for the current API version. (Only returned in sandbox.)
INVALID_PREFILL_ADDRESSThe address sent via prefill must be a string with max length 100 characters and contain a valid street address.
INVALID_PREFILL_CITYThe city sent via prefill must be a string with max length 100.
INVALID_PREFILL_DOBThe birthday sent via prefill is missing or not in YYYY-MM-DD format.
INVALID_PREFILL_EMAILThe email sent via prefill must be a valid email with max length 100 characters.
INVALID_PREFILL_FIRST_NAMEThe first name sent via prefill must be a string less than 255 characters and contain only alphabetical, unicode, dots, apostraphes and dashes.
INVALID_PREFILL_LAST_NAMEThe last name sent via prefill must be a string less than 255 characters and contain only alphabetical, unicode, dots, apostraphes and dashes.
INVALID_PREFILL_INCOMEThe stated annual income sent via prefill must be an integer between 0 and 2147483647.
INVALID_PREFILL_PHONEThe phone number sent via prefill must be a string with max length 255 characters.
INVALID_PREFILL_STATEThe state sent via prefill is missing or not in a valid two letter US state or territory code.
INVALID_PREFILL_ZIPThe zip code sent via prefill must a string with a valid USA zip code.
MFA_REQUIRED_ON_FETCHThe bank account the user tried to connect to requires multi-factor authentication and may depend on the user's browser security settings.

Report Examples

Bank Account

Here's an example response where a user has gone through NovaConnect and connected their bank account.

{
"meta": {
"public_token": "65bf7135-4eb8-4342-a7c2-0380322b3d59",
"user_args": null,
"created_at": "2025-02-07T23:10:51.987Z",
"api_version": "2.0.0",
"status": "SUCCESS",
"substatus": null,
"external_id": null,
"nova_report_revision": null
},
"product": {
"name": "Village Communities",
"product_id": "12d1e755-3d82-445d-84e6-b67b5ff7c70d",
"inquiry_type": "TENANT"
},
"sources": [
{
"source_id": "USA_FIN",
"source_type": "BANK_TRANSACTION",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "MANUAL",
"status": "SUCCESS"
}
],
"identities": [
{
"source_id": "CONSUMER_INPUT",
"source_record_id": null,
"first_name": "raymond",
"last_name": "Marshal",
"full_name": "raymond Marshal",
"emails": ["raymond@email.com"],
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "USA_FIN",
"source_record_id": null
}
],
"unmatched_sources": []
}
}
},
{
"source_id": "USA_FIN",
"source_record_id": null,
"first_name": null,
"last_name": null,
"full_name": "RAYMOND MARSHAL",
"emails": []
},
{
"source_id": "USA_FIN",
"source_record_id": null,
"first_name": null,
"last_name": null,
"full_name": "RAYMOND MARSHAL MARINA MARSHAL",
"emails": []
}
],
"account_details": [
{
"source_id": "USA_FIN",
"account_id": "fd058f61-56d3-4150-ad9f-ff899b55f799",
"owner_full_name": "RAYMOND MARSHAL",
"institution_name": "Personal Loan Account",
"account_name": "Checking Account",
"account_type": "CASH_EQUIVALENT",
"date_opened": null,
"truncated_account_number": "475462",
"responsibility": "INDIVIDUAL",
"addresses": [
{
"address_id": "6d4d5fff-25ee-4ba0-8247-9bc75b900378",
"address": "5445 ALTON PKWY IRVINE CA 92614",
"street": null,
"city": null,
"zipcode": null,
"state": null
}
],
"current_balance": 577.63
},
{
"source_id": "USA_FIN",
"account_id": "c100e365-5838-40bc-a8a5-c70be5ebf5f8",
"owner_full_name": "RAYMOND MARSHAL MARINA MARSHAL",
"institution_name": "Personal Loan Account",
"account_name": "Credit Card Account",
"account_type": "INVESTMENT",
"date_opened": null,
"truncated_account_number": "108249",
"responsibility": "JOINT",
"addresses": [
{
"address_id": "ee64a0fe-985b-4f92-acad-603a951ddb9e",
"address": "5445 ALTON PKWY IRVINE CA 92614",
"street": null,
"city": null,
"zipcode": null,
"state": null
}
],
"current_balance": 6300
}
],
"income": {
"summary": {
"annual_gross_income": 10824,
"annual_net_income": 6121
},
"financial_accounts": [
{
"source_ids": ["USA_FIN"],
"model_version": "1.1.0",
"model_type": "NOVA_INCOME",
"descriptions": ["uber"],
"is_consistent": false,
"net_recent": 5525,
"gross_recent": 9770,
"net_annual": 6121,
"gross_annual": 10824,
"history": [
{
"year": 2025,
"gross": [null, null, null, null, null, null, null, null, null, null, 0, 0],
"net": [null, null, null, null, null, null, null, null, null, null, 0, 0]
},
{
"year": 2024,
"gross": [2442, 0, 0, 2120, 0, 2146, 2015, 0, 0, 0, 2101, 2053],
"net": [1381, 0, 0, 1199, 0, 1213, 1139, 0, 0, 0, 1188, 1161]
},
{
"year": 2023,
"gross": [0, 2357, 0, 1973, null, null, null, null, null, null, null, null],
"net": [0, 1339, 0, 1121, null, null, null, null, null, null, null, null]
}
]
}
]
}
}

Pay Stub Upload

{
"meta": {
"public_token": "753c4285-9331-4502-b02b-5064904f33ce",
"user_args": null,
"created_at": "2025-02-07T23:47:23.151Z",
"api_version": "2.0.0",
"status": "SUCCESS",
"substatus": null,
"external_id": null,
"nova_report_revision": null
},
"product": {
"name": "Village Communities",
"product_id": "a8be4941-04a7-405f-b066-48313c7b003b",
"inquiry_type": "OTHER"
},
"sources": [
{
"source_id": "OCROLUS",
"source_type": "EMPLOYMENT",
"status": "SUCCESS"
},
{
"source_id": "USA_RAI",
"source_type": "FRAUD",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "MANUAL",
"status": "SUCCESS"
}
],
"identities": [
{
"source_id": "CONSUMER_INPUT",
"source_record_id": null,
"first_name": "Emelia",
"last_name": "Gutierrez",
"full_name": "Emelia Gutierrez",
"emails": ["emelia@email.com"],
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "OCROLUS",
"source_record_id": "c1367efa-baac-40d5-88f7-7cc680b12509"
}
],
"unmatched_sources": []
}
}
},
{
"source_id": "OCROLUS",
"source_record_id": "c1367efa-baac-40d5-88f7-7cc680b12509",
"first_name": null,
"last_name": null,
"full_name": "EMELIA GUTIERREZ",
"emails": []
}
],
"employment": [
{
"source_id": "OCROLUS",
"source_record_id": "c1367efa-baac-40d5-88f7-7cc680b12509",
"employer_name": "INITECH CORPORATION",
"employer_address_line_1": "1 INITECH WAY",
"employer_address_line_2": null,
"employer_city": "AUSTIN",
"employer_state": "TX",
"employment_type": null,
"employment_status": null,
"job_title": null,
"hire_date": null,
"estimated_hire_date": null
}
],
"income": {
"summary": {
"annual_gross_income": 64910.86,
"annual_net_income": 41518.01
},
"paystubs": [
{
"source_id": "OCROLUS",
"source_record_id": "c1367efa-baac-40d5-88f7-7cc680b12509",
"source_filepath": "36c29b7c-b241-494f-b853-f17b4b1bb718/936def0c-27e0-4c19-a306-aa57eb25dca8.jpg",
"employee_name": "EMELIA GUTIERREZ",
"employee_address_line_1": "123 FRANKLIN ST",
"employee_address_line_2": "APT 4",
"employee_city": "AUSTIN",
"employee_state": "TX",
"employee_zip": "73301",
"pay_period_start": "2025-01-16",
"pay_period_end": "2025-01-31",
"pay_date": "2025-01-31",
"pay_frequency": "SEMI_MONTHLY",
"paystub_provider": "ADP",
"hire_date": null,
"net_total_earnings_amount_current": 1040.23,
"net_total_earnings_amount_ytd": 18396.25,
"gross_total_earnings_amount_current": 1627.74,
"gross_total_earnings_amount_ytd": 28707.21,
"regular_pay_earnings_amount_current": 1515.84,
"regular_pay_earnings_amount_ytd": 24743.49,
"bonus_earnings_amount_current": 40.69,
"bonus_earnings_amount_ytd": 325.27,
"overtime_earnings_amount_current": 0,
"overtime_earnings_amount_ytd": 442.54,
"commission_earnings_amount_current": null,
"commission_earnings_amount_ytd": null,
"paid_time_off_earnings_amount_current": 0,
"paid_time_off_earnings_amount_ytd": 1459.97,
"vacation_earnings_amount_current": 71.21,
"vacation_earnings_amount_ytd": 952.9,
"paid_time_off_deductions_amount_current": null,
"paid_time_off_deductions_amount_ytd": null,
"vacation_deductions_amount_current": null,
"vacation_deductions_amount_ytd": null,
"medicare_tax_deductions_amount_current": 22.12,
"medicare_tax_deductions_amount_ytd": 394.81,
"social_security_deductions_amount_current": 94.58,
"social_security_deductions_amount_ytd": 1688.15,
"fica_tax_deductions_amount_current": null,
"fica_tax_deductions_amount_ytd": null,
"insights": {
"annual_gross_income": 64910.86,
"annual_net_income": 41518.01
},
"consistency_checks": {
"START_DATE_BEFORE_END_DATE": {
"boolean_value": true
},
"GROSS_PAY_YTD_GREATER_THAN_OR_EQUAL_TO_GROSS_PAY_CURRENT": {
"boolean_value": true
},
"NET_PAY_LESS_THAN_OR_EQUAL_TO_GROSS_PAY": {
"boolean_value": true
},
"COMPONENT_EARNINGS_LESS_THAN_OR_EQUAL_TO_TOTAL_GROSS_PAY": {
"boolean_value": true
},
"EMPLOYEE_NAME_EXISTS": {
"boolean_value": true
},
"EMPLOYER_NAME_EXISTS": {
"boolean_value": true
},
"START_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"END_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"PAY_DATE_IS_VALID_DATE": {
"boolean_value": true
},
"START_DATE_EXISTS": {
"boolean_value": true
},
"END_DATE_EXISTS": {
"boolean_value": true
},
"PAY_DATE_EXISTS": {
"boolean_value": true
},
"GROSS_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTS": {
"boolean_value": true
},
"NET_TOTAL_EARNINGS_AMOUNT_CURRENT_EXISTS": {
"boolean_value": true
}
},
"irregularity_detection": {
"status": "NOT_DETECTED",
"reasons": [],
"file_type": "pdf",
"genuine_pdf": true,
"version": "3.0"
}
}
]
}
}

Payroll

{
"meta": {
"public_token": "5a6f89d5-8a1e-42af-adeb-f22312638bb9",
"user_args": null,
"created_at": "2025-02-08T00:06:22.076Z",
"api_version": "2.0.0",
"status": "SUCCESS",
"substatus": null,
"external_id": null,
"nova_report_revision": null
},
"product": {
"name": "Village Communities",
"product_id": "422ecccb-942a-47ff-ab73-8a5285c3b2b4",
"inquiry_type": "OTHER"
},
"sources": [
{
"source_id": "USA_ATOMIC",
"source_type": "PAYROLL",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "MANUAL",
"status": "SUCCESS"
}
],
"identities": [
{
"source_id": "CONSUMER_INPUT",
"source_record_id": null,
"first_name": "Jane",
"last_name": "Appleseed",
"full_name": "Jane Appleseed",
"emails": ["janeappleseed@example.com"],
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "USA_ATOMIC",
"source_record_id": null
}
],
"unmatched_sources": []
}
}
},
{
"source_id": "USA_ATOMIC",
"source_record_id": null,
"first_name": "Jane",
"last_name": "Appleseed",
"full_name": null,
"emails": ["janeappleseed@example.com"]
}
],
"employment": [
{
"source_id": "USA_ATOMIC",
"source_record_id": null,
"employer_name": "Enterprise One",
"employer_address_line_1": "12345 Enterprise Rd",
"employer_address_line_2": "Suite 105",
"employer_city": "Salt Lake City",
"employer_state": "UT",
"employment_type": "fulltime",
"employment_status": "active",
"job_title": "Logistics",
"hire_date": "2023-01-01",
"estimated_hire_date": null
}
],
"income": {
"summary": {
"annual_gross_income": 60000,
"annual_net_income": 47400
},
"payroll": [
{
"source_id": "USA_ATOMIC",
"provider_name": "Paytomic",
"annual_salary_rate": 60000,
"estimated_gross_annual_income": 60000,
"estimated_net_annual_income": 47400,
"pay_period_start": "2025-01-01",
"pay_period_end": "2025-01-31",
"pay_frequency": "MONTHLY",
"statements": [
{
"pay_date": "2025-01-31",
"gross_total_earnings_amount_current": 5000,
"gross_total_earnings_amount_ytd": 10000,
"net_total_earnings_amount_current": 3950,
"net_total_earnings_amount_ytd": 7900
},
{
"pay_date": "2025-01-01",
"gross_total_earnings_amount_current": 5000,
"gross_total_earnings_amount_ytd": 5000,
"net_total_earnings_amount_current": 3950,
"net_total_earnings_amount_ytd": 3950
},
{
"pay_date": "2024-12-02",
"gross_total_earnings_amount_current": 5000,
"gross_total_earnings_amount_ytd": 60000,
"net_total_earnings_amount_current": 3950,
"net_total_earnings_amount_ytd": 47400
}
]
}
]
}
}

Revised Income

Here's are some example responses where a report was regenerated with manually computed revisions to the income estimates due to a dispute by the consumer.

Bank Account

Here's an example regenerated bank account report.

{
"meta": {
"public_token": "65bf7135-4eb8-4342-a7c2-0380322b3d59",
"user_args": null,
"created_at": "2025-02-07T23:10:51.987Z",
"api_version": "2.0.0",
"status": "SUCCESS",
"substatus": null,
"external_id": null,
"nova_report_revision": "1"
},
"product": {
"name": "Village Communities",
"product_id": "12d1e755-3d82-445d-84e6-b67b5ff7c70d",
"inquiry_type": "TENANT"
},
"sources": [
{
"source_id": "USA_FIN",
"source_type": "BANK_TRANSACTION",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "MANUAL",
"status": "SUCCESS"
}
],
"identities": [
{
"source_id": "CONSUMER_INPUT",
"source_record_id": null,
"first_name": "raymond",
"last_name": "Marshal",
"full_name": "raymond Marshal",
"emails": ["raymond@email.com"],
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "USA_FIN",
"source_record_id": null
}
],
"unmatched_sources": []
}
}
},
{
"source_id": "USA_FIN",
"source_record_id": null,
"first_name": null,
"last_name": null,
"full_name": "RAYMOND MARSHAL",
"emails": []
},
{
"source_id": "USA_FIN",
"source_record_id": null,
"first_name": null,
"last_name": null,
"full_name": "RAYMOND MARSHAL MARINA MARSHAL",
"emails": []
}
],
"account_details": [
{
"source_id": "USA_FIN",
"account_id": "fd058f61-56d3-4150-ad9f-ff899b55f799",
"owner_full_name": "RAYMOND MARSHAL",
"institution_name": "Personal Loan Account",
"account_name": "Checking Account",
"account_type": "CASH_EQUIVALENT",
"date_opened": null,
"truncated_account_number": "475462",
"responsibility": "INDIVIDUAL",
"addresses": [
{
"address_id": "6d4d5fff-25ee-4ba0-8247-9bc75b900378",
"address": "5445 ALTON PKWY IRVINE CA 92614",
"street": null,
"city": null,
"zipcode": null,
"state": null
}
],
"current_balance": 577.63
},
{
"source_id": "USA_FIN",
"account_id": "c100e365-5838-40bc-a8a5-c70be5ebf5f8",
"owner_full_name": "RAYMOND MARSHAL MARINA MARSHAL",
"institution_name": "Personal Loan Account",
"account_name": "Credit Card Account",
"account_type": "INVESTMENT",
"date_opened": null,
"truncated_account_number": "108249",
"responsibility": "JOINT",
"addresses": [
{
"address_id": "ee64a0fe-985b-4f92-acad-603a951ddb9e",
"address": "5445 ALTON PKWY IRVINE CA 92614",
"street": null,
"city": null,
"zipcode": null,
"state": null
}
],
"current_balance": 6300
}
],
"income": {
"summary": {
"annual_gross_income": 10824,
"annual_net_income": 6121
},
"financial_accounts": [
{
"source_ids": ["USA_FIN"],
"model_version": "1.1.0",
"model_type": "NOVA_INCOME",
"descriptions": ["uber"],
"is_consistent": false,
"net_recent": 5525,
"gross_recent": 9770,
"net_annual": 6121,
"gross_annual": 10824,
"history": [
{
"year": 2025,
"gross": [null, null, null, null, null, null, null, null, null, null, 0, 0],
"net": [null, null, null, null, null, null, null, null, null, null, 0, 0]
},
{
"year": 2024,
"gross": [2442, 0, 0, 2120, 0, 2146, 2015, 0, 0, 0, 2101, 2053],
"net": [1381, 0, 0, 1199, 0, 1213, 1139, 0, 0, 0, 1188, 1161]
},
{
"year": 2023,
"gross": [0, 2357, 0, 1973, null, null, null, null, null, null, null, null],
"net": [0, 1339, 0, 1121, null, null, null, null, null, null, null, null]
}
]
}
],
"revised_report_values": {
"gross_annual": 45000,
"net_annual": 32000,
"gross_recent": 49000,
"net_recent": 35000
}
}
}

Payroll

Here's an example regenerated payroll report.

{
"meta": {
"public_token": "5a6f89d5-8a1e-42af-adeb-f22312638bb9",
"user_args": null,
"created_at": "2025-02-08T00:06:22.076Z",
"api_version": "2.0.0",
"status": "SUCCESS",
"substatus": null,
"external_id": null,
"nova_report_revision": "1"
},
"product": {
"name": "Village Communities",
"product_id": "422ecccb-942a-47ff-ab73-8a5285c3b2b4",
"inquiry_type": "OTHER"
},
"sources": [
{
"source_id": "USA_ATOMIC",
"source_type": "PAYROLL",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "MANUAL",
"status": "SUCCESS"
}
],
"identities": [
{
"source_id": "CONSUMER_INPUT",
"source_record_id": null,
"first_name": "Jane",
"last_name": "Appleseed",
"full_name": "Jane Appleseed",
"emails": ["janeappleseed@example.com"],
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "USA_ATOMIC",
"source_record_id": null
}
],
"unmatched_sources": []
}
}
},
{
"source_id": "USA_ATOMIC",
"source_record_id": null,
"first_name": "Jane",
"last_name": "Appleseed",
"full_name": null,
"emails": ["janeappleseed@example.com"]
}
],
"employment": [
{
"source_id": "USA_ATOMIC",
"source_record_id": null,
"employer_name": "Enterprise One",
"employer_address_line_1": "12345 Enterprise Rd",
"employer_address_line_2": "Suite 105",
"employer_city": "Salt Lake City",
"employer_state": "UT",
"employment_type": "fulltime",
"employment_status": "active",
"job_title": "Logistics",
"hire_date": "2023-01-01",
"estimated_hire_date": null
}
],
"income": {
"summary": {
"annual_gross_income": 60000,
"annual_net_income": 47400
},
"payroll": [
{
"source_id": "USA_ATOMIC",
"provider_name": "Paytomic",
"annual_salary_rate": 60000,
"estimated_gross_annual_income": 60000,
"estimated_net_annual_income": 47400,
"pay_period_start": "2025-01-01",
"pay_period_end": "2025-01-31",
"pay_frequency": "MONTHLY",
"statements": [
{
"pay_date": "2025-01-31",
"gross_total_earnings_amount_current": 5000,
"gross_total_earnings_amount_ytd": 10000,
"net_total_earnings_amount_current": 3950,
"net_total_earnings_amount_ytd": 7900
},
{
"pay_date": "2025-01-01",
"gross_total_earnings_amount_current": 5000,
"gross_total_earnings_amount_ytd": 5000,
"net_total_earnings_amount_current": 3950,
"net_total_earnings_amount_ytd": 3950
},
{
"pay_date": "2024-12-02",
"gross_total_earnings_amount_current": 5000,
"gross_total_earnings_amount_ytd": 60000,
"net_total_earnings_amount_current": 3950,
"net_total_earnings_amount_ytd": 47400
}
]
}
],
"revised_report_values": {
"gross_annual": 65000,
"net_annual": 49000
}
}
}

Sandbox Environment

The sandbox environment provides a safe testing space to integrate and validate your implementation before going to production. This guide covers everything you need to know about testing in sandbox mode.

Overview

The sandbox environment allows you to:

  • Access predefined test user profiles with different data scenarios
  • Simulate various response states and error conditions
  • Validate your webhook integration
  • Test our paystub, payroll, or multi-aggregator bank connection methods (Finicity, Akoya, and MX)

For general information about sandbox vs. production environments, see the Quickstart Guide.

Accessing Sandbox Reports

To retrieve a sandbox report, you must provide specific test user information through the NovaConnect widget's prefill functionality. The prefill data can match one of our predefined test profiles exactly. If the prefill data is different from the user profile you select in the UI, it will appear in unmatched sources in the matching[] section of the report. You could also prefill using a test email you have access to, that will help you go through the end-to-end user journey.

Required Information

Each test user requires the following prefill fields:

  • firstName - The test user's first name
  • lastName - The test user's last name
  • dateOfBirth - Date of birth in YYYY-MM-DD format
  • email - The test user's email address
  • state - The test user's state

Learn more about implementing prefill in the Quickstart Guide.

Bank Accounts

We provide eight test user profiles, each designed to simulate different financial scenarios:

Profile TypeFirst NameLast NameDate of BirthEmailStateStated EmployerScenarioSupplier Testing Available
Default UserRaymondMarshal1995-10-01raymond@email.comCARaymond's DesignsComplete financial profile with typical transaction historyFinicity
Single Primary AccountSarahSingle1986-10-12sarah@email.comWABoeingSingle checking account with standard transactionsAkoya & Finicity
Multi-AccountMikeMany1992-05-08mike@email.comTXTargetMultiple accounts (checking, savings, investment)Akoya & Finicity
Joint AccountJasonJoint1976-03-09jason@email.comILMicrosoftJoint account ownership with shared responsibilityAkoya & Finicity
Debt Account LinkedDerekDebt1984-04-12derek@email.comTXCharles SchwabProfile with linked debt accounts (credit cards)Finicity
No IncomeNolanNoTransactions1992-03-07nolan@email.comILOptionalAccount with no transaction historyFinicity
Default UserCoryAnders1989-10-25cory@email.comNYOptionalComplete financial profile with typical transaction historyMX
New AccountNancyNewman1961-07-04nancy@email.comCAJ IndustriesAccount with less than one month of transactionsAkoya

Supplier specific testing:

If testing multiple aggregators in sandbox mode, you will need to select a bank before being routed to select one of the pre-configured test profiles above to simulate results. Please select FinBank to connect with Finicity, Mikomo to connect with Akoya, and MX Bank to connect with MX. If you are provided with a login screen, use the following credentials:

  • Username: demo
  • Password: go

Simulating Error States

You can trigger specific error conditions by using special values in the lastName field:

Expired Session

  • Last Name expiresoon
  • Result: Triggers an EXPIRED status in 5 minutes instead of the standard 72 hours
  • Use Case: Test timeout handling in your integration

Supplier Unresponsive

  • Choose FinBank
  • Pass Last Name: supplierdown
  • Result: Triggers a SUPPLIER_UNRESPONSIVE status
  • Use Case: Test error handling for aggregator connection failures

Paystub Upload

For testing purposes on the paystub upload page of the Income Navigator widget, we have provided a set of filename combinations that correspond with different outcomes. These are as follows:

FilenamePaystub OutcomeDetect Outcome
emeliaSUCCESS (default paystub)NOT_DETECTED
emelia_detectedSUCCESS (default paystub)DETECTED
emptyNOT_AUTHENTICATED (empty paystub)N/A
marieSUCCESS (thin file paystub)NOT_DETECTED
larrySUCCESS (low income paystub)NOT_DETECTED
downBUREAU_UNRESPONSIVEN/A
missingfieldsSUCCESS (paystub which is missing fields)NOT_DETECTED
Any other filenameNOT_AUTHENTICATEDN/A

In addition to these filename combinations, we have provided inputs to trigger more complex irregularity detection outcomes.

These inputs should be passed in directly using prefill values, and can be used in combination with the filenames above. Using the emelia_detected filename will always result in an outcome of DETECTED.

For each outcome below, use a Prefill First Name of getAdaptiveDecisionResult.

Prefill Last NameFile TypeIrregularity Detection Status
pdfTrustedpdfNOT_DETECTED
pdfHighRiskpdfDETECTED
pdfWarningApprovedpdfREVIEW
imageTrustedimageNOT_DETECTED
imageHighRiskManualReviewimageDETECTED

Payroll Accounts

USA_ATOMIC

We provide multiple sandbox users for testing: Jane, Alice and Paddy.

To access the reports please pass the first names via Prefill Keys, and then choose Test User on the Atomic Simulator page. If you do not enter a name for any of the sandbox users, we will default to the "Jane" report.

Here is some information about each sandbox report:

Report InfoJane (Default)AlicePaddyJimmyPatricia
Employment Statusactiveterminatedactiveactiveactive
Employment Typefulltimefulltimefulltimefulltimefulltime
Annual Income6000021612156013.213000052000
Pay Frequencymonthlysemimonthlysemimonthlybiweeklyweekly
NovaConnect Testing

If you are using the sandbox environment, you will see a special Atomic Simulator page instead of the Atomic Widget. This page contains multiple options for testing different widget states. You can test success flows, cascade and various Atomic failure states.

If you are performing production testing, then you can use the Atomic Widget to trigger different testing scenarios. Here is a list of different test cases. The test cases should work for any source provider as long as you enter the name and phone number as specified for each test case.

USA_ARGYLE

We provide multiple sandbox users for testing: Cory, Alex, Sylvia, Cassie, Sarah, Michael, Emma, David, and Lisa.

To access the reports please pass the first names via Prefill Keys, and then choose Test User on the Argyle Simulator page. If you do not enter a name for any of the sandbox users, we will default to the "Cory" report.

Here is some information about each sandbox report:

Report InfoCory (Default)AlexSylviaCassieSarahMichaelEmmaDavidLisa
Employment Statusactiveactiveactiveactiveterminatedactiveactiveactiveactive
Employment Typefulltimefulltimecontractorcontractorfulltimefulltimefulltimeparttimefulltime
Provider TypeStandardMost CommonGig (Uber)Gig (DoorDash)Most Common2nd Most CommonEnterpriseSMBSMB
Pay Frequencyvariousbiweeklyirregularirregularbiweeklysemimonthlymonthlyweeklybiweekly
Special FeaturesDefault userMissing paystubs6mo historyNo paystubsTerminated 3moQuarterly bonusYTD amountsVariable OTVariable hours

Webhooks

Webhooks are the mechanism that Nova Credit uses to inform you of core initialization and completion steps for each NovaConnect widget interaction. A session is initialized when the NovaConnect widget is opened. One session can consist of multiple suppliers, and these supplier-flow outcomes are recorded and attached to the webhook body in the history node.

We make a POST API call to the webhook callback URL that you provide. Webhooks can be managed in the Developer tab on the Nova Credit Dashboard, where you must set your callback URL and can toggle your various event subscriptions on and off. Some events or statuses are subscribed to by default.

Webhook Event Types

Each Webhook API call will contain one of the event types listed below in the JSON body:

Event TypeDescription
VISITA single NovaConnect widget interaction, which can consist of multiple suppliers. Only one terminal status outcome is sent per widget open; other supplier-flow outcomes are recorded and attached to the webhook in the history node
REGENERATED_VISITOnly occurs for reports that have been regenerated. This event type also includes a novaReportRevision in the webhook body.

Webhook Status Codes

View the status table to see the full list of statuses, with the "Webhook" column representing which ones correspond to a webhook call.

Webhook Body

Webhook Body KeyDescription
eventTypeEvent Type (see event type table above) corresponding to this webhook
statusStatus (see status code table above) corresponding to this webhook
substatusA more detailed status. See substatus types
publicTokenUnique UUID associated with this status, which can be used to retrieve the Nova Credit report
externalIdOptional unique identifier passed in by the Nova Credit customer (you) with this application. This key will only be present if externalId was passed in
userArgsOptional string passed in by the Nova Credit customer (you) with this application. This key will only be present if userArgs was passed in
eventIdUnique ID for the webhook
eventCreatedTimeWebhook event timestamp
reportTypeThe type of Nova Credit report.
historyAn array containing 1 or more objects, containing data on all of the statuses an applicant has reached within one Income Navigator widget instance, sorted by most recent to least recent
history.eventTypeEach history object will have a SUPPLIER event type
history.companyCodeData supplier for this history object
history.dateAttemptedTimestamp marking when this corresponding history object was begun
history.statusStatus (see status code table above) corresponding to this history object
history.substatusA more detailed status. See substatus types

Note that the status will be informed by the most recent supplier event status.

Example:

{
eventType: 'VISIT',
status: 'SUCCESS',
publicToken: '6b986690-458b-11e7-98fb-a71570ea65a6',
externalId: '25ad7063-fe76-437a-b4d8-3662ba4cc9c7',
userArgs: '235234224',
eventId: '028d9354-3991-46c4-97df-bd6c2ff09733',
eventCreatedTime: '2019-09-26T33:15:23.17Z',
history: [
{
eventType: 'SUPPLIER',
status: 'SUCCESS',
companyCode: 'USA_FIN',
dateAttempted: '2019-09-26T19:20:00.00Z' // newest timestamp
},
{
eventType: 'SUPPLIER',
status: 'PENDING',
companyCode: 'USA_FIN',
dateAttempted: '2019-09-26T19:18:00.00Z' // oldest timestamp
}
]
}

Webhook Failures

When a webhook fails we retry posting with an exponential increase in the time between each attempt. For example, the first retry happens after 1 second, the second after 2 seconds etc.

Number of AttemptsTime Until Retry if Unsuccessful
11 second
22 seconds
34 seconds
48 seconds
......

This strategy allows for several retries within a few minutes but expands to daily retries in the case of an outage, allowing customers to restore before receiving the callback. However, if a callback is still unsuccessful after one week we do not continue retrying.

For more information, please visit the server integration section in our Quickstart Guide.

Webhook Signature

Nova Credit optionally signs webhook payloads in order to allow for trust verification of inbound webhook requests.

When configured, the webhook request will contain these additional headers:

HeaderValue
X-Timestamptimestamp of request generation
X-Nova-SignatureSHA256 HMAC digest of request timestamp and payload, period-delimited. Your Webhook Signatures Secret Key is found under the Webhooks section on the Developer tab of your Nova Credit Dashboard.

Please contact your Nova Credit account manager to enable this feature.

Example verification of signature:

const crypto = require('crypto');

const signature = req.get('X-Nova-Signature');
const timestamp = req.get('X-Timestamp');

const checkPayload = `${timestamp}.${JSON.stringify(req.body)}`;
const checkDigest = crypto.createHmac('sha256', '< webhook secret key >')
.update(checkPayload)
.digest('base64');

return crypto.timingSafeEquals(signature, checkDigest);

For more information, please visit the server integration section in our Quickstart Guide.

Error Codes & Responses

At Nova Credit, we distinguish between two status message deliveries:

  1. Delivered by Nova Credit to the webhook
  2. If you call a resource endpoint Nova Credit provides a status in the response

Resource Endpoint Errors

When an error occurs while calling the endpoints the Nova Credit servers send back a JSON object with the following format:

{
"error": "UNKNOWN_CUSTOMER",
"terminated": true
}

Error Codes

The Nova Credit endpoints return the following HTTP status codes and error messages:

HTTP Status CodeErrorDescription
200-The request was successful.
400MALFORMED_HEADERSThe request headers are incorrectly formatted.
400MISSING_INPUTAn input is missing that the endpoint expected.
400INVALID_PUBLIC_IDThe public ID is not valid.
401EXPIRED_TOKENThe access_token you're sending in the request headers has expired. Please request a new one.
403UNKNOWN_CUSTOMERThe public_id or client_id Nova Credit received in the request from is not recognized. Check your credentials in the Nova Credit Dashboard.
403UNAUTHORIZEDThe client_id and secret_key combination is not recognized. Check your credentials in the Nova Credit Dashboard.
403ORIGIN_UNAUTHORIZEDThe origin of the request is not whitelisted on the Nova Credit servers for CORS.
404INVALID_EXTERNAL_IDThe external ID is not valid.
404INVALID_TOKENThe public_token or access_token is not valid for reasons other than expiration.
408REQUEST_TIMEOUTThe request timed out.
500INTERNAL_ERRORSomething went wrong. Please send a note to your Nova Credit Representative with additional details so we can investigate.

Changelog

We're always working to improve the Nova Credit platform! Here's a snapshot of API features we're shipping and bugs we're squashing.

Changelog History

August 2025

  • Added reportType to webhooks
  • Added explicit "current" callout to payroll pay_period_start and pay_period_end fields
  • Added USA_ARGYLE sandbox testing documentation with 9 test user profiles for employment verification testing

July 2025

  • Updated income.financial_accounts[]:
    • Added primary_account_detected and job_irregularity_risk fields and descriptions
  • Created job_irregularity_risk table
  • Updated Visit substatuses:
    • Added separate descriptions for ACCOUNT_TOO_NEW, NO_RECENT_USABLE_INFORMATION and NO_USABLE_INCOME_INFORMATION substatuses based on different income model suite versions.
  • Added /connect/income-navigator/v2/files endpoint
  • Updated Sandbox Environment section to make test inputs more clear.
  • Added MX as a bank connection partner and USA_MX as a valid source_id
  • Added revised_report_values to income
  • Added example reports with revised_report_values to Report Examples
  • Added income.financial_accounts[].inflows
  • Added income.financial_accounts[].matched_income_sources

June 2025

  • Fixed bug where /connect/income-navigator/v2/files/<filepath> was returning a 400 instead of 404 when a file was not found
  • Fixed bug where some endpoints, when returning a non-200 status code, were returning a terminated field as a string instead of a boolean

May 2025

  • Updated Visit statuses:
    • Updated documentation to include INVITED
    • Added new Visit status INITIALIZED for when /connect/initialized is called
    • Updated the logic for when a Visit status is set to EXPIRED: in addition to being set 72 hours after the widget is initially opened, if the widget is never opened it will expire 72 hours after the invite was sent or the initialization endpoint was called

April 2025

March 2025

  • Added nova_report_revision to the meta node
  • Added REGENERATED_VISIT webhook type for regenerated reports
  • Marked income.payroll[].statements[].net_total_earnings_amount_ytd as can be null
  • Fixed bug where income.summary fields were returning null values when they should be returning 0
  • Fixed bug where if identities[].full_name from a supplier is null, we were not returning a proper identities[].matching.full_name node for the CONSUMER_INPUT source. Going forward, if the full_name from the supplier is null, then it will be part of the unmatched_sources.
  • Fixed bug where multiple paystub objects were being returned in income.paystubs[], now returns the most recent paystub if there are multiple.

February 2025

  • Updates to employment[]:
    • Marked fields that can be null: source_record_id, employer_name, employer_address_line_1, employer_address_line_2, employer_city, employer_state, employment_type, employment_status, job_title
  • Updates to income.paystubs[]:
    • Marked fields that can be null: employee_name, employee_address_line_1, employee_address_line_2, employee_city, employee_state, employee_zip, pay_period_start, pay_period_end, pay_date, pay_frequency, paystub_provider, hire_date, net_total_earnings_amount_current, net_total_earnings_amount_ytd, gross_total_earnings_amount_current, gross_total_earnings_amount_ytd, regular_pay_earnings_amount_current, regular_pay_earnings_amount_ytd, bonus_earnings_amount_current, bonus_earnings_amount_ytd, overtime_earnings_amount_current, overtime_earnings_amount_ytd, commission_earnings_amount_current, commission_earnings_amount_ytd, paid_time_off_earnings_amount_current, paid_time_off_earnings_amount_ytd, vacation_earnings_amount_current, vacation_earnings_amount_ytd, paid_time_off_deductions_amount_current, paid_time_off_deductions_amount_ytd, vacation_deductions_amount_current, vacation_deductions_amount_ytd, medicare_tax_deductions_amount_current, medicare_tax_deductions_amount_ytd, social_security_deductions_amount_current, social_security_deductions_amount_ytd, fica_tax_deductions_amount_current, fica_tax_deductions_amount_ytd
    • Marked insights fields that can be null: annual_gross_income, annual_net_income
    • Marked irregularity_detection fields that can be null: file_type, genuine_pdf
  • Updates to income.payroll[]:
    • Marked fields that can be null: annual_salary_rate, pay_period_start, pay_period_end
    • Marked statements fields that can be null: gross_total_earnings_amount_current, gross_total_earnings_amount_ytd, net_total_earnings_amount_current
  • Updates to income.financial_accounts[].matched_income: Marked all fields can be null
  • Fixed bug where identities[].matching.full_name source for an OCROLUS source was missing the source_record_id
  • Fixed bug with identities[].full_name: If source has first_name and last_name but no full_name, we will now populate full_name with a concatenated first_name last_name

January 2025

  • Added docs for source_id type
  • Fixed doc for source_type, replaced CONSUMER_INPUT with MANUAL
  • Updates to account_details[]:
    • Added source_id
    • Removed addresses[].neighborhood and addresses[].district
    • Updated account_type type: removed CHECKING, SAVINGS, MONEY_MARKET, added INSTALLMENT and MORTGAGE
    • Marked fields that can be null: owner_full_name, institution_name, account_type, date_opened, truncated_account_number, responsibility, current_balance
      • Marked addresses[] fields that can be null: street, city, zipcode, state
  • Updates to identities[]:
    • Removed middle_name
    • Marked fields that can be null: source_record_id, first_name, last_name, full_name

December 2024

  • Added Nova Product Configuration via API
  • Updated irregularity_detection to match the updated (v3) fraud schema
  • Updated sample reports to have correct matching fields
  • Removed income.payroll[].annual_income
  • Removed income.payroll[].statements[].source_id
  • Updated irregularity_detection to match the updated (v3) fraud schema
  • Added source_record_id field to employment and identities node

November 2024

  • Added external_id to report meta

October 2024

  • Documentation created

Changes from v1 to v2

These are the changes from the Cash Atlas V1 Docs.

Additions/Modifications

  • Created an account_details node which includes data from the old bank_transactions[].account_details node
    • Does not include oldest_transaction_date, routing_number, full_account_number, addresses[].neighborhood, and addresses[].district
  • Added income.summary node
  • Numeric income.paystub[] data type changed from "String" to "Float".
  • Added ERROR + INVALID_PREFILL_* substatuses
  • Updated name matching logic in identities node - matching will only be included on identities that have a source_id of CONSUMER_INPUT

Removals

  • Removed identities[].middle_name
  • Removed identities[].other_names
  • Removed identities[].telephones
  • Removed bank_transactions[] node
  • Removed expenses[] node
  • Removed income.financial_accounts[].confidence_score_recent
  • Removed income.financial_accounts[].confidence_score_annual
  • Removed income.financial_accounts[].matched_income.confidence_score
  • Removed income.financial_accounts[].history[].confidence_score
  • Removed income.payroll[].annual_income
  • Removed income.payroll[].statements[].source_id
  • Removed income.paystubs[].regular_hours_earnings_current
  • Removed income.paystubs[].regular_rate_earnings_current
  • Removed income.paystubs[].commission_hours_earnings_current
  • Removed income.paystubs[].commission_rate_earnings_current
  • Removed income.paystubs[].overtime_hours_earnings_current
  • Removed income.paystubs[].overtime_rate_earnings_current
  • Removed income.paystubs[].bonus_hours_earnings_current
  • Removed income.paystubs[].bonus_rate_earnings_current
  • Removed income.paystubs[].paid_time_off_hours_earnings_current
  • Removed income.paystubs[].paid_time_off_rate_earnings_current
  • Removed income.paystubs[].vacation_hours_earnings_current
  • Removed income.paystubs[].vacation_rate_earnings_current
  • Removed income.paystubs[].annual_salary_rate
  • Removed income.paystubs[].insights.insights_type
  • Removed income.paystubs[].insights.insights_version
  • Removed income.paystubs[].insights.annual_earnings_insight
  • Removed metrics[] node
  • Removed attributes[] node
  • Removed adverse_action_codes[] node