Cash Atlas V2 API Reference
API Overview
Introduction
This document provides information on how to interact with the Nova Credit API to obtain a Cash Atlas V2 report.
The best way to get the Cash Atlas 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:
Endpoint | Description |
---|---|
GET /connect/accesstoken | Retrieves an access token for an applicant's Cash Atlas report |
GET /connect/cash-atlas/v2/json | Retrieves an applicant's Cash Atlas report in JSON form |
GET /connect/status | Retrieves the status of an applicant's Cash Atlas report |
Visit our Quickstart guide to see details on how to call these endpoints with examples.
Data Types & Formats
Data Types
Type | Description |
---|---|
String | Extended character set, numbers and punctuation symbols. This includes non-ASCII language-specific characters such as ß, à, ç, é, and more (all encoded as utf8). |
Integer | A rounded numerical value. |
Float | A 64-bit floating decimal point format. |
Bool | A boolean-flag indicating true or false. |
Object | Nested JSON level with more field-values. |
Array | A value or type array contains a zero or positive amount of elements. The elements can be of any type. |
Data Formats
Format | Description |
---|---|
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 Cash Atlas report response structure is as follows:
meta
{object}product
{object}sources
{array}identities
{array}account_details
{array}attributes
{array}scores
{array}
Example of the JSON structure of the Cash Atlas report response:
{
"meta": {
...
},
"product": {
...
},
"sources": [
...
],
"identities": [
...
],
"account_details": [
...
],
"attributes": [
...
],
"scores": [
...
]
}
meta {}
Example snippet of meta in the report response:
{
"meta": {
"public_token": "ff0886a4-f3ff-11e6-bc64-92361f002671",
"user_args": "235234224",
"created_at": "2024-01-13T11:07:46.51Z",
"api_version": "2.0.0",
"nova_report_revision": "1",
"external_id": "d167c6bb-225c-461c-be63-f0bc3a1f62ea",
"status": "SUCCESS",
"substatus": "MISMATCHED_PII"
},
...
}
Information specific to the report that's been returned.
Field | Format | Notes |
---|---|---|
public_token | UUID | The unique identifier of this report |
user_args | String | The input of the userArgs function in NovaConnect. Can be null |
created_at | Timestamp | The date the credit report was retrieved |
api_version | Full version | The API version used to generate this report |
nova_report_revision | String | The revision name for this report. This field will be null if this report has never been revised. |
external_id | String | The unique applicant identifier of the report from your system. Can be null if it is not provided. |
status | String | The status for this report. If a report is available, the status will be SUCCESS |
substatus | String | The substatus for the report. See substatuses. Can be null |
product {}
Example snippet of product in the report response:
{
"product": {
"name": "Village Communities",
"product_id": "9cf178e0-760e-11e7-abf3-5da9d338ae4b",
"inquiry_type": "TENANT"
},
...
}
Details of the product
the applicant applied for. Please refer to the Client-Side Integration section in the Quickstart Guide.
Field | Format | Notes |
---|---|---|
name | String | Product name |
product_id | UUID | The unique identifier for the product |
inquiry_type | String | See product inquiry_type values |
sources []
Example snippet of sources in the report response:
{
"sources": [
{
"source_id": "USA_FIN",
"source_type": "BANK_TRANSACTION",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "MANUAL",
"status": "SUCCESS"
}
],
}
A list of data sources used to build the applicant's report.
Field | Format | Notes |
---|---|---|
source_id | String | A human-readable identifier for the source, unique within the context of the report |
source_type | String | See source_types |
status | String | The final status for the source. See status |
identities []
Example snippet of identities in the response:
{
"identities": [{
"source_id": "USA_FIN",
"first_name": "Raymond",
"last_name": "Marshal",
"full_name": "Raymond Marshal",
"emails": ["raymond@email.com"]
...
}],
...
}
The applicant's personal identity information reported from each data source.
Field | Format | Notes |
---|---|---|
source_id | String | The identifier for the source that reported the identity information. See sources |
first_name | String | The first name of the applicant |
last_name | String | The last name of the applicant |
full_name | String | The full name of the applicant |
emails | Array of String | A list of emails associated to the applicant |
matching | Object | See matching |
matching {}
Example identities matching field object for case where there is a full name match:
{
"matching": {
"full_name": {
"matched_sources": [
{
"source_id": "USA_FIN",
"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": "USA_FIN",
"source_record_id": "c31bf8c7-c25b-4d2c-a4bc-61f79fd46e65"
}
]
}
}
}
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.
Field | Format | Notes |
---|---|---|
full_name | Object | Matched and unmatched sources for the full name of the applicant |
MatchingField {}
Example matching field object for case where there is a field match:
{
"matched_sources": [
{
"source_id": "USA_FIN",
"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": "USA_FIN",
"source_record_id": "c31bf8c7-c25b-4d2c-a4bc-61f79fd46e65"
}
]
}
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.
Field | Format | Notes |
---|---|---|
matched_sources | Array | List of sources which have a value that matches this identity. See sources |
unmatched_sources | Array | A list of sources which have a value that conflicts with this identity. See sources |
account_details []
Example account detail field object:
{
"account_details": [{
"source_id": "USA_FIN",
"account_id": "36139831-0a91-4d1f-bc3e-edc908a978c6",
"months_available": 6,
"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",
"last_statement_end_date": "2015-05-30",
"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,
"ach_details": [{
"routing_number": "123445",
"full_account_number": "789682736",
}],
},
...
],
}
An array with each instance containing details about an account. The array can have zero objects, and there is no upper bound.
Field | Format | Notes |
---|---|---|
source_id | UUID | The identifier for the source that reported the account details. |
account_id | UUID | Unique identifier for the account |
months_available | Integer | Number of months of transaction data available on the report |
owner_full_name | String | Full name of the owner of the account |
institution_name | String | Name of institution such as Chase or Bank of America |
account_name | String | Name of the account within the bank |
account_type | String | Type of the account within the bank. See account types |
date_opened * | Full Date | Date the account was opened |
truncated_account_number | String | If available, the last four digits of the account number |
responsibility | String | See responsibility |
last_statement_end_date | Full Date | End date of the of the most recent statement |
addresses | Array | See addresses |
current_balance | Float | Current balance of the account |
ach_details | Array | See ACH details |
- Denotes that the field may not be returned in the JSON response in all cases.
addresses []
Example addresses field array:
{
"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"
}],
},
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.
Field | Format | Notes |
---|---|---|
address_id | UUID | Unique identifier for the address |
address | String | The full mailing address of the account owner |
street | String | The street address where the account owner is located |
neighborhood | String | The neighborhood where the account owner is located |
district | String | The district where the account owner is located |
city | String | The city where the account owner is located |
zipcode | String | The zip code where the account owner is located |
state | String | The state where the account owner is located |
ach_details []
Example ach_details field array:
{
"ach_details": [{
"routing_number": "123445",
"full_account_number": "789682736",
}],
},
ACH Details contains the ACH Details for this account. ACH Details are returned in an array, can have zero objects, and there is no upper bound.
Field | Format | Notes |
---|---|---|
routing_number | String | Routing number of financial institution for the account. Please contact your Nova Credit account representative to enable this field |
full_account_number | String | The full account number for initiating ACH transfers for this account. Please contact your Nova Credit account representative to enable this field |
attributes []
Example snippet of attributes in the report response:
{
"attributes": [
{
"name": "ASSETS_CASH_EQUIVALENT_BALANCE",
"description": "Current cash equivalent balance on assets",
"node": "ASSETS",
"source_ids": ["USA_FIN"],
"value": 3200,
"adverse_action_code": "21"
},
{
"name": "ASSETS_CURRENT_RATIO",
"description": "Current ratio on assets",
"node": "ASSETS",
"source_ids": ["USA_FIN"],
"value": 9999998,
"adverse_action_code": "25"
},
...
],
}
Attributes are analytical values derived from the underlying data in the report. attributes
are returned in an array; the array can have zero objects, and there is no upper bound. Please consider an approach that permits adding and removing attributes without incurring additional integration work. It is particularly important that you discuss the mechanics of your attributes integration if it relies on a fixed ordering or maximum number of attributes.
Field | Format | Notes |
---|---|---|
name | String | The name of the attribute |
description | String | Human readable description of the attribute |
node | String | See node_type |
source_ids | Array | A list of IDs of the sources utilized to generate this attribute. See sources |
value | Number | Value of the attribute. See value types |
adverse_action_code | String | See adverse_action_codes |
Calculations
This service retrieves up to two years of transaction history for the consumer’s provided accounts. This data is grouped based on the transaction posted date and used to generate attributes. This grouping is used to determine which data points will be used to calculate an attribute that is bound by a time frame. If an explicit time frame is given, then the data used to compute the attribute will only include data points for past complete months.
For example, an attribute that calculates the average number of expense transactions over a 12 month period when the consumer completed the application on February 17, 2022 will only include data points between January 1, 2021 to January 31, 2022 inclusive.
In the event an attribute calculation results in an infinite or undefined number, such as dividing by 0, a cap value will be returned.
Calculation | Format | Notes |
---|---|---|
Average | Integer | The average value over the specified duration |
Minimum | Integer | The minimum value over the node's history over the specified duration |
Maximum | Integer | The maximum value over the node's history over the specified duration |
Trend | Integer | Calculate the slope of the values over the specified duration |
Sum | Integer | The sum of all values over the specified duration |
Ratio | Float | The ratio between two different sets of data |
Count | Integer | The number of occurrences a qualification nis met over the specified duration |
Boolean | Boolean | True or false |
Recency | Integer | Counts the number of days that fit the given qualification over the specified duration |
Balance | Float | Calculate the dollar amount balance over the specified duration. Only two places after the decimal are returned |
Default Condition Values
In the case that an attribute could not be calculated, an integer value will be returned indicating one of three scenarios. See Value Types for a table on values based on type.
Condition | Description |
---|---|
No usable records | No relevant records were found for the given node type. This typically occurs in scenarios such as when the user did not connect any accounts or no transactions were found across all connected accounts |
No usable records in the category | Records exist for the node, but not for the attribute's sub category |
No usable values | Records exist for the node and category, but the records do not match a constraint such as time frame |
Value Types
Type | Minimum Value | Maximum Value | Cap Value | No Usable Records | No Usable records in the Category | No Usable Values |
---|---|---|---|---|---|---|
Boolean | 0 | 1 | 5 | 8 | 7 | 6 |
Dollar Amounts | -9,999,999.99 | 9,999,994.99 | 9,999,995 | 9,999,998 | 9,999,997 | 9,999,996 |
Float | -9,999,999.99999 | 9,999,994.99999 | 9,999,995 | 9,999,998 | 9,999,997 | 9,999,996 |
Short Integer | -9,999 | 9,9994 | 9,995 | 9,998 | 9,997 | 9,996 |
Long Integer | -9,999,999 | 9,999,994 | 9,999,995 | 9,999,998 | 9,999,997 | 9,999,996 |
scores []
Example snippet of scores in the Cash Atlas response:
{
"scores": [
{
"source_ids": ["USA_FIN"],
"score_type": "NOVA_SCORE_CASH_FLOW",
"score_version": "1.0.0",
"value": 850,
"adverse_action_codes": [{
"code": "35",
"description": "Insufficient information on or lack of accounts"
}]
},
]
}
Information specific to the applicant's Nova Score. scores
are returned in an array, and all elements follow the same structure.
Field | Format | Notes |
---|---|---|
source_ids | Array | A list of ids of the sources utilized to generate this score. |
score_type | String | See score_type |
score_version | Full version | |
value | Integer | Value of the score |
adverse_action_codes | Array | See adverse_action_codes |
Tables
adverse_action_codes
adverse_action_codes
give information about the key factors that affect the consumer’s score. The requirement for lenders to send adverse action notices is a part of the Fair Credit Reporting Act (FCRA), a federal law that promotes accuracy, fairness, and privacy of information.
adverse_action_codes
can be found in two places within the report:
Within the scores
node:
adverse_action_codes
are returned in an array of objects. Each attribute maps to one specific adverse action code, and the adverse_action_codes
array will only contain the codes that are associated with attributes found in the attributes node of the API response.
Within the attributes
node:
adverse_action_code
is a string code
as defined in the table below.
Field | Format | Notes |
---|---|---|
code | String | Numeric code between 00 and 100, exclusive. Reach out to your Nova representative to retrieve the values of each code. |
description | String | Human readable description |
account_type
Values of the account_type
field.
Value |
---|
CASH_EQUIVALENT |
CHECKING |
SAVINGS |
INVESTMENT |
MONEY_MARKET |
OTHER |
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 label | Value |
---|---|
Monitoring | MONITORING |
Credit Card | CREDIT_CARD |
Vehicle Auto | VEHICLE_AUTO |
Vehicle Other | VEHICLE_OTHER |
Mortgage | MORTGAGE |
Personal | PERSONAL |
Student | STUDENT |
Utility | UTILITY |
Commercial | COMMERCIAL |
Consumer | CONSUMER |
Tenant Screening | TENANT |
Other | OTHER |
node_type
Select top level nodes from the report body that are associated with an attribute. At this time, not all node types may be available at the top level of the report. Certain category of attributes will belong to one of the existing node types.
Value | Categories |
---|---|
ASSETS | Cash equivalent accounts, investment accounts |
EXPENSES | From cash equivalent accounts, a transaction with a negative amount. NSFs (Non-sufficient funds) are an example |
INCOME | Net income, cash flow |
source_type
Values of the source_type
field.
Value | Description |
---|---|
BANK_TRANSACTION | Data was sourced from a bank connection |
CONSUMER_INPUT | Data was manually entered by the applicant |
substatus
Additional insight on certain cases that occur when fetching or parsing a report.
These substatuses may accompany a report with a SUCCESS
status:
Value | Description |
---|---|
MISMATCHED_PII | There is a mismatch between the PII in the consumers input and the PII in the pulled supplier report |
These substatuses may accompany a webhook with an ERROR
status:
Value | Description |
---|---|
MFA_REQUIRED_ON_FETCH | The bank account the user tried to connect to requires multi-factor authentication and may depend on the user's browser security settings. |
INCOMPATIBLE_ACCOUNT_TYPES_SUBMITTED | The user only submitted debt accounts (e.g. credit card). |
INVALID_PREFILLS_PII_MISSING | Must provide firstName, lastName, email, and DOB or full address. |
INVALID_PREFILL_ADDRESS | The address sent via prefill must be a string with max length 100 and contain a valid street address. |
INVALID_PREFILL_CITY | The city sent via prefill must be a string with max length 100. |
INVALID_PREFILL_DOB | The birthday sent via prefill is missing or not in YYYY-MM-DD format. |
INVALID_PREFILL_EMAIL | The email sent via prefill must be a valid email with max length 100. |
INVALID_PREFILL_FIRST_NAME | The 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_NAME | The last name sent via prefill must be a string less than 255 characters and contain only alphabetical, unicode, dots, apostraphes and dashes. |
INVALID_PREFILL_INCOME | The stated annual income sent via prefill must be an integer between 0 and 2147483647. |
INVALID_PREFILL_PHONE | The phone number sent via prefill must be a string with max length 255. |
INVALID_PREFILL_STATE | The state sent via prefill is missing or not in a valid two letter US state or territory code. |
INVALID_PREFILL_ZIP | The zip code sent via prefill must a string with a valid USA zip code. |
responsibility
Values of the responsibility
field.
Value | Description |
---|---|
INDIVIDUAL | The individual is solely responsible for the account |
JOINT | The individual is jointly responsible for the account |
score_type
Values of the score_type
field.
Value | Description |
---|---|
NOVA_SCORE_CASH_FLOW | The Nova Score |
Cash Atlas Report Example
This is a sample response of the Cash Atlas report. Not all possible data values are present.
{
"meta": {
"user_args": "22bbd586-12b9-4876-8ec0-d210d081f4a1|email@test.com",
"created_at": "2020-04-07T00:53:43.829Z",
"api_version": "2.0.0",
"public_token": "e3f60d3a-8a22-4940-9d1e-50f4f9878503"
},
"product": {
"product_id": "c3a37c41-7c62-11e7-8141-19157d9a48c7",
"name": "Pascoe Gardens Sandbox",
"inquiry_type": "TENANT"
},
"sources": [
{
"source_id": "USA_FIN",
"source_type": "BANK_TRANSACTION",
"status": "SUCCESS"
},
{
"source_id": "CONSUMER_INPUT",
"source_type": "CONSUMER_INPUT",
"status": "SUCCESS"
}
],
"identities": [{
"source_id": "CONSUMER_INPUT",
"first_name": "Raymond",
"last_name": "Marshal",
"full_name": "Raymond Marshal",
"emails": ["raymond@email.com"]
}],
"account_details": [{
"source_id": "USA_FIN",
"months_available": 6,
"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",
"last_statement_end_date": "2015-05-30",
"addresses": [
{
"address_id": "80421b7e-7918-4963-b5fb-85055c2994b7",
"address": "225 Valencia St.",
"street": "Valencia St.",
"city": "San Francisco",
"zipcode": "94103",
"state": "CA"
}
],
"current_balance": 45971,
"ach_details": [{
"routing_number": "98164521",
"full_account_number": "01885674"
}]
}],
"attributes": [
{
"name": "EXPENSES_COUNT_3_MONTH_AVG",
"description": "Average count of expenses over the last 3 months",
"node": "EXPENSES",
"source_ids": ["USA_FIN"],
"adverse_action_code": "66",
"value": 10
},
{
"name": "EXPENSES_COUNT_0_50_3_MONTH_AVG",
"description": "Average count of expenses between $0 and $50 over the last 3 months",
"node": "EXPENSES",
"source_ids": ["USA_FIN"],
"adverse_action_code": "67",
"value": 9996
},
...
],
"scores": [{
"source_ids": ["USA_FIN"],
"score_type": "NOVA_SCORE_CASH_FLOW",
"score_version": "1.0.0",
"value": 850,
"adverse_action_codes": [{
"code": "35",
"description": "Current cash equivalent balance to short term balance ratio of assets"
}]
}],
}
Sandbox Environment
Refer back to the Quickstart Guide for more information about Sandbox vs. Production.
To access a Cash Atlas sandbox report, you must pass certain identifying consumer information into the NovaConnect widget. This information may be passed in directly via prefill keys. Please refer to the Quickstart Guide to learn more about prefill keys.
Bank Accounts
The following Nova Credit test user reports have been created and can be accessed by inputting the following information:
Inputs | Default User | Single Primary Account User | Multi-Account User | Joint Account User | Debt Account Linked User | No Income User |
---|---|---|---|---|---|---|
First name | Raymond | Sarah | Mike | Jason | Derek | Nolan |
Last name | Marshal | Single | Many | Joint | Debt | NoTransactions |
Date of birth | 1995-10-01 | 1986-10-12 | 1992-05-08 | 1976-03-09 | 1984-04-12 | 1992-03-07 |
Email address | raymond@email.com | sarah@email.com | mike@email.com | jason@email.com | derek@email.com | nolan@email.com |
Phone | 310-555-6789 | 415-231-5348 | 917-340-3249 | 208-351-0093 | 512-213-3322 | 217-277-6633 |
Address | 456 7th Street | 6100 Evergreen Way | 915 Snover Street | 2213 W Montrose Avenue | 1105 Bowie Rd | 6300 N Illinois St |
City | Modesto | Everett | Houston | Chicago | Austin | Fairview Heights |
State | CA | WA | TX | IL | TX | IL |
Zip | 95313 | 98203 | 77007 | 60618 | 78773 | 62208 |
Stated employer | Raymond's Designs | Boeing | Target | Microsoft | Charles Schwab | Optional |
Stated annual income | 12000 | 120000 | 73000 | 110000 | 135000 | Optional |
Along with the identifying consumer information that is collected, the user will need to connect their bank account through one of our partners, Finicity, Inc or Akoya.
Finicity
Finicity provides a set of usernames and password combinations for testing purposes that can be found in the Finicity documentation. For example, selecting FinBank and using a username/password of demo/go will allow you to connect test accounts.
These users will return a SUCCESS
status in the webhook.
Refer to the Finicity documentation to view alternative user ID and password combinations to trigger different Finicity states.
If testing multiple aggregators in sandbox mode, you will need to select a bank first. Please select FinBank
to connect with Finicity.
Akoya
Users may also connect their bank accounts through our partner Akoya to access a Cash Atlas sandbox report. Upon loading the widget, select the test user displayed, and the appropriate report will be fetched. The test users mirror those above for Finicity.
If testing multiple aggregators in sandbox mode, you will need to select a bank first. Please select Mikomo
to connect with Akoya.
Simulating Different Cases in Sandbox
Enter the following inputs as the "Last Name" of the applicant in prefills to simulate a different case.
Inputs | Description |
---|---|
expiresoon | Simulates the EXPIRED status, immediatey instead of waiting 72 hours |
supplierdown | Simulates the SUPPLIER_UNRESPONSIVE status |
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 Type | Description | |
---|---|---|
VISIT | A 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_VISIT | Only occurs for reports that have been regenerated. This event type also includes a novaReportRevision in the webhook body. |
Webhook Status Codes
Each Webhook API call will contain one of the status codes listed below:
Status | Description | Terminal Status? | Report Available? |
---|---|---|---|
PENDING | A visit has been initialized upon opening the NovaConnect widget | ✗ | ✗ |
SUCCESS | The data source has successfully provided information on the applicant | ✓ | ✓ |
EXPIRED | The 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 | ✓ | ✗ |
ERROR | An error occurred and the Cash Atlas Report could not be compiled. If there isn't a detailed substatus, send a message to your Nova Credit Representative with the publicToken | ✓ | ✗ |
SUPPLIER_UNRESPONSIVE | The applicant has encountered a data supplier outage while going through the widget. They may need to go through NovaConnect again at a later time | ✓ | ✗ |
Webhook Body
Webhook Body Key | Description |
---|---|
eventType | Event Type (see event type table above) corresponding to this webhook |
status | Status (see status code table above) corresponding to this webhook |
substatus | A more detailed status. See substatus types |
publicToken | Unique UUID associated with this status, which can be used to retrieve the Nova Credit report |
externalId | Optional unique identifier passed in by the Nova Credit customer (you) with this application. This key will only be present if externalId was passed in |
userArgs | Optional string passed in by the Nova Credit customer (you) with this application. This key will only be present if userArgs was passed in |
eventId | Unique ID for the webhook |
eventCreatedTime | Webhook event timestamp |
novaReportRevision | Only included for webhooks with the REGENERATED_VISIT eventType . Refers to the revision number of the report |
history | An array containing 1 or more objects, containing data on all of the statuses an applicant has reached within one Cash Atlas widget instance, sorted by most recent to least recent |
history.eventType | Each history object will have a SUPPLIER event type |
history.companyCode | Data supplier for this history object |
history.dateAttempted | Timestamp marking when this corresponding history object was begun |
history.status | Status (see status code table above) corresponding to this history object |
history.substatus | A 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 Attempts | Time Until Retry if Unsuccessful |
---|---|
1 | 1 second |
2 | 2 seconds |
3 | 4 seconds |
4 | 8 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:
Header | Value |
---|---|
X-Timestamp | timestamp of request generation |
X-Nova-Signature | SHA256 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:
- Delivered by Nova Credit to the webhook
- 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:
Code | Text | Description |
---|---|---|
200 | - | Everything went well and the requested resource is either in the body or in the generic text field depending on the content-type |
400 | MALFORMED_HEADERS | The request headers are incorrectly formatted |
400 | MISSING_INPUT | An input is missing that the endpoint expected |
408 | REQUEST_TIMEOUT | The request timed out |
403 | UNKNOWN_CUSTOMER | The public_id or client_id Nova Credit received in the request from is not recognized |
403 | UNAUTHORIZED | The client_id and secret_key combination is not recognized. Please email support via support@novacredit.com |
403 | ORIGIN_UNAUTHORIZED | The origin of the request is not whitelisted on the Nova Credit servers for CORS |
401 | EXPIRED_TOKEN | The access_token you're sending in the request headers has expired. Please request a new one |
404 | INVALID_EXTERNAL_ID | The external ID is not valid |
400 | INVALID_PUBLIC_ID | The public ID is not valid |
404 | INVALID_TOKEN | The public_token or access_token is not valid for reasons other than expiration |
500 | INTERNAL_ERROR | Something went wrong. Please send a note to support@novacredit.com with additional details so we can investigate |
Bank Statements Beta
Bank statements for Cash Atlas is a new feature that is currently in beta, allowing your applicants to submit transaction data using their 4 most recent statements. If you are interested in trying it out, please reach out to your Nova Credit representative for more details.
Report Body
When bank statements are submitted, Cash Atlas reports include the standard nodes as described above plus an additional top-level array:
document_uploads
{array}
document_uploads []
The document_uploads
array contains information about each bank statement file uploaded by the applicant and used as a source for the Cash Atlas transaction analysis.
{
"document_uploads": [
{
"document_upload_id": "0236cf90-04df-11f0-88c8-813899895a3e",
"source_filepath": "d63ddc84-a078-4aad-bc7d-a3ec84b60b94/62f6cc64-91cf-4f5a-9116-67c47d79ceaf.pdf",
"irregularity_detection": {
"status": "NOT_DETECTED",
"reasons": [],
"version": "3.1",
"genuine_pdf": true
}
},
{
"document_upload_id": "023f8220-04df-11f0-88c8-813899895a3e",
"source_filepath": "d63ddc84-a078-4aad-bc7d-a3ec84b60b94/3a02a218-d5a9-4ac8-b633-6fa4a5042459.pdf",
"irregularity_detection": {
"status": "NOT_DETECTED",
"reasons": [],
"version": "3.1",
"genuine_pdf": true
}
},
{
"document_upload_id": "024a9350-04df-11f0-88c8-813899895a3e",
"source_filepath": "d63ddc84-a078-4aad-bc7d-a3ec84b60b94/7b91cc32-e4f8-4d2b-9c45-8d3579a61c23.pdf",
"irregularity_detection": {
"status": "NOT_DETECTED",
"reasons": [],
"version": "3.1",
"genuine_pdf": true
}
},
{
"document_upload_id": "0255b480-04df-11f0-88c8-813899895a3e",
"source_filepath": "d63ddc84-a078-4aad-bc7d-a3ec84b60b94/9f4e2d15-b367-4c91-a8d2-ef298c4a9b76.pdf",
"irregularity_detection": {
"status": "DETECTED",
"reasons": [
{
"reason": "No Transaction Presented",
"severity": "High Risk"
},
{
"reason": "Unusual Document Source Detected",
"severity": "High Risk"
}
],
"version": "3.1"
}
}
]
}
Field | Format | Notes |
---|---|---|
document_upload_id | String | A unique identifier for the uploaded document |
source_filepath | String | The filepath to access the uploaded document |
irregularity_detection | Object | See irregularity detection below |
irregularity_detection {}
If Irregularity Detection is enabled, this node will contain details about any irregularities detected.
Field | Format | Notes |
---|---|---|
status | String | See irregularity detection status values |
reasons | Array | See irregularity detection reasons below |
genuine_pdf | Boolean or null | True only if document is exceptionally genuine, not provided otherwise |
version | String | The version of the fraud algorithm used to generate the results |
irregularity detection reasons []
Specific reasons supporting the provided irregularity_detection
status.
Field | Format | Notes |
---|---|---|
reason | String | See irregularity detection reason values |
severity | String | See irregularity detection severity values |
Sources
Bank statement reports introduce a new source ID:
Value | Description |
---|---|
OCROLUS | Data was sourced from uploaded bank statements processed by Ocrolus |
Example source in the report response:
{
"sources": [
{
"source_id": "OCROLUS",
"source_type": "BANK_TRANSACTION",
"status": "SUCCESS"
}
]
}
Account Details
For bank statements, the account_details
node includes an additional field:
Field | Format | Notes |
---|---|---|
last_statement_end_date | Full Date | The end date of the most recent statement provided by the applicant |
Example account details with statement date:
{
"account_details": [
{
"source_id": "OCROLUS",
"account_id": "21490d35-dddb-4ff1-adf8-4b98328bde64",
"owner_full_name": "JILL S COFFEE",
"institution_name": "CHASE",
"account_name": "488083738759 CHASE CHECKING",
"account_type": "CASH_EQUIVALENT",
"responsibility": "INDIVIDUAL",
"last_statement_end_date": "2025-03-15",
"addresses": [
{
"address_id": "7d07905b-429d-4d85-9f9b-a1be0a617961",
"address": "74 Prospect Park West Park Slope, New York, NY, 11215, US",
"street": "74 Prospect Park West Park Slope",
"city": "New York",
"zipcode": "11215",
"state": "NY"
}
],
"ach_details": []
}
]
}
Tables
irregularity_detection_status
Values of the status
field in the irregularity_detection
node.
Value | Description |
---|---|
NOT_DETECTED | No irregularities were detected on the file |
DETECTED | Irregularities were detected on the file |
REVIEW | Minor fraud indications detected, manual review recommended |
irregularity_detection_reason
Values of the reason
field in the v3 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 v3 irregularity_detection
reasons
node.
Value |
---|
High Risk |
Medium Risk |
Low Risk |
Accessing Uploaded Statement Files
Document uploads in a report include a source_filepath
that can be used to retrieve the original bank statement file. These files can be downloaded by making a GET request to the Cash Atlas file endpoint using the same accessToken
used to get the report and the publicToken provided by the webhook. Make sure to encode the accessToken
using base 64.
GET https://api.novacredit.com/connect/cash-atlas/v2/files/<filepath>
Required headers
X-PUBLIC-TOKEN
The unique identifier of the report you are retrieving, provided to you via webhook.Authorization
Bearer Auth, containing thestrict base-64
encoded string of the validaccessToken
you previously retrieved.
Possible responses
200 (OK)
Bank statement file is found and returned.403 (Forbidden)
Unauthorized request.400 (Bad Request)
Malformed request, headers or missing required parameters.404 (Not Found)
File was not found. This could be because theX-PUBLIC-TOKEN
was not correct, or because thefilepath
is incorrect.
Example request
require('request').request(
{
url: 'https://api.novacredit.com/connect/cash-atlas/v2/files/d63ddc84-a078-4aad-bc7d-a3ec84b60b94/62f6cc64-91cf-4f5a-9116-67c47d79ceaf.pdf',
method: 'GET',
encoding: null,
headers: {
Authorization: `Bearer ${new Buffer('<valid access token>').toString('base64')}`,
'X-PUBLIC-TOKEN': '8ac61af8-65ae-4d78-8e02-9f10cbc0adf0',
},
},
function (err, res, body) {
fs.writeFile('bank_statement.pdf', body, function (err) {
if (err) {
throw err;
}
console.log('DONE');
});
},
);
Sandbox Testing
To test the Bank Statements feature in sandbox mode, you can supply at least one bank statement with a filename that matches against a known test user:
Filename | Outcome |
---|---|
jill.pdf | Valid statement with normal transaction history |
jill_detected.pdf | Statement with irregularities detected |
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
March 2025
- Added Bank Statements (Beta) feature details
February 2025
- Fixed bug with
identities[].full_name
: If source hasfirst_name
andlast_name
but nofull_name
, we will now populatefull_name
with a concatenatedfirst_name last_name
November 2024
- Added error substatuses for prefills
- Added
external_id
to report meta
October 2024
- Added
status
andsubstatus
to themeta
object in the JSON response
September 2024
- Added the error substatus
INVALID_PREFILL_DOB
- Added
EXPIRED
status for Webhooks and way to simulate in sandbox
July 2024
- Added instructions on testing the
SUPPLIER_UNRESPONSIVE
status - Added
REGENERATED_VISIT
to webhookeventType
- Added Webhook Signature section
- Denoted that
date_opened
may not always be present in the JSON response
June 2024
- Added
Changes from Cash Atlas v1 to Cash Atlas v2
section in Changelog
Changes from v1
to v2
View V1 Docs.
Additions/Modifications:
- Created an
account_details
node which includes data from the oldbank_transactions[].account_details
andbank_transactions[].summary
nodes - Moved
account_details.routing_number
andaccount_details.full_account_number
into a new node namedaccount_details.ach_details
- Created
scores
node that will hold ourNova Score Cash Flow
. - ENUM modifications:
- Renamed the
BUREAU_UNRESPONSIVE
status toSUPPLIER_UNRESPONSIVE
- Created a new
MISMATCHED_PII
substatus that can accompany someSUCCESS
visits where the consumer input differs from the received account_details
- Renamed the
- Added
source_id
to account_details node
- Created an
Removals:
- Removed
/connect/cash-atlas/<version>/files/<filepath>
endpoint - Removed Supplier Webhooks
- Removed references to
Paystub Verification
andUSA_ATOMIC
- Removed
middle_name
,other_names
andtelephones
fromidentities
node - Removed
oldest_transaction_date
fromaccount_details
node - Removed
employments
node - Removed
bank_transactions
node including all subnodes except foraccount_details
andsummary
which were moved into the newaccount_details
node at the top-level of the JSON (see Additions above) - Removed
expenses
node - Removed
income
node including all subnodes - Removed
metrics
node - Removed
adverse_action_codes
node - Removed account-level attributes which used to exist in
bank_transactions[].account_details[].attributes
- Removed info text around attributes being available for select customers only. All Cash Atlas V2 customers will receive an attributes node.
- Removed
DEBT
from thenode_type
table - ENUM removals:
- Removed
STATUSES
SKIPPED
NOT_AUTHENTICATED
NON_CONTRIBUTING_APPLICANT
- Removed a few
SUBSTATUSES
that usually accompanySUCCESS
visitsACCOUNT_TOO_NEW
NO_RECENT_USABLE_INFORMATION
NO_USABLE_INCOME_INFORMATION
- Removed a couple
SUBSTATUSES
that usually accompanyERROR
visitsINVALID_DATE_FORMAT_SUBMITTED
INCOMPLETE_INFORMATION
- Removed a
SUBSTATUSES
that usually accompanyNON_CONTRIBUTING_APPLICANT
visitsCOAPPLICANT_GUARANTOR_PROVIDING
- Removed
EMPLOYMENT
andPAYROLL
fromsource_type
enum
- Removed
- Reworked the
Sandbox Mode
section
- Removed