Link External Accounts with Finicity
Overview
Account holders can connect external bank accounts to a Highnote financial account to move funds in and out via different payment rails. Highnote supports two connection types: verified and non-verified.
Highnote has partnered with Finicity to verify and connect external bank accounts securely and with NACHA compliance.
External account types
You can transfer funds into or out of Highnote from an external bank account.
- Fund-in transfers: A funds transfer from an external account to a Highnote financial account. Fund-in transfers require external account verification.
- Fund-out transfers: A funds transfer from a Highnote financial account to an external account. Fund-out transfers do not require verification of the external account and can only be initiated on card products with a cash deposit (ex: debit and secured debit cards).
There are two types of Highnote external financial accounts:
| Account Type | Verified | Transfer Method |
|---|---|---|
ExternalFinancialBankAccount | Yes | Fund-in or Fund-out |
NonVerifiedExternalUSFinancialBankAccount | No | Fund-out on debit cards |
Set up your Finicity account
Before integrating with Finicity, you must sign up for an account and create an access token:
- Sign up for Finicity API keys.
- Create a Finicity access token to onboard your account holders.
- Share the access token with Highnote. Highnote uses it to securely retrieve account and routing numbers from Finicity.
Testing your Finicity connections
Highnote's Finicity partner ID is 2445583993914. When testing, input this value as the thirdPartyPartnerId.
You can test Finicity API keys in a live environment using preset test profiles for all scenarios. Finicity provides mock FinBanks to simulate testing against live financial institutions.
To begin testing, set up your Finicity test environment and then follow these steps:
- Generate a Finicity-App-Token.
- Create a test customer in Finicity.
- Generate a Connect URL and simulate customer linking bank accounts to Finicity.
- Refresh customer accounts.
- Generate a 3rd party API access token to send to Highnote. Use the following POST request to
https://api.finicity.com/aggregation/v1/partners/accessKey:
Headers
Accept: application/json,
Content-Type: application/json,
Finicity-App-Token: <app-token-from-step-1>,
Finicity-App-Key: <app-key-from-developer-portal>
Body (raw, JSON)
{
"customerId": "<customer-id-from-step-2>",
"partnerId": "<subscriber-partner-id-from-developer-portal>",
"thirdPartyPartnerId": "2445583993914",
"products": [
{
"product": "moneyTransferDetails",
"payorId": "<subscriber-partner-id-from-developer-portal>",
"maxCalls": 1000,
"accountId": "<account-id-from-step-3>",
"accessPeriod": {
"type": "timeframe",
"startTime": "2022-03-10T06:06:20Z",
"endTime": "2023-03-10T06:06:20Z"
}
},
{
"product": "availableBalanceLive",
"payorId": "<subscriber-partner-id-from-developer-portal>",
"maxCalls": 1000,
"accountId": "<account-id-from-step-3>",
"accessPeriod": {
"type": "timeframe",
"startTime": "2022-03-10T06:06:20Z",
"endTime": "2023-03-10T06:06:20Z"
}
},
{
"product": "accountOwner",
"payorId": "<subscriber-partner-id-from-developer-portal>",
"maxCalls": 1000,
"accountId": "<account-id-from-step-3>",
"accessPeriod": {
"type": "timeframe",
"startTime": "2022-03-10T06:06:20Z",
"endTime": "2023-03-10T06:06:20Z"
}
}
]
}
Sample response
{
"data": [
{
"receipt": {
"profile": 3,
"version": "1",
"receiptId": "cr_vYdb1DGoLpI9opOqwkkfBy464SmIDd",
"receiptVersion": "1",
"customerId": "5543088633794259024",
"partnerId": 2445583993914,
"products": [
{
"product": "moneyTransferDetails",
"accountId": "8977412844634022494",
"accessPeriod": {
"type": "timeframe",
"startTime": "2022-03-10T06:06:20Z",
"endTime": "2023-03-10T06:06:20Z"
}
},
{
"product": "availableBalanceLive",
"accountId": "1045023535892401594",
"accessPeriod": {
"type": "timeframe",
"startTime": "2022-03-10T06:06:20Z",
"endTime": "2023-03-10T06:06:20Z"
}
},
{
"product": "accountOwner",
"accountId": "5200183909259568542",
"accessPeriod": {
"type": "timeframe",
"startTime": "2022-03-10T06:06:20Z",
"endTime": "2023-03-10T06:06:20Z"
}
}
]
}
}
]
}
Connect a verified account
With a Finicity access token, call the Highnote API to link an external bank account. The following table maps Finicity products to Highnote access token types:
| Finicity Product | Highnote Access Token Type |
|---|---|
moneyTransferDetails | ACH_DETAILS |
availableBalanceLive | CURRENT_BALANCE |
accountOwner | ACH_OWNER_DETAILS |
Use the following mutation to add an external bank account with Finicity:
AddExternalBankAccountVerifiedThroughFinicity
Query
mutation AddExternalBankAccountVerifiedThroughFinicity(
$input: AddExternalBankAccountVerifiedThroughFinicityInput!
) {
addExternalBankAccountVerifiedThroughFinicity(input: $input) {
__typename
... on ExternalFinancialBankAccount {
id
name
provider
createdAt
updatedAt
owner {
__typename
}
externalBankAccountDetails {
id
createdAt
updatedAt
last4
type
routingNumber
}
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{ "input": { "accountHolderId": "ACCOUNT_HOLDER_ID", "name": "Finicity Checking", "bankAccountType": "CHECKING", "externalToken": { "receiptId": "processor-token-success", "customerId": "5543088633794259024", "products": [ { "productType": "ACH_DETAILS", "accountId": "ACCOUNT_ID", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } }, { "productType": "CURRENT_BALANCE", "accountId": "ACCOUNT_ID", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } }, { "productType": "ACH_OWNER_DETAILS", "accountId": "ACCOUNT_ID", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } } ] } } }
Result
{
"data": {
"addExternalBankAccountVerifiedThroughFinicity": {
"__typename": "ExternalFinancialBankAccount",
"id": "FINANCIAL_ACCOUNT_ID",
"name": "Finicity Checking",
"provider": "SIMULATED",
"createdAt": "2022-08-26T20:24:22.557Z",
"updatedAt": "2022-08-26T20:24:22.734Z",
"owner": {
"__typename": "USPersonAccountHolder"
},
"externalBankAccountDetails": {
"id": "EXTERNAL_BANK_ACCOUNT_ID",
"createdAt": "2022-08-26T20:24:22.557Z",
"updatedAt": "2022-08-26T20:24:22.730Z",
"last4": "9606",
"type": "CHECKING",
"routingNumber": "011401533"
}
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
Connect a non-verified account
Non-verified external bank accounts can only be used to receive funds from a Highnote financial account. They can never be used to move funds into Highnote.
Non-verified accounts are those that have not been verified by a third party like Finicity. The most common use case for a non-verified external bank account is to return funds to an account holder in the event of account closure. You cannot move funds into Highnote with a non-verified account.
When connecting an external bank account, your account holder must provide the following external account information:
- Routing number
- Account number
- Account type: Checking or savings
Use the following mutation to add a non-verified external bank account. Optionally, a nickname can be assigned to the non-verified account for reference.
AddNonVerifiedExternalUSFinancialBankAccount
Query
mutation addNonVerifiedExternalUSFinancialBankAccount(
$input: AddNonVerifiedExternalUSFinancialBankAccountInput!
) {
addNonVerifiedExternalUSFinancialBankAccount(input: $input) {
__typename
... on NonVerifiedExternalUSFinancialBankAccount {
id
name
createdAt
updatedAt
externalBankAccountDetails {
id
last4
type
routingNumber
createdAt
updatedAt
}
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{ "input": { "routingNumber": "111000025", "accountNumber": "12345678910", "name": "My Checking Account", "accountHolderId": "ACCOUNT_HOLDER_ID", "bankAccountType": "CHECKING" } }
Result
{
"data": {
"addNonVerifiedExternalUSFinancialBankAccount": {
"__typename": "NonVerifiedExternalUSFinancialBankAccount",
"id": "EXTERNAL_FINANCIAL_ACCOUNT_ID",
"name": "My Checking Account",
"createdAt": "2022-02-09T17:10:56.662Z",
"updatedAt": "2022-02-09T17:10:56.662Z",
"externalBankAccountDetails": {
"id": "EXTERNAL_BANK_ACCOUNT_ID",
"last4": "8910",
"type": "CHECKING",
"routingNumber": "111000025",
"createdAt": "2022-02-09T17:10:56.662Z",
"updatedAt": "2022-02-09T17:10:56.662Z"
}
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
List external accounts
Use the following query to view and present a list of an account holder's external bank accounts:
ListAccountHolders
Query
query ListAccountHolders($first: Int) {
businessAccountHolders(first: $first) {
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
edges {
cursor
node {
...accountHolder
}
}
}
}
fragment accountHolder on USBusinessAccountHolder {
id
externalFinancialAccounts {
edges {
node {
... on ExternalFinancialAccount {
__typename
... on ExternalFinancialBankAccount {
id
name
ledgers {
name
}
externalBankAccountDetails {
id
last4
type
routingNumber
createdAt
updatedAt
}
}
}
}
}
}
}
Variables
{
"first": 20
}
Result
{
"data": {
"businessAccountHolders": {
"pageInfo": {
"startCursor": "start-cursor",
"endCursor": "end-cursor",
"hasNextPage": true,
"hasPreviousPage": false
},
"edges": [
{
"cursor": "some-cursor",
"node": {
"id": "BUSINESS_ACCOUNT_HOLDER_ID",
"externalFinancialAccounts": {
"pageInfo": {
"startCursor": "start-cursor",
"endCursor": "end-cursor",
"hasNextPage": true,
"hasPreviousPage": false
},
"edges": [
{
"cursor": "some-cursor",
"node": {
"__typename": "ExternalFinancialBankAccount",
"id": "EXTERNAL_ACCOUNT_ID",
"name": "Plaid Checking",
"last4": "2730",
"type": "CHECKING",
"routingNumber": "011401533",
"createdAt": "2022-02-25T17:01:12.322Z",
"updatedAt": "2022-02-25T17:01:12.523Z",
"ledgers": [
{
"name": "AVAILABLE_CASH"
}
]
}
}
]
}
}
}
]
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
Disconnect external account
Use the following mutation to disconnect a verified or non-verified external bank account:
CloseExternalFinancialBankAccount
Query
mutation CloseExternalFinancialBankAccount(
$input: CloseExternalFinancialBankAccountInput!
) {
closeExternalFinancialBankAccount(input: $input) {
__typename
... on ExternalFinancialBankAccount {
id
name
accountStatus
createdAt
updatedAt
owner {
__typename
... on USBusinessAccountHolder {
primaryAuthorizedPerson {
id
}
businessProfile {
id
}
}
}
ledgers {
id
name
}
features {
__typename
enabled
}
externalBankAccountDetails {
id
createdAt
updatedAt
last4
type
routingNumber
}
}
... on UserError {
errors {
errorPath
code
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{ "input": { "externalFinancialBankAccountId": "EXTERNAL_BANK_ACCOUNT_ID" } }
Result
{
"data": {
"closeExternalBankAccount": {
"__typename": "ExternalFinancialBankAccount",
"id": "EXTERNAL_BANK_ACCOUNT_ID",
"name": "Plaid Checking",
"accountStatus": "CLOSED",
"createdAt": "2022-02-23T14:25:17.334Z",
"updatedAt": "2022-02-23T14:25:18.006Z",
"owner": {
"__typename": "USBusinessAccountHolder",
"primaryAuthorizedPerson": {
"id": "PRIMARY_AUTHORIZED_PERSON_ID"
},
"businessProfile": {
"id": "BUSINESS_PROFILE_ID"
}
},
"ledgers": [
{
"id": "FINANCIAL_ACCOUNT_ID",
"name": "AVAILABLE_CASH"
},
{
"id": "FINANCIAL_ACCOUNT_ID",
"name": "CASH"
}
],
"features": [
{
"__typename": "AchCapableFinancialAccountFeature",
"enabled": true
},
{
"__typename": "VendorProvidedBankFinancialAccountFeature",
"enabled": true
}
],
"externalBankAccountDetails": {
"id": "EXTERNAL_BANK_ACCOUNT_ID",
"createdAt": "2022-02-23T14:25:17.336Z",
"updatedAt": "2022-02-23T14:25:17.995Z",
"last4": "8546",
"type": "CHECKING",
"routingNumber": "011401533"
}
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}