Consumer Prepaid Template
Overview
Consumer prepaid card products allow consumers to manage personal expenses, shop both in-store and online, and withdraw cash from ATMs. Consumer prepaid card products have the following features:
- Debit card capabilities
- A predefined amount of funds
- Funded from a designated bank account
Prepaid cards require funding through a bank account. When the account holder needs to increase the balance in their financial account, a transfer is initiated from an external bank account.
The following graphic shows how a consumer prepaid card is created and funded:

This guide provides an overview of creating and setting up a consumer prepaid card product in the Test environment.
Create a card product
Use the following mutation to create a consumer prepaid card product. Use CONSUMER_PREPAID as the vertical input variable:
CreateCardProduct
Query
mutation CreateCardProduct($input: CreateCardProductInput!) {
createCardProduct(input: $input) {
__typename
... on CardProduct {
id
name
usage
}
... on UserError {
errors {
errorPath
code
description
}
}
}
}
Variables
{ "input": { "cardProduct": { "name": "Consumer Prepaid", "usage": "MULTI_USE", "vertical": "CONSUMER_PREPAID" } } }
Result
{
"data": {
"createCardProduct": {
"__typename": "CardProduct",
"id": "G8FyZHByb2R1Y3RfcGRfNjI3YjEzYjAyMDI5NDJlN9FkOTBjZGJjNmQzYmY0TYU=",
"name": "Consumer Prepaid",
"usage": "MULTI_USE"
}
},
"extensions": {
"requestId": "b85fc1ec-e770-9d06-922f-16b7486a677i"
}
}
Fund your card program
Some card products use a product funding account to transfer funds to financial accounts. In the Test environment, you can simulate depositing funds into your product funding account. Simulating deposits doesn't require connecting a verified external bank account.
Funding your product funding account requires the following steps:
- Retrieve the product funding account ID.
- Initiate a wire transfer to the product funding account.
Find product funding account ID
Use the following query to find your product funding account ID:
GetCardProductwithAccounts
Query
query GetCardProductwithAccounts($id: ID!) {
node(id: $id) {
... on CardProduct {
__typename
id
name
usage
accounts {
edges {
node {
id
name
features {
__typename
enabled
}
accountStatus
owner {
__typename
}
}
}
}
}
}
}
Variables
{
"id": "'CARD_PRODUCT_ID"
}
Result
{
"data": {
"node": {
"id": "CARD_PRODUCT_ID",
"accounts": {
"edges": [
{
"node": {
"id": "FINANCIAL_ACCOUNT_ID",
"features": [
{
"enabled": true,
"__typename": "ProductFundingFinancialAccountFeature"
}
]
}
}
]
}
}
},
"extensions": {
"requestId": "REQUEST_ID",
"rateLimit": {
"cost": 13,
"limit": 60060,
"remaining": 60041
}
}
}
Initiate a wire transfer
Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the toFinancialAccountId input variable:
SimulateDeposit
Query
mutation SimulateDeposit($input: SimulateDepositInput!) {
simulateDeposit(input: $input) {
__typename
... on Transfer {
id
status
statusReason
amount {
value
currencyCode
}
createdAt
updatedAt
ledgers {
name
}
}
... on UserError {
errors {
code
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{ "input": { "amount": { "value": 10000000, "currencyCode": "USD" }, "source": "WIRE", "toFinancialAccountId": "PRODUCT_FUNDING_ACCOUNT_ID", "memo": "Consumer Credit product funding wire deposit" } }
Result
{
"data": {
"simulateDeposit": {
"__typename": "Transfer",
"id": "WIRE_TRANSFER_ID",
"status": "PENDING",
"statusReason": null,
"amount": {
"value": 10000000,
"currencyCode": "USD"
},
"createdAt": "2023-09-01T22:26:43.629Z",
"updatedAt": "2023-09-01T22:26:43.629Z",
"ledgers": null
}
},
"extensions": {
"requestId": "REQUEST_ID",
"rateLimit": {
"cost": 12,
"limit": 60060,
"remaining": 60040
}
}
}
Create an account holder
Consumer cards are used by US person account holders. Use the following mutation to create a US person account holder:
createUSPersonAccountHolder
Query
mutation createUSPersonAccountHolder(
$input: CreateUSPersonAccountHolderInput!
) {
createUSPersonAccountHolder(input: $input) {
__typename
... on UserError {
errors {
errorPath
code
description
}
}
... on USPersonAccountHolder {
id
email
dateOfBirth
externalId
updatedAt
createdAt
name {
givenName
familyName
title
suffix
middleName
}
billingAddress {
streetAddress
extendedAddress
postalCode
region
locality
countryCodeAlpha3
}
phoneNumbers {
countryCode
number
label
}
identificationDocument {
socialSecurityNumber {
numberHash
countryCodeAlpha3
}
}
personCreditRiskAttributes {
totalAnnualIncome {
value
currencyCode
}
currentDebtObligations {
value
currencyCode
}
employmentStatus
}
}
}
}
Variables
{ "input": { "personAccountHolder": { "email": "gerrytest1@abc.com", "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "billingAddress": { "streetAddress": "123 Main Street", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-11-1111", "countryCodeAlpha3": "USA" } }, "personCreditRiskAttributes": { "totalAnnualIncome": { "value": "1000", "currencyCode": "USD" }, "currentDebtObligations": { "value": "1000", "currencyCode": "USD" }, "employmentStatus": "EMPLOYED" }, "dateOfBirth": "1980-09-01", "externalId": "EXTERNAL_ID" } } }
Result
{
"data": {
"createUSPersonAccountHolder": {
"__typename": "USPersonAccountHolder",
"id": "ACCOUNT_HOLDER_ID",
"email": "gerrytest1@abc.com",
"dateOfBirth": "1980-09-01",
"externalId": "EXTERNAL_ID",
"updatedAt": "2023-05-03T05:12:01.703Z",
"createdAt": "2023-05-03T05:12:01.703Z",
"name": {
"givenName": "Gerry",
"familyName": "Wolfe",
"title": "",
"suffix": "",
"middleName": ""
},
"billingAddress": {
"streetAddress": "123 Main Street",
"extendedAddress": "",
"postalCode": "60654",
"region": "IL",
"locality": "Chicago",
"countryCodeAlpha3": "USA"
},
"phoneNumbers": [
{
"countryCode": "1",
"number": "5555555555",
"label": "MOBILE"
}
],
"identificationDocument": {
"socialSecurityNumber": {
"numberHash": "AQAAAAOsQ644SC1GNYnzkU0evWaL290gayp0lfmx-sEyxxdQnA",
"countryCodeAlpha3": "USA"
}
},
"personCreditRiskAttributes": {
"totalAnnualIncome": [
{
"value": 1000,
"currencyCode": "USD"
}
],
"currentDebtObligations": [
{
"value": 1000,
"currencyCode": "USD"
}
],
"employmentStatus": "EMPLOYED"
}
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
Open an application
After creating an account holder, you can open an application to onboard them to your card product. Opening an application triggers identity verification processes. You can participate in the application decisioning process using Collaborative Application Decisioning.
In some cases, additional documents may be required to approve an application. For more information on collecting additional documents, see Request Documents for Application Review.
Use the following mutation to open an application for an account holder:
createAccountHolderCardProductApplication
Query
mutation createAccountHolderCardProductApplication(
$input: CreateAccountHolderCardProductApplicationInput!
) {
createAccountHolderCardProductApplication(input: $input) {
__typename
... on AccountHolderCardProductApplication {
id
applicationState {
status
}
updatedAt
createdAt
}
... on UserError {
errors {
errorPath
code
description
}
}
}
}
Variables
{ "input": { "accountHolderId": "ACCOUNT_HOLDER_ID", "cardProductId": "CARD_PRODUCT_ID", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "PRIMARY_AUTHORIZED_PERSON_ID", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } }
Result
{
"data": {
"createAccountHolderCardProductApplication": {
"__typename": "AccountHolderCardProductApplication",
"id": "APPLICATION_ID",
"applicationState": {
"status": "PENDING"
},
"createdAt": "2021-07-07T23:22:30.475Z",
"updatedAt": "2021-07-07T23:22:30.475Z"
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
Issue a financial account
Financial accounts hold the balance for payment cards. To create a financial account, pass the id of the account holder's approved application.
Financial accounts have an externalId variable field that allows you to tie the account to an entity in your system. If you do not pass in an externalId, Highnote will generate one.
Use the following mutation to issue a financial account for an application:
IssueFinancialAccountForApplication
Query
mutation IssueFinancialAccountForApplication(
$input: IssueFinancialAccountForApplicationInput!
) {
issueFinancialAccountForApplication(input: $input) {
... on FinancialAccount {
id
externalId
name
createdAt
updatedAt
application {
id
createdAt
}
cardProduct {
id
vertical
}
features {
__typename
enabled
createdAt
updatedAt
}
directDepositDetails {
id
restrictedDetails {
__typename
... on DirectDepositDetailRestrictedDetails {
number
routingNumber
bank {
name
}
}
}
}
owner {
__typename
... on USPersonAccountHolder {
id
}
}
}
}
}
Variables
{ "input": { "applicationId": "APPLICATION_ID", "name": "Financial Account", "externalId": "YOUR_EXTERNAL_ID" } }
Result
{
"data": {
"issueFinancialAccountForApplication": {
"id": "FINANCIAL_ACCOUNT_ID",
"externalId": "ABC123456",
"name": "John Doe - Account",
"createdAt": "2021-12-28T18:20:49.932Z",
"updatedAt": "2021-12-28T18:20:49.960Z",
"application": {
"id": "APPLICATION_ID",
"createdAt": "2021-12-20T17:59:33.570Z"
},
"cardProduct": {
"id": "CARD_PRODUCT_ID",
"vertical": "GENERAL_PURPOSE_RELOADABLE"
},
"features": [
{
"__typename": "DirectDepositFinancialAccountFeature",
"enabled": true,
"createdAt": "2021-12-28T18:20:49.933Z",
"updatedAt": "2021-12-28T18:20:49.933Z"
},
{
"__typename": "DebitPaymentCardFinancialAccountFeature",
"enabled": true,
"createdAt": "2021-12-28T18:20:49.933Z",
"updatedAt": "2021-12-28T18:20:49.933Z"
}
],
"directDepositDetails": {
"id": "FINANCIAL_ACCOUNT_ID",
"restrictedDetails": {
"__typename": "AccessDeniedError"
}
},
"owner": {
"__typename": "USPersonAccountHolder",
"id": "ACCOUNT_HOLDER_ID"
}
}
}
}
Issue a payment card
Once you have created a financial account, you can issue a payment card. By default, all payment cards start as virtual cards. After you issue a virtual card, you can create a physical card order if needed.
Use the following mutation to issue a virtual card:
IssuePaymentCardForFinancialAccount
Query
mutation IssuePaymentCardForFinancialAccount(
$input: IssuePaymentCardForFinancialAccountInput!
) {
issuePaymentCardForFinancialAccount(input: $input) {
... on PaymentCard {
id
bin
last4
expirationDate
network
status
financialAccounts {
id
name
}
restrictedDetails {
... on PaymentCardRestrictedDetails {
cvv
number
}
... on AccessDeniedError {
message
}
}
}
... on UserError {
errors {
errorPath
code
description
}
}
}
}
Variables
{ "input": { "financialAccountId": "FINANCIAL_ACCOUNT_ID", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } }
Result
{
"data": {
"issuePaymentCardForFinancialAccount": {
"id": "PAYMENT_CARD_ID",
"bin": "489661",
"last4": "9602",
"expirationDate": "2025-01-01T23:59:59Z",
"network": "MASTERCARD",
"status": "ACTIVE",
"financialAccounts": [
{
"id": "FINANCIAL_ACCOUNT_ID",
"name": "Test Consumer Credit Account"
}
],
"restrictedDetails": {
"message": "Access is denied"
}
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
Physical cards
By default, all payment cards start as virtual cards. Highnote also supports issuing personalized payment cards to account holders. For more information on issuing physical cards, see Print Physical Cards.
Digital wallets
Highnote supports issuing tokenized cards. Account holders can add tokenized cards to digital wallets like Apple and Google Pay. For more information, see Add Cards to Digital Wallets.
Non-originated ACH
Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data.
In the Live environment, non-originated ACH transfers are initiated by account holders. In the Test environment, you can simulate a non-originated ACH transfer to fund a financial account using the following mutation:
simulateNonOriginatedAchTransfer
Query
mutation simulateNonOriginatedAchTransfer(
$input: SimulateNonOriginatedAchTransferInput!
) {
simulateNonOriginatedAchTransfer(input: $input) {
__typename
... on NonOriginatedAchTransfer {
id
amount {
currencyCode
value
}
createdAt
updatedAt
ledgers {
id
name
normalBalance
asOf
debitBalance {
value
currencyCode
}
creditBalance {
value
currencyCode
}
}
type
purpose
sign
traceNumber
status
statusFailureReason
settlementDate
processedAt
failedAt
returnSentToBankAt
}
}
}
Variables
{ "input": { "idempotencyKey": "12345", "financialAccountId": "id", "amount": { "currencyCode": "USD", "value": "200.00" }, "purpose": "DEPOSIT", "settlementDate": "2024-12-23", "companyIdentifier": "123", "companyName": "My Company", "companyDiscretionaryData": "data", "companyEntryDescription": "description", "individualIdentificationNumber": "123", "individualName": "Joe", "paymentRelatedInformation": "RMR*IV*0123456789**999.99" } }
Result
{
"data": {
"simulateNonOriginatedAchTransfer": {
"__typename": "NonOriginatedAchTransfer",
"id": "TRANSFER_ID",
"amount": {
"currencyCode": "USD",
"value": "200.00"
},
"createdAt": "2024-09-13T10:15:30Z",
"updatedAt": "2024-09-13T10:15:30Z",
"ledgers": [
{
"id": "ledger_001",
"name": "Primary Ledger",
"normalBalance": "DEBIT",
"asOf": "2024-09-13T10:15:30Z",
"debitBalance": {
"value": "200.00",
"currencyCode": "USD"
},
"creditBalance": {
"value": "0.00",
"currencyCode": "USD"
}
}
],
"type": "DEPOSIT",
"purpose": "DEPOSIT",
"sign": "+",
"traceNumber": "123456789",
"status": "PROCESSED",
"statusFailureReason": null,
"settlementDate": "2024-12-23",
"processedAt": "2024-09-13T10:16:30Z",
"failedAt": null,
"returnSentToBankAt": null
}
}
}
Transfer from product funding account
Some prepaid card products may require using your product funding account to fund an account holder's financial account. Use the following input variables to ensure money is moving in the correct direction:
toFinancialAccountId: Account holder's financial account IDfromFinancialAccountId: Product funding account ID
Use the following mutation to initiate a transfer from your product funding account:
initiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccount
Query
mutation initiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccount(
$input: InitiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccountInput!
) {
initiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccount(
input: $input
) {
__typename
... on InterFinancialAccountTransfer {
id
status
statusReason
createdAt
updatedAt
memo
amount {
value
currencyCode
}
}
... on UserError {
errors {
code
errorPath
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{ "input": { "toFinancialAccountId": "ACCOUNT_HOLDER_FINANCIAL_ACCOUNT_ID", "fromFinancialAccountId": "PRODUCT_FUNDING_ACCOUNT_ID", "memo": "Fund Financial Account #1", "amount": { "value": 10000, "currencyCode": "USD" } } }
Result
{
"data": {
"initiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccount": {
"__typename": "InterFinancialAccountTransfer",
"id": "TRANSFER_ID",
"status": "PENDING",
"memo": "Fund Financial Account #1",
"statusReason": null,
"createdAt": "2021-12-27T22:26:55.102Z",
"updatedAt": "2021-12-27T22:26:55.127Z",
"amount": {
"value": 10000,
"currencyCode": "USD"
}
}
}
}
Transfer funds from a financial account
Use the following mutation to transfer funds from a Highnote financial account to your product funding account. For input variables, use the following IDs:
toFinancialAccountId: Product funding account IDfromFinancialAccountId: Account holder's payment card financial account ID
initiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccount
Query
mutation initiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccount(
$input: InitiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccountInput!
) {
initiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccount(
input: $input
) {
__typename
... on InterFinancialAccountTransfer {
id
status
statusReason
createdAt
updatedAt
memo
amount {
value
currencyCode
}
}
... on UserError {
errors {
code
errorPath
description
}
}
... on AccessDeniedError {
message
}
}
}
Variables
{ "input": { "toFinancialAccountId": "PRODUCT_FUNDING_ACCOUNT_ID", "fromFinancialAccountId": "FINANCIAL_ACCOUNT_ID", "memo": "unload card", "amount": { "value": 5000, "currencyCode": "USD" } } }
Result
{
"data": {
"initiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccount": {
"__typename": "InterFinancialAccountTransfer",
"id": "TRANSFER_ID",
"status": "COMPLETED",
"memo": "unload card",
"statusReason": null,
"createdAt": "2022-2-27T22:26:55.102Z",
"updatedAt": "2022-2-27T22:26:55.127Z",
"amount": {
"value": 5000,
"currencyCode": "USD"
}
}
}
}
Display account and routing number
Prepaid cards have the DIRECT_DEPOSIT feature enabled by default. Financial accounts with the DIRECT_DEPOSIT feature have an associated account and routing number that can be used to transfer funds into the account from outside Highnote.
To display the account and routing number in your website or application, you can fetch them from the API by generating a Client Token and using that token to view the restricted details.
The following graphic shows an example of what fetching an account and routing number looks like:

Use the following query to view direct deposit information:
ViewDirectDepositDetails
Query
query ViewDirectDepositDetails($id: ID!) {
node(id: $id) {
... on FinancialAccount {
directDepositDetails {
id
restrictedDetails {
__typename
... on DirectDepositDetailRestrictedDetails {
number
routingNumber
}
}
}
}
}
}
Variables
{
"id": "FINANCIAL_ACCOUNT_ID"
}
Result
{
"data": {
"node": {
"__typename": "ExternalBankAccountDetail",
"id": "FINANCIAL_ACCOUNT_ID",
"last4": "2730",
"type": "CHECKING",
"restrictedDetails": {
"number": "0493712730",
"routingNumber": "89703965"
}
}
},
"extensions": {
"requestId": "REQUEST_ID"
}
}
Display payment card data
Highnote recommends using the Card Viewer SDK to securely display payment card data and and reduce PCI non-compliance.
There are two methods for displaying payment card data on your website or application:
- Fetching the data from the Highnote API
- Use the Card Viewer SDK to ensure PCI compliance
To fetch payment card data from the API, use the following query:
FindPaymentCard
Query
query FindPaymentCard($id: ID!) {
node(id: $id) {
... on PaymentCard {
bin
last4
expirationDate
restrictedDetails {
... on PaymentCardRestrictedDetails {
cvv
number
}
}
}
}
}
Variables
{
"id": "PAYMENT_CARD_ID"
}
Result
{
"data": {
"node": {
"bin": "BIN",
"last4": "LAST_4",
"expirationDate": "EXPIRATION_DATE",
"restrictedDetails": {
"cvv": "CVV",
"number": "NUMBER"
}
}
}
}
Simulate transactions
After configuring your card product, we recommend simulating transactions. Simulating transactions is useful for testing your card program's configuration and settings.
For more information on simulating transactions, see Simulate Transactions.
Expand your integration
After configuring your card product and simulating transactions, you can use the following features to further expand your integration:
- Create authorization controls to manage spending.
- Create a rewards program for your card product.
- Set up notifications to automate your integration.