# Highnote Documentation - Full Content > Complete plaintext content of all Highnote documentation pages. Highnote is a card issuance, payment processing, and money movement platform-as-a-service. > For a lightweight index, see /llms.txt --- URL: https://docs.highnote.com/docs/get-started/about-highnote Title: About Highnote Section: Get Started Description: Get started with the Highnote platform for card issuance, payment acquiring, credit, and real-time money movement. ## What is Highnote? Highnote is a unified platform for embedded finance and was intentinally built for both card issuance and acquiring, including credit and real-time money movement. Core features include a real-time programmable ledger, integrated payments, and complete program management. - **Issuing Cards**: Launch and manage modern card programs, including debit, credit, prepaid, fleet, and virtual, with full control over design, spend rules, and user experience. - **Acquiring Payments**: Accept payments and reconcile funds with unified merchant acquiring capabilities that work seamlessly with your issuing and ledger systems. - **Managing Credit**: Offer branded or embedded credit products, including charge cards, credit lines, and revolving programs, tailored to your business model and customer needs. - **Moving Money**: Move money in real-time with direct access to push-to-card, RTP, ACH, and other domestic and cross-border rails. ## Highnote API and Dashboard Highnote uses a GraphQL API to provide a flexible, modern, and secure integration experience. The Highnote Dashboard is a no-code user interface built on top of the Highnote API. Whichever framework you prefer, start by creating an API key in the "Developers" section of the Dashboard on the API Keys tab. With your API key ready to go, you can call the API and see your results in the Dashboard, or you can create and configure Highnote products in the Dashboard directly. ## Test and Live environments Do not enter production data in the Test environment. The Highnote Test environment is for exploring features and training. Use only dummy or test data. Hignote environments contain your card products and let you build your integration and test the API. You have access to two environments on the Highnote platform, Test and Live. - **Test environment:** Build your integration with the Highnote API, simulate capabilities and transactions, and train your team on using Highnote. - **Live environment:** Actively issue payment cards and run transactions with your launched card product. The Live environment provides an easy-to-use interface to support your live card products. You can interact with both environments using the Highnote API or Dashboard. The Highnote API Guides (here in this documentation set) explain how to use the API to interact with both environments. The Highnote Support Guides explain how to use the Dashboard. ## Next steps Use the following steps to create an account and review Highnote’s getting started content: 1. Create a Highnote account. 1. Create API keys in the Dashboard on the **Developers > API Keys** page. 1. Read about the Highnote API and Dashboard. 1. Test the API in the API Explorer. --- URL: https://docs.highnote.com/docs/get-started/dashboard/organizations/manage-developers Title: Manage Developers Section: Get Started Description: Add developers to your organization and manage access to API keys, notifications, and events in the Dashboard. You can add developers to your organization so they can access the developer resources in the Highnote Dashboard. This guide provides an overview of adding developers to your organization and the available developer resources. ## Add a developer Developers need Admin permissions for the Highnote Dashboard to access Highnote’s developer tools. To add a developer to your organization, see Manage Organization and ensure you grant them **Admin** permissions. For more information on Dashboard permissions, see Dashboard roles and permissions. ## Developer tools Highnote’s Dashboard has several developer tools. Refer to the following list of developer tools for an overview of each: - **API keys:** Create and manage API keys. - **Notifications:** Add and manage notification targets. For more information, see Notifications in these API guides, or Manage notifications in the Dashboard support docs. - **Events:** Monitor and replay events across your card program. For more information, Adding a webhook in these API guides, or Monitor events in the Dashboard support docs. - **Collaborative authorization:** Add and manage collaborative authorization endpoints. For more information, see Collaborative authorization. ## Developer documentation Highnote has extensive developer documentation to assist you with integrating, designing, and optimizing your card program. For more information, see Highnote documentation. --- URL: https://docs.highnote.com/docs/get-started/dashboard/organizations/manage-notifications Title: Manage Notifications Section: Get Started Description: Create and manage webhook notification targets, configure event subscriptions, and monitor delivery attempts in the Dashboard. ## Overview This guide provides an overview of notifications and steps for adding and managing notification targets using the Highnote Dashboard. **Note:** Using Highnote notifications requires the assistance of a developer. Notifications work by using webhooks for events that occur within your Highnote implementation. Notifications allow you to monitor card program activity. The following use cases represent some common ways notifications are used: - Complete asynchronous onboarding flows - Monitor for changes or alerts - Transfer data from Highnote into third-party systems such as a CRM or analytics solution For more information on using notifications, see the Notifications developer guide. ## Add notification target Notifications targets use configurable events that send a notification to your webhooks. See the Notifications developer guide for information on setting up webhooks. Once your webhooks are configured, you can add notification targets using the Highnote Dashboard. Refer to the following steps to add notification targets: 1. From the Highnote Dashboard, click **Developers** and select the **Notifications** tab. 2. Click **Add Notification Target**. 3. Provide a **Notification Name** and **Target URL**. The target URL is your webhook's address. 4. In the notification events section, use the **toggles** to select **events** to deliver to your notification target. For an overview of events, see the Events Reference developer guide. 5. _Optional_ \- Add **Email**. This field is only available in the Live environment and is used by Highnote to send you notifications about deactivated webhooks. 6. Click **Add Webhook Notification Target**. 7. Copy your **notification target key** and store it in a safe location. 8. Click **I've copied my key**. Notification targets are not active upon creation. To activate a notification target, see Activate notification target. ## Manage notification target You can also manage notification targets from the Highnote Dashboard to monitor details, delivery attempts, and event history. Use the following steps to view the details of a notification target: 1. From the Highnote Dashboard, click **Developers** and select the **Notifications** tab. 2. Hover over your **notification target** and click **View Details**. On the notification target details page, you can view the following information: - **Status:** The status of a notification target. For a full list of statuses, see the Events Reference developer guide - **Details:** Details including the created and updated dates, type, subscriptions (events), and endpoint URL - **Delivery attempts:** A log of delivery attempts to your endpoint URL and the corresponding status - **History:** History of notification target statuses You can also execute the following actions on the notification target details page: - To change notification events for your target, click **Add/Remove Subscriptions**. - To rename your notification target, click **More** and select **Rename Target**. - To change your email, click **More** and select **Add/Update Email** or **Remove Email**. ## Activate notification target By default, notification targets are not active at creation. Use the following steps to activate a notification target using the Highnote Dashboard: 1. From the Highnote Dashboard, click **Developers** and select the **Notifications** tab. 2. Hover over your **notification target** and click **View Details**. 3. Click **Activate Target**. ## Delete notification target Use the following steps to delete a notification target using the Highnote Dashboard: 1. From the Highnote Dashboard, click **Developers** and select the **Notifications** tab. 2. Hover over your **notification target** and click **View Details**. 3. Click **Delete Target**. --- URL: https://docs.highnote.com/docs/get-started/dashboard/organizations/manage-organization Title: Manage Organization Section: Get Started Description: Invite and remove team members, assign roles, and manage organization settings in the Dashboard. You can use the Highnote Dashboard to invite team members, manage your organization, or leave an organization. This guide provides an overview of organization settings and Dashboard roles and permissions. ## Invite team members **Note:** You must invite team members to Test and Live environments separately because permissions are set at the organization level. Admin users can invite team members to their Highnote organization using the Dashboard. Use the following steps to invite team members to your organization: 1. From the Highnote Dashboard, select **Organization** from the left-hand navigation. 2. Click the **Team** tab and select **Invite Team Member**. 3. Provide the team member's **Email** and select a **Role**. For an overview of roles and their corresponding permissions, see Roles and permissions. ## Remove team members Admin users can remove team members from their Highnote organization using the Dashboard using the following steps: 1. From the Highnote Dashboard, select **Organization** from the left-hand navigation. 2. Click the **Team** tab and hover over the **Team Member name**. 3. Click the **three-dots icon** and select **Remove**. 4. In the pop-up window, click **Remove** to verify you want to remove the user. ## Leave an organization **Note:** You can’t leave an organization as the only Admin user. You must add another Admin user before leaving. Highnote team members can work across multiple organizations in Test and Live Environments. You can leave any organization from your Dashboard profile: 1. Click the **Organization** drop-down in the Dashboard. 2. Select **Profile**. 3. In the Organizations section, click the **three-dots icon** and select **Leave Organization**. --- URL: https://docs.highnote.com/docs/get-started/dashboard/organizations/monitor-events Title: Monitor Events Section: Get Started Description: View event logs, check delivery status, and replay failed notification events in the Dashboard. The events page of the Highnote Dashboard provides a view of all events across your organization. This includes events that are not related to your notification targets. You can use this log to monitor events, view event details, and replay events. This guide provides steps for viewing event details and replaying events from the Highnote Dashboard. ## View event details Use the following steps to view event details: 1. From the Highnote Dashboard, click **Developers** and select the **Events** tab. 2. Hover over an event and click **View Event Details**. The event details page shows the following details: - "Created at" date and time - Event name - Delivery attempts - Notification targets ## Replay event Events can fail for various reasons. Failed events can result in failed notifications to customers. Refer to the following steps to replay an event from the Highnote Dashboard: 1. From the Highnote Dashboard, click **Developers** and select the **Events** tab. 2. Hover over an event and click **View Event Details**. 3. Click **Replay Event**. 4. Click **Refresh** in the delivery attempts section to verify the event was replayed. --- URL: https://docs.highnote.com/docs/get-started/dashboard/organizations/roles-and-permissions Title: Roles and Permissions Section: Get Started Description: Review the permissions matrix for Admin and Support Dashboard roles, including access to account holders, cards, financial accounts, transfers, and reports. The Highnote Dashboard provides an easy-to-use interface for managing your card program. Highnote offers different user and permission levels for Dashboard users. This ensures compliance and privacy. This guide provides an overview of team member roles and permissions. ## Team member roles When an Admin user invites a team member through the Dashboard, they must assign the team member one of two roles: - Admin - Support ## Permissions Permissions are set at the organization level. You must invite team members and set permissions for Test and Live environments separately. Team member roles have different levels of permissions and capabilities in the Dashboard. The following table provides an overview of team member role permissions: | **Permission** | **Admin** | **Support** | | ---------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | | Manage organization settings | !approved | !denied | | Invite team | !approved | !denied | | Manage developer settings | !approved | !denied | | View account holders | !approved | !approved | | Manage account holders | !approved | !approved | | Monitor transactions | !approved | !approved | | Monitor payment cards | !approved | !approved | | Manage payment cards | !approved | !approved | | View spend controls | !approved | !approved | | Manage spend controls | !approved | !denied | | View applications | !approved | !approved | | Manage applications | !approved | !approved | | View financial accounts | !approved | !approved | | Issue financial accounts | !approved | !approved | | Monitor ledgers | !approved | !approved | | View internal transfers | !approved | !approved | | Manage internal transfers | !approved | !denied | | View card product balance | !approved | !approved | | Manage card product balance | !approved | !denied | | View product settings | !approved | !denied | | Manage product settings | !approved | !denied | | View reports | !approved | !approved | | Create reports | !approved | !approved | This table describes what each role can do in the Dashboard. It is not a security boundary. Permissions are enforced by the API against the role's credential, so a role may be able to perform an action programmatically that the Dashboard does not surface. --- URL: https://docs.highnote.com/docs/get-started/dashboard/using-the-dashboard Title: Using the Highnote Dashboard Section: Get Started Description: Navigate the Highnote Dashboard to create API keys, switch between Test and Live environments, and access developer tools. ## Overview The Highnote Dashboard is a no-code user interface built on top of the Highnote API. The "Developers" section of the Dashboard contains several developer-related controls. This guide is for developers. Non-technical users should refer to Using the Dashboard in the support guide. To access the Dashboard, sign up for a new account or log in. ## Test and Live environments The Highnote Dashboard lets you switch between Test and Live environments using the **environment drop-down**. For a general overview of the Test and Live environments, see the Using the Highnote Dashboard support guide. ## API keys You can create and manage API keys from the Highnote Dashboard. You must have a valid API key to interact with the Highnote API. We recommend rotating API keys to mitigate risk and misuse of sensitive data. For more information, see Rotating API Keys. ## Create API key Use the following steps to create an API key: 1. From the Highnote Dashboard, click **Developers**. 2. On the API Keys tab, click **Create API Key**. 3. Provide an **API Key Name** and click **Create API Key**. 4. Copy your API key and store it in a safe location. For security reasons, we can’t display the API key again. 5. Once you’ve copied and stored your API key, click **I’ve copied my key**. ## Revoke API key Use the following steps to revoke an API key: 1. From the Highnote Dashboard, click **Developers**. 2. On the API Keys tab, locate the API key you want to delete. 3. Click **Revoke API Key**. ## Notifications and events The Highnote Dashboard allows you to manage notifications, targets, and events. For more information on using the Dashboard to manage notifications, see the following support guides: - Manage notifications: Add, manage, activate, and delete notification targets - Monitor events: View event details and replay events ## Collaborative authorization Using the Highnote Dashboard, you can add collaborative authorization endpoints, which allow you to receive collaborative authorization requests. For more information on using the Dashboard to manage collaborative authorization endpoints, see the following support guide: Collaborative authorization. ## Dashboard roles and permissions The Highnote Dashboard offers different user and permission levels: - Admin - Support For an overview of Dashboard roles and permissions, see Dashboard roles and permissions. --- URL: https://docs.highnote.com/docs/get-started/introduction/glossary Title: Glossary Section: Get Started Description: Look up definitions for card issuance, payment acquiring, compliance, and money movement terms used across Highnote documentation. This glossary defines terms used throughout Highnote documentation, including industry-standard and Highnote-specific concepts. ## A ### Account holder A person or business issued a payment card or financial account. Highnote supports two types: _business account holders_ and _person account holders_. ### Account holder application The form account holders use to apply for a financial account. ### ACH (Automated Clearing House) The U.S. network for electronic funds transfers. Highnote supports two ACH transfer types: - **Originated ACH** — Initiated within Highnote by an account holder or card program. - _Push (Credit):_ Sends funds from a Highnote financial account to an external bank. - _Pull (Debit):_ Pulls funds from an external bank into a Highnote financial account. - **Non-originated ACH** — Initiated by a third party outside Highnote. - _Push (Credit):_ An external bank sends funds to a Highnote financial account. - _Pull (Debit):_ An external bank pulls funds from a Highnote financial account. ### AFT (Account Funding Transaction) A card network transaction that pulls funds from a card, debiting the sender. In Instant Network Transfers, AFT backs the source capability — a card's ability to send funds. ### Authorized user A person connected to an account holder who is authorized to use a payment card. ### AVS (Address Verification Service) A service that verifies a cardholder's billing address, including ZIP code, street address, city, and state. ## B ### BIN (Bank Identification Number) The first four to six digits of a card number, identifying the issuing or acquiring bank. ## C ### Card product A card program and its components, including applications, financial accounts, payment cards, bank accounts, and associated transactions. ### Card profile A configuration that defines card elements applied to a card product. Highnote supports three types: - Physical card profiles - Digital card profiles - Virtual card profiles ### Chargeback A transaction reversal initiated by the cardholder's bank. Chargebacks occur when cardholders dispute transactions due to unauthorized charges, non-receipt of goods or services, or dissatisfaction. ### Collaborative application decisioning A feature that lets you provide a recommended approval decision for card product applications based on your credit policies. ### Collaborative authorization A feature that lets you approve or decline account holder transactions in real time based on your business logic. ## D ### Digital card A tokenized representation of a payment card, created and managed virtually. Digital cards let cardholders make purchases through digital wallets. ### Dispute A cardholder's formal challenge to a posted transaction—typically for unauthorized activity or failure to receive purchased goods or services. Disputes are initiated by cardholders and investigated by Highnote. ### Document upload The process of account holders submitting documents to verify their identity or finances during application. ## E ### Electronic funds transfer (EFT) The electronic exchange of money between accounts, financial institutions, or entities. ### External bank account An account at a financial institution outside Highnote. External bank accounts can be: - _Non-verified:_ Can only receive transfers from Highnote financial accounts. - _Verified:_ Verified through Plaid or Finicity; can both send and receive transfers. ## F ### Financial account An account representing funds available for use by, or owned by, a Highnote account holder. ### Financial event Any event that impacts a financial account balance, including non-transactional events. Financial events create ledger entries. Examples include authorizations, clearings, ACH transfers, reversals, and fee transfers. See the Financial Event Reference for the complete list. ### Flexible credential A group of credentials issued to one account holder, with Highnote selecting which credential funds each transaction at authorization. The cardholder carries only the primary credential's card. ## L ### Ledger A financial account's record of activity. A financial account can have multiple ledgers depending on the card product type. ### Ledger entry A record created from a financial event using double-entry accounting. Each ledger entry changes the account balance. ## M ### Member card The payment card issued for one credential on a Flexible Credential. Each credential has its own member card, and the cardholder carries only the primary credential's. The API uses this name in , whose accepts . ## N ### Notification event A predefined event that triggers actions in integrated systems, enabling data exchange between Highnote and external platforms. ### Notification target The destination endpoint where notifications are delivered via webhook. ## O ### OCT (Original Credit Transaction) A card network transaction that pushes funds to a card, crediting the recipient. In Instant Network Transfers, OCT backs the destination capability — a card's ability to receive funds. ### On-demand funding A feature that instantly adds funds to an account holder's financial account at authorization time. ### OFAC (Office of Foreign Assets Control) An agency under the US Treasury Department that administers and enforces economic and trade sanctions based on US foreign policy and national security goals. ## P ### Payment card A card or access device connected to an account holder's financial accounts under a card product. ### Physical card A physical payment card issued to an account holder or authorized user. ### Product funding account A financial account used as a funding source for a card product. Funds can be distributed to account holder financial accounts. ### Program management A Highnote service that includes management, operations, and risk monitoring for card programs. As a program manager, Highnote establishes relationships with sponsor banks, payment networks, and distributors. ### Pseudo balance A feature that sets spend limits on financial accounts using on-demand funding. ## R ### Reconciliation An accounting process that compares two sets of financial records to ensure accuracy and agreement. ### Report A data export from the Highnote platform. Available report types include card interchange activity, card transaction activity, ledger entry, credit loan tape, fleet enhanced data summary, and more. ### Rewards Highnote's integrated cash-back rewards feature. ## S ### Source financial account A card product financial account that funds account holder financial accounts when on-demand funding is enabled. Provides real-time funding via internal Highnote transfers. ### Spend rules A feature that sets business logic to permit or restrict authorizations. ### Summary metrics Aggregated data points showing card product performance and usage. Available in the Highnote dashboard and via API. ## T ### Tokenization The process of replacing sensitive data with a secure token. For example, replacing a cardholder's personal account number (PAN) with an encrypted value to maintain security and compliance. ## V ### Velocity controls A feature that sets volume and frequency limits on transactions within specific time frames. ### Virtual card A payment card for use online, in apps, or for machine-to-machine payments. --- URL: https://docs.highnote.com/docs/get-started/introduction/launch-checklist Title: Launch Checklist Section: Get Started Description: Prepare for production launch with checklists for technology readiness, compliance, customer support, risk management, and funding. To help prepare you for launch, the Highnote team provides you with a launch readiness checklist, testing plan, and compliance resources. Before launching, create an account and an API key in the Dashboard, and complete any other instructions from the Highnote team. ## Technology Readiness To ensure your integration is prepared for launch, the Highnote Team will work with you to review the following: - [ ] APIs integrated and tested to launch with confidence. Test the following functionalities that are applicable to your Card Product: #### Funding - [ ] Simulate deposit to Financial Accounts - [ ] Simulate funding from external bank account - [ ] Simulate necessary account transfers and on-demand funding configuration #### Issuance - [ ] Collaborative Authorization integrated and tested #### Onboarding - [ ] Account Holder facing application tested and operational, including support for document upload - [ ] Simulate manual review flow #### Physical Card - [ ] Simulate Physical Card order #### Reporting - [ ] Notifications - [ ] Post-integration discovery call scheduled with Highnote Product team product-team@highnote.com ## External Testing The Highnote Team will set up and add users to your Live Environment and perform several tests to ensure functionality. During this phase, you can expect the Highnote Team to test the following: - [ ] Maximum number of cards verified - [ ] Set up and review the Support process - [ ] External test plan and issue tracking ## Compliance, Collateral, and Reporting The Highnote Team will work with you to ensure your compliance and reporting processes are ready for launch. You can expect the following during this phase: - [ ] Card Product collateral approved, including ACH consent if ACH origination is supported by the program - [ ] All disclosures, policies, and compliance documents approved - [ ] Confirm owner for the following monthly reporting requirements: - [ ] Customer Service reporting - [ ] Monthly Complaints reporting - [ ] Regulation B reporting (if applicable) - [ ] Disputes reporting - [ ] Confirm owner for Compliance Monitoring (delegated CIP where applicable) - [ ] Confirm owner for ongoing collateral review process (marketing materials and any changes to card art, primary website, etc.) ## Customer Support The Highnote Team will work with you to prepare Customer Support processes for launch. You can expect the following during this phase: - [ ] Confirm post launch Support process - [ ] Design disputes process - [ ] Confirm card ordering SLAs, expedites, and pulls - [ ] Set up disputes and risk emails ## Risk The Highnote Team will work with you to mitigate any possible risk and prepare you to handle risk processes after launch. You can expect the following during this phase: - [ ] Application flow demo for Risk and Support, including a sample of customer app screens after an account is opened - [ ] Confirm communication preference and notification email from for: - [ ] Manual review - [ ] Fraud review processes and notifications - [ ] Suspicious activity - [ ] Risk Review (ACH Hold reviews & Card Account risk reviews) - [ ] Account closures ## Funding The Highnote Team will work with you fund your Card Product. You can expect the following during this phase: - [ ] Fund the minimum for Product Funding Account ## Billing The Highnote Team will work with you to complete the following steps to ensure billing readiness: - [ ] Complete ACH authorization for debits/credits - [ ] Confirm readiness for monthly billing --- URL: https://docs.highnote.com/docs/get-started/introduction/pci-dss-compliance Title: PCI Data Security Compliance Section: Get Started Description: Understand PCI DSS compliance levels and determine your requirements. Use Highnote SDKs with tokenization to reduce your PCI scope to SAQ-A. ## Overview Highnote subscribers who access sensitive payment data from their own servers must be fully PCI compliant. Consider using the Highnote SDKs to reduce your PCI compliance requirements. Payment Card Industry Data Security Standards, or PCI DSS, are designed to protect payment data throughout the payment lifecycle. How you process and access PCI data will determine your compliance requirements. There are different levels of compliance (usually 4 for merchants and 2 for service providers). The PCI Security Standards Council (PCI SSC) develops and maintains standards for each level; and each card network defines their own specific requirements based on those standards. ## Compliance levels **All levels of PCI compliance require an Attestation of Compliance (AOC).** Full PCI DSS compliance requires a Report on Compliance (ROC) and an AOC signed by a Qualified Security Assessor (QSA). Lower levels of compliance require a Self-Assessment Questionnaire (SAQ) and a self-signed AOC. - **SAQ-A**: Typically used for **merchants** who fully outsource all cardholder data functions to PCI DSS validated third-party service providers, and have no electronic storage, processing, or transmission of any cardholder data on their systems or premises. - **SAQ-D**: Typically used for **merchants** who don't qualify for any other SAQ and handle cardholder data themselves; or for **service providers** who handle their own cardholder data and may store it electronically. #### Typical Merchant Compliance Levels | Levels | Transactions Per Year | Requirements | | :------ | :------------------------------------- | :----------------------------------------------------- | | Level 1 | 6 million | Annual ROC + AOC signed by QSA, Quarterly scans by ASV | | Level 2 | 1-6 million | Annual SAQ + self-signed AOC, Quarterly scans by ASV | | Level 3 | 20,000-1 million e-commerce | Annual SAQ + self-signed AOC, Quarterly scans by ASV | | Level 4 | Up to 20k e-commerce, or 1 mil regular | Annual SAQ + self-signed AOC, Quarterly scans by ASV | #### Typical Service Provider Compliance Levels | Levels | Transactions Per Year | Requirements | | :------ | :-------------------- | :----------------------------------------------------- | | Level 1 | 300,000 | Annual ROC + AOC signed by QSA, Quarterly scans by ASV | | Level 2 | Up to 300,000 | Annual SAQ-D + self-signed AOC, Quarterly scans by ASV | ## Highnote SDKs Highnote SDKs can significantly reduce your PCI compliance requirements. Highnote SDKs enable you to handle payment data without having PCI-scoped data flowing through your systems. Subscribers who are SAQ-A compliant, and want to maintain that compliance, should tokenize payment data with the Highnote Checkout SDK, or more customizable Secure Inputs SDK. Subscribers who are SAQ-D compliant, and already store PCI data securely, can bypass tokenization. #### Issuing - Card Viewer SDK - Embed sensitive card data into your UI using iframes. - Secure Inputs (PIN) SDK - Securely set and update PIN data from your UI using iframes. #### Acquiring - Checkout SDK - Simple embedded checkout UI to accept payment card information. - Secure Inputs (Tokenization) SDK - Customized checkout UI to tokenize payment method details. ## Compliance decision guide When analyzing your compliance needs, start by asking the following: **Question 1:** Will you handle sensitive cardholder payment data (possibly with the Highnote PaymentCardRestrictedDetails API) on your own servers? - If YES: Establish SAQ-D compliance at a minimum, or full Level 1 if you have high transaction processing volumes. - If NO: Use the Highnote Secure Inputs tokenization SDK to maintain your SAQ-A compliance (and continue to question 2). **Question 2:** Will you customize your payment and card experience for customers? - If NO: Use the Highnote Checkout SDK (acquirers) or Card Viewer SDK (issuers) to maintain your SAQ-A compliance. - If YES: Use the Highnote Secure Inputs tokenization or PIN SDKs to maintain your SAQ-A compliance. #### For Issuers | Solution | Purpose | Compliance Requirements | Best For | | --------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | | **Card Viewer SDK** | Embed viewer solution to display sensitive card data in your UI through iframes | PCI data never crosses your server. Maintains PCI SAQ-A compliance. | Issuers wanting to display card details without handling PCI data | | **Secure Inputs SDK (PIN)** | Customize your UI so customers can securely input sensitive data | PCI data never crosses your server. Maintains PCI SAQ-A compliance. | Issuers requiring customized PIN management solution while maintaining SAQ-A compliance | #### For Acquirers | Solution | Purpose | Compliance Requirements | Best For | | -------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | **Checkout SDK (with tokenization)** | Embed checkout solution to securely accept payment card details | PCI data never crosses your server. Maintains PCI SAQ-A compliance. | Merchants wanting simple, compliant checkout with minimal integration effort | | **Secure Inputs SDK (Tokenization)** | Customize your UI to securely accept payment card details | PCI data never crosses your server. Maintains PCI SAQ-A compliance. | Merchants requiring customized checkout while maintaining SAQ-A compliance | | **Direct API Integration (no tokenization)** | Server-to-server processing of card data | Requires SAQ-D compliance at minimum. May require full Level 1 PCI compliance with QSA assessment for high volumes. Your servers must securely store and handle PCI data. | Merchants already PCI SAQ-D compliant who want to bypass tokenization | --- URL: https://docs.highnote.com/docs/developers/about-developers Title: About Developer Resources Section: Developers Description: Learn about the Highnote GraphQL API, client-side SDKs, event notifications, and Snowflake Data Share for analytics. Highnote provides a comprehensive set of developer tools to build, integrate, and manage your payment solutions. Whether you're issuing cards, processing transactions, or managing accounts, these resources help you get up and running quickly. ## Highnote API The Highnote GraphQL API is your primary interface for interacting with the Highnote platform. Use it to create card products, manage account holders, issue payment cards, and process transactions. The API supports features like idempotency, search with HQL, custom metadata, and rate limiting to help you build resilient integrations. ## Highnote SDKs Highnote's SDKs simplify integration by providing client libraries for common platforms. SDKs handle client token management and provide secure access to sensitive operations like revealing payment card details. ## Event Notifications Event Notifications keep your systems in sync with changes on the Highnote platform. Subscribe to events and configure webhooks for real-time updates on transaction activity, account holder status changes, and other platform events. See the Events Reference for a complete list of available events. ## Data Share Highnote Data Share provides secure access to your Highnote data through Snowflake. Query and analyze your issuing and acquiring data for reporting and analytics, with most data available within 3 hours. See the Issuing Data Dictionary and Acquiring Data Dictionary for details on available data. ## Next steps - Learn about the API and how to make your first request. - Set up an SDK for your platform. - Configure event notifications to receive real-time updates. - Contact your Highnote representative to ask how to Connect to Snowflake and start querying your data. --- URL: https://docs.highnote.com/docs/developers/api/custom-metadata-fields Title: Custom Fields for Metadata Section: Developers Description: Add, update, and query custom key-value metadata on financial accounts and payment cards to link external system IDs, tag objects, and filter searches. ## Overview For compliance and security reasons, **do not use custom fields to store PCI or PII data.** Financial account and payment card objects implement custom fields that let you to add key-value pairs to the object. ### CustomFields Object Each Highnote [](/docs/api-reference/object#CustomStringField) object is a set of key-value pairs stored and returned in plain text. It includes a creation date and an updated date. Limits are: - You are allowed a maximum of 20 objects. - Each key is an alphanumeric string with a maximum of 40 characters. - Each value is an alphanumeric string with a maximum of 255 characters. ### Use Cases Use cases for using custom fields include: - Linking IDs in your system with Highnote data - Marking notes on Highnote data - Adding a nickname to a card - Tagging an account with the application ID - Searching for objects relating to a customer in your system ## Query custom fields You can use the following node query to find on a financial account: ## Search multiple objects You can also use a query with a to look up multiple objects and their custom fields. Use the following query to search multiple objects: ## Filters In addition to using the filter to search multiple objects, you can use the following filters to refine your search results: #### Accepts one input - [](#example-1-equals) - [](#example-2-not-equals) #### Accepts one or more inputs - [](#example-3-includes) - [](#example-4-excludes) ### Example 1: Equals The following code snippet provides an example of using the filter in your query input: Input variable for equals filter ```json { "applicationId": "", "first": 10, "filterBy": { "customFields": { "equals": { "key": "customerId", "value": "custom_123" } } } } ``` ### Example 2: Not equals The following code snippet provides an example of using the filter in your query input: Input variable for notEquals filter ```json { "applicationId": "", "first": 10, "filterBy": { "customFields": { "notEquals": { "key": "customerId", "value": "custom_123" } } } } ``` ### Example 3: Includes The following code snippet provides an example of using the filter in your query input: Input variable for includes filter ```json { "applicationId": "", "first": 10, "filterBy": { "customFields": { "includes": [ { "key": "customerId", "value": "custom_123" }, { "key": "customerId4", "value": "custom_456" } ] } } } ``` ### Example 4: Excludes The following code snippet provides an example of using the filter in your query input: Input variable for excludes filter ```json { "applicationId": "", "first": 10, "filterBy": { "customFields": { "excludes": [ { "key": "customerId", "value": "customer_123" }, { "key": "regionId", "value": "region_123" } ] } } } ``` ## Create custom fields for new object Currently, objects that support custom fields are and . You can create custom fields when creating a new object that supports . The following mutation provides an example of creating a with key-value pairs entered as input variables: ## Update custom fields of existing object Setting a key-value pair's value to empty will delete the key. You can add, update, or delete of an existing object with the mutation and by referencing key-value pairs explicitly as input variables. ### Example 1: Add fields The following example uses the UpdateCustomFields mutation to add multiple customFields key-value pairs to an existing object: ### Example 2: Add, update, delete fields ## Delete custom fields You can use the following mutation to delete _all_ for an object without having to specify the keys explicitly: ### GraphQL: Node Query: query Node($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { __typename id customFields { key ... on CustomStringField { value } } } } } Variables: { "id": "" } Expected Result: { "data": { "issueFinancialAccountForApplication": { "__typename": "FinancialAccount", "id": "", "customFields": [ { "key": "customerGroupId", "value": "group_123" }, { "key": "customerId", "value": "customer_123" } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11 } } } ### GraphQL: getFinancialAccountsForApplication Query: query getFinancialAccountsForApplication( $applicationId: ID! $first: Int $filterBy: AccountHolderFinancialAccountsFilterInput ) { node(id: $applicationId) { ... on AccountHolderCardProductApplication { id financialAccounts(first: $first, filterBy: $filterBy) { edges { node { id customFields { __typename ... on CustomStringField { key value } } } } } } } } Variables: { "applicationId": "", "first": 10, "filterBy": { "customFields": { "equals": { "key": "customField1", "value": "customValue1" } } } } Expected Result: { "data": { "node": { "id": "", "financialAccounts": { "edges": [ { "node": { "id": "", "customFields": [ { "__typename": "CustomStringField", "key": "customerGroupId", "value": "group_123" }, { "__typename": "CustomStringField", "key": "customerId", "value": "customer_123" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13 } } } ### GraphQL: IssueFinancialAccountForApplication Query: mutation IssueFinancialAccountForApplication( $input: IssueFinancialAccountForApplicationInput! ) { issueFinancialAccountForApplication(input: $input) { ... on FinancialAccount { __typename id customFields { key ... on CustomStringField { value } } } ... on UserError { __typename errors { errorPath code description } } } } Variables: { "input": { "applicationId": "", "name": "Test Account", "customFields": [ { "key": "customerId", "value": "customer_123" }, { "key": "customerGroupId", "value": "group_123" } ] } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "__typename": "FinancialAccount", "id": "", "customFields": [ { "key": "customerGroupId", "value": "group_123" }, { "key": "customerId", "value": "customer_123" } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11 } } } ### GraphQL: AddCustomFields Query: mutation UpdateCustomFields($input: UpdateCustomFieldsInput!) { updateCustomFields(input: $input) { ... on CustomFieldsResult { customFields { key ... on CustomStringField { value } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "id": "", "customFields": [ { "key": "regionId", "value": "region_123" }, { "key": "customerGroupId", "value": "group_123" }, { "key": "customerId", "value": "customer_123" } ] } } Expected Result: { "data": { "updateCustomFields": { "customFields": [ { "key": "regionId", "value": "region_123" }, { "key": "customerGroupId", "value": "group_123" }, { "key": "customerId", "value": "customer_123" } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11 } } } ### GraphQL: UpdateCustomFields Query: mutation UpdateCustomFields($input: UpdateCustomFieldsInput!) { updateCustomFields(input: $input) { ... on CustomFieldsResult { customFields { key ... on CustomStringField { value } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "id": "", "customFields": [ { "key": "regionId", "value": "" }, { "key": "customerGroupId", "value": "group_456" }, { "key": "sectorId", "value": "sector_123" } ] } } Expected Result: { "data": { "updateCustomFields": { "customFields": [ { "key": "customerId", "value": "customer_123" }, { "key": "customerGroupId", "value": "group_456" }, { "key": "sectorId", "value": "sector_123" } ] } }, "extensions": { "requestId": "316817c8-ef45-9d2e-a376-92420a136352", "rateLimit": { "cost": 11 } } } ### GraphQL: DeleteCustomFields Query: mutation DeleteCustomFields($input: DeleteCustomFieldsInput!) { deleteCustomFields(input: $input) { ... on CustomFieldsResult { customFields { key ... on CustomStringField { value } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "deleteCustomFields": { "customFields": [] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11 } } } --- URL: https://docs.highnote.com/docs/developers/api/entity-ids-and-object-types Title: Entity IDs and Object Types Section: Developers Description: How Highnote entity IDs work, how to identify object types using the __typename field, and how to read the placeholder IDs used throughout the documentation. Every in the Highnote API has a globally unique ID. Treat IDs as opaque strings you pass back to Highnote, not as structured data to parse. Every entity ID starts with a short prefix that indicates its type, followed by a hash value. But prefixes can change, so you should not treat them as a stable contract. Throughout this documentation set, **angle-bracketed placeholder text** in all caps stands in for real values. For example: | Entity | Prefix | Placeholder in Docs | | :--------------- | :------------- | :----------------------- | | FinancialAccount | | | | PaymentCard | | | | CardProduct | | | ## Identify types with For programmatic type identification, use the field — it is available on every object in the Highnote API and matches the GraphQL type name exactly: ```graphql query { node(id: "") { __typename id } } ``` ```json { "data": { "node": { "__typename": "FinancialAccount", "id": "" } } } ``` ## Documentation placeholders Interactive examples throughout the documentation use angle-bracketed placeholders to stand in for real values. Anything wrapped in is a placeholder you replace with your own data before sending a request, or a stand-in for the opaque value Highnote returns in a response. ```json { "variables": { "financialAccountId": "" } } ``` The placeholder naming follows a few consistent conventions. ### Entity ID placeholders Entity ID placeholders use the entity name in with an suffix: - → replace with a real FinancialAccount ID (e.g., ) - → replace with a real PaymentCard ID (e.g., ) - → replace with a real CardProduct ID (e.g., ) When an example has multiple IDs of the same entity type, the placeholder gets a numeric suffix to distinguish them: ```json { "edges": [ { "node": { "id": "" } }, { "node": { "id": "" } } ] } ``` When the distinction between IDs carries meaning that a numeric suffix would lose — for example, multi-party payment splits or single-use vs. reusable tokens — the suffix can be descriptive instead: ```json { "disburseToId": "", "paymentMethodTokenId": "" } ``` ### Values you provide Customer-provided values — IDs you generate or assign in your own systems — use a prefix: - — an external ID you set on a Highnote entity to reference it in your own system - — an identifier you assign to a merchant in your system - — a UUID you generate for idempotency - — an identifier you assign to an end-user - — your Finicity partner-issued customer ID ### Opaque tokens and generated values Some values are opaque tokens or platform-generated identifiers that behave differently from entity IDs. These use descriptive names without the suffix: - — a digital wallet token (Apple Pay, Google Pay, etc.) - — a tokenized payment method - — a pagination cursor used with and arguments - — a Highnote-generated request trace ID returned in the field of every response ### Interfaces and unions Some placeholders refer to GraphQL interfaces or unions with multiple concrete types. When an example includes the field, the placeholder name matches the concrete type. When no is shown, the placeholder uses the interface or umbrella name. Country-specific prefixes like are dropped from placeholder names because the placeholder convention should remain stable if Highnote expands to other regions. For example, becomes , and becomes . For example, is an interface with many concrete event types (, , , etc.). An example that queries might show , while a response that omits shows to indicate "any event in the interface." ## Placeholder reference The table below maps each placeholder used in documentation examples to its underlying GraphQL type. Placeholders for interfaces and unions include the concrete subtypes in the Variations column. | Placeholder | Entity | Variations | | :--------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | AccountHolderApplicationDocument | | | | AccountHolderCardProductApplication | | | | AccountHolderCardProductApplication | | | | AccountHolderCardProductApplicationOffer | | | | FinancialAccount | | | | AccountHolder | USBusinessAccountHolder, USPersonAccountHolder, Organization, Business | | | AccountHolderProvisioning | | | | AccountHolderProvisioningWorkflowAction | | | | AccountHolderRiskScore | | | | FinancialAccount | | | | InterFinancialAccountTransfer | | | | AchTransfer | OriginatedAchTransfer, NonOriginatedAchTransfer | | | ValidatedAddressToken | | | | ApplicationContract | | | | ProductApplication | | | | AccountHolderCardProductApplicationSnapshot | | | | RewardRedemptionAttachment (verify) | | | | AuthorizedPerson (any subtype when is not specified) | USBusinessAuthorizedPerson, USPersonAuthorizedUser | | | AuthorizedUserCardProductApplication | | | | USPersonAuthorizedUser | | | | FinancialAccount | | | | USBusinessUltimateBeneficialOwner | | | | USBusinessAccountHolder | | | | USBusinessAuthorizedPersonAccountHolder (verify) | | | | USBusinessAuthorizedPerson | | | | Business | | | | USBusinessProfile | | | | USBusinessUltimateBeneficialOwner | | | | CardProductAgreement (verify) | | | | PhysicalPaymentCardOrder | | | | CardPaymentDispute | | | | CardProductApplication (any subtype when is not specified) | AccountHolderCardProductApplication, AuthorizedUserCardProductApplication | | | CardProduct | | | | CardProfileSet | | | | CardProductVertical enum placeholder (replace with an enum value such as ) | | | | CatalogItem | | | | PaymentCardTransactionChargeback | | | | FeeTransfer | ChargedFeeTransfer, ReversedFeeTransfer | | | CheckPaymentEvent | | | | CheckPayment | | | | City (locality) placeholder (used in address examples) | | | | Opaque client token value used to authorize SDK-side calls | | | | CollaborativeAuthorizationEndpoint | | | | ConsentTemplate (verify) | | | | Timestamp of the applicant's consent (ISO 8601) | | | | CreditCardTransferAccrualEvent (verify) | | | | CreditCardTransferEvent | | | | CreditCardTransferReversalEvent (verify) | | | | CreditLimitChangeRequest | | | | FinancialAccountCreditLimitUpdateFromProductFunding | | | | CreditPlan | | | | CreditPlanTemplate | | | | CumulativeRule (verify) | | | | Pagination cursor (opaque string) | | | | Pagination cursor (legacy suffix; see above) | | | | Date-of-birth placeholder (used in person-identity examples) | | | | DeliveryAttempt | | | | DigitalCardProfile | | | | CardDigitalWalletToken | | | | DirectDepositDetail | | | | DisbursementTransferEvent | | | | PaymentCardTransactionDispute | | | | CardPaymentDispute | | | | DocumentUploadFile (verify) | | | | DocumentUploadLink | | | | DocumentUploadSession | | | | DocumentUploadSessionLink (verify) | | | | Doing-business-as name placeholder (used in business-profile examples) | | | | ElectronicFundsTransfer | PayrollTransfer, CreditFunds, DebitFunds, SecureDepositACHTransfer, SecureDeposit, IntegratorInitiatedFundsWithdrawalACHTransfer, IntegratorInitiatedFundsDepositACHTransfer, SecureCardBalanceRepaymentACHTransfer, ExternallyInitiatedWireTransfer, OriginatedAchTransfer, NonOriginatedAchTransfer, ExternalMoneyMovementTransaction | | | FinancialAccount | | | | FinancialAccount | | | | Customer-provided employer name (example data) | | | | CollaborativeAuthorizationEndpoint | | | | Pagination end cursor (legacy suffix; see above) | | | | EnhancedDataEvent | | | | TransactionEnhancedData (verify) | | | | TransactionEvent | ReversalEvent, ClearingEvent, EnhancedDataEvent, AuthorizationEvent, IssuerPreliminaryAuthorizationEvent, AuthorizationAndClearEvent, VerificationEvent, BalanceInquiryEvent, AdjustmentEvent | | | Expiration date string (e.g., ) | | | | VerifiedExternalBankAccount (verify) | | | | ExternalBankAccount (verify) | | | | ExternalFinancialAccount | ExternalFinancialBankAccount, NonVerifiedExternalUSFinancialBankAccount | | | ExternalFinancialBankAccount | | | | Subscriber-assigned external ID on a Highnote entity (see above) | | | | ExternalMoneyMovementTransactionEvent | | | | ExternalMoneyMovementTransaction | | | | ExternalPhysicalPaymentCardOrder | | | | Family-name placeholder (used in person-identity examples) | | | | FeeChargeEvent | | | | FeeChargeRuleCountCondition | | | | FeeChargeRule | | | | FeeConfiguration | | | | FeeReversalEvent | | | | FeeSchedule | | | | FeeTransferEvent | | | | FeeTransfer | ChargedFeeTransfer, ReversedFeeTransfer | | | FinancialAccount | | | | Ledger | | | | FinancialAccountSnapshot | | | | FinancialAccountStatement | Product-specific statement types (Consumer/Commercial × Credit/Prepaid/Charge) | | | FlexibleCredentialAttemptEvent | | | | FlexibleCredential | | | | PaymentCardFulfillment (verify) | | | | Given-name placeholder (used in person-identity examples) | | | | GlobalNote | | | | PhysicalCardGroupOrder | | | | PhysicalCardGroupOrder | | | | Hash value (e.g., a card-number hash) | | | | Idempotency key for the request (see above) | | | | InstallmentAgreement | | | | InstantNetworkTransferEvent | | | | InstantNetworkTransfer | | | | InterFinancialAccountTransfer | | | | InterFinancialAccountTransferEvent | | | | InterFinancialAccountTransfer | | | | IP-address placeholder (e.g., consent capture) | | | | LedgerEntry | CreditLedgerEntry, DebitLedgerEntry | | | Ledger | | | | Legal business-name placeholder (used in business-profile examples) | | | | MastercardFleetAuthorizationData | | | | MerchantAcceptor | | | | Merchant descriptor shown to cardholders on statements | | | | Merchant | | | | Free-form name placeholder | | | | Generic node identifier (used in interface examples) | | | | NotificationEvent | | | | WebhookNotificationTarget | | | | Free-form number placeholder (e.g., card number) | | | | Generic order identifier (specific orders use entity-specific placeholders like or ) | | | | Organization | | | | AccountHolder | USBusinessAccountHolder, USPersonAccountHolder, Organization, Business | | | PaymentCard | | | | PaymentCardSnapshot | | | | PaymentCardTransactionChargeback | | | | PaymentCardTransactionDispute | | | | PaymentMethodToken | | | | PaymentOrder | | | | PaymentTransactionStep (verify) | | | | PaymentTransaction | PaymentDebitTransaction, PaymentCreditTransaction | | | PaymentTransactionSummary | PaymentDebitTransactionSummary, PaymentCreditTransactionSummary | | | USPersonAccountHolder | | | | USPersonAuthorizedUser | | | | Email placeholder (used in person-identity examples) | | | | Free-form phone-number placeholder | | | | PhysicalCardGroupOrder | | | | PhysicalPaymentCardOrder | | | | PhysicalPaymentCard (verify) | | | | PhysicalPaymentCardOrder | | | | Postal-code placeholder (used in address examples) | | | | AccountHolderCardProductApplication | | | | PricingPlan | | | | AuthorizedPerson | USBusinessAuthorizedPerson, USBusinessAuthorizedPersonSnapshot, BusinessAuthorizedPerson | | | ProductApplication | | | | ProductBalance (verify) | | | | FinancialAccount | | | | FinancialAccount | | | | PseudoBalanceUpdate (verify) | | | | Receiver identification number on an ACH transfer | | | | RewardRedemptionConfiguration | | | | Region/state placeholder (used in address examples) | | | | Report | | | | RequestedIdentityUpdate | | | | Highnote-generated request trace ID (returned in ) | | | | ReviewWorkflowEvent | | | | RewardEarnRule | RewardMerchantCategoryEarnRule, RewardDefaultEarnRule | | | RewardPointsTransfer | | | | RewardRedemptionAttachment (verify) | | | | RewardRedemptionConfiguration | | | | RtpTransferEvent | OriginatedRtpTransferEvent, NonOriginatedRtpTransferEvent | | | RtpTransfer | OriginatedRtpTransfer, NonOriginatedRtpTransfer | | | ScheduledTransferEvent | | | | ScheduledTransfer | | | | Highnote-issued API secret key value | | | | SecretKey (verify) | | | | InterFinancialAccountTransfer | | | | FinancialAccount | | | | InterFinancialAccountTransfer | | | | SigningKey | | | | Generic ID placeholder (used in conceptual examples; replace per context) | | | | AccountHolderCardProductApplication | | | | FinancialAccount | | | | SpendRule | Concrete subtypes: AmountLimitSpendRule, MerchantCategorySpendRule, CVVSpendRule, and others | | | Social Security number placeholder (used in person-identity examples) | | | | Pagination start cursor (legacy suffix; see above) | | | | FinancialAccountStatement | SecuredDepositCommercialCreditCardFinancialAccountStatement, CreditPayInFullCardFinancialAccountStatement, ConsumerChargeCardFinancialAccountStatement, ConsumerPrepaidCardFinancialAccountStatement, ConsumerRevolvingCardFinancialAccountStatement, CommercialChargeCardFinancialAccountStatement, CommercialRevolvingCardFinancialAccountStatement | | | Street-address placeholder (used in address examples) | | | | Customer-support email placeholder (used in business-profile examples) | | | | Generic target entity identifier | | | | Tax identification number placeholder (used in business-profile examples) | | | | Opaque tokenized-data token | | | | Generic token identifier | | | | TransactionEnhancedData (verify) | | | | TransactionEvent | Concrete subtypes: AuthorizationEvent, ClearingEvent, AdjustmentEvent, ReversalEvent, and others | | | Transaction | Concrete subtypes: DebitTransaction, CreditTransaction | | | Transfer | | | | USBusinessUltimateBeneficialOwner | | | | UnifiedFundsTransfer | | | | UnifiedFundsTransferQuote | | | | UnifiedFundsTransferStep | UnifiedFundsTransferInitiateRequestStep, UnifiedFundsTransferInstantNetworkTransferStep, UnifiedFundsTransferRtpStep | | | UserDefinedFieldDefinition | | | | UserDefinedField | | | | User | | | | ValidatedAddress | | | | VelocityRule | | | | VerifiedExternalBankAccount (verify) | | | | VirtualCardProfile | | | | VisaFleetAuthorizationData | | | | WebhookNotificationTarget | | | | WireTransfer | | | | WireTransferReversal (verify) | | | | WorkflowConfiguration (verify) | | | | Subscriber-assigned application ID | | | | Customer-defined consent template identifier | | | | Customer-provided end-user identifier | | | | Customer-provided external ID on a Highnote entity | | | | Customer-provided Finicity partner customer ID | | | | Customer-generated idempotency key (UUID) | | | | Customer-assigned merchant identifier | | --- URL: https://docs.highnote.com/docs/developers/api/error-handling Title: API Error Handling Section: Developers Description: Handle GraphQL errors using the errors-as-data pattern with UserError types. Use the requestId field to troubleshoot failed requests with Highnote support. ## Query errors The Highnote API rejects invalid queries and populates error information in the array. These errors are similar to compile-time errors and can be triggered if you send an invalid type or miss a required field. Invalid queries return a error response with the following body: ```graphql { "data": null, "errors": [ { "message": "String cannot represent integer", "locations": [{"line": 1, "column": 6}], "errorPath": [] } ] } ``` We recommend testing requests and queries in the Test environment before using them in your Live environment. After testing in the Test environment, you should see very few errors. ## Validation and logic errors The Highnote API uses the errors as data pattern for validation and logic errors. Using (instead of ) lets Highnote document and tailor what is returned to your system. Invalid input errors are represented as data in the type that is part of the returned type. All mutations have the type on the union that you can select and query for errors. ## Troubleshooting with request ID The Highnote API includes a field with a unique identifier for each request. The request ID is especially useful when you need help with a response. Ensure you log this ID on any errors you encounter so the Highnote support team can monitor and debug your request. The field can be found in the key of the response: --- URL: https://docs.highnote.com/docs/developers/api/idempotency Title: Idempotency Section: Developers Description: Prevent duplicate mutations when retrying failed API requests by providing unique idempotency keys with your requests. ## Overview The Highnote GraphQL API supports idempotency to ensure platform reliability and consistency. Our Highnote API IdempotencyKey lets you reattempt failed API requests, without creating duplicates or provoking conflicts. ## Key specifications To enable idempotency, add an to all Highnote API mutations with the following specifications: - Format: Version 4 UUID>) - Length: 10 to 255 characters After receiving the request, the Highnote platform stores the provided UUID with your Organization ID and query. With the idempotency key stored, the Highnote API tracks the parameters of incoming requests to determine if a request is new or a retry. ## Key example The following code snippet is an example of a mutation sent to the API with an idempotency key provided as an input variable: ### GraphQL: ChargeOrderWithPaymentMethodToken Query: mutation ChargeOrderWithPaymentMethodToken( $input: ChargePaymentOrderPaymentMethodTokenInput! ) { chargePaymentOrderFromPaymentMethodToken(input: $input) { ... on CardCapturePaymentOrderSummary { transaction { __typename id } } } } Variables: { "input": { "paymentMethodTokenId": "", "orderId": "", "amount": { "currencyCode": "USD", "value": "250" }, "merchantAcceptorId": "", "idempotencyKey": "12345678-1234-5678-1234-567812345678", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "chargePaymentMethodToken": { "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "" } } } } --- URL: https://docs.highnote.com/docs/developers/api/intro-to-graphql Title: Intro to GraphQL Section: Developers Description: Learn core GraphQL concepts including queries, mutations, the type system, and Relay pagination as they apply to the Highnote API. ## What is GraphQL? GraphQL is a query language for APIs that lets clients request only the data they need. GraphQL APIs offer several benefits over REST APIs: - **Reduced data transfer**: Specify the exact data you need - **Simplified client code**: Simplify and easily maintain code without relying on multiple endpoints or parsing logic - **Powerful querying**: Use nested queries, filtering, sorting, and pagination to find the data you need Highnote uses a GraphQL API to provide a flexible, modern, and secure integration experience. This guide prepares those who are new to GraphQL on using the Highnote API. For a deeper dive, see Using the Highnote API. Building a Node.js backend? The official [](https://github.com/highnote-oss/nodejs-sdk) (currently in beta) wraps the Highnote API in typed, resource-oriented methods — no GraphQL required. See it used end-to-end in the example reference apps (illustrative only, not production templates). ## How it works GraphQL operates on a defined type system called a _schema_. The schema describes the types of data available. Unlike REST APIs, where each endpoint typically corresponds to a specific resource and returns fixed datasets, GraphQL has a single endpoint that allows clients to specify the data they need using _queries_. Fetching data from a single endpoint allows clients to use single requests with specific fields to get all the data they need, reducing over-fetching and under-fetching data. When a client sends a query, the server checks it against a schema defining the available data types. Then, it uses resolver functions to gather the requested data from different sources. These functions work simultaneously, making data retrieval efficient. Finally, the server returns the collected data to the client in a single JSON object. ## Key concepts The following sections break down GraphQL's key concepts to help you understand how a GraphQL API works and how to interact with it. ### Operations GraphQL uses the term _operations_ to define request types. The following three operations are used in GraphQL for sending requests: - **Query**: Fetches data - **Mutation**: Writes data - **Subscription**: Receives real-time updates The Highnote API does not currently use subscriptions. ### Type system GraphQL uses a type system called a _schema_ to describe what data can be queried. The building blocks of a schema are object types. _Objects_ represent data you can fetch, with each object having _fields_. These fields are the specific pieces of data you can request. For example, the following code sample defines a object type with two fields, and name: ```graphql type CardProduct { id: ID! name: String } ``` ### Arguments Every field on a GraphQL object can have zero or more arguments. Arguments work like filters for additional information to help refine the data you request. For example, the object in the Highnote API has several arguments for different fields. In the following code sample, the field has and arguments that help refine the queried data: ```graphql type CardProduct { id: ID! name: String accounts(first: Int, after: String): FinancialAccountConnection } ``` ### Queries and mutations Queries and mutations are special objects that define the entry point of a GraphQL query. As noted in this guide, queries and mutations are operations that fetch or write data. Refer to the following pages of Highnote API Reference for available queries and mutations: - Query - Mutation ### Scalars A GraphQL object type has a name and fields, but those fields have to resolve to produce concrete data. This is where scalar types come in. If we use the object code sample to execute a query, the returned data would look something like this: ```graphql { "data": { "CardProduct": { "id": "1234", "name": "MyCardProduct" } } } ``` In this example, the and fields have resolved to scalar types in the query's response. GraphQL uses the following default scalar types: - : A signed 32-bit integer - : A signed double-precision fractional value as specified by IEEE 754 - : A UTF-8 character sequence - : true or false - : Represents a unique identifier GraphQL also allows for custom scalar types. For a complete list of the Highnote API's scalars, see Scalars in the API Reference. ### Enums Enumeration types, also called _enums_, are a special kind of scalar restricted to a specific set of values. Enums allow you to: - Validate that any arguments of this type are one of the allowed fields - Facilitate communication through the schema that a field will always be one of a finite set of values For example, in the Highnote API, a enum is restricted to the following values: - - For a complete list of the Highnote API's enums, see Enums in the API Reference. ### Interfaces Interfaces define a set of fields that other types must include to be considered that type. Interfaces are useful when you want to return an object or set of objects of several different types. This allows you to query for objects of other specific types as long as they share those required fields defined in the interface. For example, Highnote’s API has an interface named representing card product features. Any type that implements must have the interface’s exact fields: ```graphql interface CardProductFeature { enabled: Boolean createdAt: String updatedAt: String } ``` For a complete list of the Highnote API's interfaces, see Interfaces in the API Reference. ### Unions Union types are another way to define possible return types for a field. Unlike interfaces, they don’t have shared fields. When you query a field that uses a union type, you must use a special fragment to specify which fields you want depending on the returned type. For example, Highnote’s API has a union named that represents different card product application types. When you return a union type in the Highnote API, you will retrieve the following possible types: - - For a complete list of the Highnote API's unions, see Unions in the API Reference. ### Inputs Input types define the structure of the data you’re sending. Input types are valuable for mutations where you want to pass in a whole object. For example, if you are building a mutation for a card product application, you can use the to input data to filter data. For a complete list of the Highnote API's inputs, see Inputs in the API Reference. ### Introspection Highnote’s API has an introspection system that allows authenticated users to fully introspect the API. We recommend using the Highnote API Explorer to test the API’s introspection system in the Test environment. You can paste the following code sample into the **Query** section of the API Explorer to try out introspection: ```graphql { __schema { types { name } } } ``` ### Node queries and global IDs The Highnote API uses node queries and global IDs to look up individual objects. A _node query_ is defined as a pattern that allows clients to pass a global ID without specifying the entity it represents. In the following code sample, the node query is fetching an for either the or objects: ```graphql query NodeQuery($id: ID!) { node(id: $id) { ... on CardProduct { __typename id name } ... on PaymentCard { __typename id last4 } } } ``` Be sure to define the variable, e.g., ```json { "id": "pd_4644868cd7b749fa82a4149d46d9827d" } ``` When the query is resolved, the response looks something like this: ```json { "data": { "node": { "__typename": "CardProduct", "id": "pd_4644868cd7b749fa82a4149d46d9827d", "name": "Commercial Credit Card" } }, "extensions": { "requestId": "7482cd9d-4467-9d53-bb56-af6d843d608b", "rateLimit": { "cost": 1, "limit": 100000, "remaining": 99999 } } } ``` ### Pagination The Highnote API automatically paginates data following the Relay Cursor Connections Specification. Relay uses the edges field to obtain its list: specifies the position in the list, and contains the requested fields. For example, the following query finds an organization’s card products and lists the , , , and for each card product. The and fields define how the data is displayed. The and variables let the Highnote API know which records to return. You can adjust these variables to return as much or as little data as possible. - : Specifies maximum number of items to fetch at once (Integer, default 20). - : Specifies where in the list the cursor should start fetching (String). For example, to retrieve the first 10 card products, set to . To retrieve the next 10 card products, set to the cursor of the last item from the previous page. ```graphql query ListCardProducts($first: Int, $after: String) { cardProducts(first: $first, after: $after) { edges { cursor node { __typename id name usage vertical } } pageInfo { startCursor endCursor hasNextPage } } } ``` ### Making requests The Highnote API serves data as JSON over HTTP(s). GraphQL does not use HTTP verbs (, , etc.) or have multiple endpoints per resource. Instead, you make requests to a single endpoint using specific queries or mutations. Requests to the Highnote API should contain the following: - or : The operation of the request - _Optional_ - : A JSON payload used to pass dynamic data in a request - _Optional_ - : Specifies an action in the case multiple queries are sent In the following example, we use the ping query to showcase a request to the Highnote API: ```sh curl -X POST \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic ' \ --data '{"query":"query Ping {\n ping\n}"}' \ https://api.us.test.highnoteplatform.com/graphql ``` This request will return data in a JSON payload that looks like this: ```json { "data": { "ping": "pong" }, "extensions": { "requestId": "" } } ``` For more information on using the Highnote API to make requests, see Using the Highnote API. ## Clients and codegen The GraphQL ecosystem is dynamic and strongly enhances developers' and integrators' experiences. As a result, GraphQL supports innovation and modern approaches to development. When using the Highnote API, we recommend the following desktop clients, extensions, and codegens. ### Desktop clients When developing with GraphQL APIs, using a GUI tool that leverages introspection to provide documentation and type hints is helpful. Some of the tools we recommend using include: - Insomnia - GraphQL Playground - GraphiQL - Postman ### Editor plugins and browser extensions We recommend the following plugins for various IDEs to make your development experience more seamless: - GraphQL Developer Tools (Chrome) - Altair (Chrome, Firefox) - GraphQL DevTools (Firefox) - VSCode GraphQL - vim-graphql - JS GraphQL (IntelliJ, WebStorm) ### Codegen tools We recommend using GraphQL Code Generator to generate TypeScript definitions and SDKs for use with GraphQL. --- URL: https://docs.highnote.com/docs/developers/api/rate-limiting Title: API Rate Limiting Section: Developers Description: Manage request count and complexity rate limits, implement exponential backoff for 429 responses, and use webhooks to reduce polling. ## Rate limits By default the Test environment has 50% of the rate limit of the Live environment. To maintain optimal performance, an API rate limit limits the number of requests a client can make within a specific time frame. The Highnote platform has different rate limit types: - Request count - Complexity Rate limiting is based on which type you hit _first_. And each rate limit type is different for each Auth/API type. #### Request count rate limits | Auth/API Type | Limit | Note | | :------------ | :------------------------------------------ | :----------------------------------------------------- | | API key | 200 requests per 10 seconds | Aggregate limit across all API keys assigned to an org | | Client token | 20 requests per 10 seconds per user/subject | | | REST API | 200 requests per 10 seconds | | #### Complexity rate limits | Auth/API Type | Limit | Note | | :------------ | :----------------------------------------------- | :----------------------------------------------------- | | API key | 5,000 complexity per 10 seconds | Aggregate limit across all API keys assigned to an org | | Client token | 5,000 complexity per 10 seconds per user/subject | | | REST API | N/A | | For more information on calculating request complexity, see Request Complexity. ## Rate limited responses When an API request is rate limited, Highnote API returns a status code. If you exceed the API rate limit, the cost field is not returned in your API response. Instead, the Highnote API uses a field to show how long to wait before retrying. The following example represents a response of a rate-limited API request: ### When request is rate limited The following example represents a response of a request that is rate-limited: ```json { "data": {}, "errors": [ { "message": "Usage limit exceeded. More than x request points used in y seconds. See https://highnote.com/docs/developers/api/error-handling#rate-limit-errors for details on how to handle API rate limits." } ], "extensions": { "requestId": "4378192a-3529-928c-9894-5f815edd4f07", "rateLimit": { "asOf": "2024-03-15T18:29:36.090Z", "count": { "cost": 1, "remaining": 0, "limit": 200 }, "complexity": { "remaining": 0, "limit": 2500 }, "remaining": "0", "limit": 2500 } } } ``` ### When request is not rate limited The following example represents a response of a request that is not rate-limited: ```json { "data": {}, "errors": {}, "extensions": { "requestId": "4378192a-3529-928c-9894-5f815edd4f07", "rateLimit": { "asOf": "2024-03-15T18:29:36.090Z", "count": { "cost": 1, "remaining": 199, "limit": 200 }, "complexity": { "cost": 10, "remaining": 2490, "limit": 2500 }, "cost": "10", "remaining": "2490", "limit": 2500 } } } ``` ## Best practices Refer to the following best practices to avoid hitting rate limits: - **Avoid polling:** Avoid polling the API for asynchronous updates by registering a webhook target to receive notification events. See Notifications. - **Use pagination:** When querying for listed data, use pagination to limit the number of requested items. - **Implement exponential backoff:** Implement retries with exponential backoff when an API request receives a response. For help, see: - Implementing Exponential Backoff - Apollo Client Retry Link - Exponential Backoff npm package --- URL: https://docs.highnote.com/docs/developers/api/request-complexity Title: Request Complexity Section: Developers Description: Calculate the computational cost of your GraphQL queries and optimize them to stay within complexity limits. ## Overview Request complexity refers to the computational cost and resource usage of executing a GraphQL query. ecause GraphQL lets clients request deeply nested and complex data structures in a single query, complexity must be managed to avoid overloading the server. ## Scoring complexity Common factors that increase complexity are operation, depth, and type. For example: - **Operation**: Mutations are often more complex than queries due to data writes and consistency requirements. - **Depth**: Deeply nested queries are more complex than shallow ones. - **Type**: Objects with multiple fields or relationships to other objects are more complex than primitive types such as scalars. Highnote manages the complexity of its API with complexity scoring, rate limiting, and pagination. ### Type and pattern costs Query operation types are scored as follows: - **Query**: Query cost is based on the types and fields requested. - **Mutation**: Mutations have a base cost of 10, plus any additional costs based on the types and fields requested. Other types and patterns are scored as follows: | Type / Pattern | Description | Cost | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- | | Object | Type with a defined set of fields (e.g., a User with id, name, email fields) | 1 point | | Interface | Template type that defines required fields other types must implement. Uses maximum type complexity (where only the _most expensive_ type requested is counted). | 1 point | | Union | Type that can be one of several object types. Uses maximum type complexity. | 1 point | | Scalar | Primitive type like String, Int, Boolean. Cost is accounted for in the object it belongs to. | 0 points | | Enum | User-defined type with a fixed set of allowed values. Cost is accounted for in the object it belongs to. | 0 points | | Connection | Pattern for pagination, typically implemented as an object type with edges and nodes. Defines how different types of data are connected and how they can be queried. | 2 points + number of objects requested | The fields and are intrinsic to the connection pattern and have no separate complexity cost. ### Simple example The following example demonstrates a simple request complexity calculation: ```graphql query ListCardProducts { cardProducts(first: 10) { # Connection 2 + 10 items pageInfo { # PageInfo object 0 point startCursor endCursor hasNextPage hasPreviousPage } edges { # Edges field - 0 point cursor # String - 0 point node { # Node field in connection - 0 point id # String - 0 point name # String - 0 point vertical # String - 0 point features { # Object - 1 point enabled # Boolean - 0 point } } } } } ``` ```html 2 + 10(1) ``` ### Nested example The following example demonstrates a more complex request complexity calculation that includes nested connection objects to illustrate how pagination cost can multiply: ```graphql query LookupStatement($id: ID!) { node(id: $id) { # Object 1 point ... on SecuredDepositCommercialCreditCardFinancialAccountStatement { statementEntries(first: 20) { # Connection 2 + 20 items edges { # Edges field - 0 point node { # Node field in connection - 0 point ledgerEntry { # Object - 1 point __typename # String - 0 id # ID - 0 point ledger { # Object - 1 point ledgerEntries(first: 20) { # Connection 2 + 20 items edges { # Edges field - 0 point node { # Node field in connection - 0 point amount { # 1 Object - 1 point value # 0 UnsignedInt - 0 point } } } } } } } } } } } } ``` ```html 1 + 2 + 20(1 + 1 + 2 + 20(1)) = 483 ``` ## Testing request costs Every Highnote GraphQL API response includes the request cost under the _extensions_ field. We recommend that you test the cost of your queries in the API Explorer. The following example represents a request cost response in an API request that is not rate-limited: ```json { "data": {}, "errors": {}, "extensions": { "rateLimit": { "limit": 100, "cost": 5, "remaining": 95 } } } ``` --- URL: https://docs.highnote.com/docs/developers/api/rotating-keys Title: Rotating API Keys Section: Developers Description: Rotate your API keys to maintain security. Create new keys, update your applications, and revoke old keys through the Highnote Dashboard. ## Before you start We strongly recommend rotating your Highnote API keys every _90 days_. The practice of rotating API keys helps mitigate risk associated with unauthorized access and misuse of sensitive data or services. ## Rotate your API keys To rotate your API keys, create new keys and revoke old ones: 1. Login to the Highnote dashboard. 1. Click **Developers** from the left-hand navigation menu. 1. On the **API Keys** tab, click **Create API Key** and follow the prompts. Create multiple API keys if needed. 1. Copy and store your new API key in a secure place. 1. Update your applications to use your new API key. 1. Delete old API keys by clicking **Revoke API Key** in the Highnote dashboard. --- URL: https://docs.highnote.com/docs/developers/api/search-hql Title: Highnote Query Language Section: Developers Description: Search for accounts, cards, transactions, and other objects using Highnote Query Language (HQL). ## Overview The Highnote Query Language (HQL) provides programmatic search capabilities across Highnote entities using SQL-like syntax through the GraphQL API. Specifically, HQL enables complex searches that would normally require multiple standard GraphQL requests. Money values are in the currency's minor units — means **$5.00**, not $500. See HQL Conventions. | Search Type | Example | | :------------------------- | :-------------------------------------------------------------------------------------------------------------- | | **Cross-field conditions** | | | **List operations** | | | **Custom metadata** | | | **Logical grouping** | | The API processes HQL queries through several search contexts: Financial Accounts, Payment Transactions (acquiring), Universal Transactions (issuing), and Transaction Batches and their entries (acquiring), each exposing context-specific searchable fields alongside common attributes. The field tables below cover the first three; for transaction batches and batch entries, see Transaction Batching. HQL operates through the field within GraphQL inputs: ```graphql { filterBy: { searchQueryLanguage: { query: "transactionAmount > USD 100 AND accountStatus = 'ACTIVE'", version: "VERSION_1" } } } ``` ## Limitations HQL is a standalone filter system that uses the field within inputs. If provided with other standard filters, HQL takes precedence and the other filters are ignored. **Minimum API version**: The minimum supported Search API version is . **Rate limits**: See API Rate Limiting for details. **Search latency**: Highnote’s Search API has a latency period of up to two minutes. ## HQL Conventions The Highnote Query Language uses the following conventions: - A **term** is a keyword used to search on attributes related to an entity. - An **expression** is . For example, . - A **value is unquoted** when it is a bare number, a money value, or an identifier-shaped token of letters, digits, and underscores. A Highnote identifier is identifier-shaped, so needs no quotes. - A **value must be wrapped in single quotes** when it contains anything else, such as a space, a comma, a parenthesis, or a literal apostrophe. For example, is quoted because of the space. Quoting a value that does not require it is always safe. - A **literal apostrophe inside a quoted value** must be escaped, either with a backslash or by doubling it. and are both valid and equivalent. An unescaped apostrophe makes the query invalid. - A **money value** is a currency code followed by an amount, as in . Quoting it () is also accepted. - ** and carry no precedence.** Conditions combine strictly left to right, so evaluates as . Group explicitly with parentheses when you mean anything else. The amount in a money value is in the currency's **minor** units, never its major ones. matches transactions above **$5.00**, not $500. - The scale follows the currency, so it is not always cents: is ¥300, and is 0.300 BHD. - Write the amount as a whole number. A decimal such as is rejected as an invalid money filter. - A comparison with , , , , , or also scopes results to the currency you name, so returns no EUR transactions. ## Build query strings safely An HQL query is parsed server-side against a defined grammar, and the string you send is normalized before it is parsed: non-ASCII quote characters — , , and — are converted to ASCII . That conversion happens **after** any check your own code ran, so a value carrying no ASCII quote at the moment you inspect it can still become a live string delimiter by the time the query is parsed. Because of that, **validate every interpolated value against a positive allowlist** — the exact keyspace you expect, such as a known identifier prefix followed by hexadecimal, or one member of a fixed set of status names — and reject everything else. Do not rely on escaping quote characters, and do not rely on stripping them: the character that ends up breaking out of a quoted string need not be present when you look for it. This matters most where a filter is the only thing separating one of your customers from another. A query is always confined to your own organization — every request is scoped from the authenticated principal, and a query string cannot widen that — but within your organization the filter you build is the boundary. Treat any identifier that reaches you from a customer, a URL, or a form field as untrusted, and prefer an identifier your own backend resolved over one the caller supplied. ## HQL Grammar The following ANTLR 4 grammar is the authoritative definition of the string you pass to . It is published so that client libraries, query builders, and code generation tools can produce valid HQL directly rather than inferring the syntax from examples. The grammar defines syntax only. It does not describe which fields a search context accepts, nor which operators a given field allows — a query can parse cleanly and still be rejected. See Operators for the operators that are restricted to specific fields, HQL Conventions for when a value needs quoting, and the field table in each search section for the fields that section supports. ```text grammar SearchQuery; // Parser Rules searchQuery : query? EOF ; query : expression ( (AND | OR) expression )* ; expression : term | '(' query ')' ; term : NOT? comparison ; comparison : IDENTIFIER (EQ | NEQ | GT | GTE | LT | LTE | PREFIX_EQ | FUZZY_EQ | LIKE) value | IDENTIFIER IN '(' valueList ')' | IDENTIFIER NOT IN '(' valueList ')'; valueList : value (',' value)* ; value : STRING | NUMBER | money | IDENTIFIER | ALPHANUMERIC ; money : IDENTIFIER NUMBER ; // Lexer Rules AND : 'AND' ; OR : 'OR' ; NOT : 'NOT' ; IN : 'IN' ; PREFIX_EQ : '^=' ; FUZZY_EQ : '~=' ; LIKE : 'LIKE' ; EQ : '=' ; NEQ : '!=' ; GT : '>' ; GTE : '>=' ; LT : '<' ; LTE : '<=' ; IDENTIFIER : [a-zA-Z_][a-zA-Z0-9_]* ; NUMBER : [0-9]+ ('.' [0-9]+)? ; ALPHANUMERIC : [a-zA-Z0-9_]+; STRING : '\'' ( '\\\'' | '\'\'' | ~'\'' )* '\'' ; WS : [ \t\r\n]+ -> skip ; ``` An empty query is legal and matches everything. The anchor on means the parser must consume the whole input: a malformed query is rejected outright rather than silently evaluated as the longest valid prefix. ## Operators | Operator | Description | Example | | :------- | :------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | | Equal to | | | | Not Equal to | | | | Greater Than | | | | Greater Than or Equal To | | | | Less Than | | | | Less Than or Equal To | | | | Prefix match. Restricted to fields with fuzzy search enabled — see below | | | | Fuzzy match, tolerant of edit distance. Restricted to fields with fuzzy search enabled — see below | | | | Wildcard match against the full field value, using and . Restricted to fields with fuzzy search enabled — see below | | | | Returns entities that match any value in list | | | | Negates a single comparison. Distinct from | | | | Returns entities that do not match any value in list | | | | Both sides of expression are valid | | | | Either side of expression is valid | | | | Groups search terms together | | ### Fuzzy, prefix, and wildcard search , , and are enabled on specific text fields only. Every other field rejects all three with an validation error, even though the query parses. Today they are enabled on three Universal Transaction Search fields: , , and . No field in Account Search, Acquiring Search, or the transaction-batch contexts described in Transaction Batching accepts them. All three operators are case-insensitive: and match the same values. is a wildcard match against the **full** field value, not a substring search. matches only the exact value . Add the wildcards yourself to match a substring: - — the value contains - — the value starts with Use to match exactly one character. ## Account Search An account search applies to [](/docs/api-reference/object#FinancialAccount) attributes. Returns [](/docs/api-reference/object#FinancialAccount). | Field | Description | Example | | :-------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------ | | id (or accountId) | [](/docs/api-reference/object#FinancialAccount) | | | productId | The Card Product associated to the Financial Account | | | activeFeatures | The list of active features. Valid enum values: FinancialAccountFeatureType | | | primaryAccountHolder | Primary account holder of the Financial Account | | | primaryAccountAccountHolder | Account Id of the primary user | | | primaryAccountHolderAccount | If authorized user, Account Id of the primary user account; else Account Id of the primary user | | | customField | Custom fields linked to Financial Account. Must be an exact match. | | | accountStatus | Status of a Financial Account. Valid enum values: FinancialAccountStatus | | | application | Application used to issue the Financial Account | | | program | The Program associated with the Financial Account | | | createdAt | Datetime (ISO 8601) the Financial Account was created | | ## Acquiring Search An acquiring search applies to attributes of the following: [](/docs/api-reference/interface#PaymentTransaction), [](/docs/api-reference/interface#PaymentTransactionLifecycleStep), and [](/docs/api-reference/interface#PaymentTransactionEvent). Returns [](/docs/api-reference/interface#PaymentTransaction). | Field | Description | Example | | :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------- | | id | Identifier of the [](/docs/api-reference/interface#PaymentTransaction) | | | transactionId | The parent transaction id, if applicable | | | transactionAmount | Amount of the transaction | | | accountId | Financial Accounts linked to the Payment Transaction and corresponding Steps and Events | | | transactionSearchType | Narrows down the search to either a or . | | | type | Narrows down the search to a specific transaction type, using the same values as the Universal Transaction Search field. Only acquiring transaction types match in this context. | | | transactionSearchStatus | A normalized value that represents whether a transaction is , , or . Dependent on the lifecycle of the transaction. | | | cardholderEmail | Email associated with the cardholder of a Payment Transaction. Must be an exact match. | | | cardholderName | Name associated with the cardholder of a Payment Transaction. Must be an exact match. | | | authorizationIdentifier | ID of the authorization response code provided by the processor for this PaymentTransaction on a successful authorization | | | addressResponseCode | Address Verification Service result for the street address. Valid values are , , , , and . | | | postalResponseCode | Address Verification Service result for the postal code. Valid values are , , , , , , and . | | | last4 | Last 4 digits of the card used for the Payment Transaction | | | orderId | Originating [](/docs/api-reference/object#PaymentOrder) that this transaction was initiated from | | | productId | The Card Product that is associated with a transaction. Multiple Card Products may be associated with a transaction. | | | contractId | The used to make the payment | | | transferAccountId | Financial Accounts on the transfers created when the transaction's Payment Instructions resolve | | | transferId | Unique ID of the transfer | | | disburseToId | The ID for the transaction | | | actionDate | A normalized timestamp field that searches on the last updated date for a transaction. For example, within the lifecycle of a Transaction, searches on the latest createdAt of a TransactionEvent. | | | completedAt | A normalized timestamp field that searches on when a transaction was completed, if applicable. For example, if a Transaction has gone through the entire payment lifecycle, completedAt can be used to search when the final TransactionEvent occurred. | | | createdAt | The date and time, in ISO 8601 format, this object was created. | | | updatedAt | The date and time, in ISO 8601 format, this object was updated. | | ## Universal Transaction Search A universal transaction search applies to normalized values related to the transaction types listed under below, as well as attributes specific to individual transaction types. UTS searches span both issuing and acquiring transactions. Universal Transaction Search does not cover every Issuing Transaction Type. Fee transfers, credit card transfers, reward point transfers, and crypto funding transfers are not searchable from this context. Returns [](/docs/api-reference/object#TransactionSearchResult). | Field | Description | Applies To | | :----------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------- | | id | Identifier of the transaction | All | | transactionSearchStatus | A normalized value across all transaction types that represents whether a transaction is , , or . Dependent on the lifecycle of each transaction type. | All | | transactionAmount | A normalized value that searches across all transaction types' values.. Ex: | All | | transactionAmountCurrencyCode | Currency that the transaction was initiated with | All | | transactionId | The parent transaction id, if applicable | All | | accountHolderId | The AccountHolder that may be associated with a transaction. Multiple AccountHolders may be associated with a transaction. | All | | transactionSearchType | Narrows down the search to either a or . | All | | type | Narrows down the search to a specific transaction type. Allowed values are , , , , , , , , , , , | All | | accountId | A FinancialAccount that may be associated with a transaction. Multiple FinancialAccounts can be associated with 1 transaction. | All | | createdAt | When the transaction was created | All | | actionDate | A normalized timestamp field that searches on the last updated date for a transaction. For example, within the lifecycle of a Transaction, searches on the latest createdAt of a TransactionEvent | All | | completedAt | A normalized timestamp field that searches on when a transaction was completed, if applicable. For example, if a Transaction has gone through the entire payment lifecycle, completedAt can be used to search when the final TransactionEvent occurred. | All | | productId | The CardProduct that is associated with a transaction. Multiple CardProducts may be associated with a transaction | All | | last4 | The last 4 digits of the card used in the transaction | TransactionEvent types | | cardProcessingType | The method or channel used to process the transaction. Valid enum values: cardProcessingType | TransactionEvent types | | cardAcceptorIdentificationCode | Highnote assigned Merchant ID | TransactionEvent types | | merchantName | Name of the merchant | TransactionEvent types | | institutionName | Name of the institution | TransactionEvent types | | merchantCategoryCode or mcc | Human friendly enums representing 4-digit ISO-18245 merchant category codes. Valid enum values: MerchantCategory | TransactionEvent types | | cardAcceptorLocation | Geographic/address info about where the transaction took place | TransactionEvent types | | transactionCountryCode | Country code where the transaction took place | TransactionEvent types | | postedAmount | Final settled transaction amount charged to the cardholder's account | TransactionEvent types | ## HQL Examples Use the following mutation to list card product accounts, and then search by date. ```graphql query ListCardProductAccounts( $id: ID! $first: Int $after: String $filterBy: AccountHolderFinancialAccountsFilterInput ) { node(id: $id) { id __typename ... on Organization { accounts(first: $first, after: $after, filterBy: $filterBy) { __typename pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { node { id name createdAt updatedAt accountStatus accountAttributes cardProduct { id } cardProductApplication { ... on AccountHolderCardProductApplication { accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id name { familyName givenName middleName suffix title } } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id businessProfile { name { legalBusinessName doingBusinessAsName } } } } } } } owner { ... on USPersonAccountHolder { id name { familyName givenName middleName suffix title } } ... on USBusinessAccountHolder { id businessProfile { name { legalBusinessName doingBusinessAsName } } } ... on Organization { id profile { displayName } } } ledgers(ledgerNames: AVAILABLE_CASH) { id name normalBalance creditBalance { value currencyCode decimalPlaces } debitBalance { value currencyCode decimalPlaces } } features { enabled ... on SecuredCreditPaymentCardFinancialAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on FleetCardAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on CommercialCreditPayInFullCardAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on CreditCardAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on OnDemandFundingFinancialAccountFeature { sourceFinancialAccount { id } } } } } } } ... on CardProduct { accounts(first: $first, after: $after, filterBy: $filterBy) { __typename pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { node { id name createdAt updatedAt accountStatus accountAttributes cardProductApplication { ... on AccountHolderCardProductApplication { accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id name { familyName givenName middleName suffix title } } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id businessProfile { name { legalBusinessName doingBusinessAsName } } } } } } } owner { ... on USPersonAccountHolder { id name { familyName givenName middleName suffix title } } ... on USBusinessAccountHolder { id businessProfile { name { legalBusinessName doingBusinessAsName } } } ... on Organization { id profile { displayName } } } ledgers(ledgerNames: AVAILABLE_CASH) { id name normalBalance creditBalance { value currencyCode decimalPlaces } debitBalance { value currencyCode decimalPlaces } } features { enabled ... on SecuredCreditPaymentCardFinancialAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on FleetCardAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on CommercialCreditPayInFullCardAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on CreditCardAccountFeature { creditLimit { currencyCode decimalPlaces value } } ... on OnDemandFundingFinancialAccountFeature { sourceFinancialAccount { id } } } } } } } } } ``` --- URL: https://docs.highnote.com/docs/developers/api/api-searching-the-api Title: Searching the API Section: Developers Description: Search and filter API objects using date, number, string, and enum filters. Combine multiple filters and understand search latency and data retention limits. ## Before you start Highnote launched the Highnote Query Language to improve your ability to search across our API. All Highnote API entities use the same search and sorting conventions. You can use the following examples to build your queries when filtering for matches. Results will always return as a paginated list you can traverse using cursors. ## Search latency Searching across multiple years of data may introduce minimal additional latency, though this impact is typically imperceptible in normal usage. Highnote's Search API experiences a synchronization delay of up to 2 minutes for newly created objects. When you create a new object (such as an account holder), it's immediately stored in the main database but takes up to 2 minutes to synchronize with the search database. During this period, the new object won't appear in search results. This process is illustrated below: Highnote's Search API experiences a synchronization delay of up to 2 minutes for newly created objects. When you create a new object (such as an account holder), it's immediately stored in the main database but takes up to 2 minutes to synchronize with the search database. During this period, the new object won't appear in search results. This process is illustrated below: ## Data retention Highnote maintains the following data retention periods through the standard API: - **Issuing transactions:** 4 years - **Acquiring transactions:** 2 years You can fetch issuing and acquiring data beyond the retention period from Highnote Data Share. ## Filtering basics Different fields can filter every entity in our graph. However, all fields of the same type follow similar conventions. ## Date filters To filter by date range, use the following filters: - - - - - - ## Number filters To filter by numbers, use the following filters: - - - - - - ## String filters To filter with common string matching, use the following filters: - - - - - ## List filters You can filter multiple values by choosing what values to include or exclude from the results. In the following example, the request is filtered to include and : ## Enum filters You can filter enums by including the enum values you wish to include, exclude, or match exactly. In the following example, the request is filtered to equal : ## Combine filters You can combine multiple filters to construct more advanced queries. In the following example, an enum, number, and date filter are used: ## Application search You can use the Highnote API to search Account Holder applications based on , , and search fields. | Type | Field | Filter | | :------------------------------------ | :---------- | :----- | | | | Enum | | | | Date | | | | Date | The following example query would return the first 20 account holder applications with an status: ### GraphQL: SearchPersonAccountHolders Query: query SearchPersonAccountHolders( $first: Int $filters: PersonAccountHolderFilterInput ) { personAccountHolders(first: $first, filterBy: $filters) { pageInfo { hasNextPage } edges { cursor node { id } } } } Variables: { "first": 20, "filters": { "dateOfBirth": { "greaterThan": "2021-06-01T00:00:00Z", "lessThan": "2021-07-01T00:00:00Z" } } } Expected Result: { "data": { "personAccountHolders": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "" } } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SearchTransactionEvents Query: query SearchTransactionEvents( $id: ID! $first: Int $filters: CardProductTransactionEventsFilterInput ) { node(id: $id) { ... on CardProduct { transactionEvents(first: $first, filterBy: $filters) { pageInfo { hasNextPage } edges { cursor node { ... on AuthorizationEvent { id } } } } } } } Variables: { "id": "", "first": 20, "filters": { "approvedAmount": { "currencyCode": "USD", "lessThan": 10000000 } } } Expected Result: { "data": { "node": { "transactionEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: SearchPersonAccountHolders Query: query SearchPersonAccountHolders( $first: Int $filters: PersonAccountHolderFilterInput ) { personAccountHolders(first: $first, filterBy: $filters) { pageInfo { hasNextPage } edges { cursor node { id email } } } } Variables: { "first": 20, "filters": { "email": { "endsWith": "com" } } } Expected Result: { "data": { "personAccountHolders": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "", "email": "foo@example.com" } } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SearchTransactionEvents Query: query SearchTransactionEvents( $id: ID! $first: Int $filters: CardProductTransactionEventsFilterInput ) { node(id: $id) { ... on CardProduct { transactionEvents(first: $first, filterBy: $filters) { pageInfo { hasNextPage } edges { cursor node { ... on AuthorizationEvent { id } ... on ClearingEvent { id } } } } } } } Variables: { "id": "", "first": 20, "filters": { "eventType": { "includes": [ "AUTHORIZATION_EVENT", "CLEARING_EVENT" ] } } } Expected Result: { "data": { "node": { "transactionEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "" } }, { "cursor": "some-cursor", "node": { "id": "" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: SearchTransactionEvents Query: query SearchTransactionEvents( $id: ID! $first: Int $filters: CardProductTransactionEventsFilterInput ) { node(id: $id) { ... on CardProduct { transactionEvents(first: $first, filterBy: $filters) { pageInfo { hasNextPage } edges { cursor node { __typename } } } } } } Variables: { "id": "", "first": 20, "filters": { "eventType": { "equals": "AUTHORIZATION_EVENT" } } } Expected Result: { "data": { "node": { "transactionEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "AuthorizationEvent" } }, { "cursor": "", "node": { "__typename": "AuthorizationEvent" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: SearchTransactionEvents Query: query SearchTransactionEvents( $id: ID! $first: Int $filters: CardProductTransactionEventsFilterInput ) { node(id: $id) { ... on CardProduct { transactionEvents(first: $first, filterBy: $filters) { pageInfo { hasNextPage } edges { cursor node { ... on AuthorizationEvent { __typename } ... on ClearingEvent { __typename } } } } } } } Variables: { "id": "", "first": 20, "filters": { "eventType": { "includes": [ "AUTHORIZATION_EVENT", "CLEARING_EVENT" ] } } } Expected Result: { "data": { "node": { "transactionEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "" } }, { "cursor": "some-cursor", "node": { "id": "" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: GetCardProductWithApplications Query: query GetCardProductWithApplications( $id: ID! $searchFilter: CardProductApplicationFilterInput ) { node(id: $id) { ... on CardProduct { __typename id name searchCardProductApplications(first: 20, filterBy: $searchFilter) { pageInfo { hasNextPage } edges { ... on AccountHolderCardProductApplicationEdge { cursor node { __typename ... on AccountHolderCardProductApplication { id applicationState { status } accountHolderSnapshot { __typename ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id billingAddress { streetAddress } } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { businessProfile { name { legalBusinessName doingBusinessAsName } businessType } } } } } createdAt updatedAt } } } } } } } Variables: { "id": "", "searchFilter": { "id": { "equals": "" } } } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "name": "Account Fee", "searchCardProductApplications": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "IN_REVIEW" }, "accountHolderSnapshot": { "__typename": "USPersonAccountHolderSnapshot", "accountHolderCurrent": { "id": "", "billingAddress": { "streetAddress": "123 St.123" } } }, "createdAt": "2023-07-17T14:35:22.870Z", "updatedAt": "2023-07-17T14:35:26.984Z" } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "limit": 30030, "remaining": 29927, "cost": 103 } } } --- URL: https://docs.highnote.com/docs/developers/api/status-changes Title: API Status and Changes Section: Developers Description: Monitor the operational status of the Highnote platform and GraphQL API, subscribe to incident notifications, and track GraphQL schema changes programmatically. ## API and platform status Highnote provides transparency on the operational status of the platform and GraphQL API using the Highnote Status Page. You can subscribe to updates on the page and will be notified of any downtime. When an incident impacts the platform and GraphQL API, the Highnote team immediately begins investigating, assessing the impact, and communicating via the status page. Refer to the following details of each phase and the activities that occur in each phase: | Phase | Activities | | :------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Incident identification | When an incident has been identified, Highnote will create an incident in the incident tracking system and begin the investigation. | | Investigation and communication | The Highnote Incident Commander and incident response team work to investigate the issue, determine the scope, and identify a resolution. Based on the scope and severity, the Highnote status page is updated with partial or full outages. | | Resolution and communication | Once the resolution is identified and tested, the fix is deployed to production. The Highnote team will then communicate update(s) to you through the Highnote status page. | | Post mortem | After the incident management process has occurred, the Highnote incident response team walks through what happened, the resolution, and lessons learned for future improvements. | ## API changes When changes occur to the Highnote GraphQL API, the Highnote team reviews them to assess their impact and communicates with you proactively about the upcoming changes. The following table provides details of each phase for implementing API changes and the activities that occur in each phase. | Phase | Activities | | :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Planning | Once a change is determined, change planning begins. This includes documenting the change and its impact. | | Communication and documentation | The Highnote team ensures that the change's documentation is completed and that your usage is reviewed to determine its impact on you. Highnote creates communication that includes the change's description, the reason for the change, the potential impact on you of the change, and the timing. For more information on communication timelines, see Additive Changes and Breaking Changes. | | Implementation | Highnote ensures the execution of communication to you by Highnote Customer Support. This includes performing the change as documented. | | Retrospective | After the change is launched, Highnote holds a retrospective to reflect on the change management process. | ### Additive changes Additive changes refer to modifications of notifications or Highnote's API schema that introduce new features, functionality, or resources without altering or removing existing components. All additive changes are recorded in the API changelog. Direct communications for additive changes are only sent when an additive change results in a business or user experience change. ### Breaking changes Breaking changes refer to modifications to notifications and/or Highnote's API schema that alter existing behavior in a way that may cause existing client applications and integrations to break or malfunction. Highnote provides _90 days notice_ before releasing breaking changes. ### Monitoring changes To retrieve API schema changes programmatically, use the [](/docs/api-reference/query#schemaChangelogs) query. Each request returns a paginated list of recent schema changelogs; re-query on your own cadence to detect new entries. Each node corresponds to a specific deploy and groups changes under their schema root paths. Every change includes a (for example, ), a human-readable , and a level of , , or . Use with the argument to page forward while is . ### GraphQL: SchemaChangelogs Query: query SchemaChangelogs($first: Int! = 10, $after: String) { schemaChangelogs(first: $first, after: $after) { edges { node { id createdAt changes { rootPath changes { path changeType message criticality { level } } } } } pageInfo { hasNextPage endCursor } } } Variables: { "first": 10, "after": null } Expected Result: { "data": { "schemaChangelogs": { "edges": [ { "node": { "id": "", "createdAt": "2026-04-24T00:41:33.367Z", "changes": [ { "rootPath": "Mutation", "changes": [ { "path": "Mutation.simulateFlexibleCredentialAuthorization", "changeType": "FIELD_ADDED", "message": "Field 'simulateFlexibleCredentialAuthorization' was added to object type 'Mutation'", "criticality": { "level": "NON_BREAKING" } } ] }, { "rootPath": "SimulateFlexibleCredentialAuthorizationInput", "changes": [ { "path": "SimulateFlexibleCredentialAuthorizationInput", "changeType": "TYPE_ADDED", "message": "Type 'SimulateFlexibleCredentialAuthorizationInput' was added", "criticality": { "level": "NON_BREAKING" } } ] } ] } }, { "node": { "id": "", "createdAt": "2026-04-22T02:20:02.185Z", "changes": [ { "rootPath": "AccountHolder", "changes": [ { "path": "AccountHolder", "changeType": "UNION_MEMBER_ADDED", "message": "Member 'Business' was added to Union type 'AccountHolder'", "criticality": { "level": "DANGEROUS" } } ] } ] } }, { "node": { "id": "", "createdAt": "2026-04-17T21:18:59.056Z", "changes": [ { "rootPath": "PaymentTransactionResponseCodeProcessorResponseCode", "changes": [ { "path": "PaymentTransactionResponseCodeProcessorResponseCode.AUTHENTICATION_REQUIRED", "changeType": "ENUM_VALUE_ADDED", "message": "Enum value 'AUTHENTICATION_REQUIRED' was added to enum 'PaymentTransactionResponseCodeProcessorResponseCode'", "criticality": { "level": "DANGEROUS" } } ] } ] } } ], "pageInfo": { "hasNextPage": true, "endCursor": "" } } } } --- URL: https://docs.highnote.com/docs/developers/api/testing-the-api Title: Testing the API Section: Developers Description: Simulate real-time transactions and compliance scenarios in the Highnote Test environment before going live. ## Before you start The Highnote Test environment (or dashboard) replicates the full functionality of the Live environment, and lets you simulate real-time transactions and compliance scenarios. The Highnote docs include an API Explorer (standalone and embedded as snippets) that lets you run those simulations (in the dashboard) from the docs. This guide explains how to use the API Explorer. ## How It works The API Explorer can be used in two ways: - **Highnote API Explorer**: The Highnote API Explorer is an interface for executing API calls in your Test environment, perform queries, and search the Highnote API schema. You can write your own queries and mutations, or start from any example in these docs. - **Embedded code snippets**: Highnote embeds instances of the API Explorer directly in the Highnote documentation. These instances appear as testable code snippets. You can use the sample query supplied in each instance of the built-in tool to send requests to the Highnote API executed in your Test environment. ## Using embedded code snippets To use the embedded code snippets, you must sign in to your Highnote account. Once signed in, the embedded code snippets communicate with your Test environment. To execute an embedded code snippet in the Highnote docs: 1. Go to any page with a executable code snippet, e.g., Simulate External Wire Transfer. 1. Review the mutation in the **Operation** window of the embedded API Explorer. You do not need to change anything in this section for testing purposes. 1. Click **Variables** to open the input variables section. You can either use the pre-filled inputs or customize them for testing purposes. 1. Click **Run Query** to execute the request in your Test environment. The **Response** section populates the request response. 1. Open your Highnote dashboard and verify that the request was executed correctly in your Test environment. If you use the default values, "My Test Product" will be listed as a Commercial Prepaid product in your dashboard. ## Using the Highnote API Explorer To use the Highnote API Explorer, you must sign in to your Highnote dashboard. ### Running an operation To run an operation in the API Explorer: 1. Open the API Explorer and enter a query or mutation in the **Operation** window. To start from a worked example instead of writing one from scratch, use the executable snippet on any guide in these docs — for example Simulate External Wire Transfer — and copy it across. 1. Click **Variables** to open the input variables section, and supply any variables your operation takes. 1. Click **Run Query** or **Run Mutation** to execute the API call. The response populates in the **Response** field. You can also verify the API call was executed correctly in the dashboard. Use the **Docs** tab to browse the Highnote schema while you work, and the **History** tab to return to operations you have already run in this browser. ### Using autocomplete The API Explorer has an autocomplete feature that populates options based on what is in the Highnote schema. You can use the autocomplete feature to help you build your queries and mutations. To build a simple query with autocomplete: 1. Open the API Explorer. Clear the Query window if pre-populated. 1. Start typing and choose from the autocomplete box. 1. Append curly brackets, e.g., , then inside the brackets, type and select to create the query, . The query shows an error with a red wavy line under . 1. Hover over to reveal an error message above and a link to the schema docs just below. 1. While hovering, click the blue **reportUsage** hyperlink under to expose the schema docs on the right. 1. In the Schema window, click **ReportUsage!** to expose valid subfields and their descriptions. 1. Leaving the error as is, click **Run Query** in the Variables window. Two things happen: (a) The Query window populates with all valid subfields and the error clears. (b) The Results window returns a paginated list of reports with usage limits from your Test environment. #### Operation ```graphql query { reportUsage { reportType limit limitRemaining periodEnd } } ``` #### Response ```json { "data": { "reportUsage": [ { "reportType": "CARD_TRANSACTION_ACTIVITY", "limit": 3, "limitRemaining": 3, "periodEnd": "2025-01-15T05:00:00.000Z" }, { "reportType": "LEDGER_ENTRY", "limit": 3, "limitRemaining": 3, "periodEnd": "2025-01-15T05:00:00.000Z" }, ... ] }, "extensions": { "requestId": "8d8389b4-9755-98a6-b72b-dac56a3d84ec", "rateLimit": { "cost": 1, "limit": 100000, "remaining": 99999 } } } ``` --- URL: https://docs.highnote.com/docs/developers/api/using-the-api Title: Using the Highnote API Section: Developers Description: Make GraphQL requests to the Highnote API with proper authentication headers, request body structure, and response handling. ## Before you start This guide uses a simple cURL command to demonstrate how to query the Highnote API. Our command sends a query: ```shell curl --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic YOUR_BASE64_ENCODED_API_KEY' \ --data '{"query":"query {ping}"}' \ https://api.us.test.highnote.com/graphql ``` A slash represents a newline. Also, options can be represented in single-dash format (which you may see throughout the Highnote docs): ```shell curl -X POST \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic YOUR_BASE64_ENCODED_API_KEY' \ -d '{"query":"query {ping}"}' \ https://api.us.test.highnote.com/graphql ``` If successful, the ping query returns the following payload (with the info removed for simplicity): ```json { "data": { "ping": "pong" }, "extensions": { "requestId": "" } } ``` ## Headers The Highnote API requires the following headers: - - ### Content type The Highnote API accepts and returns , so you must pass a header with the value of : ```shell --header 'Content-Type: application/json' ``` ### Authorization The Highnote API uses Basic authentication which requires a base64-encoded API key (that is set as the username and does not require a password). To create a base64-encoded API key: 1. Create an API key in the Highnote Dashboard. This key is ASCII-encoded. See Creating and Managing API Keys. 2. Convert your API key from ASCII to base64: ```shell echo -n 'YOUR_ASCII_ENCODED_API_KEY' | base64 ``` 3. Pass your base64-encoded key with the header using the scheme: ```shell --header 'Authorization: Basic YOUR_BASE64_ENCODED_API_KEY' ``` Requests with missing or invalid credentials return a response code. ## Request body The Highnote API accepts requests with payloads. Requests include: | Field | Description | | :------------------------------- | :------------------------------------------------- | | or (required) | Defines the request operation | | (optional) | JSON payload passing dynamic data in a request | | Operation name (optional) | Name of the request, esp. useful when running many | In our query example, the request body is on line 4: ```shell --data '{"query":"query {ping}"}' ``` The following code snippet makes the same simple query. To run the query, sign in and expand "Variables", then watch the change with each call. ```graphql query { ping } ``` ```json { "data": { "ping": "pong" }, "extensions": { "requestId": "" } } ``` ### Operation name You can add an operation name (conventionally in PascalCase); for example, we can name our query : ```shell curl --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic YOUR_BASE64_ENCODED_API_KEY' \ --data '{"query":"query PingPong {ping}"}' \ https://api.us.test.highnote.com/graphql ``` ```graphql query PingPong { ping } ``` ```json { "data": { "ping": "pong" }, "extensions": { "requestId": "" } } ``` ### Variables The query doesn't take any arguments, so we cannot use it to test variables; but we _can_ test the query which does accept them. - Query that tries to get a node with id = (and which probably returns ): ```shell --data '{ "query": "query { node(id: \"node_123abc\") { id } }" }' ``` - Query with the operation name, ```shell --data '{ "query": "query GetNode { node(id: \"node_123abc\") { id } }" }' ``` - Query with a variable for the : ```shell curl --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic YOUR_BASE64_ENCODED_API_KEY' \ --data '{ "query": "query GetNode($id: ID!) { node(id: $id) { id } }", "variables": { "id": "node_123abc" } }' \ https://api.us.test.highnote.com/graphql ``` The following code snippets makes the same query: ```graphql query GetNode($id: ID!) { node(id: $id) { id } } ``` ```json { "id": "node_123abc" } ``` ```json { "data": { "node": null }, "extensions": { "requestId": "" } } ``` ### Multiple requests You can make multiple GraphQL requests in one by providing a single value with multiple calls as a string, for example, and : ```shell curl --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Basic YOUR_BASE64_ENCODED_API_KEY' \ --data '{ "query": "query { ping organizations { id profile { displayName } } }" }' \ https://api.us.test.highnote.com/graphql ``` ```graphql query { ping organizations { id profile { displayName } } } ``` ```json { "data": { "ping": "pong", "organizations": [ { "id": "", "profile": { "displayName": "ORG_NAME" } } ] }, "extensions": { "requestId": "" } } ``` ## Request URL The Highnote API has a unique URL for its Live and Test environments. Both environments use a endpoint but with a different subdomain. Our sample query has a request URL on line 5 for the Test environment. ```sh https://api.us.test.highnote.com/graphql ``` ```sh # Test Environment Request URL https://api.us.test.highnote.com/graphql # Live Environment Request URL https://api.us.highnote.com/graphql ``` ## Status codes Unlike REST, GraphQL often returns a status code even when there are errors. For error handling, the response includes an object with detailed information for troubleshooting. For mutations, request the type on the union type for specific details about the failure. See error handling for more information. There are a few non status codes that Highnote’s GraphQL API returns for the following cases: | Status Code | Scenario | | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | | GraphQL request was successful or validation/logic errors occurred. See error handling for more information. | | | GraphQL validation failed, usually because of malformed input or selection sets. In this case, the collection will be on the response body. | | | Credentials are invalid. | | | Something is wrong on the Highnote side. | ## Response bodies The response body of a query contains the data requested from the API endpoint. A Highnote API response body contains the following in format: | Field | Description | | :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Result of the given operation(s). Reflects the shape of your selection on the query. | | | Returns if the GraphQL engine fails to parse or validate the given request. | | | Map of data custom to a GraphQL implementation. The Highnote API includes a for debugging and info which we have been removing for simplicity. | You can format the response body in pretty by installing install jq and editing the URL in your cURL command as follows: References: - For info on the , see Troubleshooting with request ID. - For info on responses and formats, see the GraphQL spec. --- URL: https://docs.highnote.com/docs/developers/data-share/about-datashare Title: About Highnote Data Share Section: Developers Description: Query and analyze your Highnote issuing and acquiring data in Snowflake for reporting, analytics, and reconciliation. ## Overview This guide provides an overview of Highnote's secure data share product with Snowflake. With data share, you can easily access, query, and analyze your Highnote data in Snowflake. The Highnote Issuing Data Dictionary and Acquiring Data Dictionary describe data available for your queries. ## Reconciliation Highnote recommends Data Share as the path for reconciliation—comparing your own records against Highnote's ledger and transaction data. Data Share is built for the high-volume, repeated reads that reconciliation requires. - **Use Data Share, not the API, for bulk reconciliation.** Pulling ledger and transaction data through the API for reconciliation is request-intensive and subject to rate limiting. Reserve the API for real-time, transactional reads. - **Treat exported data as complete.** Once your data lands in Snowflake within the freshness window described below, it is suitable for reconciling against your own ledger. ## Data freshness Highnote's secure data share product makes most of your data available to query within 3 to 12 hours. Data freshness guidelines are as follows: - Typically, data is available within **3 hours** of its creation but can extend to **12 hours** after a schema change or BigQuery/Snowflake system issues. - Interchange detail information is mutable and may require up to **5 days** for a complete data load due to card network delays. - Once exported, data is retained in Snowflake for **5 years**. ## Amount representation All amounts in Highnote reports use a conversion rate of 1 to 1,000,000 units. For example, $1 = 1,000,000 units in a Highnote report. | Actual Value | Representation in Highnote Report | | :----------- | :-------------------------------- | | $1 | 1,000,000 | | $1,000 | 1,000,000,000 | | $1,000,000 | 1,000,000,000,000 | Signed amounts (fields ending with ) can have negative values. --- URL: https://docs.highnote.com/docs/developers/data-share/connect-to-snowflake Title: Connect to Snowflake Section: Developers Description: Set up a Snowflake connection with Highnote, accept data shares through Private Sharing, and start querying card and transaction data. ## Overview Highnote connects directly to your Snowflake account to support data share -- this section explains how. First, send Highnote your Snowflake account details, then accept the data share request from Highnote and connect. For help, contact support@highnote.com. ## Prerequisites - A Snowflake account. - An role. ## Connect your Highnote account 1. Log into your Snowflake account and get your **account number** and **region**. Send this info to Highnote. 2. Wait 2-3 business days to see the dataset privately shared to your Snowflake account. (Highnote will notify you once the share is completed.) 3. Log in to Snowflake with your role, navigate to **Data Products**, and select **Private Sharing**. 4. Click the **Get** arrow from the dataset we shared to accept the share. 5. Confirm you can view your Highnote data on the **Data and Databases** page. 6. Query Highnote data directly in Snowflake by going to **Home** → **Query data** → new worksheet. Refer to the Snowflake docs for detailed information: - Consuming Shared Data | Viewing available shares - Snowsight Quick Tour For sample query samples, see the Issuing and Acquiring query libraries. --- URL: https://docs.highnote.com/docs/developers/data-share/dictionary-acquiring Title: Acquiring Data Dictionary Section: Developers Description: Schema documentation and sample SQL queries for acquiring data in Snowflake, including payment transactions, orders, merchant disbursements, and disputes. ## Overview The Highnote Acquiring Data Dictionary provides all the data available for querying your payment transactions, items, and orders. The queries and objects below demonstrate how you can construct on-demand reports and generate metrics as needed. ## Data tables and fields This section lists the data tables and associated fields available to query your Highnote data. ### Table: code enum lookup The table is mutable and is updated periodically. The code tables reproduced on this page are snapshots, so decode through rather than treating any of them as exhaustive. Join this table to decode the enum-coded columns on payment transaction event into human-readable names. For an example, see Query: Decode transaction lifecycle codes. | Field name | Data type | Description | | :--------------- | :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | table_name | String | Name of the database table to which the enum values correspond. Helps identify which table the enum codes belong to. | | code_column_name | String | Name of the column within the referenced that uses the enum code. Provides a direct link between the enum value and its usage in a specific column of a table. | | code | String | Actual enum code used in the database. This is the value stored in the column specified by in the . | | code_enum | String | Descriptive name or label representing the enum code. This human-readable description provides more context for what the code represents. | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the code enum lookup record was created. Helps track when the enum was first introduced into the system. | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the code enum lookup record was last updated. Helps with auditing and understanding the history of changes to the enum values. | Filter to and to the column you want to decode (, , , , , or ), then match on : ```sql SELECT event."payment_transaction_event_id", event."event_type_code", elookup."code_enum" AS "event_type_name" FROM payment_transaction_event event LEFT JOIN code_enum_lookup elookup ON elookup."table_name" = 'payment_transaction_event' AND elookup."code_column_name" = 'event_type_code' AND elookup."code" = event."event_type_code" LIMIT 100; ``` Always filter on both and , not alone. The same code value can mean different things in different tables and columns. ### Table: payment transaction event The table is mutable and always displays the current state. Use the following fields to query your Payment Transactions. | Data Field | Data Type | Description | | :------------------------------------------ | :---------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | payment_transaction_event_id | String | Unique key identifying each event in a payment's lifecycle (e.g., authorization, capture, refund, payout) | | payment_id | String | Unique ID of the parent payment that ties together all lifecycle events from initial authorization through final settlement | | payment_transaction_step_id | String | Unique ID of a processing step that records the network response and outcome (e.g., approved, declined) at each stage | | payment_credential_id | String | Unique ID of the payment credential (card, token, or network token) used for the transaction | | brand | String | Card brand name | | step_type_code | String | Code of the transaction step type. Decode with [](#table-code-enum-lookup) or see Step type codes | | step_type_value | String | Name of the transaction step type (e.g., AUTHORIZATION, CAPTURE, REVERSAL, REFUND, VERIFICATION, DISPUTE). Populated by a separate mapping; see Step type codes | | event_type_code | String | Code of the payment transaction event type. Decode with [](#table-code-enum-lookup) or see Event type codes | | event_type_value | String | Name of the payment transaction event type. Populated by a separate mapping; see Event type codes | | refund_indicator | Boolean | Indicates whether this event is a refund or not | | merchant_settlement_account_id | String | Unique ID of the financial account where merchant funds are deposited after settlement | | merchant_id | String | Unique ID assigned by Highnote to identify the merchant entity | | merchant_acceptor_id | String | Card acceptor ID (ISO 8583) that identifies the merchant to the card network | | network_merchant_id | String | Unique ID assigned by the card network (Visa, Mastercard) for transaction routing | | acquirer_reference_number | String | Reference number sent to the card network to uniquely identify the capture for reconciliation | | processing_code | String | ISO 8583 processing code that indicates the transaction type and account type (e.g., purchase, refund, cash advance). Decode with [](#table-code-enum-lookup), or use | | processing_code_name | String | Human-readable name of the ISO 8583 processing code | | transaction_amount_signed | Integer | Amount of the transaction event requested by the cardholder, in the local currency of the acquirer or source location of the transaction (in minor units, signed) | | transaction_amount_currency_code | String | ISO 4217 code representing the currency of the transaction amount | | settlement_amount_signed | Integer | Amount of the transaction event in the settlement's currency (in minor units, signed). Usually the same as transaction_amount_signed | | settlement_amount_currency_code | String | ISO 4217 code representing the currency of the settlement amount | | interchange_fee_amount_signed | Integer | Fee charged by the card network (issuer) for processing the transaction (in minor units, signed) | | interchange_fee_amount_currency_code | String | ISO 4217 code representing the currency of the interchange fee amount | | platform_fee_amount_signed | Integer | Fee charged by the platform for this transaction, also called merchant discount fee (in minor units, signed) | | platform_fee_amount_currency_code | String | ISO 4217 code representing the currency of the platform fee amount | | dispute_chargeback_fee_amount_signed | Integer | Fee associated with a dispute or chargeback transaction (in minor units, signed) | | dispute_chargeback_fee_amount_currency_code | String | ISO 4217 code representing the currency of the dispute chargeback fee amount | | fee_amount_signed | Integer | Total fee amount for the transaction event (in minor units, signed) | | fee_amount_currency_code | String | ISO 4217 code representing the currency of the fee amount | | net_disbursement_amount_signed | Integer | Net disbursed amount to the merchant's settlement account (settlement_amount_signed + fee_amount_signed) | | dispute_amount_signed | Integer | Amount being disputed in a chargeback or dispute case (in minor units, signed) | | dispute_amount_currency_code | String | ISO 4217 code representing the currency of the disputed amount | | batch_job_id | String | Unique ID of the batch job that processed the payout and initiated fund transfers | | original_network_transaction_id | String | Network transaction ID of the original transaction | | processor_code | String | Code of the processor that handled the transaction. Decode with [](#table-code-enum-lookup) or see Processor codes | | network_response_code | String | Highnote's normalized response code. Decode with [](#table-code-enum-lookup) | | program_id | String | Unique ID of the acquiring program that groups products under a sponsor bank relationship | | program_name_snapshot | String | Snapshot of the acquiring program name at the time when the transaction event is processed | | product_id | String | Unique ID of the acquiring product that defines merchant pricing and processing rules | | product_name_snapshot | String | Snapshot of the acquiring product name at the time when the transaction event is processed | | payment_order_id | String | Unique ID of the payment order containing items and distribution instructions for the transaction | | payout_id | String | Unique ID of the payout batch that groups disbursements processed together | | receiving_account_id | String | Unique ID of the external bank account receiving the payout funds | | transfer_id | String | Identifies the internal transfer between Highnote-held accounts for an () event. Does not represent a transfer to the merchant's own bank account — see on () rows for that. | | disbursement_transaction_id | String | Unique ID linking this event to the merchant disbursement that transferred funds to the settlement account | | network_settlement_date | Date | Date that banks use to settle the card transaction amounts | | platform_date | Date | Date the platform recorded the transaction event, with a cutoff time of 5 PM Pacific Time (8 PM Eastern Time). Populated on every event, including events that never settle | | total_installment_amount_signed | Integer | Total amount for all installment payments combined (in minor units, signed) | | total_installment_amount_currency_code | String | ISO 4217 code representing the currency of the total installment amount | | number_of_installments | Integer | Total number of installment payments for the transaction (e.g., 4, 6, 12) | | installment_amount_signed | Integer | Amount of each individual installment payment (in minor units, signed) | | installment_amount_currency_code | String | ISO 4217 code representing the currency of the installment amount | | installment_payment_number | Integer | Current installment number in the sequence (e.g., 1, 2, 3...) | | installment_frequency_code | String | Code of the frequency of installment payments. Decode with [](#table-code-enum-lookup) | | first_installment_date | Date | Date of the first installment payment | | total_amount_funded_signed | Integer | Cumulative total amount funded so far across completed installments (in minor units, signed) | | total_amount_funded_currency_code | String | ISO 4217 code representing the currency of the total amount funded | | single_auth_installment_ind | Boolean | Indicates whether this is a single authorization with multiple captures (true) or multiple authorizations for each installment (false) | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the payment transaction event record was created | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the payment transaction event record was last updated | #### Event type codes marks the type of event within a payment's lifecycle. The numeric suffix carries no ordering — do not infer a lifecycle sequence from it, and do not assume a code means the same thing in another Highnote enum. Decode through [](#table-code-enum-lookup). The pre-existing column on the table is populated by a separate mapping maintained outside this enum. It can use a different label than for the same code, or leave the column empty for a code it doesn't cover. Treat as the canonical decode. In this dataset an row marks a capture cleared through the card network, and an row a disbursement of settled funds into the merchant's settlement account. Funds reaching the merchant's own bank account are marked by (), not . An internal transfer between Highnote-held accounts is marked by () — see [](#table-payment-transaction-event). Check for those rows rather than assuming a capture always clears. Settlement is a distinct lifecycle stage from clearing and has no of its own. If you need to act on settlement itself, use the transaction lifecycle notification events, which expose , and separately. That catalog describes as funds "disbursed to the merchant" — read that as the merchant's settlement account, the same distinction drawn above, not the merchant's own bank account. #### Step type codes marks the processing step (authorization, capture, reversal, and so on) within a payment's lifecycle. Decode it through [](#table-code-enum-lookup), which returns at least the values below for . The column on the table is populated by a separate mapping, like , and may disagree with . Treat as the canonical decode. | Code | Name | Notes | | :--- | :------------------------ | :------------------------------------- | | s000 | UNKNOWN | Reserved. Not expected in normal data. | | s001 | AUTHORIZATION | | | s002 | REVERSAL | | | s003 | CAPTURE | | | s004 | SETTLEMENT | Deprecated. | | s005 | DISBURSEMENT | Deprecated. | | s006 | REFUND | Refund step. | | s007 | VERIFICATION | | | s008 | DISPUTE | | | s009 | INCREMENTAL_AUTHORIZATION | | #### Processor codes marks which processor handled the transaction. Decode it through [](#table-code-enum-lookup), which returns at least the values below for . | Code | Name | Notes | | :--- | :------------- | :------------------------------------------------------------------------------------ | | p000 | UNKNOWN | | | p001 | VISA_DMS | Visa, dual message | | p002 | VISA_SMS | Visa, single message | | p003 | MASTERCARD_DMS | Mastercard, dual message | | p004 | MASTERCARD_SMS | Mastercard, single message | | p005 | MNGS | Mastercard NEX, formerly MNGS (Mastercard Network Gateway Services) | | p006 | PAYROC | | | p007 | HIGHNOTE | | | p008 | FISERV | | | p009 | AMEX | American Express | ### Table: payment instruction item The table is mutable and always displays the current state. Use the following fields to query your Payment Instructions. | Data Field | Data Type | Description | | :------------------------------- | :---------------------------------------- | :-------------------------------------------------------------------------------- | | payment_instruction_item_id | String | Unique key identifying a fund distribution instruction for a specific order item | | payment_instruction_group_id | String | Unique ID grouping related payment instructions that should be processed together | | payment_order_id | String | Unique ID of the payment order containing items and distribution instructions | | payment_order_item_list_id | String | Unique ID of a line item within the payment order (e.g., product, tax, shipping) | | catalog_item_id | String | Unique ID of the catalog item from the merchant's product catalog | | order_item_name | String | Name of the order item | | order_item_description | String | Description of the order item | | order_item_quantity | Decimal | Quantity of the order item | | order_item_amount_signed | Integer | Amount of the order item | | order_item_amount_currency_code | String | ISO 4217 code representing the currency of the order item amount | | order_total_amount_signed | Integer | Total amount of the order | | order_total_amount_currency_code | String | ISO 4217 code representing the currency of the order total amount | | instruction_percent | Decimal | Payment instruction percentage | | instruction_amount_signed | Integer | Payment instruction amount | | financial_account_id | String | Unique ID of the financial account receiving the disbursed funds | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the payment instruction item record was created | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the payment instruction item record was last updated | ### Table: payment order item The table is mutable and always displays the current state. Use the following fields to query your Payment Orders. | Data Field | Data Type | Description | | :------------------------------- | :---------------------------------------- | :----------------------------------------------------------------------------------------- | | payment_order_id | String | Unique ID of the parent payment order containing this item | | payment_order_item_list_id | String | Unique key identifying a line item within the payment order (e.g., product, tax, shipping) | | payment_instruction_group_id | String | Unique ID grouping related payment instructions for this item | | order_item_name | String | Name of the order item | | order_item_description | String | Description of the order item | | order_item_quantity | Decimal | Quantity of the order item | | order_item_amount_signed | Integer | Amount of the order item | | order_item_amount_currency_code | String | ISO 4217 code representing the currency of the order item amount | | order_total_amount_signed | Integer | Total amount of the order | | order_total_amount_currency_code | String | ISO 4217 code representing the currency of the order total amount | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the payment order item record was created | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the payment order item record was last updated | ### Table: merchant disbursement The table provides disbursement amounts for merchants by product and network settlement date. Use the following fields to reconcile merchant payouts and understand the breakdown of transaction amounts, fees, and adjustments. | Data Field | Data Type | Description | | :------------------------------------------ | :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | | disbursement_transaction_id | String | Unique key identifying a merchant payout record aggregated by product and network settlement date | | merchant_settlement_account_id | String | Unique ID of the financial account where merchant funds are deposited after settlement | | merchant_id | String | Unique ID assigned by Highnote to identify the merchant entity | | network_merchant_id | String | Unique ID assigned by the card network (Visa, Mastercard) for transaction routing | | product_id | String | Unique ID of the acquiring product that defines merchant pricing and processing rules | | product_name_snapshot | String | Name of the acquiring product at the time of disbursement | | program_id | String | Unique ID of the acquiring program that groups products under a sponsor bank relationship | | program_name_snapshot | String | Name of the program at the time of disbursement | | network_settlement_date | Date | Date on which the network settled the transactions | | gross_transaction_amount_signed | Integer | Gross transaction amount in minor units (signed: positive=CREDIT, negative=DEBIT) | | gross_transaction_amount_currency_code | String | ISO 4217 code representing the currency of the gross transaction amount | | interchange_fee_amount_signed | Integer | Interchange fee amount in minor units (signed: positive=CREDIT, negative=DEBIT) | | interchange_fee_amount_currency_code | String | ISO 4217 code representing the currency of the interchange fee amount | | platform_fee_amount_signed | Integer | Platform fee amount in minor units (signed: positive=CREDIT, negative=DEBIT) | | platform_fee_amount_currency_code | String | ISO 4217 code representing the currency of the platform fee amount | | dispute_amount_signed | Integer | Disputed transaction amount for the merchant and settlement date in minor units (signed) | | dispute_amount_currency_code | String | ISO 4217 code representing the currency of the dispute amount | | dispute_chargeback_fee_amount_signed | Integer | Chargeback fee amount for the merchant and settlement date in minor units (signed) | | dispute_chargeback_fee_amount_currency_code | String | ISO 4217 code representing the currency of the dispute chargeback fee amount | | carryover_amount_signed | Integer | Disbursement carryover amount in minor units when below minimum threshold (signed) | | carryover_amount_currency_code | String | ISO 4217 code representing the currency of the carryover amount | | precision_variance_amount_signed | Integer | Interchange precision adjustment amount for reconciliation in minor units (signed) | | precision_variance_amount_currency_code | String | ISO 4217 code representing the currency of the precision variance amount | | processor_code | String | Code of the processor that handled the disbursement. Decode with [](#table-code-enum-lookup) or see Processor codes | | sponsor_bank_id | String | Unique ID of the sponsor bank that facilitates the merchant's payment processing relationship | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the merchant disbursement record was created | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the merchant disbursement record was last updated | ### Table: merchant dispute The table is mutable and always displays the current state of each dispute, including the latest stage information. Use the following fields to query and track your merchant dispute cases through their lifecycle. | Data Field | Data Type | Description | | :------------------------------------- | :---------------------------------------- | :------------------------------------------------------------------------------------------------------ | | transaction_dispute_id | String | Unique key identifying a dispute case as it progresses through the chargeback lifecycle | | financial_account_id | String | Unique ID of the financial account associated with the disputed transaction | | merchant_id | String | Unique ID assigned by Highnote to identify the merchant entity | | merchant_acceptor_id | String | Sub-merchant ID within a payment facilitator model | | merchant_category_code | String | 4-digit ISO 18245 code classifying businesses by the type of goods or services they provide | | network_case_id | String | Case ID assigned by the card network (e.g., VROL for Visa, NGOM for Mastercard) to track the dispute | | payment_id | String | Unique ID of the parent payment that ties together all lifecycle events | | original_transaction_capture_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Event date of the original payment transaction step | | original_transaction_capture_amount | Integer | Transaction amount from original payment step in minor units | | network_code | String | Card scheme/network identifier (e.g., VISA, MASTERCARD, DISCOVER, AMEX) | | card_bin | String | Bank Identification Number - first 6-8 digits of the payment card | | card_last4 | String | Last 4 digits of the payment card number | | case_type_code | String | Type of case: CHARGEBACK or INQUIRY | | requested_amount_signed | Integer | Requested dispute amount in minor units (can be null for inquiries) | | requested_amount_currency_code | String | ISO 4217 code representing the currency of the requested amount | | settled_dispute_amount | Integer | Final settled dispute amount in minor units | | settled_dispute_amount_currency_code | String | ISO 4217 code representing the currency of the settled dispute amount | | dispute_category_code | String | Category of dispute: FRAUD, INVALID_AUTHORIZATION, PROCESSING_ERROR, CONSUMER_DISPUTE, or COMPLIANCE | | network_reason_code | String | Network-specific reason code for the chargeback (e.g., 4837 for Mastercard) | | network_reason_description | String | Human-readable description of the network reason code | | stage_code | String | Current stage of chargeback lifecycle: FIRST_CHARGEBACK, REPRESENTMENT, PRE_ARBITRATION, or ARBITRATION | | status_code | String | Current status of the dispute stage: INITIAL, IN_REVIEW, TIMED_OUT, or CLOSED | | stage_start_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the current dispute stage began | | stage_end_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the current dispute stage ended | | response_due_by_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | SLA target deadline for merchant/acquirer response to the current stage | | final_outcome_code | String | Final resolution outcome: WON, LOST, or CANCELLED | | closed_ind | Boolean | Indicator whether the dispute case is closed | | closed_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the dispute case was closed | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the merchant dispute record was created | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the merchant dispute record was last updated | ## Query library This acquiring query library includes a selection of common Highnote queries in the Snowflake dialect. We demonstrate how to generate the following types of reports: - Foundational reports - Transaction detail reports - Aggregated financial reports - Distribution reports The queries below include a defined date range which you can edit as necessary: ```sql SET (report_start, report_end) = ('2025-03-01', '2025-03-31'); ``` To see the full data set, remove the condition in each query, and remove the where present: ```sql BETWEEN $report_start AND $report_end ``` ## Foundational reports Foundational reports are essential for understanding the system's structure and configuration. These reports identify available accounts, ledger types, and their relationships, providing the foundational context needed to interpret all other financial reports. ### Query: Accounts and Ledgers The following query returns all accounts and associated ledgers. ```sql SELECT DISTINCT "financial_account_id", "financial_account_name_snapshot", "ledger_type_code", "ledger_type_code_enum" FROM ledger_entry ORDER BY "financial_account_id", "ledger_type_code"; ``` ### Query: Decode transaction lifecycle codes The following query decodes and on payment transaction events into human-readable names, using the table. See Table: code enum lookup for background. ```sql SELECT event."payment_transaction_event_id", event."payment_id", event."step_type_code", step_lookup."code_enum" AS "step_type_name", event."event_type_code", event_lookup."code_enum" AS "event_type_name", event."platform_date" FROM payment_transaction_event event LEFT JOIN code_enum_lookup step_lookup ON step_lookup."table_name" = 'payment_transaction_event' AND step_lookup."code_column_name" = 'step_type_code' AND step_lookup."code" = event."step_type_code" LEFT JOIN code_enum_lookup event_lookup ON event_lookup."table_name" = 'payment_transaction_event' AND event_lookup."code_column_name" = 'event_type_code' AND event_lookup."code" = event."event_type_code" WHERE event."platform_date" BETWEEN $report_start AND $report_end ORDER BY event."platform_date" DESC LIMIT 100; ``` ## Transaction detail reports Transaction detail reports monitor individual transactions and their impact on account balances over time. These reports show the complete flow of funds through the system, including running balances, transaction linkages, and reconciliation details necessary for auditing and troubleshooting. ### Query: Cash movement The following query returns the running balance of a settlement account, showing how each transaction affects the account balance over time. ```sql SELECT ledger."financial_account_name_snapshot" AS "Account", ledger."create_timestamp" AS "Ledger Datetime", ledger."update_sequence" AS "Update Sequence", ledger."financial_event_type" AS "Event Type", ledger."ledger_type_code" AS "Ledger Type Code", ledger."ledger_type_code_enum" AS "Ledger Type Value", ( ledger."balance_at_ledger_entry_signed" - IF(ledger."normal_balance_type" = 'DEBIT', -1, 1) * ledger."change_amount_signed" ) / 1000000 AS "Beginning balance", IF(ledger."normal_balance_type" = 'DEBIT', -1, 1) * ledger."change_amount_signed" / 1000000 AS "Amount", ledger."balance_at_ledger_entry_signed" / 1000000 AS "Ending balance" FROM ledger_entry ledger WHERE ledger."financial_account_id" = 'ac_' /* Settlement Account */ AND "ledger_type_code" = 'a003' ORDER BY "update_sequence"; ``` ### Query: Balance report The following query returns all transactions and running balances for a Product Funding account, linking each ledger entry to its corresponding payment event for reconciliation purposes. Disabled columns use block comments () rather than , since a comment directly above a live column silently drops that column if the query is ever reflowed onto one line; is reserved for standalone lines like section headers, where a collapse fails loudly instead. ```sql SELECT /* event."platform_date" AS "Event Date", */ /* event."event_type_code" AS "Event", */ ledger."transaction_id", ledger."create_timestamp" AS "Ledger Datetime", ledger."financial_account_name_snapshot" AS "Account Name", /* event."transfer_id" AS "Transaction Event Id", */ ledger."update_sequence" AS "Update Sequence", ( ledger."balance_at_ledger_entry_signed" - IF(ledger."normal_balance_type" = 'DEBIT', -1, 1) * ledger."change_amount_signed" ) / 1000000 AS "Beginning balance", IF(ledger."normal_balance_type" = 'DEBIT', -1, 1) * ledger."change_amount_signed" / 1000000 AS "Amount", ledger."financial_event_type" AS "financial_event_type", ledger."balance_at_ledger_entry_signed" / 1000000 AS "Ending balance" FROM ledger_entry ledger LEFT JOIN payment_transaction_event event ON event."transfer_id" = ledger."transaction_id" AND event."event_type_code" = 'e024' /* TRANSFER_COMPLETED */ WHERE ledger."ledger_type_code" = 'a003' AND ledger."financial_account_id" = 'ac_' /* Product Funding Account */ ORDER BY "update_sequence"; ``` ### Query: Product funding account The following query generates a parameterized monthly ledger report for a Product Funding Account, showing all transactions and balance changes for a specified date range in reverse chronological order. ```sql -- Set Desired Reporting Range SET (report_start, report_end) = ('2025-03-01', '2025-03-31'); -- Product Funding SELECT DISTINCT ledger."update_sequence" AS "Update Sequence", ledger."transaction_id" AS "Transaction ID", ledger."create_timestamp" AS "Ledger Datetime", ledger."financial_account_name_snapshot" AS "Account Name", ( ledger."balance_at_ledger_entry_signed" - IF(ledger."normal_balance_type" = 'DEBIT', -1, 1) * ledger."change_amount_signed" ) / 1000000 AS "Beginning Balance", IF(ledger."normal_balance_type" = 'DEBIT', -1, 1) * ledger."change_amount_signed" / 1000000 AS "Amount", ledger."financial_event_type" AS "Financial Event Type", ledger."balance_at_ledger_entry_signed" / 1000000 AS "Ending Balance" FROM ledger_entry ledger LEFT JOIN payment_transaction_event event ON event."transfer_id" = ledger."transaction_id" AND event."event_type_code" = 'e024' /* TRANSFER_COMPLETED */ WHERE ledger."ledger_type_code" = 'a003' AND ledger."financial_account_id" = 'ac_' /* Product Funding Account */ AND ledger."create_timestamp" BETWEEN $report_start AND $report_end ORDER BY "Update Sequence" DESC; ``` ## Aggregated financial reports Aggregated reports consolidate transaction data into meaningful business metrics. These reports provide executive-level insights into settlement volumes, payout amounts, and platform fees across different time periods and payment brands. ### Query: Monthly aggregated invoice The following query generates a monthly settlement report for a defined date range, summarizing completed payouts by payment brand with counts, gross amounts, merchant fees, and net settlement totals. ```sql SELECT "brand" AS "Brand", COUNT(DISTINCT "payment_transaction_event_id") AS "Settled Sales Count", SUM("transaction_amount_signed") / 1000000 AS "Total Gross Settled Amount", SUM("platform_fee_amount_signed") / 1000000 AS "Merchant Discount Fee", SUM("net_disbursement_amount_signed") / 1000000 AS "Total Net Settled Amount" FROM payment_transaction_event WHERE "event_type_code" = 'e022' /* PAYOUT_COMPLETED */ AND "platform_date" >= '2025-02-01' AND "platform_date" < '2025-03-01' GROUP BY ALL ORDER BY 1; ``` ### Query: Monthly payout The following query summarizes daily payout batches for a defined date range, showing the number of transactions and total amount disbursed in each payout run. ```sql SELECT "platform_date" AS "Date", "payout_id" AS "Payout Id", COUNT(DISTINCT "payment_transaction_event_id") AS "Settled Sales Count", SUM("net_disbursement_amount_signed") / 1000000 AS "Payout Amount" FROM payment_transaction_event WHERE "event_type_code" = 'e022' /* PAYOUT_COMPLETED */ AND "platform_date" >= '2025-02-01' AND "platform_date" < '2025-03-01' GROUP BY ALL ORDER BY 1, 2; ``` ### Query: Monthly aggregated fees The following query calculates the total platform fees earned from all completed payouts during a defined date range. ```sql SELECT SUM("platform_fee_amount_signed") / 1000000 AS "Fee" FROM payment_transaction_event WHERE "event_type_code" = 'e022' /* PAYOUT_COMPLETED */ AND "platform_date" >= '2025-02-01' AND "platform_date" < '2025-03-01'; ``` ## Distribution reports Distribution reports reveal how the payment system operates behind the scenes. These reports show payment routing rules, fund distribution logic, and product-level performance metrics that help optimize payment operations and understand revenue allocation. ### Query: Distribution payment detail The following query retrieves payment distribution instructions for a defined date range, showing how order amounts are split across different financial accounts based on percentage-based routing rules. ```sql SELECT "create_timestamp" AS "Create Timestamp", "payment_order_id" AS "Payment Order Id", "order_item_name" AS "Item Name", "order_item_quantity" AS "Order Quantity", ROUND("order_item_amount_signed" / 1000000, 6) AS "Order Amount", "instruction_percent" AS "Instruction %", ROUND("instruction_amount_signed" / 1000000, 6) AS "Instruction Amount", "financial_account_id" AS "Financial Account Id" FROM payment_instruction_item WHERE "create_timestamp" >= '2025-02-01' AND "create_timestamp" < '2025-03-01' ORDER BY "create_timestamp", "financial_account_id"; ``` ### Query: Cleared transactions by brand / item The following query analyzes cleared transactions by payment brand and product/item type for a defined date range, showing total sales amounts for each combination. It filters on , so the totals cover captures cleared through the card network. ```sql SELECT "brand" AS "Brand", item."order_item_name" AS "Item", SUM(item."order_item_amount_signed") / 1000000 AS "Amount" FROM payment_transaction_event AS event JOIN payment_order_item_list AS item ON event."payment_order_id" = item."payment_order_id" WHERE event."event_type_code" = 'e013' /* CLEARED */ AND "platform_date" >= '2024-02-01' AND "platform_date" < '2025-03-01' GROUP BY ALL ORDER BY 1, 2; ``` --- URL: https://docs.highnote.com/docs/developers/data-share/dictionary-issuing Title: Issuing Data Dictionary Section: Developers Description: Schema documentation and sample SQL queries for issuing data in Snowflake, including card transactions, ledger entries, interchange fees, and settlement dates. ## Overview The Highnote Issuing Data Dictionary provides all the data available for querying your card products, transactions, and ledger entries. The queries and objects below demonstrate how you can construct on-demand reports and generate metrics as needed. ## Data tables and fields This section lists the data tables and associated fields available to query your Highnote data. ### Table: code enum lookup The table is mutable and is updated periodically. Any enum values reproduced in the field descriptions on this page are examples, not exhaustive lists, so decode through rather than treating them as complete. Join this table to decode the enum-coded columns on card transaction event and ledger entry into human-readable names. For an example inside a full report, see Query: Get ledger entry report. | Field name | Data type | Description | | :--------------- | :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | table_name | String | Name of the database table to which the enum values correspond. Helps identify which table the enum codes belong to. | | code_column_name | String | Name of the column within the referenced that uses the enum code. Provides a direct link between the enum value and its usage in a specific column of a table. | | code | String | Actual enum code used in the database. This is the value stored in the column specified by in the . | | code_enum | String | Descriptive name or label representing the enum code. This human-readable description provides more context for what the code represents. | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the code enum lookup record was created. Helps track when the enum was first introduced into the system. | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the code enum lookup record was last updated. Helps with auditing and understanding the history of changes to the enum values. | Filter to the table that owns the column and to the column you want to decode, then match on : ```sql SELECT ledger."ledger_entry_id", ledger."ledger_type_code", elookup."code_enum" AS "ledger_type_name" FROM "LEDGER_ENTRY" ledger LEFT JOIN "CODE_ENUM_LOOKUP" elookup ON elookup."table_name"='ledger_entry' AND elookup."code_column_name"='ledger_type_code' AND elookup."code"=ledger."ledger_type_code" LIMIT 100; ``` Always filter on both and , not alone. The same code value can mean different things in different tables and columns. #### Decodable columns The following columns decode through : | table_name | code_column_name | | :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | card_transaction_event | , , , , , , , | | ledger_entry | | Two things to keep in mind when you write the filter: - **These columns store the code, not the decoded name.** holds , not ; holds , not . Match on and select . - ** names the table that owns the enum, which is not always the table you are querying.** Account statement entry also carries a column, but the enum is registered only under — decode it with that filter. ### Table: card The table is mutable and always displays the current state. Use the following fields to query your card products. | Field name | Data type | Description | | :-------------------- | :---------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | | card_id | String | Unique key identifying an issued payment card linked to a cardholder and financial account | | product_id | String | Unique ID of the card product that defines card behavior, limits, and features | | product_name_snapshot | String | Name of the card product associated with the card | | product_type_code | String | Type of the product | | card_network | String | Name of the network provider (Visa, Mastercard) | | expiration_date | Date | Date that the card expires | | last4 | String | Last 4 digits of the card | | cardholder_party_id | String | Unique ID of the cardholder's party record containing identity and contact information | | state | String | State of the card: , , , | | financial_account_id | String | Unique ID of the financial account linked to the card for spending and balance management | | form_factor | String | Form of the card: or | | card_profile_set_id | String | Unique ID of the card profile set that defines card design, BIN, and network configuration | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the card record was created | | export_id | String | ID that Highnote uses to track a record's lifecycle. To facilitate data investigations, Highnote may request shared record identifiers and . | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the card record last updated | ### Table: card revision The table provides an audit trail of changes to a card. This table captures each change made to the card table as a separate record. The version column represents the sequential revision number of each change. Use the following fields to query and track how a card has changed over time. | Data Field | Data Type | Description | | :-------------------- | :---------------------------------------- | :----------------------------------------------------------------------------------------- | | card_revision_id | String | Unique key identifying a point-in-time snapshot capturing each card state change | | card_id | String | Unique ID of the payment card this revision belongs to | | product_id | String | Unique ID of the card product that defines card behavior, limits, and features | | product_name_snapshot | String | Name of the card product associated with the card | | product_type_code | String | Type of the product | | version | Integer | Sequential revision number indicating the order of changes | | card_network | String | Name of the network provider (Visa, Mastercard) | | expiration_date | Date | Date that the card expires | | last4 | String | Last 4 digits of the card | | cardholder_party_id | String | Unique ID of the cardholder's party record containing identity and contact information | | state | String | State of the card: , , , | | financial_account_id | String | Unique ID of the financial account linked to the card for spending and balance management | | form_factor | String | Form of the card: or | | card_profile_set_id | String | Unique ID of the card profile set that defines card design, BIN, and network configuration | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the card revision record was created | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the card revision record was last updated | ### Table: card transaction event The table is mutable and always displays the current state. Use the following fields to query your transaction feed. | Field name | Data type | Description | | :---------------------------------- | :---------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the card transaction event record was created | | export_id | String | ID that Highnote uses to track a record's lifecycle. To facilitate data investigations, Highnote may request shared record identifiers and . | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the card transaction event record was last updated | | authorization_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the transaction was first authorized on the financial account, if applicable | | interchange_create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the interchange record was created | | platform_settlement_date | Date | Date when the transaction was settled on the platform, with a cutoff of 8 PM Eastern Time (ET) | | product_id | String | Unique ID of the card product that defines card behavior, limits, and features | | product_name_snapshot | String | Name of the card product associated with the transaction | | financial_account_id | String | Unique ID of the financial account linked to the card for spending and balance management | | card_profile_set_id | String | Unique ID of the card profile set that defines card design, BIN, and network configuration | | card_network | String | Name of the network provider (Visa, Mastercard) | | bin_classification | String | Classification of the network BIN product type (consumer, commercial, business, etc.) | | bin_funding_type | String | Funding type for the card program (credit, prepaid, debit) | | account_holder_id | String | Unique ID of the account holder (person or business) who owns the financial account | | payment_card_id | String | Unique ID of the payment card used in the transaction | | processing_network_code | String | Card transaction network. Possible values: (Visanet), (Mastercard Dual Message), (Maestro Single Message), (PULSE), or (Moneypass) | | financial_event_id | String | Unique key identifying the card transaction event. Matches in the [](#table-dispute-chargeback) and [](#table-dispute-chargeback-revision) tables. Also identifies the financial event that triggered balance changes across ledgers | | event_type | String | Type of card financial event, e.g., , , , | | transaction_id | String | Unique ID grouping related events (e.g., AUTH and CLEAR) that belong to the same card transaction | | merchant_identifier | String | Identifier of the merchant | | merchant_category_code | String | 4-digit ISO 18245 code representing retail financial services. MCCs classify businesses by the type of goods or services they provide. | | merchant_name | String | Name of the merchant where the transaction took place | | merchant_country | String | ISO 3166 Alpha-3 code representing the country where the card was accepted | | card_acceptor_location | String | Location where the transaction took place. Maps to the merchantID in MerchantDetails GraphQL object. | | issuer_response_code | Enum | Highnote response code stored as the raw code, e.g. (), (), (). Decode with [](#table-code-enum-lookup) | | avs_address_response_code | Enum | Code representing the result of an address verification check. Decode with [](#table-code-enum-lookup) | | avs_postal_code_response_code | Enum | Code representing the result of a postal code verification check. Decode with [](#table-code-enum-lookup) | | cvv_response_code | Enum | Code representing the result of a card verification value (CVV) check. Decode with [](#table-code-enum-lookup) | | settlement_ind | Boolean | Flag identifying a settled transaction | | approved_amount_signed | Integer | Funds approved and posted to the Highnote ledger for the transaction. Appears as in GQL response. Includes fees. | | approved_amount_currency_code | String | ISO 4217 code representing the currency of the approved amount | | surcharge_fee_amount_signed | Integer | Fee for the approved amount of each transaction event type | | surcharge_fee_amount_currency_code | String | ISO 4217 code representing the currency of the surcharge fee amount | | requested_amount_signed | Integer | Funds requested by the network for each transaction event type | | requested_amount_currency_code | String | ISO 4217 code representing the currency of the requested amount | | interchange_amount_signed | Integer | Interchange amount of the transaction. Positive for income. Negative for expense. | | interchange_amount_currency_code | String | ISO 4217 code representing the currency of the interchange amount | | interchange_data_availability_ind | Boolean | Indicates whether or not the interchange data is available for the transaction event | | interchange_rate_code | String | Code provided by the card network that denotes the interchange category or rate applied to the transaction. Only available for VNT and MCC. | | pos_terminal_type_code | String | Code representing where the payment was initiated. Decode with [](#table-code-enum-lookup), or see [](/docs/api-reference/enum#PointOfServiceCategory) in the API reference. | | pos_pan_entry_mode_code | String | Code representing the method for inputting a Primary Account Number (PAN) into a POS system. This is done manually or electronically via a card reader. Decode with [](#table-code-enum-lookup), or see [](/docs/api-reference/enum#PanEntryMode) in the API Reference. | | pos_card_data_input_capability_code | String | Code representing the POS terminal's card input capabilities, e.g., decodes to , meaning the POS terminal can read magnetic stripe cards. Decode with [](#table-code-enum-lookup), or see [](/docs/api-reference/enum#CardDataInputCapability) in the API Reference. | | pos_card_presence_code | String | Code representing the presence of a card during the sale: , , , | | transaction_type_code | String | Code representing the card transaction processing type from the transaction type network, e.g., =goods and services, =cash, =returns, etc. Decode with [](#table-code-enum-lookup) | | platform_transaction_category | String | Category created by Highnote to calculate Highnote TPV invoices, e.g., , , , , , etc. Non-TPV records display as . | | take_rate_transaction_impact | Integer | Direction multiplier used to calculate the take rate for Highnote TPV invoices. Supported values: , , . | | net_settled_transaction_impact | Integer | Direction multiplier used to calculate the net settlement for Highnote TPV invoices. Supported values: , , . | | original_transaction_id | String | Unique ID of the original purchase transaction when this event is a refund or reversal. Empty if the network does not provide sufficient context. | | issuer_settlement_date | Date | Highnote (issuer) defined settlement date, calculated using network cutoff and transaction timestamp. Date that banks use to settle the card transaction amounts. | | risk_score | Integer | The transaction risk score provided by the respective network. Visa values are between 0-99. Mastercard values are between 0-999. | ### Table: ledger entry The table is immutable. Use the following fields to query your account ledgers. | Field name | Data type | Description | | :------------------------------ | :---------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the ledger entry record was created | | export_id | String | ID that Highnote uses to track a record's lifecycle. To facilitate data investigations, Highnote may request shared record identifiers and . | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the ledger entry record was last updated | | product_id | String | Unique ID of the card product that defines card behavior, limits, and features | | product_name_snapshot | String | Name of the card product associated with the ledger entry | | financial_account_id | String | Unique ID of the financial account that holds funds and tracks balances | | financial_account_name_snapshot | String | Name of the financial account associated with the ledger entry | | transaction_id | String | Unique ID grouping related events (e.g., AUTH and CLEAR) that belong to the same card transaction | | financial_event_type | String | Activity type of the financial event (e.g., , , , ) | | financial_event_id | String | Unique ID of the financial event that triggered this ledger entry | | ledger_entry_id | String | Unique key identifying an immutable record of a balance change (e.g., authorization hold, clearing, funding) | | change_amount_signed | Integer | Amount by which the ledger balance changed | | normal_balance_type | String | Expected balance type of an account. Possible values are or . | | balance_at_ledger_entry_signed | Integer | Balance of the account after the ledger entry | | card_transaction_settlement_ind | Boolean | Flag identifying cleared transactions to settle at the bank | | billing_month | Date | Month of a billed invoice, with a cutoff of 8 PM Eastern Time (ET) | | ledger_type_code | String | Code representing the type of ledger. Decode with [](#table-code-enum-lookup) | | platform_transaction_category | String | Category created by Highnote to calculate Highnote TPV invoices, e.g., , , , , , etc. Non-TPV records display as . | | take_rate_transaction_impact | Integer | Direction multiplier used to calculate the take rate for Highnote TPV invoices. Supported values: , , . | | net_settled_transaction_impact | Integer | Direction multiplier used to calculate the net settlement for Highnote TPV invoices. Supported values: , , . | | issuer_settlement_date | Date | Highnote (issuer) defined settlement date, calculated using network cutoff and transaction timestamp. Date that banks use to settle the card transaction amounts. | | receivable_purchase_date | Date | Date when Highnote purchases receivables from the sponsor bank | | receivable_purchase_percent | Integer | Percentage of card settlement amount to be purchased for receivables | | receivables_purchase_ind | Boolean | Indicates that ledger entry is involved in purchasing receivables | ### Table: account statement The table captures point-in-time snapshots of an account's billing cycle — including period boundaries, primary ledger balances, payment due dates, and totals for purchases, credits, and fees. Use the following fields to query account statements. | Field name | Data type | Description | | :------------------------------------- | :---------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | | account_statement_id | String | Unique ID identifying the account statement record | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the statement record was created in the ledger | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the statement record was last updated | | statement_period_start_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp of the start of the statement period | | statement_period_end_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp of the end of the statement period | | statement_opened_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the statement was opened | | statement_closed_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the statement was closed. Only populated for closed statements. | | payment_due_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp by which payment is due for this statement | | starting_primary_balance_amount_signed | Decimal | Primary balance amount at the start of the statement period. Positive for debit balances, negative for credit balances. | | starting_primary_balance_currency_code | String | ISO 4217 code representing the currency of the starting primary balance | | ending_primary_balance_amount_signed | Decimal | Primary balance amount at the end of the statement period | | ending_primary_balance_currency_code | String | ISO 4217 code representing the currency of the ending primary balance | | total_purchases_amount_signed | Decimal | Total amount of purchases posted during the statement period | | total_purchases_amount_currency_code | String | ISO 4217 code representing the currency of the total purchases amount | | total_credits_amount_signed | Decimal | Total amount of credits (e.g., payments, refunds) posted during the statement period | | total_credits_amount_currency_code | String | ISO 4217 code representing the currency of the total credits amount | | total_fee_amount_signed | Decimal | Total amount of fees assessed during the statement period | | total_fee_currency_code | String | ISO 4217 code representing the currency of the total fee amount | | total_fee_credit_amount_signed | Decimal | Total amount of fee credits (fee reversals or waivers) posted during the statement period | | total_fee_credit_amount_currency_code | String | ISO 4217 code representing the currency of the total fee credit amount | ### Table: account statement entry The table represents individual ledger entries that contributed to an account statement during the billing period. Each row references a parent statement () and the underlying ledger entry (). Use the following fields to query individual entries within an account statement. | Field name | Data type | Description | | :-------------------------- | :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | account_statement_entry_id | String | Unique ID identifying the account statement entry record | | financial_account_id | String | Unique ID of the financial account associated with this entry | | account_statement_id | String | Unique ID of the parent [](#table-account-statement) record this entry belongs to | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the statement entry was created in the ledger | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the statement entry was last updated | | ledger_type_code | String | Code identifying the ledger type that produced this entry (e.g., primary, fee, interest). Decode with [](#table-code-enum-lookup) filtered to | | ledger_entry_id | String | Unique ID of the underlying ledger entry that this statement entry references | | financial_event_id | String | Unique ID of the financial event that triggered this entry | | financial_entity_id | String | Unique ID of the financial entity associated with this entry | | product_name_snapshot | String | Snapshot of the card product name at the time the entry was processed | | credit_ind | Boolean | Flag indicating whether the entry is a credit () or a debit () to the account | | update_amount_signed | Decimal | Signed amount by which this entry updates the balance. Sign convention follows . | | update_amount_currency_code | String | ISO 4217 code representing the currency of the update amount | | balance_update_sequence | Integer | Monotonic sequence number indicating the order of balance updates within the statement. Used to deterministically reconstruct running balance. | ### Table: dispute chargeback The table is mutable and always displays the current state of each dispute case, denormalized with chargeback, credit, and original-transaction context. Use the following fields to query the current state of dispute and chargeback cases. All amount columns are integers with a fixed precision of 6 decimal places; divide by 1,000,000 for the currency amount. For example, a $45.00 dispute reads as . | Field name | Data type | Description | | :------------------------------------------- | :---------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | dispute_case_id | String | Unique ID identifying the Highnote dispute case | | product_id | String | Unique ID of the card product | | product_name_snapshot | String | Name of the card product | | account_holder_id | String | Unique ID of the account holder | | financial_account_id | String | Unique ID of the financial account associated with the card | | payment_card_id | String | Unique ID of the payment card | | last4 | String | Last 4 digits of the payment card | | payment_network | String | Card payment network (e.g., , ) | | processing_network_code | String | Processing network code derived from the acquirer network code | | card_transaction_event_id | String | Unique ID of the card transaction event the dispute was filed against. Joins to in the [](#table-card-transaction-event) table | | original_transaction_id | String | Transaction lifecycle identifier shared across related events (e.g., and ) | | original_transaction_amount_signed | Integer | Amount of the original transaction associated with the dispute | | approved_amount_signed | Integer | Total amount approved and posted for the disputed transaction, including the surcharge fee. Always a positive magnitude, unlike the sign-adjusted field of the same name in the [](#table-card-transaction-event) table | | approved_amount_currency_code | String | ISO 4217 code representing the currency of the approved amount | | surcharge_fee_amount_signed | Integer | Surcharge fee included in the approved amount. minus this fee equals the fee-exclusive posted amount. Always a positive magnitude, unlike the sign-adjusted field of the same name in the [](#table-card-transaction-event) table | | surcharge_fee_amount_currency_code | String | ISO 4217 code representing the currency of the surcharge fee amount | | original_transaction_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the original transaction event was created | | dispute_category | String | Type of transaction dispute | | dispute_status | String | Current status of the dispute case | | dispute_amount_signed | Integer | Disputed amount of the original transaction | | dispute_amount_currency_code | String | ISO 4217 code representing the currency of the dispute amount | | dispute_credit_status_code | String | Status of the dispute credit. Possible values: , , , , , , . The credited amount for is not exposed in this table | | dispute_credit_amount_signed | Integer | Amount the cardholder receives when the dispute is won and no provisional credit was issued | | dispute_credit_amount_currency_code | String | ISO 4217 code representing the currency of the dispute credit amount | | won_credit_amount_signed | Integer | Amount credited to the cardholder when the dispute is won. This column is not currently populated and reads or null | | won_credit_amount_currency_code | String | ISO 4217 code representing the currency of the won credit amount | | credit_issue_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the cardholder was credited (provisional credit, dispute credit, or chargeback credit won) | | dispute_create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the dispute was created in the Highnote system | | dispute_update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the dispute case was last updated (dispute-only) | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Row-level create timestamp. Same value as since the dispute is the seed entity for this row. | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Row-level update timestamp. Latest update across the dispute, chargeback, and credit / credit-adjustment / credit-reversal workflows that contribute columns to this row. | | chargeback_case_id | String | Unique ID identifying the Highnote chargeback case | | chargeback_status | String | Status of the chargeback case | | external_network_id | String | Identifier of the card network's chargeback case | | external_network_id_type | String | Type of external network identifier | | chargeback_requested_amount_signed | Integer | Chargeback amount filed with the card network | | chargeback_requested_amount_currency_code | String | ISO 4217 code representing the currency of the chargeback requested amount | | chargeback_provisional_credit_status_code | String | Status of the provisional credit. Possible values: , , , , , | | provisional_credit_amount_signed | Integer | Temporary credit from the product funding account to the cardholder's financial account | | provisional_credit_amount_currency_code | String | ISO 4217 code representing the currency of the provisional credit amount | | provisional_credit_lost_amount_signed | Integer | Amount of provisional credit revoked from the cardholder when the chargeback is lost. Adjustment amounts for partially won chargebacks are not exposed in this table | | provisional_credit_lost_amount_currency_code | String | ISO 4217 code representing the currency of the provisional credit lost amount | | provisional_credit_issue_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the provisional credit was issued to the cardholder | | provisional_credit_finalized_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the provisional credit was finalized (won, partially won, or revoked) | | chargeback_create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the Highnote chargeback case was created | | chargeback_update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the Highnote chargeback case was last updated | ### Table: dispute chargeback revision The table provides the full revision history of mutable dispute and chargeback records. This table captures each state change to a record in the [](#table-dispute-chargeback) table as a separate row. The column represents the sequential revision number for each dispute case, ordered by revision timestamp. Credit fields (credit status codes, amounts, and timestamps) reflect the current state of the dispute case's credit workflows, not point-in-time state at each revision; all revisions of the same dispute case show identical credit values. Use the following fields to query and track how a dispute or chargeback case has changed over time. All amount columns are integers with a fixed precision of 6 decimal places; divide by 1,000,000 for the currency amount. For example, a $45.00 dispute reads as . | Field name | Data type | Description | | :------------------------------------------- | :---------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | revision_id | String | Unique ID identifying this revision event | | version | Integer | Sequential version number for each revision of the same dispute case, ordered by revision timestamp | | dispute_case_id | String | Unique ID of the Highnote dispute case this revision belongs to | | product_id | String | Unique ID of the card product | | product_name_snapshot | String | Name of the card product | | account_holder_id | String | Unique ID of the account holder | | financial_account_id | String | Unique ID of the financial account associated with the card | | payment_card_id | String | Unique ID of the payment card | | last4 | String | Last 4 digits of the payment card | | payment_network | String | Card payment network (e.g., , ) | | processing_network_code | String | Processing network code derived from the acquirer network code | | card_transaction_event_id | String | Unique ID of the card transaction event the dispute was filed against. Joins to in the [](#table-card-transaction-event) table | | original_transaction_id | String | Transaction lifecycle identifier shared across related events (e.g., and ) | | original_transaction_amount_signed | Integer | Amount of the original transaction associated with the dispute | | approved_amount_signed | Integer | Total amount approved and posted for the disputed transaction, including the surcharge fee. Always a positive magnitude, unlike the sign-adjusted field of the same name in the [](#table-card-transaction-event) table | | approved_amount_currency_code | String | ISO 4217 code representing the currency of the approved amount | | surcharge_fee_amount_signed | Integer | Surcharge fee included in the approved amount. minus this fee equals the fee-exclusive posted amount. Always a positive magnitude, unlike the sign-adjusted field of the same name in the [](#table-card-transaction-event) table | | surcharge_fee_amount_currency_code | String | ISO 4217 code representing the currency of the surcharge fee amount | | original_transaction_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the original transaction event was created | | dispute_revision_id | String | Unique ID identifying this dispute revision snapshot | | dispute_category | String | Type of transaction dispute | | dispute_status | String | Status of the dispute case at this revision | | dispute_amount_signed | Integer | Disputed amount of the original transaction | | dispute_amount_currency_code | String | ISO 4217 code representing the currency of the dispute amount | | dispute_credit_status_code | String | Status of the dispute credit. Possible values: , , , , , , . The credited amount for is not exposed in this table | | dispute_credit_amount_signed | Integer | Amount the cardholder receives when the dispute is won and no provisional credit was issued | | dispute_credit_amount_currency_code | String | ISO 4217 code representing the currency of the dispute credit amount | | won_credit_amount_signed | Integer | Amount credited to the cardholder when the dispute is won. This column is not currently populated and reads or null | | won_credit_amount_currency_code | String | ISO 4217 code representing the currency of the won credit amount | | credit_issue_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the cardholder was credited (provisional credit, dispute credit, or chargeback credit won) | | dispute_create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the dispute was created in the Highnote system | | dispute_update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the dispute case was last updated (dispute-only) | | chargeback_case_id | String | Unique ID of the Highnote chargeback case this revision belongs to | | chargeback_revision_id | String | Unique ID of the chargeback revision snapshot active at this event | | chargeback_status | String | Status of the chargeback case at this revision | | external_network_id | String | Identifier of the card network's chargeback case | | external_network_id_type | String | Type of external network identifier | | chargeback_requested_amount_signed | Integer | Chargeback amount filed with the card network | | chargeback_requested_amount_currency_code | String | ISO 4217 code representing the currency of the chargeback requested amount | | chargeback_provisional_credit_status_code | String | Status of the provisional credit. Possible values: , , , , , | | provisional_credit_amount_signed | Integer | Temporary credit from the product funding account to the cardholder's financial account | | provisional_credit_amount_currency_code | String | ISO 4217 code representing the currency of the provisional credit amount | | provisional_credit_lost_amount_signed | Integer | Amount of provisional credit revoked from the cardholder when the chargeback is lost. Adjustment amounts for partially won chargebacks are not exposed in this table | | provisional_credit_lost_amount_currency_code | String | ISO 4217 code representing the currency of the provisional credit lost amount | | provisional_credit_issue_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the provisional credit was issued to the cardholder | | provisional_credit_finalized_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the provisional credit was finalized (won, partially won, or revoked) | | chargeback_create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the Highnote chargeback case was created | | chargeback_update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the Highnote chargeback case was last updated | | create_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Row-level create timestamp | | update_timestamp | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Row-level update timestamp | ## Concepts Adhere to the following guidance when querying your issuing data. ### Interchange data The interchange (IC) report based on the Highnote schema is an estimate. The interchange (IC) amounts in the schema-based report can differ from those in the invoice. The IC amounts in the invoice are those that the networks deposit in the bank accounts automatically. The IC amounts in the report are affected by the cut-off times Highnote uses for reporting. The IC report based on the Highnote schema should only be used as a benchmark so you can see an estimate of what the IC could be in the invoice we provide. ### Issuer settlement date example If = June 10 and ET = Eastern Time, transactions have the following criteria: **VISA:** - Network Raw Settlement Date: June 11 - Transactions between: June 10 @ 6 AM ET → June 11 @ 6 AM ET **NEX - MCI, MSI, PULSE, PPE, CIR, EXI:** - Network Raw Settlement Date: June 10 - Transactions between: June 9 @ 8 PM ET → June 10 @ 8 PM ET **NEX - MoneyPass:** - Network Raw Settlement Date: June 9, June 10 - Transactions between: June 9 @ 4 PM ET → June 10 @ 4 PM ET ### TPV calculations When calculating Total Payment Volume (TPV), the table accounts for both card transactions and their adjustments. The table can be used to calculate TPV in the invoice, but it does not include any manual adjustments for card transactions. ## Query library This section includes sample Highnote queries in the Snowflake dialect. You can use them to retrieve data from Highnote's data sharing tables. ### Query: Get card activity report The following query retrieves yesterday's card issuing transactions (based on a defined time cutoff), showing detailed transaction data including interchange fees, merchant information, and card product details for reconciliation and reporting. ```sql SELECT TO_VARCHAR(event."create_timestamp", 'YYYY-MM-DD HH24:MI:SS.FF5 UTC') AS "posted_date_time", event."platform_settlement_date", event."product_id" AS "card_product_id", event."product_name_snapshot" AS "card_product_name", event."card_profile_set_id" AS "public_card_profile_set_id", event."card_network" AS "payment_network", event."bin_classification", event."bin_funding_type", event."payment_card_id", event."processing_network_code", event."financial_event_id", event."event_type" AS "financial_event", event."transaction_id", ROUND(event."approved_amount_signed"/1000000, 4) AS "transaction_settlement_amount", event."approved_amount_currency_code" AS "transaction_settlement_amount_currency_code", ROUND(event."interchange_amount_signed"/1000000, 4) AS "interchange_amount", event."interchange_amount_currency_code" AS "interchange_amount_currency_code", event."interchange_rate_code" AS "network_interchange_rate_code", event."merchant_category_code", event."merchant_name", event."card_acceptor_location" AS "merchant_description", event."merchant_country" AS "merchant_country" FROM "CARD_TRANSACTION_EVENT" event WHERE event."create_timestamp" >= CONVERT_TIMEZONE('America/Los_Angeles', 'UTC', TO_TIMESTAMP(DATEADD(DAY, -2, CURRENT_DATE) || ' 17:00:00')) AND event."create_timestamp" < CONVERT_TIMEZONE('America/Los_Angeles', 'UTC', TO_TIMESTAMP(DATEADD(DAY, -1, CURRENT_DATE) || ' 17:00:00')) ORDER BY event."create_timestamp" DESC LIMIT 100; ``` ### Query: Get ledger entry report The following query retrieves yesterday's card-related ledger entries (based on a defined time cutoff), showing how card transactions impact the general ledger with debits, credits, and running balances across different financial accounts. ```sql SELECT TO_VARCHAR(ledger."create_timestamp", 'YYYY-MM-DD HH24:MI:SS.FF5 UTC') AS "created_at", ledger."product_id" AS "card_product_id", ledger."product_name_snapshot" AS "card_product_name", ledger."financial_account_id", ledger."financial_account_name_snapshot" AS "financial_account_name", ledger."transaction_id", ledger."financial_event_type" AS "financial_event", ledger."financial_event_id", elookup."code_enum" AS "ledger_name", "ledger_entry_id", ROUND(ABS(ledger."change_amount_signed")/1000000, 2) AS "change_amount", CASE WHEN ledger."change_amount_signed" < 0 THEN 'DEBIT' ELSE 'CREDIT' END AS "change_amount_direction", ledger."normal_balance_type" AS "normal_balance", ROUND(ledger."balance_at_ledger_entry_signed"/1000000, 2) AS "balance_at_ledger_entry" FROM "LEDGER_ENTRY" ledger LEFT JOIN "CODE_ENUM_LOOKUP" elookup ON elookup."table_name"='ledger_entry' AND elookup."code_column_name"='ledger_type_code' AND ledger."ledger_type_code"=elookup."code" WHERE ledger."create_timestamp" >= CONVERT_TIMEZONE('America/Los_Angeles', 'UTC', TO_TIMESTAMP(DATEADD(DAY, -2, CURRENT_DATE) || ' 17:00:00')) AND ledger."create_timestamp" < CONVERT_TIMEZONE('America/Los_Angeles', 'UTC', TO_TIMESTAMP(DATEADD(DAY, -1, CURRENT_DATE) || ' 17:00:00')) ORDER BY ledger."create_timestamp" DESC LIMIT 100; ``` --- URL: https://docs.highnote.com/docs/developers/events/events-reference Title: Events Reference Section: Developers Description: Look up event notification types by domain with their corresponding API objects. ## Overview This guide is a reference for all Highnote notification events, organized by domain. When you query for notification events, the Highnote API returns a [](/docs/api-reference/object#NotificationEvent) object. This object contains: - A [](/docs/api-reference/enum#NotificationEventName) field — a enum value that identifies the event type, such as . - A [](/docs/api-reference/union#NotificationEventNode) field — a union type that contains the event details. The tables below list both the value you filter on when subscribing to events, and the event object you query for event details. Example payloads below show realistic values for every field the API populates. Placeholders are wrapped in angle brackets (). A value in an example means the field is intentionally absent for that event type (for example, a terminal success event has no ). ### Node patterns The field follows one of two patterns depending on the domain: - **Dedicated event objects** — Each value maps to its own event object with event-specific fields. For example, returns an [](/docs/api-reference/object#OriginatedAchTransferInitiatedEvent) node. In your notification event query, you can use inline fragments on to select fields specific to each event type. - **Shared domain object** — Multiple values share the same object type. For example, and both return an [](/docs/api-reference/object#AccountHolderCardProductApplication) node. Because the type is the same regardless of which state change occurred, use the field to determine what happened, and query the shared object for the entity's current state. ## ACH transfers Highnote organizes ACH transfer types by initiator. Highnote initiates **"originated"** ACH transfers, and external parties initiate **"non-originated"** ACH transfers. Both types can move funds in either direction (into or out of Highnote accounts) depending on the use case. The following table describes each ACH transfer type and its direction of money movement. For more, see the ACH transfers docs. | Type | Direction | Description | | :-------------------------- | :------------ | :----------------------------------------------------------------------------------------------------------------------------------- | | Originated ACH transfer | Pull (Debit) | Highnote originates an ACH instruction to pull funds from an external bank account into a Highnote financial account | | | Push (Credit) | Highnote originates an ACH instruction to push funds from a Highnote financial account to an external bank account | | Non-originated ACH transfer | Pull (Debit) | An external bank initiates an ACH instruction on their platform to pull funds from a Highnote financial account. | | | Push (Credit) | An external bank initiates an ACH instruction on their platform to push funds from the external bank to a Highnote financial account | The following table describes _some_ of the fields you may see in an ACH notification event response. For a full list of response fields, refer to the API Reference. | Field | Description | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | | The direction of the transfer, (pushing funds from a Highnote financial account to an external account) or (pulling funds from an external account to a Highnote financial account) | | | The amount of the ACH transfer | | | Description of the type of ACH provided by the originator of the ACH transfer | | | An alphanumeric code used to identify the originator of the ACH transfer | | | Name of the company that initiated the ACH transfer | | | A unique 15 digit number assigned by the originator to identify the transfer | | | Describes the purpose of the transfer, for example, deposit | | | Describes transfer processing speed. Nacha same day transfer limit is up to $1 million | | | The impact of the transfer on a Highnote financial account | | | Represents the status of the ACH transfer, including a failure reason if applicable | ### Originated ACH transfer Originated ACH transfer notifications are triggered when an ACH transfer is initiated from within the Highnote platform. The following notification events are available for originated ACH transfers: | Notification Event Name | Event | Description | | :----------------------------------- | :------------------------------------------------------------------------ | :------------------------------------------------------------- | | | Object | ACH transfer initiated. | | | Object | ACH transfer is pending. | | | Object | ACH transfer sent to the external financial institution. | | | Object | ACH transfer processed and reflected on the financial account. | | | Object | ACH transfer failed. | | | Object | Return received from the external financial institution. | | | Object | ACH transfer canceled. | Some notifications carry . These are system-generated and require no action. See Merchant disbursements.
Example payload: ORIGINATED_ACH_TRANSFER_INITIATED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-08-26T18:40:34.999Z", "expiresAt": "2024-09-25T18:40:34.999Z", "id": "", "name": "ORIGINATED_ACH_TRANSFER_INITIATED", "node": { "__typename": "OriginatedAchTransferInitiatedEvent", "createdAt": "2024-08-26T18:40:32.481Z", "id": "", "transfer": { "__typename": "OriginatedAchTransfer", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 15000 }, "cardProduct": { "__typename": "CardProduct", "id": "" }, "companyEntryDescription": "entrydesc", "companyIdentifier": "1852922649", "companyName": "HIGHNOTEPLATFORM", "createdAt": "2024-08-26T18:40:32.481Z", "effectiveEntryDate": "2024-08-27", "expectedProcessedAt": "2024-08-30T03:00:00.000Z", "fromFinancialAccount": { "__typename": "ExternalFinancialBankAccount", "id": "" }, "holdStatus": "NO_HOLDS", "holdType": "UNSPECIFIED", "id": "", "individualIdentificationNumber": "id", "individualName": "name", "paymentRelatedInformation": "Payment for services rendered", "purpose": "DEPOSIT", "sameDay": true, "sign": "POSITIVE", "status": "INITIATED", "toFinancialAccount": { "__typename": "FinancialAccount", "id": "" }, "type": "PULL", "updatedAt": "2024-08-26T18:40:32.491Z" } } } }, "extensions": { "signatureTimestamp": 1724697637357 } } ```
### Non-originated ACH transfer Non-originated ACH transfer notifications are triggered when an ACH transfer is initiated from outside the Highnote platform by a third-party. The following notification events are available for non-originated ACH transfers: | Notification Event Name | Event | Description | | :-------------------------------------- | :-------------------------------------------------------------------------- | :------------------------------------------------------------ | | | Object | ACH transfer received from an external financial institution. | | | Object | ACH transfer processed. | | | Object | ACH transfer failed. | | | Object | ACH transfer returned. |
Example payload: NON_ORIGINATED_ACH_TRANSFER_RECEIVED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-08-26T18:41:31.421Z", "expiresAt": "2024-09-25T18:41:31.421Z", "id": "", "name": "NON_ORIGINATED_ACH_TRANSFER_RECEIVED", "node": { "__typename": "NonOriginatedAchTransferReceivedEvent", "createdAt": "2024-08-26T18:41:29.208Z", "id": "", "transfer": { "__typename": "NonOriginatedAchTransfer", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 30101 }, "cardProduct": { "__typename": "CardProduct", "id": "" }, "companyEntryDescription": "entrydesc", "companyIdentifier": "0123456789", "companyName": "HIGHNOTETESTING", "createdAt": "2024-08-26T18:41:29.208Z", "financialAccount": { "__typename": "FinancialAccount", "id": "" }, "holdStatus": "NO_HOLDS", "holdType": "UNSPECIFIED", "id": "", "individualIdentificationNumber": "id", "individualName": "name", "paymentRelatedInformation": "Payment for services rendered", "purpose": "DEPOSIT", "settlementDate": "2024-08-26", "sign": "POSITIVE", "status": "RECEIVED", "traceNumber": "111111118215827", "type": "PUSH", "updatedAt": "2024-08-26T18:41:29.554Z" } } } }, "extensions": { "signatureTimestamp": 1724697692414 } } ```
### ACH transfer hold ACH transfer hold notification events are triggered when a hold is added or removed from an ACH transfer. The following notification events are available for ACH transfer hold events: | Notification Event Name | Event | Description | | :-------------------------- | :--------------------------------------------------------------- | :--------------------------------- | | | Object | Hold added to an ACH transfer. | | | Object | Hold removed from an ACH transfer. |
Example payload: ACH_TRANSFER_HOLD_ADDED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-08-26T18:43:47.305Z", "expiresAt": "2024-09-25T18:43:47.305Z", "id": "", "name": "ACH_TRANSFER_HOLD_ADDED", "node": { "__typename": "AchTransferHoldAddedEvent", "fromHoldStatus": "NO_HOLDS", "fromHoldType": "UNSPECIFIED", "holdStatusAddedAt": "2024-08-26T18:43:44.415Z", "id": "", "transfer": { "__typename": "OriginatedAchTransfer", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 15000 }, "cardProduct": { "__typename": "CardProduct", "id": "" }, "companyEntryDescription": "entrydesc", "companyIdentifier": "1852922649", "companyName": "HIGHNOTEPLATFORM", "createdAt": "2024-08-26T18:43:35.151Z", "effectiveEntryDate": "2024-08-27", "expectedProcessedAt": "2024-08-30T03:00:00.000Z", "fromFinancialAccount": { "__typename": "ExternalFinancialBankAccount", "id": "" }, "holdStatus": "ON_HOLD", "holdType": "RISK", "id": "", "individualIdentificationNumber": "id", "individualName": "name", "lastHoldStatusChangedAt": "2024-08-26T18:43:44.415Z", "paymentRelatedInformation": "Payment for services rendered", "purpose": "DEPOSIT", "sameDay": true, "sign": "POSITIVE", "status": "PENDING", "toFinancialAccount": { "__typename": "FinancialAccount", "id": "" }, "type": "PULL", "updatedAt": "2024-08-26T18:43:42.699Z" } } } }, "extensions": { "signatureTimestamp": 1724697829334 } } ```
## Application status Triggered when an application transitions between statuses. Includes issuing account holder and authorized user applications, and acquiring business onboarding applications. | Field | Description | | :----------------- | :----------------------------------------------- | | | The status of the application | | | The time the application status was last updated | ### Account holder applications All account holder application events return an [](/docs/api-reference/object#AccountHolderCardProductApplication) event object. | Notification Event Name | Description | | :--------------------------------------------------------- | :----------------------------------------------------------------------------------------- | | | Application approved. | | | Application closed. | | | Application requires account holder to verify identity due to a credit report fraud alert. | | | Application requires account holder to unfreeze their credit bureau report. | | | Application denied. | | | Document upload sessions requested for the application. | | | Identity update sessions requested for the application. | | | Application requires manual review. | | | Application offers need to be decisioned. | | | Application requires an underwriting decision. |
Example payload: CARD_PRODUCT_APPLICATION_APPROVED ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2022-02-23T22:22:03.830Z", "name": "CARD_PRODUCT_APPLICATION_APPROVED", "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "createdAt": "2022-02-23T22:21:58.759Z", "updatedAt": "2022-02-23T22:22:01.475Z", "applicationState": { "status": "APPROVED" } } } }, "extensions": { "requestId": "b5920a0f-ce66-9b8f-964a-6b5166e88dd2" } } ```
Example payload: CARD_PRODUCT_APPLICATION_CREDIT_REPORT_FRAUD_ALERT ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2022-02-23T22:22:03.830Z", "name": "CARD_PRODUCT_APPLICATION_CREDIT_REPORT_FRAUD_ALERT", "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "createdAt": "2022-02-23T22:21:58.759Z", "updatedAt": "2022-02-23T22:22:01.475Z", "applicationState": { "status": "PENDING" } } } }, "extensions": { "requestId": "" } } ```
Example payload: CARD_PRODUCT_APPLICATION_CREDIT_REPORT_FREEZE ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2022-02-23T22:22:03.830Z", "name": "CARD_PRODUCT_APPLICATION_CREDIT_REPORT_FREEZE", "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "createdAt": "2022-02-23T22:21:58.759Z", "updatedAt": "2022-02-23T22:22:01.475Z", "applicationState": { "status": "PENDING" } } } }, "extensions": { "requestId": "" } } ```
Example payload: CARD_PRODUCT_APPLICATION_DOCUMENT_UPLOAD_REQUESTED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2023-02-08T15:41:56.871Z", "name": "CARD_PRODUCT_APPLICATION_DOCUMENT_UPLOAD_REQUESTED", "expiresAt": "2023-03-10T15:41:56.873Z", "node": { "id": "", "applicationState": { "status": "IN_REVIEW" }, "updatedAt": "2023-02-08T15:41:54.831Z", "__typename": "AccountHolderCardProductApplication", "createdAt": "2023-02-07T21:27:06.955Z", "agentServicingRestrictedDetails": { "memo": "Document upload sessions" } }, "id": "" } }, "extensions": { "signatureTimestamp": 1675871903487 } } ```
Example payload: CARD_PRODUCT_APPLICATION_UNDERWRITING_DECISION_REQUESTED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-12-12T16:32:49.125Z", "id": "", "name": "CARD_PRODUCT_APPLICATION_UNDERWRITING_DECISION_REQUESTED", "node": { "__typename": "AccountHolderCardProductApplication", "applicationState": { "status": "PENDING" }, "createdAt": "2022-12-12T16:32:44.499Z", "id": "", "updatedAt": "2022-12-12T16:32:44.499Z" } } }, "extensions": { "signatureTimestamp": 1670862772620 } } ```
### Authorized user applications All authorized user application events return an [](/docs/api-reference/object#AuthorizedUserCardProductApplication) event object. | Notification Event Name | Description | | :------------------------------------------------------------------------- | :---------------------------------------------------------------------- | | | Authorized user application approved. | | | Authorized user application closed. | | | Authorized user application denied. | | | Document upload sessions requested for the authorized user application. | | | Authorized user application requires manual review. | | | Authorized user application requires an underwriting decision. |
Example payload: AUTHORIZED_USER_CARD_PRODUCT_APPLICATION_APPROVED ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2022-02-23T22:22:03.830Z", "name": "AUTHORIZED_USER_CARD_PRODUCT_APPLICATION_APPROVED", "node": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "createdAt": "2022-02-23T22:21:58.759Z", "updatedAt": "2022-02-23T22:22:01.475Z", "applicationState": { "status": "APPROVED" } } } }, "extensions": { "requestId": "ID" } } ```
### Acquiring applications All acquiring application events return a [](/docs/api-reference/object#ProductApplication) event object. Highnote creates this application when you onboard a business to accept card payments or move money over payment rails. | Notification Event Name | Description | | :---------------------------------------------- | :------------------------------------------------------ | | | Application approved. | | | Application closed. | | | Application denied. | | | Document upload sessions requested for the application. | | | Application requires additional review. | | | Application is being processed. | Capability provisioning follows approval, and each capability reports its own status rather than emitting events. To follow a business from application through provisioning, see Track status and start transacting.
Example payload: PRODUCT_APPLICATION_APPROVED ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2026-08-12T11:47:39.412Z", "expiresAt": "2026-09-11T11:47:39.412Z", "name": "PRODUCT_APPLICATION_APPROVED", "node": { "__typename": "ProductApplication", "id": "", "createdAt": "2026-08-12T11:47:37.108Z", "updatedAt": "2026-08-12T11:47:39.221Z", "applicationState": { "status": "APPROVED" } } } }, "extensions": { "requestId": "" } } ```
Example payload: PRODUCT_APPLICATION_DOCUMENT_UPLOAD_REQUESTED ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2026-08-12T11:31:22.905Z", "expiresAt": "2026-09-11T11:31:22.905Z", "name": "PRODUCT_APPLICATION_DOCUMENT_UPLOAD_REQUESTED", "node": { "__typename": "ProductApplication", "id": "", "createdAt": "2026-08-12T11:30:58.774Z", "updatedAt": "2026-08-12T11:31:20.663Z", "applicationState": { "status": "IN_REVIEW" } } } }, "extensions": { "signatureTimestamp": 1786534282905 } } ```
## Acquiring card payment Triggered during the lifecycle of a payment transaction processed through your acquiring integration. These events track authorizations, captures, clearing, settlement, disbursement, reversals, and verifications. ### Transaction lifecycle | Notification Event Name | Event | Description | | :------------------------------------------------------ | :------------------------------------------------------------------------------------ | :---------------------------------------------------- | | | Object | Payment transaction authorized. | | | Object | Payment transaction authorization declined. | | | Object | Incremental authorization approved. | | | Object | Incremental authorization declined. | | | Object | Payment transaction reversed. | | | Object | Payment transaction reversal declined. | | | Object | Payment transaction capture initiated. | | | Object | Payment transaction capture is processing. | | | Object | Payment transaction capture declined. | | | Object | Payment transaction settled. | | | Object | Payment transaction cleared through the card network. | | | Object | Payment transaction clearing failed. | | | Object | Settled funds disbursed to the merchant. | | | Object | Payment transaction payout settled and deposited. | | | Object | Payout transfer completed. | ### Verification | Notification Event Name | Event | Description | | :----------------------------------------- | :------------------------------------------------------------------------ | :-------------------------------------- | | | Object | Card verification transaction approved. | | | Object | Card verification transaction declined. | ### Dispute All acquiring dispute events return a [](/docs/api-reference/object#CardPaymentDispute) event object. See About Disputes in the Acquiring docs for details. | Notification Event Name | Description | | :---------------------------------------------- | :------------------------------------------------------------------------------------------------------ | | | A requires action from the merchant. | | | An issuer opens a against a payment. | | | A comes under active review. | | | The response deadline for a passes without action. The merchant loses the dispute. | | | A has been withdrawn. | | | A is closed. The payload's , when set, carries the final result. | | | The issuer accepts responsibility for a . The merchant wins the dispute. | | | The merchant accepts responsibility for a . The merchant loses the dispute. |
Example payload: CARD_PAYMENT_DISPUTE_ACTION_REQUIRED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2026-04-22T16:23:44.690Z", "id": "", "name": "CARD_PAYMENT_DISPUTE_ACTION_REQUIRED", "node": { "__typename": "CardPaymentDispute", "id": "", "cardPaymentDisputeStatus": "IN_REVIEW", "category": "FRAUD", "networkReason": { "code": "10.4", "description": "Other Fraud" }, "stages": [ { "__typename": "CardPaymentDisputeChargebackStage", "amount": { "__typename": "Amount", "value": 7500, "currencyCode": "USD", "decimalPlaces": 2 }, "responseDueAt": "2026-05-17T00:00:00.000Z" } ], "transactionEvent": { "__typename": "CardPaymentClearedEvent", "amount": { "__typename": "Amount", "value": 10000, "currencyCode": "USD", "decimalPlaces": 2 }, "createdAt": "2026-01-15T00:00:00.000Z", "updatedAt": "2026-01-16T00:00:00.000Z", "acquirerReferenceNumber": "24445551234567890123456", "paymentTransaction": { "__typename": "PaymentDebitTransaction", "id": "" } }, "createdAt": "2026-01-15T00:00:00.000Z" } } }, "extensions": { "signatureTimestamp": 1745338424690 } } ```
## Balance notifications Triggered when a balance update is applied to a financial account, such as when funds become available. The returns a [](/docs/api-reference/object#BalanceNotificationEvent) event object. | Notification Event Name | Description | | :--------------------------- | :--------------------------------------------------- | | | A balance update was applied to a financial account. | The following table describes _some_ of the fields you may see in a balance notification event response. For a full list of response fields, refer to the API Reference. | Field | Description | | :-------------------- | :------------------------------------------------------------------------------------------------------------------- | | | The direction funds are moving relative to the : for funds in, for funds out | | | The unsigned amount by which the balance changed. Always a positive value. | | | The date and time the balance update occurred | | | The resulting balance after the change was applied, exposed as / plus | | | The ledger the balance belongs to, such as | | | Whether the balance update is or | | | The money movement that triggered the update, such as or | | | The financial account associated with the balance notification |
Example payload: BALANCE_NOTIFICATION_EVENT ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "name": "BALANCE_NOTIFICATION_EVENT", "createdAt": "2026-05-22T00:14:27.956Z", "node": { "__typename": "BalanceNotificationEvent", "publicBalanceId": "", "accountingDirection": "CREDIT", "financialAccount": { "id": "" }, "ledger": { "id": "", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 153699, "currencyCode": "USD", "decimalPlaces": 2 }, "asOf": "2026-05-22T00:14:06.396Z" }, "ledgerType": "CASH", "eventType": "EFT", "subeventType": "CRYPTO_PAYOUT", "stepType": "COMPLETE", "amount": { "__typename": "Amount", "value": 150000, "currencyCode": "USD", "decimalPlaces": 2 }, "balanceNotificationTransactionId": "", "asOfDate": "2026-05-22T00:14:06.396Z" }, "expiresAt": "2026-06-21T00:14:27.957Z" } }, "extensions": { "signatureTimestamp": 1779408869663 } } ```
## Chargebacks and disputes Triggered when dispute cases or chargebacks change status, or when provisional or dispute credits are issued or revoked. Three event names below carry in the name: , , and . These are issuer-liable variants of the existing and outcomes below, not additional events alongside them — once the issuer-liable credit status flag is enabled for a tenant, an outcome that previously fired or fires the corresponding name instead. To receive one of these events, add its name to a webhook target's subscription list; subscribing to or does not carry over automatically. ### Disputes All dispute events return a [](/docs/api-reference/object#PaymentCardTransactionDispute) event object. | Notification Event Name | Description | | :----------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | | | Dispute case initiated. | | | Dispute case resolved with dispute credit. | | | Dispute case resolved in cardholder's favor. | | | Dispute case resolved against cardholder. | | | Dispute case rejected. | | | Dispute case cancelled. | | | Provisional credit issued for a dispute. | | | Provisional credit revoked for a dispute. | | | Provisional credit retained for a dispute; the issuer is liable for the loss. Issuer-liable variant of above. | | | Provisional credit finalized in cardholder's favor. | | | Provisional credit partially retained for a dispute; the issuer is liable for the uncredited portion. Issuer-liable variant of above. | | | Dispute credit issued. | | | Dispute credit reversed. |
Example payload: PAYMENT_CARD_TRANSACTION_DISPUTE_CASE_STATUS_INITIATED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "", "id": "", "name": "PAYMENT_CARD_TRANSACTION_DISPUTE_CASE_STATUS_INITIATED", "node": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "INITIATED", "createdAt": "2023-03-23T16:57:43.752Z", "updatedAt": "2023-03-23T16:57:43.752Z" } } }, "extensions": { "signatureTimestamp": 1666245348543 } } ```
Example payload: PAYMENT_CARD_TRANSACTION_DISPUTE_PROVISIONAL_CREDIT_ISSUED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "", "id": "", "name": "PAYMENT_CARD_TRANSACTION_DISPUTE_PROVISIONAL_CREDIT_ISSUED", "node": { "__typename": "PaymentCardTransactionDispute", "id": "csmdi_22fbdb3d6590e640fa98056b76b431c87f", "status": "IN_PROGRESS", "createdAt": "2023-03-23T16:57:43.752Z", "updatedAt": "2023-03-23T16:57:43.752Z" } } }, "extensions": { "signatureTimestamp": 1666245348543 } } ```
### Chargebacks All chargeback events return a [](/docs/api-reference/object#PaymentCardTransactionChargeback) event object. | Notification Event Name | Description | | :------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- | | | Chargeback provisional credit issued. | | | Chargeback provisional credit revoked. | | | Chargeback provisional credit retained; the issuer is liable for the loss. Issuer-liable variant of above. |
Example payload: PAYMENT_CARD_TRANSACTION_CHARGEBACK_PROVISIONAL_CREDIT_ISSUED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "", "id": "", "name": "PAYMENT_CARD_TRANSACTION_CHARGEBACK_PROVISIONAL_CREDIT_ISSUED", "node": { "__typename": "PaymentCardTransactionChargeback", "id": "", "dispute": { "id": "" }, "creditStatus": "PROVISIONAL_CREDIT_ISSUED", "status": "RECEIVED", "createdAt": "2023-03-23T16:57:43.752Z", "updatedAt": "2023-03-23T16:57:43.752Z" } } }, "extensions": { "signatureTimestamp": 1666245348543 } } ```
## Check payment Triggered during the lifecycle of a check payment, from funding through shipment, delivery, and completion. All check payment events return a [](/docs/api-reference/object#CheckPaymentEvent) event object. | Notification Event Name | Description | | :--------------------------------------------------- | :-------------------------------------------------- | | | Check payment initiated, pending funding. | | | Check funding initiated. | | | Check funded, pending disbursement. | | | Check funds disbursed to external accounts. | | | Check pending processing by Highnote. | | | Check is being processed by Highnote. | | | Check processed by Highnote. | | | Check printed. | | | Check printed, pending shipment. | | | Check shipped. | | | Check paid out. | | | Check delivered and cashed or deposited. | | | Check placed on hold for risk assessment. | | | Check voided. | | | Check payment failed. | | | Check reversal initiated due to voiding or failure. | | | Check reversal completed. | ## Collaborative application decisioning If you use collaborative application decisioning, subscribe to to receive applications that need your underwriting decision. This event is listed under Account holder applications and Authorized user applications. ## Credit limit Triggered when a credit limit change request changes status. | Notification Event Name | Event | Description | | :------------------------------------------- | :------------------------------------------------------------------------------ | :------------------------------------------ | | | Object | Credit limit change request status changed. |
Example payload: INCREASE INITIATED ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2024-01-01T00:00:00.000Z", "name": "CREDIT_LIMIT_CHANGE_REQUEST_STATUS_CHANGED", "node": { "__typename": "CreditLimitChangeRequest", "id": "", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "financialAccountId": "ac_1234", "creditLimitChangeRequestType": "INCREASE", "creditLimitChangeRequestStatus": "INITIATED", "creditLimitChangeRequestFailureReason": null } } }, "extensions": { "requestId": "b5920a0f-ce66-9b8f-964a-6b5166e88dd2" } } ```
Example payload: INCREASE FAILED ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2024-01-01T00:00:00.000Z", "name": "CREDIT_LIMIT_CHANGE_REQUEST_STATUS_CHANGED", "node": { "__typename": "CreditLimitChangeRequest", "id": "", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "financialAccountId": "ac_1234", "creditLimitChangeRequestType": "INCREASE", "creditLimitChangeRequestStatus": "FAILED", "creditLimitChangeRequestFailureReason": "NSF" } } }, "extensions": { "requestId": "b5920a0f-ce66-9b8f-964a-6b5166e88dd2" } } ```
## Crypto funding flow Crypto funding flow notifications track the lifecycle of a crypto funding flow, in which funds are received from an external crypto provider and converted to fiat on a Highnote financial account. Each event implements the [](/docs/api-reference/interface#CryptoFundingFlowEvent) interface and returns the it belongs to. The sequence below traces a crypto funding flow end to end — from the on-chain deposit, through conversion and settlement, to the that marks the spend gate, the point at which funds become available for card authorizations: | Notification Event Name | Event | Description | | :------------------------------ | :------------------------------------------------------------------- | :------------------------------------------------------------ | | | Object | Funding received from the crypto provider; not yet processed. | | | Object | Funding flow processed and posted to the financial account. | | | Object | Funding flow failed. |
Example payload: CRYPTO_FUNDING_FLOW_RECEIVED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-08-26T18:40:34.999Z", "expiresAt": "2024-09-25T18:40:34.999Z", "id": "", "name": "CRYPTO_FUNDING_FLOW_RECEIVED", "node": { "__typename": "CryptoFundingFlowReceivedEvent", "createdAt": "2024-08-26T18:40:32.481Z", "id": "", "transfer": { "__typename": "CryptoFundingFlowTransfer", "id": "", "createdAt": "2024-08-26T18:40:32.481Z", "status": "RECEIVED", "cryptoAmount": { "__typename": "Amount", "currencyCode": "USDC", "decimalPlaces": 2, "value": 50000 }, "fiatAmount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 50000 }, "receivingAccount": { "__typename": "FinancialAccount", "id": "" }, "fundingAccount": { "__typename": "FinancialAccount", "id": "" } } } } }, "extensions": { "signatureTimestamp": 1724697637357 } } ```
## Digital wallet token status Triggered when a card digital wallet token (Apple Pay, Google Wallet) changes status. | Notification Event Name | Event | Description | | :------------------------------------- | :------------------------------------------------------------------------- | :------------------------------- | | | Object | Digital wallet token activated. | | | Object | Digital wallet token suspended. | | | Object | Digital wallet token terminated. |
Example payload: DIGITAL_WALLET_TOKEN_ACTIVATED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-12-12T16:32:49.125Z", "id": "", "name": "DIGITAL_WALLET_TOKEN_ACTIVATED", "node": { "__typename": "CardDigitalWalletTokenEvent", "paymentCardId": "", "tokenStatus": "ACTIVE", "tokenPreviousStatus": "SUSPENDED", "reason": "DEVICE_FOUND" } } }, "extensions": { "signatureTimestamp": 1670862772620 } } ```
## Document upload Triggered during the document upload lifecycle, including on-demand document requests. | Notification Event Name | Event | Description | | :--------------------------------------- | :---------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | | | Object | An on-demand document upload session was created. See Request Documents On-Demand. | | | Object | A document upload session moved into a terminal state. | | | Object | A document upload link completed its upload. | ## External bank account Triggered when a verified external bank account is added, removed, requires further verification, has its verification link expire, or fails to link. | Notification Event Name | Event | Description | | :---------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | | | Object | Verified external bank account created. | | | Object | Verified external bank account disconnected. | | | Object | Verified external bank account creation failed. | | | Object | Account holder must complete verification via a hosted Link URL to finish linking. | | | Object | Hosted Link URL expired before the account holder completed verification. |
Example payload: EXTERNAL_BANK_ACCOUNT_REMOVED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-11-04T06:53:59.966Z", "id": "", "name": "EXTERNAL_BANK_ACCOUNT_REMOVED", "node": { "__typename": "ExternalBankAccountRemovedEvent", "id": "", "accountHolderId": "", "accountName": "Plaid Checking", "accountStatus": "CLOSED", "createdAt": "2022-11-04T06:53:27.627Z", "externalBankAccountDetail": { "__typename": "ExternalBankAccountDetail", "id": "", "createdAt": "2022-11-04T06:53:27.627Z", "last4": "9606", "routingNumber": "011401533", "type": "CHECKING", "updatedAt": "2022-11-04T06:53:27.672Z" }, "provider": "SIMULATED", "removedAt": "2022-11-04T06:53:58.700Z", "updatedAt": "2022-11-04T06:53:58.737Z" } } }, "extensions": { "signatureTimestamp": 1667544843895 } } ```
Example payload: LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT_VERIFICATION_REQUIRED The node-level is when the hosted Link URL expires, the deadline by which the account holder must complete verification. It is distinct from the envelope-level , which is when the Notification Event itself expires. ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2026-06-25T21:43:19.000Z", "expiresAt": "2026-07-25T21:43:19.000Z", "id": "", "name": "LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT_VERIFICATION_REQUIRED", "node": { "__typename": "LinkVerifiedExternalBankAccountVerificationRequiredEvent", "id": "", "accountHolder": { "__typename": "USPersonAccountHolder", "id": "" }, "hostedLinkUrl": "", "expiresAt": "2026-06-29T21:43:19.000Z", "createdAt": "2026-06-25T21:43:19.000Z", "updatedAt": "2026-06-25T21:43:19.000Z" } } }, "extensions": { "signatureTimestamp": 1782422599000 } } ```
Example payload: LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT_EXPIRED Triggered when the hosted Link URL expires before the account holder completes verification. The event carries no or , since the link is no longer actionable. ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2026-06-25T21:43:19.000Z", "expiresAt": "2026-07-25T21:43:19.000Z", "id": "", "name": "LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT_EXPIRED", "node": { "__typename": "LinkVerifiedExternalBankAccountExpiredEvent", "id": "", "accountHolder": { "__typename": "USPersonAccountHolder", "id": "" }, "createdAt": "2026-06-25T21:43:19.000Z", "updatedAt": "2026-06-29T21:43:19.000Z" } } }, "extensions": { "signatureTimestamp": 1782422599000 } } ```
## Fee transfer Triggered when a fee is charged or reversed on a financial account. | Notification Event Name | Event | Description | | :---------------------- | :---------------------------------------------------- | :------------ | | | Object | Fee charged. | | | Object | Fee reversed. |
Example payload: FEE_CHARGE_EVENT ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_3a298028eb3f6de6f0be97e4d81434f0", "name": "FEE_CHARGE_EVENT", "createdAt": "2025-06-13T21:46:19.621Z", "node": { "__typename": "FeeChargeEvent", "id": "fxtre_22is001d6b701c5de5e41c7a4a45da724f20c7f", "feeActivityType": "VIRTUAL_CARD_REISSUE_FEE", "originatingAccount": { "__typename": "FinancialAccount", "id": "ac_c02293c2e80657be40018f0c05eee6ef62fd" }, "receivingAccount": { "__typename": "FinancialAccount", "id": "ac_og22d44c3eb6e6f14929954ba278ffcd84ec" }, "status": { "__typename": "NonFailureFeeTransferStatus", "status": "COMPLETE" }, "transferDate": "2025-06-13T21:46:15.839Z", "feeTransferAmount": { "currencyCode": "USD", "value": 500 } }, "expiresAt": "2025-07-13T21:46:19.622Z" } }, "extensions": { "signatureTimestamp": 1749851179952 } } ```
Example payload: FEE_REVERSAL_EVENT ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_e865d0cdd17de956e92a9b3cee8d7fcc", "name": "FEE_REVERSAL_EVENT", "createdAt": "2025-06-13T21:46:55.921Z", "node": { "__typename": "FeeReversalEvent", "id": "fxtre_22is001a074a8835a9b46a1ab158723d04f8f4a", "feeActivityType": "VIRTUAL_CARD_REISSUE_FEE", "originatingAccount": { "__typename": "FinancialAccount", "id": "ac_og22d44c3eb6e6f14929954ba278ffcd84ec" }, "receivingAccount": { "__typename": "FinancialAccount", "id": "ac_c02293c2e80657be40018f0c05eee6ef62fd" }, "status": { "__typename": "NonFailureFeeTransferStatus", "status": "COMPLETE" }, "transferDate": "2025-06-13T21:46:53.632Z", "feeTransferAmount": { "currencyCode": "USD", "value": 500 }, "sourceFeeTransferEvent": { "__typename": "FeeTransferEvent", "id": "fxtre_22is001d6b701c5de5e41c7a4a45da724f20c7f" } }, "expiresAt": "2025-07-13T21:46:55.921Z" } }, "extensions": { "signatureTimestamp": 1749851216256 } } ```
## Financial account attributes Triggered when a financial account attribute is added or removed. Attributes indicate account conditions such as delinquency, charge-off, or suspension. All financial account attribute events return a [](/docs/api-reference/object#FinancialAccount) event object. | Notification Event Name | Description | | :----------------------------------------------------------------------- | :---------------------------------------------------- | | | Charge-off attribute added. | | | Charge-off attribute removed. | | | Closed with balance attribute added. | | | Closed with balance attribute removed. | | | Delinquent attribute added. | | | Delinquent attribute removed. | | | Delinquent suspended attribute added. | | | Delinquent suspended attribute removed. | | | Program owner initiated suspension attribute added. | | | Program owner initiated suspension attribute removed. |
Example payload: FINANCIAL_ACCOUNT_ATTRIBUTE_ADDED_DELINQUENT ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2023-02-15T23:34:16.399Z", "id": "", "name": "FINANCIAL_ACCOUNT_ATTRIBUTE_ADDED_DELINQUENT", "node": { "__typename": "FinancialAccount", "accountAttributes": ["DELINQUENT"], "accountStatus": "ACTIVE", "createdAt": "2023-02-15T23:34:03.095Z", "externalId": "", "id": "", "name": "Test PIF Commercial Credit Account" } } }, "extensions": { "signatureTimestamp": 1676504056802 } } ```
## Financial account statement Triggered when a financial account statement is ready or a payment due date is approaching. | Notification Event Name | Event | Description | | :---------------------------------- | :----------------------------------------------------------------------- | :------------------------------------------- | | | Object | Financial account statement is ready. | | | Object | A statement payment due date is approaching. |
Example payload: FINANCIAL_ACCOUNT_STATEMENT_READY ```json { "data": { "node": { "__typename": "FinancialAccountStatementReadyEvent", "id": "", "financialAccountId": "", "createdAt": "2024-06-06T12:34:56.789Z" } }, "extensions": { "signatureTimestamp": 1727990400000 } } ```
Example payload: UPCOMING_STATEMENT_DUE_DATE ```json { "data": { "node": { "__typename": "UpcomingStatementDueDateEvent", "createdAt": "2026-04-25T08:00:00.000Z", "financialAccount": { "__typename": "FinancialAccount", "id": "" }, "numberOfDaysUntilDueDate": 5, "paymentDueDayOfMonth": 15, "upcomingStatementDueDate": "2026-04-30T00:00:00.000Z" } }, "extensions": { "signatureTimestamp": 1777104000000 } } ```
## Financial account status Triggered when a financial account transitions between statuses. | Notification Event Name | Event | Description | | :------------------------------- | :-------------------------------------------------------------------- | :------------------------------------------------ | | | Object | Financial account entered ACTIVE status. | | | Object | Financial account has been closed. | | | Object | Financial account entered PENDING_CLOSURE status. | | | Object | Financial account entered SUSPENDED status. | | | Object | Financial account entered UNDER_REVIEW status. |
Example payload: ACCOUNT_STATUS_SUSPENDED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-10-20T05:55:45.841Z", "id": "nee_6f9f952070c8d0a6c446e3764bc905e3", "name": "ACCOUNT_STATUS_SUSPENDED", "node": { "__typename": "AccountStatusSuspendedEvent", "accountName": "My Sample Account", "createdAt": "2022-10-20T05:55:40.505Z", "externalId": "D5LDSYLPMR", "id": "ac_c022c3165221cf7546ca9db0ccd480831234" } } }, "extensions": { "signatureTimestamp": 1666245348543 } } ```
## Identity documents and updates Triggered when identity verification documents are requested or identity information is updated for account holders, authorized persons, or beneficial owners. | Notification Event Name | Event | Description | | :---------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------- | :------------------------------------------------------------- | | | Object | Identity documents requested for a business account holder. | | | Object | Business account holder identity updated. | | | Object | Identity documents requested for an authorized person. | | | Object | Authorized person identity updated. | | | Object | Identity documents requested for an ultimate beneficial owner. | | | Object | Ultimate beneficial owner identity updated. | | | Object | Identity documents requested for a person account holder. | | | Object | Person account holder identity updated. |
Example payload: PERSON_ACCOUNT_HOLDER_IDENTITY_DOCUMENTS_REQUESTED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-07-03T17:41:20.785Z", "expiresAt": "2024-08-02T17:41:20.785Z", "id": "", "name": "PERSON_ACCOUNT_HOLDER_IDENTITY_DOCUMENTS_REQUESTED", "node": { "createdAt": "2024-07-03T17:41:16.559Z", "documentUploadSession": { "__typename": "IdentityVerificationDocumentUploadSession", "id": "" }, "personAccountHolder": { "__typename": "USPersonAccountHolder", "id": "PERSON_ACCOUNT_HOLDER" }, "reason": "CIP_VERIFICATION" } } }, "extensions": { "signatureTimestamp": 1720028482632 } } ```
Example payload: PERSON_ACCOUNT_HOLDER_IDENTITY_UPDATED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-05-15T19:37:00.917Z", "expiresAt": "2024-06-14T19:37:00.917Z", "id": "", "name": "PERSON_ACCOUNT_HOLDER_IDENTITY_UPDATED", "node": { "__typename": "PersonAccountHolderIdentityUpdatedEvent", "createdAt": "2024-05-15T19:36:59.225Z", "personAccountHolder": { "__typename": "USPersonAccountHolder", "id": "" }, "updateTypes": ["FULL_LEGAL_NAME"] } } }, "extensions": { "signatureTimestamp": 1715801821319 } } ```
## Instant network transfer Instant Network Transfers (INTs) are implemented through Highnote's Unified Funds Transfer (UFT) framework. Instant Network Transfers use the API object to handle the technical processing of these transactions. For events triggered during the lifecycle of a transfer itself, see Unified funds transfer below. ### Capabilities The events in this section are triggered when an Instant Network Transfer (INT) capability on a changes status. INT capabilities determine whether a tokenized payment card can act as the **destination of a push** or the **source of a pull**. Highnote sends one notification per capability status change. For conceptual information, see Capabilities in the Instant Network Transfer docs. | Notification Event Name | Event | Description | | :------------------------------------------------------- | :------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------- | | | Object | INT capability moved to . | | | Object | INT capability moved to . | | | Object | INT capability moved to . The card requires manual review by Highnote's Operations team before it can be used. | | | Object | INT capability previously in was reviewed. Inspect for the outcome ( or ). | #### Destination vs source capabilities Because the field returns a [](/docs/api-reference/union#PaymentCardInstrumentCapability) union, inspect to distinguish the destination capability from the source capability: - [](/docs/api-reference/object#InstantNetworkTransferDestinationPaymentInstrumentCapability) — the card can receive funds (push / OCT). - [](/docs/api-reference/object#InstantNetworkTransferSourcePaymentInstrumentCapability) — the card can send funds (pull / AFT). #### Status alias Both members expose the same fields, including and . Highnote's webhook delivery aliases per member — for destination capabilities, for source capabilities — so your handler receives a flat shape and can tell the two directions apart by key. The example payloads below reflect this delivery shape. If you query a directly via the GraphQL API rather than receive it via webhook, aliasing is your choice. The query below shows the same pattern: ```graphql ... on PaymentMethodCapabilityEnabledEvent { paymentMethodToken { id } capability { __typename ... on InstantNetworkTransferDestinationPaymentInstrumentCapability { destinationStatus: status createdAt updatedAt } ... on InstantNetworkTransferSourcePaymentInstrumentCapability { sourceStatus: status createdAt updatedAt } } } ``` #### Payloads The example payloads below reflect the actual webhook delivery shape, with aliased per direction.
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_ENABLED_EVENT (destination) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_95af6a7374d43747ebe5cd8297d283ac", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_ENABLED_EVENT", "createdAt": "2026-05-01T23:30:38.222Z", "node": { "__typename": "PaymentMethodCapabilityEnabledEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "destinationStatus": "ENABLED", "createdAt": "2026-05-01T23:30:10.716Z", "updatedAt": "2026-05-01T23:30:10.716Z" } }, "expiresAt": "2026-06-30T23:30:38.222Z" } }, "extensions": { "signatureTimestamp": 1777678238603 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_ENABLED_EVENT (source) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_389e720d1981622bb381d23f87b52c48", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_ENABLED_EVENT", "createdAt": "2026-04-28T20:07:17.278Z", "node": { "__typename": "PaymentMethodCapabilityEnabledEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferSourcePaymentInstrumentCapability", "sourceStatus": "ENABLED", "createdAt": "2026-04-28T20:06:52.361Z", "updatedAt": "2026-04-28T20:06:52.361Z" } }, "expiresAt": "2026-05-28T20:07:17.286Z" } }, "extensions": { "signatureTimestamp": 1777406839540 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_DISABLED_EVENT (destination) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_bb611b55ff7e7b300e74de823e55e5f1", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_DISABLED_EVENT", "createdAt": "2026-04-28T20:07:17.280Z", "node": { "__typename": "PaymentMethodCapabilityDisabledEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "destinationStatus": "DISABLED", "createdAt": "2026-04-28T20:06:52.355Z", "updatedAt": "2026-04-28T20:06:52.355Z" } }, "expiresAt": "2026-05-28T20:07:17.286Z" } }, "extensions": { "signatureTimestamp": 1777406839538 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_DISABLED_EVENT (source) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_87dcbf565a05d631e9ff2814547e7670", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_DISABLED_EVENT", "createdAt": "2026-04-28T20:10:20.420Z", "node": { "__typename": "PaymentMethodCapabilityDisabledEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferSourcePaymentInstrumentCapability", "sourceStatus": "DISABLED", "createdAt": "2026-04-28T20:09:53.046Z", "updatedAt": "2026-04-28T20:09:53.046Z" } }, "expiresAt": "2026-05-28T20:10:20.423Z" } }, "extensions": { "signatureTimestamp": 1777407021225 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_REQUIRES_REVIEW_EVENT (destination) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_c9f710caa3f06ccbbc6605199beae107", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_REQUIRES_REVIEW_EVENT", "createdAt": "2026-05-01T23:25:54.519Z", "node": { "__typename": "PaymentMethodCapabilityRequiresReviewEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "destinationStatus": "REQUIRES_REVIEW", "createdAt": "2026-05-01T23:25:29.543Z", "updatedAt": "2026-05-01T23:25:29.543Z" } }, "expiresAt": "2026-06-30T23:25:54.521Z" } }, "extensions": { "signatureTimestamp": 1777677955151 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_REQUIRES_REVIEW_EVENT (source) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_9cf52cfa08f87311aa1516f676fd00d2", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_REQUIRES_REVIEW_EVENT", "createdAt": "2026-05-01T23:25:54.521Z", "node": { "__typename": "PaymentMethodCapabilityRequiresReviewEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferSourcePaymentInstrumentCapability", "sourceStatus": "REQUIRES_REVIEW", "createdAt": "2026-05-01T23:25:29.585Z", "updatedAt": "2026-05-01T23:25:29.585Z" } }, "expiresAt": "2026-06-30T23:25:54.521Z" } }, "extensions": { "signatureTimestamp": 1777677955071 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT (destination, enabled) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_af2a043cc3e76d3696a698df96bc8ffd", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT", "createdAt": "2026-05-01T23:27:05.245Z", "node": { "__typename": "PaymentMethodCapabilityReviewedEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "destinationStatus": "ENABLED", "createdAt": "2026-05-01T23:26:48.671Z", "updatedAt": "2026-05-01T23:26:48.671Z" } }, "expiresAt": "2026-06-30T23:27:05.245Z" } }, "extensions": { "signatureTimestamp": 1777678025698 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT (source, enabled) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_ab62a5ef1139944f019ff2e3ebd70316", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT", "createdAt": "2026-05-01T23:27:05.269Z", "node": { "__typename": "PaymentMethodCapabilityReviewedEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferSourcePaymentInstrumentCapability", "sourceStatus": "ENABLED", "createdAt": "2026-05-01T23:26:48.984Z", "updatedAt": "2026-05-01T23:26:48.984Z" } }, "expiresAt": "2026-06-30T23:27:05.269Z" } }, "extensions": { "signatureTimestamp": 1777678025776 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT (destination, disabled) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_fd34948b7c1d6a4a3624e8e50cad4c7c", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT", "createdAt": "2026-05-01T23:29:07.261Z", "node": { "__typename": "PaymentMethodCapabilityReviewedEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "destinationStatus": "DISABLED", "createdAt": "2026-05-01T23:28:48.654Z", "updatedAt": "2026-05-01T23:28:48.654Z" } }, "expiresAt": "2026-06-30T23:29:07.261Z" } }, "extensions": { "signatureTimestamp": 1777678147616 } } ```
Example payload: PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT (source, disabled) ```json { "data": { "node": { "__typename": "NotificationEvent", "id": "nee_22792b0c309843a2f69fe78703baf379", "name": "PAYMENT_METHOD_CAPABILITY_STATUS_REVIEWED_EVENT", "createdAt": "2026-05-01T23:29:07.292Z", "node": { "__typename": "PaymentMethodCapabilityReviewedEvent", "paymentMethodToken": { "__typename": "PaymentMethodToken", "id": "" }, "capability": { "__typename": "InstantNetworkTransferSourcePaymentInstrumentCapability", "sourceStatus": "DISABLED", "createdAt": "2026-05-01T23:28:48.846Z", "updatedAt": "2026-05-01T23:28:48.846Z" } }, "expiresAt": "2026-06-30T23:29:07.292Z" } }, "extensions": { "signatureTimestamp": 1777678147772 } } ```
## Internal transfer Triggered when funds are transferred between Highnote financial accounts. | Field | Description | | :----------------------- | :--------------------------------------------------------------------------------- | | | A description of the transfer for reference; input provided from your organization | | | The current status of the internal transfer | ### Between financial accounts All events return an [](/docs/api-reference/object#InterFinancialAccountTransfer) event object. | Notification Event Name, description, and event object | | :---------------------------------------------------------------------------------------------------------------------- | |
Internal transfer between financial accounts pending. | |
Internal transfer between financial accounts completed. | |
Internal transfer between financial accounts failed. | ### From funding account to payment card account | Notification Event Name, description, and event object | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
Transfer from funding account to payment card account pending.
Event object | |
Transfer from funding account to payment card account completed.
Event object | |
Transfer from funding account to payment card account failed.
Event object | ### From payment card account to funding account | Notification Event Name, description, and event object | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
Transfer from payment card account to funding account pending.
Event object | |
Transfer from payment card account to funding account completed.
Event object | |
Transfer from payment card account to funding account failed.
Event object |
Example payload: INTERNAL_TRANSFER_BETWEEN_FINANCIAL_ACCOUNTS_PENDING ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2023-02-15T23:34:16.399Z", "id": "nee_8b35c7332637359ee998cbd35ee10923", "name": "INTERNAL_TRANSFER_BETWEEN_FINANCIAL_ACCOUNTS_PENDING", "node": { "__typename": "InterFinancialAccountTransfer", "id": "ia_229d0fc1823ba64d8e9539ea160a93f00e", "toFinancialAccount": { "id": "ac_c022126bc2bb629545a988564e267d8982a5", "name": "To Account", "createdAt": "2023-07-19T20:45:23.091Z", "updatedAt": "2023-07-19T20:45:23.114Z", "externalId": "8UMLNCAKPJ", "accountAttributes": [], "accountStatus": "ACTIVE" }, "fromFinancialAccount": { "id": "ac_og226c09fff75b35495a932bc5ee92b722ad", "name": "From Account", "createdAt": "2023-07-19T20:44:35.110Z", "updatedAt": "2023-07-19T20:44:35.128Z", "externalId": "LBA3ME6QXF", "accountAttributes": [], "accountStatus": "ACTIVE" }, "amount": { "currencyCode": "USD", "value": 1000 }, "statusReason": null, "memo": "", "purpose": null, "transferActivityType": "SET_LIMIT", "createdAt": "2023-07-19T20:50:21.485Z", "updatedAt": "2023-07-19T20:50:21.486Z" } } } } ```
Example payload: INTERNAL_TRANSFER_FROM_FUNDING_FINANCIAL_ACCOUNT_ TO_PAYMENT_CARD_FINANCIAL_ACCOUNT_PENDING ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-08-22T20:11:36.337Z", "id": "nee_8521b5febf49f4b19d7deb01dc0b5539", "name": "INTERNAL_TRANSFER_FROM_FUNDING_FINANCIAL_ACCOUNT_TO_PAYMENT_CARD_FINANCIAL_ACCOUNT_PENDING", "node": { "__typename": "InternalTransferFromFundingFinancialAccountToPaymentCardFinancialAccountPendingEvent", "amount": { "currencyCode": "USD", "value": 500000, "decimalPlaces": 2 }, "createdAt": "2022-08-22T20:11:32.302Z", "id": "ia_22dab11a1e0df343a89f7ecb53096bd32e", "internalTransferStatus": "PENDING", "updatedAt": "2022-08-22T20:11:32.302Z" } } }, "extensions": { "signatureTimestamp": 1661199096776 } } ```
Example payload: INTERNAL_TRANSFER_FROM_PAYMENT_CARD_FINANCIAL_ACCOUNT_ TO_FUNDING_FINANCIAL_ACCOUNT_PENDING ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-08-19T23:11:53.132Z", "id": "nee_49f8c163f4f8a2c47fe702f02fcbbf52", "name": "INTERNAL_TRANSFER_FROM_PAYMENT_CARD_FINANCIAL_ACCOUNT_TO_FUNDING_FINANCIAL_ACCOUNT_PENDING", "node": { "__typename": "InternalTransferFromPaymentCardFinancialAccountToFundingFinancialAccountPendingEvent", "amount": { "currencyCode": "USD", "value": 350000, "decimalPlaces": 2 }, "createdAt": "2022-08-19T23:11:51.931Z", "id": "ia_22e017a985a3034683aa55cef491902791", "internalTransferStatus": "PENDING", "updatedAt": "2022-08-19T23:11:51.931Z" } } }, "extensions": { "signatureTimestamp": 1660950715339 } } ```
## Notification system Triggered when a notification target is activated. | Notification Event Name | Event | Description | | :----------------------------------- | :------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------- | | | Object | Notification target activated. This event is automatically delivered and cannot be unsubscribed. | | | Object | Sent when the mutation is called. | | | Object | Sent when the mutation is called. |
Example payload: NOTIFICATION_ACTIVATION ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-10-21T19:14:46.664Z", "id": "nee_b0f306cc171b44ef89223ca68a0da569", "name": "NOTIFICATION_ACTIVATION", "node": { "__typename": "NotificationTargetActivationEvent", "ping": "pong" } } }, "extensions": { "signatureTimestamp": 1666379691368 } } ```
## Payment card Triggered when a payment card changes status or when card transaction events occur (issuing side). ### Card status | Notification Event Name | Event | Description | | :------------------------- | :--------------------------------------------------------------- | :------------------------ | | | Object | Payment card issued. | | | Object | Payment card activated. | | | Object | Payment card suspended. | | | Object | Payment card unsuspended. | | | Object | Payment card closed. |
Example payload: PAYMENT_CARD_ACTIVATED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2021-12-02T18:12:13.408Z", "id": "", "name": "PAYMENT_CARD_ACTIVATED", "node": { "__typename": "PaymentCardActivatedEvent", "id": "", "bin": "510510", "cardProductId": "", "expirationDate": "Sat Jan 01 08:00:00 UTC 2022", "formFactor": "VIRTUAL", "last4": "5100", "network": "MASTERCARD", "status": "ACTIVE", "previousStatus": "ACTIVATION_REQUIRED", "updatedAt": "2021-12-02T18:12:13.408Z" } } }, "extensions": { "signatureTimestamp": 1638843592782 } } ```
### Card transactions (issuing) | Notification Event Name | Event | Description | | :---------------------------------------------- | :--------------------------------------------------------------------------------- | :------------------------------------------------------ | | | Object | Card authorization approved. | | | Object | Card authorization declined. | | | Object | Card authorization and clear approved (single message). | | | Object | Card authorization and clear declined (single message). | | | Object | Card authorization reversed. | | | Object | Card transaction cleared. | | | Object | Card transaction adjusted. | | | Object | Enhanced transaction data received (Level 2/3). | | | Object | Card verification approved. | | | Object | Card verification declined. | #### Surcharge fees Authorization events include a array that surfaces fees applied to the transaction. Each entry has , , and . The current [](/docs/api-reference/enum#TransactionFeeType) value is , used for ATM network charges on cash withdrawals or balance inquiries. You can find the following fees array in the example below. ```json "fees": [ { "requestedFeeAmount": { "currencyCode": "USD", "value": 250, "decimalPlaces": 2 }, "approvedFeeAmount": { "currencyCode": "USD", "value": 250, "decimalPlaces": 2 }, "transactionFeeType": "SURCHARGE" } ], ```
Example payload: PAYMENT_CARD_AUTHORIZATION_APPROVED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-02-14T19:40:27.635Z", "expiresAt": "2024-03-15T19:40:27.642Z", "id": "nee_f7bf7cd4faa05f091801c288de8a1c30", "name": "PAYMENT_CARD_AUTHORIZATION_APPROVED", "node": { "__typename": "PaymentCardAuthorizationApprovedEvent", "accountHolderId": "", "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "38082a7f771345ce989e4574ff3252e4" }, "approvedAmount": { "currencyCode": "USD", "value": 15000, "decimalPlaces": 2 }, "avsResponseCode": "NOT_PROVIDED", "cardId": "", "createdAt": "2024-02-14T19:40:22.954Z", "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 49925000, "decimalPlaces": 2 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 50000000, "decimalPlaces": 2 }, "cvvResponseCode": "MATCH", "financialAccountId": "", "id": "", "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "category": "AUTOMATED_FUEL_DISPENSERS", "categoryCode": "5542", "countryCodeAlpha3": "USA", "description": "KWIK TRIP 123456", "merchantId": "", "name": "My Awesome Fuel" }, "partial": true, "paymentCardSnapshot": { "createdAt": "2024-02-14T19:40:22.954Z", "paymentCardCurrent": { "id": "" }, "status": "ACTIVE" }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "terminalSupportsPartialApproval": true }, "postalCodeResponseCode": "NOT_PROVIDED", "requestedAmount": { "currencyCode": "USD", "value": 100, "decimalPlaces": 2 }, "responseCode": "APPROVED_FOR_PARTIAL_AMOUNT", "transactionId": "", "transactionProcessingType": "GOODS_AND_SERVICES" } } }, "extensions": { "signatureTimestamp": 1707939629312 } } ```
Example payload: PAYMENT_CARD_AUTHORIZATION_AND_CLEAR_APPROVED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-02-14T19:45:09.082Z", "expiresAt": "2024-03-15T19:45:09.082Z", "id": "", "name": "PAYMENT_CARD_AUTHORIZATION_AND_CLEAR_APPROVED", "node": { "__typename": "PaymentCardAuthorizationAndClearApprovedEvent", "accountHolderId": "", "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "a72be1cc26ea444697b8fa171f6bab6f" }, "approvedAmount": { "currencyCode": "USD", "value": 1000, "decimalPlaces": 2 }, "avsResponseCode": "NOT_PROVIDED", "cardId": "", "createdAt": "2024-02-14T19:45:04.386Z", "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 49930000, "decimalPlaces": 2 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 50000000, "decimalPlaces": 2 }, "cvvResponseCode": "NOT_PROVIDED", "financialAccountId": "", "id": "", "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "Redmond", "postalCode": "98053", "region": "WA" }, "category": "AUTOMATED_CASH_DISBURSE", "categoryCode": "6011", "countryCodeAlpha3": "USA", "description": "HIGHNOTE SF CA US 1234", "merchantId": "1234567890", "name": "HIGHNOTE_PLATFORM 1234" }, "paymentCardSnapshot": { "createdAt": "2024-02-14T19:45:04.386Z", "paymentCardCurrent": { "id": "" }, "status": "ACTIVE" }, "pointOfServiceDetails": { "category": "AUTOMATED_TELLER_MACHINE", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "panEntryMode": "INTEGRATED_CIRCUIT_CARD", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "UNATTENDED", "terminalSupportsPartialApproval": false }, "postalCodeResponseCode": "NOT_PROVIDED", "requestedAmount": { "currencyCode": "USD", "value": 1000, "decimalPlaces": 2 }, "fees": [ { "requestedFeeAmount": { "currencyCode": "USD", "value": 250, "decimalPlaces": 2 }, "approvedFeeAmount": { "currencyCode": "USD", "value": 250, "decimalPlaces": 2 }, "transactionFeeType": "SURCHARGE" } ], "responseCode": "APPROVED", "transactionId": "", "transactionProcessingType": "CASH" } } }, "extensions": { "signatureTimestamp": 1707939909559 } } ```
Example payload: PAYMENT_CARD_CLEARED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-02-14T19:44:18.646Z", "expiresAt": "2024-03-15T19:44:18.647Z", "id": "", "name": "PAYMENT_CARD_CLEARED", "node": { "__typename": "PaymentCardClearedEvent", "accountHolderId": "", "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "38082a7f771345ce989e4574ff3252e4" }, "approvedAmount": { "currencyCode": "USD", "value": 10000, "decimalPlaces": 2 }, "avsResponseCode": "NOT_PROVIDED", "cardId": "", "createdAt": "2024-02-14T19:44:18.148Z", "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 49930000, "decimalPlaces": 2 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 50000000, "decimalPlaces": 2 }, "cvvResponseCode": "MATCH", "financialAccountId": "", "id": "", "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "category": "AUTOMATED_FUEL_DISPENSERS", "categoryCode": "5542", "countryCodeAlpha3": "USA", "description": "The awesomest awesome fuel dispensers", "merchantId": "Merchant Id", "name": "My Awesome Fuel" }, "partial": true, "paymentCardSnapshot": { "createdAt": "2024-02-14T19:44:18.148Z", "paymentCardCurrent": { "id": "" }, "status": "ACTIVE" }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "terminalSupportsPartialApproval": true }, "postalCodeResponseCode": "NOT_PROVIDED", "requestedAmount": { "currencyCode": "USD", "value": 10000, "decimalPlaces": 2 }, "responseCode": "APPROVED", "transactionId": "", "transactionProcessingType": "GOODS_AND_SERVICES" } } }, "extensions": { "signatureTimestamp": 1707939859969 } } ```
Example payload: PAYMENT_CARD_ADJUSTMENT ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-06-10T14:22:08.312Z", "id": "", "name": "PAYMENT_CARD_ADJUSTMENT", "node": { "__typename": "PaymentCardAdjustmentEvent", "accountHolderId": "", "approvedAmount": { "currencyCode": "USD", "value": 500, "decimalPlaces": 2 }, "cardId": "", "createdAt": "2024-06-10T14:22:07.891Z", "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 49935000, "decimalPlaces": 2 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 50000000, "decimalPlaces": 2 }, "financialAccountId": "", "id": "", "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94107", "region": "CA" }, "category": "BAKERIES", "categoryCode": "5462", "countryCodeAlpha3": "USA", "merchantId": "", "name": "HIGHNOTE PLATFORM" }, "paymentCardSnapshot": { "createdAt": "2024-06-10T14:22:07.891Z", "paymentCardCurrent": { "id": "" }, "status": "ACTIVE" }, "pointOfServiceDetails": { "category": "ECOMMERCE", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "panEntryMode": "INTEGRATED_CIRCUIT_CARD", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "terminalSupportsPartialApproval": true }, "responseCode": "APPROVED", "transactionId": "", "transactionProcessingType": "ADJUSTMENT_CREDIT" } } }, "extensions": { "signatureTimestamp": 1718025729105 } } ```
Example payload: PAYMENT_CARD_ENHANCED_DATA_RECEIVED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2023-04-01T00:55:18.566Z", "id": "", "name": "PAYMENT_CARD_ENHANCED_DATA_RECEIVED", "node": { "__typename": "PaymentCardEnhancedDataEvent", "accountHolderId": "", "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "63e2d6aaaef24f5d9cab99af689c5a21" }, "cardId": "cd_b47701ed1fe71b98acb2d67c710a912d", "createdAt": "2023-04-01T00:55:16.495Z", "financialAccountId": "", "id": "", "responseCode": "APPROVED", "transactionId": "", "transactionProcessingType": "GOODS_AND_SERVICES" } } }, "extensions": { "signatureTimestamp": 1680310520414 } } ```
Example payload: PAYMENT_CARD_VERIFICATION_APPROVED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-05-09T22:27:32.871Z", "id": "", "name": "PAYMENT_CARD_VERIFICATION_APPROVED", "node": { "__typename": "PaymentCardVerificationApprovedEvent", "approvedAmount": { "currencyCode": "USD", "value": 100, "decimalPlaces": 2 }, "avsResponseCode": "NOT_PROVIDED", "createdAt": "2022-05-09T22:27:31.636Z", "cvvResponseCode": "NOT_PROVIDED", "id": "", "financialAccountId": "", "accountHolderId": "", "paymentCardId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "paymentCardSnapshot": { "createdAt": "2024-02-14T19:43:23.039Z", "paymentCardCurrent": { "id": "" }, "status": "ACTIVE" }, "pointOfServiceDetails": { "category": "AUTOMATIC_FUEL_DISPENSER", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": false, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT", "postalCodeResponseCode": "NOT_PROVIDED", "requestedAmount": { "currencyCode": "USD", "value": 100, "decimalPlaces": 2 }, "responseCode": "APPROVED", "transactionId": "" } } }, "extensions": { "signatureTimestamp": 1652135254644 } } ```
## Payroll advance Triggered when a payroll advance repayment completes or a write-off is finalized. | Notification Event Name | Event | Description | | :------------------------------------ | :------------------------------------------------------------------------- | :----------------------------------- | | | Object | Payroll advance repayment completed. | | | Object | Payroll advance write-off completed. | The following response codes are returned from a **complete payroll repayment** status event: | Payment Event Status | Description | | :------------------- | :-------------------------------------------------------------------------------------------------------------- | | | Status indicates that the payroll advance has not been paid | | | The balance of the payroll advance is fully repaid. | | | The balance of the payroll advance is partially repaid. | | | The payroll advance is written off on the Highnote platform because the 3 repayment was reached. |
Example payload: PAYROLL_ADVANCE_REPAYMENT_COMPLETED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-09-14T23:04:17.337Z", "id": "", "name": "PAYROLL_ADVANCE_REPAYMENT_COMPLETED", "node": { "id": "", "employerFinancialAccountId": "", "payrollAdvance": { "advanceAmount": { "currencyCode": "USD", "value": 100000, "decimalPlaces": 2 }, "amountApplied": { "currencyCode": "USD", "value": 10000, "decimalPlaces": 2 }, "amountBefore": { "currencyCode": "USD", "value": 80000, "decimalPlaces": 2 }, "balanceAfter": { "currencyCode": "USD", "value": 70000, "decimalPlaces": 2 }, "id": "", "paymentAdvanceStatus": "PARTIALLY_REPAID", "repaymentAttemptCount": 3 } } } }, "extensions": { "signatureTimestamp": 1663196658157 } } ```
Example payload: PAYROLL_ADVANCE_WRITE_OFF_COMPLETED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-09-14T23:04:27.797Z", "id": "", "name": "PAYROLL_ADVANCE_WRITE_OFF_COMPLETED", "node": { "id": "", "payrollAdvance": { "advanceAmount": { "currencyCode": "USD", "value": 100000, "decimalPlaces": 2 }, "amountApplied": { "currencyCode": "USD", "value": 0, "decimalPlaces": 2 }, "amountBefore": { "currencyCode": "USD", "value": 70000, "decimalPlaces": 2 }, "balanceAfter": { "currencyCode": "USD", "value": 0, "decimalPlaces": 2 }, "id": "", "paymentAdvanceStatus": "WRITTEN_OFF", "repaymentAttemptCount": 3, "writeOffAmount": { "currencyCode": "USD", "value": 70000, "decimalPlaces": 2 } } } } }, "extensions": { "signatureTimestamp": 1663196668260 } } ```
## Physical card order Triggered when a physical payment card or group order ships or fails to ship. | Notification Event Name | Event | Description | | :---------------------------------------------- | :-------------------------------------------------------------------------------- | :------------------------------------------------- | | | Object | Physical payment card shipped. | | | Object | Physical payment card shipment failed. | | | Object | Physical payment card group order shipped. | | | Object | Physical payment card group order shipment failed. |
Example payload: PHYSICAL_PAYMENT_CARD_SHIPPED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-04-08T00:57:05.589Z", "id": "", "name": "PHYSICAL_PAYMENT_CARD_SHIPPED", "node": { "__typename": "PhysicalPaymentCardShippedEvent", "createdAt": "2022-04-08T00:56:46.242Z", "id": "", "orderState": { "status": "SHIPPED" }, "paymentCardId": "", "updatedAt": "2022-04-08T00:57:03.588Z" } } }, "extensions": { "signatureTimestamp": 1649379429987 } } ```
Example payload: PHYSICAL_PAYMENT_CARD_GROUP_ORDER_SHIPPED ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-10-25T22:28:02.991Z", "id": "", "name": "PHYSICAL_PAYMENT_CARD_GROUP_ORDER_SHIPPED", "node": { "__typename": "PhysicalPaymentCardGroupOrderShippedEvent", "cardCount": 1, "cardProductId": "", "createdAt": "2022-10-25T22:24:53.923Z", "groupOrderState": { "status": "SHIPPED" }, "id": "", "updatedAt": "2022-10-25T22:27:58.019Z" } } }, "extensions": { "signatureTimestamp": 1666736885597 } } ```
## Provision account holder Triggered during the automated account holder provisioning workflow. Each workflow action progresses through the same statuses: INITIATED, IN_PROGRESS, COMPLETED, ERROR, or NOT_COMPLETED. All provision account holder events return an [](/docs/api-reference/object#AccountHolderProvisioning) event object. ### Workflow status | Notification Event Name | Description | | :------------------------------------- | :------------------------------------------ | | | Provisioning workflow initiated. | | | Provisioning workflow in progress. | | | Provisioning workflow completed. | | | Provisioning workflow encountered an error. | | | Provisioning workflow rejected. | ### Create application | Notification Event Name | Description | | :---------------------------------------------------------- | :---------------------------------------------- | | | Create application action initiated. | | | Create application action in progress. | | | Create application action completed. | | | Create application action encountered an error. | | | Create application action did not complete. | ### Issue financial account | Notification Event Name | Description | | :--------------------------------------------------------------- | :--------------------------------------------------- | | | Issue financial account action initiated. | | | Issue financial account action in progress. | | | Issue financial account action completed. | | | Issue financial account action encountered an error. | | | Issue financial account action did not complete. | ### Issue payment card | Notification Event Name | Description | | :---------------------------------------------------------- | :---------------------------------------------- | | | Issue payment card action initiated. | | | Issue payment card action in progress. | | | Issue payment card action completed. | | | Issue payment card action encountered an error. | | | Issue payment card action did not complete. | ### Link external bank account | Notification Event Name | Description | | :------------------------------------------------------------------ | :------------------------------------------------------ | | | Link external bank account action initiated. | | | Link external bank account action in progress. | | | Link external bank account action completed. | | | Link external bank account action encountered an error. | | | Link external bank account action did not complete. | ### Notify provider | Notification Event Name | Description | | :------------------------------------------------------- | :------------------------------------------- | | | Notify provider action initiated. | | | Notify provider action in progress. | | | Notify provider action completed. | | | Notify provider action encountered an error. | | | Notify provider action did not complete. | ### Register Visa payable funding account | Notification Event Name | Description | | :----------------------------------------------------------------------------- | :----------------------------------------------------------------- | | | Register Visa payable funding account action initiated. | | | Register Visa payable funding account action in progress. | | | Register Visa payable funding account action completed. | | | Register Visa payable funding account action encountered an error. | | | Register Visa payable funding account action did not complete. | ### Set credit limit | Notification Event Name | Description | | :-------------------------------------------------------- | :-------------------------------------------- | | | Set credit limit action initiated. | | | Set credit limit action in progress. | | | Set credit limit action completed. | | | Set credit limit action encountered an error. | | | Set credit limit action did not complete. | ## Report Triggered when an on-demand report completes or fails. All report events return a [](/docs/api-reference/object#Report) event object. | Notification Event Name | Description | | :---------------------- | :----------------------------- | | | Report completed successfully. | | | Report failed. | ## RTP transfers Real-Time Payment (RTP) transfers move funds between accounts in real time. Highnote organizes RTP transfers by initiator: Highnote initiates **"originated"** RTP transfers, and external parties initiate **"non-originated"** RTP transfers. The following table describes each RTP transfer type and its direction of money movement. For more, see the Transfer Funds API docs. | Type | Direction | Description | | :-------------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------ | | Originated RTP transfer | Outbound | Highnote initiates a real-time payment to push funds from a Highnote financial account to an external bank account. | | Non-originated RTP transfer | Inbound | An external party initiates a real-time payment to push funds into a Highnote financial account. | The following table describes _some_ of the fields you may see in an RTP notification event response. For a full list of response fields, refer to the API Reference. | Field | Description | | :-------------------- | :------------------------------------------------------------------------------------------------------------- | | | The current status of the RTP transfer, such as , , , , or | | | The origin of the funds, including the and the source | | | The destination of the funds, including the and the destination | | | Additional bank transfer details, including | | | When the transfer has failed, the reason for the failure, such as or | A node in an RTP notification event carries , , and only. It never carries , even when Highnote has resolved a name for the receiving bank. Query the RTP transfer by ID to read that field. See Receiving institution name. ### Originated RTP transfer Originated RTP transfer notifications are triggered when a real-time payment is initiated from within the Highnote platform. All originated RTP transfer events return an [](/docs/api-reference/object#OriginatedRtpTransferEvent) event object. The following notification events are available for originated RTP transfers: | Notification Event Name | Description | | :----------------------------------------- | :------------------------------------------------------------- | | | RTP transfer initiated. | | | RTP transfer is pending. | | | RTP transfer is processing. | | | RTP transfer completed and reflected on the financial account. | | | RTP transfer failed. |
Example payload: ORIGINATED_RTP_TRANSFER_INITIATED_EVENT ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-08-26T18:40:34.999Z", "expiresAt": "2024-09-25T18:40:34.999Z", "id": "", "name": "ORIGINATED_RTP_TRANSFER_INITIATED_EVENT", "node": { "__typename": "OriginatedRtpTransferEvent", "createdAt": "2024-08-26T18:40:32.481Z", "failureReason": null, "id": "", "status": "INITIATED", "rtpTransfer": { "__typename": "OriginatedRtpTransfer", "bankTransferDetails": { "__typename": "RtpTransferBankTransferDetails", "paymentRelatedInformation": "Invoice #12345 - October 2024 payment" }, "createdAt": "2024-08-26T18:40:32.481Z", "destination": { "__typename": "RtpTransferDestination", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 15000 }, "node": { "__typename": "USBankAccount", "id": "" } }, "failureReason": null, "id": "", "source": { "__typename": "RtpTransferSource", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 15000 }, "node": { "__typename": "FinancialAccount", "id": "" } }, "status": "INITIATED", "updatedAt": "2024-08-26T18:40:32.491Z" } } } }, "extensions": { "signatureTimestamp": 1724697637357 } } ```
### Non-originated RTP transfer Non-originated RTP transfer notifications are triggered when a real-time payment is initiated from outside the Highnote platform by a third party. All non-originated RTP transfer events return a [](/docs/api-reference/object#NonOriginatedRtpTransferEvent) event object. The following notification events are available for non-originated RTP transfers: | Notification Event Name | Description | | :-------------------------------------------- | :---------------------- | | | RTP transfer received. | | | RTP transfer completed. | | | RTP transfer failed. |
Example payload: NON_ORIGINATED_RTP_TRANSFER_RECEIVED_EVENT ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-08-26T18:41:31.421Z", "expiresAt": "2024-09-25T18:41:31.421Z", "id": "", "name": "NON_ORIGINATED_RTP_TRANSFER_RECEIVED_EVENT", "node": { "__typename": "NonOriginatedRtpTransferEvent", "createdAt": "2024-08-26T18:41:29.208Z", "failureReason": null, "id": "", "status": "RECEIVED", "rtpTransfer": { "__typename": "NonOriginatedRtpTransfer", "bankTransferDetails": { "__typename": "RtpTransferBankTransferDetails", "paymentRelatedInformation": "Invoice #67890 - October 2024 payment" }, "createdAt": "2024-08-26T18:41:29.208Z", "destination": { "__typename": "RtpTransferDestination", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 25000 }, "node": { "__typename": "FinancialAccount", "id": "" } }, "failureReason": null, "id": "", "source": { "__typename": "RtpTransferSource", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 25000 }, "node": { "__typename": "USBankAccount", "id": "" } }, "status": "RECEIVED", "updatedAt": "2024-08-26T18:41:29.554Z" } } } }, "extensions": { "signatureTimestamp": 1724697692414 } } ```
## Unified funds transfer Triggered during the lifecycle of a Unified Funds Transfer (single-call money movement via the Transfer Funds API). Instant network transfer events return an [](/docs/api-reference/object#InstantNetworkTransfer) event object. Unified funds transfer events return a [](/docs/api-reference/object#UnifiedFundsTransfer) event object. | Notification Event Name | Description | | :----------------------------------------- | :---------------------------------- | | | Instant network transfer initiated. | | | Instant network transfer completed. | | | Instant network transfer failed. | | | Unified funds transfer initiated. | | | Unified funds transfer completed. | | | Unified funds transfer failed. | ## Wire transfer Wire transfers move funds between Highnote financial accounts and external bank accounts via the Fedwire network. See Wire Transfers for more. Wire transfer events return a [](/docs/api-reference/object#WireTransfer) event object. Highnote emits a single wire transfer event, triggered when an incoming wire transfer crediting a Highnote financial account has completed: | Notification Event Name | Description | | :------------------------------ | :-------------------------------------------------------------------------- | | | Triggered when a wire transfer crediting a financial account has completed. | To monitor a wire transfer that has not completed, query the node for its current and . Notification events are _not_ emitted for the other [](/docs/api-reference/enum#WireTransferStatus) values: , , . See Find wire transfers.
Example payload: WIRE_TRANSFER_COMPLETED_EVENT ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2024-08-26T18:42:11.312Z", "expiresAt": "2024-09-25T18:42:11.312Z", "id": "", "name": "WIRE_TRANSFER_COMPLETED_EVENT", "node": { "__typename": "WireTransfer", "amount": { "__typename": "Amount", "currencyCode": "USD", "decimalPlaces": 2, "value": 250000 }, "financialAccount": { "__typename": "FinancialAccount", "id": "" }, "id": "", "status": "COMPLETED" } } }, "extensions": { "signatureTimestamp": 1724697731542 } } ```
--- URL: https://docs.highnote.com/docs/developers/events/fetching-events Title: Fetching Events Section: Developers Description: Fetch, monitor, and replay notification events. Events are stored for 30 days and can be filtered by type, status, and date. ## Overview The Highnote platform tracks all events across your platform, allowing you to fetch, monitor, and replay events. Events are also used to create notifications. Note the following about events: - All events are stored for 30 days. - Events can be replayed to trigger failed notifications. For more information, see Replay Events. You can view events using the Highnote API or dashboard. This guide provides an overview of fetching and viewing events using the Highnote API. For an overview of monitoring events using the dashboard, see Monitor events. ## Fetch all events You can fetch _all events_ using the following query. This returns a paginated list of results, defaulting to 20 entries: ## Fetch individual events You can fetch individual events using the following query and the notification event as an input: ### GraphQL: NotificationEvents Query: query NotificationEvents($after: String, $first: Int) { notificationEvents(after: $after, first: $first) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { node { ... on NotificationEvent { __typename id createdAt expiresAt name node { __typename ... on Node { id } ... on AuthorizationEvent { id approvedAmount { value } } } } } } } } Variables: { "first": 20 } Expected Result: { "data": { "notificationEvents": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "start-cursor", "endCursor": "end-cursor" }, "edges": [ { "node": { "id": "", "createdAt": "2021-11-19T19:13:02.778Z", "expiresAt": "2021-12-19T19:13:02.778Z", "name": "AUTHORIZATION_CREATED", "node": { "id": "", "approvedAmount": { "value": 20000 }, "__typename": "AuthorizationEvent" } } }, { "node": { "id": "", "createdAt": "2021-11-19T19:12:25.912Z", "expiresAt": "2021-12-19T19:12:25.912Z", "name": "AUTHORIZATION_CREATED", "node": { "id": "", "approvedAmount": { "value": 12000 }, "__typename": "AuthorizationEvent" } } } ] } } } ### GraphQL: Event Query: query Event($id: ID!) { node(id: $id) { __typename ... on NotificationEvent { __typename id createdAt expiresAt name node { ... on Node { id } ... on AuthorizationEvent { id approvedAmount { value } } } } } } Variables: { "id": "" } Expected Result: { "node": { "__typename": "NotificationEvent", "id": "", "createdAt": "2022-03-03T15:46:44.944Z", "expiresAt": "2022-04-03T15:46:44.944Z", "name": "AUTHORIZATION_CREATED", "node": { "id": "", "approvedAmount": { "value": 0 } } } } --- URL: https://docs.highnote.com/docs/developers/events/notifications Title: Notifications Section: Developers Description: Set up webhook and email notifications to monitor and respond to events in your integration. ## Overview Highnote supports notifications that let you monitor and respond to events in your Highnote integration. Common use cases are: - Interacting with asynchronous onboarding flows - Monitoring changes and alerts - Transferring data into third-party systems ## Key concepts Understanding the notification architecture helps you implement an efficient event monitoring system. Here's a breakdown of the key concepts: - **Event Types**: Categories of events that occur within your Highnote integration. Examples include authorization events, card issuance events, and system notifications like webhook activation. - **Notification Targets**: Destinations that receive notifications, primarily webhook endpoints in Highnote's implementation. These are HTTP endpoints that receive event data when specific events occur. - **Subscriptions**: Relationships between event types and notification targets. When you "subscribe" a target to an event type, you're configuring that target to receive notifications when events of that type occur. ## Change management Notification schemas can change over time. When new attributes are added, Highnote will notify you seven days before release. When a breaking change occurs, Highnote will notify you 90 days before release to ensure ample time for any necessary updates. To maintain uninterrupted service, we recommend building robust and resilient integrations that can adapt to these changes. ## Webhooks Highnote notifications use webhooks to deliver events to your system. Refer to the following guidelines for using webhooks: - Webhooks can be managed using the Highnote API or the dashboard - You can have up to 50 active webhooks at a time - You can configure specific events to be delivered to each webhook Notification events are sent as POST requests with JSON bodies. Highnote will send the following headers on each request: - : - : The result of computing an HMAC 256 signature of the request body - : This will be sent in cases where the event is being manually re-delivered - : ## Best practices We recommend using the following best practices to ensure your webhooks remain secure and maintain functionality with your integration. ### Rotate signing keys The signing key used to verify payloads is modifiable using the mutation. Refer to the following guidelines for rotating signing keys: - We recommend rotating signing keys periodically or when you suspect a compromise to keep them secure. - When rotating signing keys, multiple keys become active for the notification endpoint. The old key expires in 24 hours after rotating a signing key. - Before the old key expires, signatures for all keys are sent in the notification payload. - A notification target can have a maximum of five active keys at a time. Use the following mutation to rotate a signing secret: ### Verify payloads You can ensure events pushed to your webhook are coming from Highnote by inspecting the HTTP header. The header contains a comma-separated list of signatures. Usually, the list will only contain one item unless you are rolling your signing key. To verify the signature with the payload you received refer to the following steps: 1. Sign the received payload using your language-specific HMAC signing library and the signing key secret for your notification target. 2. Once you have a local signature, extract the value of the and compare the two using a timing-safe equals operation. The following code sample displays how this process would look in node.js: ```ts function verifySignature( secret: string, payload: string, remoteSignature: string, ): boolean { const localSignature = createHmac("sha256", secret) .update(payload) .digest("hex"); return timingSafeEqual( Buffer.from(remoteSignature), Buffer.from(localSignature), ); } ``` If there is equality between the signatures, verify the timestamp of the event is within a certain threshold. The signature timestamp can be found in the payload at , with the value being the number of milliseconds since Unix epoch. ```ts function within15minutes(payload: string): boolean { const jsonPayload = JSON.parse(payload); const { signatureTimestamp } = jsonPayload.extensions; return Date.now() - signatureTimestamp <= 15 * 60 * 1000; } ``` ### Handle out-of-order delivery Webhook notifications can arrive out of order. See Out-of-order delivery for the failure mode and how to handle money movement and reconciliation. ### Handle duplicate events Webhook endpoints may receive duplicate events. To prevent processing duplicate events, you should implement idempotent event handling. This can be done by maintaining a log of all processed events and not processing events that have already been logged. ### Process events asynchronously Asynchronous queues help you handle multiple events at a pace that fits your system's capacity. Set up your event handler to use an asynchronous queue for managing incoming notification events. Processing events synchronously can lead to scalability problems and overloading of your webhook endpoints, especially during high-traffic time periods. ## Out-of-order delivery Highnote webhook notifications signal that something happened on the platform. They are not authoritative — notifications are not guaranteed to arrive in the order events occurred, and webhook timestamps are not reliable enough to reconstruct event order from the payload. **Do not use webhook arrival order to drive money movement (refunds, credits, debits) or financial reconciliation.** For ordering-sensitive and money-critical logic, use one of these authoritative sources instead: - **Data Share** — near-real-time replication of your Highnote data into Snowflake. Query the canonical state on whatever cadence you need. - **Reports** — batch financial reports for daily reconciliation and end-of-period truth. Webhook notifications are still the right pattern for _event-driven UX_ (for example, refreshing a transaction list the moment a notification fires). They are the wrong pattern for moving money based on what events have or haven't fired. ### Worked example Consider a card transaction: 1. Cardholder buys for **$300**. Highnote sends an authorization webhook. 2. The merchant clears the transaction. Highnote sends a clearing webhook for **$300**. The cardholder's account is debited. 3. The merchant issues a refund after clearing (a **post-clearing reversal**). Highnote sends a reversal webhook for **$300**. The cardholder should be credited back. If your endpoint receives these notifications **out of order**: | Order arrived | Event | Wrong response | Correct response | | :------------ | :------------ | :-------------------------------------------------- | :------------------------------------------------------------------------------------- | | 1st | Reversal $300 | Treat as an authorization release; release the hold | Treat as a refund — check the field, or wait for the clearing | | 2nd | Clearing $300 | Debit the cardholder's account | Debit the cardholder's account | The cardholder is now **debited $300 with no refund credit**, because the reversal was processed as an authorization release. The fix is not to reconstruct order from webhooks (which has its own race conditions). Use Data Share or Reports to read the authoritative state of the transaction, and drive money movement from that. ### Fallback on reversal events If you must process webhooks for money movement and cannot use Data Share or Reports, check the field on reversal events: - — clearing has already happened. Process the reversal as a **refund** (credit the cardholder). - — no clearing yet. Process as a standard authorization release (release the hold). This handles the reversal-after-clearing race but does not solve the broader class of ordering issues. For everything else, use Data Share or Reports. ## Adding a webhook Adding an email to a webhook target is only supported in the Live environment. If you attempt to add an email to a webhook in the Test environment, you will get an . You can add webhooks using the mutation. For more information on this mutation, see addWebhookNotificationTarget in the API reference. The requirements for an HTTP webhook are: - The endpoint must be served via HTTPS - Must return a status code. All other status codes will be considered a delivery failure and the request will be retried The following process outlines how a webhook is verified and activated: 1. When a webhook is created, the status updates to . 2. Highnote delivers a event to your webhook, which is a test event. 3. Upon receiving a response to the test event, the status updates to . 4. If the webhook does not return a response, the status remains in . You can attempt to activate the webhook using the mutation. This process is outlined in the following graphic: For testing, if you do not have a server, you can use webhook.site, requestbin, or pipedream. _Do not use these services for your production webhooks._ Use the following mutation to add a webhook. You can choose to add an email to your webhook target to receive deactivation emails by including the field in your query. Adding an email to a webhook target is _optional_ and only supported in the Live environment: ## Updating a subscription Subscriptions are established when you create a webhook, but you can update an existing webhook with the following mutations: - [](/docs/api-reference/mutation#addSubscriptionsToNotificationTarget) lets you add new event type subscriptions to an existing notification target. - [](/docs/api-reference/mutation#removeSubscriptionsFromNotificationTarget) lets you remove event type subscriptions from an existing notification target. ### Add Subscriptions to Notification Use the following mutation to add one or more subscriptions to an existing webhook or other application notification target: ### Remove Subscriptions from Notification Use the following mutation to remove one or more subscriptions from an existing webhook or other application notification target: ### Test updating subscriptions You can test the creation and updating of subscriptions with https://webhook.site: #### Create a webhook with default subscription 1. Go to https://webhook.site to automatically create a usable webhook URL for testing. 2. Click your unique URL to copy it. 3. Go to Add a webhook and run the mutation with your webhook URL as the input. 4. Copy the target from the results and temporarily store for safe keeping. 5. Note the subscription to events. 6. Go to the Dashboard and find your new webhook under Developers > Notifications. You should see an active webhook that is subscribed to . #### Add a subscription 1. Go to Add subscriptions 2. Add you webhook URL (prefixed by ) as the input for the notification . 3. Note the list of new subscriptions to: 4. Run the mutation and view the dashboard to see the change. Your webhook should now be subscribed to , and . #### Remove a subscription 1. Go to Remove subscriptions . 2. Add you webhook URL as the input for . 3. Unsubscribe from existing event, . 4. Run the mutation and view the dashboard to see the change. Your webhook should only be subscribed to and . ## Retries and failures A notification delivery is considered a failure if: - Highnote does not receive a 2xx HTTP status code in the response - If there is no response within 10 seconds, which is considered a timeout Highnote handles notification failures and retries as follows: | Event | Retries in Live environment | Retries in Test environment | | :---------------------- | :---------------------------------- | :-------------------------- | | Notification activation | Two within a minute | Two within a minute | | All other notifications | Nine times with exponential backoff | Three times | If a notification fails all attempts, we will disable the webhook target. If you have an email address configured for your webhook, you will receive an email notifying you of the deactivation. You must manually reactivate it through the API or dashboard. If your webhook endpoint is down or if you miss any events, you can retrieve them via the API. ### View delivery attempts Use the following query to view delivery attempts. If no target is enabled for the event type, the value will be : ### Retrieve failed notifications You can use the following query to retrieve failed notifications. This is useful when your webhook endpoint is down and, as a result, deactivated. For more information on retries and failures, see Retries and Failures. ### Replay events Once you have retrieved any failed notification events, you can use the following mutation to replay them or manually re-deliver events to your webhooks: ## Rename a target You can update the name of a notification target without affecting the delivery of events using the following mutation: ## Add email to existing target Adding an email to a webhook target is only supported in the Live environment. If you attempt to add an email to a webhook in the Test environment, you will get an . Emails are used to receive deactivation emails. You can use the following mutation to add an email to an existing webhook target. Adding an email to a webhook target is _optional_ and only supported in the Live environment: ## Remove email from existing target Removing an email to a webhook target is only supported in the Live environment. If you attempt to add an email to a webhook in the Test environment, you will get an . You can use the following mutation to remove an email from a webhook target: ## Delete a target Deleting a notification target may impact the functionality of your Highnote integration and cannot be reversed. Notification targets may be deleted. Deleting a target will stop the delivery of all events because the notification target will no longer exist. Use the following mutation to remove a notification target: ## Expiration of deactivated targets Once a target is deactivated, any attempts to send notifications to the target will return an error status. A webhook with a status for more than 30 days is considered expired. It will be deleted and no longer visible. ### GraphQL: RotateNotificationTargetSigningKey Query: mutation rotateNotificationTargetSigningKey( $input: RotateNotificationTargetSigningKeyInput! ) { rotateNotificationTargetSigningKey(input: $input) { ... on WebhookNotificationTarget { id status signingKeys { id secret createdAt expiresAt } } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "rotateNotificationTargetSigningKey": { "id": "" } } } ### GraphQL: AddWebhookNotificationTarget Query: mutation AddWebhookNotificationTarget( $input: AddWebhookNotificationTargetInput! ) { addWebhookNotificationTarget(input: $input) { __typename ... on WebhookNotificationTarget { id name uri subscriptions email createdAt status signingKeys { id secret } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "name": "My Webhook", "uri": "https://webhook.site", "subscriptions": [ "CARD_PRODUCT_APPLICATION_APPROVED" ], "email": "notifications-alerts@mycompany.com" } } Expected Result: { "data": { "addWebhookNotificationTarget": { "__typename": "WebhookNotificationTarget", "id": "", "name": "My Webhook", "uri": "https://webhook.site", "subscriptions": [ "CARD_PRODUCT_APPLICATION_APPROVED" ], "email": "notifications-alerts@mycompany.com", "createdAt": "2021-11-19T19:16:23.477Z", "status": "PENDING_VERIFICATION", "signingKeys": [ { "id": "some-id", "secret": "some_secret" } ] } } } ### GraphQL: AddSubscriptionsToNotificationTarget Query: mutation AddSubscriptionsToNotificationTarget( $input: AddSubscriptionsToNotificationTargetInput! ) { addSubscriptionsToNotificationTarget(input: $input) { ... on WebhookNotificationTarget { id name subscriptions status } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "targetId": "", "subscriptions": [ "PAYMENT_CARD_AUTHORIZATION_DECLINED", "PAYMENT_CARD_AUTHORIZATION_REVERSED" ] } } Expected Result: { "data": { "addSubscriptionsToNotificationTarget": { "id": "", "name": "My Webhook", "subscriptions": [ "CARD_PRODUCT_APPLICATION_APPROVED", "PAYMENT_CARD_AUTHORIZATION_DECLINED", "PAYMENT_CARD_AUTHORIZATION_REVERSED" ], "status": "ACTIVE" } } } ### GraphQL: RemoveSubscriptionsFromNotificationTarget Query: mutation RemoveSubscriptionsFromNotificationTarget( $input: RemoveSubscriptionsFromNotificationTargetInput! ) { removeSubscriptionsFromNotificationTarget(input: $input) { ... on WebhookNotificationTarget { id name subscriptions status } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "targetId": "", "subscriptions": [ "PAYMENT_CARD_AUTHORIZATION_DECLINED" ] } } Expected Result: { "data": { "removeSubscriptionsFromNotificationTarget": { "id": "", "name": "My Webhook", "subscriptions": [ "CARD_PRODUCT_APPLICATION_APPROVED", "PAYMENT_CARD_AUTHORIZATION_REVERSED" ], "status": "ACTIVE" } } } ### GraphQL: WebhookNotificationTarget Query: query WebhookNotificationTarget($id: ID!) { node(id: $id) { __typename ... on WebhookNotificationTarget { status id deliveryAttempts { __typename pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id uri response { httpStatusCode } deliveryAttemptStatus createdAt event { name id } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WebhookNotificationTarget", "status": "ACTIVE", "id": "", "deliveryAttempts": { "__typename": "DeliveryAttemptConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "some-cursor", "endCursor": "some-cursor" }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "DeliveryAttempt", "id": "", "uri": "https://webhook.site/", "response": { "httpStatusCode": 200 }, "deliveryAttemptStatus": "SUCCESS", "createdAt": "2021-12-20T18:42:51.805Z", "event": { "name": "NOTIFICATION_ACTIVATION", "id": "" } } } ] } } } } ### GraphQL: GetUnsuccessfulWebhookNotificationTargetEvents Query: query GetUnsuccessfulWebhookNotificationTargetEvents( $id: ID! $filterBy: WebhookNotificationTargetEventFilterInput ) { node(id: $id) { __typename ... on WebhookNotificationTarget { webhookNotificationTargetEvents(filterBy: $filterBy) { __typename pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { __typename cursor node { __typename hasSuccessfulDelivery event { __typename id name } } } } } } } Variables: { "id": "", "filterBy": { "hasSuccessfulDelivery": false, "name": [ "PAYMENT_CARD_AUTHORIZATION_APPROVED" ], "eventCreatedAt": { "greaterThan": "2024-03-07T00:37:07.175Z" } } } Expected Result: { "data": { "node": { "__typename": "WebhookNotificationTarget", "webhookNotificationTargetEvents": { "__typename": "WebhookNotificationTargetEventConnection", "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "__typename": "WebhookNotificationTargetEventEdge", "cursor": "some-cursor", "node": { "__typename": "WebhookNotificationTargetEvent", "hasSuccessfulDelivery": false, "event": { "__typename": "NotificationEvent", "id": "", "name": "PAYMENT_CARD_AUTHORIZATION_APPROVED" } } }, { "__typename": "WebhookNotificationTargetEventEdge", "cursor": "some-cursor", "node": { "__typename": "WebhookNotificationTargetEvent", "hasSuccessfulDelivery": false, "event": { "__typename": "NotificationEvent", "id": "", "name": "PAYMENT_CARD_AUTHORIZATION_APPROVED" } } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: ReplayNotificationEvent Query: mutation ReplayNotificationEvent($input: ReplayNotificationEventInput!) { replayNotificationEvent(input: $input) { ... on NotificationEvent { __typename id node { __typename ... on Node { id } ... on AuthorizationEvent { id approvedAmount { value } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "notificationEventId": "" } } Expected Result: { "data": { "replayEvent": { "__typename": "NotificationEvent", "id": "", "node": { "__typename": "AuthorizationEvent", "id": "", "approvedAmount": { "value": 20000 } } } } } ### GraphQL: RenameNotificationTarget Query: mutation RenameNotificationTarget($input: RenameNotificationTargetInput!) { renameNotificationTarget(input: $input) { ... on WebhookNotificationTarget { id name status } } } Variables: { "input": { "targetId": "", "name": "My Updated Webhook" } } Expected Result: { "data": { "renameNotificationTarget": { "id": "", "name": "My Updated Webhook", "status": "ACTIVE" } } } ### GraphQL: SetEmailForNotificationTarget Query: mutation setEmailForNotificationTarget( $input: SetEmailForNotificationTargetInput! ) { setEmailForNotificationTarget(input: $input) { ... on WebhookNotificationTarget { id name uri email subscriptions createdAt status signingKeys { id secret } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "targetId": "", "email": "notification-alerts@mycompany.com" } } Expected Result: { "data": { "setEmailForNotificationTarget": { "__typename": "WebhookNotificationTarget", "id": "", "name": "My Target", "uri": "URL", "subscriptions": [ "PAYMENT_CARD_ACTIVATED", "AUTHORIZED_USER_CARD_PRODUCT_APPLICATION_APPROVED", "CARD_PRODUCT_APPLICATION_APPROVED", "CARD_PRODUCT_APPLICATION_IN_REVIEW", "CARD_PRODUCT_APPLICATION_MANUAL_REVIEW", "CARD_PRODUCT_APPLICATION_DENIED", "CARD_PRODUCT_APPLICATION_CLOSED", "PAYMENT_CARD_TRANSACTION_DISPUTE_CASE_STATUS_INITIATED", "PAYMENT_CARD_TRANSACTION_CHARGEBACK_PROVISIONAL_CREDIT_ISSUED" ], "email": "notification-alerts@mycompany.com" } } } ### GraphQL: RemoveEmailForNotificationTarget Query: mutation RemoveEmailForNotificationTarget( $input: RemoveEmailFromNotificationTargetInput! ) { removeEmailFromNotificationTarget(input: $input) { __typename ... on WebhookNotificationTarget { id name uri subscriptions email } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "targetId": "" } } Expected Result: { "data": { "removeEmailFromNotificationTarget": { "__typename": "WebhookNotificationTarget", "id": "", "name": "My Target", "uri": "https://webhook.site/2c0910c2-4369-4c4c-b7f4-818017215da9", "subscriptions": [ "PAYMENT_CARD_ACTIVATED", "AUTHORIZED_USER_CARD_PRODUCT_APPLICATION_APPROVED", "CARD_PRODUCT_APPLICATION_APPROVED", "CARD_PRODUCT_APPLICATION_IN_REVIEW", "CARD_PRODUCT_APPLICATION_MANUAL_REVIEW", "CARD_PRODUCT_APPLICATION_DENIED", "CARD_PRODUCT_APPLICATION_CLOSED", "PAYMENT_CARD_TRANSACTION_DISPUTE_CASE_STATUS_INITIATED", "PAYMENT_CARD_TRANSACTION_CHARGEBACK_PROVISIONAL_CREDIT_ISSUED" ], "email": null } } } ### GraphQL: RemoveNotificationTarget Query: mutation RemoveNotificationTarget($input: RemoveNotificationTargetInput!) { removeNotificationTarget(input: $input) { ... on WebhookNotificationTarget { id } } } Variables: { "input": { "targetId": "" } } Expected Result: { "data": { "removeNotificationTarget": { "id": "" } } } --- URL: https://docs.highnote.com/docs/developers/sdks/acquiring/checkout-sdk Title: Checkout SDK Section: Developers Description: Embed a drop-in payment card checkout form using the Checkout SDK. Collects card details securely via iframe without PCI data exposure. ## Overview The Checkout SDK is a drop-in solution with some customization options. For a more customizable solution, use the Secure Inputs for Tokenization SDK. The Highnote Checkout SDK is a checkout UI that you can embed in your application or website to accept payment card information. The Checkout SDK uses an iframe that prevents PCI-scoped data from flowing through your system or being accessible to scripts running on your page. This guide explains how to install and use the Checkout SDK. ## Prerequisites 1. A Highnote account 2. A server-side integration using an API key ## Installation The Highnote Checkout SDK follows semver and can be installed using the following: - JavaScript package manager: , , or - Content Delivery Network (CDN) via traditional tag. ### Install by package manager The Checkout SDK supports the following **JavaScript** package managers: , , and . ```sh title="npm" npm i @highnoteplatform/checkout ``` ```sh title="yarn" yarn add @highnoteplatform/checkout ``` ```sh title="pnpm" pnpm add @highnoteplatform/checkout ``` ### Install by CDN To ensure stability and avoid potential issues caused by updates, replace with a specific version number such as . You can install Checkout SDK directly from a content delivery network (CDN) such as JSDelivr. To install the Checkout SDK by tag, add the following to your HTML file: ```html title="Script tag for Checkout SDK" ``` ## Usage To accept payment information, configure elements to hold each field of the checkout iframe as follows: 1. Prepare your HTML 2. Fetch a client token 3. Initialize checkout 4. Charge payment method. ### Prepare your HTML You must provide the Checkout SDK with an HTML selector for the element the checkout UI is rendered in. This element must be mounted before initializing the Checkout SDK. The following example uses a element to mount the Checkout SDK iframe: ```html title="Prepare HTML for checkout" Checkout
``` ### Fetch a client token A payment method tokenization client token can only be used one time. To obtain a client token from your server for the Checkout SDK, use the following mutation: ## Initialize checkout You can initialize the Checkout SDK by using a function. This returns a Promise that contains an object with an method that can be used to remove the checkout UI. The client token and selector you fetched previously must be passed to this function as part of the configuration. Invalid configuration values will return a message. The method passes a object that contains a field. This field is the object. You can call your server endpoint with the to create an authorization using the mutation, supplying the token as the member of the input. Use the following code snippet to initialize checkout: ```js title="Initialize checkout" try { const { unmount } = await renderCheckout({ selector: "#checkoutForm", clientToken: "client token from server", onTokenizeError: (error) => { // handle error from tokenization call }, onTokenizeSuccess: (payload) => { // handle success }, }); } catch (error) { console.log(error.errors); } ``` ### Charge payment method To authorize and capture using the , you must make a server-side call to the mutation and pass the token ID returned when initializing checkout as the input. Use the following mutation to charge a payment method: ## Error handling Refer to the following guidelines for handling Checkout SDK errors: - Input validations are handled implicitly by the SDK and shown as errors inline. - For tokenization errors, the checkout UI will show a default error state. - _Optional_ - Pass an callback to the function if you want to perform custom error handling. ### Error types The following error types are supported for the _Secure Inputs SDK_ for tokenization: | Error | Description | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **InvalidCredentialError** | The provided client token is invalid or expired. Use the in the payload for support and debugging. | | **SecureInputsRequestError** | Represents errors encountered when communicating with the Highnote API, such as an incorrect payment card ID. Use the in the payload for support and debugging. | | **SecureInputsFieldsInputError** | Raised when an invalid configuration is provided at runtime. | | **GenericError** | A generic catchall error. | ## Checkout form The checkout form uses the following _default_ fields: - Card number - Expiration date - CVV/CVC - Postal code Default fields are required to tokenize a payment method and always rendered. ### Additional fields To add additional fields to the checkout form, use the object: - — renders a full name input field - — renders address fields for street address, extended address, city, state, postal code, and country When tokenizing for Instant Network Transfers (INT), and are required for OFAC and AVS compliance checks. Set both to . ### Example The following code snippet is an example configuration for a checkout form: ```js title="Cardholder name setting" const { unmount } = await renderCheckout({ selector: "#checkoutForm", clientToken: "client token from server", additionalFormSections: { cardHolderName: true, billingAddress: true, }, onTokenizeError: (error) => { // handle error from tokenization call }, onTokenizeSuccess: (payload) => { // handle success }, }); ``` ## Using the Live environment By default, the library will make requests against the Test environment. When you are ready to switch to 'live', set the environment configuration option: ```js title="Live Environment" const { unmount } = await renderCheckout({ // Set this to `live` environment: "live", // ... }); ``` ## Lifecycle If you need to unmount payment card fields, use the method on the returned reference. This is useful when you are finished with tokenization, need to "restart" the integration, or navigate to a new view client-side. Using this will ensure the cleanup of any DOM and event handlers. The following code sample provides an example function to unmount fields: ```js titl="Unmounting Fields" const { unmount } = await renderCheckout({ onTokenizeSuccess: async (tokenPayload) => { // Send token to your server to make charge await unmount(); }, // ...config }); ``` ## Content security policy If your application enforces a content security policy, you must set the frame-src header to allow iframes from the Highnote domain: ```html title="Content security policy" Content-Security-Policy: frame-src https://cdn.highnote.com ``` ### GraphQL: GeneratePaymentMethodTokenizationClientToken Query: mutation GeneratePaymentMethodTokenizationClientToken( $input: GeneratePaymentMethodTokenizationClientTokenInput! ) { generatePaymentMethodTokenizationClientToken(input: $input) { __typename ... on ClientToken { expirationDate usage value } } } Variables: { "input": { "permissions": [ "TOKENIZE_PAYMENT_METHOD" ] } } Expected Result: { "data": { "generatePaymentMethodTokenizationClientToken": { "__typename": "ClientToken", "expirationDate": "2024-01-01T00:00:00.000Z", "usage": "UNTIL_EXPIRATION", "value": "TOKEN" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 10, "limit": 60060, "remaining": 60049 } } } ### GraphQL: ChargePaymentTransaction Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentMethodToken": { "id": "" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2024-02-22T17:26:20.474Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:26:20.474Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "978647564526179", "responseCode": { "authorizationCode": "Q5Z539", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } --- URL: https://docs.highnote.com/docs/developers/sdks/acquiring/secure-inputs-sdk-tokenization Title: Secure Inputs SDK for Tokenization Section: Developers Description: Build custom payment card input fields that tokenize card data securely via iframe using the Secure Inputs SDK. ## Overview The Secure Inputs SDK for tokenization is a customizable checkout solution. For a simpler, drop-in solution, use the Checkout SDK. The Highnote Secure Inputs SDK can be used to tokenize payment method details so you can process payments in your application or website. This prevents PCI-scoped data from flowing through your servers or being accessible to scripts running on your page. This guide explains how to install and use the Secure Inputs (Tokenization) SDK. ## Prerequisites 1. A Highnote account 2. A server-side integration using an API key 3. Payment card ID ## Installation The Highnote Secure Inputs SDK follows semver and can be installed using the following: - JavaScript package manager: , , or - Content Delivery Network (CDN) via traditional tag. ### Install by package manager The Secure Inputs SDK supports the following JavaScript package managers: , , and . ```sh title="npm" npm i @highnoteplatform/secure-inputs ``` ```sh title="yarn" yarn add @highnoteplatform/secure-inputs ``` ```sh title="pnpm" pnpm add @highnoteplatform/secure-inputs ``` ### Install by CDN To ensure stability and avoid potential issues caused by updates, replace with a specific version number such as . You can install Secure Inputs SDK directly from a content delivery network (CDN) such as JSDelivr. To install the Secure Inputs SDK by tag, add the following to your HTML file: ```html title="Script tag for Secure Inputs SDK" ``` ## Usage To render secure input fields in your UI, configure elements to hold each field as follows: 1. Prepare your HTML 2. Fetch a client token 3. Initialize secure inputs. ### Prepare your HTML To use the Secure Inputs SDK, you must provide elements for the payment details fields. The following fields are supported for the Secure Inputs SDK for tokenization: - - or and - ```html title="Prepare HTML for Tokenization" Payment Form
``` ### Fetch a client token To obtain a client token from your server for the Secure Inputs SDK, use the mutation. Refer to the following guidelines when generating a payment method tokenization client token: - The client token is only valid for _30 minutes_ but can be used multiple times. - Once a token expires, you must generate a new one. Use the following mutation to generate a payment method tokenization client token: ### Initialize secure inputs The secure inputs library works by injecting an iframe into the payment element to render the appropriate data. You can style the content inside each iframe by passing any combination of styling options. You can initialize the card viewer by using a function. This returns a Promise that contains a reference to the instance. This is useful for lifecycle management and interactions such as field submission. #### Excluded card brands The field accepts four _lowercase_ string values — , ,, . They are distinct from the enum values for [](/docs/api-reference/enum#AcquiringPaymentCardBrand). #### On success The method passes a object that contains a field. This field is the object. You can call your server endpoint with the to create an authorization using the mutation, supplying the token as the member of the input. The following code sample shows how to initialize the Secure Inputs SDK for tokenization. ```js title="Initialize Secure Inputs" const secureInputs = await renderFieldsForTokenization({ clientToken: "client token from server", // Optionally exclude card brands from being accepted excludedCardBrands: ["amex", "discover"], // Specify the individual fields to render data into elements: { cardNumber: { selector: "#card-number", }, expirationDate: { selector: "#expiration-date", }, securityCode: { selector: "#security-code", }, }, onReady: () => { // Callback to indicate that the secure inputs have loaded // and are ready for entry. }, onSuccess: (token) => { // The payment card was successfully tokenized. // Send this to your server for authorization/charge }, onError: (error) => { // Handle errors }, }); ``` ### Additional cardholder data The secure input fields capture PCI-scoped card details (, , ). When calling to tokenize, you can also pass non-PCI cardholder data such as and via the parameter, typed as . When tokenizing for Instant Network Transfers (INT), and are required for OFAC and AVS compliance checks. ```js title="Submit with additional cardholder data" const { submit, unmount } = await renderFieldsForTokenization({ // ...config }); // Collected from your UI const fullName = "Jane Doe"; const billingAddress = { streetAddress: "123 Main St", locality: "San Francisco", region: "CA", postalCode: "94111", countryCodeAlpha3: "USA", }; // Submit with additional data submit({ additionalData: { cardHolder: { fullName, billingAddress, }, }, }); ``` The object accepts the following fields: | Field | Type | Description | | :--------------- | :--------------------- | :------------------------------------------------------------------------------ | | | | The full name as represented on the card. Must be between 1 and 255 characters. | | | | The billing address associated with the card. is required. | ## Error handling The Secure Inputs SDK doesn't render error messages or update your UI inside iframes when errors occur. You must introspect and handle errors accordingly. You can pass an handler to the call. This callback will be invoked whenever an error is raised from the integration. ### Error types The following error types are supported for the Secure Inputs SDK for tokenization: | Error | Description | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **InvalidCredentialError** | The provided client token is invalid or expired. The payload will contain the which can be used for support and debugging. | | **SecureInputsRequestError** | Represents errors encountered when communicating with the Highnote API, such as an incorrect payment card ID. The payload will contain the which can be used for support and debugging. | | **SecureInputsFieldsInputError** | Raised when an invalid configuration is provided at runtime. | | **GenericError** | A generic catchall error. | ### Error examples The following code samples provides examples of secure inputs errors: ```ts title="Examples" const handleError = (error: SecureInputsTokenizationError) => { switch (error.name) { case "SecureInputsRequestError": // Handle errors from tokenization // related to fields or additional data // passed in for tokenization. // See "Error codes" below for all possible codes. console.error(error); break; case "InvalidCredentialError": // Handle invalid/expired credential // Unmount fields, fetch new client token, re-initialize break; default: // Handle generic errors // Try unmount fields, fetch new client token, re-initialize console.error(error); } }; const { unmount, submit } = await renderFieldsForTokenization({ // ... onError: handleError, // ... }); ``` ## Error codes When tokenization fails, the contains a field with one of the following values. The response also includes an array that identifies the specific field that caused the error. Use these codes and paths to surface helpful messages to your users. ```json title="Example error response" { "__typename": "UserError", "errors": [ { "code": "INVALID_SECURITY_CODE", "description": "The security code provided does not match the card type", "errorPath": ["input", "paymentCard", "securityCode"] } ] } ``` ### Card fields | Code | Description | Field | Action | | :---------------------------------- | :-------------------------------------------------------- | :------------------ | :-------------------------------------------------------------- | | | Security code does not match card type. Must be 3 digits. | | Prompt the cardholder to re-enter the security code. | | | Expiration date is in the past. Format: /. | | Prompt the cardholder to enter a valid expiration date. | | | Card number has an invalid length. Must be 15–19 digits. | | Prompt the cardholder to re-enter the card number. | | | The card number does not match any recognized card brand. | | Prompt the cardholder to re-check and re-enter the card number. | ### Token and payment method | Code | Description | Field | Action | | :----------------------------- | :------------------------------------------------------------------------------------ | :------------------ | :------------------------------------------------ | | | Token ID cannot be null. | | Provide a valid token ID in the request. | | | Token ID has an invalid format. Must use the prefix. | | Use a token ID with the prefix. | | | Payment method cannot be null. | | Provide a payment method in the request. | | | Payment method type is invalid or not provided. Valid types: , , . | | Set the payment method type to a supported value. | | | Payment method is not currently supported. Only is supported for tokenization. | | Use as the payment method type. | ### General input Address fields are validated for presence and length only. Invalid address data returns , , or with the specific field identified in . | Code | Description | Field | Action | | :------------------------- | :------------------------------------------------------------------------------------------------------ | :------ | :---------------------------------------------------------------- | | | Input cannot be null. | | Provide a value for the required field indicated in . | | | Input cannot be empty. | | Provide a non-empty value for the field indicated in . | | | Input exceeds maximum character length. Limits: name 255, address lines 512, city 255, title/suffix 10. | | Shorten the input to within the allowed character limit. | | | Name format is invalid. Must be 1–255 characters. | | Enter a name between 1 and 255 characters. | ## Styling options The following styling options are available for use in elements for your secure inputs fields: | Property | Examples | Docs | | :-------------- | :--------------------------------------------------- | :-------------------------------------------------------------------------- | | | , , | MDN Docs | | | , | MDN Docs | | | , , System fonts only | MDN Docs | | | , , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , , | MDN Docs | ### iframe defaults Highnote injects card viewer iframes with the following defaults. Your CSS styling can override each of these: - - (browser default) - (browser default) The document and body inside the frame will have transparent backgrounds and default to , ### Custom fonts The Secure Inputs SDK only supports system fonts. ### Layout The layout of payment card fields in the card viewer is customizable. Highnote injects iframes into the provided container elements, which will inherit the width of the container. You can customize the width and height of the container to accommodate your UI as needed. The following code sample provides an example of custom layout styling: ```html title="Styling" #card-number { margin: 1em; } /* You can target the iframe with a child combinator. */ #card-number > iframe { height: 140px; } ``` ## Using the Live environment By default, the card viewer library will make requests against the Test environment. When you are ready to switch to the Live environment, set the configuration option using the following function call: ```js title="Live Environment" const { unmount } = await renderFieldsForTokenization({ // Set this to `live` environment: "live", // ... }); ``` ## Lifecycle The Secure Inputs SDK's lifecycle consists of unmounting fields. If you need to unmount payment card fields, use the method on the returned reference. This is useful when you need to "restart" the integration, or navigate to a new view client-side. Using this will ensure the cleanup of any DOM and event handlers. The following code sample provides an example function to unmount fields: ```js title="Unmounting Fields" const { submit, unmount } = await renderFieldsForTokenization({ onSuccess: async (token) => { // The payment card was successfully tokenized. // Send this to your server for authorization/charge await unmount(); }, // ...config }); // ... submit(); ``` ## Content security policy If your application enforces a content security policy, you must set the frame-src header to allow iframes from the Highnote domain: ```html title="Content security policy" Content-Security-Policy: frame-src https://cdn.highnote.com ``` ### GraphQL: GeneratePaymentMethodTokenizationClientToken Query: mutation GeneratePaymentMethodTokenizationClientToken( $input: GeneratePaymentMethodTokenizationClientTokenInput! ) { generatePaymentMethodTokenizationClientToken(input: $input) { __typename ... on ClientToken { expirationDate usage value } } } Variables: { "input": { "permissions": [ "TOKENIZE_PAYMENT_METHOD" ] } } Expected Result: { "data": { "generatePaymentMethodTokenizationClientToken": { "__typename": "ClientToken", "expirationDate": "2024-01-01T00:00:00.000Z", "usage": "UNTIL_EXPIRATION", "value": "TOKEN" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 10, "limit": 60060, "remaining": 60049 } } } --- URL: https://docs.highnote.com/docs/developers/sdks/issuing/sardine-processor-api Title: Sardine Processor API Section: Developers Description: Enable Sardine bring-your-own integration for onboarding risk evaluation. Generate client tokens, simulate risk levels, and look up identity risk scores. ## Overview Highnote supports a **bring-your-own Sardine integration model**. Under this approach, you maintain full ownership and management of your Sardine account while allowing Highnote to access your onboarding risk scores. To enable this parent-child relationship, you **must have an active Sardine account and integration** in both the Test and Live environments. In the Test environment, Highnote connects to your Sardine test account, so you must have an active Sardine account before integrating in the Test environment. This setup grants Highnote the necessary permissions to act on behalf of your Sardine account for risk evaluation purposes. ## Sardine application process The application process with the Sardine Processor is asynchronous and does not block the applicant from seeing the Application Submission Screen. The sequence of steps for evaluating an application with Sardine is as follows: 1. **Card Applicant**: Submit Application 2. **Subscriber Frontend**: Initialize Onboarding Flow 3. **Subscriber Backend**: Generate Risk Client Token 4. **Subscriber Frontend**: Initialize Sardine SDK 5. **Subscriber Frontend**: Create Account Holder 6. **Subscriber Backend**: Create US Person Account Holder 7. **Highnote**: Evaluate Account Holder information 8. **Subscriber Backend**: Create Account Holder Card Product Application 9. **Highnote**: Assess Onboarding Evaluation Signals and Risk ## Generate risk client token Generate a client token to create an account holder and associated application with the Highnote GraphQL API. ## Create the account holder After generating a risk client token, use it as the **Bearer token** in your Authorization header when calling [](/docs/api-reference/mutation#createUSPersonAccountHolder) or [](/docs/api-reference/mutation#createUSBusinessAccountHolder). The Sardine session ID is carried in the token's claims; there is no GraphQL input field for it. For an end-to-end mutation example, see Create an account holder in the Quick Start Templates. For bearer-token mechanics, see Set authorization header. ## Simulate risk level The risk levels in this section are **simulated by Sardine, not by Highnote**. In the Test environment, simulation runs through your own Sardine test account, so you must have an active Sardine account and an enabled integration before you can simulate risk levels. Using simulated values for Account Holders may result in different application outcomes based on verification of the applicant's identity. See Simulate Application Review for more information. You can trigger varying fraud risk levels using the Person Account Holder's email or the email of the Primary Authorized Person for a Business Account Holder. Highnote will move the application to or based on the assessed fraud risk level and verification of the applicant's identity. | Email | Risk | Application Status | | :------------------------ | :---------- | :----------------- | | | | | | | | | | | | | | | | | ## Lookup risk scores Given an application ID, the following query retrieves identity risk scores for a card product application. Results show both the overall account holder risk scores and the specific verification-level risk scores. ### GraphQL: GenerateRiskClientToken Query: mutation GenerateRiskClientToken($input: GenerateRiskClientTokenInput!) { generateRiskClientToken(input: $input) { __typename ... on ClientToken { value expirationDate } ... on UserError { errors { __typename code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "sessionId": "497dcba3-ecbf-4587-a2dd-5eb0665e6880" } } Expected Result: { "data": { "generateRiskClientToken": { "__typename": "ClientToken", "value": "encoded-client-token", "expirationDate": "2025-06-28T00:33:00.472Z" } }, "extensions": { "requestId": "acbe108a-f4f7-90cb-b56b-d87b02ac568c", "rateLimit": { "cost": 11 } } } ### GraphQL: nodeAccountHolderCardProductApplicationWithIdentityRiskScores Query: query nodeAccountHolderCardProductApplicationWithIdentityRiskScores($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { __typename applicationState { status } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { __typename name { givenName familyName } billingAddress { streetAddress locality postalCode countryCodeAlpha3 } currentVerification { status reason riskScores { ... on AccountHolderRiskScore { id identityRiskScores { __typename riskLevel determinedAt ... on SardineIdentityRiskScore { sessionKey } } } } results { code description } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "AccountHolderCardProductApplication", "applicationState": { "status": "APPROVED" }, "accountHolderSnapshot": { "accountHolderCurrent": { "__typename": "USPersonAccountHolder", "riskScores": { "id": "", "identityRiskScores": [ { "__typename": "SardineIdentityRiskScore", "riskLevel": "MEDIUM", "determinedAt": "2025-10-29T21:18:18.329Z", "sessionKey": "seed686205984eb49f5cea8b324f4321" } ] } }, "name": { "givenName": "Seed", "familyName": "Customer" }, "billingAddress": { "streetAddress": "1 Market Street", "locality": "San Francisco", "postalCode": "94112", "countryCodeAlpha3": "USA" }, "currentVerification": { "status": "PASSED", "reason": "PASSED", "riskScores": { "id": "", "identityRiskScores": [ { "__typename": "SardineIdentityRiskScore", "riskLevel": "MEDIUM", "determinedAt": "2025-09-30T21:07:17.060Z", "sessionKey": "seed686205984eb49f5cea8b324f4321" } ] }, "results": [ { "code": "ADDRESS_MATCH", "description": "ADDRESS_MATCHED" }, { "code": "PHONE_MATCH", "description": "PHONE_MATCH" }, { "code": "DOB_MATCH", "description": "KYC_DOB_MATCH" }, { "code": "SSN_MATCH", "description": "KYC_SSN_MATCH" }, { "code": "NAME_MATCH", "description": "KYC_NAME_MATCH" } ] } } } }, "extensions": { "requestId": "84285c7f-5de5-9b34-98b4-89790d3fb961", "rateLimit": { "cost": 11 } } } --- URL: https://docs.highnote.com/docs/developers/sdks/issuing/card-viewer-sdk-v1 Title: Card Viewer SDK Section: Developers Description: Reference for version 1 of the Card Viewer SDK, the renderFields API published on the latest npm tag. Version 2 introduces a different API and is documented separately. ## Overview The Highnote Card Viewer SDK lets you **embed sensitive card data into your UI** using iframes. This prevents PCI-scoped data from flowing through your servers or from being accessible to scripts running on your page. ## Prerequisites 1. A Highnote account 2. A server-side integration using an API key 3. Payment card ID ## Installation The Highnote Card Viewer SDK follows semver and can be installed using the following: - JavaScript package manager: , , or - Content Delivery Network (CDN) via traditional tag. ### Package manager install The Card Viewer SDK supports the following JavaScript package managers: [](https://www.npmjs.com/package/@highnoteplatform/card-viewer), [](https://yarnpkg.com/package?q=highnoteplatform%2Fcard-viewer&name=%40highnoteplatform%2Fcard-viewer), and . Every install command on this page pins deliberately. Unpinned installs resolve the dist-tag, which will move to version 2 — whose API is different and which ships no at all — so an unpinned command on a version 1 page would quietly fetch code this page does not describe. ```sh title="npm" npm i @highnoteplatform/card-viewer@1 ``` ```sh title="yarn" yarn add @highnoteplatform/card-viewer@1 ``` ```sh title="pnpm" pnpm add @highnoteplatform/card-viewer@1 ``` ### CDN install To ensure stability and avoid potential issues caused by updates, replace with an exact version number such as . You can install the Card Viewer SDK directly from a content delivery network (CDN) such as JSDelivr. To install the Card Viewer SDK by tag, add the following to your HTML file: ```html title="Script tag for Card Viewer SDK" ``` ## Usage To render card details in your UI, you must set up elements to hold each field as follows: 1. Prepare your HTML with card detail elements. 2. Fetch a client token. 3. Initialize card viewer. ### Prepare your HTML To use the Card Viewer SDK, provide an element for each field you want to render in an iframe. The following example uses Card number, CVV, Expiration date. ```html title="Prepare HTML" Payment Card

Card Number

CVV

Expiration Date

``` ### Fetch a client token To obtain a client token from your server for the Card Viewer SDK, use the [](/docs/api-reference/mutation#generatePaymentCardClientToken) mutation. Refer to the following guidelines when generating a payment card client token: - Provide the of the payment card you are rendering. - Provide . It is required — for the Card Viewer SDK the value is . Omitting it fails schema validation before the request reaches Highnote. - The client token is only valid for _15 minutes_, but can be used multiple times. - Once a token expires, you must generate a new one to render payment card details. Use the following mutation to generate a payment card client token: ### Initialize card viewer The card viewer library works by injecting an iframe into each provided element to render the appropriate data. You can style the content inside each iframe by passing any combination of styling options. You can initialize the card viewer by using a function. This returns a Promise that contains a reference to the instance. This is useful for lifecycle management and interactions such as card number masking. The following example shows how to initialize the card viewer: ```ts title="Render Fields" const { unmount } = await renderFields({ clientToken: "client token from server", // This is the same paymentCardId used to generate the token paymentCardId: "", onError: (error) => { // Handle errors }, onReady: () => { // Called after data has been fetched and sdk is ready to display information // For eg, can be used to show a custom loading indicator document.querySelector(".loading").classList.add("hidden"); document.querySelector(".cardFields").classList.remove("hidden"); }, // Specify the individual fields to render data into elements: { cardNumber: { selector: "#cardNumber", }, cvv: { selector: "#cvv", }, expirationDate: { selector: "#expirationDate", }, }, }); ``` ## Error handling The card viewer doesn't render error messages or update your UI inside iframes when errors occur. You must introspect and handle errors accordingly. When initializing the card viewer, you can pass an handler to the function. This callback is invoked whenever an error is raised from the integration. ### Error types The following error types are supported for the Card Viewer SDK: | Error | Description | | :----------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ | | **InvalidCredentialError** | The provided client token is invalid or expired. Use the in the payload for support and debugging. | | **CardViewerRequestError** | Represents errors encountered when communicating with the Highnote API. Use the in the payload for support and debugging. | | **CardViewerFieldsInputError** | Raised when an invalid configuration is provided at runtime. | | **CopyToClipboardError** | Raised when there is an issue copying a field value to a user's clipboard. | | **CardViewerHandshakeError** | Raised when the SDK cannot complete its handshake with the injected iframes. Carries a and no request context. | | **CardViewerError** | A generic catchall error. | ### Example errors The following code sample provides examples of card viewer errors: ```ts title="Card Viewer Errors" const handleError = ( error: HighnoteRequestError | HighnoteConfigError | Error, ) => { switch (error.name) { case "InvalidCredentialError": // Handle invalid/expired credential // Unmount fields, fetch new client token, re-initialize console.error(error.context.requestId); // "some-request-id" break; case "CardViewerRequestError": console.error(error.context.requestId); // some-request-id break; case "CardViewerFieldsInputError": console.error(error.message); // "Invalid Payment Card ID" break; default: console.error(error); } }; const { unmount } = await renderFields({ clientToken: "client token from server", // This is the same paymentCardId used to generate the token paymentCardId: "", onError: (error) => { // Handle errors }, onReady: () => { // Called after data has been fetched and sdk is ready to display information }, // Specify the individual fields to render data into elements: { cardNumber: { selector: "#cardNumber", }, cvv: { selector: "#cvv", }, expirationDate: { selector: "#expirationDate", }, }, }); ``` ## Styling options The following styling options are available for use in elements for your card viewer: | Property | Examples | Docs | | :-------------- | :--------------------------------------------------- | :-------------------------------------------------------------------------- | | | , , | MDN Docs | | | , | MDN Docs | | | , , System fonts only | MDN Docs | | | , , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , , | MDN Docs | ### iframe defaults Highnote injects card viewer iframes with the following defaults. Your CSS styling can override each of these: - - (browser default) - (browser default) The document and body inside the frame will have transparent backgrounds and default to , . ### Custom fonts The Card Viewer SDK only supports system fonts. ### Layout The layout of payment card fields in the card viewer is customizable. Highnote injects iframes into the provided container elements, which will inherit the width of the container. You can customize the width and height of the container to accommodate your UI as needed. The following code sample provides an example of custom layout styling: ```css title="Card Styling" #cardNumber { margin: 1em; } /* You can target the iframe with a child combinator. */ #cardNumber > iframe { height: 140px; } ``` ## Using the Live environment By default, the card viewer library will make requests against the Test environment. When you are ready to switch to the Live environment, set the environment configuration option using the following function call: ```javascript title="Live Environment" const { unmount } = await renderFields({ clientToken: "client token from server", paymentCardId: "", // Set this to `live` environment: "live", onError: handleError, elements, }); ``` ## Lifecycle The Card Viewer SDK has a lifecycle that consists of a loading state, which resolves with payment card details. You can also unmount payment card details as needed. ### Loading state When rendering card viewer fields, the library writes the required iframes into your UI and renders them in a loading state. While in the loading state, the fields will be populated with placeholder characters: - Card number: - CVV: - Expiration Date: You can't change these values. Once the configuration has been validated and the fields rendered, the library will request the card details from the Highnote API and replace the loading values with the corresponding data. ### Unmount fields If you need to unmount payment card fields, use the method on the returned reference. This is useful when you need to "restart" the integration, or navigate to a new view client-side. Using this will ensure the cleanup of any DOM and event handlers. The following code sample provides an example function to unmount fields: ```ts title="Unmounting Fields" const { unmount } = await renderFields({ // ...config }); // Later...unmount await unmount(); ``` ## Interactions The Card Viewer SDK supports the following end-user interactions: - Account holders can toggle sensitive data via card number masking - Account holders can copy their payment card details to their clipboard to complete payments ### Card number masking By default, the payment card number will be masked (). Only the last four digits will be shown when the card number is available. You can toggle the masking on and off using the method on the returned card viewer reference. The following code sample is an example of a card number masking configuration: ```ts title="Card masking config" const { toggleCardNumberMask } = await renderFields({ // ...config }); // Toggle card number mask const err = toggleCardNumberMask(); if (err) { console.log(err); // { name: "CardViewerToggleMaskError", message: "Unable to toggle card number mask." } } ``` ### Copy to clipboard By default, users can select and copy payment card detail values to their clipboard. You can use the configuration property to toggle the "copy to clipboard" feature on or off. When enabled, clicking the card number, expiration date, or CVV field will copy the underlying value to the account holder's clipboard. This results in a copy event. In addition to the copy event, two callback functions allow customization when a user copies or fails to copy a value: | callback | description | | :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | | Invoked when an account holder successfully copies a value to their clipboard. This function will also receive an object with the property and a property of | | | invoked with an error of type in the event this functionality fails. | The following code sample is an example of a copy to clipboard configuration: ```ts title="Copy To Clipboard Config" const { unmount } = await renderFields({ clientToken: "client token from server", // This is the same paymentCardId used to generate the token paymentCardId: "", // This allows a user to click and copy the value of a field. Enabled by default enableClipboard: true, // Only needed is clipboard is enabled onCopyToClipboardSuccess: ({ field }) => { console.log(`${field} value copied!`); // cardNumber value copied! }, onError: (error) => { // Handle errors }, onReady: () => { // Called after data has been fetched and sdk is ready to display information }, // Specify the individual fields to render data into elements: { cardNumber: { selector: "#cardNumber", }, cvv: { selector: "#cvv", }, expirationDate: { selector: "#expirationDate", }, }, }); ``` ## Content security policy If your application enforces a content security policy, you must set the header to allow iframes from the Highnote domain: ```html title="Content security policy" Content-Security-Policy: frame-src https://cdn.highnote.com ``` ### GraphQL: GeneratePaymentCardClientToken Query: mutation GeneratePaymentCardClientToken( $input: GeneratePaymentCardClientTokenInput! ) { generatePaymentCardClientToken(input: $input) { ... on ClientToken { value expirationDate } } } Variables: { "input": { "paymentCardId": "", "permissions": [ "READ_RESTRICTED_DETAILS" ] } } Expected Result: { "data": { "generatePaymentCardClientToken": { "value": "TOKEN", "expirationDate": "2022-02-07T20:04:50.633Z" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/developers/sdks/issuing/card-viewer-sdk Title: Card Viewer SDK (v2 alpha) Section: Developers Description: Securely display payment card details including card number, CVV, and expiration using version 2 of the Card Viewer SDK (createCardViewer). Version 2 is a pre-release published under the alpha dist-tag. ## Overview The Highnote Card Viewer SDK lets you **embed sensitive card data into your UI** using iframes. This prevents PCI-scoped data from flowing through your servers or from being accessible to scripts running on your page. ## Prerequisites 1. A Highnote account 2. A server-side integration using an API key 3. Payment card ID ## Installation The Highnote Card Viewer SDK follows semver and can be installed using the following: - JavaScript package manager: , , or - Content Delivery Network (CDN), imported as an ES module This guide documents the version 2 API (). Version 2 is currently published under the **** dist-tag — the tag still points at version 1, whose API differs. Install with the tag shown below so the examples on this page resolve. Running version 1? See the Card Viewer SDK v1 reference. ### Package manager install The Card Viewer SDK supports the following JavaScript package managers: [](https://www.npmjs.com/package/@highnoteplatform/card-viewer), [](https://yarnpkg.com/package?q=highnoteplatform%2Fcard-viewer&name=%40highnoteplatform%2Fcard-viewer), and . ```sh title="npm" npm i @highnoteplatform/card-viewer@alpha ``` ```sh title="yarn" yarn add @highnoteplatform/card-viewer@alpha ``` ```sh title="pnpm" pnpm add @highnoteplatform/card-viewer@alpha ``` ### CDN install You can load the Card Viewer SDK directly from a content delivery network (CDN) such as JSDelivr. Version 2 is published as ES modules and CommonJS only — there is no browser-global (UMD) build, and the v1 path no longer exists. Load it with and an ; a classic tag will fail. ```html title="Module script for Card Viewer SDK" ``` ## Usage To render card details in your UI, you must set up elements to hold each field as follows: 1. Prepare your HTML with card detail elements. 2. Fetch a client token. 3. Initialize card viewer. ### Prepare your HTML To use the Card Viewer SDK, provide an element for each field you want to render in an iframe. The following example uses Card number, CVV, Expiration date. ```html title="Prepare HTML" Payment Card

Card Number

CVV

Expiration Date

``` ### Fetch a client token To obtain a client token from your server for the Card Viewer SDK, use the [](/docs/api-reference/mutation#generatePaymentCardClientToken) mutation. Refer to the following guidelines when generating a payment card client token: - Provide the of the payment card you are rendering. - Provide . It is required — for the Card Viewer SDK the value is . Omitting it fails schema validation before the request reaches Highnote. - The client token is only valid for _15 minutes_, but can be used multiple times. - Once a token expires, you must generate a new one to render payment card details. Use the following mutation to generate a payment card client token: ### Initialize card viewer The card viewer library works by injecting an iframe into each provided element to render the appropriate data. You can style the content inside each iframe by passing any combination of styling options. You can initialize the card viewer by using the function. This returns a instance synchronously — register your event listeners on it, then call to fetch the client token and inject the iframes. returns a Promise that resolves once every requested field has rendered. The instance is useful for lifecycle management and interactions such as card number masking. The following example shows how to initialize the card viewer: ```ts title="Create Card Viewer" const viewer = createCardViewer({ // Called by the SDK at mount time — return a valid client token getClientToken: async () => "client token from server", // This is the same paymentCardId used to generate the token paymentCardId: "", // Specify the individual fields to render data into elements: { cardNumber: { selector: "#cardNumber", }, cvv: { selector: "#cvv", }, expirationDate: { selector: "#expirationDate", }, }, }); // Register listeners before calling mount() viewer.on("ready", () => { // Called after data has been fetched and the sdk is ready to display information // For eg, can be used to show a custom loading indicator document.querySelector(".loading").classList.add("hidden"); document.querySelector(".cardFields").classList.remove("hidden"); }); viewer.on("error", (error) => { // Handle field-level errors (these do not reject mount()) }); await viewer.mount(); ``` ## React The SDK ships a React binding at the subpath. It is optional — works inside a React app as well — but the component owns mount and teardown for you, so you do not manage the lifecycle by hand. ```tsx title="React binding" function PaymentCard({ getClientToken }) { const [masked, setMasked] = useState(true); return (

CVV

Expiration Date

)} ); } ``` Attach only the refs you want rendered — that is how you render a subset of the fields. Props fall into three groups, and the difference matters — reaching for a remount you do not need re-fetches a client token and re-renders PCI iframes. - ** and ** remount the iframes automatically when they change. - **The callbacks** — , , , , and — are held in refs refreshed on every render, so they always fire the latest function you passed. A changing function identity neither remounts nor leaves you with a stale closure. - **Everything else** — , , , and which refs you attach — is read once at mount. Changing one later takes effect on the next remount, so conditionally revealing a field requires a remount rather than a re-render. carries one caveat: it is only wired up if it is defined at mount. Going from to a function later will not start delivering metrics, so pass one from the first render if you want them. Wrap in . The component holds it in a ref, so a changing function identity will not remount the iframes, but it keeps your dependency arrays honest. accepts the same options as — , , and — and adds five props of its own. Four of them replace the events you would register with in the imperative API: , , (receives ) and (receives ). There is no to call on the component, so subscribe through these props instead. The fifth is , which takes the same styling options keyed by field. ## Telemetry Pass to receive the card viewer's own mount-phase measurements. Telemetry is opt-in: when you don't supply a handler, the SDK creates no marks or measures at all, so leaving it off costs nothing. ```js const viewer = createCardViewer({ // ... onMetric: (metric) => { switch (metric.type) { case "timing": recordDuration(metric.name, metric.durationMs, metric.tags); break; case "count": incrementCounter(metric.name, metric.count, metric.tags); break; default: // New metric kinds are additive — ignore what you don't recognize // rather than assuming a value field that may not be there. break; } }, }); ``` ### The payload is a discriminated union on . The value field is **named per variant** rather than shared, so a handler written against cannot silently receive a count in it. | Field | Type | Notes | | ------------ | ------------------------ | ----------------------------------------------------------------------------- | | | | The discriminator. Branch on it. | | | | Dot-namespaced and stable. | | | | ** only.** Milliseconds. | | | | ** only.** The increment, defaulting to . | | | | Low-cardinality dimensions. Always carries , , . | | | | Epoch milliseconds at emit. | , , , and are all exported for TypeScript consumers. ### What gets emitted | Metric | Kind | Meaning | | -------------------------------------- | ------ | ----------------------------------------------------------------- | | | timing | End-to-end duration. | | | timing | Time for that field's iframe to load. | | | timing | postMessage handshake with that field. | | | timing | Client-token fetch attributed to that field. | | | timing | Time to apply configuration to that field. | | | count | A repaint prompt was issued for a field. | | | count | A repaint prompt was issued but could not be verified as landing. | The field name is currently baked into the metric name after a colon. If you are building dashboards, split on the **first** colon and record the field as a separate dimension — that keeps one series per phase instead of one per phase × field. Do not split the counter names: their suffix is meaningful on its own. | | What it means | | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | | Routine and self-healing. Any field mounted inside a closed accordion or an unopened modal emits it. | | / | Rare and transient. | | | Permanent for that host — the repaint prompt never lands, so the field keeps the blank-until-repainted symptom. This is the one worth alerting on. | New keys may be added to in a minor release. If you forward metrics to a third-party monitoring vendor, copy across the specific keys you want rather than spreading wholesale — otherwise a future SDK version can send a dimension to that vendor without anyone having decided it should. ## Error handling The card viewer doesn't render error messages or update your UI inside iframes when errors occur. You must introspect and handle errors accordingly. Errors surface in two places, and you must handle both: - **Field-level errors** — register a listener before calling . This fires for errors scoped to an individual field (a missing container element, a broken postMessage channel, a token fetch failure, a card-data fetch failure, a failed handshake, or a relay failure). A field-level error does **not** itself reject . :::note when a field-level error does end in a rejection All requested fields share a single call, so a failing token callback fails _every_ field. When no field can signal ready, waits out its internal timeout and then rejects with — so a on the event is typically followed by a rejection. Always wrap in / as well as registering the listener. ::: - **Whole-mount failures** — rejects when the mount as a whole cannot complete (for example, none of the requested fields could be rendered, or the SDK's internal mount timeout is exceeded). Wrap in a / to handle these. Every error the SDK raises — from either surface — is a . extends the built-in , so holds, and it carries a stable you can branch on along with the standard . ### Error codes is typed as , not a closed union — the iframe can surface codes over the protocol, so always include a branch when switching on it. The codes below are the ones the SDK raises today: | Code | Surface | Description | | :---------------------- | :------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **CONTAINER_NOT_FOUND** | | The element referenced by a field's could not be found in the DOM. | | **CHANNEL_ERROR** | | The postMessage channel between the host page and the iframe encountered an error. | | **TOKEN_FETCH_FAILED** | | Client-side, before any request: your callback rejected, or returned a token that was malformed or already expired. The SDK never obtained a usable token to send. | | **FETCH_ERROR** | | Server-side, during the card-data request: the iframe sent the request but the Highnote API rejected the token/request or returned no card data. The most common data-retrieval failure. | | **HANDSHAKE_FAILED** | | The iframe failed to complete its initial handshake with the host page. | | **RELAY_FAILED** | | A field never received its share of the card data relayed from the source field's fetch. | | **NO_FIELDS_RENDERED** | rejection | Thrown as a when none of the requested fields could be mounted. | | **MOUNT_TIMEOUT** | rejection | Thrown as a when the SDK's internal mount timeout is exceeded. | | **ALREADY_MOUNTED** | rejection | Thrown as an when is called more than once on the same instance. | | **CONFIGURE_FAILED** | | A field's message could not be delivered — for example a reloaded frame or a transferred-port edge case. | | **CONFIGURE_ERROR** | | Defensive-only: the iframe rejected a malformed or forged message. Not reachable from the documented API — handle it via your branch. | | **FIELD_NOT_MOUNTED** | | An operation targeted a field that was not mounted — reachable from the documented API by calling when was not included in . | | **MOUNT_FAILED** | rejection | The mount failed with an unexpected non- throw (also surfaced by the React binding). | ### Example errors The following code sample provides examples of handling card viewer errors from both surfaces: ```ts title="Card Viewer Errors" const handleError = (err: CardViewerError) => { switch (err.code) { case "TOKEN_FETCH_FAILED": // Fetch a new client token and re-initialize console.error(err.message); break; case "FETCH_ERROR": case "CONTAINER_NOT_FOUND": case "HANDSHAKE_FAILED": case "CHANNEL_ERROR": case "RELAY_FAILED": console.error(err.message); break; default: console.error(err); } }; const viewer = createCardViewer({ getClientToken: async () => "client token from server", // This is the same paymentCardId used to generate the token paymentCardId: "", // Specify the individual fields to render data into elements: { cardNumber: { selector: "#cardNumber", }, cvv: { selector: "#cvv", }, expirationDate: { selector: "#expirationDate", }, }, }); // Field-level errors — do not reject mount() viewer.on("error", handleError); viewer.on("ready", () => { // Called after data has been fetched and sdk is ready to display information }); try { // Whole-mount failures reject here await viewer.mount(); } catch (err) { handleError(err as CardViewerError); } ``` ## Styling options The following styling options are available for use in elements for your card viewer: | Property | Examples | Docs | | :-------------- | :--------------------------------------------------- | :-------------------------------------------------------------------------- | | | , , | MDN Docs | | | , | MDN Docs | | | , , System fonts only | MDN Docs | | | , , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , , | MDN Docs | ### iframe defaults Highnote injects card viewer iframes with the following defaults. Your CSS styling can override each of these: - - (browser default) - (browser default) The document and body inside the frame will have transparent backgrounds and default to , . ### Custom fonts The Card Viewer SDK only supports system fonts. ### Layout The layout of payment card fields in the card viewer is customizable. Highnote injects iframes into the provided container elements, which will inherit the width of the container. You can customize the width and height of the container to accommodate your UI as needed. The following code sample provides an example of custom layout styling: ```css title="Card Styling" #cardNumber { margin: 1em; } /* You can target the iframe with a child combinator. */ #cardNumber > iframe { height: 140px; } ``` ## Using the Live environment By default, the card viewer library will make requests against the Test environment. When you are ready to switch to the Live environment, set the environment configuration option using the following function call: ```javascript title="Live Environment" const viewer = createCardViewer({ getClientToken: async () => "client token from server", paymentCardId: "", // Set this to `live` environment: "live", elements, }); viewer.on("error", handleError); await viewer.mount(); ``` ## Lifecycle The Card Viewer SDK has a lifecycle that consists of a loading state, which resolves with payment card details. You can also destroy payment card fields as needed. ### Loading state When rendering card viewer fields, the library writes the required iframes into your UI and renders them in a loading state. While in the loading state, the fields will be populated with placeholder characters: - Card number: - CVV: - Expiration Date: You can't change these values. Once the configuration has been validated and the fields rendered, the library will request the card details from the Highnote API and replace the loading values with the corresponding data. ### Destroy fields If you need to remove payment card fields, call the method on the instance. This is useful when you need to "restart" the integration, or navigate to a new view client-side. Using this will ensure the cleanup of any DOM and event handlers. is synchronous and safe to call at any point in the lifecycle — before, during, or after . The following code sample provides an example function to destroy fields: ```ts title="Destroying Fields" const viewer = createCardViewer({ // ...config }); await viewer.mount(); // Later...destroy viewer.destroy(); ``` ## Interactions The Card Viewer SDK supports the following end-user interactions: - Account holders can toggle sensitive data via card number masking - Account holders can copy their payment card details to their clipboard to complete payments ### Card number masking By default, the payment card number will be masked (). Only the last four digits will be shown when the card number is available. You can mask or reveal a field's value using the method on the instance. takes the field name and an explicit boolean — to mask, to reveal — so your integration owns the masked/revealed state instead of blindly toggling it. Calling with the current state is a no-op (idempotent). While this example focuses on , works for any rendered field. The following code sample is an example of a card number masking configuration: ```ts title="Card masking config" const viewer = createCardViewer({ // ...config }); await viewer.mount(); // Track masked state in your own UI, then call setMask explicitly let masked = true; const toggleCardNumberVisibility = () => { masked = !masked; viewer.setMask("cardNumber", masked); }; ``` ### Copy to clipboard Users can select and copy payment card detail values to their clipboard. You can use the configuration property to toggle the "copy to clipboard" feature on or off. ** defaults to ** — pass to disable it. Earlier builds defaulted it to ; restored the version 1 default, so each field iframe carries unless you opt out. When enabled, clicking the card number, expiration date, or CVV field will copy the underlying value to the account holder's clipboard. This results in a copy event. In addition to the copy event, two events allow customization when a user copies or fails to copy a value: | event | description | | :------------------ | :------------------------------------------------------------------------------------------------------------- | | | Fires when an account holder successfully copies a value to their clipboard. The handler receives . | | | Fires when the copy fails. The handler receives . | The following code sample is an example of a copy to clipboard configuration: ```ts title="Copy To Clipboard Config" const viewer = createCardViewer({ getClientToken: async () => "client token from server", // This is the same paymentCardId used to generate the token paymentCardId: "", // Defaults to true — set to false to disable copy to clipboard enableClipboard: true, // Specify the individual fields to render data into elements: { cardNumber: { selector: "#cardNumber", }, cvv: { selector: "#cvv", }, expirationDate: { selector: "#expirationDate", }, }, }); viewer.on("clipboard:success", ({ field }) => { console.log(`${field} value copied!`); // cardNumber value copied! }); viewer.on("clipboard:error", ({ field, message }) => { console.error(`Failed to copy ${field}: ${message}`); }); viewer.on("error", (error) => { // Handle errors }); viewer.on("ready", () => { // Called after data has been fetched and sdk is ready to display information }); await viewer.mount(); ``` ## Content security policy If your application enforces a content security policy, you must set the header to allow iframes from the Highnote domain: ```html title="Content security policy" Content-Security-Policy: frame-src https://cdn.highnote.com ``` ### GraphQL: GeneratePaymentCardClientToken Query: mutation GeneratePaymentCardClientToken( $input: GeneratePaymentCardClientTokenInput! ) { generatePaymentCardClientToken(input: $input) { ... on ClientToken { value expirationDate } } } Variables: { "input": { "paymentCardId": "", "permissions": [ "READ_RESTRICTED_DETAILS" ] } } Expected Result: { "data": { "generatePaymentCardClientToken": { "value": "TOKEN", "expirationDate": "2022-02-07T20:04:50.633Z" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/developers/sdks/issuing/document-upload-sdk Title: Document Upload SDK Section: Developers Description: Collect identity verification documents from account holders during manual review using the Document Upload SDK. ## Overview The Highnote Document Upload SDK lets you **collect identity verification documents from account holders** when a card product application enters manual review. ## Prerequisites 1. A Highnote account 2. A server-side integration using an API key 3. Document upload session ID 4. An HTML selector for injecting a DOM element ## Installation The Highnote Document Upload SDK follows semver and can be installed using the following: - JavaScript package manager: , , or - Content Delivery Network (CDN) via traditional tag. ### Install by package manager The Document Upload SDK supports the following JavaScript package managers: [](https://www.npmjs.com/package/@highnoteplatform/document-upload), [](https://yarnpkg.com/package?q=highnoteplatform%2F&name=%40highnoteplatform%2Fdocument-uploads), and . ```sh title="npm" npm i @highnoteplatform/document-upload ``` ```sh title="yarn" yarn add @highnoteplatform/document-upload ``` ```sh title="pnpm" pnpm add @highnoteplatform/document-upload ``` ### Install by CDN To ensure stability and avoid potential issues caused by updates, replace with a specific version number such as . You can install Document Upload SDK directly from a content delivery network (CDN) such as JSDelivr. To install the Document Upload SDK by tag, add the following to your HTML file: ```html title="Script tag for Document Upload SDK" ``` ## Usage To use the Document Upload SDK, you must fetch a document upload session ID and set up elements for each field as follows: 1. Prepare your HTML 2. Fetch document upload session ID 3. Fetch a client token 4. Initialize document upload. Supported file formats are PDF, PNG, JPG. We recommend a file size of 10MB or less. ## Prepare your HTML To prepare your HTML, you must provide an element to which to append the . The document upload library uses the to render the appropriate document upload widget. You can style the content inside the widget by passing any combination of styling options. The following code sample shows an example how you can prepare your HTML for the Document Upload SDK: ```html title="Prepare HTML" Document-Upload
``` ## Fetch document upload session ID If an account holder's card product application status is , they must provide specific documents for Customer Identification Program (CIP) verification. To use the Document Upload SDK for document collection, you must use a document upload session ID to start a secure document upload session. Use the following query to retrieve a card product application and fetch your document upload session ID: ## Fetch a client token To get a client token from your server for the Document Upload SDK, use the [](/docs/api-reference/mutation#generateDocumentUploadClientToken) mutation. Refer to the following guidelines when generating a payment card client token: - Provide the of the payment card you are rendering. - The client token is only valid for 15 minutes, but can be used multiple times. - Once a token expires, you must generate a new one to render payment card details. Use the following mutation to generate a document upload client token: ## Initialize document upload You can initialize the Document Upload SDK by calling an function. This returns a Promise containing a reference to the instance, which includes helper methods to enact on the SDK such as and . The following code sample is an example of an function: ```js title="Initialize Document Upload" const { unmount, endSession } = await initializeDocumentUploadSdk({ clientToken: "client-token", documentUploadSessionId: "document-upload-session-id", environment: "test", documentUploadComponent: { selector: "#document-upload-component" }, onSuccess: handleSuccess, onError: handleError, }); ``` ## Error handling The following error types are supported for the Document Upload SDK: | Error | Description | | :----------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ | | **InvalidCredentialError** | The provided client token is invalid or expired. Use the in the payload for support and debugging. | | **DocumentUploadRequestError** | Represents errors encountered when communicating with the Highnote API. Use the in the payload for support and debugging. | | **DocumentUploadConfigurationError** | An invalid configuration is provided at runtime. Example messages include: | | | | | | | | | | | **GenericDocumentUploadError** | All unknown and unexpected errors. | The following code sample provides examples of document upload errors: ```ts title="Error Examples" const handleError = (error: Error) => { switch (error.name) { case "InvalidCredential": // Handle invalid/expired credential // Unmount fields, fetch new client token, re-initialize console.error(error.context.requestId); // "some-request-id" break; case "DoumentUploadRequestError": console.error(error.context.requestId); // some-request-id break; case "DocumentUploadConfigError": console.error(error.message); // "Invalid Session ID" break; default: console.error(error); } }; const handleOnLoad = (component: Element) => { console.log(`[Integrator log]: ${component.id} value appended to selector!`); }; const handleOnSuccess = (onSuccess: boolean) => { if (onSuccess) { console.log(`[Integrator log]: All documents uploaded and session closed.`); } }; await initializeDocumentUploadSdk({ clientToken: "client-token", documentUploadSessionId: "document-upload-session-id", environment: "test", documentUploadComponent: { selector: "#document-upload-component" }, onLoad: handleOnLoad, onSuccess: handleOnSuccess, onError: handleError, }); ``` ## Styling options The following styling options are available for use in elements for your document upload widget: | HTML Element | id | Description | | :----------- | :----------------------------------- | :------------------------------------------------------------------------------------------------------------- | | | | The selector provided during initialization of the SDK. | | | | The that is rendered by the SDK. | | | | The that contains documents required and documents uploaded. This reloaded on each new upload. | | | | The that contains all elements that are not reloaded. | | | | The file selector for uploads. | | | | The list of documents to be uploaded. | | | | Button to upload required documents. | | | | All section headings. | | | | All informational text. | ## Using the Live environment By default, the card viewer library makes requests against the Test environment. When you are ready to switch to the Live environment, set the environment configuration option using the following function call: ```js title="Live Environment" const { unmount, endSession } = await initializeDocumentUploadSdk({ clientToken: "client-token", documentUploadSessionId: "document-upload-session-id", environment: "live", documentUploadComponent: { selector: "#document-upload-component" }, onSuccess: handleSuccess, onError: handleError, }); ``` ## Lifecycle When the Document Upload SDK initializes, it automatically renders the required document upload widget and closes the sessions once all requirements are met. You are required to handle and behavior as you wish. The rendered widget contains two sections: 1. **Documents uploaded**: Includes documents already uploaded 2. **Documents required**: Includes a drop-down of the required documents and a method for uploading them The widget guides the user through the document upload process with reloaded components triggered by an upload event on subsequent steps. When no more documents are left to be uploaded, the SDK will end the document upload session and submit uploads for review. ## Interactions The Document Upload SDK supports the following interactions: - Allows account holder to upload documentation - Unmount the SDK - End the document upload session ## Upload document Once the SDK is initialized, the document upload widget provides the applicant with a list of uploaded documents and a dropdown menu with outstanding, required documents. The account holder can pick a document to upload and click on the **Upload button**. The applicant must be able to successfully upload all required documents until no document type options remain to select from the dropdown. ## Unmount SDK The Document Upload SDK provides a call-back function for you to unmount the SDK. This allows you to decouple it with the client-token for a fresh start at any time. ## End session This action will submit any uploaded documents for review. The Document Upload SDK provides a call-back function for you to end a document session at any time. ### GraphQL: getApplication Query: query getApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { currentVerification { requiredDocuments { ... on AccountHolderApplicationRequiredDocument { documentUploadSession { ... on USAccountHolderApplicationDocumentUploadSession { id } } } } } } ... on USBusinessAccountHolderSnapshot { primaryAuthorizedPerson { currentVerification { requiredDocuments { ... on AccountHolderApplicationRequiredDocument { documentUploadSession { ... on USAccountHolderApplicationDocumentUploadSession { id } } } } } } businessProfile { currentVerification { requiredDocuments { ... on AccountHolderApplicationRequiredDocument { documentUploadSession { ... on USAccountHolderApplicationDocumentUploadSession { id } } } } } ultimateBeneficialOwners { currentVerification { requiredDocuments { ... on AccountHolderApplicationRequiredDocument { documentUploadSession { ... on USAccountHolderApplicationDocumentUploadSession { id } } } } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "accountHolderSnapshot": { "primaryAuthorizedPerson": { "currentVerification": { "requiredDocuments": [ { "documentUploadSession": { "id": "" } } ] } }, "businessProfile": { "currentVerification": { "requiredDocuments": [ { "documentUploadSession": { "id": "" } } ] }, "ultimateBeneficialOwners": [] } } } }, "extensions": { "requestId": "", "rateLimit": { "limit": 30030, "remaining": 30016, "cost": 14 } } } ### GraphQL: GenerateDocumentUploadClientToken Query: mutation GenerateDocumentUploadClientToken( $input: GenerateDocumentUploadClientTokenInput! ) { generateDocumentUploadClientToken(input: $input) { ... on ClientToken { value expirationDate usage } } } Variables: { "input": { "documentUploadSessionId": "", "permissions": [ "MANAGE_DOCUMENT_UPLOAD_SESSION" ] } } Expected Result: { "data": { "generateDocumentUploadClientToken": { "value": "TOKEN", "expirationDate": "2022-02-07T20:04:50.633Z", "usage": "UNTIL_EXPIRATION" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/developers/sdks/issuing/secure-inputs-sdk-pins Title: Secure Inputs SDK for PINs Section: Developers Description: Let customers securely enter and update their card PIN through iframe-based input fields using the Secure Inputs SDK. ## Overview The Highnote Secure Inputs SDK enables customers to **securely set and update their PIN from your UI** using iframes. This prevents PCI-scoped data from flowing through your servers or from being accessible to scripts running on your page. ## Prerequisites 1. A Highnote account 2. A server-side integration using an API key 3. Payment card ID ## Installation The Highnote Secure Inputs SDK follows semver and can be installed using the following: - JavaScript package manager: , , or - Content Delivery Network (CDN) via traditional tag. ### Install by package manager Installation steps are the same for both the PIN and tokenization Secure Inputs SDKs. The Secure Inputs SDK supports the following JavaScript package managers: [](https://www.npmjs.com/package/@highnoteplatform/secure-inputs), [](https://yarnpkg.com/package?q=highnoteplatform%2F&name=%40highnoteplatform%2Fsecure-inputs), and . ```sh title="npm" npm i @highnoteplatform/secure-inputs ``` ```sh title="yarn" yarn add @highnoteplatform/secure-inputs ``` ```sh title="pnpm" pnpm add @highnoteplatform/secure-inputs ``` ### Install by CDN To ensure stability and avoid potential issues caused by updates, replace with a specific version number such as . You can install Secure Inputs SDK directly from a content delivery network (CDN) such as JSDelivr. To install the Secure Inputs SDK by tag, add the following to your HTML file: ```html title="Script tag for Secure Inputs SDK" ``` ## Usage To render secure input fields in your UI, configure elements to hold each field as follows: 1. Prepare your HTML 2. Fetch a client token 3. Initialize secure inputs. ### Prepare your HTML To use the Secure Inputs SDK, you must provide an element for the PIN field. The following code sample uses a element to contain the iframe for the secure input field: ```html title="Prepare HTML for PIN entry" Edit Payment Card PIN

Enter a new PIN for your Payment Card

``` ### Fetch a client token To obtain a client token from your server for the secure inputs SDK, use the [](/docs/api-reference/mutation#generatePaymentCardClientToken) mutation. Refer to the following guidelines when generating a payment card client token: - Provide the of the payment card that needs the PIN set or updated. - The client token is only valid for _15 minutes_, but can be used multiple times. - Once a token expires, you must generate a new one. Use the following mutation to generate a payment card client token: ### Initialize secure inputs The secure inputs library works by injecting an iframe into the PIN element to render the appropriate data. You can style the content inside each iframe by passing any combination of styling options. You can initialize the card viewer by using a function. This returns a Promise that contains a reference to the instance. This is useful for lifecycle management and interactions such as field submission. #### PIN element properties Pass these properties on the element inside : | Property | Required | Type | Default | Description | | :-------------- | :------: | :-------- | :------ | :------------------------------------------------------------------------------------------------ | | | x | | — | Client token returned by the mutation. Valid for 15 minutes. | | | x | | — | ID of the payment card needing the PIN set or updated. Must match the ID used for the token. | | | x | | — | CSS selector for the container element that will hold the PIN iframe. | | | | | | Mask PIN digits like a password field while the cardholder types. | | | | | | Render a toggle inside iframe so cardholder can reveal/hide entered PIN. must be . | The following example shows how to initialize the Secure Inputs SDK: ```js title="Initialize Secure Inputs" const secureInputs = await renderFields({ // Specify the individual fields to render data into elements: { pin: { clientToken: "client token from server", // This is the same paymentCardId used to generate the token paymentCardId: "", selector: "#pin", // Mask the PIN digits like a password field. Default: false. masked: true, // Render a visibility toggle inside the iframe. Only takes effect when masked is true. Default: false. showToggle: true, }, }, onSuccess: (element) => { // Inform the user on success }, onError: (error) => { // Handle errors }, }); ``` ## Error handling The Secure Inputs SDK doesn't render error messages or update your UI inside iframes when errors occur. You must introspect and handle errors accordingly. You can pass an handler to the call. This callback will be invoked whenever an error is raised from the integration. ### Error types The following error types are supported for the secure inputs SDK: | Error | Description | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **InvalidCredentialError** | The provided client token is invalid or expired. Use the in the payload for support and debugging. | | **SecureInputsRequestError** | Represents errors encountered when communicating with the Highnote API, such as an incorrect payment card ID. Use the in the payload for support and debugging. | | **SecureInputsFieldsInputError** | Raised when an invalid configuration is provided at runtime. | | **SecureInputsError** | A generic catchall error. | ### Example errors The following code sample provides examples of secure inputs errors: ```ts title="Render Fields" const handleError = (error: SecureInputsError) => { switch (error.name) { case "InvalidCredentialError": // Handle invalid/expired credential // Unmount fields, fetch new client token, re-initialize console.error(error.context.requestId); // "some-request-id" break; case "SecureInputsRequestError": // Handle invalid payment card IDs console.error(error.context.requestId); // some-request-id break; case "SecureInputsFieldInputError": // Handle user input errors such as invalid pin console.error(error.message); // "Invalid Payment Card ID" break; default: console.error(error); } }; const { unmount } = await renderFields({ // ... onError: handleError, // ... }); ``` ## Styling options The following styling options are available for use in elements for your secure inputs fields: | Property | Examples | Docs | | :-------------- | :--------------------------------------------------- | :-------------------------------------------------------------------------- | | | , , | MDN Docs | | | , | MDN Docs | | | , , System fonts only | MDN Docs | | | , , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , | MDN Docs | | | , , | MDN Docs | ### iframe defaults Highnote injects card viewer iframes with the following defaults. Your CSS styling can override each of these: - - (browser default) - (browser default) The document and body inside the frame will have transparent backgrounds and default to , ### Custom fonts The Secure Inputs SDK only supports system fonts. ### Layout The layout of payment card fields in the card viewer is customizable. Highnote injects iframes into the provided container elements, which will inherit the width of the container. You can customize the width and height of the container to accommodate your UI as needed. The following code sample provides an example of custom layout styling: ```css title="Styling" #pin { margin: 1em; } /* You can target the iframe with a child combinator. */ #pin > iframe { height: 140px; } ``` ## Using the Live environment By default, the card viewer library will make requests against the Test environment. When you are ready to switch to the Live environment, set the configuration option using the following function call: ```js title="Live Environment" const { unmount } = await renderFields({ // Set this to `live` environment: "live", // ... }); ``` ## Lifecycle If you need to unmount payment card fields, use the method on the returned reference. This is useful when you need to "restart" the integration, or navigate to a new view client-side. Using this will ensure the cleanup of any DOM and event handlers. The following code sample provides an example function to unmount fields: ```ts title="Unmounting Fields" const { submit, unmount } = await renderFields({ onSuccess: async (field) => { if (field === "pin") { // Inform customer their PIN changed successfully. await unmount(); } }, // ...config }); // ... submit(); ``` ## Content security policy If your application enforces a content security policy, you must set the frame-src header to allow iframes from the Highnote domain: ```html title="Content security policy" Content-Security-Policy: frame-src https://cdn.highnote.com ``` ### GraphQL: GeneratePaymentCardClientToken Query: mutation GeneratePaymentCardClientToken( $input: GeneratePaymentCardClientTokenInput! ) { generatePaymentCardClientToken(input: $input) { ... on ClientToken { value expirationDate } } } Variables: { "input": { "paymentCardId": "", "permissions": [ "SET_PAYMENT_CARD_PIN" ] } } Expected Result: { "data": { "generatePaymentCardClientToken": { "value": "TOKEN", "expirationDate": "2022-02-07T20:04:50.633Z" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/developers/sdks/about-sdks Title: SDK Overview Section: Developers Description: Choose the right Highnote SDK for your use case. Covers Card Viewer, Checkout, Secure Inputs, and Document Upload for issuing and acquiring integrations. ## Overview Highnote offers the following server-side SDKs that let you integrate quickly with the Highnote API. | SDK | Processing Side | Capability | | :--------------------------------------------------------------------------------------------- | :-------------- | :---------------------------------------------------------------------------------------------------------------- | | Card Viewer | Issuing | Embed sensitive card data in your UI and avoid PCI data from being compromised | | Checkout | Acquiring | Accept payment card details in a configured checkout experience | | Document Upload | Issuing | Collect identity verification documents from account holders when a card product application enters manual review | | Secure Inputs (PINs) | Issuing | Create a UI where customers can securely input sensitive data without compromise | | Secure Inputs (Tokenization) | Acquiring | Create secure inputs for accepting payment card details | --- URL: https://docs.highnote.com/docs/developers/sdks/client-tokens Title: Client Tokens Section: Developers Description: Generate short-lived client tokens to authorize client-side operations like tokenizing account holders, viewing card details, and setting PINs. ## Overview Most client tokens are valid for **15 minutes**. Client tokens scoped solely to payment method tokenization are valid for **30 minutes**. Once expired, you must generate a new one. Client tokens are short-lived credentials that pass sensitive information from your client to Highnote. Some use cases require client tokens; some are recommended to use them for enhanced security. Most client tokens are valid for 15 minutes. When a token expires, you must generate a new one. Generating client tokens requires an API key. The token generation mutation should be done from your server and sent to your client. To use client tokens: 1. Generate a client token scoped to your use case. 2. Set your authorization header. 3. Call the API with the client token in the authorization header. ## Supported use cases The following use cases are supported for client tokens: | Use Case | Generate Token | Utilize Token | Requires Token | | :--------------------------------- | :------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------------------- | :------------- | | Card Viewer SDK | Generate token | Utilize token | Yes | | Secure Inputs SDK for PINs | Generate token | Utilize token | Yes | | Tokenize business account holder | Generate token | Utilize token | Yes | | Tokenize person account holder | Generate token | Utilize token | Yes | | Tokenize authorized user | Generate token | Utilize token | Yes | | Create business account holder | Generate token | Utilize token | No | | Create person account holder | Generate token | Utilize token | No | | Bring-your-own Sardine integration | Generate token | Utilize token | Yes | | Create authorized user | Generate token | Utilize token | No | | Create document upload session | Generate token | Utilize token | No | | Set payment card PIN | Generate token | Utilize token | Yes | | View account and routing number | Generate token | | Yes | | View payment card details | Generate token | | Yes | | View external bank account details | Generate token | | Yes | ## Generate a client token Every client token has a unique mutation associated with it. These mutations use the ID of the object you are tokenizing and requested permissions as inputs. The following mutation example generates a payment card client token to set a PIN on a payment card. Refer to the supported use cases reference for the mutation for your use case. ## Set authorization header Once you have generated a client token, you must set the authorization header in your GraphQL client with the token. The following example shows the base64 encoded client token that we generated using the mutation, and the example authorization header for our use case: ### Example client token ```bash eyJraWQiOiIxIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdWQiOiJwcm9kLnRlc3QuYXBpLmJheTEuY29tIiwib3JnIjoib2dfYnMwMWQ3ODNhY2U5NzBiZjRiMGE5ZDQxNGNmNzRjMzIyZjZkIiwicmVnIjoiVVNBIiwiYXBwaWQiOiJhcF9iYXkxOmNsaWVudHNkazowMDAwMDAwMDAwMDAwMDAwMCIsImlzcyI6InByb2QuYXV0aC5iYXkxLmNvbSIsInJ0X2FjY291bnRfaG9sZGVyX3Rva2VuaXplX3ciOltdLCJ0biI6InRuXzIzdXN0M3ByM2FlOGRmODE1NDdkNGM3MDhjZjVmYTI2YzJkZGVjNDUiLCJleHAiOjE2NDIwMTUzNzksImVudiI6InRlc3QiLCJpYXQiOjE2NDIwMTQ0Nzl9 ``` ### Example authorization header ```bash curl -X POST \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ --data '{"query":"mutation SetPinForPaymentCard($input: SetPinForPaymentCardInput!) {\n setPinForPaymentCard(input: $input) {\n __typename\n ...on PaymentCard {\n id\n bin\n last4\n }\n ... on UserError {\n errors {\n path\n code\n }\n }\n }\n}", "variables": {"input":"{\n\t\"paymentCardId\": \"some-payment-card-id\",\n\t\"newPin\": \"12ssss34\"\n}"}}' \ https://api.us.test.highnote.com/graphql ``` ## Call the API After setting the authorization header, you can call the API. The following example uses the mutation to call the API and set the PIN for the payment card: ### GraphQL: GeneratePaymentCardClientToken Query: mutation GeneratePaymentCardClientToken( $input: GeneratePaymentCardClientTokenInput! ) { generatePaymentCardClientToken(input: $input) { ... on ClientToken { value expirationDate } } } Variables: { "input": { "paymentCardId": "", "permissions": [ "SET_PAYMENT_CARD_PIN" ] } } Expected Result: { "data": { "generatePaymentCardClientToken": { "value": "TOKEN", "expirationDate": "2022-02-07T20:04:50.633Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SetPinForPaymentCard Query: mutation SetPinForPaymentCard($input: SetPinForPaymentCardInput!) { setPinForPaymentCard(input: $input) { __typename ... on PaymentCard { id } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "paymentCardId": "", "newPin": "1234" } } Expected Result: { "data": { "setPinForPaymentCard": { "__typename": "PaymentCard", "id": "" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/developers/sdks/installation Title: Installation Section: Developers Description: Install Highnote SDKs using npm, yarn, pnpm, or CDN script tags. ## Overview Highnote SDKs follow semver and can be installed using: - JavaScript package manager: , , or - Content Delivery Network (CDN) via traditional tag. Minimum requirements are: - A Highnote account - A server-side integration using an API key ## Installation instructions Refer to the docs for each SDK on how to install: #### Issuing - Card Viewer SDK installation - Document Upload SDK installation - Secure Inputs SDK (for PINS) installation #### Acquiring - Checkout SDK installation - Secure Inputs SDK (for Tokenization) installation --- URL: https://docs.highnote.com/docs/developers/sdks/supported-packages Title: Supported Packages and Browsers Section: Developers Description: Verify SDK compatibility with Node 18+ and supported browsers including Chrome, Safari, Firefox, Edge, and mobile. ## Supported Packages - Minimum supported package: Node 18 (Hydrogen) Refer to Node.js Releases. ## Supported Browsers Highnote's SDKs are browser-based and work with modern browsers. To provide a secure and compliant experience, we only support browsers that are actively receiving security updates. The following browsers are supported: ### Desktop - Chrome 109+ - Safari 15.6+ - Firefox 115+ - Edge 120+ - Opera 105+ ### Mobile - iOS Safari 15.6+ - Android Chrome 121+ If you have an issue with a Highnote SDK on a supported browser or device, contact support@highnote.com for assistance. --- URL: https://docs.highnote.com/docs/issuing/about-issuing Title: About Issuing Cards Section: Issuing Description: Issue and manage payment cards with the Highnote platform. Create card products, onboard account holders, control authorizations with spend rules, and track balances with integrated ledgers. ## What is Issuing? Highnote Issuing is a card issuing solution built on the most modern payments platform. With Highnote Issuing, you can easily: - Create and manage customizable payment cards, including virtual, physical, and tokenized digital cards. - Control and optimize authorizations with spend rules and velocity controls. - Track money movement and balances with the integrated ledger. - Quickly bring card products to market with Highnote’s GraphQL API and SDKs. Highnote empowers you to own your card program with end-to-end card program management. You can launch your card program without the hassle of managing your own compliance and business operations. Our in-house compliance and operations teams manage Know Your Customer (KYC) and Know Your Business (KYB) regulatory compliance, transaction monitoring, daily reconciliation, settlement, and more. ## Key concepts The Highnote API Reference contains comprehensive resources for creating and managing your card program. The following concepts are the key components for all card programs built using Highnote’s Issuing platform: | Concept | Definition | | :------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------- | | Account holder | A person or business issued or provided use of a payment card or financial account connected to a card product | | Card product | Represents your card program, including applications, financial accounts, payment cards, bank accounts, and transactions | | Financial account | An account defined to represent funds available for use by, or owned by, a Highnote account holder | | Financial event | Any event that affects the balance of a financial account, including non-transaction events | | Flexible Credential | A primary and a secondary credential behind one card the cardholder carries, with routing chosen at authorization. | | Ledger | A financial account's record of financial account activity | | Payment card | A card, other access device, or account number connected to account holders under a card product | | Transaction event | An event resulting from using a payment card | For other terms and concepts, see the Glossary. ## Issuing process Card products are customizable, and each card program may look different. In general, the Highnote Issuing process occurs as follows: 1. Create a card product and customize it to fit your needs. 1. Onboard account holders using an application on your app or website. 1. Create a financial account for each approved account holder application. 1. Issue the account holder a payment card. ## Quick start templates Highnote’s card issuing platform lets you create a card product that fits your needs. You can jumpstart your card program with easy-to-use guides using one of Highnote’s Quick Start Templates. The following templates are supported: - Consumer Credit, Commercial Credit, Fleet Credit - Consumer Charge, Commercial Charge - Consumer Prepaid, Commercial Prepaid - AP Automation - Virtual Card Express ## Next steps If you haven't done so already: 1. Create an account and explore the Dashboard. 1. Learn about the Highnote API and Highnote SDKs. 1. Review the Dashboard Support Guides. 1. Create your card product and prepare for launch. --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/add-funds-to-account Title: Add Funds to a Financial Account Section: Issuing Description: Add funds to a financial account using Originated ACH, Non-originated ACH, or transfers from a product funding account. ## Overview Financial accounts hold payment card balances. The funding source for a financial account differs depending on your card product vertical. The following table lists the **funding source** for each card product vertical: | Product Vertical | Funding Source | | :--------------- | :--------------------------------------------------------------------------------------------------------------------------- | | Debit | Funded using Originated ACH transfers from an account holder's verified external bank account or Non-originated ACH transfer | | Charge | Funded by the credit limit, which is backed by your product funding account balance | | Secured charge | Funded using secured deposits sent via transfer from an account holder's verified external bank account | | Fleet | Funded by the credit limit, which is backed by your product funding account balance | | AP automation | Funded using Non-originated ACH transfers | | Prepaid | Funded using internal Highnote transfers from your product funding account balance | | Payroll | Funded via external payroll or Non-originated ACH transfers | ### Transfer methods Card product cancellation periods and risk and compliance reviews can impact transfer timelines. The following table outlines the different transfer methods used for funding a **financial account**, and their associated timelines: | Transfer Method | Timeline | | :------------------------- | :-------------------------- | | Originated ACH | Three to five business days | | Originated next day ACH | One to three business days | | Originated same day ACH | One to two business days | | Non-originated ACH | Three to five business days | | Internal Highnote transfer | Within seconds | ### Cutoff times Originated ACH transfers have specific cutoff times for processing. Initiating a transfer after the specified cutoff time may result in additional processing time. - **Originated next day ACH**: If a transfer is initiated before 4 PM EST, it will be processed by the bank the following business day. If initiated after 4 PM EST, the transfer will be processed two business days from initiation. - **Originated same day ACH**: If a transfer is initiated before 2 PM EST, the bank will process it the same day. If initiated after 2 PM EST, the transfer will be processed the following business day. All originated ACH transfer methods have a required three business day hold period once the transfer has been initiated and is processing. ## Find financial account ID Use the following query to find a financial account ID by application ID: ## Add funds to a financial account To add funds to a Highnote financial account, use one of the following methods: - **Originated ACH:** Use this method for debit card products. - **Non-originated ACH:** Use this method for API automation products. - **Transfer from product funding account:** Use this method for credit and charge card products. ### Non-originated ACH 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: - If is in the past, the transfer processes immediately and is not held. - If is in the future, you must follow up with or to progress or fail the transfer. ::: ### Originated ACH To pull funds from an external bank account via an originated ACH transfer, your account holder must connect a verified external account. Once an account holder connects a verified external account, refer to the following guidelines for adding funds using originated ACH transfers: - For the field, use the verified external account ID. - For the field, use the account holder financial account. - _Optional_ - Use a boolean to request the transfer to use same day ACH. Use the following mutation to initiate an originated ACH transfer: ### 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: - : Account holder's financial account ID - : Product funding account ID Use the following mutation to initiate a transfer from your product funding account: ## Fund load review You can inform Highnote that a WireTransfer or Non originated fund load has been sent. Once the information has been reviewed, the funds will be applied to the FinancialAccount. ### Request wire fund load to a financial account Call with a , , and to start a wire fund load request. You must specify a memo. This should be the same memo that appears in the bank account when the wire transfer occurs. ### Query wire fund load request Use the following to retrieve a wire fund load request: ### GraphQL: FindAccountHolderCardProductApplication Query: query FindAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { __typename id createdAt updatedAt applicationState { status } cardProduct { name } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id financialAccounts(first: 20) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id name } } } } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id financialAccounts(first: 20) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id name } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "createdAt": "2022-02-24T15:55:10.842Z", "updatedAt": "2022-02-24T15:55:17.742Z", "applicationState": { "status": "APPROVED" }, "cardProduct": { "name": "Business Prepaid" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "", "financialAccounts": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "start-cursor", "endCursor": "end-cursor" }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "FinancialAccount", "id": "", "name": "Financial Account #1" } }, { "cursor": "some-cursor", "node": { "__typename": "FinancialAccount", "id": "", "name": "Financial Account #2" } } ] } } } } }, "extensions": { "requestId": "" } } ### GraphQL: 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" } } Expected Result: { "data": { "simulateNonOriginatedAchTransfer": { "__typename": "NonOriginatedAchTransfer", "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 } } } ### GraphQL: InitiateAchTransfer-Originated-Deposit Query: mutation InitiateAchTransfer($input: InitiateAchTransferInput!) { initiateAchTransfer(input: $input) { __typename ... on OriginatedAchTransfer { id amount { value currencyCode } createdAt updatedAt type purpose sign sameDay traceNumber status effectiveEntryDate sentToBankAt processedAt fromFinancialAccount { __typename ... on Node { id } ... on ExternalFinancialBankAccount { id name } } toFinancialAccount { __typename ... on Node { id } ... on FinancialAccount { id name } } } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "idempotencyKey": "00000000-0000-0000-0000-000000000000", "fromFinancialAccountId": "", "toFinancialAccountId": "", "purpose": "DEPOSIT", "amount": { "value": 10000, "currencyCode": "USD" }, "transferAgreementConsent": { "consentTimestamp": "2025-01-15T10:30:00.000Z", "authorizedPersonId": "", "template": { "consentTemplateId": "your-consent-template-id", "consentTemplateVersion": "1.0" } }, "companyEntryDescription": "DEPOSIT", "individualName": "John Doe", "sameDay": false } } Expected Result: { "data": { "initiateAchTransfer": { "__typename": "OriginatedAchTransfer", "id": "", "amount": { "value": 10000, "currencyCode": "USD" }, "createdAt": null, "updatedAt": null, "type": "PULL", "purpose": "DEPOSIT", "sign": "POSITIVE", "sameDay": false, "traceNumber": null, "status": "PENDING", "effectiveEntryDate": null, "sentToBankAt": null, "processedAt": null, "fromFinancialAccount": { "__typename": "ExternalFinancialBankAccount", "id": "", "name": "External Checking Account" }, "toFinancialAccount": { "__typename": "FinancialAccount", "id": "", "name": "Primary Account" } } } } ### GraphQL: 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": "", "fromFinancialAccountId": "", "memo": "Fund Financial Account #1", "amount": { "value": 10000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccount": { "__typename": "InterFinancialAccountTransfer", "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" } } } } ### GraphQL: InitiateAddWiredFundsToFinancialAccount Query: mutation InitiateAddWiredFundsToFinancialAccount( $input: InitiateAddWiredFundsToFinancialAccountInput! ) { initiateAddWiredFundsToFinancialAccount(input: $input) { __typename ... on ReviewWorkflowEvent { id reviewState createdAt updatedAt transfer { __typename ... on WireTransfer { id type } } reviewItem { __typename ... on WireTransferReview { toFinancialAccount { __typename id } memo amount { ... on Amount { currencyCode value } } externalIdentifier } } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "toFinancialAccountId": "", "memo": "240926-HNS", "idempotencyKey": "00000000-0000-0000-0000-000000000000", "amount": { "value": 500000, "currencyCode": "USD" }, "externalIdentifier": "an additional reference ID" } } Expected Result: { "data": { "initiateAddWiredFundsToFinancialAccount": { "__typename": "ReviewWorkflowEvent", "id": "", "reviewState": "PENDING", "createdAt": "2025-01-23T21:13:41.685Z", "updatedAt": "2025-01-23T21:13:41.707Z", "transfer": null, "reviewItem": { "__typename": "WireTransferReview", "toFinancialAccount": { "__typename": "FinancialAccount", "id": "" }, "memo": "Initiate workflow approval for wire transfer", "amount": { "currencyCode": "USD", "value": 999999 }, "externalIdentifier": "2b43fc97-2541-43fc-8dd6-6ab414ad0a48" } } } } ### GraphQL: NodeWireTransferApprovalEvent Query: query nodeWireTransferApprovalEvent($id: ID!) { node(id: $id) { __typename ... on ReviewWorkflowEvent { id reviewState createdAt updatedAt transfer { __typename ... on WireTransfer { __typename id memo type status ledgers { name debitBalance { value } creditBalance { value } } } } reviewItem { __typename ... on WireTransferReview { toFinancialAccount { __typename id } memo amount { value currencyCode } externalIdentifier } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "ReviewWorkflowEvent", "id": "", "reviewState": "COMPLETED", "createdAt": "2025-01-23T21:13:41.685Z", "updatedAt": "2025-01-23T21:14:17.886Z", "transfer": { "__typename": "WireTransfer", "id": "", "memo": "Initiate workflow approval for wire transfer", "type": "INCOMING_WIRE_TRANSFER", "status": "COMPLETED", "ledgers": [ { "name": "CASH", "debitBalance": { "value": 999999 }, "creditBalance": { "value": 0 } }, { "name": "FUND_IN_HOLD", "debitBalance": { "value": 0 }, "creditBalance": { "value": 0 } }, { "name": "FUND_IN_HOLD", "debitBalance": { "value": 0 }, "creditBalance": { "value": 0 } }, { "name": "AVAILABLE_CASH", "debitBalance": { "value": 0 }, "creditBalance": { "value": 999999 } }, { "name": "CREDIT_OUTSTANDING", "debitBalance": { "value": 999999 }, "creditBalance": { "value": 0 } }, { "name": "AVAILABLE_CREDIT", "debitBalance": { "value": 0 }, "creditBalance": { "value": 999999 } } ] }, "reviewItem": { "__typename": "WireTransferReview", "toFinancialAccount": { "__typename": "FinancialAccount", "id": "" }, "memo": "Initiate workflow approval for wire transfer", "amount": { "value": 999999, "currencyCode": "USD" }, "externalIdentifier": "2b43fc97-2541-43fc-8dd6-6ab414ad0a48" } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/add-funds-to-balance Title: Add Funds to your Program Funding Account Balance Section: Issuing Description: Fund your product funding account via wire transfers in the Live environment or simulated wire transfers in Test. ## Overview Card products have an underlying financial account called the product funding account. Like all financial accounts, the product funding account has its own associated set of ledgers. The ledgers for your product funding account differ based on your card product's vertical. Funding your product funding account differs for Live and Test environments: - **Live environment**: Your product funding account has an account and routing number, and may be funded via wire transfer from an external bank account. - **Test environment**: You can Simulate Funding your Balance via Wire Transfer to test your integration. Your product funding account's role depends on your card product vertical. The following table provides an overview of each card product vertical and its associated product funding account role: | Card Product Vertical | Product Funding Account Role | | :-------------------- | :---------------------------------------------------------------------------------------------------------------------- | | Prepaid debit | Covers negative balances in account holder financial accounts and issues provisional credits | | Charge | Backs the line of credit issued to financial accounts | | Secured charge | Backs the line of credit issued to financial accounts | | Fleet | Backs the line of credit issued to financial accounts | | AP automation | Provides funds to account holder financial accounts via funds load | | Prepaid | Provides funds to account holder financial accounts via funds load | | Payroll | Provides payroll advance, covers negative balances in account holder financial accounts, and issues provisional credits | ## Transfer methods The speed and cost of transfer methods varies. The following table outlines the transfer methods available for product funding accounts, and the speed of each method: | Transfer Method | Speed | | :------------------------- | :---------------- | | Wire transfer | Same business day | | Internal Highnote transfer | Within seconds | ## Find your product funding account ID To fund your product funding account in the Live environment, you will initiate a wire transfer outside of Highnote. This does not require knowing your product funding account ID. To fund your product funding account using an internal Highnote transfer or to simulate a wire transfer in the Test environment, you must use your product funding account ID. You can use the following query to find your product funding account ID using the Highnote API. In the response payload, the ID in the field is your product funding account ID: ## Simulate a wire transfer In the Test environment, use the following mutation to simulate a wire transfer to fund your product funding account: ## Find wire transfers After a wire transfer is initiated, you can use the Highnote API to find incoming and outgoing wire transfers. The direction of a wire transfer is defined as follows: - **Incoming**: Money is coming into a Highnote financial account via wire transfer. - **Outgoing**: Money is leaving a Highnote financial account via wire transfer. ### Incoming wire transfers Use the following query to find an incoming wire transfer: ### Outgoing wire transfers Use the following query to find an outgoing wire transfer: ## Find wire transfer reversals Wire transfer reversals occur when a wire transfer has been reversed by Highnote's support team. In the event of a wire transfer reversal, a memo is left on the wire transfer to state the reason for the reversal. The direction of a wire transfer reversal is defined as follows: - **Incoming**: An incoming wire transfer has been reversed by the Highnote support team. - **Outgoing**: An outgoing wire transfer has been reversed by the Highnote support team. ### Incoming wire transfer reversal Use the following query to find an incoming wire transfer reversal: ### Outgoing wire transfer reversal Use the following query to find an outgoing wire transfer reversal: ## 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: - : Product funding account ID - : Account holder's payment card financial account ID ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "name": "Business Prepaid", "usage": "MULTI_USE", "accounts": { "edges": [ { "node": { "id": "", "name": "Business Prepaid - Product Funding", "features": [ { "__typename": "ProductFundingFinancialAccountFeature", "enabled": true }, { "__typename": "AchCapableFinancialAccountFeature", "enabled": true } ], "accountStatus": "ACTIVE", "owner": { "__typename": "Organization" } } }, { "node": { "id": "", "name": "Business Prepaid - Negative Balance Reserve", "features": [ { "__typename": "NegativeBalanceReserveFinancialAccountFeature", "enabled": true } ], "accountStatus": "ACTIVE", "owner": { "__typename": "Organization" } } }, { "node": { "id": "", "name": "Business Prepaid - Product Reserve ", "features": [ { "__typename": "ProductReserveFinancialAccountFeature", "enabled": true } ], "accountStatus": "ACTIVE", "owner": { "__typename": "Organization" } } } ] } } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 1500, "currencyCode": "USD" }, "toFinancialAccountId": "MC40LmFj", "memo": "", "source": "WIRE" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "Transfer" } }, "extensions": { "requestId": "19070e66-2fd9-968a-94be-85c4836eae7b" } } ### GraphQL: NodeWireTransfer Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an incoming wire transfer", "type": "INCOMING_WIRE_TRANSFER", "status": "COMPLETED", "financialAccount": { "id": "" } } } } ### GraphQL: NodeWireTransfer Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an outgoing wire transfer", "type": "OUTGOING_WIRE_TRANSFER", "status": "COMPLETED", "financialAccount": { "id": "" } } } } ### GraphQL: NodeWireTransfer Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an incoming wire transfer reversal", "type": "INCOMING_WIRE_TRANSFER_REVERSAL", "status": "COMPLETED", "financialAccount": { "id": "" } } } } ### GraphQL: NodeWireTransfer Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an outgoing wire transfer reversal", "type": "OUTGOING_WIRE_TRANSFER_REVERSAL", "status": "COMPLETED", "financialAccount": { "id": "" } } } } ### GraphQL: 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": "", "fromFinancialAccountId": "", "memo": "unload card", "amount": { "value": 5000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccount": { "__typename": "InterFinancialAccountTransfer", "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" } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/check-payment Title: Check Payment Section: Issuing Description: Send physical check payments from financial accounts. Covers address validation, shipping methods, check events, and signature requirements for checks over $2,000. ## Overview To enable Check Payment, contact your Highnote implementation team or support@highnote.com. Subscribers can enable their systems to let account holders send payments by check. Checks are funded by a . Checks greater than $2,000 USD must have a signature of the Primary Authorized Person linked to the . ## Attaching a signature to a FinancialAccount Only checks greater than or equal to $2,000 require a signature. Signatures must be uploaded as an image file (PNG, JPG, or BMP) and attached to a . Highnote automatically converts uploads to PNG. High-level steps are: 1. Create an upload session to attach the signature to a . 1. Upload the signature to Highnote with either the Document Upload SDK or the Highnote GraphQL API. ## Create check payment upload session To begin, create a check payment document upload session to associate a signature with a . ## Upload signature to Highnote Next, upload the signature to Hignote. Signatures can be uploaded to Highnote one of two ways: - The Document Upload SDK lets users upload their own signature file. - The Highnote GraphQL API can upload a signature if the file is already present. If you use the Highnote GraphQL API, the document upload process consists of the following steps: 1. _Optional_ - Generate a client token. 1. Start a document upload session to Highnote 1. Create a document upload link 1. Upload the signature with the upload link. 1. End the document upload session ### Start document upload session For compliance reasons, you must generate a client token to make requests directly from your client if you are not using a server or do not have access to one. See Client Tokens. The Start mutation generates a session URL. Upload sessions expire 30 days from creation; and each session notifies you of any requirements your system needs to enforce to upload the file. Use the following mutation to start a document upload session: ### Create document upload link Document upload links expire 5 minutes after creation. Each upload link created with this mutation represents a single upload file. If, for example, you are required to upload two signature files, you must create a unique link for each. When creating upload links, the document upload session status transitions to . You can use the field in the mutation's response to stream the document upload. To create a document upload link, use the from the response for this mutation's variable field: ### End the document upload session After the signature has been uploaded, you can end the document upload session. When ending a session, the session status transitions to and no other actions can be taken. If more documentation is required, a new session must be started to upload the additional documents. Use the following mutation to end a document upload session: ## Initiate a physical check payment Refer to the check image below to see how physical check items map to API fields. To begin a check payment, call the mutation using a sufficiently funded and a recipient's name and an address (ideally, a ). #### Address Validation Before initiating a check payment, Highnote recommends that you utilize the Address Validation service (below) to ensure the recipient's address is correctly formatted and verified. Steps are: 1. Call to check if the check payment address is valid. 1. From the response, copy representing the validated address. 1. Call with the response token Id. #### Shipping Method You can specify the type of check and the shipping method when initiating a check payment. The check funding process takes 2-3 business days to complete, in addition to the stated mailing times. The following shipping methods are supported: | **Method** | **Timing** | **Carrier** | | :---------- | :---------------- | :----------- | | | 2-5 business days | USPS | | | 2-5 business days | USPS | | | 2 days | FEDEX or UPS | | | Next day | FEDEX or UPS | ## Validate check payment address You can validate the check payment address using the mutation. This mutation validates addresses using a CASS-certified service to ensure it is properly formatted to reduce possible shipping delays or returns. The Highnote API returns an response with a validated address token, or an error message explaining why the address is invalid. ## Initiate physical check payment with validated address token Use the following mutation to initiate a check payment with a : ## Initiate physical check payment with unvalidated address While not recommended, you can use the following mutation to initiate a check payment with an unvalidated address. To use a validated address instead, see Initiate physical check payment with validated address token (above). ## Check payment event types Payments made by check follow an event lifecycle with the possible types outlined below. Your platform receives a notification event as each check payment transitions to a new type. The Highnote transaction event and notification event for all check payment types is the CheckPaymentEvent. For typical "happy path" check payments, subscribers can expect to receive events in the order as presented in the following table: | # | Event Type | Description | | :-- | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------- | | | Happy path order of events | | | 1 | | The check has been initiated and is pending processing by Highnote. | | 2 | | The check is being processed and validated by Highnote. It is being checked for funds availability and risk analysis. | | 3 | | The check has been processed by Highnote and is awaiting funding to our check provider. | | 4 | | The check has been picked up by the daily check cutoff window for funding. | | 5 | | The check funding to our external check provider has been initiated. | | 6 | | The check has been funded and is pending disbursement. | | 7 | | The funds have been disbursed to external accounts. | | 8 | | The check has been printed. | | 9 | | The check has been printed and is pending shipment. | | 10 | | The check has been shipped. | | 11 | | The check has been deposited by the recipient. | | 12 | | The check has been deposited by the recipient and the ledgers against the have been reconciled. | | | Alternative events | | | | | The check has been put on hold for risk assessment. | | | | The check has been voided. | | | | The check has failed. The reason for the failure is included in the event. | | | | The check has been reversed due to voiding or failure. | | | | The check reversal has been completed. | ## Query for check payments Use the following mutations to query for one check payment or list multiple check payments. ### View a check payment Use the query to query for a . ## List check payments Use the query to return a list of . The query can return all check-related fields including the check image. ## Simulate check payment event changes Simulating an event is an asynchronous action. Highnote sends a webhook event and adds the event shortly after the simulation. Use the SimulateCheckPaymentEvent mutation below to test different Check Payment event types. In the Test environment, a Check Payment does not progress past the event type in the Check Payment workflow. But you can simulate the progress of a check payment by triggering the mutation with a specific event type. For example, triggers a event. You can only actively simulate 5 event types (below), and only in the given order. The Highnote platform applies the other event types as appropriate. For example, when you simulate paying out by check, you trigger the event type. Highnote then moves it to . | Sim Order | Event Type | Description | | :-------: | :------------------ | :------------------------------------------------------------------- | | 1 | | The check funding to our external check provider has been initiated. | | 2 | | The check has been funded and is pending disbursement. | | 3 | | The funds have been disbursed to external accounts. | | 4 | | The check has been shipped. | | 5 | | The check has been deposited by the recipient. | ## Check image The following image maps API fields to the physical check: 1. Business account holder _or_ Personal account holder and 2. : InitiatePhysicalCheckPaymentInput 3. : InitiatePhysicalCheckPaymentInput 4. : InitiatePhysicalCheckPaymentInput 5. Uploaded signature ### GraphQL: CreateCheckPaymentDocumentUploadSession Query: mutation CreateCheckPaymentDocumentUploadSession( $input: CreateCheckPaymentDocumentUploadSessionInput! ) { createCheckPaymentDocumentUploadSession(input: $input) { __typename ... on DocumentUploadSession { id } } } Variables: { "input": { "financialAccountId": "", "documentTypes": [ "ACCOUNT_HOLDER_SIGNATURE" ] } } Expected Result: { "data": { "createSignatureUploadSession": { "__typename": "CheckPaymentDocumentUploadSession", "id": "" } } } ### GraphQL: StartDocumentUploadSession Query: mutation StartDocumentUploadSession($input: StartDocumentUploadSessionInput!) { startDocumentUploadSession(input: $input) { ... on Node { id } ... on CheckPaymentDocumentUploadSession { id status } } } Variables: { "input": { "documentUploadSessionId": "my-signature-upload-session" } } Expected Result: { "data": { "startDocumentUploadSession": { "id": "start-document-upload-session-id", "status": "INITIATED" } } } ### GraphQL: CreateDocumentUploadLink Query: mutation CreateDocumentUploadLink($input: CreateDocumentUploadLinkInput!) { createDocumentUploadLink(input: $input) { ... on Node { id } ... on DocumentUploadLink { id uploadUrl } } } Variables: { "input": { "documentUploadSessionId": "my-signature-upload-session", "documentType": "ACCOUNT_HOLDER_SIGNATURE" } } Expected Result: { "data": { "createDocumentUploadLink": { "id": "signature-upload-link-id", "uploadUrl": "https://storage.googleapis.upload-to-bucket" } } } ### GraphQL: EndDocumentUploadSession Query: mutation EndDocumentUploadSession($input: EndDocumentUploadSessionInput!) { endDocumentUploadSession(input: $input) { ... on DocumentUploadSession { status } } } Variables: { "input": { "documentUploadSessionId": "my-signature-upload-session" } } Expected Result: { "data": { "endDocumentUploadSession": { "status": "SUBMITTED" } } } ### GraphQL: ValidateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { __typename ... on AddressValidatedWithChangesResult { token { id } } ... on AddressValidatedResult { token { id } } } } } } Variables: { "input": { "idempotencyKey": "idempotency-key", "address": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "postalCode": "94107-2134", "region": "CA", "locality": "SAN FRANCISCO", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressValidatedResult", "token": { "id": "tkvad_1" } } } } } ### GraphQL: InitiatePhysicalCheckPayment Query: mutation InitiatePhysicalCheckPayment( $input: InitiatePhysicalCheckPaymentInput! ) { initiatePhysicalCheckPayment(input: $input) { __typename ... on CheckPayment { id amount { __typename value currencyCode decimalPlaces } recipient { __typename name address { __typename streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } checkType shippingTime status events { __typename id type } } } } Variables: { "input": { "financialAccountId": "ac_1", "amount": { "value": 100, "currencyCode": "USD" }, "recipient": { "name": "John Doe", "validatedAddressTokenId": "tkvad_1" }, "shippingTime": "STANDARD" } } Expected Result: { "data": { "initiatePhysicalCheckPayment": { "__typename": "CheckPayment", "id": "eftck_1", "amount": { "__typename": "Amount", "value": 100, "currencyCode": "USD", "decimalPlaces": 2 }, "recipient": { "__typename": "CheckPaymentRecipient", "name": "John Doe", "address": { "__typename": "Address", "streetAddress": "123 Main St", "extendedAddress": "Apt 1", "postalCode": "12345", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "checkType": "PHYSICAL", "shippingTime": "STANDARD", "status": "PENDING", "events": [ { "__typename": "CheckPaymentEvent", "id": "eftct_1", "type": "FUNDING_PENDING" } ] } } } ### GraphQL: InitiatePhysicalCheckPayment Query: mutation InitiatePhysicalCheckPayment( $input: InitiatePhysicalCheckPaymentInput! ) { initiatePhysicalCheckPayment(input: $input) { __typename ... on CheckPayment { id amount { __typename value currencyCode decimalPlaces } recipient { __typename name address { __typename streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } checkType shippingTime status events { __typename id type } } } } Variables: { "input": { "financialAccountId": "ac_1", "amount": { "value": 100, "currencyCode": "USD" }, "recipient": { "name": "John Doe", "address": { "streetAddress": "123 Main St", "extendedAddress": "Apt 1", "postalCode": "12345", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "shippingTime": "STANDARD" } } Expected Result: { "data": { "initiatePhysicalCheckPayment": { "__typename": "CheckPayment", "id": "eftck_1", "amount": { "__typename": "Amount", "value": 100, "currencyCode": "USD", "decimalPlaces": 2 }, "recipient": { "__typename": "CheckPaymentRecipient", "name": "John Doe", "address": { "__typename": "Address", "streetAddress": "123 Main St", "extendedAddress": "Apt 1", "postalCode": "12345", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "checkType": "PHYSICAL", "shippingTime": "STANDARD", "status": "PENDING", "events": [ { "__typename": "CheckPaymentEvent", "id": "eftct_1", "type": "FUNDING_PENDING" } ] } } } ### GraphQL: QueryCheckPayment Query: query QueryCheckPayment($id: ID!) { node(id: $id) { __typename ... on CheckPayment { id amount { value decimalPlaces currencyCode } recipient { __typename name address { __typename streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } checkType shippingTime status failureReason events { __typename id type } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CheckPayment", "id": "", "amount": { "value": 1, "decimalPlaces": 2, "currencyCode": "USD" }, "recipient": { "__typename": "CheckPaymentRecipient", "name": "John Doe", "address": { "__typename": "Address", "streetAddress": "123 Main St", "extendedAddress": "Apt 1", "postalCode": "12345", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "checkType": "PHYSICAL", "shippingTime": "STANDARD", "status": "FUNDING_PENDING", "failureReason": null, "events": [ { "__typename": "CheckPaymentEvent", "id": "", "type": "FUNDING_PENDING" }, { "__typename": "CheckPaymentEvent", "id": "", "type": "PENDING_PROCESSING_BY_HIGHNOTE" } ] } } } ### GraphQL: ListCheckPayments Query: query ListCheckPayments($financialAccountId: ID!, $first: Int, $after: String) { node(id: $financialAccountId) { __typename ... on FinancialAccount { checkPayments(first: $first, after: $after) { __typename ... on CheckPaymentsConnection { edges { node { id amount { __typename value currencyCode decimalPlaces } recipient { __typename name address { __typename streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } checkType shippingTime status events { __typename id type } } } } } } } } Variables: { "financialAccountId": "ac_1", "first": 20 } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "searchCheckPayments": { "__typename": "SearchCheckPaymentsConnection", "edges": [ { "node": { "id": "eftck_1", "amount": { "__typename": "Amount", "value": 100, "currencyCode": "USD", "decimalPlaces": 2 }, "recipient": { "__typename": "CheckPaymentRecipient", "name": "John Doe", "address": { "__typename": "Address", "streetAddress": "123 Main St", "extendedAddress": "Apt 1", "postalCode": "12345", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "checkType": "PHYSICAL", "shippingTime": "STANDARD", "status": "PENDING", "events": [ { "__typename": "CheckPaymentEvent", "id": "eftct_1", "type": "FUNDING_PENDING" } ] } } ] } } } } ### GraphQL: SimulateCheckPaymentEvent Query: mutation SimulateCheckPaymentEvent($input: SimulateCheckPaymentEventInput!) { simulateCheckPaymentEvent(input: $input) { __typename ... on UserError { errors { code errorPath description } } ... on CheckPayment { id amount { value } recipient { __typename name address { __typename streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } checkType shippingTime status events { __typename id type } } } } Variables: { "input": { "checkPaymentId": "", "checkEventType": "FUNDING_STARTED" } } Expected Result: { "data": { "simulateCheckPaymentEvent": { "__typename": "CheckPayment", "id": "", "amount": { "value": 1 }, "recipient": { "__typename": "CheckPaymentRecipient", "name": "John Doe", "address": { "__typename": "Address", "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "postalCode": "94107-2134", "region": "CA", "locality": "SAN FRANCISCO", "countryCodeAlpha3": "USA" } }, "checkType": "PHYSICAL", "shippingTime": "STANDARD", "status": "PENDING", "events": [ { "__typename": "CheckPaymentEvent", "id": "", "type": "FUNDING_PENDING" }, { "__typename": "CheckPaymentEvent", "id": "", "type": "PENDING_PROCESSING_BY_HIGHNOTE" } ] } }, "extensions": { "requestId": "ec582845-68af-964f-93ef-e5c9f2d613c9", "rateLimit": { "cost": 14 } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/connect-external-accounts-finicity Title: Link External Accounts with Finicity Section: Issuing Description: Connect external bank accounts using Finicity for verified fund-in transfers or non-verified fund-out transfers. ## 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 | | :------------------------------------------ | :------- | :---------------------- | | | Yes | Fund-in or Fund-out | | | 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: 1. Sign up for Finicity API keys. 2. Create a Finicity access token to onboard your account holders. 3. 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 . When testing, input this value as the . 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: 1. Generate a Finicity-App-Token. 2. Create a test customer in Finicity. 3. Generate a Connect URL and simulate customer linking bank accounts to Finicity. 4. Refresh customer accounts. 5. Generate a 3rd party API access token to send to Highnote. Use the following POST request to : #### Headers ```bash Accept: application/json, Content-Type: application/json, Finicity-App-Token: , Finicity-App-Key: ``` #### Body (raw, JSON) ```json { "customerId": "", "partnerId": "", "thirdPartyPartnerId": "2445583993914", "products": [ { "product": "moneyTransferDetails", "payorId": "", "maxCalls": 1000, "accountId": "", "accessPeriod": { "type": "timeframe", "startTime": "2022-03-10T06:06:20Z", "endTime": "2023-03-10T06:06:20Z" } }, { "product": "availableBalanceLive", "payorId": "", "maxCalls": 1000, "accountId": "", "accessPeriod": { "type": "timeframe", "startTime": "2022-03-10T06:06:20Z", "endTime": "2023-03-10T06:06:20Z" } }, { "product": "accountOwner", "payorId": "", "maxCalls": 1000, "accountId": "", "accessPeriod": { "type": "timeframe", "startTime": "2022-03-10T06:06:20Z", "endTime": "2023-03-10T06:06:20Z" } } ] } ``` #### Sample response ```json { "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 | | :--------------------- | :------------------------- | | | | | | | | | | Use the following mutation to add an external bank account with Finicity: ## 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. ## List external accounts Use the following query to view and present a list of an account holder's external bank accounts: ## Disconnect external account Use the following mutation to disconnect a verified or non-verified external bank account: ### GraphQL: 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": "", "name": "Finicity Checking", "bankAccountType": "CHECKING", "externalToken": { "receiptId": "processor-token-success", "customerId": "5543088633794259024", "products": [ { "productType": "ACH_DETAILS", "accountId": "", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } }, { "productType": "CURRENT_BALANCE", "accountId": "", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } }, { "productType": "ACH_OWNER_DETAILS", "accountId": "", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } } ] } } } Expected Result: { "data": { "addExternalBankAccountVerifiedThroughFinicity": { "__typename": "ExternalFinancialBankAccount", "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": "", "createdAt": "2022-08-26T20:24:22.557Z", "updatedAt": "2022-08-26T20:24:22.730Z", "last4": "9606", "type": "CHECKING", "routingNumber": "011401533" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "bankAccountType": "CHECKING" } } Expected Result: { "data": { "addNonVerifiedExternalUSFinancialBankAccount": { "__typename": "NonVerifiedExternalUSFinancialBankAccount", "id": "", "name": "My Checking Account", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z", "externalBankAccountDetails": { "id": "", "last4": "8910", "type": "CHECKING", "routingNumber": "111000025", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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 Node { id } ... on ExternalFinancialBankAccount { id name ledgers { name } externalBankAccountDetails { id last4 type routingNumber createdAt updatedAt } } } } } } } Variables: { "first": 20 } Expected Result: { "data": { "businessAccountHolders": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "", "externalFinancialAccounts": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "ExternalFinancialBankAccount", "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": "" } } ### GraphQL: 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": "" } } Expected Result: { "data": { "closeExternalBankAccount": { "__typename": "ExternalFinancialBankAccount", "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": "" }, "businessProfile": { "id": "" } }, "ledgers": [ { "id": "", "name": "AVAILABLE_CASH" }, { "id": "", "name": "CASH" } ], "features": [ { "__typename": "AchCapableFinancialAccountFeature", "enabled": true }, { "__typename": "VendorProvidedBankFinancialAccountFeature", "enabled": true } ], "externalBankAccountDetails": { "id": "", "createdAt": "2022-02-23T14:25:17.336Z", "updatedAt": "2022-02-23T14:25:17.995Z", "last4": "8546", "type": "CHECKING", "routingNumber": "011401533" } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/connect-external-accounts Title: Link External Accounts with Plaid Section: Issuing Description: Connect external bank accounts using Plaid with Hosted URL, Plaid SDK, or direct processor token integration. Supports verified and non-verified accounts. ## 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 Plaid to verify and connect external bank accounts securely and with NACHA compliance. ## Integration paths The Highnote platform offers three integration paths for Plaid: - **Hosted URL Integration:** No-code solution where Highnote manages the Plaid relationship on your behalf. Best for reducing compliance burden and frontend development. - **Plaid SDK Integration:** Highnote manages the Plaid relationship, but you integrate the Plaid Link SDK into your application for a native experience. - **Connect verified account with Plaid:** You maintain a direct relationship with Plaid, authenticate users in your application, and pass verification details to Highnote via . Contact your Highnote representative about Plaid products and pricing available for your program. ## External bank account types {#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 | | :------------------------------------------ | :------- | :---------------------- | | | Yes | Fund-in or Fund-out | | | No | Fund-out on debit cards | ## Prerequisite: Complete Plaid onboarding form {#step-0-complete-plaid-onboarding-form} Delegating your Plaid relationship to Highnote reduces your compliance requirements as Highnote provides and manages a secure vault. Using the no-code hosted URL solution also removes your need for frontend SDK development. All users should complete Highnote's **Plaid Onboarding form**. The Hosted URL and Plaid SDK integrations both _require_ completing the onboarding form. The form requests the information outlined below. ### Company / Application Details - Company email, name, URL - Legal name and address - Assets Under Management (amount and currency) - Application (or company) name and icon ### Integration Details Highnote supports Plaid's Auth, Balance, and Identity payment products by default. - Plaid Link configuration: Customizable or Plaid default - Integration flow: Hosted URL (no-code) or SDK - SDKs to integrate: Web, iOS, Android, React Native, Mobile webview. - Redirect URI. When integrating via SDK, this is [](https://plaid.com/docs/api/link/#link-token-create-request-redirect-uri) or [](https://plaid.com/docs/api/link/#link-token-create-request-android-package-name) (which is the [](/docs/api-reference/input#VerifiedExternalBankAccountLinkExperience) used in Step 2): - Web SDK: Web SDK redirect URI - Apple iOS: Universal Link redirect URI - Android, React Native: Android package name Highnote requires a redirect URI per SDK integration even if the mutation input variable is optional. ### Contacts - Technical Contact name and email - Billing Contact name and email - Customer Support email, and optionally phone, URL, link update URL ### What's Possible | Feature | Supported | Description | | :--------------------------------------------------------------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Link customization | Yes | Subscribers can customize their integrations after completing the Highnote Onboarding form. | | US OAuth institutions | Yes | Highnote handles registration with all Plaid-supported financial institutions. | | Developer log access | Passed-through | Highnote surfaces Plaid integration-related errors under in the API mutation response. | ## Testing your Plaid workflows Highnote only supports and account types at this time. You can test your Plaid workflows with dummy data from Plaid. Some banks, such as Chase, are supported with restrictions. Refer to the Plaid documentation for support: - Plaid Sandbox Overview - OAuth Guide Chase restrictions are: - Must have full Production access for at least one product and have also completed the OAuth registration process - Chase has an additional waiting period; it may take up to two weeks after Production approval for Chase Production access to be granted. You must also complete the Security Questionnaire. ## Authentication methods Both the Hosted URL and Plaid SDK integrations use Plaid Link, which supports the following authentication methods. When an end user connects their bank account, Plaid automatically selects the best method based on the capabilities of the user's financial institution. No integration changes are required. | Method | Verification time | How it works | | :--------------------------------------------------------------------------------------------- | :---------------------- | :------------------------------------------------------------------------------------------------ | | Instant Auth | Instant | User logs in with their bank credentials. | | Instant Micro-deposits | ~5 seconds | Plaid sends a $0.01 deposit via RTP or FedNow. User enters the code from the deposit description. | | Automated Micro-deposits | 1–2 business days | Plaid initiates a micro-deposit that verifies automatically without user action. | | Same-day Micro-deposits | Up to 1 business day | Plaid sends a Same Day ACH deposit. User enters the code from the deposit description. | ## Hosted URL Integration To connect a verified Plaid account with Highnote via the no-code hosted solution: - Step 0: Complete Highnote's Plaid Onboarding form. - Step 1: Integrate Plaid Hosted URL with your application. - Step 2: Create a with the Highnote API (and ). - Step 3: Query the status of your external account link. ### Step 1. Integrate Plaid Hosted Link Refer to the Plaid Hosted Link documentation to integrate Plaid Link into your application. ### Step 2. Create hosted URL Create a Highnote with set to . You can send the generated URL to an end user to start the Hosted Link session. Use the following mutation to generate a **** for an account holder (or end user): ### Step 3. Get link status Monitor the status of the external bank account to check whether the account holder successfully linked their account. You can either subscribe to external bank account events with a webhook, or poll with the following query. ## Plaid SDK Integration Refer to the Plaid Link documentation on SDK integration for more guidance. To connect a verified account with Highnote via SDK: - Step 0: Complete Highnote's Plaid Onboarding form. - Step 1: Integrate Plaid Link with your application. - Step 2: Create a **** with the Highnote API (e.g., ). - Step 3: Initiate Plaid Link by using the to retrieve a . - Step 4: Link an external bank account by sending the to Highnote. - Step 5: Query the status of your external account link. ### Step 1. Integrate Plaid Link Refer to the Plaid Link documentation to integrate the Plaid Link SDK into your application. ### Step 2. Create link token {#step-2-create-link-token-or-hosted-url} Create a Highnote with set to your chosen SDK. Use this token to initiate Plaid Link (in the next step) and generate a in Plaid. In the Test environment, Highnote gives you a to generate a in Plaid's Sandbox environment. Your card product must be configured by Highnote for the Plaid integration. ### Step 3. Initialize Plaid Link {#step-3-initialize-plaid-link-sdk-only} Generate a in Plaid with the from Step 2 to initialize Plaid Link. Plaid Link provides a temporary in the callback. The details for passing the vary by platform. See the page for your specific platform integration: web, iOS, Android, React Native, or mobile webview. In Highnote's Test environment, you can create a in all three of Plaid's API environments: - **Plaid Sandbox**: Test simulated users - **Plaid Limited Production**: Test live users - **Plaid Production**: Production environment for when you're ready to go live and have valid Highnote Live environment API keys. ### Step 4. Link external account with public token {#step-4-link-external-account-with-public-token-sdk-only} Call the mutation to link an external bank account with Plaid's ephemeral . Highnote will create a persistent and use it to call various Plaid products for the account holder. In the Test environment, provide the you received from Plaid's Sandbox environment or one of the simulated values below. | Simulated Public Token Value | Result | | :--------------------------------------- | :------ | | public-token-success | Success | | public-token-no-ach-account-number | Failure | | public-token-no-routing-account-number | Failure | | public-token-wrong-sub-type | Failure | | public-token-wrong-currency-code | Failure | | public-token-wrong-length-account-number | Failure | | public-token-wrong-length-routing-number | Failure | | public-token-non-digit-routing-number | Failure | | public-token-not-found | Failure | | public-token-institution-down | Failure | | public-token-item-login-required | Failure | ### Step 5. Get link status Monitor the status of the external bank account to check whether the account holder successfully linked their account. You can either subscribe to external bank account events with a webhook, or poll with the following query. ## Connect verified account with Plaid {#connect-verified-account-with-plaid} As a subscriber, you can integrate with Highnote while maintaining your direct relationship with Plaid. You authenticate end-user bank accounts in your applications with Plaid, and then securely pass verification details to Highnote with . Refer to the Plaid documentation, Add Highnote to your app. To connect a verified account with Plaid: - Step 0: Set up your Plaid account and sign up for Plaid API keys. - Step 1: Enable your Plaid account for Highnote integration on the Plaid dashboard. - Step 2: Create a in Plaid. - Step 3: Get Plaid's Highnote by exchanging it with the . - Step 4: Link an external bank account by sending the to Highnote. - Step 5: Test your Plaid connections. ### Prerequisite: Set up your Plaid account {#step-0-set-up-your-plaid-account} This step is a prerequisite to connecting a verified account with Plaid. Create a business or developer Plaid account. On the Plaid dashboard, go to the Keys tab and create Plaid API keys. ### Step 1. Enable Plaid account for Highnote Highnote requires only one bank account. If a user has multiple bank accounts, the array from Plaid may contain information from all of them. To ensure the array contains only one, go to the Plaid dashboard and set Account Select to "enabled for one account". Follow the Plaid docs to enable your Plaid account for Highnote integration. On the Plaid dashboard: - Go to the **Integrations** tab, click enable Highnote. - Go to the **Application** tab, complete your application profile. - Go to the **Link customization** tab, select the use cases you want to use with Highnote. ### Step 2. Create a Plaid link token Follow the Plaid docs to create a one-time Plaid . You will use this token to exchange it for a "Highnote" to send to Highnote. ### Step 3. Get Plaid's Highnote processor token Follow the Plaid docs to exchange your for a Plaid "Highnote" . ### Step 4. Link external account with processor token Processor token errors must be resolved with Plaid. Refer to Plaid Errors. Use the mutation to link an external bank account with Plaid's . Highnote retrieves the account number, routing number, and account type from Plaid, and links the information to the associated account holder for future payment usage. If the response includes a processor token error, get a new from Plaid and reattempt adding the external bank account. All processor token errors must be resolved with Plaid. In some cases, your customer may need to resubmit their bank account credentials for you to retrieve a new . See the Plaid docs for a list of possible Plaid-related errors. Use the following mutation to add an external bank account using Plaid: ### Step 5. Test Plaid connections To test Plaid, you will need to use your . You can create Highnote in all three of Plaid's API environments: - **Plaid Sandbox**: Test simulated users - **Plaid Development**: Test live users - **Plaid Production**: Production environment for when you're ready to go live and have valid Highnote Live environment API keys ## 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 Plaid. 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. ## List external accounts You can view and present a list of an account holder's external bank accounts using the following query: ## Disconnect external account The CloseExternalFinancialBankAccount mutation lets you support the following disconnect experiences: - Provide an interface for account holders to disconnect external accounts from your app or website. - Provide an interface for your organization's support team to disconnect external accounts. Guidelines for disconnecting an external bank account: - When the external bank account is disconnected, all scheduled payments associated with it are canceled. If the Highnote financial account associated with the external bank account has a pending payment, the account cannot be disconnected until all pending payments are settled. - Customers must re-verify their identity to reconnect a _verified_ external bank account to their Highnote financial account. - Customers do not need to re-verify their identity to reconnect a _non-verified_ external bank account to their Highnote financial account. Use the following mutation to disconnect a verified or non-verified external bank account: ### GraphQL: GenerateVerifiedExternalBankAccountLinkToken Query: mutation GenerateVerifiedExternalBankAccountLinkToken( $input: GenerateVerifiedExternalBankAccountLinkTokenInput! ) { generateVerifiedExternalBankAccountLinkToken(input: $input) { __typename ... on GenerateVerifiedExternalBankAccountExternalLinkToken { externalLinkToken expirationDate accountHolder { __typename ... on Node { id } ... on USPersonAccountHolder { id email dateOfBirth externalId updatedAt createdAt } ... on USBusinessAccountHolder { id } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "linkExperience": { "flow": "ANDROID_SDK", "redirectUri": "com.example" } } } Expected Result: { "data": { "generateVerifiedExternalBankAccountLinkToken": { "__typename": "GenerateVerifiedExternalBankAccountExternalLinkToken", "externalLinkToken": "link-sandbox-b1b8b1ef-065b-18e9-aab3-ee396895efda", "expirationDate": "2024-12-03T21:19:01.056Z", "accountHolder": { "__typename": "USBusinessAccountHolder", "id": "" } } }, "extensions": { "requestId": "b3ef5ec2-92c5-9644-8108-3650398d8f9d", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60049 } } } ### GraphQL: AccountHolderProvisioning Query: query AccountHolderProvisioning($id: ID!) { node(id: $id) { ... on AccountHolderProvisioning { __typename id idempotencyKey createdAt updatedAt outcome { status } workflowActions { __typename id action actionInput { linkVerifiedExternalBankAccountInput { publicToken } } outcome { status } executionOrder node { __typename ... on UserError { errors { errorPath code description } } ... on WorkflowActionResultOutcome { createdAt updatedAt result { __typename ... on WorkflowActionLinkVerifiedExternalBankAccountResult { externalFinancialBankAccounts { __typename id name accountStatus createdAt updatedAt provider externalBankAccountDetails { last4 id } } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "AccountHolderProvisioning", "id": "", "idempotencyKey": "IDEMPOTENCY-KEY", "createdAt": "2024-12-03T20:58:11.449Z", "updatedAt": "2024-12-03T20:58:14.747Z", "outcome": { "status": "COMPLETED" }, "workflowActions": [ { "__typename": "AccountHolderProvisioningWorkflowAction", "id": "", "action": "LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT", "actionInput": { "linkVerifiedExternalBankAccountInput": { "publicToken": "public-sandbox-97435641-d2cf-421f-8d60-c0fe568b4ae2" } }, "outcome": { "status": "COMPLETED" }, "executionOrder": 1, "node": { "__typename": "WorkflowActionResultOutcome", "createdAt": "2024-12-03T20:58:11.449Z", "updatedAt": "2024-12-03T20:58:11.449Z", "result": { "__typename": "WorkflowActionLinkVerifiedExternalBankAccountResult", "externalFinancialBankAccounts": [ { "__typename": "ExternalFinancialBankAccount", "id": "", "name": "Plaid Checking", "accountStatus": "ACTIVE", "createdAt": "2024-12-03T20:58:14.222Z", "updatedAt": "2024-12-03T20:58:14.222Z", "provider": "PLAID_RESELLER", "externalBankAccountDetails": { "last4": "0052", "id": "" } } ] } } } ] } }, "extensions": { "requestId": "e9c64e5d-3df7-9464-9ebc-19c39cb08168", "rateLimit": { "cost": 10, "limit": 60060, "remaining": 60050 } } } ### GraphQL: ProvisionAccountHolder Query: mutation ProvisionAccountHolder($input: ProvisionAccountHolderInput!) { provisionAccountHolder(input: $input) { __typename ... on AccountHolderProvisioning { id accountHolder { __typename ... on Node { id } ... on USPersonAccountHolder { id name { givenName } } ... on USBusinessAccountHolder { id } } workflowActions { id action outcome { status } } } } } Variables: { "input": { "idempotencyKey": "IDEMPOTENCY-KEY", "accountHolderId": "", "actions": [ "LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT" ], "actionInput": { "linkVerifiedExternalBankAccountInput": { "publicToken": "public-sandbox-97435641-d2cf-421f-8d60-c0fe568b4ae2" } } } } Expected Result: { "data": { "provisionAccountHolder": { "__typename": "AccountHolderProvisioning", "id": "", "accountHolder": { "__typename": "USBusinessAccountHolder", "id": "" }, "workflowActions": [ { "id": "", "action": "LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT", "outcome": { "status": "INITIATED" } } ] } }, "extensions": { "requestId": "fa750ebf-a141-9849-adc0-74817358b23b", "rateLimit": { "cost": 14, "limit": 60060, "remaining": 60046 } } } ### GraphQL: AccountHolderProvisioning Query: query AccountHolderProvisioning($id: ID!) { node(id: $id) { ... on AccountHolderProvisioning { __typename id idempotencyKey createdAt updatedAt outcome { status } workflowActions { __typename id action actionInput { linkVerifiedExternalBankAccountInput { publicToken } } outcome { status } executionOrder node { __typename ... on UserError { errors { errorPath code description } } ... on WorkflowActionResultOutcome { createdAt updatedAt result { __typename ... on WorkflowActionLinkVerifiedExternalBankAccountResult { externalFinancialBankAccounts { __typename id name accountStatus createdAt updatedAt provider externalBankAccountDetails { last4 id } } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "AccountHolderProvisioning", "id": "", "idempotencyKey": "IDEMPOTENCY-KEY", "createdAt": "2024-12-03T20:58:11.449Z", "updatedAt": "2024-12-03T20:58:14.747Z", "outcome": { "status": "COMPLETED" }, "workflowActions": [ { "__typename": "AccountHolderProvisioningWorkflowAction", "id": "", "action": "LINK_VERIFIED_EXTERNAL_BANK_ACCOUNT", "actionInput": { "linkVerifiedExternalBankAccountInput": { "publicToken": "public-sandbox-97435641-d2cf-421f-8d60-c0fe568b4ae2" } }, "outcome": { "status": "COMPLETED" }, "executionOrder": 1, "node": { "__typename": "WorkflowActionResultOutcome", "createdAt": "2024-12-03T20:58:11.449Z", "updatedAt": "2024-12-03T20:58:11.449Z", "result": { "__typename": "WorkflowActionLinkVerifiedExternalBankAccountResult", "externalFinancialBankAccounts": [ { "__typename": "ExternalFinancialBankAccount", "id": "", "name": "Plaid Checking", "accountStatus": "ACTIVE", "createdAt": "2024-12-03T20:58:14.222Z", "updatedAt": "2024-12-03T20:58:14.222Z", "provider": "PLAID_RESELLER", "externalBankAccountDetails": { "last4": "0052", "id": "" } } ] } } } ] } }, "extensions": { "requestId": "e9c64e5d-3df7-9464-9ebc-19c39cb08168", "rateLimit": { "cost": 10, "limit": 60060, "remaining": 60050 } } } ### GraphQL: AddExternalBankAccountVerifiedThroughPlaid Query: mutation AddExternalBankAccountVerifiedThroughPlaid( $input: AddExternalBankAccountVerifiedThroughPlaidInput! ) { addExternalBankAccountVerifiedThroughPlaid(input: $input) { __typename ... on ExternalFinancialBankAccount { id name provider createdAt updatedAt owner { __typename } ledgers { id name } externalBankAccountDetails { id createdAt updatedAt last4 type } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "accountHolderId": "", "externalToken": { "value": "processor-token-success" } } } Expected Result: { "data": { "addExternalBankAccountVerifiedThroughPlaid": { "__typename": "ExternalFinancialBankAccount", "id": "", "name": "Plaid Checking", "provider": "SIMULATED", "createdAt": "2022-09-09T19:33:02.822Z", "updatedAt": "2022-09-09T19:33:02.881Z", "owner": { "__typename": "USPersonAccountHolder" }, "ledgers": [ { "id": "", "name": "AVAILABLE_CASH" }, { "id": "", "name": "CASH" } ], "externalBankAccountDetails": { "id": "", "createdAt": "2022-09-09T19:33:02.822Z", "updatedAt": "2022-09-09T19:33:02.880Z", "last4": "9606", "type": "CHECKING" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "bankAccountType": "CHECKING" } } Expected Result: { "data": { "addNonVerifiedExternalUSFinancialBankAccount": { "__typename": "NonVerifiedExternalUSFinancialBankAccount", "id": "", "name": "My Checking Account", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z", "externalBankAccountDetails": { "id": "", "last4": "8910", "type": "CHECKING", "routingNumber": "111000025", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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 Node { id } ... on ExternalFinancialBankAccount { id name ledgers { name } externalBankAccountDetails { id last4 type routingNumber createdAt updatedAt } } } } } } } Variables: { "first": 20 } Expected Result: { "data": { "businessAccountHolders": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "", "externalFinancialAccounts": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "ExternalFinancialBankAccount", "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": "" } } ### GraphQL: 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": "" } } Expected Result: { "data": { "closeExternalBankAccount": { "__typename": "ExternalFinancialBankAccount", "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": "" }, "businessProfile": { "id": "" } }, "ledgers": [ { "id": "", "name": "AVAILABLE_CASH" }, { "id": "", "name": "CASH" } ], "features": [ { "__typename": "AchCapableFinancialAccountFeature", "enabled": true }, { "__typename": "VendorProvidedBankFinancialAccountFeature", "enabled": true } ], "externalBankAccountDetails": { "id": "", "createdAt": "2022-02-23T14:25:17.336Z", "updatedAt": "2022-02-23T14:25:17.995Z", "last4": "8546", "type": "CHECKING", "routingNumber": "011401533" } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/move-funds-out-of-highnote Title: Move Funds Out of Highnote Section: Issuing Description: Withdraw funds from Highnote via Originated ACH or Non-originated ACH using virtual account and routing numbers. Includes same-day ACH cutoff times. ## Overview Account holders can move funds out of their financial account using both originated ACH and non-originated ACH transfers. This guide provides steps for moving funds out of Highnote using both transfer methods. ### Transfer methods Card product cancellation periods and risk and compliance reviews can impact transfer timelines. The following table outlines the different transfers methods for moving funds out of Highnote, and their associated timelines: | Transfer Method | Timeline | Notes | | :---------------------- | :-------------------------- | :-------------------------------------------------------------------------------------- | | Originated ACH | Three to five business days | | | Originated next day ACH | One to three business days | | | Originated same day ACH | One to two business days | Nacha same day transfer limit is up to $1 million | | Non-originated ACH | Three to five business days | | ### Cutoff times Originated ACH transfers have specific cutoff times for processing. Initiating a transfer after the specified cutoff time may result in additional processing time. - **Originated next day ACH**: If a transfer is initiated before 4 PM EST, it will be processed by the bank the following business day. If initiated after 4 PM EST, the transfer will be processed two business days from initiation. - **Originated same day ACH**: If a transfer is initiated before 2 PM EST it will be processed by the bank same day. If initiated after 2 PM EST, the transfer will be processed the following business day. All Originated ACH Debit transfers (funds pulling in) have a required three business day hold period once the transfer has been initiated and is processing. ## Find financial account ID To retrieve a financial account ID, you can query the API using an application ID. Use the following query to find a financial account ID: ## Move funds to an external account with originated ACH You can allow account holders to withdraw funds from a Highnote financial account to a verified external bank account using originated ACH. Once an external bank account has been connected, use the following IDs as input variables in the mutation: - : Financial account ID of the external bank account - : Account holder's Highnote financial account ID Use the following mutation to move funds to a verified external account: ## Move funds to an external account with non-originated ACH If financial accounts for your card product have the enabled, account holders can use their virtual account and routing numbers to add their financial accounts to third-party services such as banks or payment apps. Account holders can initiate withdrawals and move funds out of their Highnote financial accounts using these third-party services. ### GraphQL: FindAccountHolderCardProductApplication Query: query FindAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { __typename id createdAt updatedAt applicationState { status } cardProduct { name } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id financialAccounts(first: 20) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id name } } } } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id financialAccounts(first: 20) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id name } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "createdAt": "2022-02-24T15:55:10.842Z", "updatedAt": "2022-02-24T15:55:17.742Z", "applicationState": { "status": "APPROVED" }, "cardProduct": { "name": "Business Prepaid" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "", "financialAccounts": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "start-cursor", "endCursor": "end-cursor" }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "FinancialAccount", "id": "", "name": "Financial Account #1" } }, { "cursor": "some-cursor", "node": { "__typename": "FinancialAccount", "id": "", "name": "Financial Account #2" } } ] } } } } }, "extensions": { "requestId": "" } } ### GraphQL: InitiateAchTransfer-Originated-Withdrawal Query: mutation InitiateAchTransfer($input: InitiateAchTransferInput!) { initiateAchTransfer(input: $input) { __typename ... on OriginatedAchTransfer { id amount { value currencyCode } createdAt updatedAt type purpose sign sameDay traceNumber status effectiveEntryDate sentToBankAt processedAt fromFinancialAccount { __typename ... on Node { id } ... on FinancialAccount { id name } } toFinancialAccount { __typename ... on Node { id } ... on ExternalFinancialBankAccount { id name } } } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "idempotencyKey": "00000000-0000-0000-0000-000000000000", "fromFinancialAccountId": "", "toFinancialAccountId": "", "purpose": "WITHDRAWAL", "amount": { "value": 10000, "currencyCode": "USD" }, "transferAgreementConsent": { "consentTimestamp": "2025-01-15T10:30:00.000Z", "authorizedPersonId": "", "template": { "consentTemplateId": "your-consent-template-id", "consentTemplateVersion": "1.0" } }, "companyEntryDescription": "WITHDRAWAL", "individualName": "John Doe", "sameDay": false } } Expected Result: { "data": { "initiateAchTransfer": { "__typename": "OriginatedAchTransfer", "id": "", "amount": { "value": 10000, "currencyCode": "USD" }, "createdAt": null, "updatedAt": null, "type": "PUSH", "purpose": "WITHDRAWAL", "sign": "NEGATIVE", "sameDay": false, "traceNumber": null, "status": "PENDING", "effectiveEntryDate": null, "sentToBankAt": null, "processedAt": null, "fromFinancialAccount": { "__typename": "FinancialAccount", "id": "", "name": "Primary Account" }, "toFinancialAccount": { "__typename": "ExternalFinancialBankAccount", "id": "", "name": "External Checking Account" } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/on-demand-funding Title: On-demand Funding Section: Issuing Description: Maintain zero-balance financial accounts with real-time on-demand funding from a source account. Configure pseudo balances with automatic daily, weekly, or monthly resets. ## Overview On-demand funding is a card product feature that allows financial accounts to maintain a $0 balance until authorization and receive real-time funding as needed. On-demand funding uses a **source financial account** for funding **account holder financial accounts**. When an account holder initiates a transaction, Highnote moves funds from the source financial account into the account holder's financial account to cover the cost of the transaction. ## Enable on-demand funding For prepaid and debit card products, you can enable and test on-demand funding features in your Test environment. Highnote must enable the feature for your card product in the Live environment. When enabling on-demand funding, you can optionally choose to enable pseudo balance. Use the following mutation to enable on-demand funding and use a boolean value to optionally enable pseudo balance in your Test environment: ## Issue source financial account Before issuing a financial account with an on-demand funding source, you must have a source financial account. A source financial account is a pre-funded account that links to the account holder's financial account for funding. The following accounts can be used as source financial accounts: - A financial account issued against an application - A product funding account - A financial account that exists at the account holder level Source financial accounts can be existing accounts or new accounts. To issue a new financial account as your source financial account, use the following mutation: ### Issue a financial account with on-demand funding source When an account holder's application is approved, you can issue the account holder a financial account with an on-demand funding source. Use the following mutation to issue a financial account with an on-demand funding source: ### Lookup source financial account Once a financial account is issued, you can look up the source financial account using the following query: ## Manage pseudo limit and balance Enable pseudo balance by setting to on the . Each financial account is linked to a source financial account. A card product can have multiple source accounts, but each financial account has exactly one. An account holder can have multiple financial accounts, each with its own independent limit. These mutations let you allocate spending limits from a source account to individual financial accounts and manage their available balances. ```sh title="Source account and financial account relationship" Card Product ├── Source Account A │ ├── Financial Account 1 (limit: $500) │ ├── Financial Account 2 (limit: $300) │ └── Financial Account 3 (limit: $200) │ ALLOCATED_PSEUDO_LIMIT = $1,000 │ └── Source Account B ├── Financial Account 4 (limit: $400) └── Financial Account 5 (limit: $600) ALLOCATED_PSEUDO_LIMIT = $1,000 ``` **Limit** and **balance** are two separate concepts on different ledgers: - **Limit** ( ledger) — the maximum spending ceiling for an individual financial account. When you set a limit, Highnote also debits on the source account, which tracks the sum of all allocations across its linked financial accounts. - **Balance** ( ledger) — the current available amount a cardholder can spend. Highnote declines transactions that would exceed the available balance. These mutations support incremental adjustments (add or subtract amounts) and automatic resets on a configurable cadence. | Mutation | What it does | | :-------------------- | :------------------------------------------------------------------------------------- | | | Set the spending limit to an absolute amount. Optionally configure auto-reset cadence. | | | Increment or decrement the spending limit. | | | Increment or decrement the available balance. | | | Reset the balance to zero. Configure auto-reset cadence. | ### Set pseudo limit Use to set the maximum allowable amount that the pseudo balance can reach before rejecting transactions. This sets the ledger value. You can optionally configure automatic resets by providing a and . When is set to , the available balance resets according to the specified cadence. For cadence options, see Reset pseudo balance. ### Update pseudo limit Use to increment or decrement the . - Increment by setting to - Decrement by setting to ### Update pseudo balance Use to increment or decrement the on a financial account. - Increment by setting to - Decrement by setting to ### Reset pseudo balance Use to reset the pseudo balance to zero. Set to and provide a to configure automatic resets. The following cadence options are available: | Cadence | Description | | :------------ | :-------------------------------------------------------------------------- | | | Resets daily at the time specified in . | | | Resets weekly on the same weekday and time as . | | | Resets monthly on the same day-of-month and time as . | | | Resets every 90 calendar days from the date and time. | | | Resets quarterly (every 3 months) on the same day and time as . | | | Resets annually on the same date and time as . | | | Never resets automatically. Manual reset via required. | ### GraphQL: EnableOnDemandFundingFeature Query: mutation EnableOnDemandFundingFeature( $input: EnableOnDemandFundingFeatureInput! ) { enableOnDemandFundingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled ... on OnDemandFundingCardProductFeature { pseudoBalanceEnabled } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "pseudoBalanceEnabled": true } } Expected Result: { "data": { "enableOnDemandFundingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "OnDemandFundingCardProductFeature", "enabled": true, "pseudoBalanceEnabled": true } ] } }, "extensions": { "requestId": "" } } ### GraphQL: IssueFundingFinancialAccountForApplication Query: mutation IssueFundingFinancialAccountForApplication( $input: IssueFundingFinancialAccountForApplicationInput! ) { issueFundingFinancialAccountForApplication(input: $input) { ... on FinancialAccount { id name createdAt updatedAt application { id createdAt } cardProduct { id vertical } } } } Variables: { "input": { "applicationId": "", "name": "On-demand funding source account" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "name": "On-demand funding source account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "id": "", "vertical": "GENERAL_PURPOSE_RELOADABLE" } } } } ### GraphQL: IssueFinancialAccountForApplicationWithOnDemandFundingSource Query: mutation IssueFinancialAccountForApplicationWithOnDemandFundingSource( $input: IssueFinancialAccountForApplicationWithOnDemandFundingSourceInput! ) { issueFinancialAccountForApplicationWithOnDemandFundingSource(input: $input) { ... on FinancialAccount { id externalId name createdAt updatedAt application { id createdAt } cardProduct { id vertical } features { __typename enabled createdAt updatedAt ... on OnDemandFundingFinancialAccountFeature { sourceFinancialAccountId } } directDepositDetails { id restrictedDetails { __typename ... on DirectDepositDetailRestrictedDetails { number routingNumber bank { name } } } } owner { __typename ... on Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "", "sourceFinancialAccountId": "" } } Expected Result: { "data": { "IssueFinancialAccountForApplicationWithOnDemandFundingSource": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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" }, { "__typename": "OnDemandFundingFinancialAccountFeature", "enabled": true, "createdAt": "2021-12-28T18:20:49.933Z", "updatedAt": "2021-12-28T18:20:49.933Z", "sourceFinancialAccountId": "" } ], "directDepositDetails": { "id": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: FindSourceFinancialAccount Query: query FindSourceFinancialAccount($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { __typename id name features { __typename enabled createdAt updatedAt ... on OnDemandFundingFinancialAccountFeature { sourceFinancialAccountId } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "id": "", "name": "My Financial Account Name", "features": [ { "__typename": "DirectDepositFinancialAccountFeature", "enabled": true, "createdAt": "2023-04-25T22:12:10.118Z", "updatedAt": "2023-04-25T22:12:10.118Z" }, { "__typename": "PrePaidPaymentCardFinancialAccountFeature", "enabled": true, "createdAt": "2023-04-25T22:12:10.118Z", "updatedAt": "2023-04-25T22:12:10.118Z" }, { "__typename": "OnDemandFundingFinancialAccountFeature", "enabled": true, "createdAt": "2023-04-25T22:12:10.118Z", "updatedAt": "2023-04-25T22:12:10.118Z", "sourceFinancialAccountId": "" } ] } }, "extensions": { "requestId": "" } } ### GraphQL: setPseudoLimit Query: mutation SetPseudoLimit($input: SetPseudoLimitInput!) { setPseudoLimit(input: $input) { ... on InterFinancialAccountTransfer { toFinancialAccount { id features { ... on ResetBalanceFinancialAccountFeature { cadence createdAt effectiveFrom effectiveThrough enabled resetTime updatedAt } } } fromFinancialAccount { id ledgers { name nextBalanceResetAt debitBalance { value } } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 10000, "currencyCode": "USD" }, "resetAvailableBalance": true, "cadence": "DAILY", "resetTime": "2026-01-27T01:23:45.000Z", "financialAccountId": "" } } Expected Result: { "data": { "setPseudoLimit": { "toFinancialAccount": { "id": "ac_2", "features": [ { "cadence": "DAILY", "createdAt": "2026-01-26T23:19:03.950Z", "effectiveFrom": "2026-01-26T23:19:03.950Z", "effectiveThrough": null, "enabled": true, "resetTime": "2026-01-27T01:23:45.000Z", "updatedAt": "2026-01-26T23:21:23.251Z" } ] }, "fromFinancialAccount": { "id": "ac_3", "ledgers": [ { "name": "ALLOCATED_PSEUDO_LIMIT", "nextBalanceResetAt": null, "debitBalance": { "value": 10000 } } ] } } } } ### GraphQL: updatePseudoLimit Query: mutation UpdatePseudoLimit($input: UpdatePseudoLimitInput!) { updatePseudoLimit(input: $input) { ... on InterFinancialAccountTransfer { fromFinancialAccount { ledgers { __typename name debitBalance { value } creditBalance { value } } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 1500, "currencyCode": "USD" }, "financialAccountId": "", "sign": "POSITIVE" } } Expected Result: { "data": { "updatePseudoLimit": { "fromFinancialAccount": { "ledgers": [ { "__typename": "Ledger", "name": "AVAILABLE_CASH", "debitBalance": { "value": 0 }, "creditBalance": { "value": 100000 } }, { "__typename": "Ledger", "name": "ALLOCATED_PSEUDO_LIMIT", "debitBalance": { "value": 50000 }, "creditBalance": { "value": 0 } } ] } } } } ### GraphQL: updatePseudoBalance Query: mutation UpdatePseudoBalance($input: UpdatePseudoBalanceInput!) { updatePseudoBalance(input: $input) { ... on InterFinancialAccountTransfer { fromFinancialAccount { id ledgers { name creditBalance { value } debitBalance { value } } features { __typename ... on ResetBalanceFinancialAccountFeature { cadence createdAt effectiveFrom effectiveThrough enabled resetAvailableBalance resetTime updatedAt } } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 20, "currencyCode": "USD" }, "financialAccountId": "", "sign": "POSITIVE" } } Expected Result: { "data": { "updatePseudoBalance": { "fromFinancialAccount": { "id": "ac_1", "ledgers": [ { "name": "PSEUDO_AVAILABLE_CASH", "creditBalance": { "value": 60000 }, "debitBalance": { "value": 0 } }, { "name": "ACCOUNT_HOLDER_PSEUDO_LIMIT", "creditBalance": { "value": 60000 }, "debitBalance": { "value": 0 } }, { "name": "PSEUDO_CASH", "creditBalance": { "value": 0 }, "debitBalance": { "value": 60000 } } ], "features": [ { "__typename": "ResetBalanceFinancialAccountFeature", "cadence": "DAILY", "createdAt": "2026-01-09T17:00:00.000Z", "effectiveFrom": "2026-01-09T17:00:00.000Z", "effectiveThrough": null, "enabled": true, "resetAvailableBalance": true, "resetTime": "2026-01-10T00:00:00.000Z", "updatedAt": "2026-01-09T17:00:00.000Z" } ] } } } } ### GraphQL: resetPseudoBalance Query: mutation ResetPseudoBalance($input: ResetPseudoBalanceInput!) { resetPseudoBalance(input: $input) { ... on InterFinancialAccountTransfer { fromFinancialAccount { id ledgers { name creditBalance { value } debitBalance { value } } features { __typename ... on ResetBalanceFinancialAccountFeature { cadence createdAt effectiveFrom effectiveThrough enabled resetAvailableBalance resetTime updatedAt } } } toFinancialAccount { id ledgers { name creditBalance { value } debitBalance { value } } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "financialAccountId": "", "cadence": "DAILY", "resetAvailableBalance": true } } Expected Result: { "data": { "resetPseudoBalance": { "fromFinancialAccount": { "id": "ac_1", "ledgers": [ { "name": "AVAILABLE_CASH", "creditBalance": { "value": 60000 }, "debitBalance": { "value": 0 } }, { "name": "CASH", "creditBalance": { "value": 0 }, "debitBalance": { "value": 60000 } }, { "name": "ALLOCATED_PSEUDO_LIMIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 25000 } } ], "features": [] }, "toFinancialAccount": { "id": "ac_1", "ledgers": [ { "name": "PSEUDO_AVAILABLE_CASH", "creditBalance": { "value": 0 }, "debitBalance": { "value": 0 } }, { "name": "ACCOUNT_HOLDER_PSEUDO_LIMIT", "creditBalance": { "value": 25000 }, "debitBalance": { "value": 0 } }, { "name": "PSEUDO_CASH", "creditBalance": { "value": 0 }, "debitBalance": { "value": 0 } } ] } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/payroll-advance Title: Payroll Advance Section: Issuing Description: Offer payroll advances tied to employment data with automatic repayment via non-originated ACH. ## Enable the feature Your financial accounts must have PayrollAdvanceFinancialAccountFeature enabled to use Payroll Advance. The Highnote team will assist with setting up and enabling the payroll advance feature for your card product. In addition to enabling the feature, you must integrate with a payroll data source partner to access employment data with your customer's consent and if necessary, determine a pre-funding amount. ## Create an employer financial account Before initiating an advance, you must create an employer financial account. This account is used to initiate a transfer from your product funding account to the employee financial account. Use the following mutation to issue an employer financial account: ## Initiate advance Payroll advances start with retrieving payroll data from a partner source. Once this data is retrieved, an account holder can request an advance for their employee financial account. Payroll advance transfers are internal transfers between Highnote financial accounts. Use the following mutation to initiate a payroll advance after a request is received: ## List payroll advance ledgers Use the following query to list all payroll advance payable and receivable ledgers, their outstanding balances, and additional relevant data: ## Repay payroll advance Payroll advance repayment is received using deposit initiated via a non-originated ACH transfer. Repayment occurs in the following order of events: 1. The employee provides demand deposit account (DDA) details for their employee financial account to their payroll provider. 2. Employee initiates the payroll advance repayment deposit. 3. Once Highnote receives the payroll advance repayment deposit, you must send an API call to and provide the employer financial account ID. **You must confirm payroll advance repayment deposits by 11:00 AM Eastern Standard Time (EST), one business day before the** **settlement date.** 4. If the repayment deposit is confirmed, it processes as a payroll advance repayment. 5. If the repayment deposit is not confirmed, Highnote deposits the funds into the employee financial account without advance repayment. You can monitor and confirm payroll deposits using the Payroll advance repayment status notification. This notification triggers when a repayment processes and provides the status of the repayment. For step three in the repayment process, use the following mutation to confirm a payroll advance repayment deposit. Use as an input variable: ### GraphQL: IssueEmployerFinancialAccountForCardProduct Query: mutation IssueEmployerFinancialAccountForCardProduct( $input: IssueEmployerFinancialAccountForCardProductInput! ) { issueEmployerFinancialAccountForCardProduct(input: $input) { ... on EmployerFinancialAccount { id name createdAt updatedAt application { id createdAt } cardProduct { id vertical } owner { __typename ... on Node { id } ... on Organization { id } } features { __typename enabled createdAt updatedAt } } } } Variables: { "input": { "cardProductId": "", "name": "", "companyIdentifier": "1234567890" } } Expected Result: { "data": { "issueEmployerFinancialAccountForCardProduct": { "id": "", "companyIdentifier": "1234567890", "name": "", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "cardProduct": { "id": "", "vertical": "CONSUMER_DEBIT" }, "owner": { "__typename": "Organization", "id": "" }, "features": { "__typename": "PayrollEmployerAdvanceFinancialAccountFeature", "enabled": true, "createdAt": "2021-12-28T18:20:49.933Z", "updatedAt": "2021-12-28T18:20:49.933Z" } } } } ### GraphQL: initiatePayrollAdvance Query: mutation initiatePayrollAdvance($input: InitiatePayrollAdvanceInput!) { initiatePayrollAdvance(input: $input) { __typename ... on Node { id } ... on Transfer { id status statusReason createdAt updatedAt amount { value currencyCode } ledgers { name } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "toFinancialAccountId": "", "fromFinancialAccountId": "", "memo": "employee ID", "amount": { "value": 10000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiatePayrollAdvance": { "__typename": "Transfer", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2021-12-27T22:26:55.102Z", "updatedAt": "2021-12-27T22:26:55.127Z", "amount": { "value": 10000, "currencyCode": "USD" }, "ledgers": null } } } ### GraphQL: FindAccount Query: query FindAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { __typename id name ledgers { id name normalBalance asOf debitBalance { value currencyCode } creditBalance { value currencyCode } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "id": "", "name": "John Doe - Account", "ledgers": [ { "id": "", "name": "DEPOSIT_HOLD", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "REFUND_HOLD", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "FUND_IN_HOLD", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "AVAILABLE_CASH", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "DEPOSIT_AUTHORIZATION", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "REFUND_AUTHORIZATION", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "CASH", "normalBalance": "DEBIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "AUTHORIZATION", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "FEE_AUTHORIZATION", "normalBalance": "CREDIT", "asOf": "2022-04-20T14:34:39.948Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } } ] } } } ### GraphQL: confirmPayrollDeposit Query: mutation confirmPayrollDeposit($input: ConfirmPayrollDepositInput!) { confirmPayrollDeposit(input: $input) { ... on Node { id } ... on PayrollTransfer { id status { __typename ... on NonFailureExternallyInitiatedACHStatus { status } ... on FailureExternallyInitiatedACHStatus { status statusReasonCode } } createdAt updatedAt amount { value currencyCode } } ... on CreditFunds { id status { __typename ... on NonFailureExternallyInitiatedACHStatus { status } ... on FailureExternallyInitiatedACHStatus { status statusReasonCode } } createdAt updatedAt amount { value currencyCode } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "", "isPayrollDeposit": true, "employerFinancialAccountId": "" } } Expected Result: { "data": { "confirmPayrollDeposit": { "__typename": "PayrollTransfer", "id": "", "status": { "__typename": "NonFailureExternallyInitiatedACHStatus", "status": "PENDING" }, "createdAt": "2021-12-27T22:26:55.102Z", "updatedAt": "2021-12-27T22:26:55.127Z", "amount": { "value": 2000, "currencyCode": "USD" } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/sim-connecting-ext-account Title: Simulate Connecting a Bank Account Section: Issuing Description: Test external bank account connections with Plaid or Finicity using simulated data in the Test environment. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. External bank accounts are used to transfer funds into and out of a Highnote financial account. Highnote has partnered with Plaid and Finicity to offer secure options for connecting an external bank account. For more information, see Connect External Accounts. This guide provides steps for simulating connecting an external bank account to a Highnote financial account. ## Prerequisites - A Highnote account - An API key or API Explorer - A financial account ## Simulate connecting an external account with Finicity Use the following mutation to simulate connecting an external bank account with Finicity: ## Simulate connecting an external account with Plaid Use the following mutation to simulate connecting an external account with Plaid: ## Simulate connecting a non-verified account Non-verified external accounts are used to transfer funds out of a Highnote financial account. You can't move funds into Highnote from a non-verified external account. Use the following mutation with test routing and account numbers to simulate connecting a non-verified external account: - **Test routing number:** 091000019 - **Test account number:** Any 5 digit number ## Automate your integration To automate your integration, subscribe to external bank account notification events. The details provided in the payloads from these events can be used for the following use cases: - Automate your application or website's transaction processing workflows - Create account holder notifications and alerts ### GraphQL: 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": "", "name": "Finicity Checking", "bankAccountType": "CHECKING", "externalToken": { "receiptId": "processor-token-success", "customerId": "5543088633794259024", "products": [ { "productType": "ACH_DETAILS", "accountId": "", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } }, { "productType": "CURRENT_BALANCE", "accountId": "", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } }, { "productType": "ACH_OWNER_DETAILS", "accountId": "", "callLimit": 1000, "expirationDetail": { "start": "2022-03-10T06:06:20Z", "expiry": "2023-03-10T06:06:20Z" } } ] } } } Expected Result: { "data": { "addExternalBankAccountVerifiedThroughFinicity": { "__typename": "ExternalFinancialBankAccount", "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": "", "createdAt": "2022-08-26T20:24:22.557Z", "updatedAt": "2022-08-26T20:24:22.730Z", "last4": "9606", "type": "CHECKING", "routingNumber": "011401533" } } }, "extensions": { "requestId": "" } } ### GraphQL: AddExternalBankAccountVerifiedThroughPlaid Query: mutation AddExternalBankAccountVerifiedThroughPlaid( $input: AddExternalBankAccountVerifiedThroughPlaidInput! ) { addExternalBankAccountVerifiedThroughPlaid(input: $input) { __typename ... on ExternalFinancialBankAccount { id name provider createdAt updatedAt owner { __typename } ledgers { id name } externalBankAccountDetails { id createdAt updatedAt last4 type } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "accountHolderId": "", "externalToken": { "value": "processor-token-success" } } } Expected Result: { "data": { "addExternalBankAccountVerifiedThroughPlaid": { "__typename": "ExternalFinancialBankAccount", "id": "", "name": "Plaid Checking", "provider": "SIMULATED", "createdAt": "2022-09-09T19:33:02.822Z", "updatedAt": "2022-09-09T19:33:02.881Z", "owner": { "__typename": "USPersonAccountHolder" }, "ledgers": [ { "id": "", "name": "AVAILABLE_CASH" }, { "id": "", "name": "CASH" } ], "externalBankAccountDetails": { "id": "", "createdAt": "2022-09-09T19:33:02.822Z", "updatedAt": "2022-09-09T19:33:02.880Z", "last4": "9606", "type": "CHECKING" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "091000019", "accountNumber": "12345", "name": "My Checking Account", "accountHolderId": "", "bankAccountType": "CHECKING" } } Expected Result: { "data": { "addNonVerifiedExternalUSFinancialBankAccount": { "__typename": "NonVerifiedExternalUSFinancialBankAccount", "id": "", "name": "My Checking Account", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z", "externalBankAccountDetails": { "id": "", "last4": "8910", "type": "CHECKING", "routingNumber": "111000025", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z" } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/sim-wire-transfer Title: Simulate a Wire Transfer Section: Issuing Description: Simulate incoming and outgoing wire transfers to your product funding account in the Test environment. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. Wire transfers are used to transfer funds into a Highnote product funding account. For more information on product funding accounts, see Add Funds to your Balance. This guide provides steps for simulating wire transfers using the Highnote API. ## Prerequisites - A Highnote account - An API key or API Explorer - A product funding financial account ## Simulate a wire transfer In the Test environment, use the following mutation to simulate a wire transfer to fund your product funding account: ## Find wire transfers After a wire transfer is initiated, you can use the Highnote API to find incoming and outgoing wire transfers. The direction of a wire transfer is defined as follows: - **Incoming**: Money is coming into a Highnote financial account via wire transfer. - **Outgoing**: Money is leaving a Highnote financial account via wire transfer. ### Incoming wire transfers Use the following query to find an incoming wire transfer: ### Outgoing wire transfers Use the following query to find an outgoing wire transfer: ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 1500, "currencyCode": "USD" }, "toFinancialAccountId": "MC40LmFj", "memo": "", "source": "WIRE" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "Transfer" } }, "extensions": { "requestId": "19070e66-2fd9-968a-94be-85c4836eae7b" } } ### GraphQL: NodeWireTransfer Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an incoming wire transfer", "type": "INCOMING_WIRE_TRANSFER", "status": "COMPLETED", "financialAccount": { "id": "" } } } } ### GraphQL: NodeWireTransfer Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an outgoing wire transfer", "type": "OUTGOING_WIRE_TRANSFER", "status": "COMPLETED", "financialAccount": { "id": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/transfer-btwn-financial-accts Title: Transfer Funds between Financial Accounts Section: Issuing Description: Transfer funds between Highnote financial accounts in real time for rewards redemption, peer-to-peer payments, or internal company transfers. ## Overview You can transfer funds between Highnote accounts in real time. Transferring funds between Highnote accounts is used for various use cases: - **Rewards redemptions:** Transfer funds from your product funding account to an account holder's financial account. - **Internal company transfers:** Set up intra-company transfers between financial accounts for the same business account holder. - **Peer-to-peer transfers:** You can enable peer-to-peer transfers of funds from one account holder's financial account to another. To enhance funds transfer management and organization, Highnote offers transfer purposes. For available transfer purposes, see TransferStatus in the API Reference. ## Initiate internal transfer Use the following mutation to initiate a transfer between Highnote financial accounts: ## Check internal transfer status You can query and display the status of internal transfers between financial accounts. The mutation has the following statuses: | Status | Description | | :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | The platform is currently validating and executing the transfer. | | | The platform has completed the transfer. | | | The platform was not able to complete the transfer. See Failed Status Values for more information. | ### Failed status values If a transfer returns a status, it returns a code, with one of the following values: | Status Reason Code | Description | | :------------------ | :-------------------------------- | | | The associated account is closed. | | | The account was not found. | Use the following query to check the status of an internal transfer: ### GraphQL: InitiateTransferBetweenFinancialAccounts Query: mutation InitiateTransferBetweenFinancialAccounts( $input: InitiateTransferBetweenFinancialAccountsInput! ) { initiateTransferBetweenFinancialAccounts(input: $input) { __typename ... on InterFinancialAccountTransfer { id status statusReason createdAt updatedAt memo purpose amount { value currencyCode } ledgers { name } } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "toFinancialAccountId": "", "fromFinancialAccountId": "", "purpose": "GENERAL", "memo": "p2p", "amount": { "value": 10000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferBetweenFinancialAccounts": { "__typename": "InterFinancialAccountTransfer", "id": "", "status": "COMPLETED", "createdAt": "2023-02-23T03:40:07.230Z", "updatedAt": "2023-02-23T03:40:07.230Z", "memo": "p2p", "purpose": "GENERAL", "amount": { "value": 1000, "currencyCode": "USD" } } } } ### GraphQL: CheckAccountTransferStatus Query: query CheckAccountTransferStatus($id: ID!) { node(id: $id) { __typename ... on InterFinancialAccountTransfer { id status statusReason } } } Variables: { "id": "" } Expected Result: { "node": { "__typename": "InterFinancialAccountTransfer", "id": "", "status": "COMPLETED", "statusReason": null } } --- URL: https://docs.highnote.com/docs/issuing/accounts/funding/using-ledgers Title: Using Ledgers Section: Issuing Description: View financial account ledgers, ledger entries, and balances. Understand ledger names, normal balance direction, and financial events for account statements. ## Overview When you create a card product, Highnote creates ledgers for your financial accounts based on the card product vertical. Ledgers have a , , and a that is determined by the ledger category. For example, a ledger has a category of and a of . For a full list of ledger names, see LedgerName in the API Reference. A ledger is made up of the following foundational concepts: | Concept | Definition | | :-------------- | :------------------------------------------------------------------------------------ | | Normal balance | The expected balance of a ledger | | Financial event | Any event that impacts the balance of a financial account | | Ledger entry | A record of a financial event, resulting in a change in a financial account's balance | | Account balance | The current balance of a ledger, reflecting all financial events | Account balances show all financial events for a given ledger. When an individual financial event occurs, it results in a ledger entry. Each ledger entry reflects the change in account balance. Refer to the following example for a breakdown of this process: 1. Funds are transferred from an external bank account into a Highnote financial account. 2. The funds transfer results in a ledger entry in the financial account's ledger, reflecting the account balance. 3. When transactions are made using a payment card, the ledger reflects pending authorizations and holds on the account. 4. After a transaction clears, the ledger reflects the money available to spend in a financial account. ## Account balances Account balances reflect the current balance of a ledger based on financial events, based on the following: - Represented by a single positive number - The direction of the balance, either or - The account's normal balance If the account balance and normal balance agree, the balance is interpreted as _positive_. If the balance of a ledger and the normal balance disagree, the balance is interpreted as _negative_. The following example using a ledger outlines how account balances and normal balances are reflected. ledgers have a normal balance of : - If a ledger has a $1000 debit balance, the balance is positive. This means the account balance is $1000 because the normal balance for a ledger is debit. - If a ledger has a $1000 credit balance, the balance is negative. In this case, the account balance and normal balance disagree, meaning there is -$1000 in the account. Highnote's ledger system is based on account principles, with cash and activity being represented independently. This means that account balances provide a snapshot for a point in time, rather than reflecting pending or available balances. Pending or available balances can be calculated across ledgers if desired. ## Use cases Ledgers and financial events can be used to create account statements, display account balances, and show money movement statuses. Refer to the following table for the objects used to create each use case: | Use case | Objects | | :--------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | | Transaction feed without account balance | FinancialAccountActivity | | Account statement with balance | FinancialAccountActivity for _pending_ and Ledger for _posted_ | | Money movement status | FinancialAccountActivity | ## Find all ledgers for your organization Use the following query to list all ledgers for your organization. The query returns each ledger's , , and : ## Operation for ledger entries Use the following query to find a ledger and its associated ledger entries: ### GraphQL: FindOrganization Query: query FindOrganization($id: ID!) { node(id: $id) { ... on Organization { accounts { edges { node { id ledgers { id name normalBalance asOf debitBalance { value currencyCode } creditBalance { value currencyCode } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "id": "", "ledgers": [ { "id": "", "name": "CASH", "normalBalance": "DEBIT", "asOf": "2021-08-06T16:12:39.735Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "AVAILABLE_CASH", "normalBalance": "CREDIT", "asOf": "2021-08-06T16:12:39.735Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "UNCOLLECTED_FUNDS", "normalBalance": "DEBIT", "asOf": "2021-08-06T16:25:21.280Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "NETWORK_PAYABLE", "normalBalance": "CREDIT", "asOf": "2021-08-06T16:25:21.280Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "NETWORK_RECEIVABLE", "normalBalance": "DEBIT", "asOf": "2021-08-06T16:25:21.280Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "INTERCHANGE_REVENUE", "normalBalance": "CREDIT", "asOf": "2021-08-06T16:25:21.280Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "NETWORK_EXPENSE", "normalBalance": "CREDIT", "asOf": "2021-08-06T16:25:21.280Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } } ] } ] } } } } ### GraphQL: FindLedger Query: query FindLedger($id: ID!) { node(id: $id) { ... on Ledger { id name ledgerEntries(first: 1) { edges { node { __typename id amount { value } journalEntry { credits { amount { value } } debits { amount { value } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "name": "AVAILABLE_CASH", "ledgerEntries": { "edges": [ { "node": { "__typename": "CreditLedgerEntry", "id": "", "amount": { "value": 1000 }, "journalEntry": { "credits": [ { "amount": { "value": 1000 } } ], "debits": [ { "amount": { "value": 1000 } } ] } } } ] } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/query-product-and-account-settings Title: Querying Card Products and Financial Accounts Section: Issuing Description: Introspect your Card Product and Financial Account configuration through the Highnote GraphQL API: features, attached rules, credit, billing, and a runnable settings-snapshot query. ## Overview This guide explains how to query your Card Product and Financial Account settings with the Highnote API. These two nesting entities hold almost all of your configuration: - **Card Product**: Blueprint for a program. Defines the capabilities, rules, credit terms (if applicable), and fee structure. Settings attached to the Card Product apply to all of its Financial Accounts. - **Financial Account**: Single account opened under a Card Product. Account-level settings, lifecycle states, and balances attached to a Financial Account apply only to that account. ### Settings Your effective settings come from both entities: 1. The Card Product determines what the program allows. 2. The Financial Account determines what is true of that one account. !A Card Product is the blueprint whose settings cascade to every Financial Account opened under it. Some settings are restricted to Highnote's dashboard applications. Throughout this guide they are marked **_dashboard only_**, either in an "Available to" column or inline after the field name. Everything unmarked is readable with an API key. Restriction is per entity, not per field name: several fields are readable on and dashboard-only on the beneath it. Check the entity you are actually querying. Selecting a dashboard-only field with an API key does not return a partial result — the whole operation fails validation and returns nothing. ### Categories Across both entities, settings fall into a few recurring categories: - **Features**: Capability flags such as ACH, direct deposit, or on-demand funding, exposed as a interface you read with . - **Attached rules**: Spend, velocity, risk, transfer, and check rules that limit what the product or account can do. - **Credit**: Credit configuration and plans. - **Fees**: Fee schedules. - **Lifecycle and balances** (accounts only): Status, attributes, billing summary, and live velocity balances. !Categories of settings queryable on a Card Product and on a Financial Account, side by side. The rest of this guide walks each entity's fields by category, then gives one query that captures a full snapshot of both. ## Finding your products and accounts Every settings query in this guide takes a Card Product ID or a Financial Account ID, so the first step is finding yours. Card Products have a top-level entry point and can be listed directly. Financial Accounts have no equivalent entry point. You reach one by traversing from its Card Product, from its account holder, or by direct lookup. !Entry-point queries lead to Card Product and Financial Account, with the key fields you read on each. ### Card Products is the top-level entry point. It is paginated and returns every CardProduct on your account. ```graphql query MyCardProducts { cardProducts(first: 20) { edges { node { id name commercial usage vertical } } pageInfo { hasNextPage endCursor } } } ``` ### Financial Accounts There is no top-level query. To list yours, use one of three traversal paths: | Path | When to Use It | | --------------------------------------------------------------------------------------- | ------------------------------------------------- | | | All Financial Accounts for a known Card Product | | / | All Financial Accounts for a known account holder | | | Direct lookup of a known Financial Account | ## Card Product settings CardProduct is the largest configuration surface in the API. ### Identity and shape | Field | What It Tells You | | ------------------------------------------ | ---------------------------------------------- | | , , , | Core identity and business intent | | | or | | | Internal template the product was created from | | | Attached s (program profiles) | | , | BIN range, card art, and network configuration | ### Features returns a list of interfaces. Use inline fragments to read each capability's flag and per-feature configuration: ```graphql features { __typename ... on AuthorizedUserCardProductFeature { enabled } ... on ChargeCardProductFeature { enabled } ... on CollaborativeApplicationUnderwritingCardProductFeature { enabled } ... on CollaborativeAuthorizationCardProductFeature { enabled } ... on CreditLimitVarianceCardProductFeature { enabled } ... on DirectMerchantAcquiringCardProductFeature { enabled } ... on DisputeChargebackCardProductFeature { enabled } ... on EarlyDirectDepositCardProductFeature { enabled } ... on ExternalBusinessManagementCardProductFeature { enabled } ... on OnDemandFundingCardProductFeature { enabled } ... on PartialFundingCardProductFeature { enabled } ... on PointRewardCardProductFeature { enabled } ... on RevolvingCardProductFeature { enabled } ... on SecuredDepositCardProductFeature { enabled } } ``` ### Rules attached at Card Product level These apply to every Financial Account under the product. | Field | Purpose | Available to | | ------------------------------------------------------------------------------------- | ------------------------------------------------------ | -------------- | | | MCC, country, amount, and merchant-ID allow/blocklists | API key | | | Velocity caps (count and amount over a time window) | API key | | , | Read-only platform-mandated rules layered on top | API key | | | Between-account transfer limits | API key | | | Between-account velocity transfer limits | API key | | | Real-time risk decisioning | API key | | , | Earn and redeem configurations | API key | | , | ACH and external transfer constraints | Dashboard only | | , , | Risk-decisioning rules | Dashboard only | | , | Check-payment constraints | Dashboard only | ### Credit | Field | Purpose | | ------------------------------------ | ---------------------------------------------------------------- | | | Credit product configuration (limits, plan templates, structure) | | , | Active plans and templates available to attach | ### Fees | Field | Purpose | | -------------- | -------------------------------------- | | | Fee schedules attached to this product | ### Activity and operations These are paginated and filterable. | Field | Purpose | | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | | | The Financial Accounts under this product | | | All cards issued from this product | | | Applications routed to this product | | | Recent transaction events on this product | | , | Disputes and chargebacks scoped to the product | | , , , , | Money-movement modalities scoped to the product | | | Physical card group orders | ## Financial Account settings FinancialAccount exposes the largest per-account configuration surface in the API. ### Identity and lifecycle | Field | Purpose | | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | , , , , | Identity | | , | Who owns the account and who the cardholder is (these can differ for authorized-user accounts) | | | Parent product | | | Origin application | | , | Lifecycle state | | , | Flagged states and reasons (for example, , ) | | | The underlying issuing bank | | , | Subscriber metadata | | | Audit-style history of changes | ### Features returns interfaces — a different list than . The , , and fields live on the interface itself, so you can read directly; use inline fragments when a feature has additional configuration. ```graphql features { __typename enabled ... on AchCapableFinancialAccountFeature { enabled } ... on AuthorizedUserAccountFeature { enabled } ... on CardFundingFinancialAccountFeature { enabled } ... on CheckCapableAccountFeature { enabled } ... on CommercialCreditPayInFullCardAccountFeature { enabled } ... on CreditCardAccountFeature { enabled } ... on DebitPaymentCardFinancialAccountFeature { enabled } ... on DirectDepositFinancialAccountFeature { enabled } ... on FleetCardAccountFeature { enabled } ... on IncomeAccountFinancialAccountFeature { enabled } ... on JustInTimeFundingFinancialAccountFeature { enabled } ... on MerchantSettlementFinancialAccountFeature { enabled } ... on NegativeBalanceReserveFinancialAccountFeature { enabled } ... on NonVerifiedFinancialAccountFeature { enabled } ... on OnDemandFundingFinancialAccountFeature { enabled } ... on PartialFundingFinancialAccountFeature { enabled } ... on PayrollAdvanceFinancialAccountFeature { enabled } ... on PayrollEmployerAdvanceFinancialAccountFeature { enabled } ... on PointRewardFinancialAccountFeature { enabled } ... on PrePaidPaymentCardFinancialAccountFeature { enabled } ... on PreprintedCardFinancialAccountFeature { enabled } ... on ProductFundingFinancialAccountFeature { enabled } ... on ProductReserveFinancialAccountFeature { enabled } ... on ProductSecuredDepositFinancialAccountFeature { enabled } ... on RepaymentFinancialAccountFeature { enabled } ... on ResetBalanceFinancialAccountFeature { enabled } ... on SecuredCreditPaymentCardFinancialAccountFeature { enabled } ... on SecuredDepositFinancialAccountFeature { enabled } ... on SuspenseFinancialAccountFeature { enabled } ... on VendorProvidedBankFinancialAccountFeature { enabled } } ``` ### Balances and billing | Field | Purpose | | --------------------------------- | ------------------------------------------------------------------------------------- | | | Underlying double-entry ledgers; the canonical balance source | | | Latest closed statement: minimum payment due, payment due date, and remaining balance | | | Latest balance snapshot | | | Paginated statement history | | | Cycle anchor and cadence configuration | | | Past cycles | | , | Past-due tracking | ### Direct deposit details | Field | Purpose | | ---------------------- | ------------------------------------------ | | | Direct deposit routing and account numbers | The account and routing numbers sit behind , which requires a Direct Deposit Details client token with the permission. Without that token the field resolves to an . ### Attached rules The same field names as the Card Product, scoped to the Financial Account — but **not the same availability**. The inter-account transfer rules are readable with an API key on and dashboard-only on , so check each entity separately rather than assuming a field carries the same access on both. - - - - , — _dashboard only_ - , , — _dashboard only_ - , — _dashboard only_ ### Live velocity balances How much room is left under each velocity rule: - - - — _dashboard only_ - , — _dashboard only_ - — _dashboard only_ - — _dashboard only_ ### Activity These are paginated and filterable. | Field | What It Returns | | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | | | All money-movement and ledger activity | | | Card transaction events | | | Cards issued on this account | | , | Disputes and chargebacks | | | Fees charged | | , , , | ACH activity by direction and origination | | | Between-account transfers | | | Future scheduled inbound transfers | | , | Credit plan instances | | | Per-account credit configuration | | | Review history | | , | Active and closed risk investigations — _dashboard only_ | | , | Operational notes | ## Settings snapshot query Supply a and a of your choice. This query pulls a comprehensive settings snapshot for both entities in one round trip, with the feature unions resolved and a sample of each attached-rule connection. This query selects only fields an API key can read, so you can run it as written. The attached-rule connections marked _dashboard only_ in the tables above are deliberately left out — on : , , ; on : , , . Adding any of them makes the whole query fail rather than returning a partial result. Most are dropped along with the connection type they return, which is itself restricted; is dropped by its own field-level restriction, since the type it returns is readable on . Either way the document fails validation and returns nothing. The unrestricted is included on both types. ```graphql query CardProductAndFinancialAccountSnapshot( $cardProductId: ID! $financialAccountId: ID! ) { # ============================================================ # CARD PRODUCT SETTINGS # ============================================================ cardProduct: node(id: $cardProductId) { __typename ... on CardProduct { id name commercial usage vertical sourceTemplateId # Card design and BIN defaultCardProfileSet { id name } cardProfileSets(first: 10) { ... on CardProfileSetConnection { edges { node { id name } } } } # Profiles profiles { __typename ... on Node { id } } # Capability flags (every CardProductFeature subtype) features { __typename ... on AuthorizedUserCardProductFeature { enabled } ... on ChargeCardProductFeature { enabled } ... on CollaborativeApplicationUnderwritingCardProductFeature { enabled } ... on CollaborativeAuthorizationCardProductFeature { enabled } ... on CreditLimitVarianceCardProductFeature { enabled } ... on DirectMerchantAcquiringCardProductFeature { enabled } ... on DisputeChargebackCardProductFeature { enabled } ... on EarlyDirectDepositCardProductFeature { enabled } ... on ExternalBusinessManagementCardProductFeature { enabled } ... on OnDemandFundingCardProductFeature { enabled } ... on PartialFundingCardProductFeature { enabled } ... on PointRewardCardProductFeature { enabled } ... on RevolvingCardProductFeature { enabled } ... on SecuredDepositCardProductFeature { enabled } } # Credit and fees creditConfiguration { __typename } creditPlanTemplates(first: 10) { edges { node { id } } } creditPlans(first: 10) { edges { node { id } } } feeSchedules(first: 20) { edges { node { id status } } } # Subscriber-managed rules attachedSpendRules(first: 20) { edges { node { id name } } } attachedVelocityRules(first: 20) { edges { node { id name } } } attachedInterFinancialAccountTransferRules(first: 20) { ... on InterFinancialAccountTransferRuleConnection { edges { node { __typename ... on Node { id } } } } } attachedRewardRules(first: 20) { edges { node { __typename } } } attachedRewardRedemptionConfigurations(first: 20) { edges { node { __typename } } } # Platform-imposed rules (read only) attachedPlatformSpendRules(first: 20) { edges { node { id name } } } attachedPlatformVelocityRules(first: 20) { edges { node { id name } } } # Risk rules attachedRealtimeRiskRules(first: 20) { ... on RealtimeRiskRuleConnection { edges { node { __typename ... on Node { id } } } } } # Sample of related accounts accounts(first: 5) { edges { node { id name accountStatus partnerBankName } } } } } # ============================================================ # FINANCIAL ACCOUNT SETTINGS # ============================================================ financialAccount: node(id: $financialAccountId) { __typename ... on FinancialAccount { id externalId name createdAt updatedAt accountStatus partnerBankName # Lifecycle and state flags accountAttributes financialAccountAttributesWithReason { attribute reason } accountClosureReasons # Relationships cardProduct { id name } owner { __typename ... on Node { id } } accountHolder { __typename ... on Node { id } } cardProductApplication { __typename ... on Node { id } } # Capabilities (enabled lives on the interface) features { __typename enabled } # Direct deposit details (account and routing numbers require a # Direct Deposit Details token with READ_RESTRICTED_DETAILS) directDepositDetails { id restrictedDetails { __typename ... on DirectDepositDetailRestrictedDetails { number routingNumber } } } # Balances and billing billingSummary { asOf minimumPaymentDue { value currencyCode decimalPlaces } paymentDueOn remainingLatestClosedStatementBalance { value currencyCode decimalPlaces } } statementSnapshot { __typename } activeBillingCycleConfiguration { __typename } delinquency { __typename } delinquencyState { __typename } # Credit configuration creditConfiguration { __typename } purchasePlans { __typename } # Attached rules (account level) attachedSpendRules(first: 20) { edges { node { id name } } } attachedVelocityRules(first: 20) { edges { node { id name } } } attachedRealtimeRiskRules(first: 20) { ... on RealtimeRiskRuleConnection { edges { node { __typename ... on Node { id } } } } } # Live velocity balances velocitySpendRuleBalances { __typename } # Recent activity samples paymentCards(first: 5) { edges { node { id last4 expirationDate } } } financialAccountActivities(first: 5) { edges { node { __typename } } } transactionEvents(first: 5) { edges { node { __typename ... on Node { id } } } } installmentAgreements(first: 5) { edges { node { id } } } feeTransferEvents(first: 5) { edges { node { __typename } } } # Subscriber metadata customFields { __typename key ... on CustomStringField { value } } userDefinedFields(first: 5) { edges { node { __typename } } } } } } ``` ### Variables ```json { "cardProductId": "", "financialAccountId": "" } ``` Card Product IDs are prefixed ; Financial Account IDs are prefixed . See Entity IDs and Object Types for the full prefix table. ### Notes on running - Highnote caps pagination at **20 items per page**. Pass or fewer, and page through more results with set to the from . - Connection types exposed through a union (for example, ) require an inline fragment such as to reach . - is the canonical way to fetch any entity by its global ID. - An flag returns only when the capability is currently active on the entity. ## What is not directly queryable - **Webhook subscriptions** are managed through queries and webhook mutations, not on or . - **API key configuration** lives outside the Subscriber-facing schema. - **Partner-bank-side state** is not directly visible; Highnote exposes and limited derived information. - **Some platform-level configuration** (interchange routing, network-side product enablement) is reflected in behavior but not exposed as raw configuration. ## Introspection patterns | When You See… | Do This | | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | A field | Paginate with and ; some accept | | A union (a field whose type ends in ) | Use an inline fragment to reach the data | | A interface (, ) | Read on the interface, then inline-fragment per subtype for additional configuration | | A rule connection | Nodes are heterogeneous; fragment on the specific rule type for its configuration fields | For the full filter-input shapes (for example, ), introspect them with in your GraphQL client, or see the Searching the API guide. ## Quick reference - Start at to enumerate your products. - From each , expand , , , , , , and . - From each , expand , , , , and the rule and collections. - Use to drill into any specific entity by its global ID. - Pagination uses and ; filters use . The settings snapshot query returns a comprehensive snapshot in a single round trip. ### GraphQL: MyCardProducts Query: query MyCardProducts { cardProducts(first: 20) { edges { node { id name commercial usage vertical } } pageInfo { hasNextPage endCursor } } } Variables: {} Expected Result: { "data": { "cardProducts": { "edges": [ { "node": { "id": "pd_36cb6f6818014bbba8644397ec5dfc86", "name": "Consumer Prepaid", "commercial": false, "usage": "MULTI_USE", "vertical": "CONSUMER_PREPAID" } } ], "pageInfo": { "hasNextPage": false, "endCursor": "MQ" } } } } ### GraphQL: CardProductAndFinancialAccountSnapshot Query: query CardProductAndFinancialAccountSnapshot( $cardProductId: ID! $financialAccountId: ID! ) { # ============================================================ # CARD PRODUCT SETTINGS # ============================================================ cardProduct: node(id: $cardProductId) { __typename ... on CardProduct { id name commercial usage vertical sourceTemplateId # Card design and BIN defaultCardProfileSet { id name } cardProfileSets(first: 10) { ... on CardProfileSetConnection { edges { node { id name } } } } # Profiles profiles { __typename ... on Node { id } } # Capability flags (every CardProductFeature subtype) features { __typename ... on AuthorizedUserCardProductFeature { enabled } ... on ChargeCardProductFeature { enabled } ... on CollaborativeApplicationUnderwritingCardProductFeature { enabled } ... on CollaborativeAuthorizationCardProductFeature { enabled } ... on CreditLimitVarianceCardProductFeature { enabled } ... on DirectMerchantAcquiringCardProductFeature { enabled } ... on DisputeChargebackCardProductFeature { enabled } ... on EarlyDirectDepositCardProductFeature { enabled } ... on ExternalBusinessManagementCardProductFeature { enabled } ... on OnDemandFundingCardProductFeature { enabled } ... on PartialFundingCardProductFeature { enabled } ... on PointRewardCardProductFeature { enabled } ... on RevolvingCardProductFeature { enabled } ... on SecuredDepositCardProductFeature { enabled } } # Credit and fees creditConfiguration { __typename } creditPlanTemplates(first: 10) { edges { node { id } } } creditPlans(first: 10) { edges { node { id } } } feeSchedules(first: 20) { edges { node { id status } } } # Subscriber-managed rules attachedSpendRules(first: 20) { edges { node { id name } } } attachedVelocityRules(first: 20) { edges { node { id name } } } attachedInterFinancialAccountTransferRules(first: 20) { ... on InterFinancialAccountTransferRuleConnection { edges { node { __typename ... on Node { id } } } } } attachedRewardRules(first: 20) { edges { node { __typename } } } attachedRewardRedemptionConfigurations(first: 20) { edges { node { __typename } } } # Platform-imposed rules (read only) attachedPlatformSpendRules(first: 20) { edges { node { id name } } } attachedPlatformVelocityRules(first: 20) { edges { node { id name } } } # Risk rules attachedRealtimeRiskRules(first: 20) { ... on RealtimeRiskRuleConnection { edges { node { __typename ... on Node { id } } } } } # Sample of related accounts accounts(first: 5) { edges { node { id name accountStatus partnerBankName } } } } } # ============================================================ # FINANCIAL ACCOUNT SETTINGS # ============================================================ financialAccount: node(id: $financialAccountId) { __typename ... on FinancialAccount { id externalId name createdAt updatedAt accountStatus partnerBankName # Lifecycle and state flags accountAttributes financialAccountAttributesWithReason { attribute reason } accountClosureReasons # Relationships cardProduct { id name } owner { __typename ... on Node { id } } accountHolder { __typename ... on Node { id } } cardProductApplication { __typename ... on Node { id } } # Capabilities (enabled lives on the interface) features { __typename enabled } # Direct deposit details (account and routing numbers require a # Direct Deposit Details token with READ_RESTRICTED_DETAILS) directDepositDetails { id restrictedDetails { __typename ... on DirectDepositDetailRestrictedDetails { number routingNumber } } } # Balances and billing billingSummary { asOf minimumPaymentDue { value currencyCode decimalPlaces } paymentDueOn remainingLatestClosedStatementBalance { value currencyCode decimalPlaces } } statementSnapshot { __typename } activeBillingCycleConfiguration { __typename } delinquency { __typename } delinquencyState { __typename } # Credit configuration creditConfiguration { __typename } purchasePlans { __typename } # Attached rules (account level) attachedSpendRules(first: 20) { edges { node { id name } } } attachedVelocityRules(first: 20) { edges { node { id name } } } attachedRealtimeRiskRules(first: 20) { ... on RealtimeRiskRuleConnection { edges { node { __typename ... on Node { id } } } } } # Live velocity balances velocitySpendRuleBalances { __typename } # Recent activity samples paymentCards(first: 5) { edges { node { id last4 expirationDate } } } financialAccountActivities(first: 5) { edges { node { __typename } } } transactionEvents(first: 5) { edges { node { __typename ... on Node { id } } } } installmentAgreements(first: 5) { edges { node { id } } } feeTransferEvents(first: 5) { edges { node { __typename } } } # Subscriber metadata customFields { __typename key ... on CustomStringField { value } } userDefinedFields(first: 5) { edges { node { __typename } } } } } } Variables: { "cardProductId": "pd_36cb6f6818014bbba8644397ec5dfc86", "financialAccountId": "ac_c02204zs5i9mdnp381js3mksl5q8x9e6p6os" } Expected Result: { "data": { "cardProduct": { "__typename": "CardProduct", "id": "pd_36cb6f6818014bbba8644397ec5dfc86", "name": "Consumer Prepaid", "commercial": false, "usage": "MULTI_USE", "vertical": "CONSUMER_PREPAID", "sourceTemplateId": "default_consumer_prepaid", "defaultCardProfileSet": { "id": "", "name": "Default Card Profile Set" }, "cardProfileSets": { "edges": [ { "node": { "id": "", "name": "Default Card Profile Set" } } ] }, "profiles": [], "features": [ { "__typename": "DirectMerchantAcquiringCardProductFeature" } ], "creditConfiguration": null, "creditPlanTemplates": { "edges": [] }, "creditPlans": { "edges": [] }, "feeSchedules": { "edges": [] }, "attachedSpendRules": { "edges": [] }, "attachedVelocityRules": { "edges": [] }, "attachedInterFinancialAccountTransferRules": { "edges": [] }, "attachedRewardRules": { "edges": [] }, "attachedRewardRedemptionConfigurations": { "edges": [] }, "attachedPlatformSpendRules": { "edges": [] }, "attachedPlatformVelocityRules": { "edges": [] }, "attachedRealtimeRiskRules": { "edges": [] }, "accounts": { "edges": [ { "node": { "id": "ac_c02204zs5i9mdnp381js3mksl5q8x9e6p6os", "name": "Financial Account", "accountStatus": "ACTIVE", "partnerBankName": "" } } ] } }, "financialAccount": { "__typename": "FinancialAccount", "id": "ac_c02204zs5i9mdnp381js3mksl5q8x9e6p6os", "externalId": "8XB836QCX9", "name": "Financial Account", "createdAt": "2026-06-27T04:50:44.517Z", "updatedAt": "2026-06-27T04:50:44.517Z", "accountStatus": "ACTIVE", "partnerBankName": "", "accountAttributes": [], "financialAccountAttributesWithReason": [], "accountClosureReasons": [], "cardProduct": { "id": "pd_36cb6f6818014bbba8644397ec5dfc86", "name": "Consumer Prepaid" }, "owner": { "__typename": "USPersonAccountHolder", "id": "ps_ah0104z4ut86egq6r1js3lt4ale8x53wmbp2" }, "accountHolder": { "__typename": "USPersonAccountHolder", "id": "ps_ah0104z4ut86egq6r1js3lt4ale8x53wmbp2" }, "cardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "ap_22pcgm04zeomj6avgwa1js3lvibrwk2wvjb6wc" }, "features": [ { "__typename": "DirectDepositFinancialAccountFeature", "enabled": true }, { "__typename": "PrePaidPaymentCardFinancialAccountFeature", "enabled": true } ], "directDepositDetails": { "id": "dd_6ad0d38f33594d0b89b17dc0076228b4", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "billingSummary": null, "statementSnapshot": null, "activeBillingCycleConfiguration": null, "delinquency": null, "delinquencyState": null, "creditConfiguration": null, "purchasePlans": [], "attachedSpendRules": { "edges": [] }, "attachedVelocityRules": { "edges": [] }, "attachedRealtimeRiskRules": { "edges": [] }, "velocitySpendRuleBalances": [], "paymentCards": { "edges": [] }, "financialAccountActivities": { "edges": [] }, "transactionEvents": { "edges": [] }, "installmentAgreements": { "edges": [] }, "feeTransferEvents": { "edges": [] }, "customFields": [], "userDefinedFields": { "edges": [] } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/application-denials Title: Application Denials Section: Issuing Description: Understand why a card product application is denied: the general application denial reasons, inactivity denials, how the reason is delivered in notifications, and how it relates to credit adverse action codes. ## Overview When a card product application is denied, two fields expose why, at different levels of specificity: - : a general reason available on every card product application. - : specific reasons populated only for underwritten (credit) applications. **This guide covers the general denial reasons**, including inactivity denials, and how they relate to adverse action codes. For credit decisions, see Simulate Underwriting Decisions. ## Application denial reasons The field is available on both and . It returns one of two intentionally general values from the enum: - : the application could not be decisioned within the timeframe defined in the cardholder agreement because required information was missing. - : the application was denied for another reason. Highnote keeps these subscriber-facing reasons general by design. Internally, Highnote maintains more specific denial reasons for auditing and compliance. is available on every card product application. Underwritten applications additionally receive a more specific adverse action code. See Adverse action codes. ## Inactivity denials An inactivity denial () occurs when an application stalls before it can be decisioned and the timeframe defined in the cardholder agreement elapses. This is typically because information needed to verify the applicant was never provided. Because this timeframe is set by the cardholder agreement, it can vary by card product. An inactivity denial reflects an application that was never completed, not a substantive decision against the applicant. ## Denial notifications When an application is denied, Highnote sends a notification event: - : for account holder applications. - : for authorized user applications. The denied application is included in the event, so you can read directly from the notification. No separate lookup is required. ## Adverse action codes Underwritten (credit) applications populate the field, in addition to the general . Each entry carries a (an ) and a human-friendly . The code reflects the step at which the application was denied; for example, an application closed while awaiting underwriting maps to . In collaborative underwriting, a decision must be received within 30 days of the application creation date, or the application transitions to with an adverse action code. - See Collaborative Application Decisioning to learn how adverse action reasons are assigned during underwriting. - See Simulate Underwriting Decisions for the complete list of adverse action codes and how to simulate them in the Test environment. - See AdverseActionCode in the API Reference for the enum definition. --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/authorized-users-v1 Title: Onboard Authorized Users (deprecated) Section: Issuing Description: Create authorized users for commercial card products with separate financial accounts and categorized spending. This is the deprecated v1 model. ## Overview Highnote released a simplified model for Authorized Users that applies to both consumer and commercial card products. Going forward, all authorized users are Person account holder objects, even commercial products where the primary account holder is a Business account holder object. An authorized user of a commercial card product is a cardholder with access to a card product, but with fewer permissions than the primary account holder. On the Highnote platform, each authorized user is recognized as a separate entity. For example, a business account holder can issue cards to employees as authorized users. Each employee is assigned a unique ID, regardless of whether they are associated with multiple cards under the same account, or have a shared user profile in your system. The following graphic shows the relationship of a single card product with an authorized user who has multiple applications and payment cards: ## Prerequisites 1. A Highnote account 2. An API key, the API Explorer. or the Dashboard 3. An account holder with approved application 4. Authorized users feature enabled by the Highnote Support team. Contact support@highnote.com to have this feature enabled. ## Categorized spending Categorized spending is one use case for an authorized user of a commercial card. This use case requires the API to pass specific financial account IDs. For simpler use cases in the Dashboard, see Authorized users in the Support docs. To configure an authorized user for categorized spending of a commercial card: 1. Create individual financial accounts using a business account holder's application. Each financial account represents a different spending category. For example, you might have separate financial accounts for gas, groceries, and office supplies. 2. Onboard authorized users under the business account holder. 3. Open an application for the authorized user and pass the of the spend category financial account. 4. Issue cards to authorized users. In this use case, each authorized user must be onboarded individually. If authorized users need access to multiple spending categories, they must apply to each financial account separately. One authorized user account may have several applications, financial accounts, and cards; each representing a different spend category. ## Onboard an authorized user Authorized users must be **18 or older** and 100 or younger (to combat fraud and elder financial abuse); and their **first names must be at least one character**. For enhanced security, unboard authorized users with client tokens. Before adding authorized users, you must onboard an account holder with an approved application. When creating a new authorized user, you will pass the to establish the relationship with the account holder. For extra security, you can generate a client token and tokenize authorized user information on your client before passing the data to Highnote. When using the following mutation to create an authorized user, the following inputs are required: - - - - - ## Open application After creating an authorized user, you must open an authorized user application and present your cardholder agreements. You can subscribe to notification events for updates on the application status. Use the following mutation to open an authorized user application: ## Issue payment card If you choose to issue physical cards, during card personalization, the authorized user's first and last name are _required for line 1_. For more information on issuing physical cards, see the Print Physical Cards guide. Once an authorized user has an approved application, you can issue a payment card to the authorized user. Use the following query to issue a payment card to an authorized user: ## Find authorized user Once an authorized user has been created, you can find authorized details, including associated applications and payment cards. Use the following query to find authorized user details: ### GraphQL: CreateUSPersonAuthorizedUser Query: mutation CreateUSPersonAuthorizedUser( $input: CreateUSPersonAuthorizedUserInput! ) { createUSPersonAuthorizedUser(input: $input) { __typename ... on USPersonAuthorizedUser { id email dateOfBirth externalId createdAt updatedAt name { givenName familyName title suffix middleName } billingAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } identificationDocument { socialSecurityNumber { numberHash countryCodeAlpha3 } } cardProductApplications { edges { node { id } } } paymentCards { edges { node { id } } } associatedAccountHolders { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { ... on Node { id } ... on USBusinessAccountHolder { __typename id } ... on USPersonAccountHolder { __typename id } } } } } } } Variables: { "input": { "accountHolderId": "", "personAuthorizedUser": { "email": "foo@example.com", "name": { "givenName": "Bill", "familyName": "Someone" }, "billingAddress": { "streetAddress": "123 Main Street", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE" }, "identificationDocument": { "socialSecurityNumber": { "number": "123-21-1131", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "1980-09-01", "externalId": "user-id-in-your-system" } } } Expected Result: { "data": { "createUSPersonAuthorizedUser": { "__typename": "USPersonAuthorizedUser", "id": "", "email": "foo@example.com", "dateOfBirth": "1980-09-01", "externalId": "my-external-id", "createdAt": "2021-07-07T23:22:30.475Z", "updatedAt": "2021-07-07T23:22:30.475Z", "name": { "givenName": "Bill", "familyName": "Someone", "title": "Mr.", "suffix": "Jr.", "middleName": "Bob" }, "billingAddress": { "streetAddress": "123 Main Street", "extendedAddress": "somewhere", "postalCode": "60654", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "5555555555", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": { "numberHash": "some-hash", "countryCodeAlpha3": "USA" } }, "cardProductApplications": [], "paymentCards": [], "associatedAccountHolders": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "cursorvalue", "endCursor": "cursorvalue" }, "edges": [ { "cursor": "cursorvalue", "node": { "__typename": "USBusinessAccountHolder", "id": "" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: CreateAuthorizedUserCardProductApplication Query: mutation createAuthorizedUserCardProductApplication( $input: CreateAuthorizedUserCardProductApplicationInput! ) { createAuthorizedUserCardProductApplication(input: $input) { __typename ... on AuthorizedUserCardProductApplication { id applicationState { status } financialAccount { id name createdAt } accountHolderCardProductApplication { id applicationState { status } } authorizedUserSnapshot { ... on USPersonAuthorizedUserSnapshot { authorizedUserCurrent { id } name { givenName familyName } billingAddress { streetAddress locality } email phoneNumbers { label number } dateOfBirth } ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } name { givenName familyName } billingAddress { streetAddress locality } email phoneNumbers { label number } dateOfBirth } } applicationHistory { pageInfo { hasNextPage } } updatedAt createdAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "authorizedUserId": "", "accountHolderCardProductApplicationId": "", "financialAccountId": "", "cardHolderAgreementConsent": { "consentTimestamp": "2025-04-16T04:46:56.234Z", "primaryAuthorizedPersonId": "" } } } Expected Result: { "data": { "createAuthorizedUserCardProductApplication": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "financialAccount": { "id": "", "name": "Primary account", "createdAt": "2025-04-15T18:42:25.914Z" }, "accountHolderCardProductApplication": { "id": "", "applicationState": { "status": "APPROVED" } }, "authorizedUserSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Authorized", "familyName": "User" }, "billingAddress": { "streetAddress": "642 Harrison St", "locality": "San Francisco" }, "email": "au@abc.com", "phoneNumbers": [ { "label": null, "number": "1234567890" } ], "dateOfBirth": "2007-04-01" }, "applicationHistory": { "pageInfo": { "hasNextPage": false } }, "updatedAt": "2025-04-17T04:45:57.217Z", "createdAt": "2025-04-17T04:45:57.214Z" } }, "extensions": { "requestId": "4e43ebaf-4248-9b64-b599-6e93236e90e6", "rateLimit": { "cost": 41, "limit": 60060, "remaining": 60019, "asOf": "2025-04-17T04:45:57.469Z", "complexity": { "limit": 60060, "remaining": 60019, "cost": 41 }, "count": { "limit": 60060, "remaining": 60059, "cost": 1 } } } } ### GraphQL: IssuePaymentCardForAuthorizedUserApplication Query: mutation IssuePaymentCardForAuthorizedUserApplication( $input: IssuePaymentCardForAuthorizedUserApplicationInput! ) { issuePaymentCardForAuthorizedUserApplication(input: $input) { ... on PaymentCard { id bin last4 expirationDate network status formFactor cardProductApplication { ... on Node { id } ... on AuthorizedUserCardProductApplication { __typename id } } } } } Variables: { "input": { "applicationId": "", "options": { "activateOnCreate": true, "expirationDate": "2024-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForAuthorizedUserApplication": { "id": "", "bin": "510520", "last4": "0707", "expirationDate": "2024-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "formFactor": "VIRTUAL", "application": null, "cardProductApplication": { "__typename": "AuthorizedUserCardProductApplication", "id": "" } } }, "extensions": { "requestId": "" } } ### GraphQL: GetUSPersonAuthorizedUser Query: query GetUSPersonAuthorizedUser($id: ID!) { node(id: $id) { ... on USPersonAuthorizedUser { id email dateOfBirth externalId updatedAt createdAt name { givenName familyName title suffix middleName } billingAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } associatedAccountHolders { pageInfo { hasNextPage } edges { cursor node { __typename ... on Node { id } ... on USBusinessAccountHolder { id } } } __typename } cardProductApplications { pageInfo { hasNextPage } edges { cursor node { id applicationState { status } } } } paymentCards { pageInfo { hasNextPage } edges { cursor node { id status } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "email": "foo@example.com", "dateOfBirth": "1980-09-01", "externalId": "my-external-id", "createdAt": "2021-07-07T23:22:30.475Z", "updatedAt": "2021-07-07T23:22:30.475Z", "name": { "givenName": "Bill", "familyName": "Someone", "title": "Mr.", "suffix": "Jr.", "middleName": "Bob" }, "billingAddress": { "streetAddress": "123 Main Street", "extendedAddress": "somewhere", "postalCode": "60654", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "5555555555", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": { "numberHash": "some-hash", "countryCodeAlpha3": "USA" } }, "cardProductApplications": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "", "status": "APPROVED" } } ] }, "paymentCards": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "", "status": "ACTIVE" } } ] }, "associatedAccountHolders": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "some-cursor", "endCursor": "some-cursor" }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "USBusinessAccountHolder", "id": "" } } ] } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/authorized-users Title: Onboard Authorized Users Section: Issuing Description: Onboard authorized users with tokenization and issue cards from primary or dedicated financial accounts. Configure spend rules per authorized user. ## Overview Highnote released a simplified model for Authorized Users that applies to both consumer and commercial card products. Going forward, all authorized users are Person account holder objects, even commercial products where the primary account holder is a Business account holder object. An authorized user of a card product is a person who is granted access to the financial account of the primary account holder. Authorized user operations are managed through the [](/docs/api-reference/object#USPersonAccountHolder) object, which links them to their applications, financial accounts, and payment cards. To onboard a consumer authorized user: 1. **Create an authorized user** securely with a token (or if necessary without token): Onboard a new user by providing their personal information, such as name, address, and date of birth. 2. **Create a card application for the authorized user**: Apply for a card product on their behalf and link them to a primary financial account. 3. **Issue a payment card to the authorized user**: Issue a virtual or physical payment card directly to the approved authorized user. You have two options: (a) issue the card from the primary financial account, or (b) create an authorized user financial account and issue from that. ## Step 1. Create authorized user securely with tokenization Creating an authorized user is the first step in the onboarding process. You can create authorized users with or without tokenizing, but Highnote highly recommends tokenization for enhanced security, especially in client-side applications. Tokenizing ensures that sensitive data is never directly handled by your servers. This set of mutations let you tokenize an authorized user's personally identifiable information (PII) before creating their profile. The flow involves generating a client token, using it to tokenize the user's data, and then creating the user from that secure token. ### 1a. Generate client token The first step in the tokenization process is to generate a short-lived client token. This token grants temporary permission for a client-side application to securely submit user data for tokenization without having long-term API credentials exposed on the client. No input is required to generate the client token. ### 1b. Tokenize authorized user With a valid client token from the previous step, you can now exchange the authorized user's personal information for a secure, single-use token. The tokenizeUSPersonAccountHolder mutation takes the user's PII and returns a token that represents this data, which can then be safely passed to your backend. ### 1c. Create authorized user from token The final step is to create the authorized user's profile using the secure token. By calling createUSPersonAccountHolderFromToken, your backend can create the user without ever directly handling their sensitive PII, which was exchanged for the token in the previous step. ## Create authorized user (without tokenization) Highnote recommends that you use the more secure process of creating authorized users with tokenization. To create an authorized user without tokenization, call the following createUSPersonAccountHolder mutation and provide the user's personal information to generate their profile and unique ID. ## Step 2. Create card application for authorized user After creating a user profile, the next step is to create a card application for them. This mutation links the authorized user to a primary account, which allows them to be issued a payment card. Set to the ID of the primary account holder's financial account. ## Step 3. Issue payment card to authorized user After an authorized user has been created and their application has been approved, you can issue them a payment card. Depending on your card program's configuration, you have two options: - Option 1: Issue a card directly from the primary account holder's account or - Option 2: Issue a card from a dedicated authorized user financial account which requires that you (a) create the account application, then (b) issue the card from the account generated by the application. ## Option 1: Issue card from primary account Authorized user cards issued from a primary financial account inherit spend rules from the primary account. To create separate authorized user spend rules, you must create a dedicated authorized user financial account. Some card programs let you issue an authorized user card directly from the primary financial account, and do _not_ require a dedicated authorized user account. To issue a payment card to an authorized user from the primary account holder account, call the mutation issuePaymentCardForAuthorizedUserApplication. Set to the ID of the application you submitted in Step 2. This application in Step 2 is tied to the of the primary account holder. ## Option 2: Issue card from authorized user account Some card programs _require_ a dedicated authorized user account to issue a payment card to an authorized user. For example, if your program requires unique spend rules for the primary user and the authorized user, then each of them must have their own financial account. ### (Option 2a) Create financial account application for authorized user First, create a financial account application for the authorized user by calling the mutation issueFinancialAccountForApplication. Just as with Option 1, set to the ID of the application you submitted in Step 2, because it is tied to the of the primary account holder. The difference is that rather than issuing a card as you did in Option 1, here, you are applying to create a financial account for the authorized user from which you can issue a card in the next step. ### (Option 2b) Issue card from authorized user account Next, issue a payment card to the authorized use from the new financial account (created above). Use the issuePaymentCardForFinancialAccount mutation to create a card for the financial account created based on the authorized user application. Set to the ID of the financial account you created for this authorized user (in Option 2a). ## Minimum age for authorized users By default, an authorized user must be at least 18 years old, and at most 99 years old. This is the same default range Highnote applies to primary account holders. Highnote Operations can set a different minimum and maximum age for your program's authorized user identity verification workflow. For example, a family-finance program might allow a parent to add a child of any age as an authorized user. This setting is not self-service. Contact your Highnote representative to request a custom age range for your program. The [](/docs/api-reference/input#USPersonAccountHolderInput) field has no enforced minimum age when you create the account holder — Highnote checks the applicant's age against your program's configured minimum during identity verification, not at account holder creation. A 99-year maximum-age check still applies at creation, as a platform-wide sanity check independent of your program's configured range. Revetting (re-evaluating) an existing authorized user's application does not yet apply your program's custom age range. The platform default of 18 years applies instead. New applications are not affected. ## Update authorized user You can modify an authorized user's personal information after their profile has been created. The following mutations allow you to update their billing address, phone number, and email address individually. Each mutation requires the accountHolderId of the account holder the authorized user belongs to, plus the authorized user's unique authorizedUserId to identify which profile to update. ### Address To update the billing address for an authorized user, call the mutation updateUSPersonAuthorizedUserBillingAddress. ### Phone number To update the phone number for an authorized user, call the mutation updateUSPersonAuthorizedUserPhone. ### Email To update the email address for an authorized user, call the mutation updateUSPersonAuthorizedUserEmail. ## Query authorized users The following four queries let you find authorized users by person, or by account. The first two queries are person-centric, designed to find and retrieve the profiles of authorized users. - Find authorized user by authorized user ID - Find authorized user by personal data The last two queries are account-centric, designed to map the relationships between users and their financial accounts. - Find financial accounts for authorized user - Find all authorized users by primary financial account ### Find authorized user by authorized user ID This query uses USPersonAccountHolder to retrieve a single authorized user's complete profile by using their unique . The returned information includes personal details such as their name, email, and date of birth, as well as their billing address and phone number. It also fetches the status of any card products they have applied for. ### Find authorized user by personal data This query uses USPersonAccountHolder to search for authorized users by filtering on specific personal information, such as their name and date of birth. It returns a paginated list of all users who match the search criteria. For each user found, the query provides a detailed profile that includes their personal data, contact information, and the status of their applications. ### Find financial accounts for authorized user This query retrieves all the financial accounts associated with a single authorized user by using that person's account holder as the input. The results include a list of financial accounts, with details on account status, enabled features (like ), and ledger balances. This is used to see all the accounts a person is authorized to use. ### Find all authorized users by primary financial account This query identifies all authorized users linked to a specific primary financial account by using the account's . It returns a list of the associated authorized user financial accounts, including details about their status, features, payment cards, and ledger balances. This is useful for retrieving all authorized users on a single primary account. ## How to determine Authorized User types To determine if a or is an Authorized User: 1. Query the USPersonAccountHolder or PersonAccountHolder node. 2. Check for associations; the account holder is acting as an Authorized User if: - Application type = . - Financial account has feature with type = . | \_\_typename | Is Authorized User? | How to Determine in New Model? | | :------------------------- | :------------------ | :------------------------------------------------------------------------ | | USPersonAuthorizedUser | Yes | Deprecated, use USPersonAccountHolder instead | | PersonAuthorizedUser | Yes | Deprecated, use PersonAccountHolder instead | | USBusinessAuthorizedPerson | No | Not an authorized user | | AuthorizedPerson | No | Not an authorized user | | PersonAccountHolder | No\* | \*But can be, if associated with authorized user applications or features | | USPersonAccountHolder | No\* | \*But can be, if associated with authorized user applications or features | ### GraphQL: GenerateTokenizeAccountHolderClientToken Query: mutation GenerateTokenizeAccountHolderClientToken { generateTokenizeAccountHolderClientToken { __typename ... on ClientToken { value expirationDate usage } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } Variables: {} Expected Result: { "data": { "generateTokenizeAccountHolderClientToken": { "__typename": "ClientToken", "value": "", "expirationDate": "2026-03-28T01:00:00.000Z", "usage": "UNTIL_EXPIRATION" } }, "extensions": { "requestId": "d47a92c3-5f18-4e6d-b902-3a8c1ef57b24" } } ### GraphQL: TokenizeUSPersonAccountHolder Query: mutation TokenizeUSPersonAccountHolder( $input: CreateUSPersonAccountHolderInput! ) { tokenizeUSPersonAccountHolder(input: $input) { ... on USPersonAccountHolderToken { token } } } Variables: { "input": { "personAccountHolder": { "email": "foo@example.com", "name": { "givenName": "Ian", "familyName": "Somnia" }, "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" } }, "dateOfBirth": "1980-09-01", "externalId": "some-id" } } } Expected Result: { "data": { "tokenizeUSPersonAccountHolder": { "token": "input-token" } } } ### GraphQL: CreateUSPersonAccountHolderFromToken Query: mutation CreateUSPersonAccountHolderFromToken( $input: CreateUSPersonAccountHolderFromTokenInput! ) { createUSPersonAccountHolderFromToken(input: $input) { ... on USPersonAccountHolder { id externalId createdAt } } } Variables: { "input": { "token": "input-token" } } Expected Result: { "data": { "createUSPersonAccountHolderFromToken": { "id": "ps_ah01a290dd7d366c46b3a0a39e6e1f6dd670=", "externalId": "some-id", "createdAt": "2022-01-12T19:07:19.056Z" } } } ### GraphQL: 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 } } } } } Variables: { "input": { "personAccountHolder": { "email": "au@abc.com", "name": { "givenName": "Authorized", "familyName": "User" }, "billingAddress": { "streetAddress": "642 Harrison St", "extendedAddress": "Suite 100", "postalCode": "94107", "locality": "San Francisco", "region": "CA", "countryCodeAlpha3": "USA" }, "phoneNumber": { "countryCode": "1", "number": "1234567890", "label": "MOBILE", "extension": "312" }, "identificationDocument": { "socialSecurityNumber": { "number": "234-11-1111", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "2007-04-01" } } } Expected Result: { "data": { "createUSPersonAccountHolder": { "__typename": "USPersonAccountHolder", "id": "", "email": "au@abc.com", "dateOfBirth": "2007-04-01", "externalId": "", "updatedAt": "2025-04-15T18:42:47.343Z", "createdAt": "2025-04-15T18:42:47.343Z", "name": { "givenName": "Authorized", "familyName": "User", "title": "", "suffix": "", "middleName": "" }, "billingAddress": { "streetAddress": "642 Harrison St", "extendedAddress": "Suite 100", "postalCode": "94107", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "1234567890", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": { "numberHash": "AQAAAAPrQQYZbUDpgaWGiJ9Kijz_dKCR06i5tRa4r_JZoBVTng", "countryCodeAlpha3": "USA" } } } }, "extensions": { "requestId": "2b1496f5-1bc0-912f-b230-97b6fc883245", "rateLimit": { "cost": 15, "limit": 60060, "remaining": 59682, "asOf": "2025-04-15T18:42:47.385Z", "complexity": { "limit": 60060, "remaining": 59682, "cost": 15 }, "count": { "limit": 60060, "remaining": 60042, "cost": 1 } } } } ### GraphQL: CreateAuthorizedUserCardProductApplication Query: mutation createAuthorizedUserCardProductApplication( $input: CreateAuthorizedUserCardProductApplicationInput! ) { createAuthorizedUserCardProductApplication(input: $input) { __typename ... on AuthorizedUserCardProductApplication { id applicationState { status } financialAccount { id name createdAt } accountHolderCardProductApplication { id applicationState { status } } authorizedUserSnapshot { ... on USPersonAuthorizedUserSnapshot { authorizedUserCurrent { id } name { givenName familyName } billingAddress { streetAddress locality } email phoneNumbers { label number } dateOfBirth } ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } name { givenName familyName } billingAddress { streetAddress locality } email phoneNumbers { label number } dateOfBirth } } applicationHistory { pageInfo { hasNextPage } } updatedAt createdAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "authorizedUserId": "", "accountHolderCardProductApplicationId": "", "financialAccountId": "", "cardHolderAgreementConsent": { "consentTimestamp": "2025-04-16T04:46:56.234Z", "primaryAuthorizedPersonId": "" } } } Expected Result: { "data": { "createAuthorizedUserCardProductApplication": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "financialAccount": { "id": "", "name": "Primary account", "createdAt": "2025-04-15T18:42:25.914Z" }, "accountHolderCardProductApplication": { "id": "", "applicationState": { "status": "APPROVED" } }, "authorizedUserSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Authorized", "familyName": "User" }, "billingAddress": { "streetAddress": "642 Harrison St", "locality": "San Francisco" }, "email": "au@abc.com", "phoneNumbers": [ { "label": null, "number": "1234567890" } ], "dateOfBirth": "2007-04-01" }, "applicationHistory": { "pageInfo": { "hasNextPage": false } }, "updatedAt": "2025-04-17T04:45:57.217Z", "createdAt": "2025-04-17T04:45:57.214Z" } }, "extensions": { "requestId": "4e43ebaf-4248-9b64-b599-6e93236e90e6", "rateLimit": { "cost": 41, "limit": 60060, "remaining": 60019, "asOf": "2025-04-17T04:45:57.469Z", "complexity": { "limit": 60060, "remaining": 60019, "cost": 41 }, "count": { "limit": 60060, "remaining": 60059, "cost": 1 } } } } ### GraphQL: IssuePaymentCardForAuthorizedUserApplication Query: mutation IssuePaymentCardForAuthorizedUserApplication( $input: IssuePaymentCardForAuthorizedUserApplicationInput! ) { issuePaymentCardForAuthorizedUserApplication(input: $input) { ... on PaymentCard { id bin last4 expirationDate network status formFactor cardProductApplication { ... on Node { id } ... on AuthorizedUserCardProductApplication { __typename id } } } } } Variables: { "input": { "applicationId": "", "options": { "activateOnCreate": true, "expirationDate": "2024-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForAuthorizedUserApplication": { "id": "", "bin": "510520", "last4": "0707", "expirationDate": "2024-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "formFactor": "VIRTUAL", "application": null, "cardProductApplication": { "__typename": "AuthorizedUserCardProductApplication", "id": "" } } }, "extensions": { "requestId": "6ed5be48-7736-917a-b0c3-f21cd7c6a2b2" } } ### GraphQL: IssueFinancialAccountForApplication Query: mutation IssueFinancialAccountForApplication( $input: IssueFinancialAccountForApplicationInput! ) { issueFinancialAccountForApplication(input: $input) { ... on FinancialAccount { id accountStatus cardProductApplication { __typename ... on AccountHolderCardProductApplication { id appState: applicationState { status } } ... on AuthorizedUserCardProductApplication { id authAppState: applicationState { status } } } revisionSnapshots { edges { node { id financialAccount { id } cardProductApplication { __typename ... on AccountHolderCardProductApplication { id appState: applicationState { status } } ... on AuthorizedUserCardProductApplication { id authAppState: applicationState { status } } } } } } ledgers { name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } updatedAt createdAt } } } Variables: { "input": { "applicationId": "", "name": "Auth account" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "accountStatus": "ACTIVE", "application": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "appState": { "status": "APPROVED" } }, "cardProductApplication": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "appState": { "status": "APPROVED" } }, "revisionSnapshots": { "edges": [ { "node": { "id": "", "financialAccount": { "id": "" }, "application": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "appState": { "status": "APPROVED" } }, "cardProductApplication": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "appState": { "status": "APPROVED" } } } } ] }, "ledgers": [ { "name": "AVAILABLE_CASH", "normalBalance": "CREDIT", "creditBalance": { "value": 0, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, { "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "value": 0, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, { "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 0, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, { "name": "CREDIT_OUTSTANDING", "normalBalance": "DEBIT", "creditBalance": { "value": 0, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } } ], "updatedAt": "2025-04-17T06:00:06.554Z", "createdAt": "2025-04-17T06:00:06.554Z" } }, "extensions": { "requestId": "820c1448-b9c3-93cc-ab61-4929ae2b4e36", "rateLimit": { "cost": 119, "limit": 60060, "remaining": 59940, "asOf": "2025-04-17T06:00:06.704Z", "complexity": { "limit": 60060, "remaining": 59940, "cost": 119 }, "count": { "limit": 60060, "remaining": 60058, "cost": 1 } } } } ### GraphQL: IssuePaymentCardForFinancialAccount Query: mutation IssuePaymentCardForFinancialAccount( $input: IssuePaymentCardForFinancialAccountInput! ) { issuePaymentCardForFinancialAccount(input: $input) { ... on PaymentCard { id bin last4 expirationDate network status financialAccounts { id name } } ... on UserError { errors { code description } } } } Variables: { "input": { "financialAccountId": "", "options": { "activateOnCreate": true, "expirationDate": "2026-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489651", "last4": "1942", "expirationDate": "2026-01-01T23:59:59Z", "network": "VISA", "status": "ACTIVE", "financialAccounts": null } }, "extensions": { "requestId": "2776372f-0246-9ce9-ac22-d996258c0857", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60046, "asOf": "2025-04-17T06:03:18.082Z", "complexity": { "limit": 60060, "remaining": 60046, "cost": 11 }, "count": { "limit": 60060, "remaining": 60056, "cost": 1 } } } } ### GraphQL: UpdateUSPersonAuthorizedUserBillingAddress Query: mutation updateUSPersonAuthorizedUserBillingAddress( $input: UpdateUSPersonAuthorizedUserBillingAddressInput! ) { updateUSPersonAuthorizedUserBillingAddress(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAuthorizedUser { id billingAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } } Variables: { "input": { "billingAddress": { "streetAddress": "444 Main Street", "postalCode": "60606", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "authorizedUserId": "", "accountHolderId": "", "updatePaymentCardBillingAddress": true } } Expected Result: { "data": { "updateUSPersonAuthorizedUserBillingAddress": { "__typename": "USPersonAuthorizedUser", "id": "", "billingAddress": { "streetAddress": "444 Main Street", "extendedAddress": "", "postalCode": "60606", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" } } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSPersonAuthorizedUserPhone Query: mutation updateUSPersonAuthorizedUserPhone( $input: UpdateUSPersonAuthorizedUserPhoneInput! ) { updateUSPersonAuthorizedUserPhone(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAuthorizedUser { id phoneNumbers { countryCode number label } } } } Variables: { "input": { "phoneNumber": { "countryCode": "1", "number": "234123444", "label": "MOBILE", "extension": "312" }, "authorizedUserId": "", "accountHolderId": "" } } Expected Result: { "data": { "updateUSPersonAuthorizedUserPhone": { "__typename": "USPersonAuthorizedUser", "id": "", "phoneNumbers": [ { "countryCode": "1", "number": "234123444", "label": "MOBILE" } ] } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSPersonAuthorizedUserEmail Query: mutation updateUSPersonAuthorizedUserEmail( $input: UpdateUSPersonAuthorizedUserEmailInput! ) { updateUSPersonAuthorizedUserEmail(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAuthorizedUser { id email } } } Variables: { "input": { "email": "abc@123.com", "authorizedUserId": "", "accountHolderId": "" } } Expected Result: { "data": { "updateUSPersonAuthorizedUserEmail": { "__typename": "USPersonAuthorizedUser", "id": "", "email": "abc@123.com" } }, "extensions": { "requestId": "" } } ### GraphQL: GetUSPersonAccountHolder Query: query GetUSPersonAccountHolder($id: ID!) { node(id: $id) { __typename ... 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 } } paymentCards { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { node { id last4 } } } applications { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { node { __typename ... on AccountHolderCardProductApplication { id appState: applicationState { status } } ... on AuthorizedUserCardProductApplication { id authAppState: applicationState { status } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "USPersonAccountHolder", "id": "", "email": "au@abc.com", "dateOfBirth": "2007-04-01", "externalId": "", "updatedAt": "2025-04-17T04:45:30.681Z", "createdAt": "2025-04-17T04:45:30.469Z", "name": { "givenName": "Authorized", "familyName": "User", "title": "", "suffix": "", "middleName": "" }, "billingAddress": { "streetAddress": "642 Harrison St", "extendedAddress": "Suite 100", "postalCode": "94107", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "1234567890", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": { "numberHash": "", "countryCodeAlpha3": "USA" } }, "paymentCards": null, "cardProductApplications": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA0LTE3VDA0JTNBNDUlM0E1Ny4yMTQwMDAwMDBaJmk9YXBfZTFjODcwYjgyYjViNDhmNmJlMDQ5MDAzZjk5MDUzM2Y", "endCursor": "dD0yMDI1LTA0LTE3VDA0JTNBNDUlM0E1Ny4yMTQwMDAwMDBaJmk9YXBfZTFjODcwYjgyYjViNDhmNmJlMDQ5MDAzZjk5MDUzM2Y" }, "edges": [ { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "appStatus": { "status": "APPROVED" } } } ] }, "applications": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA0LTE3VDA0JTNBNDUlM0E1Ny4yMTQwMDAwMDBaJmk9YXBfZTFjODcwYjgyYjViNDhmNmJlMDQ5MDAzZjk5MDUzM2Y", "endCursor": "dD0yMDI1LTA0LTE3VDA0JTNBNDUlM0E1Ny4yMTQwMDAwMDBaJmk9YXBfZTFjODcwYjgyYjViNDhmNmJlMDQ5MDAzZjk5MDUzM2Y" }, "edges": [ { "node": { "__typename": "AuthorizedUserCardProductApplication", "id": "", "authAppState": { "status": "APPROVED" } } } ] } } }, "extensions": { "requestId": "25a68a1d-f208-910e-b417-5b58a292cdc0", "rateLimit": { "cost": 72, "limit": 60060, "remaining": 59987, "asOf": "2025-04-17T06:08:24.075Z", "complexity": { "limit": 60060, "remaining": 59987, "cost": 72 }, "count": { "limit": 60060, "remaining": 60058, "cost": 1 } } } } ### GraphQL: ListAccountHolders Query: query ListAccountHolders($first: Int, $after: String) { personAccountHolders(first: $first, after: $after) { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { ... 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 } } paymentCards { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { node { id last4 } } } applications { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { node { __typename ... on AccountHolderCardProductApplication { id appState: applicationState { status } } ... on AuthorizedUserCardProductApplication { id authAppState: applicationState { status } } } } } } } } } } Variables: { "first": 2, "filterBy": { "name": { "givenName": { "soundsLike": [ "John" ] } }, "dateOfBirth": { "equals": "1980-09-01" } } } Expected Result: { "data": { "personAccountHolders": { "pageInfo": { "startCursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTYlM0E1MS43MzQwMDAwMDBaJmk9cHNfNWE3OTE2Yzk2YzcxNDcwNGI0N2Q1NDliNTIzMDc5ZWQ", "endCursor": "dD0yMDI1LTA0LTA5VDIyJTNBNTMlM0EyNS4yMTIwMDAwMDBaJmk9cHNfN2MwYWVkMjkyZjFjNDA2ZGIwZDk3M2M2NjM0NTg4N2Q", "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "cursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTYlM0E1MS43MzQwMDAwMDBaJmk9cHNfNWE3OTE2Yzk2YzcxNDcwNGI0N2Q1NDliNTIzMDc5ZWQ", "node": { "id": "", "email": "gerrytest1@abc.com", "dateOfBirth": "1980-09-01", "externalId": "some-id", "updatedAt": "2025-04-15T16:57:33.909Z", "createdAt": "2025-04-15T16:56:51.223Z", "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": "", "countryCodeAlpha3": "USA" } }, "paymentCards": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTklM0E0Mi45ODAwMDAwMDBaJmk9Y2RfMDhlMDFlMzZiYmU2NDRhMTk2ZmVkYWExYzJiZjVmNDI", "endCursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTklM0E0Mi45ODAwMDAwMDBaJmk9Y2RfMDhlMDFlMzZiYmU2NDRhMTk2ZmVkYWExYzJiZjVmNDI" }, "edges": [ { "node": { "id": "", "last4": "2229" } } ] }, "cardProductApplications": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTclM0EyNS4xMzAwMDAwMDBaJmk9YXBfMzc3NmNjZWU3OTI1NGQ1MzgwODEyMTYwYjNiYTRhMTE", "endCursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTclM0EyNS4xMzAwMDAwMDBaJmk9YXBfMzc3NmNjZWU3OTI1NGQ1MzgwODEyMTYwYjNiYTRhMTE" }, "edges": [ { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "appStatus": { "status": "APPROVED" } } } ] }, "applications": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTclM0EyNS4xMzAwMDAwMDBaJmk9YXBfMzc3NmNjZWU3OTI1NGQ1MzgwODEyMTYwYjNiYTRhMTE", "endCursor": "dD0yMDI1LTA0LTE1VDE2JTNBNTclM0EyNS4xMzAwMDAwMDBaJmk9YXBfMzc3NmNjZWU3OTI1NGQ1MzgwODEyMTYwYjNiYTRhMTE" }, "edges": [ { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "appState": { "status": "APPROVED" } } } ] } } }, { "cursor": "dD0yMDI1LTA0LTA5VDIyJTNBNTMlM0EyNS4yMTIwMDAwMDBaJmk9cHNfN2MwYWVkMjkyZjFjNDA2ZGIwZDk3M2M2NjM0NTg4N2Q", "node": { "id": "", "email": "test@gmail.com", "dateOfBirth": "1970-04-01", "externalId": "", "updatedAt": "2025-04-09T22:53:25.159Z", "createdAt": "2025-04-09T22:53:25.121Z", "name": { "givenName": "DENVIL", "familyName": "RODRIGUEZ", "title": "", "suffix": "", "middleName": "" }, "billingAddress": { "streetAddress": "3101 N CRYSTAL SPRINGS RD", "extendedAddress": "", "postalCode": "32837", "region": "WI", "locality": "JANESVILLE", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "7659628365", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": { "numberHash": "", "countryCodeAlpha3": "USA" } }, "paymentCards": null, "cardProductApplications": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA0LTA5VDIyJTNBNTMlM0EyOC4yMjgwMDAwMDBaJmk9YXBfMDZkMTIzMWQxYTFjNDNkZGEwNWMxNDE1NGRmMGFjZDY", "endCursor": "dD0yMDI1LTA0LTA5VDIyJTNBNTMlM0EyOC4yMjgwMDAwMDBaJmk9YXBfMDZkMTIzMWQxYTFjNDNkZGEwNWMxNDE1NGRmMGFjZDY" }, "edges": [ { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "appStatus": { "status": "DENIED" } } } ] }, "applications": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA0LTA5VDIyJTNBNTMlM0EyOC4yMjgwMDAwMDBaJmk9YXBfMDZkMTIzMWQxYTFjNDNkZGEwNWMxNDE1NGRmMGFjZDY", "endCursor": "dD0yMDI1LTA0LTA5VDIyJTNBNTMlM0EyOC4yMjgwMDAwMDBaJmk9YXBfMDZkMTIzMWQxYTFjNDNkZGEwNWMxNDE1NGRmMGFjZDY" }, "edges": [ { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "appState": { "status": "DENIED" } } } ] } } } ] } }, "extensions": { "requestId": "09a9625a-cf23-925e-a0da-ea6d9191b461", "rateLimit": { "cost": 144, "limit": 60060, "remaining": 59916, "asOf": "2025-04-17T06:11:53.394Z", "complexity": { "limit": 60060, "remaining": 59916, "cost": 144 }, "count": { "limit": 60060, "remaining": 60059, "cost": 1 } } } } ### GraphQL: GetAuthorizedUserFinancialAccountByPersonAccountHolder Query: query GetAuthorizedUserFinancialAccountByPersonAccountHolder( $id: ID! $first: Int $after: String ) { node(id: $id) { __typename ... on USPersonAccountHolder { id authorizedUserFinancialAccounts(first: $first, after: $after) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id name createdAt accountStatus cardProduct { id } ledgers { id name normalBalance creditBalance { value currencyCode decimalPlaces } debitBalance { value currencyCode decimalPlaces } } features { __typename enabled createdAt updatedAt ... on AuthorizedUserAccountFeature { primaryAccountHolderAccount { id } } } } } } } } } Variables: { "id": "", "first": 1 } Expected Result: { "data": { "node": { "__typename": "USPersonAccountHolder", "id": "", "authorizedUserFinancialAccounts": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA1LTA0VDAyJTNBMTElM0E0NC43NjYwMDAwMDBaJmk9YWNfYzAyMmEwMDcwNmI5M2ViNjRkYjNiOGI5OWQwOTFjYzJiNTk3", "endCursor": "dD0yMDI1LTA1LTA0VDAyJTNBMTElM0E0NC43NDIwMDAwMDBaJmk9YWNfYzAyMjI0YTY2YjBlYTMzNDRlM2RiOGM3MDRmMGI4ZTY4NTY2" }, "edges": [ { "cursor": "dD0yMDI1LTA1LTA0VDAyJTNBMTElM0E0NC43NjYwMDAwMDBaJmk9YWNfYzAyMmEwMDcwNmI5M2ViNjRkYjNiOGI5OWQwOTFjYzJiNTk3", "node": { "__typename": "FinancialAccount", "id": "", "name": "Authorized User Person", "createdAt": "2025-05-04T02:11:44.745Z", "updatedAt": "2025-05-04T02:11:44.745Z", "externalId": "T3RU5YLRUL", "accountAttributes": [], "accountStatus": "ACTIVE", "features": [ { "__typename": "DirectDepositFinancialAccountFeature", "enabled": true, "createdAt": "2025-05-04T02:11:44.688Z", "updatedAt": "2025-05-04T02:11:44.688Z", "effectiveFrom": "2025-05-04T02:11:44.688Z", "effectiveThrough": null }, { "__typename": "PrePaidPaymentCardFinancialAccountFeature", "enabled": true, "createdAt": "2025-05-04T02:11:44.688Z", "updatedAt": "2025-05-04T02:11:44.688Z", "effectiveFrom": "2025-05-04T02:11:44.688Z", "effectiveThrough": null }, { "__typename": "AuthorizedUserAccountFeature", "enabled": true, "createdAt": "2025-05-04T02:11:44.688Z", "updatedAt": "2025-05-04T02:11:44.688Z", "effectiveFrom": "2025-05-04T02:11:44.688Z", "effectiveThrough": null, "primaryAccountHolderAccount": { "id": "" }, "primaryAccountAccountHolderParty": { "id": "" } } ], "paymentCards": { "edges": [ { "node": { "id": "", "status": "ACTIVE", "last4": "1250" } } ] }, "ledgers": [ { "id": "ac_c022a00706b93eb64db3b8b99d091cc2b597_a001", "name": "AVAILABLE_CASH", "normalBalance": "CREDIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c022a00706b93eb64db3b8b99d091cc2b597_a031", "name": "CREDIT_OUTSTANDING", "normalBalance": "DEBIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c022a00706b93eb64db3b8b99d091cc2b597_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c022a00706b93eb64db3b8b99d091cc2b597_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } ] } }, { "cursor": "dD0yMDI1LTA1LTA0VDAyJTNBMTElM0E0NC43NDIwMDAwMDBaJmk9YWNfYzAyMjI0YTY2YjBlYTMzNDRlM2RiOGM3MDRmMGI4ZTY4NTY2", "node": { "__typename": "FinancialAccount", "id": "", "name": "Authorized User Person", "createdAt": "2025-05-04T02:11:44.717Z", "updatedAt": "2025-05-04T02:11:44.717Z", "externalId": "CH9SYVFR5M", "accountAttributes": [], "accountStatus": "ACTIVE", "features": [ { "__typename": "DirectDepositFinancialAccountFeature", "enabled": true, "createdAt": "2025-05-04T02:11:44.694Z", "updatedAt": "2025-05-04T02:11:44.694Z", "effectiveFrom": "2025-05-04T02:11:44.694Z", "effectiveThrough": null }, { "__typename": "PrePaidPaymentCardFinancialAccountFeature", "enabled": true, "createdAt": "2025-05-04T02:11:44.694Z", "updatedAt": "2025-05-04T02:11:44.694Z", "effectiveFrom": "2025-05-04T02:11:44.694Z", "effectiveThrough": null }, { "__typename": "AuthorizedUserAccountFeature", "enabled": true, "createdAt": "2025-05-04T02:11:44.694Z", "updatedAt": "2025-05-04T02:11:44.694Z", "effectiveFrom": "2025-05-04T02:11:44.694Z", "effectiveThrough": null, "primaryAccountHolderAccount": { "id": "" }, "primaryAccountAccountHolderParty": { "id": "" } } ], "paymentCards": { "edges": [ { "node": { "id": "", "status": "ACTIVE", "last4": "6328" } }, { "node": { "id": "", "status": "ACTIVE", "last4": "9561" } } ] }, "ledgers": [ { "id": "ac_c02224a66b0ea3344e3db8c704f0b8e68566_a031", "name": "CREDIT_OUTSTANDING", "normalBalance": "DEBIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c02224a66b0ea3344e3db8c704f0b8e68566_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c02224a66b0ea3344e3db8c704f0b8e68566_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c02224a66b0ea3344e3db8c704f0b8e68566_a001", "name": "AVAILABLE_CASH", "normalBalance": "CREDIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } ] } } ] } } }, "extensions": { "requestId": "946fa84c-2baa-9163-bccf-e3a61efa229d", "rateLimit": { "cost": 563 } }, "headers": {}, "status": 200 } ### GraphQL: GetAuthorizedUserFinancialAccountByFinancialAccount Query: query GetAuthorizedUserFinancialAccountByFinancialAccount( $id: ID! $first: Int $after: String ) { node(id: $id) { __typename ... on FinancialAccount { id authorizedUserFinancialAccounts(first: $first, after: $after) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename ...FinancialAccount features { __typename enabled createdAt updatedAt effectiveFrom effectiveThrough ... on AuthorizedUserAccountFeature { primaryAccountHolderAccount { id } primaryAccountAccountHolderParty { ... on Node { id } ... on USPersonAccountHolder { id } } } } paymentCards { edges { node { id status last4 } } } ledgers { id name normalBalance creditBalance { __typename value currencyCode decimalPlaces } debitBalance { __typename value currencyCode decimalPlaces } } } } } } } } fragment FinancialAccount on FinancialAccount { id name createdAt updatedAt externalId accountAttributes accountStatus } Variables: { "id": "", "first": 1 } Expected Result: { "__typename": "FinancialAccount", "id": "", "authorizedUserFinancialAccounts": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yMDI1LTA1LTA3VDAxJTNBMTklM0EwMy45NjUwMDAwMDBaJmk9YWNfYzAyMjhlM2RhNmE2ZTQ5NzQ1N2M4N2M2NWY3NGQ5ODE2MDQ3", "endCursor": "dD0yMDI1LTA1LTA3VDAxJTNBMTglM0E1OC40MzUwMDAwMDBaJmk9YWNfYzAyMjgxNmVjZjkwNWE5YjQyN2ViYzg2NDcyZGVlYTkyNDRk" }, "edges": [ { "cursor": "dD0yMDI1LTA1LTA3VDAxJTNBMTklM0EwMy45NjUwMDAwMDBaJmk9YWNfYzAyMjhlM2RhNmE2ZTQ5NzQ1N2M4N2M2NWY3NGQ5ODE2MDQ3", "node": { "__typename": "FinancialAccount", "id": "", "name": "Authorized User Person", "createdAt": "2025-05-07T01:19:03.939Z", "updatedAt": "2025-05-07T01:19:03.939Z", "externalId": "7BQ6MPS3M4", "accountAttributes": [], "accountStatus": "ACTIVE", "features": [ { "__typename": "DirectDepositFinancialAccountFeature", "enabled": true, "createdAt": "2025-05-07T01:19:03.907Z", "updatedAt": "2025-05-07T01:19:03.907Z", "effectiveFrom": "2025-05-07T01:19:03.907Z", "effectiveThrough": null }, { "__typename": "PrePaidPaymentCardFinancialAccountFeature", "enabled": true, "createdAt": "2025-05-07T01:19:03.907Z", "updatedAt": "2025-05-07T01:19:03.907Z", "effectiveFrom": "2025-05-07T01:19:03.907Z", "effectiveThrough": null }, { "__typename": "AuthorizedUserAccountFeature", "enabled": true, "createdAt": "2025-05-07T01:19:03.907Z", "updatedAt": "2025-05-07T01:19:03.907Z", "effectiveFrom": "2025-05-07T01:19:03.907Z", "effectiveThrough": null, "primaryAccountHolderAccount": { "id": "" }, "primaryAccountAccountHolderParty": { "id": "" } } ], "paymentCards": { "edges": [ { "node": { "id": "", "status": "ACTIVE", "last4": "3714" } }, { "node": { "id": "", "status": "ACTIVE", "last4": "2908" } } ] }, "ledgers": [ { "id": "ac_c0228e3da6a6e497457c87c65f74d9816047_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c0228e3da6a6e497457c87c65f74d9816047_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c0228e3da6a6e497457c87c65f74d9816047_a031", "name": "CREDIT_OUTSTANDING", "normalBalance": "DEBIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, { "id": "ac_c0228e3da6a6e497457c87c65f74d9816047_a001", "name": "AVAILABLE_CASH", "normalBalance": "CREDIT", "creditBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "debitBalance": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } ] } } ] } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/close-an-account Title: Close an Account Section: Issuing Description: Close a financial account in the Test environment or contact Highnote to close one in Live. Resolve closure blockers and simulate closures to test status changes. ## Overview Closing a financial account permanently ends an account holder's access to the account and to any payment cards attached to it. Before launching your card product, Highnote works with your team to establish steps for account closure that are specific to your card product and servicing responsibilities. Where you can close an account depends on the surface and the environment: | Surface | Test environment | Live environment | | :----------------- | :----------------------------------------------------- | :----------------------------------- | | Highnote Dashboard | An admin in your organization can close an account | Not available—contact Highnote | | Highnote API | Simulated account closure | Not available | The account closure flow is outlined in the following graphic: ### Live environment In the Live environment, a typical account closure process takes place as follows: 1. Your team contacts Highnote to request the closure. Highnote records who requested it: your team, the account holder, the Partner Bank, or Highnote. 2. The financial account status transitions to . 3. During the status, (a) any closure blockers on the account are resolved, and (b) authorizations are blocked on any associated payment cards. 4. The financial account status is updated to . ### Test environment In the Test environment, your team can close an account from the Highnote Dashboard as follows: 1. **Initiate Closure** to move the account to . 2. Resolve any closure blockers on the account. 3. **Close Account** to move the account to . Your team initiates each status transition and resolves any closure blockers, not Highnote. In Test, the Dashboard offers closure only on account holder financial accounts, not on product-level accounts such as those that fund your card product or hold reserves. Simulated closures move a Test financial account through the same statuses as a real closure, but they don't check closure blockers, and consent is supplied automatically rather than captured from the account holder. ## Blockers and restrictions {#account-closure-restrictions} Two things need resolving before an account closes: blockers, which Highnote validates, and items your team settles directly with the account holder. ### Closure blockers Account closure blockers are conditions on the account that must be resolved before the account can close. Blockers are evaluated at both the initiation and finalization stage, but they only prevent finalization. That is: - an account _can_ move to with blockers present - an account _cannot_ move to with blockers present. In the Dashboard Test environment, **required ledger balances must be $0** or your team cannot close the account. Common blockers include the following: | Blocker | How to resolve | | :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- | | | All cards associated with the account must have status or | | | Wait for pending authorizations on the account to clear or expire | | | Wait for in-progress transfers to reach a terminal state, e.g., , | | | Cancel scheduled one-time and recurring transfers on the account | |
| Required ledger balances on the account must be $0 | | | Contact Highnote to close a line of credit | | | Contact Highnote to resolve a risk hold on a transfer associated with the account | | | Each authorized user account on the account must have status | ### Funds owed Rewards may be forfeited when a financial account is closed for a card product with a rewards program. Any unclaimed rewards should be communicated to the account holder by your support team. Funds owed to the account holder are returned before the account closes — an outstanding balance is a closure blocker. Unclaimed rewards don't block closure, but they should be resolved with the account holder before the account is closed. For example, if an account holder has funds in their financial account and unclaimed rewards, the funds are returned to the account holder and the rewards are forfeited. ## Notify the account holder Some card products may require notifying an account holder by regulation. Contact support@highnote.com to inquire whether your card product requires account holder notification. When closing a financial account, we recommend notifying the account holder of any related account closure events. Subscribe to the following notification events to notify account holders of account closure events: | Notification event | Description | Reference | | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- | | | Notifies you when an account is pending closure, e.g., after your team initiates an account closure from the Dashboard. | Financial account status | | | Notifies you when an account has been closed. You can send a confirmation message to the account holder to inform them of their financial account’s change in status. | Financial account status | | | Notifies you when an ACH withdrawal of funds owed to your account holder is initiated prior to account closure. Related ACH funds withdrawal events track the transfer through processing. | ACH funds out | ## Simulate account closure Simulations run only in the Test environment and don't affect real accounts. Highnote's account closure simulation lets you test the following: - Initiating an account closure - Fully closing an account --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/financial-account-revisions Title: Financial Account Revisions Section: Issuing Description: Query the chronological history of changes to a financial account for auditing, fraud detection, and regulatory compliance. ## Overview The object reveals financial account history, which provides a detailed chronological log of updates and activities. This log captures key changes across various financial account fields, ensuring that you, your team, and account holders can troubleshoot and audit changes precisely. By maintaining a history of updates to critical fields, the API supports enhanced transparency, security, and operational efficiency. ## Use cases Highnote’s Financial Account History feature supports the following use cases: - **Fraud Detection and Prevention:** By monitoring updates to account status and owner information, you can quickly identify and respond to suspicious activities. - **Regulatory Compliance and Reporting:** Detailed logs support compliance with financial regulations by providing auditable records of all account activities and changes. - **Customer Support and Account Management:** Access to a comprehensive history of account updates and activities enables customer service representatives to efficiently resolve inquiries and issues, offering a superior customer experience. - **Financial Analysis and Product Development:** Analysis of account activity and feature utilization can inform product improvements, tailored financial services, and targeted marketing strategies. ## Find financial account revisions Use the following query to find financial account history: ### GraphQL: FindFinancialAccountRevisionSnapshot Query: query FindFinancialAccountRevisionSnapshot( $id: ID! $first: Int $after: String ) { node(id: $id) { ... on FinancialAccount { id revisionSnapshots(first: $first, after: $after) { edges { cursor node { __typename ... on FinancialAccountSnapshot { id financialAccountAttributes accountStatus cardProduct { id name } externalId name application { id applicationState { status } } updatedAt } } } } } } } Variables: { "id": "", "first": 10, "after": "" } Expected Result: { "data": { "node": { "id": "", "revisionSnapshots": { "edges": [ { "node": { "__typename": "FinancialAccountSnapshot", "id": "", "financialAccountAttributes": [ "DELINQUENT" ], "accountStatus": "ACTIVE", "cardProduct": { "id": "", "name": "consumer-credit_7-25-24", "__typename": "CardProduct" }, "externalId": "4PBJLKYYHD", "name": "fin acct cc_7-25-24, number 2", "application": { "id": "", "applicationState": null, "__typename": "AccountHolderCardProductApplication" }, "updatedAt": "2024-08-14T23:06:30.918Z" }, "__typename": "FinancialAccountSnapshotEdge" } ], "__typename": "FinancialAccountSnapshotConnection" } } }, "extensions": { "requestId": "0d2e1aab-d324-981c-a705-50826c5541d5", "rateLimit": { "cost": 83, "limit": 60060, "remaining": 59977 } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/onboard-an-account Title: Onboard an Account Section: Issuing Description: Onboard US Business and US Person account holders, open card product applications, and issue financial accounts with KYC, KYB, and OFAC verification. ## Overview Onboarding an account is the process of associating an account holder with a card product: 1. **Create an account holder**, business or consumer. 2. **Open a card product application** to associate an account holder with a card product. 3. **Issue a financial account**. Highnote creates card products on your behalf in the Live environment. You can create a card product yourself in the Test environment -- with these API snippets, or in the Dashboard. After onboarding an account holder, you are finally ready to issue a payment card. ## Account holder types There are two types of card products, each with a dedicated account holder type: - **Commercial** card products: Used by **US Business** account holders - **Consumer** card products: Used by **US Person** account holders For more information on each vertical, see the Quick Start Templates. ## Prerequisites 1. A Highnote account 2. Access to the Highnote API, API Explorer, or Dashboard 3. A card product. ## Create your card product Creating a card product is a prerequisite to onboarding account holders. In Prod Live, Highnote does this first step for you. In the Test environment, you can practice creating card products and configuring them to fit the needs of your customers. There are several types of card product verticals you can offer to your customers. Replace the and input variables with your card product's corresponding values. ## Simulate External Wire Transfer This mutation simulates an external wire transfer to a balance. ## Onboard an account holder Once your card product is created, you can begin onboarding an account by creating an account holder -- a business account holder for commercial products, or a person account holder for consumer products. Account holders are objects that can open applications for card products and receive financial accounts that have been issued to them. To onboard an account holder in the Dashboard, see Account holder basics. ### Onboard a US business account holder A is an account holder that uses a commercial card product. There are several different components that make up a US business account holder's details: - **Business details**: Includes business name, identification number (EIN), business type, business phone, physical address, legal entity address, business description, and website - **Primary authorized person**: Person authorized to act on behalf of the business; if a primary authorized person owns or controls at least 25% of the business, they are also automatically added as a beneficial owner - **Beneficial owners**: Person who owns or controls at least 25% of the business You can use the following mutation to create a : ### Onboard a US person account holder A is an account holder that uses a consumer card product. This type of account holder has account details that include the account holder's name, address, contact information, date of birth, and social security number (SSN). You can use the following mutation to create a : ### Required fields When creating an account holder onboarding form or experience for your app or website, there are several required fields an account holder must complete. These required fields are essential for running identity checks and ensuring the account holder qualifies for your card product. For a list of required fields for account holders, review the **Create Account Holder** section of the Design Your Card Experience guide. ## Validate addresses Highnote recommends validating physical addresses before using them when onboarding account holders. Address validation uses a CASS-certified service to ensure each address is properly formatted and deliverable, which reduces later KYC friction and delivery problems for issued cards or checks. The mutation returns a . Pass the token's ID as the corresponding field on an onboarding input in place of the raw address. ### Supported address token fields | Input | Nested location | Token field | | :------------------------------- | :------------------------------------------------- | :-------------------- | | | | | | | | | | | | | | | | | | | | | You must provide exactly one address field or its token counterpart for each input. The API rejects requests that set both. ### Token scope The mutation accepts an optional argument that controls how many times the returned token can be consumed: | Scope | Behavior | | :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | _(default)_ | The token can be consumed exactly once. Use this when a validated address maps to a single input path. | | | The token can be consumed multiple times. Use this when the same validated address needs to land on more than one input path in the same request — for example, reusing a home address for both the primary authorized person and an ultimate beneficial owner, or reusing the same billing address across UBOs. | Each response includes an timestamp indicating when the token is no longer valid. ### Validate an address Call with the address you want to validate. The mutation returns an whose outcome indicates whether the address is valid, valid with changes, incomplete, or invalid. For the full response-type reference and simulation examples, see Validate shipping address. Once you have a token ID from a valid or valid-with-changes outcome, pass it as the field on the onboarding input path listed in the table above. ## Open an application With an account holder created, you can open an application for your card product. When an application is opened, you must present your compliance agreements and record the timestamp the account holder consents to the agreements. Once an application is submitted, it is reviewed by the Highnote team in an asynchronous process. We recommend displaying a view for the account holder that lets them know their application is being reviewed. This process is outlined in the following graphic: During the review process, Highnote runs the following verification checks: - Know Your Customer (KYC) - Know Your Business (KYB) - Office of Foreign Assets Control (OFAC) screening - First and third-party fraud risk You can use the following mutation to create an account holder application for a card product. For this example mutation, include the following IDs as input variables: - - - _Required only for business account holders_ - These IDs are in the Onboard an Account Holder mutation response or can be found on the account holder page of the dashboard. ## Check application status The following graphic displays the application status lifecycle, from opening an application to decisioning: After an application is submitted, the returned displays one of the following statuses: | Status | Description | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | PENDING | The application has been received, and the system is running automated verifications. | | IN_REVIEW | Sometimes, an application may be flagged for manual review because fraud is suspected or the information provided appears incorrect. This status indicates that a Highnote agent is reviewing the application to determine a decision or if additional information is required from the account holder. | | DENIED | The application has failed one or more card product policies. A payment card cannot be issued to this account holder. Customer notification of the denial and denial reason may be required. | | APPROVED | The application has been approved. You may now issue a financial account for the account holder. | You can monitor an open application's status using the created in the response to the open application query. Use the following query to check the application status: ### View application workflows An application advances through a sequence of workflows (such as identity verification, business rule validation, credit underwriting) before reaching a terminal . Query the field on the application to see each workflow's , , and . For the available statuses and workflow types, see [](/docs/api-reference/object#ProductApplicationWorkflow). ## Add account notes After issuing a financial account, you can use the following mutation to allow your agents to add notes to a financial account. Adding notes is useful for various internal servicing needs: ### Find account notes by account holder Use the following query to find the notes recorded for an account holder. A note appears when it's created with the account holder as its aggregate entity, as in the createGlobalNote mutation above. This example queries a person account holder. For a business account holder, query the same field on [](/docs/api-reference/object#USBusinessAccountHolder). ## Provision an account holder Provisioning an account holder lets you bundle multiple actions in a single call: 1. Open an application once the account holder is created. 2. Issue a financial account once the application is approved. 3. Issue a payment card once the financial account is created. Using the mutation reduces your implementation and development effort of orchestrating API calls. The workflow systemically orchestrates the next call to action once the previous action is successfully completed. The inputs to the actions of , , and must all be provided to provision the business or person account holder. ## Check provisioning status Use the following query to lookup the overall status of account holder provisioning as well as the status of the individual actions: ## Next steps: Issue cards After onboarding an account, you can issue a card to the account holder. This process involves the following steps: 1. Issue a financial account to the account holder 2. Issue a virtual card 3. _Optional_ Issue a physical card 4. Activate the card 5. _Optional_ Set a PIN ### GraphQL: 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": "My Test Product", "usage": "VERTICAL_USAGE", "vertical": "" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "", "name": "My Test Product", "usage": "MULTI_USE" } }, "extensions": { "requestId": "" } } ### GraphQL: CreateUSBusinessAccountHolder Query: mutation CreateUSBusinessAccountHolder( $input: CreateUSBusinessAccountHolderInput! ) { createUSBusinessAccountHolder(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on USBusinessAccountHolder { externalId id createdAt updatedAt primaryAuthorizedPerson { id email dateOfBirth percentageOwnership authorizingPersonTitle createdAt updatedAt name { givenName familyName title suffix middleName } homeAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } identificationDocument { socialSecurityNumber { numberHash countryCodeAlpha3 } } } businessProfile { id website businessType createdAt updatedAt name { legalBusinessName doingBusinessAsName } businessDescription billingAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } legalAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } identificationDocument { employerIdentificationNumber { numberHash countryCodeAlpha3 } } ultimateBeneficialOwners { id percentageOwnership dateOfBirth email createdAt updatedAt name { givenName familyName title suffix middleName } homeAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } identificationDocument { socialSecurityNumber { numberHash countryCodeAlpha3 } } } } } } } Variables: { "input": { "primaryAuthorizedPerson": { "name": { "givenName": "Bill", "familyName": "Someone" }, "email": "foo@example.com", "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "homeAddress": { "streetAddress": "123 Main Street", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-11-1111", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "1980-09-01", "percentageOwnership": 25, "authorizingPersonTitle": "PRESIDENT" }, "businessProfile": { "name": { "legalBusinessName": "Foo Inc.", "doingBusinessAsName": "Foo Inc." }, "businessDescription": "A small retail shop.", "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "billingAddress": { "streetAddress": "123 Main Street", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "legalAddress": { "streetAddress": "123 Main Street", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "identificationDocument": { "employerIdentificationNumber": { "number": "12-3456789", "countryCodeAlpha3": "USA" } }, "website": "https://www.foowebsite.com", "businessType": "PARTNERSHIP", "creditRiskAttributes": { "annualRevenue": { "value": "500000", "currencyCode": "USD" } }, "ultimateBeneficialOwners": [ { "email": "foobo@example.com", "name": { "givenName": "Scott", "familyName": "Someone" }, "homeAddress": { "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" } }, "dateOfBirth": "1980-09-01", "percentageOwnership": 75 } ] }, "externalId": "user-id-in-your-system" } } Expected Result: { "data": { "createUSBusinessAccountHolder": { "__typename": "USBusinessAccountHolder", "externalId": "user-id-in-your-system", "id": "", "createdAt": "2024-11-20T22:25:21.561Z", "updatedAt": "2024-11-20T22:25:21.596Z", "primaryAuthorizedPerson": { "id": "", "email": "foo@example.com", "dateOfBirth": "1980-09-01", "percentageOwnership": 25, "authorizingPersonTitle": "PRESIDENT", "createdAt": "2024-11-20T22:25:21.562Z", "updatedAt": "2024-11-20T22:25:21.597Z", "name": { "givenName": "Bill", "familyName": "Someone", "title": "", "suffix": "", "middleName": "" }, "homeAddress": { "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" } } }, "businessProfile": { "id": "", "website": "https://www.foowebsite.com", "businessType": "PARTNERSHIP", "createdAt": "2024-11-20T22:25:21.561Z", "updatedAt": "2024-11-20T22:25:21.596Z", "name": { "legalBusinessName": "Foo Inc.", "doingBusinessAsName": "Foo Inc." }, "businessDescription": "A small retail shop.", "billingAddress": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "60654", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" }, "legalAddress": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "60654", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "5555555555", "label": "MOBILE" } ], "identificationDocument": { "employerIdentificationNumber": { "numberHash": "AQAAAAP-DCG8rUeazMDEAOX1QWMGpxrCbhBcc9eIL7-RvRiTXA", "countryCodeAlpha3": "USA" } }, "ultimateBeneficialOwners": [ { "id": "", "percentageOwnership": 75, "dateOfBirth": "1980-09-01", "email": "foobo@example.com", "createdAt": "2024-11-20T22:25:21.562Z", "updatedAt": "2024-11-20T22:25:21.597Z", "name": { "givenName": "Scott", "familyName": "Someone", "title": "", "suffix": "", "middleName": "" }, "homeAddress": { "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" } } } ] } } }, "extensions": { "requestId": "13d1c450-dac5-9d9f-814b-21978441ed1f", "rateLimit": { "cost": 29, "limit": 60060, "remaining": 60031 } } } ### GraphQL: 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": "" } } } Expected Result: { "data": { "createUSPersonAccountHolder": { "__typename": "USPersonAccountHolder", "id": "", "email": "gerrytest1@abc.com", "dateOfBirth": "1980-09-01", "externalId": "", "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": "" } } ### GraphQL: ValidateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { __typename ... on AddressValidatedWithChangesResult { token { id } } ... on AddressValidatedResult { token { id } } } } } } Variables: { "input": { "idempotencyKey": "idempotency-key", "address": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "postalCode": "94107-2134", "region": "CA", "locality": "SAN FRANCISCO", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressValidatedResult", "token": { "id": "tkvad_1" } } } } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "createdAt": "2021-07-07T23:22:30.475Z", "updatedAt": "2021-07-07T23:22:30.475Z" } }, "extensions": { "requestId": "" } } ### GraphQL: LookupApplication Query: query LookupApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { __typename applicationState { status } applicationWorkflows { executionOrder status workflowType } decisionedAt expiresAt accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { __typename currentVerification { status reason results { code description } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "AccountHolderCardProductApplication", "applicationState": { "status": "APPROVED" }, "applicationWorkflows": [ { "executionOrder": 0, "status": "COMPLETED", "workflowType": "IDENTITY" }, { "executionOrder": 1, "status": "COMPLETED", "workflowType": "BUSINESS_RULE_VALIDATION" }, { "executionOrder": 2, "status": "COMPLETED", "workflowType": "CREDIT_UNDERWRITING" } ], "accountHolderSnapshot": { "__typename": "USPersonAccountHolderSnapshot", "decisionedAt": "2024-10-25T18:53:48.968Z", "expiresAt": "2024-10-25T18:53:48.968Z", "currentVerification": { "status": "PASSED", "reason": "PASSED", "results": [ { "code": "ADDRESS_MATCH", "description": "The account holder's address was able to be verified." } ] } } } }, "extensions": { "requestId": "" } } ### GraphQL: CreateGlobalNote Query: mutation createGlobalNote($input: CreateGlobalNoteInput!) { createGlobalNote(input: $input) { __typename ... on GlobalNote { id createdBy { id } message createdAt primaryEntity { __typename ... on Node { id } ... on FinancialAccount { id externalId } } aggregateEntity { __typename ... on USBusinessAccountHolder { id externalId } ... on USPersonAccountHolder { id externalId } } } ... on AccessDeniedError { message } ... on UserError { errors { __typename errorPath code description } } } } Variables: { "input": { "message": "This is a note!", "primaryEntity": { "primaryEntityId": "", "primaryEntityType": "FINANCIAL_ACCOUNT" }, "aggregateEntity": { "aggregateEntityId": "", "aggregateEntityType": "ACCOUNT_HOLDER" } } } Expected Result: { "data": { "createGlobalNote": { "__typename": "GlobalNote", "id": "", "createdBy": { "id": "" }, "message": "This is a high note!", "createdAt": "2024-06-28T18:13:26.620Z", "primaryEntity": { "__typename": "FinancialAccount", "id": "", "externalId": "2KRBVWEJY4" }, "aggregateEntity": { "__typename": "USPersonAccountHolder", "id": "", "externalId": "some-id" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60047 } } } ### GraphQL: GetPersonAccountHolder Query: query getPersonAccountHolder($id: ID!) { node(id: $id) { ... on USPersonAccountHolder { id globalNotes { ... on GlobalNoteConnection { pageInfo { hasNextPage hasPreviousPage } edges { node { message } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "ACCOUNT_HOLDER", "globalNotes": { "pageInfo": { "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "node": { "message": "This is a note!" } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 23, "limit": 60060, "remaining": 60037 } } } ### GraphQL: ProvisionAccountHolder Query: mutation provisionAccountHolder($input: ProvisionAccountHolderInput!) { provisionAccountHolder(input: $input) { __typename ... on AccountHolderProvisioning { id idempotencyKey createdAt updatedAt outcome { status } accountHolder { ... on Node { id } ... on USBusinessAccountHolder { id businessProfile { name { legalBusinessName } } } } currentAction { id action } nextAction { id action } workflowActions { id action actionInput { createAccountHolderCardProductApplicationInput { cardHolderAgreementConsent { consentTimestamp primaryAuthorizedPerson { ... on Node { id } ... on USBusinessAuthorizedPerson { name { familyName } id } ... on USPersonAuthorizedUser { id name { familyName } } } } } issueFinancialAccountForApplicationInput { name } issuePaymentCardForFinancialAccountInput { options { activateOnCreate cardProfileSet { id description } expirationDate } } } outcome { status } executionOrder node { ... on Node { id } ... on UserError { errors { errorPath code description } } ... on AccountHolderCardProductApplication { id applicationState { status } } ... on FinancialAccount { id name } ... on PaymentCard { id status } } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "idempotencyKey": "IDEMPOTENCY-KEY", "accountHolderId": "", "actions": [ "CREATE_APPLICATION", "ISSUE_FINANCIAL_ACCOUNT", "ISSUE_PAYMENT_CARD" ], "actionInput": { "createAccountHolderCardProductApplicationInput": { "cardProductId": "", "cardHolderAgreementConsent": { "consentTimestamp": "2024-11-12T16:20:15.657Z", "primaryAuthorizedPersonId": "" } }, "issueFinancialAccountForApplicationInput": { "name": "Fianancial Account Name" }, "issuePaymentCardForFinancialAccountInput": { "options": { "activateOnCreate": true, "expirationDate": "2026-01-01T23:59:59Z" } } } } } Expected Result: { "data": { "provisionAccountHolder": { "__typename": "AccountHolderProvisioning", "id": "", "idempotencyKey": "IDEMPOTENCY-KEY", "createdAt": "2024-11-12T13:47:53.359Z", "updatedAt": "2024-11-12T13:47:53.359Z", "outcome": { "status": "INITIATED" }, "accountHolder": { "id": "", "businessProfile": { "name": { "legalBusinessName": "BlueJay" } } }, "currentAction": null, "nextAction": null, "workflowActions": [ { "id": "", "action": "CREATE_APPLICATION", "actionInput": { "createAccountHolderCardProductApplicationInput": { "cardHolderAgreementConsent": { "consentTimestamp": "2024-11-12T13:47:53.206Z", "primaryAuthorizedPerson": { "name": { "familyName": "Smith" }, "id": "" } } } }, "outcome": { "status": "INITIATED" }, "executionOrder": 1, "node": null }, { "id": "", "action": "ISSUE_FINANCIAL_ACCOUNT", "actionInput": { "createAccountHolderCardProductApplicationInput": null, "issueFinancialAccountForApplicationInput": { "name": "Fianancial Account Name" } }, "outcome": { "status": "INITIATED" }, "executionOrder": 2, "node": null }, { "id": "", "action": "ISSUE_PAYMENT_CARD", "actionInput": { "createAccountHolderCardProductApplicationInput": null, "issueFinancialAccountForApplicationInput": null, "issuePaymentCardForFinancialAccountInput": { "options": { "activateOnCreate": true, "cardProfileSet": null, "expirationDate": "2026-01-01T23:59:59Z" } }, "initiateFinancialAccountCreditLimitUpdateFromProductFundingInput": null }, "outcome": { "status": "INITIATED" }, "executionOrder": 3, "node": null } ] } }, "extensions": { "requestId": "069a472a-aba1-9d1c-8198-87dba121b902", "rateLimit": { "cost": 31 } } } ### GraphQL: accountHolderProvisioning Query: query accountHolderProvisioning($id: ID!) { node(id: $id) { ... on AccountHolderProvisioning { id idempotencyKey createdAt updatedAt outcome { status } accountHolder { __typename ... on Node { id } ... on USBusinessAccountHolder { id businessProfile { name { legalBusinessName } } } } currentAction { id action } nextAction { id action } workflowActions { id action actionInput { createAccountHolderCardProductApplicationInput { cardHolderAgreementConsent { consentTimestamp primaryAuthorizedPerson { __typename ... on Node { id } ... on USPersonAuthorizedUser { id name { familyName } } ... on USBusinessAuthorizedPerson { name { familyName } id } } } } issueFinancialAccountForApplicationInput { name } issuePaymentCardForFinancialAccountInput { options { activateOnCreate cardProfileSet { id description } expirationDate } } } outcome { status } executionOrder node { __typename ... on Node { id } ... on UserError { errors { errorPath code description } } ... on AccountHolderCardProductApplication { id createdAt updatedAt applicationState { status } accountHolderSnapshot { ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { __typename id } businessProfile { name { legalBusinessName } } } } } ... on FinancialAccount { id name externalId createdAt } ... on PaymentCard { id status } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "idempotencyKey": "9f5fb1c4-4239-4004-bbef-5986b1b46f50", "createdAt": "2024-11-12T13:47:53.359Z", "updatedAt": "2024-11-12T13:48:14.912Z", "outcome": { "status": "COMPLETED" }, "accountHolder": { "__typename": "USBusinessAccountHolder", "id": "", "businessProfile": { "name": { "legalBusinessName": "BlueJay" } } }, "currentAction": null, "nextAction": null, "workflowActions": [ { "id": "", "action": "CREATE_APPLICATION", "actionInput": { "createAccountHolderCardProductApplicationInput": { "cardHolderAgreementConsent": { "consentTimestamp": "2024-11-12T13:47:53.206Z", "primaryAuthorizedPerson": { "__typename": "USBusinessAuthorizedPerson", "name": { "familyName": "Smith" }, "id": "" } } } }, "outcome": { "status": "COMPLETED" }, "executionOrder": 1, "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "createdAt": "2024-11-12T13:47:54.240Z", "updatedAt": "2024-11-12T13:48:00.953Z", "applicationState": { "status": "APPROVED" }, "accountHolderSnapshot": { "accountHolderCurrent": { "__typename": "USBusinessAccountHolder", "id": "" }, "businessProfile": { "name": { "legalBusinessName": "BlueJay" } } } } }, { "id": "", "action": "ISSUE_FINANCIAL_ACCOUNT", "actionInput": { "createAccountHolderCardProductApplicationInput": null, "issueFinancialAccountForApplicationInput": { "name": "Fianancial Account Name" } }, "outcome": { "status": "COMPLETED" }, "executionOrder": 2, "node": { "__typename": "FinancialAccount", "id": "", "name": "Fianancial Account Name", "externalId": "2485287743", "createdAt": "2024-11-12T13:48:04.483Z" } }, { "id": "", "action": "ISSUE_PAYMENT_CARD", "actionInput": { "createAccountHolderCardProductApplicationInput": null, "issueFinancialAccountForApplicationInput": null, "issuePaymentCardForFinancialAccountInput": { "options": { "activateOnCreate": true, "cardProfileSet": null, "expirationDate": "2026-01-01T23:59:59Z" } }, "initiateFinancialAccountCreditLimitUpdateFromProductFundingInput": null }, "outcome": { "status": "COMPLETED" }, "executionOrder": 3, "node": { "__typename": "PaymentCard", "id": "", "status": "ACTIVE" } } ] } }, "extensions": { "requestId": "f776cf23-c4bf-9a98-ad59-af8174862aac", "rateLimit": { "cost": 26 } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/onboard-fleet Title: Onboard a Fleet Account Section: Issuing Description: Onboard a business account holder for fleet card programs using the direct API or tokenized flow, with optional fuel tax exemption. ## Overview Fleet card products are used by business account holders. This guide covers the fleet-specific onboarding process, including fuel tax exemption. For general onboarding concepts such as account holder types and application review, see Onboard an Account. ## Before you begin Before creating a business account holder, determine the following: - **Is this fleet fuel tax exempt?** If yes, you must include the attribute during account holder creation. This attribute cannot be added or updated after onboarding. - **Are you collecting data from a UI?** If yes, use the tokenized flow to keep PII off your servers. If you're calling the API from your backend, use the direct API flow. A US business account holder requires the following: - **Business details**: Business name, identification number (EIN), business type, phone, billing address, and website - **Primary authorized person**: Person authorized to act on behalf of the business. If they own or control at least 25% of the business, they are also added as a beneficial owner. - **Beneficial owners**: Any person who owns or controls at least 25% of the business ## Fuel tax exemption Be careful. The fuel tax exemption attribute must be set during account holder creation. It cannot be added or updated after onboarding. For non-exempt fleets, omit (which is optional). For fuel tax exempt fleets, pass in the input with: - set to - set to - date in format. When the fuel tax exemption is enabled, Highnote's platform tracks the Fleet's qualifying transactions to enable fuel tax reclamation reporting. ## Onboard with direct API flow Use to create the account holder directly from your server. The field is optional: ## Onboard with tokenized flow If you're collecting account holder data from a UI, use the tokenized flow to keep PII off your servers. ### Step 1. Generate a client token Generate a client token using . For more information on client tokens, see Client Tokens. ### Step 2. Tokenize the account holder data Tokenize the account holder data using . This mutation accepts the same as the direct flow, so can be included in the tokenized data. The token expires after 1 hour. ### Step 3. Create the account holder from the token Create the account holder using . This mutation only takes the token — no separate input is needed. ## Query fuel tax exemption status You can read back the fuel tax exemption status by querying the business account holder's : ## Next steps After creating a business account holder, continue with the Fleet Credit Template to open an application, issue a financial account, and configure your fleet card product. ### GraphQL: CreateUSBusinessAccountHolder Query: mutation CreateUSBusinessAccountHolder( $input: CreateUSBusinessAccountHolderInput! ) { createUSBusinessAccountHolder(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on USBusinessAccountHolder { id externalId createdAt updatedAt businessProfile { id name { legalBusinessName doingBusinessAsName } businessType operatingDetails { indicatorAttributes { type value reportedAt } } } } } } Variables: { "input": { "primaryAuthorizedPerson": { "name": { "givenName": "", "familyName": "" }, "dateOfBirth": "1980-01-01", "homeAddress": { "streetAddress": "123 Main St", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-11-1111", "countryCodeAlpha3": "USA" } } }, "businessProfile": { "name": { "legalBusinessName": "LEGAL_BUSINESS_NAME" }, "businessType": "LIMITED_LIABILITY_COMPANY", "billingAddress": { "streetAddress": "456 Commerce Blvd", "postalCode": "90210", "locality": "Los Angeles", "region": "CA", "countryCodeAlpha3": "USA" }, "identificationDocument": { "employerIdentificationNumber": { "number": "12-3456789", "countryCodeAlpha3": "USA" } }, "businessPlanAttributes": [ { "indicatorAttribute": { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } } ] } } } Expected Result: { "data": { "createUSBusinessAccountHolder": { "__typename": "USBusinessAccountHolder", "id": "", "externalId": null, "createdAt": "2026-03-26T18:00:00.000Z", "updatedAt": "2026-03-26T18:00:00.000Z", "businessProfile": { "id": "", "name": { "legalBusinessName": "LEGAL_BUSINESS_NAME", "doingBusinessAsName": null }, "businessType": "LIMITED_LIABILITY_COMPANY", "operatingDetails": { "indicatorAttributes": [ { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } ] } } } }, "extensions": { "requestId": "1ab32e1c-4949-9421-8240-c39ca4123jkl" } } ### GraphQL: GenerateTokenizeAccountHolderClientToken Query: mutation GenerateTokenizeAccountHolderClientToken { generateTokenizeAccountHolderClientToken { __typename ... on ClientToken { value expirationDate usage } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } Variables: {} Expected Result: { "data": { "generateTokenizeAccountHolderClientToken": { "__typename": "ClientToken", "value": "", "expirationDate": "2026-03-28T01:00:00.000Z", "usage": "UNTIL_EXPIRATION" } }, "extensions": { "requestId": "d47a92c3-5f18-4e6d-b902-3a8c1ef57b24" } } ### GraphQL: TokenizeUSBusinessAccountHolder Query: mutation TokenizeUSBusinessAccountHolder( $input: CreateUSBusinessAccountHolderInput! ) { tokenizeUSBusinessAccountHolder(input: $input) { __typename ... on USBusinessAccountHolderToken { token } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "primaryAuthorizedPerson": { "name": { "givenName": "", "familyName": "" }, "dateOfBirth": "1980-01-01", "homeAddress": { "streetAddress": "123 Main St", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-11-1111", "countryCodeAlpha3": "USA" } } }, "businessProfile": { "name": { "legalBusinessName": "LEGAL_BUSINESS_NAME" }, "businessType": "LIMITED_LIABILITY_COMPANY", "billingAddress": { "streetAddress": "456 Commerce Blvd", "postalCode": "90210", "locality": "Los Angeles", "region": "CA", "countryCodeAlpha3": "USA" }, "identificationDocument": { "employerIdentificationNumber": { "number": "12-3456789", "countryCodeAlpha3": "USA" } }, "businessPlanAttributes": [ { "indicatorAttribute": { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } } ] } } } Expected Result: { "data": { "tokenizeUSBusinessAccountHolder": { "__typename": "USBusinessAccountHolderToken", "token": "" } }, "extensions": { "requestId": "e6f103a8-2c49-4d7a-8b35-9d1fe4a26c81" } } ### GraphQL: CreateUSBusinessAccountHolderFromToken Query: mutation CreateUSBusinessAccountHolderFromToken( $input: CreateUSBusinessAccountHolderFromTokenInput! ) { createUSBusinessAccountHolderFromToken(input: $input) { __typename ... on USBusinessAccountHolder { id businessProfile { id name { legalBusinessName } operatingDetails { indicatorAttributes { type value reportedAt } } } } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "token": "" } } Expected Result: { "data": { "createUSBusinessAccountHolderFromToken": { "__typename": "USBusinessAccountHolder", "id": "", "businessProfile": { "id": "", "name": { "legalBusinessName": "LEGAL_BUSINESS_NAME" }, "operatingDetails": { "indicatorAttributes": [ { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } ] } } } }, "extensions": { "requestId": "b85fc1ec-e770-9d06-922f-16b7486a699i" } } ### GraphQL: GetBusinessAccountHolder Query: query GetBusinessAccountHolder($id: ID!) { node(id: $id) { ... on USBusinessAccountHolder { id businessProfile { name { legalBusinessName } operatingDetails { indicatorAttributes { type value reportedAt } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "businessProfile": { "name": { "legalBusinessName": "Fuel Corp." }, "operatingDetails": { "indicatorAttributes": [ { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } ] } } } }, "extensions": { "requestId": "a23de4f1-8821-4b3c-9a17-6c4f82d19e05" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/reevaluate-application Title: Reevaluate an Application Section: Issuing Description: Reevaluate an approved card product application to update account holder information while preserving the application history. ## Overview Reevaluate an Application should be used for changes to an already approved application, including updates to contact details such as address, phone number, and email. Some changes may require re-verification. Update Account Information is deprecated but will remain available for updating contact details such as address, phone number, and email as needed. Reevaluating an application creates a new application from an existing approved one and runs a customized processing workflow. You can update account holder identity information (e.g., legal name, SSN, EIN, address) on an approved application without modifying the original. Use cases include: - **Identity updates**: An account holder legally changes their name or address after approval. - **Periodic re-verification**: Re-run KYC or KYB checks against updated identity information. - **Compliance-driven reviews**: Satisfy regulatory requirements for periodic account holder re-vetting. Application data is a point-in-time snapshot of verified customer information. Approved applications are immutable for compliance and audit purposes. Instead of modifying an approved application directly, the reevaluation process creates a new edition of the application, processes it through a workflow, and, if approved, promotes it as the current application. ## Prerequisites - A Highnote account - Access to the Highnote API or API Explorer - An **approved** card product application - A **workflow configuration ID** () provided by the Highnote Operations team Contact your Highnote representative to set up a workflow configuration tailored to your specific reevaluation use case. The ability to query existing workflow configurations via the API is planned for a future release. ## How reevaluation works The reevaluation process follows three phases: 1. **Initiation**: You call the mutation with the approved application ID and a workflow configuration ID. Highnote creates a new application (a "reevaluation edition") and begins processing the specified workflow. 2. **Processing**: The new application moves through the workflow. Depending on the configuration, this may include collecting updated identity information from the account holder and running KYC/KYB verification. 3. **Resolution**: The reevaluation either succeeds or fails: - **Approved**: The new application is promoted as the current application. All dependent objects (financial accounts, payment cards) seamlessly reference the updated application. The original application is retired. - **Rejected**: The original application remains unchanged in status. You can initiate a new reevaluation. ### Application status values | Status | Description | | :--------- | :------------------------------------------------------------------------------------------- | | | The reevaluation application has been created and the workflow is in progress. | | | The reevaluation has been approved and the application is now the current edition. | | | The reevaluation was not successfully processed. The original application remains unchanged. | | | A previously current application that has been replaced by a successful reevaluation. | ### Constraints - Only **one active reevaluation** per application at a time. You must wait for the current reevaluation to reach a terminal state ( or ) before initiating another. - The source application must be in status. - Reevaluating one application has no impact on any other applications the account holder may have for different card products. ### Edition tracking Each reevaluation creates a new edition of the application, tracked by the field: - **Edition 0**: The original application. - **Edition 1**: The first reevaluation. - **Edition 2**: The second reevaluation, and so on. You can view the full edition history using the connection on the application. ## Step 1: Reevaluate an application Use the following mutation to create a reevaluation of an approved application. Provide: - : The ID of an approved . - : The workflow configuration ID provided by Highnote. The mutation creates a new application in status and automatically begins the configured workflow. ## Step 2: Check reevaluation status After initiating a reevaluation, use the following query to check the status of the new application and view the source application it was created from. The field on the reevaluated application points to the immediate parent -- the application that was used to create this reevaluation. ## Step 3: View application edition history Use the following query to view the full reevaluation history of an application. The connection returns all prior editions with their status and edition number. ## What happens after approval When a reevaluation is approved: 1. The new application is **promoted** as the current application for the account holder and card product. 2. All dependent objects (financial accounts, payment cards) seamlessly reference the updated application. 3. Updated identity information is pushed to the Identity service. 4. The previously current application transitions to status. It remains accessible through the connection for audit purposes. The field on and returns only the current application. Use the connection on an application to access its reevaluation history. ## What happens after rejection When a reevaluation is rejected: 1. The original application remains in status, unchanged. 2. The reevaluation application is marked . 3. You can initiate a new reevaluation for the same application. ### GraphQL: ReevaluateApplication Query: mutation ReevaluateApplication($input: ReevaluateApplicationInput!) { reevaluateApplication(input: $input) { __typename ... on Node { id } ... on AccountHolderCardProductApplication { id applicationState { status } sourceApplication { ... on AccountHolderCardProductApplication { id applicationState { status } } } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { name { givenName familyName } currentVerification { status reason } } ... on USBusinessAccountHolderSnapshot { primaryAuthorizedPerson { name { givenName familyName } currentVerification { status } } businessProfile { name { legalBusinessName } currentVerification { status } } } } createdAt updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "applicationId": "", "productApplicationWorkflowConfigurationId": "" } } Expected Result: { "data": { "reevaluateApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "sourceApplication": { "id": "", "applicationState": { "status": "APPROVED" } }, "accountHolderSnapshot": { "name": { "givenName": "Jane", "familyName": "Doe" }, "currentVerification": { "status": "PENDING", "reason": "PENDING" } }, "createdAt": "2026-02-25T18:00:00.000Z", "updatedAt": "2026-02-25T18:00:00.000Z" } }, "extensions": { "requestId": "" } } ### GraphQL: FindReevaluatedApplication Query: query FindReevaluatedApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } sourceApplication { ... on AccountHolderCardProductApplication { id applicationState { status } } } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { name { givenName familyName } currentVerification { status reason results { code description } } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id } primaryAuthorizedPerson { name { givenName familyName } currentVerification { status reason } } businessProfile { name { legalBusinessName doingBusinessAsName } currentVerification { status reason } } } } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "PENDING" }, "sourceApplication": { "id": "", "applicationState": { "status": "APPROVED" } }, "accountHolderSnapshot": { "name": { "givenName": "Jane", "familyName": "Doe" }, "currentVerification": { "status": "PENDING", "reason": "PENDING", "results": [] } }, "createdAt": "2026-02-25T18:00:00.000Z", "updatedAt": "2026-02-25T18:00:00.000Z" } }, "extensions": { "requestId": "" } } ### GraphQL: LookupApplicationWithPreviousEditions Query: query LookupApplicationWithPreviousEditions($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } reevaluationEdition sourceApplication { ... on AccountHolderCardProductApplication { id applicationState { status } } } previousApplications(first: 10) { pageInfo { hasNextPage endCursor } edges { node { ... on Node { id } ... on AccountHolderCardProductApplication { id reevaluationEdition applicationState { status } createdAt } } } } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "APPROVED" }, "reevaluationEdition": 1, "sourceApplication": { "id": "", "applicationState": { "status": "APPROVED" } }, "previousApplications": { "pageInfo": { "hasNextPage": false, "endCursor": "" }, "edges": [ { "node": { "id": "", "reevaluationEdition": 0, "applicationState": { "status": "APPROVED" }, "createdAt": "2026-01-01T00:00:00.000Z" } } ] }, "createdAt": "2026-02-25T18:00:00.000Z", "updatedAt": "2026-02-25T18:00:00.000Z" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/request-docs-for-app-review Title: Request Documents for Application Review Section: Issuing Description: Collect identity verification documents from account holders when applications are under manual review. Supports PDF, PNG, and JPG uploads. ## Overview Document requests are usually made as part of a pre-defined application review workflow. Applications are often flagged for review because additional account holder verification information is needed. This review process confirms a person or business's identity and ensures compliance with Know-Your-Customer (KYC) or Know-Your-Business (KYB) regulations. Sometimes, however, additional documents are requested outside of this flow, for example, when a business cannot complete its SOS filings in time, or when the application is under manual review. For these "generic" document requests, see Request for additional documents at the bottom of this page. ## Prerequisites 1. An account holder card product application with an status 2. Access to the Highnote API, API Explorer, or dashboard ## Application review process The application review process typically takes place as follows: 1. Application is flagged for review and inherits an status. 2. Application is either manually reviewed by Highnote or indicates that additional documentation is needed from the account holder. 3. _Optional_ - Send a notification to account holders of the application review status and direct them to the document upload flow using the application status event notification. 4. Generate a document upload session so the account holder can upload their documents. 5. Highnote reviews account holder documents and makes one of the following application decisions: - **Approve the application**: Documents were verified and the account holder's identity was confirmed. - **Deny the application**: Documents were not provided or appear to be fraudulent. - **Ask for more documents**: Additional documents are needed to confirm the identity of the account holder. ### Account holder documentation Depending on the type of account holder applying for a card product, documentation may be required from more than one applicant. For example, for business account holders, documents may be required for the primary authorized person and each beneficial owner. When an application enters status, the API returns the reason why it was flagged for review in . When there are multiple response codes, the account holder may need to provide multiple documents. In the response payload for the mutation, the following fields can be used to resolve a flagged application: - The field provides the document(s) that are most likely to resolve the review status with the fewest documents needed. - The to see all document types that may resolve each result code. ### US business account holder documentation Business entity documentation is only relevant to and includes documentation related to the business. In cases where a business account holder is a **sole proprietor**, personal information can be used in place of business-related documentation. For example, a sole proprietor may not have an EIN but can have one of the following documents: - Taxpayer identification - Social Security card - Owner’s full tax return with Schedule C included ## Collect documents for identity verification The application will be if the documents appear forged, outdated, or invalid. Also, documents cannot be expired and must be dated within 60 days. After the application is status (and verification documents are required), you can collect documents with the Document Upload SDK; or you can use the Highnote GraphQL API to generate URLs for each required document. One or more documents may be required based on the review response and the document type they provide. #### Document upload lifecycle #### Using the API If you use the Highnote API, the document upload process consists of the following steps: 1. _Optional_ - Generate a client token 2. Start document upload session 3. Create document upload link 4. End the document upload session ### File formats sizes sizes Supported file formats are PDF, PNG, JPG. We recommend a file size of 10MB or less. ### Start session For compliance reasons, if you are not using a server or do not have access to one, you must generate a client token to make requests directly from your client. See Client Tokens. Start a document upload session by generating a URL to send the account holder that allows them to upload their documents. We recommend using the application status event notification to send a notification to account holders to alert them of the application review status and provide a URL to your document upload session. Note the following when starting a document upload session: - Document upload sessions expire 30 days from creation. If the account holder does not provide the required documentation within 30 days, the application will be . - A session will indicate any requirements that your system may need to enforce when uploading the file. Use the following mutation to start a document upload session: ### Create link Document upload links expire 5 minutes after creation. Once a document upload session has started, you must create a secure upload link for each document. For example, if the applicant must provide a driver’s license and utility bill, each document would need its own unique upload link. Note the following when creating upload links: - Upload links expire 5 minutes after being created. If expired, an error message is returned, and you must request a new link. - Each upload link represents a single upload file. - When creating upload links, the document upload session status transitions to . - To stream the document upload, use the field in the mutation's response. Use the following mutation to create a document upload link. Use the from the response for this mutation's variable field: ### End session After an account holder has confirmed they have uploaded all required documents, you can end the document upload session. Check that every upload requirement is satisfied before ending a session. Specifically: 1. Query the session's . Each [](/docs/api-reference/object#UploadRequirement) carries a list. 2. For each requirement, confirm that every constraint's [](/docs/api-reference/object#DocumentUploadRequirementConstraint) is — meaning no further documents are required. Note the following when ending a document upload session: - When ending a session, the session status transitions to . - Once the session is , no other actions can be taken on it. If more documentation is required, a new session must be started to upload the additional documents. - The Highnote team will review the account holder's documents and decide on the application status. Use the following mutation to end a document upload session: ### Monitor application review status To protect account holder privacy, Highnote does _not_ return a public link for accessing document contents. You can monitor the status of account holder documents while the Highnote team reviews them by querying for the status using the Highnote API or the dashboard. For a full list of application status codes, see the AccountHolderApplicationStatusCode enum. Note the following about monitoring application review statuses: - Each document has its own individual status - Displaying the review status to the account holder is optional Use the following query to fetch the review status of an account holder application: ## Update document upload status Once you've closed the document upload session, you can simulate the review status of each document by assigning a new status of or . Use the following mutation to simulate the review status for each document uploaded in the upload session: ## Simulate application review Highnote's application review simulation allows you to test the following: - Application statuses - Your application review workflow - Document uploads For more information, see Simulate Application Review. ## Request for additional documents Highnote may also request documents outside of the application review process, such as compliance reviews or manual investigations. These requests are event-driven and independent of the application lifecycle. For details, see Request Documents On-Demand. ### GraphQL: StartDocumentUploadSession Query: mutation startDocumentUploadSession($input: StartDocumentUploadSessionInput!) { startDocumentUploadSession(input: $input) { __typename ... on Node { id } ... on USAccountHolderApplicationDocumentUploadSession { id status documents { id status uploadUrl } recommendedDocumentTypes documentContext { ... on AccountHolderApplicationDocumentUploadSessionContext { documentVerificationResultCodeContext { entries { document verificationResultCodes } } verificationResultCodeDocumentContext { entries { verificationResultCode documents } } } } } } } Variables: { "input": { "documentUploadSessionId": "" } } Expected Result: { "data": { "node": { "__typename": "USAccountHolderApplicationDocumentUploadSession", "id": "", "status": "INITIATED", "documents": null, "recommendedDocumentTypes": [ "DRIVERS_LICENSE" ], "documentContext": { "documentVerificationResultCodeContext": { "entries": [ { "document": "DRIVERS_LICENSE", "verificationResultCodes": [ "NAME_MISMATCH" ] }, { "document": "PAY_STUB", "verificationResultCodes": [ "NAME_MISMATCH" ] }, { "document": "PASSPORT", "verificationResultCodes": [ "NAME_MISMATCH" ] } ] }, "verificationResultCodeDocumentContext": { "entries": [ { "verificationResultCode": "NAME_MISMATCH", "documents": [ "DRIVERS_LICENSE", "PAY_STUB", "PASSPORT" ] } ] } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 7, "limit": 1000, "remaining": 993 } } } ### GraphQL: CreateDocumentUploadLink Query: mutation createDocumentUploadLink($input: CreateDocumentUploadLinkInput!) { createDocumentUploadLink(input: $input) { __typename ... on Node { id } ... on DocumentUploadLink { id documentUploadSession { id status } documentType documentCategoryType status uploadUrl } } } Variables: { "input": { "documentUploadSessionId": "", "documentType": "PASSPORT" } } Expected Result: { "id": "", "status": "PENDING", "documentUploadSession": { "id": "", "status": "IN_PROGRESS" }, "documentType": "PASSPORT", "documentCategoryType": "PRIMARY_DOCUMENT_TYPE", "uploadUrl": "https://storage.googleapis.upload-to-bucket" } ### GraphQL: EndDocumentUploadSession Query: mutation endDocumentUploadSession($input: EndDocumentUploadSessionInput!) { endDocumentUploadSession(input: $input) { __typename ... on Node { id } ... on USAccountHolderApplicationDocumentUploadSession { id status documents { ... on DocumentUploadLink { id status documentType documentCategoryType } } } } } Variables: { "input": { "documentUploadSessionId": "" } } Expected Result: { "id": "", "status": "SUBMITTED", "documents": [ { "id": "", "status": "UPLOADED", "documentType": "PASSPORT", "documentCategoryType": "PRIMARY_DOCUMENT_TYPE" } ] } ### GraphQL: findApplicationStatusAndRequiredDocumentsToUpload Query: query findApplicationStatusAndRequiredDocumentsToUpload($id: ID!) { node(id: $id) { __typename ... on AccountHolderCardProductApplication { id applicationState { status } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { __typename currentVerification { status requiredDocuments { documentUploadSession { ... on USAccountHolderApplicationDocumentUploadSession { id status } } status uploadedDocuments { ... on AccountHolderApplicationDocument { status type revisions { status type } } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "IN_REVIEW" }, "currentVerification": { "status": "PENDING", "reason": "DOCUMENT_UPLOAD_REQUIRED", "requiredDocuments": [ { "documentUploadSession": { "id": "", "status": "CREATED" }, "status": "CREATED", "uploadedDocuments": [] } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateApplicationDocumentReview Query: mutation simulateApplicationDocumentReview( $input: SimulateApplicationDocumentReviewInput! ) { simulateApplicationDocumentReview(input: $input) { __typename ... on AccountHolderApplicationDocument { createdAt status type updatedAt fileReviewReasons revisions { createdAt status type updatedAt fileReviewReasons } } ... on UserError { __typename errors { code errorPath description } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "applicationId": "", "documentUploadSessionId": "", "documentUploadLinkId": "", "newReviewStatus": "APPROVED", "fileReviewReasons": [ "ILLEGIBLE_DOCUMENT", "PARTIAL_DOCUMENT" ] } } Expected Result: { "data": { "simulateApplicationDocumentReview": { "__typename": "AccountHolderApplicationDocument", "createdAt": "2022-10-11T19:47:00.048Z", "status": "APPROVED", "type": "PASSPORT", "updatedAt": "2022-10-11T22:02:57.136Z", "fileReviewReasons": [ "ILLEGIBLE_DOCUMENT", "PARTIAL_DOCUMENT" ], "revisions": [ { "createdAt": "2022-10-11T19:47:00.048Z", "status": null, "type": "PASSPORT", "updatedAt": "2022-10-11T19:47:00.177Z", "fileReviewReasons": null } ] } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/request-docs-on-demand Title: Request Documents On-Demand Section: Issuing Description: Collect additional identity verification documents from account holders outside of the application review process using the Document Upload SDK or the Highnote API. ## Overview Highnote may request additional documents from an account holder outside of the normal application review process. These requests are triggered by compliance reviews, manual investigations, or other lifecycle events that require updated documentation. Unlike application review document requests, which are tied to a , on-demand document requests are event-driven and independent of the application lifecycle. ## How it works 1. Highnote creates a and sends a notification event via webhook. 2. You query the session by ID to see what documents are requested. 3. You collect and upload the documents using the Document Upload SDK or the Highnote API. ### Session status lifecycle After Highnote creates a session and you query by the session ID, you can begin the upload process: | Status | Description | | :------------ | :----------------------------------------------------------------------------------------------------- | | | The session has been created but not yet started. | | | The session has been started and files can be uploaded. | | | A file upload has been initiated within the session. | | | The session has ended. No further uploads are accepted. Highnote will review the uploaded documents. | | | The session expired due to inactivity. Files can no longer be uploaded. A new session must be created. | After a session is , Highnote reviews the documents. You can monitor the outcome by subscribing to the notification event. ### File formats and sizes Supported file formats: PDF, PNG, JPG. Maximum file size: 10 MB. ## Get requested documents When you receive a , extract the from the event payload. Use this ID to query for the session and see what documents are needed. The response includes a array with the requested and whether each document is . ## Upload documents After reviewing the requested documents, upload them using the Document Upload SDK or the Highnote API directly. ### Using the SDK The Document Upload SDK provides a pre-built widget that handles file selection, upload, and session management. The SDK automatically renders the list of required documents and closes the session when all uploads are complete. To use the SDK for on-demand document requests, pass the from the event payload when initializing the SDK. See the Document Upload SDK guide for installation, configuration, and error handling. ### Direct API integration If you prefer to manage the upload flow yourself, use the following API operations: #### Start session Start the document upload session to begin uploading files. Sessions expire 30 days from creation. #### Create upload link Create a secure upload link for each document. Each link represents a single file upload. Use the field in the response to stream the document. #### End session After all documents are uploaded, end the session. The session status transitions to and no further uploads are accepted. ### GraphQL: FindDocumentUploadSession Query: query FindDocumentUploadSession($id: ID!) { node(id: $id) { __typename ... on ManualDocumentRequestUploadSession { id status expiresAt createdAt updatedAt documentRequests { documentType required } documents { id status } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "ManualDocumentRequestUploadSession", "id": "", "status": "CREATED", "expiresAt": "2026-04-25T00:00:00.000Z", "createdAt": "2026-03-26T00:00:00.000Z", "updatedAt": "2026-03-26T00:00:00.000Z", "documentRequests": [ { "documentType": "DRIVERS_LICENSE", "required": true } ], "documents": null } }, "extensions": { "requestId": "", "rateLimit": { "cost": 7, "limit": 1000, "remaining": 993 } } } ### GraphQL: StartDocumentUploadSession Query: mutation startDocumentUploadSession($input: StartDocumentUploadSessionInput!) { startDocumentUploadSession(input: $input) { __typename ... on Node { id } ... on USAccountHolderApplicationDocumentUploadSession { id status documents { id status uploadUrl } recommendedDocumentTypes documentContext { ... on AccountHolderApplicationDocumentUploadSessionContext { documentVerificationResultCodeContext { entries { document verificationResultCodes } } verificationResultCodeDocumentContext { entries { verificationResultCode documents } } } } } } } Variables: { "input": { "documentUploadSessionId": "" } } Expected Result: { "data": { "node": { "__typename": "USAccountHolderApplicationDocumentUploadSession", "id": "", "status": "INITIATED", "documents": null, "recommendedDocumentTypes": [ "DRIVERS_LICENSE" ], "documentContext": { "documentVerificationResultCodeContext": { "entries": [ { "document": "DRIVERS_LICENSE", "verificationResultCodes": [ "NAME_MISMATCH" ] }, { "document": "PAY_STUB", "verificationResultCodes": [ "NAME_MISMATCH" ] }, { "document": "PASSPORT", "verificationResultCodes": [ "NAME_MISMATCH" ] } ] }, "verificationResultCodeDocumentContext": { "entries": [ { "verificationResultCode": "NAME_MISMATCH", "documents": [ "DRIVERS_LICENSE", "PAY_STUB", "PASSPORT" ] } ] } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 7, "limit": 1000, "remaining": 993 } } } ### GraphQL: CreateDocumentUploadLink Query: mutation createDocumentUploadLink($input: CreateDocumentUploadLinkInput!) { createDocumentUploadLink(input: $input) { __typename ... on Node { id } ... on DocumentUploadLink { id documentUploadSession { id status } documentType documentCategoryType status uploadUrl } } } Variables: { "input": { "documentUploadSessionId": "", "documentType": "PASSPORT" } } Expected Result: { "id": "", "status": "PENDING", "documentUploadSession": { "id": "", "status": "IN_PROGRESS" }, "documentType": "PASSPORT", "documentCategoryType": "PRIMARY_DOCUMENT_TYPE", "uploadUrl": "https://storage.googleapis.upload-to-bucket" } ### GraphQL: EndDocumentUploadSession Query: mutation endDocumentUploadSession($input: EndDocumentUploadSessionInput!) { endDocumentUploadSession(input: $input) { __typename ... on Node { id } ... on USAccountHolderApplicationDocumentUploadSession { id status documents { ... on DocumentUploadLink { id status documentType documentCategoryType } } } } } Variables: { "input": { "documentUploadSessionId": "" } } Expected Result: { "id": "", "status": "SUBMITTED", "documents": [ { "id": "", "status": "UPLOADED", "documentType": "PASSPORT", "documentCategoryType": "PRIMARY_DOCUMENT_TYPE" } ] } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/sim-account-closure Title: Simulate Account Closure Section: Issuing Description: Simulate the account closure workflow in the Test environment, from PENDING_CLOSURE through CLOSED status. ## Overview Do not enter production data in the Test environment. The Highnote Test environment is for exploring features and training. Use only dummy or test data. For credit card products, you have the option to close an account with a balance, which blocks authorizations and payment card issuance but allows repayments to continue to be made towards the outstanding balance payable. You can subscribe to financial account attribute events to be notified when an account has been closed with a balance and financial account status events when the balance has been paid off and the account is . Simulated closures follow the same lifecycle as real ones and can't be reversed by your team. Once a financial account reaches , it can't be reopened from your organization. For the account closure lifecycle, closure blockers, and notification events, see Close an Account. ## Simulate initiate an account closure Initiating an account closure in the Test environment moves the financial account's status to . Use the following mutation to simulate initiating an account closure: ## Simulate an account closure In the Test environment, you can simulate account closure by moving the financial account from to . Use the following mutation to simulate closing an account: ### GraphQL: SimulateInitiateFinancialAccountClosure Query: mutation simulateInitiateFinancialAccountClosure( $input: SimulateInitiateFinancialAccountClosureInput! ) { simulateInitiateFinancialAccountClosure(input: $input) { ... on FinancialAccount { __typename id accountStatus accountAttributes } ... on UserError { __typename errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "closeWithBalance": true } } Expected Result: { "data": { "simulateInitiateFinancialAccountClosure": { "__typename": "FinancialAccount", "id": "", "accountStatus": "PENDING_CLOSURE", "accountAttributes": [ "PENDING_CLOSURE", "CLOSED_WITH_BALANCE" ] } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateCloseFinancialAccount Query: mutation simulateCloseFinancialAccount( $input: SimulateCloseFinancialAccountInput! ) { simulateCloseFinancialAccount(input: $input) { ... on FinancialAccount { __typename id accountStatus accountAttributes } ... on UserError { __typename errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "" } } Expected Result: { "data": { "simulateCloseFinancialAccount": { "__typename": "FinancialAccount", "id": "", "accountStatus": "CLOSED", "accountAttributes": [ "PENDING_CLOSURE" ] } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/sim-application-review Title: Simulate Application Review Section: Issuing Description: Simulate KYC and KYB verification results, document uploads, and application status changes in the Test environment. ## Overview Do not enter production data in the Test environment. The Highnote Test environment is for exploring features and training. Use only dummy or test data. Highnote's application review simulation lets you test the following: - The status of an application - Your application review workflow - Document uploads ## Prerequisites 1. A Highnote account 2. Access to the Highnote API, API Explorer, or dashboard 3. A card product ## Simulate application review workflow To simulate an application review workflow, we recommend using the following sequence: Create an account holder with an open application: 1. Create an account holder with **specific KYC/KYB values**. 2. Open an application to simulate an or status. Simulate a document upload: 1. Simulate a document upload session. 2. Update the status of the document. 3. Update the identity verification status of the account holder. 4. _Optionally_ Simulate additional document upload sessions, e.g., if identity re-verification fails. 5. Update the application status to approve or deny. ## Create account holder with simulated values To simulate an application with the status of or , you must create an account holder with specific simulated values (provided below). These values differ depending on whether the applicant is undergoing Know-Your-Customer (KYC) or Know-Your-Business (KYB) verification: - **KYC**: Verification for person applications - **KYB**: Verification for business applications ### Person (KYC) verification values KYC verification is used to verify the identity of the following types of applicants: - - - Use the following values when creating an account holder to simulate the following application statuses: | Application Status | Account Holder Detail | Simulation Value | | :----------------- | :-------------------- | :-------------------- | | | | FORCE-DECLINE | | | | 123 Manual Review St. | For applications, you can use additional values to produce failure tags and simulate different failure scenarios: | Failure Tag | Account Holder Detail | Simulation Value | Pass Tag | | :-------------------------------------------------------------- | :--------------------------- | :--------------------------------------- | :-------------- | | | | 2000-01-01 | | | | | 66666 or 11111 | | | | | 6666666666 | | | ; Requires one document to verify identity | | 666-66-6666, 111-11-1111, or 111-11-1211 | | | ; Requires two documents to verify identity | | 111-11-1131 | N/A | | | and | IN-REVIEW | | | | | 123 Warning St. | N/A | After creating an account holder with simulated values, open an application. ### Business (KYB) verification values KYB verification is used to verify the identity and details of a . KYC verification is also required for each or under a . Use the following values when creating an account holder to simulate the following application statuses: | Application Status | Account Holder Detail | Simulation Value | | :----------------- | :-------------------- | :-------------------- | | | | FORCE-DECLINE | | | | 123 Manual Review St. | For applications, you can use additional values to produce failure tags and simulate different failure scenarios: | Failure Tag | Account Holder Detail | Simulation Value | Pass Tag | | :----------------------------------- | :--------------------------------------------------------------------------- | :-------------------------------------------------- | :----------------------------------- | | | | 66666 or 11111 | | | | | 666-66-6666, 111-11-1111, or 111-11-1211 | | | | | MISMATCH | | | | and | IN-REVIEW | | | | N/A | Simulate three or more failure tags from this table | | | | | 123 Warning St. | N/A | After creating an account holder with simulated values, open an application. ## Simulate document upload session Once an application has entered status, you can begin a document upload session to simulate adding supporting documents. Use the following steps to simulate the document upload session: 1. _Optional_ Generate a client token. 2. Start document upload session. 3. Create document upload link. 4. End the document upload session. ## Update document upload status Once you've closed the document upload session, you can simulate the **review status** of each document by assigning a new status of or . Use the following mutation to simulate the review status for each document uploaded in the upload session: ## Update identity verification status - In the **Test** environment, you can approve an application with the identity verification status set to any value: , , . - In the **Live** environment, the identity verification status of each account holder must be set to before you can approve an application. ::: Once a document review status is assigned, you can simulate the **identity verification status** of an account holder, represented by the field. For business account holders that have multiple authorized persons or owners, all account holder identities must pass for an application to be approved. Use the following mutation to simulate an identity verification status change, and update from to or : ## Simulate additional document upload sessions If you are only simulating one document upload session, skip this simulation. The following scenarios may require additional document upload sessions: - The document provided by the account holder is insufficient to approve the application. - You need to add primary authorized persons or beneficial owners to a business account holder. - An application has multiple applicants, each of which requires multiple document types. When simulating additional document upload sessions: - The application status remains , - The for each unverified application remains . - The for each requested application updates to . Use the following mutation to simulate additional document upload sessions. Provide a specific for each . See document types. ## Update application status This mutation lets you approve or deny an application status, but it does not approve each of the verification components. Verification components must be approved before you can create a financial account. To update verification components, see Update the identity verification status. To simulate an application status, you can update the application from to or . Use the following mutation to update the application status: ### GraphQL: SimulateApplicationDocumentReview Query: mutation simulateApplicationDocumentReview( $input: SimulateApplicationDocumentReviewInput! ) { simulateApplicationDocumentReview(input: $input) { __typename ... on AccountHolderApplicationDocument { createdAt status type updatedAt revisions { createdAt status type updatedAt } } ... on UserError { errors { code errorPath description } } ... on AccessDeniedError { message } } } Variables: { "input": { "applicationId": "", "documentUploadLinkId": "", "documentUploadSessionId": "", "newReviewStatus": "APPROVED" } } Expected Result: { "data": { "simulateApplicationDocumentReview": { "__typename": "AccountHolderApplicationDocument", "createdAt": "2022-10-13T21:20:38.463Z", "status": "APPROVED", "type": "DRIVERS_LICENSE", "updatedAt": "2022-10-13T21:20:45.587Z", "revisions": [ { "createdAt": "2022-10-13T21:20:38.463Z", "status": null, "type": "DRIVERS_LICENSE", "updatedAt": "2022-10-13T21:20:38.510Z" } ] } } } ### GraphQL: SimulateApplicationVerificationStatusChange Query: mutation simulateApplicationVerificationStatusChange( $input: SimulateApplicationVerificationStatusChangeInput! ) { simulateApplicationVerificationStatusChange(input: $input) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id name { givenName familyName } } currentVerification { reason status results { code } requiredDocuments { referenceIdentifier documentUploadSession { ... on USAccountHolderApplicationDocumentUploadSession { id status createdAt updatedAt documents { id uploadUrl createdAt updatedAt } } } uploadedDocuments { ... on AccountHolderApplicationDocument { createdAt status type updatedAt } } } } } } } } } Variables: { "input": { "applicantId": "", "applicationId": "", "newVerificationStatus": "PASSED" } } Expected Result: { "data": { "simulateApplicationVerificationStatusChange": { "id": "", "applicationState": { "status": "IN_REVIEW" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "", "name": { "givenName": "IN-REVIEW" } }, "name": { "givenName": "IN-REVIEW", "familyName": "lastName" }, "currentVerification": { "reason": "PASSED", "status": "PASSED", "results": [ { "code": "NAME_MISMATCH" }, { "code": "ADDRESS_MATCH" }, { "code": "DOB_MATCH" } ], "requiredDocuments": [ { "status": "SUBMITTED", "documentUploadSession": { "id": "", "status": "SUBMITTED" }, "uploadedDocuments": [ { "createdAt": "2022-10-13T21:20:38.463Z", "status": "APPROVED", "type": "DRIVERS_LICENSE", "updatedAt": "2022-10-13T21:20:45.587Z" } ] } ] } } } } } ### GraphQL: SimulateCreateApplicationDocumentsUploadSessions Query: mutation simulateCreateApplicationDocumentsUploadSessions( $input: SimulateCreateApplicationDocumentsUploadSessionsInput! ) { simulateCreateApplicationDocumentsUploadSessions(input: $input) { __typename ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } accountHolderSnapshot { __typename ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id name { givenName } } currentVerification { reason status results { code } } } } updatedAt createdAt } ... on UserError { errors { code errorPath description } } ... on AccessDeniedError { message } } } Variables: { "input": { "applicationId": "", "memo": "Additional documents are requested", "requestedDocuments": [ { "applicantId": "", "documentType": [ "PASSPORT" ] }, { "applicantId": "", "documentType": [ "DRIVERS_LICENSE", "STATE_ISSUED_ID" ] } ] } } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "IN_REVIEW" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "", "name": { "givenName": "IN-REVIEW" } }, "name": { "givenName": "IN-REVIEW", "familyName": "DECLINE" }, "currentVerification": { "reason": "DOCUMENT_UPLOAD_REQUIRED", "status": "PENDING", "requiredDocuments": [ { "status": "CREATED", "documentUploadSession": { "id": "", "status": "UPLOADED", "documents": null }, "uploadedDocuments": null }, { "status": "CREATED", "documentUploadSession": { "id": "", "status": "CREATED", "documents": null }, "uploadedDocuments": null } ] } } } } } ### GraphQL: SimulateApplicationStatusChange Query: mutation simulateApplicationStatusChange( $input: SimulateApplicationStatusChangeInput! ) { simulateApplicationStatusChange(input: $input) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id name { givenName } } name { givenName familyName } billingAddress { streetAddress locality region countryCodeAlpha3 postalCode } currentVerification { reason status results { code } requiredDocuments { referenceIdentifier documentUploadSession { ... on USAccountHolderApplicationDocumentUploadSession { id status createdAt updatedAt documents { id uploadUrl createdAt updatedAt } } } } } } } } ... on UserError { errors { code errorPath description } } ... on AccessDeniedError { message } } } Variables: { "input": { "applicationId": "", "newApplicationStatus": "APPROVED" } } Expected Result: { "data": { "simulateApplicationStatusChange": { "id": "", "applicationState": { "status": "APPROVED" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "", "name": { "givenName": "IN-REVIEW", "familyName": "lastName" } }, "currentVerification": { "reason": "PASSED", "status": "PASSED", "results": [ { "code": "DOB_MATCH" }, { "code": "ADDRESS_MATCH" }, { "code": "NAME_MISMATCH" } ], "requiredDocuments": [ { "status": "SUBMITTED", "documentUploadSession": { "id": "", "status": "SUBMITTED" }, "uploadedDocuments": [ { "createdAt": "2022-10-13T21:20:38.463Z", "status": "APPROVED", "type": "DRIVERS_LICENSE", "updatedAt": "2022-10-13T21:20:45.587Z" } ] } ] } } } } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/update-account-info Title: Update Account Information Section: Issuing Description: Update account holder contact information including address, phone, email, and credit risk attributes like income and employment status. ## Overview This guide provides steps for updating account holder information using the Highnote API. To update in the Highnote Dashboard, see Manage account holders. ## Account holder update notifications When account holder information is updated, Highnote may need to request documents to verify the account holder's identity. To automate your integration and stay notified of identity verification requests, subscribe to the following notification events: - Account holder identity documents requested notification events: Stay notified when an identity verification is requested for an account holder update to kickoff your document upload workflow - Account holder information update notification events: Stay notified when an account holder update is successfully applied to an account When using an account holder identity documents request event, the referenced by the event can be queried as a node using the type, and can also be interacted with via existing mutations to , and . See Collect documents for identity verification. ## Update person account holder For PENDING applications, contact support@highnote.com to request changes to account holder information. You cannot do this yourself. You can use the Highnote API to update account holder address, phone number, and website. To ensure compliance with Know Your Customer or Know Your Business (KYC-KYB), the Highnote team must update other account holder information such as Social Security Number (SSN), Employer Identification Number (EIN), date of birth, account holder name, etc. ## Address Account holders have two billing addresses, one at the account holder level and another associated with an account holder's payment card. Refer to the following table for an overview of each billing address object: | Object | Description | Use case | | :------------------- | :------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | billingAddress | The account holder level billing address | Used for KYC-KYB verification and mailing address if a separate mailing address is not set for the object | | billingAddressOnCard | The billing address associated with an account holder's payment card | Used for transaction authorization | When updating an account holder's address, you must update the and . Updating both addresses ensures data accuracy across account holder and payment card objects. The mutation uses the following input fields to update both addresses: - : The account level billing address - : The global ID for the account holder - : Boolean field used to update the ; must set the value to When updating an account holder's address, note the following requirements: - The new address must be a US-based physical address and can’t be a PO box. - The full address must be provided with the update, even if only a partial update is needed. For example, if the street address changes and the zip code remains the same, the full address is still needed for the update. Use the following mutation to update an account holder's and : ## Phone number When updating an account holder's phone number, note the following: - The new phone number must include the country code. - Only one phone number can be associated with an account holder. - Updating the account holder's phone number replaces the current one, regardless of the phone type in the update request. The account holder can only have a home or office phone number listed and not both. Use the following query to update an account holder's phone number: ## Email When updating an account holder’s email, note the following: - The new email must be a valid email address. - We recommend you send an email to your account holder using the old email address to notify them of the email update and mitigate potential fraud risks. Use the following query to update an account holder's email: ## Credit risk attributes You can update the credit risk attributes for a person account holder. These credit risk attributes include the following: - Annual income - Debt obligations - Employment status Use the following mutation to update a person account holder's credit risk attributes: ## Update business account holder For PENDING applications, contact support@highnote.com to request changes to account holder information. You cannot do this yourself. You can let business account holders update their their address, phone number, and website. To ensure compliance with Know Your Customer or Know Your Business (KYC-KYB), the Highnote team must update other account holder information such as Social Security Number (SSN), Employer Identification Number (EIN), date of birth, account holder name, etc. ### Address An account holder has two billing addresses, one at the account holder level and another associated with an account holder's payment card. Refer to the following table for an overview of each billing address object: | Object | Description | Use case | | :------------------- | :------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------- | | billingAddress | The account holder level billing address | Used for KYC-KYB verification and mailing address if a separate mailing address is not set for the object | | billingAddressOnCard | The billing address associated with an account holder's payment card | Used for transaction authorization | When updating an account holder's address, you must update the and . Updating both addresses ensures data accuracy across account holder and payment card objects. The mutation uses the following input fields to update both addresses: - : The account level billing address - : The global ID for the account holder - : Boolean field used to update the ; must set the value to When updating an account holder's address, note the following requirements: - The new address must be a US-based physical address and can’t be a PO box. - The full address must be provided with the update, even if only a partial update is needed. For example, if the street address changes and the zip code remains the same, the full address is still needed for the update. Use the following mutation to update an account holder's and : ### Phone number When updating an account holder's phone number, note the following: - The new phone number must include the country code. - Only one phone number can be associated with an account holder. - Updating the account holder's phone number replaces the current one, regardless of the phone type in the update request. For example, this means the account holder can only have a home or office phone number listed and not both. Use the following query to update a business account holder's phone number: ### Website Use the following query to update a business account holder's website URL: ## Update business associated person Business account holders may need to update the information of the primary authorized person and/or beneficial owners. You can enable account holders to update the address, phone number, and email of the primary authorized person and/or beneficial owners. Other account holder information, such as Social Security Number (SSN), date of birth, or name, may need to be manually reviewed by an agent to ensure compliance with Know Your Customer (KYC) or Know Your Business (KYB). ### Address When updating a business associated person's address, note the following requirements: - The new address must be a U.S. physical address and cannot be a PO box. - The full address must be provided with the update, even if only a partial update is needed. For example, if the street address changes and the zip code remains the same, the full address is still needed for the update. Use the following query to update a business associated person's address: ### Phone number When updating a business associated person's phone number, note the following: - The new phone number must include the country code. - Only one phone number can be associated with an account holder. - Updating the account holder’s phone number replaces the current one, regardless of the phone type in the update request. The account holder can only have a home or office phone number listed and not both. Use the following query to update a business associated person's phone number: ### Email When updating a business associated person's email, note the following: - The new email must be a valid email address. - We recommend you send an email to your account holder using the old email address to notify them of the email update and mitigate potential fraud risks. Use the following query to update a business associated person's email: ## Update authorized user You can provide the ability for authorized users to update their address, phone number, and email. Each mutation requires the accountHolderId of the account holder the authorized user belongs to, plus the authorized user's unique authorizedUserId to identify which profile to update. Other information, such as Social Security Number (SSN), date of birth, or name may need to be manually reviewed by a Highnote agent to ensure compliance with Know Your Customer (KYC) or Know Your Business (KYB). ### Address When updating an authorized user's address, note the following requirements: - The new address must be a U.S. physical address and cannot be a PO box. - The full address must be provided with the update, even if only a partial update is needed. For example, if the street address changes and the zip code remains the same, the full address is still needed for the update. Use the following query to update an authorized user's address: ### Phone number When updating an authorized user's phone number, note the following: - The new phone number must include the country code. - Only one phone number can be associated with an account holder. - Updating the authorized user’s phone number replaces the current one, regardless of the phone type in the update request. The account holder can only have a home or office phone number listed and not both. Use the following query to update an authorized user's phone number: ### Email When updating an authorized user's email, note the following: - The new email must be a valid email address. - We recommend you send an email to your authorized user using the old email address to notify them of the email update and mitigate potential fraud risks. Use the following query to update an authorized user's email: ### GraphQL: UpdateUSPersonAccountHolderBillingAddress Query: mutation updateUSPersonAccountHolder( $billingAddressInput: UpdateUSPersonAccountHolderBillingAddressInput! ) { updateUSPersonAccountHolderBillingAddress(input: $billingAddressInput) { __typename ... on UserError { errors { code description errorPath __typename } __typename } } } Variables: { "billingAddressInput": { "billingAddress": { "streetAddress": "444 Main Street", "postalCode": "60606", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "accountHolderId": "", "updatePaymentCardBillingAddress": true } } Expected Result: { "data": { "updateUSPersonAccountHolderBillingAddress": { "__typename": "USPersonAccountHolder" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 100, "remaining": 99989 } } } ### GraphQL: UpdateUSPersonAccountHolderPhone Query: mutation updateUSPersonAccountHolderPhone( $input: UpdateUSPersonAccountHolderPhoneInput! ) { updateUSPersonAccountHolderPhone(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAccountHolder { id phoneNumbers { countryCode number label } } } } Variables: { "input": { "phoneNumber": { "countryCode": "1", "number": "234123444", "label": "MOBILE", "extension": "312" }, "accountHolderId": "" } } Expected Result: { "data": { "updateUSPersonAccountHolderPhone": { "__typename": "USPersonAccountHolder", "phoneNumbers": { "countryCode": "1", "number": "234123444", "label": "MOBILE", "extension": "312" }, "id": "" }, "extensions": { "requestId": "" } } } ### GraphQL: UpdateUSPersonAccountHolderEmail Query: mutation updateUSPersonAccountHolderEmail( $input: UpdateUSPersonAccountHolderEmailInput! ) { updateUSPersonAccountHolderEmail(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAccountHolder { id email } } } Variables: { "input": { "email": "abc@123.com", "accountHolderId": "" } } Expected Result: { "data": { "updateUSPersonAccountHolderEmail": { "__typename": "USPersonAccountHolder", "id": "", "email": "abc@123.com" } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSPersonAccountHolderCreditRiskAttribute Query: mutation updateUSPersonAccountHolderCreditRiskAttribute( $input: UpdateUSPersonAccountHolderCreditRiskAttributeInput! ) { updateUSPersonAccountHolderCreditRiskAttribute(input: $input) { __typename ... 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 } } ... on UserError { errors { code description errorPath } } } } Variables: { "input": { "accountHolderId": "", "personCreditRiskAttributes": { "totalAnnualIncome": { "value": "2000", "currencyCode": "USD" }, "currentDebtObligations": { "value": "2000", "currencyCode": "USD" }, "employmentStatus": "EMPLOYEED" } } } Expected Result: { "data": { "updatePersonAccountHolderCreditRiskAttribute": { "__typename": "USPersonAccountHolder", "id": "", "email": "gerrytest1@abc.com", "dateOfBirth": "", "externalId": "", "updatedAt": "2023-07-29T15:08:15.304Z", "createdAt": "2023-07-29T15:06:08.626Z", "name": { "givenName": "", "familyName": "", "title": "", "suffix": "", "middleName": "" }, "billingAddress": null, "phoneNumbers": [ { "countryCode": "1", "number": "2222222222", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": null }, "personCreditRiskAttributes": { "totalAnnualIncome": [ { "value": 2000, "currencyCode": "USD" } ], "currentDebtObligations": [ { "value": 2000, "currencyCode": "USD" } ], "employmentStatus": "EMPLOYEED" } } }, "extensions": { "requested": "", "rateLimit": { "cost": 15 } } } ### GraphQL: UpdateUSBusinessAccountHolderBillingAddress Query: mutation updateUSBusinessAccountHolder( $billingAddressInput: UpdateUSBusinessAccountHolderBillingAddressInput! ) { updateUSBusinessAccountHolderBillingAddress(input: $billingAddressInput) { __typename ... on UserError { errors { code description errorPath __typename } __typename } } } Variables: { "billingAddressInput": { "billingAddress": { "streetAddress": "444 Main Street", "postalCode": "60606", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "accountHolderId": "", "updatePaymentCardBillingAddress": true } } Expected Result: { "data": { "updateUSBuisnessAccountHolderBillingAddress": { "__typename": "USBusinessAccountHolder" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 100, "remaining": 99989 } } } ### GraphQL: UpdateUSBusinessAccountHolderPhone Query: mutation updateUSBusinessAccountHolderPhone( $input: UpdateUSBusinessAccountHolderPhoneInput! ) { updateUSBusinessAccountHolderPhone(input: $input) { __typename ... on USBusinessAccountHolder { id businessProfile { id phoneNumbers { countryCode number label } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "phoneNumber": { "countryCode": "1", "number": "4444444444", "label": "MOBILE" } } } Expected Result: { "data": { "updateUSBusinessAccountHolderPhone": { "__typename": "USBusinessAccountHolder", "id": "", "businessProfile": { "id": "", "phoneNumbers": [ { "countryCode": "1", "number": "4444444444", "label": "MOBILE" } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSBusinessAccountHolderWebsite Query: mutation updateUSBusinessAccountHolderWebsite( $input: UpdateUSBusinessAccountHolderWebsiteInput! ) { updateUSBusinessAccountHolderWebsite(input: $input) { __typename ... on USBusinessAccountHolder { id businessProfile { id website } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "website": "https://highnote.com" } } Expected Result: { "data": { "updateUSBusinessAccountHolderWebsite": { "__typename": "USBusinessAccountHolder", "id": "", "website": "https://highnote.com" } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSAssociatedPersonAccountHolderHomeAddress Query: mutation updateUSAssociatedPersonAccountHolderHomeAddress( $input: UpdateUSAssociatedPersonAccountHolderHomeAddressInput! ) { updateUSAssociatedPersonAccountHolderHomeAddress(input: $input) { ... on USBusinessAuthorizedPerson { __typename id homeAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } ... on UserError { __typename errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "businessAccountHolderId": "", "homeAddress": { "streetAddress": "444 Main Street", "postalCode": "60606", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "updateUSAssociatedPersonAccountHolderHomeAddress": { "__typename": "USBusinessAuthorizedPerson", "id": "", "homeAddress": { "streetAddress": "444 Main Street", "postalCode": "60606", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSAssociatedPersonAccountHolderPhone Query: mutation updateUSAssociatedPersonAccountHolderPhone( $input: UpdateUSAssociatedPersonAccountHolderPhoneInput! ) { updateUSAssociatedPersonAccountHolderPhone(input: $input) { ... on USBusinessAuthorizedPerson { __typename id phoneNumbers { countryCode number label } } ... on UserError { __typename errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "businessAccountHolderId": "", "phoneNumber": { "countryCode": "1", "number": "4444444444", "label": "MOBILE" } } } Expected Result: { "data": { "updateUSAssociatedPersonAccountHolderPhone": { "__typename": "USBusinessAuthorizedPerson", "id": "", "phoneNumbers": [ { "countryCode": "1", "number": "4444444444", "label": "MOBILE" } ] }, "extensions": { "requestId": "" } } } ### GraphQL: UpdateUSAssociatedPersonAccountHolderEmail Query: mutation updateUSAssociatedPersonAccountHolderEmail( $input: UpdateUSAssociatedPersonAccountHolderEmailInput! ) { updateUSAssociatedPersonAccountHolderEmail(input: $input) { ... on USBusinessAuthorizedPerson { __typename id email } ... on UserError { __typename errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "businessAccountHolderId": "", "email": "bar@example.com" } } Expected Result: { "data": { "updateUSAssociatedPersonAccountHolderEmail": { "__typename": "USBusinessAuthorizedPerson", "id": "", "email": "bar@example.com" } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSPersonAuthorizedUserBillingAddress Query: mutation updateUSPersonAuthorizedUserBillingAddress( $input: UpdateUSPersonAuthorizedUserBillingAddressInput! ) { updateUSPersonAuthorizedUserBillingAddress(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAuthorizedUser { id billingAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } } Variables: { "input": { "billingAddress": { "streetAddress": "444 Main Street", "postalCode": "60606", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "authorizedUserId": "", "accountHolderId": "", "updatePaymentCardBillingAddress": true } } Expected Result: { "data": { "updateUSPersonAuthorizedUserBillingAddress": { "__typename": "USPersonAuthorizedUser", "id": "", "billingAddress": { "streetAddress": "444 Main Street", "extendedAddress": "", "postalCode": "60606", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" } } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSPersonAuthorizedUserPhone Query: mutation updateUSPersonAuthorizedUserPhone( $input: UpdateUSPersonAuthorizedUserPhoneInput! ) { updateUSPersonAuthorizedUserPhone(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAuthorizedUser { id phoneNumbers { countryCode number label } } } } Variables: { "input": { "phoneNumber": { "countryCode": "1", "number": "234123444", "label": "MOBILE", "extension": "312" }, "authorizedUserId": "", "accountHolderId": "" } } Expected Result: { "data": { "updateUSPersonAuthorizedUserPhone": { "__typename": "USPersonAuthorizedUser", "id": "", "phoneNumbers": [ { "countryCode": "1", "number": "234123444", "label": "MOBILE" } ] } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateUSPersonAuthorizedUserEmail Query: mutation updateUSPersonAuthorizedUserEmail( $input: UpdateUSPersonAuthorizedUserEmailInput! ) { updateUSPersonAuthorizedUserEmail(input: $input) { __typename ... on UserError { errors { code description errorPath } } ... on USPersonAuthorizedUser { id email } } } Variables: { "input": { "email": "abc@123.com", "authorizedUserId": "", "accountHolderId": "" } } Expected Result: { "data": { "updateUSPersonAuthorizedUserEmail": { "__typename": "USPersonAuthorizedUser", "id": "", "email": "abc@123.com" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/accounts/onboarding/update-identity-info Title: Update Identity Information Section: Issuing Description: Update identity information on an in-progress card product application to resolve verification mismatches. ## Overview Identity information can be updated at any time—while submitting a new application, or after an application has been approved via Reevaluate an Application. Reevaluate is the recommended path for identity changes on approved accounts. The same workflow supports two use cases: - **Resolve a verification mismatch.** Highnote flags a mismatch (name, SSN, address, DOB) during application review, and the subscriber updates the affected field to clear it. After confirmation, Highnote re-runs verification—if the updated information matches, verification is approved; if it still results in a mismatch, identity documents may be requested from the account holder. - **Update contact information.** The subscriber updates or on an Account Holder, typically when an authorized person's contact information changes. OTP delivery reads from the latest identity, so changes are propagated to existing cards and per-card updates are not required. This page explains the identity update workflow: how to find, initiate, confirm, or cancel requested identity changes. The workflow is the same regardless of which use case triggers it. ## Workflow You can update supported fields for both BusinessAccountHolder or PersonAccountHolder. The workflow is as follows: - Step 1 Subscriber receives notification, . - Step 2 Subscriber queries Business or Person updatable fields. - Step 3 Subscriber initiates Business or Person identity updates. - Step 4 Subscriber enables customer to or initiated updates. - If customer confirms: Confirm the Initiated Update. - If customer cancels, does not follow through, or no changes are needed: Cancel the Initiated Update. - Step 5 Find newly updated fields on the application. Once confirmed or canceled, additional changes are no longer allowed. ## Updatable fields The following fields can be updated when an identity update is requested. ### Person account holder The following **Person Account Holder** fields can be updated: | Field | Triggered On | | :-------------------------------------------- | :-------------------------------------- | | | | | | | | | or | | | | | | Contact update (e.g., OTP delivery) | | | Contact update (e.g., OTP delivery) | ### Business profile The following **Business Profile** fields can be updated for Business Account Holders only: | Field | Triggered On | | :---------------------------------------------------- | :-------------------------------------- | | | | | | | | | or | You cannot update a Business Profile if any of the following tags are present on the application: or . If either of those tags exist, Highnote performs additional validation and verification to determine the final KYB status of the Business Profile. ### Business primary authorized person The following **Primary Authorized Person** fields can be updated for both Business Account Holders and Person Account Holders: | Field | Triggered On | | :-------------------------------------------- | :-------------------------------------- | | | | | | | | | or | | | | | | Contact update (e.g., OTP delivery) | | | Contact update (e.g., OTP delivery) | You cannot update a Primary Authorized Person if any of the following tags are present on the application: , , , or . If any of these tags exist, Highnote performs additional validation and verification to determine the final KYC status of the Primary Authorized Person. ### Business ultimate beneficial owner The following **Ultimate Beneficial Owner** fields can be updated for both Business Account Holders and Person Account Holders: | Field | Triggered On | | :-------------------------------------------- | :-------------------------------------- | | | | | | | | | or | | | | | | Contact update (e.g., OTP delivery) | | | Contact update (e.g., OTP delivery) | | | Ownership update | You cannot update an Ultimate Beneficial Owner (UBO) if any of the following tags are present on the application: , , , or . If any of these tags exist, Highnote performs additional validation and verification to determine the final KYC status of the Ultimate Beneficial Owner. ## Step 1: Receive notification of requested updates The process begins when you receive the NotificationEventName, from Highnote. The notification fires in two scenarios: - During initial application review, when Highnote's verification flags an identity mismatch. - After the subscriber calls Reevaluate an Application on an approved application, when the configured workflow requests identity updates. See Application status in the Events Reference. ## Step 2: Find requested identity updates Use the queries below to find requested identity updates on an application, indicated by = . The field within the array defines which fields can be updated to resolve identity verification. ### Find person identity update requests Use the following query to find requested identity updates for Person Account Holders: ### Find business identity update requests Use the following query to find requested identity updates for Business Account Holders: ## Step 3: Initiate identity updates Use the mutations below to initiate identity updates for US Person and US Business entities. ### Initiate person account holder identity update Use the following mutation to initiate an identity update for a Person Account Holder: ### Initiate business profile identity update Use the following mutation with to initiate an identity update for a Business Account Holder. ### Initiate business authorized person identity update Use the following mutation to initiate an identity update for a Business Account Holder Primary Authorized Person: ### Initiate business ultimate beneficial owner identity update Use the following mutation to initiate an identity update for a Business Account Holder Ultimate Beneficial Owner: ## Step 4: Confirm or cancel initiated update Once confirmed or canceled, additional changes are no longer allowed. ### Confirm the initiated update Use the following mutation with the to confirm and submit the initiated updates. Once confirmed, KYC and/or KYB automatically re-runs with the updated identity information. If identity verification can still not be resolved with the updated information, documentation may be requested for the identity. ### Cancel the initiated update You cannot cancel an update that has been confirmed. Use the following mutation to cancel an identity update if the customer cancels, does not follow through, or if no changes are needed. Updates that are cancelled may require further documentation verify the identity. ## Step 5: Find updated fields on application Use the following query to lookup and review the on the Account Holder's application. ### GraphQL: FindPersonRequestedIdentityUpdates Query: query FindPersonRequestedIdentityUpdates($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } name { givenName familyName middleName } email dateOfBirth currentVerification { status reason results { code } requestedUpdates { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "ap_YOUR_PERSON_APPLICATION_ID", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "pd_YOUR_CARD_PRODUCT_ID" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "ps_ah_YOUR_PERSON_ACCOUNT_HOLDER_ID" }, "name": { "givenName": "Jane", "familyName": "Doe", "middleName": null }, "email": "jane.doe@example.com", "dateOfBirth": "1990-01-15", "currentVerification": { "status": "PENDING", "reason": "IDENTITY_UPDATE_REQUESTED", "results": [], "requestedUpdates": [ { "id": "idtus_YOUR_REQUESTED_IDENTITY_UPDATE_ID", "status": "OPEN", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "ap_YOUR_PERSON_APPLICATION_ID" }, "requestedFor": { "__typename": "USPersonAccountHolder", "id": "ps_ah_YOUR_PERSON_ACCOUNT_HOLDER_ID" }, "changesRequested": [ "FULL_LEGAL_NAME", "SOCIAL_SECURITY_NUMBER" ], "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T21:18:25.271Z", "appliedUpdates": [] } ] } }, "updatedAt": "2024-07-23T21:18:25.271Z", "createdAt": "2024-07-23T21:18:25.271Z" } } } ### GraphQL: FindBusinessRequestedIdentityUpdates Query: query FindAccountHolderCardProductApplicationRequestedUpdates($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } accountHolderSnapshot { ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id } primaryAuthorizedPerson { currentVerification { status reason results { code } requestedUpdates { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } } businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { status reason results { code } requestedUpdates { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } ultimateBeneficialOwners { ... on USBusinessUltimateBeneficialOwnerSnapshot { currentVerification { status reason results { code } requestedUpdates { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } } } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "primaryAuthorizedPerson": { "currentVerification": { "status": "PENDING", "reason": "IDENTITY_UPDATE_REQUESTED", "results": [], "requestedUpdates": [ { "id": "", "status": "OPEN", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessAuthorizedPerson", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T21:18:25.271Z", "changesRequested": [ "SOCIAL_SECURITY_NUMBER", "FULL_LEGAL_NAME" ], "appliedUpdates": [] } ] }, "updatedAt": "2024-07-23T21:18:25.271Z", "createdAt": "2024-07-23T21:18:25.271Z" }, "businessProfile": { "name": { "legalBusinessName": "IN-REVIEW", "doingBusinessAsName": "ManualReview Inc" }, "updatedAt": "2024-07-23T21:18:25.271Z", "createdAt": "2024-07-23T21:18:25.271Z", "currentVerification": { "status": "PENDING", "reason": "IDENTITY_UPDATE_REQUESTED", "results": [], "requestedUpdates": [ { "id": "", "status": "OPEN", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessProfile", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "changesRequested": [ "EMPLOYER_IDENTIFICATION_NUMBER", "LEGAL_BUSINESS_NAME" ], "appliedUpdates": [] } ] }, "ultimateBeneficialOwners": [ { "currentVerification": { "status": "PENDING", "reason": "IDENTITY_UPDATE_REQUESTED", "results": [], "requestedUpdates": [ { "id": "", "status": "OPEN", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessUltimateBeneficialOwner", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T21:18:25.271Z", "changesRequested": [ "SOCIAL_SECURITY_NUMBER" ], "appliedUpdates": [] } ] } } ] } }, "updatedAt": "2024-07-23T21:18:25.271Z", "createdAt": "2024-07-23T21:18:25.271Z" } } } ### GraphQL: InitiateUSPersonAccountHolderRequestedIdentityUpdate Query: mutation InitiateUSPersonAccountHolderRequestedIdentityUpdate( $input: InitiateUSPersonAccountHolderRequestedIdentityUpdateInput! ) { initiateUSPersonAccountHolderRequestedIdentityUpdate(input: $input) { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on Node { id } ... on USPersonAccountHolder { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on Node { id } ... on USPersonAccountHolder { id } } createdAt updatedAt } } } } } Variables: { "input": { "requestedIdentityUpdateId": "", "personAccountHolder": { "name": { "givenName": "Jane", "familyName": "Doe" }, "identificationDocument": { "socialSecurityNumber": { "number": "123-45-6789", "countryCodeAlpha3": "USA" } } } } } Expected Result: { "data": { "initiateUSPersonAccountHolderRequestedIdentityUpdate": { "id": "idtus_YOUR_REQUESTED_IDENTITY_UPDATE_ID", "status": "INITIATED", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "ap_YOUR_PERSON_APPLICATION_ID" }, "requestedFor": { "__typename": "USPersonAccountHolder", "id": "ps_ah_YOUR_PERSON_ACCOUNT_HOLDER_ID" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T23:18:25.271Z", "changesRequested": [ "FULL_LEGAL_NAME", "SOCIAL_SECURITY_NUMBER" ], "appliedUpdates": [ { "appliedChanges": [], "requestedChange": { "__typename": "USPersonAccountHolder", "id": "ps_ah_YOUR_PERSON_ACCOUNT_HOLDER_ID" }, "createdAt": "2024-07-23T23:18:25.271Z", "updatedAt": "2024-07-23T23:18:25.271Z" } ] } } } ### GraphQL: InitiateUSBusinessProfileRequestedIdentityUpdate Query: mutation InitiateUSBusinessProfileRequestedIdentityUpdate( $input: InitiateUSBusinessProfileRequestedIdentityUpdateInput! ) { initiateUSBusinessProfileRequestedIdentityUpdate(input: $input) { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id identificationDocument { employerIdentificationNumber { countryCodeAlpha3 } } name { legalBusinessName } } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } Variables: { "input": { "requestedIdentityUpdateId": "", "businessProfile": { "identificationDocument": { "employerIdentificationNumber": { "number": "34-1213141", "countryCodeAlpha3": "USA" } }, "name": { "legalBusinessName": "My Company" } } } } Expected Result: { "data": { "initiateUSBusinessProfileRequestedIdentityUpdate": { "id": "", "status": "INITIATED", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessProfile", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T21:18:25.271Z", "changesRequested": [ "EMPLOYER_IDENTIFICATION_NUMBER", "LEGAL_BUSINESS_NAME" ], "appliedUpdates": [ { "appliedChanges": [], "requestedChange": { "__typename": "USBusinessProfile", "id": "", "identificationDocument": { "employerIdentificationNumber": { "countryCodeAlpha3": "USA" } }, "name": { "legalBusinessName": "My Company" } } } ] } } } ### GraphQL: InitiateUSBusinessAuthorizedPersonRequestedIdentityUpdate Query: mutation InitiateUSBusinessAuthorizedPersonRequestedIdentityUpdate( $input: InitiateUSBusinessAuthorizedPersonRequestedIdentityUpdateInput! ) { initiateUSBusinessAuthorizedPersonRequestedIdentityUpdate(input: $input) { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } Variables: { "input": { "requestedIdentityUpdateId": "", "primaryAuthorizedPerson": { "name": { "givenName": "Joe" }, "identificationDocument": { "socialSecurityNumber": { "number": "543-39-8765", "countryCodeAlpha3": "USA" } } } } } Expected Result: { "data": { "initiateUSBusinessAuthorizedPersonRequestedIdentityUpdate": { "id": "", "status": "INITIATED", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessAuthorizedPerson", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T23:18:25.271Z", "changesRequested": [ "GIVEN_NAME", "SOCIAL_SECURITY_NUMBER" ], "appliedUpdates": [ { "appliedChanges": [], "requestedChange": { "__typename": "USBusinessAuthorizedPerson", "id": "" } } ] } } } ### GraphQL: InitiateUSBusinessUltimateBeneficialOwnerRequestedIdentityUpdate Query: mutation initiateUSBusinessUltimateBeneficialOwnerRequestedIdentityUpdate( $input: InitiateUSBusinessUltimateBeneficialOwnerRequestedIdentityUpdateInput! ) { initiateUSBusinessUltimateBeneficialOwnerRequestedIdentityUpdate( input: $input ) { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id identificationDocument { employerIdentificationNumber { countryCodeAlpha3 } } name { legalBusinessName } } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } Variables: { "input": { "requestedIdentityUpdateId": "", "ultimateBeneficialOwner": { "name": { "givenName": "John" }, "identificationDocument": { "socialSecurityNumber": { "number": "543-39-8765", "countryCodeAlpha3": "USA" } } } } } Expected Result: { "data": { "initiateUSBusinessUltimateBeneficialOwnerRequestedIdentityUpdate": { "id": "", "status": "INITIATED", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessUltimateBeneficialOwner", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T23:18:25.271Z", "changesRequested": [ "GIVEN_NAME", "SOCIAL_SECURITY_NUMBER" ], "appliedUpdates": [ { "appliedChanges": [], "requestedChange": { "__typename": "USBusinessUltimateBeneficialOwner", "id": "", "identificationDocument": { "employerIdentificationNumber": { "countryCodeAlpha3": "USA" } }, "name": { "legalBusinessName": null } } } ] } } } ### GraphQL: ConfirmRequestedIdentityUpdate Query: mutation ConfirmRequestedIdentityUpdate( $input: ConfirmRequestedIdentityUpdateInput! ) { confirmRequestedIdentityUpdate(input: $input) { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id identificationDocument { employerIdentificationNumber { countryCodeAlpha3 } } name { legalBusinessName } } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } Variables: { "input": { "id": "", "confirmedAt": "2024-07-23T21:18:25.271Z" } } Expected Result: { "data": { "confirmRequestedIdentityUpdate": { "id": "", "status": "CONFIRMED", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessProfile", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-24T21:18:25.271Z", "changesRequested": [ "EMPLOYER_IDENTIFICATION_NUMBER", "LEGAL_BUSINESS_NAME" ], "appliedUpdates": [ { "appliedChanges": [ "EMPLOYER_IDENTIFICATION_NUMBER", "LEGAL_BUSINESS_NAME" ], "requestedChange": { "__typename": "USBusinessProfile", "id": "", "identificationDocument": { "employerIdentificationNumber": { "countryCodeAlpha3": "USA" } }, "name": { "legalBusinessName": "My Company" } } } ] } } } ### GraphQL: CancelRequestedIdentityUpdate Query: mutation CancelRequestedIdentityUpdate( $input: CancelRequestedIdentityUpdateInput! ) { cancelRequestedIdentityUpdate(input: $input) { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id identificationDocument { employerIdentificationNumber { countryCodeAlpha3 } } name { legalBusinessName } } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } Variables: { "input": { "id": "", "confirmedAt": "2024-07-23T21:18:25.271Z" } } Expected Result: { "data": { "cancelRequestedIdentityUpdate": { "id": "", "status": "CANCELLED", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessProfile", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-24T21:18:25.271Z", "changesRequested": [ "EMPLOYER_IDENTIFICATION_NUMBER", "LEGAL_BUSINESS_NAME" ], "appliedUpdates": [] } } } ### GraphQL: FindApplicationIdentityUpdates Query: query FindApplicationIdentityUpdates($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } accountHolderSnapshot { ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id } primaryAuthorizedPerson { currentVerification { status reason results { code } requestedUpdates { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt updatedAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } } businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { status reason results { code } requestedUpdates { ... on RequestedIdentityUpdate { id status referredBy { __typename ... on AccountHolderCardProductApplication { id } ... on AuthorizedUserCardProductApplication { id } } requestedFor { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } changesRequested createdAt appliedUpdates { ... on RequestedIdentityAppliedUpdate { appliedChanges requestedChange { __typename ... on USBusinessProfile { id } ... on USBusinessAuthorizedPerson { id } ... on USBusinessUltimateBeneficialOwner { id } ... on USPersonAccountHolder { id } ... on USPersonAuthorizedUser { id } } createdAt updatedAt } } } } } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "primaryAuthorizedPerson": { "currentVerification": { "status": "PENDING", "reason": "IDENTITY_UPDATE_REQUESTED", "results": [], "requestedUpdates": [ { "id": "", "status": "OPEN", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessAuthorizedPerson", "id": "" }, "changesRequested": [ "SOCIAL_SECURITY_NUMBER", "GIVEN_NAME" ], "createdAt": "2024-07-23T21:18:25.271Z", "updatedAt": "2024-07-23T21:18:25.271Z", "appliedUpdates": [] } ], "updatedAt": "2024-07-23T21:18:25.271Z", "createdAt": "2024-07-23T21:18:25.271Z" } }, "businessProfile": { "name": { "legalBusinessName": "My Company", "doingBusinessAsName": "ManualReview Inc" }, "updatedAt": "2024-07-23T21:18:25.273Z", "createdAt": "2024-07-23T21:18:25.271Z", "currentVerification": { "status": "PENDING", "reason": "PENDING", "results": [], "requestedUpdates": [ { "id": "", "status": "CONFIRMED", "referredBy": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "requestedFor": { "__typename": "USBusinessProfile", "id": "" }, "createdAt": "2024-07-23T21:18:25.271Z", "changesRequested": [ "EMPLOYER_IDENTIFICATION_NUMBER", "LEGAL_BUSINESS_NAME" ], "appliedUpdates": [ { "appliedChanges": [ "EMPLOYER_IDENTIFICATION_NUMBER", "LEGAL_BUSINESS_NAME" ], "requestedChange": { "__typename": "USBusinessProfile", "id": "", "identificationDocument": { "employerIdentificationNumber": { "countryCodeAlpha3": "USA" } }, "name": { "legalBusinessName": "My Company" } } } ] } ] } } }, "updatedAt": "2024-07-23T21:18:25.273Z", "createdAt": "2024-07-23T21:18:25.271Z" } } } --- URL: https://docs.highnote.com/docs/issuing/cards/design/design-card-experience Title: Design Your Card Experience Section: Issuing Description: Design the cardholder journey from onboarding and application through card issuance, account access, and funding. ## Before you start Each cardholder has a journey, from onboarding, through their day-to-day use of your card product. Building a card experience for your cardholders on your website or app is an integral step in launching a card product. This guide aims to help your team understand and explore how to build a specific card experience for cardholders. It is companion to Highnote’s API guides and meant for designers, product managers, and front-end engineers. ## Onboarding experience Creating the account holder onboarding flow is the first part of designing a card experience. During onboarding, account holders enter their personal information and open applications. ### Account holder credentials Highnote does not manage your users' credentials for logging into your website or application. Before designing your card experience, you must have a way to create user credentials in your system or connect your Highnote card experience to your existing user credentials. Highnote’s object supports an that you can use to match your existing user credentials to account holders in the Highnote platform. Refer to the following account holder types for an overview of the account holder object: - US Person Account Holder: An account holder who uses a consumer card product - US Business Account Holder: An account holder who uses a commercial card product ### Create account holder Account holder first names must be at least _one character_. After a user logs in using their credentials, you can direct them to a form where they can provide their account holder details. Account holder details have required input fields that are essential for running KYC or KYB identity checks, ensuring the account holder qualifies for your card product, and creating the account holder in Highnote. We recommend collecting account holder details in a single view to avoid storing sensitive information on your client. US Person and US Business Account Holders have different required input fields. Refer to the following table for an overview of the required input fields for each account holder type: | Account Holder Type | Required Input Fields | | :------------------------- | :---------------------------------------------------------------------------------------------------------- | | US Person Account Holder | First name | | | Last name | | | Street address | | | City | | | State/Territory | | | Postal code | | | Email | | | Phone number | | | Date of birth | | | SSN | | US Business Account Holder | Legal business name | | | Identification Number (EIN) | | | Business type | | | Business phone | | | Street address | | | City | | | State | | | Postal code | | | Primary Authorized Person | | Primary Authorized Person | First name | | | Last name | | | Email | | | Phone | | | Home Address | | | City | | | State | | | Postal code | | | SSN | | | Date of birth | | Beneficial Owners | First name | | | Last name | | | Email | | | Phone | | | Home address | | | City | | | State | | | Postal code | | | SSN | | | Percentage ownership | | | DOB | Refer to the following API guides and references with your development team to create this part of your card experience: - Onboard an Account Holder guide - Create US Person Account Holder mutation - Create US Business Account Holder mutation ### Open an application The API call used to create an account holder is separate from the API call used to open an application. You can open an application using one of the following methods: - Use the API to create an account holder and open the application in two separate flows. - Use the API to create an account holder and open the application in the same flow, with the open application call requested silently at the time of account creation. - If you choose this option, you must present your card product's terms when you capture the account holder details. When opening the application, you must display your complete card product terms to the account holder, capture their consent, and record when they agreed to the terms. Refer to the following API guides and references with your development team to create this part of your card experience: - Open an Application guide - Create Account Holder Card Product Application mutation ### Display application status After an application opens, it enters a status while under review. Application reviews are automated and usually process quickly, but risky applications may sometimes require a more extended review period. After an account holder applies, you can look up the application status and display the status in your card experience. For example, you can create different views for when an application is , , or , ensuring account holders can track their application status while logged into their account. You can also subscribe to application status notifications and events. Using notifications and events, you can use status changes to send account holders an email or push notification notifying them whether they’ve been approved or denied, or if extra documentation is required. Refer to the following API guides and references with your development team to create this part of your card experience: - Check Application Status guide - Account Holder Application Status Code query - Application Status Events reference ## Collect additional documentation Some applications may require additional documents from the account holder to verify their identity. When an application needs additional documents for approval, you can create a notification or callout in your card experience that notifies the applicant. This notification or callout is triggered using the verification status reason code. After notifying the applicant, you can provide a view informing them what documents they need for identity verification and a way to upload them to Highnote using a document upload link. When an application returns a status, the API response provides the needed documents. Once uploaded, the Highnote team reviews the documents, so you do not need to create an experience for your support team to verify the documents. During the review process, you can show a pending status view to your applicant. This pending status view can either be the same application status view you created previously, or a specific one related to the document review status. Refer to the following API guides and references with your development team to create this part of your card experience: - Request Documents for Application Review guide - Document Upload SDK - Application Status notification - Document Upload notification ## Issue and order cards After onboarding an account holder and approving their application, you can create the card issuing and ordering experience. ### Issue financial account and virtual card When an account holder has been approved for your card product, you will issue them a financial account. A financial account stores card balances and requires no end-user input, meaning you can create it in the backend immediately after application approval. In addition to storing card balances, financial accounts can support linking external bank accounts to transfer money in and out of them. Some financial accounts can even have account and routing numbers to support direct deposits. After issuing a financial account, you can issue a card to the account holder. By default, the card starts as a virtual card, with the option to issue a physical card. Issuing a card also requires no end-user input, so you can issue the card in the backend immediately after issuing a financial account. You can also choose to activate a card automatically at creation or design your own activation experience for the account holder to self-activate their card. During this step, you can use notifications and events to send an email or push notification to the account holder to let them know their card is ready. Refer to the following API guides and references with your development team to create this part of your card experience: - Issue a Financial Account guide - Issue a Virtual Card guide - Activate a Card guide - Issue Financial Account mutation - Issue Payment Card mutation ### Display virtual card By default, a payment card starts as a virtual card. After issuing a card, you can display the virtual card on your app or website to the account holder so they may use the card for online purchases immediately. You can also provide a method for the account holder to add their card to a digital wallet like Apple Pay or Google Wallet. Refer to the following API guides and references with your development team to create this part of your card experience: - Display a Card guide - Card Viewer SDK - Add Cards to Digital Wallets guide ### Order physical card You also have the option of ordering physical cards for account holders. There are two methods for issuing physical cards: - Pre-fill the account holder’s details using your data on file and immediately order the card once the application is approved. This option drives spending and increases the account holder's excitement at approval time. - Provide a way for the account holder to order a card after the application experience is complete. You can also use the Physical Cards events reference to send emails or push notifications to account holders when their physical cards ship. Refer to the following API guides and references with your development team to create this part of your card experience: - Physical Cards Design guide - Print Physical Cards guide - Print Cards in Bulk guide - Physical Card Fulfillment events reference - Embedded Devices guide ## Core experience After an account holder has gone through your onboarding experience and been issued a card, you will want to ensure they can access their account on your app or website. When an account holder accesses their account, we recommend directing them to a core experience where they can view account information, manage or control their card, view recent transaction history, and more. We recommend including the following when designing your card’s core experience: - Display account balance or credit limit - Display the last four digits of a card number - Display direct deposit information for financial accounts with the direct deposit feature enabled - Provide a button for disabling, suspending, or activating their card - Provide a link to replace lost, stolen, or damaged cards - Provide a view of recent transactions with a link to view all transactions or statements ## Funds and balances Your card experience should include a way for account holders to transfer funds or view their account balance or credit limits. The process for funding financial accounts differs depending on the type of card product you offer: - Debit, prepaid credit, or secured credit card products support connecting external bank accounts to transfer funds to or from a financial account via ACH. You can create an experience using Plaid or Finicity in your application that allows account holders to link their accounts. - Account holders using credit, consumer charge, or fleet card products use credit lines to fund their financial accounts. ### Debit, prepaid, and secured credit card products You can create an experience that allows your account holders to connect their external bank accounts as a funding source. We recommend designing one of the following experiences for connecting a bank account: - Create a section in your app or website where the bank account information lives, and add a button to that section that can be used to connect a bank account. - Immediately after card approval, redirect the account holder to a UI for connecting their bank account. When the account holder starts the experience to connect their bank account, they will be redirected to Plaid or Finicity. Plaid or Finicity will ask for their banking credentials, authenticate the account holder, and send their bank account information to your app or website. You can display a success screen or notification when the account holder's bank account information has been received. Once an account holder's bank account is connected, you can create an experience for them to add funds or move funds out of their financial account. We recommend creating buttons for transferring funds from their external bank account to their card product's financial account. Each card product type has a different funding source. See the Add Funds to an Account guide for more details. ### Credit, charge, and fleet cards Funding for credit, consumer charge, and fleet card products uses the credit limit issued to the account holder. The credit limit uses your product funding account to fund the account holder's financial account. This means, at the minimum, the equivalent of the issued credit line must be available in your product funding account. The account holder does not need to connect an external bank account; they only need to be able to monitor their credit limit. We recommend creating a display in your app or website’s core experience that displays the account holder's credit limit. Refer to the following API guides and references with your development team to create this part of your card experience: - Connect External Accounts guide - Add Funds to an Account guide - Move Funds Out of Highnote guide - Commercial Charge guide - Consumer Charge guide - Fleet guide ## Account holder management Another essential part of building a card experience is to design a way for account holders to manage their account details. US Person and US Business account holder can update their address, phone number, email, and website. You can also create a way for beneficial owners and authorized users to update their account information. We recommend designing a settings page for your app or website that houses account holder information and allows the end-user to update it. Each piece of account holder information uses its own API call, so we recommend designing the settings page as a form with a field for each piece of account holder information that can be submitted and saved. Refer to the Update Account Information guide to create this part of your card experience. --- URL: https://docs.highnote.com/docs/issuing/cards/design/ordering-physical-cards Title: Ordering Physical Cards Section: Issuing Description: Plan your physical card ordering process, including approval workflows, manufacturing lead times, and shipping timelines for on-demand and premium cards. ## Overview The card ordering process involves: - Submitting your card design. - Approving proofs during the manufacturing process. ## Ordering process The ordering process differs based on whether you order on-demand or premium cards. ### On-demand cards {#ordering-on-demand} The typical card ordering process for on-demand cards is as follows: 1. Finalized card design received from card program 2. Design approved by card manufacturer 3. Card program receives proof from card manufacturer 4. Card program approves proof 5. Card network approval 6. Quality assurance (QA) 7. Pre-product order notification sent 8. Program live ### Premium cards {#ordering-premium} The typical card ordering process for premium cards is as follows: 1. Finalized card design received from card program 2. Receive and approve sales quote 3. Receive and approve proof 4. Submit proof 5. Card manufacturing begins 6. Card personalization begins 7. Receive personalization proofs 8. Approve proof 9. Final approval ## Lead and shipping timelines Getting a card into an account holder's hands has two parts: - **Lead time**: the production steps in the tables below, from card design through processing, before the card is handed to the courier. - **Shipping time**: the transit leg from the courier to the account holder, which depends on the shipping method you choose. Your total timeline is lead time plus shipping time. Both are subject to change. ### On-demand cards {#timelines-on-demand} On-demand cards are faster to manufacture than premium cards (weeks vs months), but a little bit slower to process unless expedited (48 hours vs same-day/next-day). #### Lead time {#lead-time-on-demand} Typical lead times for on-demand cards are as follows: | Step | Timeline | | :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Proof creation | 2 days from receiving the card design in the correct format | | Brand approval | ~2-5 days from submission | | Card manufacturing | ~1 week after proof creation; cards printed same day on-demand | | Activation labels | 1 week | | Processing | 48-hour SLA after receiving the card file | | Expedited processing | Same day if card file submitted by 5 AM PT cutoff.
Use a shipping method. Additional fees apply. Contact support@highnote.com. | #### Shipping time {#shipping-time-on-demand} Typical transit times after the card ships are as follows: | Shipping speed | Transit time | | :--------------- | :---------------- | | Ground | 1-8 business days | | Priority / 2-day | 1-3 business days | | Overnight | Next business day | See Shipping methods, for all shipping methods and their values. ### Premium cards {#timelines-premium} Premium cards take longer to manufacture than on-demand cards (months vs weeks), but are faster to process (same-day or next-day vs 48 hours). #### Lead time {#lead-time-premium} Typical lead times for premium cards are as follows: | Step | Timeline | | :------------------ | :----------------------------------------------------------- | | Proof creation | 2 days from receiving the card design in the correct format | | Brand approval | ~2-5 days from submission | | Card manufacturing | 6-18 weeks from brand approval (depending on card selection) | | Packaging materials | ~8 weeks upon final proof approval | | Activation labels | ~8 weeks plus shipping | | Processing | Same day or next day after receiving the card file | #### Shipping time {#shipping-time-premium} Typical transit times after the card ships are as follows: | Shipping speed | Transit time | | :--------------- | :---------------- | | Ground | 1-8 business days | | Priority / 2-day | 1-3 business days | | Overnight | Next business day | See Shipping methods, for all shipping methods and their values. --- URL: https://docs.highnote.com/docs/issuing/cards/design/physical-cards Title: Physical Card Design Section: Issuing Description: Design physical cards with on-demand or premium materials. Covers personalization, card art templates, packaging, and Visa and Mastercard design guidelines. ## Overview Highnote offers multiple options for designing and printing physical cards for account holders. You can choose from the following physical card options: - **On-demand cards**: On-demand cards are traditional plastic cards. They have lower upfront costs, are printable on-demand, and support ordering one-off cards. - **Premium cards**: Premium cards are premium plastic or metal cards. They are highly customizable, with unique printing and design options. The following table provides an overview of the differences between on-demand and premium cards: | Options | On-demand | Premium | | :---------------------------- | :------------ | :---------- | | Pricing structure | Pay-as-you-go | Pay in bulk | | Minimum quantity requirements | No | Yes | | Program setup time | Fast | Average | | Material options | Limited | Extensive | | Print quality | Good | Best | ## Customization options On-demand and premium cards have different materials, printing, and design options. The following table outlines the differences in customization options for each card type: | | On-demand plastic | Premium plastic | Premium metal | | :---------------------------- | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Material and printing methods | Digital printing | Offset (Litho printing), silkscreen, digital printing | Embedded metal, metal veneer lite, metal veneer, metal hybrid, ceramic metal, full metal | | Design options | Matte and glossy materials, foil | Colored core, decorated edge, colored mag stripe, matte and glossy varnishes, 3D effects, hot stamping, holograms, metallic ink, foil, special inks, textures, translucent plastic, sustainable cards | Mechanical engraving, laser engraved personalization, knock-out capability, raised matte and glossy varnishes, metallic foils, 24k gold, crystal and/or diamond embedding available on higher-end cards | ## Design guidelines To minimize approval delays, please follow these guidelines carefully. Card art must follow specific guidelines for approval by Highnote and Partner Banks. Refer to general and card network-specific guidelines when designing card art. It is important that you follow these guidelines in order to minimize approval delays. Network guidelines: - Visa: Contact your Highnote representative for Visa Product Brand Standards. - Mastercard: - Card Design Snap Shot — design guidelines PDF (see slide 6: "Card Design Essentials - Physical Cards") - Mastercard Design Center Library — card art asset library ### Card design tips Highnote recommends the design templates in the Arroweye Resource Library. When designing your card art, we recommend keeping designs simple. Here are some general recommendations for card designs: - All fonts must be outlined to ensure compatibility with all printers and devices. - All images must be embedded. - Card art file must be layered. Put each design element in a separate layer. - The card needs to have bleed. - Dual Interface logo needs to be on card if the card is Dual Interface. #### Background tips #### Logo tips ### General guidelines Keep the following general guidelines in mind when designing physical cards: - On-demand cards are printed in Cyan, Magenta, Yellow, and Key (CMYK). Designing in RGB may cause inaccurate colors during printing. - Premium cards are printed in CMYK or Pantone Matching System (PMS). Designing in RGB may cause inaccurate colors during printing. - Black should be set to . - The front and back of your card design may be either horizontal or vertical. - The minimum type size is 6pt for optimal legibility. - Avoid border designs that follow the edge of the card. - Keep logos and text 3/32” away from the edges of the card and from required elements, for example, the card’s magnetic stripe, hologram, and signature panel. ## Personalization Card personalization refers to a card’s dynamic content. Personalization may be on the front or back of the card, in any combination. Personalization includes: - Cardholder name - Business name (optional) - Primary Account Number (16-digit card number) - Expiration date ## On-demand card guidelines To avoid delays, be sure to use all design templates from the Arroweye resource library. ## Design approval Card design is subject to approval by both Highnote and the sponsor bank as outlined in Marketing and Collateral. When you are ready to submit the final artwork, send files to collateral-review@highnote.com. ### File formats Send your physical card design file in Adobe Illustrator format using any of the following file types: , , or . ## Packaging materials You can design and customize packaging materials to send your cards to account holders. The following packaging material options are available for all card types: - Mailers - Burgopak sliders - Customized packaging ### Mailer **Warning:** Your bank partner may have special requirements, for example, around "Member FDIC" language. Also, some partners require that you include the term, "Powered by Highnote". Contact the Highnote Implementation team for help with your requirements. When using a mailer, cards are sent to account holders in envelopes within a trifold insert. You can customize mailers to match your brand. Refer to the following guidelines for customizing mailers: - Mailers are printed on white paper stock with 3/16” whitespace on all edges - Do not support bleeds - Use vector and PDF file types - White knockouts are added in the address area To create your mailer, use the design template from the Arroweye Resource Library. The following graphic is an example of the front of a mailer insert inside an envelope: The following graphic is an example of a full mailer insert: --- URL: https://docs.highnote.com/docs/issuing/cards/design/tokenized-cards Title: Digital Wallet Tokenized Card Design Section: Issuing Description: Design tokenized card art for Apple Pay and Google Wallet with logo and icon specifications, network approval requirements, and testing guidance. ## Overview Tokenized cards are provisioned to digital wallets such as Apple Pay or Google Wallet. Before a card product may be utilized with a digital wallet, you must work with Highnote to ensure all aspects of the program are in order, properly formatted, and approved to facilitate tokenization by the Partner Bank and payment network. ## Design guidelines Card art must follow specific guidelines for approval by Highnote and Partner Banks. Some guidelines apply to all digital cards, while others apply only to cards issued using Visa or Mastercard. Refer to general and card network-specific guidelines when designing card art. - Visa: Digital Card Art - Mastercard: - Card Design Snap Shot — design guidelines PDF (see slide 7: "Digital Tokenized Cards - What’s Important To Know?" and slide 9: "Things to Know") - Mastercard Design Center Library — card art asset library ### Card design tips When designing card art for tokenized cards, we recommend keeping designs simple. For network-specific cards, refer to the guidance from Visa and Mastercard linked to above. For all digital cards, refer to the following design tips: #### Logo - SVG (up to 1MB) or PNG (up to 3MB) file type - Hex color format - 1372 x 283 pixels #### Icon - PNG image - Hex color format - 100 x 100 pixels ### General guidelines Refer to the following general guidelines when designing tokenized card art: - Digital cards must have rounded corners. - Only absolute pixels, not the image resolution (e.g., 72ppi), are relevant. - Do not include shading or any three-dimensional elements in your tokenization assets. - Card art must not include any of the following variable elements: - Cardholder name - PAN - Expiration date - Labels describing embossed/printed attributes - Representations of magnetic stripe or EMV chip contacts - Static pictures of dynamic elements such as holograms ## Design approval Card design is subject to approval by Highnote and the Partner Bank as outlined in Marketing and Collateral. When you are ready to submit final artwork, send your card art files to collateral-review@highnote.com. ## Testing Following approval and authorization, Highnote will work alongside you to test your tokenized card before production. The testing process involves tokenizing allowed listed cards with each wallet provider you plan to support to ensure the tokenized cards and notifications appear as desired. ## Launch After successful testing, you are ready to launch your tokenized card and enable digital wallet access for your customers! --- URL: https://docs.highnote.com/docs/issuing/cards/design/virtual-cards Title: Virtual Card Design Section: Issuing Description: Design virtual card art for online purchases. Covers Visa and Mastercard brand mark requirements, PAN and CVV display, and single-use or multi-use options. ## Overview This page provides guidance for designing card art for virtual cards. A virtual card is a payment card that exists only in virtual form. Common uses are online purchases, subscriptions, or temporary payments. Virtual cards can be single-use or multi-use. ## Supported networks Highnote supports issuing virtual cards on the following card networks: - Visa - Mastercard ## General guidelines Highnote recommends displaying virtual card designs on a neutral background. ### Visa guidelines Visa virtual cards require the following elements: | Element | Details | | :------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------- | | Brand mark | Must be 3 mm from card edge and in Title Case. | | Cardholder name | | | PAN | Must be full 16 digit PAN | | CVC/CVV | 3-digit Card Validation Code or Value | | Expiration date | | | Virtual Limited Use | (Optional) If applicable, add: "Visa Virtual Account" or "Virtual Account". Must be in Title Case. | #### Limited use Visa cards You must add a limited use disclaimer in your card holder materials or application to communicate account restrictions, e.g., card not-present scenarios. Displaying “Limited Use” (or local language equivalent) on Visa Virtual reference cards is optional. When used, it should appear in a size and location that is clearly visible or, be in materials provided to the card holder. ### Mastercard guidelines Mastercard virtual cards require the following elements: | Element | Details | | :----------------- | :----------------------------------------------------------------------------------------------------------------- | | Brand mark | Must be one of: Mastercard symbol, Mastercard Premium brand mark, Maestro, or Cirrus. Must be 3 mm from card edge. | | Product Identifier | Must be 8.8 mm in size, and at least 4 mm from brand mark | | PAN | Must be full 16 digit PAN | | CVC/CVV | 3-digit Card Validation Code or Value | | Expiration date | | For additional card art references, see the Mastercard Design Center Library. --- URL: https://docs.highnote.com/docs/issuing/cards/issue/add-cards-to-digital-wallets Title: Add Cards to Digital Wallets Section: Issuing Description: Add payment cards to Apple Pay or Google Wallet using push provisioning, including provisioning decline controls. Manage digital wallet tokens, handle identity verification, and simulate provisioning in Test. ## Overview Digital wallets enable your customers to store a card's primary account number (PAN) as a tokenized digital account number. This token is presented to the merchant in place of the PAN, so the merchant cannot see or retain the payment card's information. You can provision payment cards to digital wallets such as Apple Pay, Google Wallet, and Samsung Pay. Payment cards are added to digital wallets in four ways: - **Manual entry**: An account holder opens a digital wallet app on their phone and manually enters their card details. - **In-app push provisioning**: An account holder taps a software button — such as "Add to Apple Wallet" or "Add to Google Wallet" — inside your iOS or Android app, which triggers a provisioning flow native to the device. Works for virtual or physical cards. - **Apple Pay Web Push Provisioning (WPP)**: An account holder selects a card on your website and provisions it to one or more Apple devices linked to their Apple ID. - **Tap to Add**: An account holder physically taps their card to the back of an NFC-enabled phone, which prompts the digital wallet to add it. Requires a physical Visa or Mastercard card. The four methods differ in where the action happens, what your team needs to build, and what kind of card the cardholder uses: | Method | Cardholder start | What you build | Card constraint | | :---------------------------------- | :------------------------------- | :---------------------------------------------------------------------------------------------------- | :-------------------------- | | **Manual entry** | Their wallet app | Nothing | None | | **In-app push provisioning** | Your iOS or Android app | An app integration with the wallet vendor's SDK plus the matching Highnote push provisioning mutation | None | | **Apple Pay Web Push Provisioning** | Your website | A web frontend plus a backend call to | Apple Pay only | | **Tap to Add** | Their wallet's "Add Card" screen | Nothing | Physical Visa or Mastercard | ## Prerequisites - A Highnote account - An API key or the API Explorer - An approved tokenized card design ## Wallet provider enums The Highnote API has two wallet-related enums that serve different purposes: | Enum | Values | Purpose | | :------------------------------------------------------------------------ | :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [](/docs/api-reference/enum#DigitalWalletProvider) | , , | Specifies which digital wallets your card art is designed for.
Used when creating or updating a digital card profile. | | [](/docs/api-reference/enum#WalletProviderType) | , | Identifies wallet provider during push provisioning. Used in mutation [](/docs/api-reference/mutation#addPaymentCardToGooglePayByDevicePushProvisioning) | Apple Pay has a dedicated push provisioning protocol and mutation, [](/docs/api-reference/mutation#addPaymentCardToApplePayByDevicePushProvisioning). Google Pay and Samsung Pay share a provisioning path, and use to distinguish them. ## Apple Pay prerequisites You must complete the following steps before developing a push provisioning project. The Highnote team will assist with each step as you prepare for your push provisioning implementation: 1. Your program must be in implementation or launched with a partner bank. During this process, your program undergoes due diligence with the partner bank, a BIN is assigned, and the tokenization request is prepared to be submitted to the network. _You must complete this step before providing Apple Pay with your card program details._ 2. All Digital Wallet assets should be submitted and approved. You can find the list of assets here: Digital Wallet Designs 3. Sign the Apple Pay Terms and Conditions and list Highnote as your program manager. 4. Email applepayentitlements@apple.com and implementation-team@highnote.com with the following information: - A request to enable Apple Pay push provisioning in your app - Your App name as it appears on AppStore Connect - Your Developer team ID - Your ADAM ID (Example: 13254705253) - Your Bundle ID (Example: com.company.appname) - Application Launch URL (Example: myapp://apple_wallet) - Whether you already have an app published to the App Store After receiving a response from the Apple Pay Entitlements team, you can expect the following questions: - Who is the sponsor bank you work with to offer your debit or credit product? - How do you plan to use Apple Pay? For example, your application provides users a method to add their card to Apple Pay directly using the _Add to Wallet_ interface. - Will you offer both physical and virtual cards? Answer _yes_ or _no_ depending on your card product details. - What are your proposed use cases for in-app (push) provisioning? For example, you are adding the capability to add a card to Apple Pay directly from your application. - Will you use a third party in the development and/or management of Apple Pay? If yes, provide the third-party company name. - In what country is your business headquarters located? Provide your headquarters' location. - What is your Team Name? Provide the name of your company or division. After completing the previous steps, you can access Apple Pay's Wallet API documentation for more information on building your push provisioning implementation. ## Google Wallet prerequisites Google requires you to complete the following steps before developing a push provisioning project. The Highnote team will assist with each step as you prepare for your push provisioning implementation: 1. Apply for Google Wallet documentation access. 2. Define package name for Activation Method. For example, . 3. Define action for Activation Method. For example, . 4. Define package name for App Launching. For example, . 5. Define action for App Launching. For example, . 6. Submit Google's Push Provisioning API Access request form. After submitting the request form, you will receive a response prompting you to provide more information to describe your company. The Highnote team will assist with providing answers to additional information requests. You can expect the following responses: - Select the option that best describes your company. For example, you might select a financial company or card issuer operating under a BIN Sponsor. - Does your company have a signed CTA with Google? - Does your BIN/Sponsor or Program Manager have a signed CTA agreement with Google? - Name of program manager: For this response, you would provide the answer of _Highnote_. - App Package name - Launch date - Please select the appropriate network(s): Visa or Mastercard After completing the previous steps, you can complete Google's Push Provisioning API UX Review Request. ## Next steps After completing the prerequisites for the digital wallets you wish to support, the Highnote team secures payment network push provisioning approval and establishes a kickoff meeting with your development team. Google provides a standard solution that your development team can utilize. See Google's SDK releases for more information. ## Apple Pay in-app push provisioning {#apple-pay-push-provisioning} The Apple Pay push provisioning process validates the following when an account holder adds a payment card to their Apple Wallet: - The provided is valid - The payment card has a status of - The payment card is allowed to be provisioned If any of the above criteria fails validation, the request is rejected. If all validations pass, the API returns the response required by Apple's SDK for provisioning the card to the Apple Wallet. ### User experience You must add an "Add to Apple Wallet" call to action in your iOS app that uses the mutation . Apple provides guidelines and assets for the button. ### Apple Wallet provisioning experience The following graphic is an example of an Apple Pay push provisioning user interface (UI) experience: ### Provisioning flow The following graphic displays the flow of data during the Apple Pay push provisioning process: ## Apple Pay Web Push Provisioning Apple Pay Web Push Provisioning (WPP) lets an account holder provision a card to one or more Apple devices linked to their Apple ID directly from a supported web browser. WPP is appropriate when your subscriber experience originates on the web rather than from an iOS app — for example, an account-management portal or a card-launch landing page. WPP is supported for Visa and Mastercard products. Your Highnote representative will work with you to plan and launch your WPP use case. ### Apple Pay Web Push Provisioning prerequisites Before launching WPP, complete the following: 1. Complete all Digital Wallet Tokenization design and configuration steps described in Tokenized card design and the Apple Pay prerequisites section above. 2. Successfully complete either manual or in-app push provisioning with cards from your product. WPP cannot be your first provisioning surface — it builds on a working DWT integration. 3. Receive sign-off from Apple for your WPP use case. 4. Integrate with Highnote's WPP API as described below. 5. Build, host, and test a website that provides the user experience described in the next section. 6. Receive launch sign-off from Apple. Contact your Highnote representative for non-production environment details, the assigned by Apple, and the "Add to Apple Wallet" website button assets. ### User experience Your website must provide the following user experience: 1. The cardholder signs in to your site to identify their account. 2. The cardholder initiates WPP by selecting one of their cards to provision. 3. Your website displays Terms and Conditions, which the cardholder must accept. 4. A pop-up browser window with a self-contained Apple sign-in experience (within Apple's domain) appears, where the cardholder signs in with their Apple ID. 5. After signing in, the cardholder chooses one or more devices linked to their Apple ID to provision the card to, then confirms the provisioning result on each target device. 6. Your website displays the result of the provisioning request for each selected Apple device. ### Generate the provisioning token Call the mutation from your website's backend to obtain a JSON Web Signature (JWS) object. The JWS is consumed by Apple's JavaScript library to initialize the WPP session. The mutation validates that the is valid, the card is , and the card is allowed to be provisioned. If validation fails, the request is rejected. The response contains: - — the signed token your website passes to the Apple JavaScript library. Includes , , , and a (key identifier). - — the provisioning session state identifier. - — the token expiration time in ISO 8601 format. Generate a fresh token if the cardholder reaches the "Add to Apple Wallet" button after this time. ### Integrate with Apple's JavaScript library After your backend issues the JWS, your website integrates with Apple's JavaScript library to render the "Add to Apple Wallet" button and handle the provisioning flow. The integration consists of three parts: - **Place the button.** Use the "Add to Apple Wallet" assets provided by your Highnote representative. Reference Apple's Add to Apple Wallet button guidelines for sizing and placement. - **Initialize the library.** Call with the Apple assigned during your WPP implementation, the production domain , the DOM of your button, a callback that fetches the JWS from your backend, and a callback that receives the per-device provisioning result. - **Handle the result.** The is invoked with a status code indicating success, partial success, timeout, or failure for each selected device. See JavaScript status codes for the full list. Apple's Web Provisioning JavaScript documentation is the authoritative reference for the JavaScript implementation. ### JavaScript status codes Your callback must handle the following status codes returned by Apple's JavaScript library. #### 1xx — interim | Code | Description | | :---- | :--------------------------------------------------------------------------------------------------------------------------------------------- | | 10001 | The selected device connected after the web provisioning. The UI timed out, and the credential may be provisioned on the device. | | 10002 | The Issuer was contacted to begin provisioning for the selected device. The UI timed out, and the credential may be provisioned on the device. | #### 2xx — success | Code | Description | | :--- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 200 | Successful. Provisioning succeeded on all devices selected by the cardholder. | | 201 | Status unknown. Apple reached out to the device(s), but the device(s) didn't respond to the notifications within the UI timeout threshold. The credential might still provision after the timeout. | | 202 | No eligible devices. | | 206 | Partially successful. Provisioning succeeded on some of the devices selected by the cardholder. Not applicable if the flow is constrained to a single device. | #### 4xx — client errors | Code | Description | | :---- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | 403 | User interaction failed. The Apple ID sign-in failed. | | 406 | The Issuer rejected or failed the provisioning attempt. | | 408 | Timeout. No result was obtained — the cardholder may have closed the pop-up window without interaction or moved to another app or window. See also code 444. | | 40801 | Timeout. The Apple UI failed to load. | | 412 | Bad JWS. | | 41201 | Bad JWS. Expired. | | 444 | Cardholder dismissed the page without completing the flow. The system may sometimes return a 408 instead if it can't identify this scenario. | #### 5xx — server errors | Code | Description | | :---- | :----------------------------------------------- | | 500 | Error. An unknown error on Apple systems. | | 50001 | Error. Apple failed to process the provisioning. | ## Google Wallet in-app push provisioning {#google-wallet-push-provisioning} The Google Wallet push provisioning process validates the following: - The provided is valid - The payment card has a status of - The payment card is allowed to be provisioned If any of the above criteria fails validation, the request is rejected. If all validations pass, the API returns the response required by Google SDK for provisioning the card to the Google Wallet. ### User experience You must add a "Save to Phone" call to action in your Android app that uses the mutation . Google provides assets for the button. ### Google Wallet provisioning experience The following graphic is an example of a Google Wallet push provisioning user interface (UI) experience: ### Provisioning flow The following graphic displays the flow of data during the Google Wallet push provisioning process: ## Provisioning decline controls Highnote offers a digital card profile control that can make digital wallet provisioning stricter (never more permissive) than the wallet provider recommends. By default, when a cardholder adds a card to a digital wallet, the wallet provider (via the payment network) returns a recommendation to approve, request additional verification, or decline the provisioning attempt, plus one or more reason codes describing the risk it observed. Highnote follows that recommendation, unless your digital card profile has a stricter provisioning control enabled. When enabled, the control declines a provisioning attempt on a disqualifying reason, even one the wallet provider would approve. The control is off by default: with no reasons configured, provisioning behaves exactly as before. In the current release, provisioning decline reasons are configured by Highnote per digital card profile rather than through a subscriber-facing API. Contact your Highnote representative to enable or adjust this control. ### How it works 1. A cardholder attempts to add a card to a digital wallet. 2. The wallet provider, through the network, returns a recommendation and a set of reason codes. 3. If any reason your digital card profile is configured to decline on is present in that set, Highnote declines the provisioning attempt, regardless of the wallet provider's recommendation. 4. The decline is recorded on the digital wallet token with an issuer decline reason of . The wallet provider's own recommendation and reasons remain recorded separately. The control overrides a recommendation to approve or request additional verification. It does not affect an attempt the wallet provider already declines — a network decline stands on its own. ### Decline reasons A digital card profile can be configured to decline on any of the following wallet-provider reasons: | Reason | The wallet provider ... | | :------------------------- | :--------------------------------------------------------------------- | | | flagged the provisioning attempt as high risk or suspected fraud. | | | reported suspicious activity on the account or device. | | | reported a low device trust score. | | | reported a low account trust score. | | | reported too many recent provisioning attempts for the cardholder. | | | reported that the account or the account-card relationship is too new. | ### What a cardholder sees When a provisioning attempt is declined, the card is not added to the wallet, and the cardholder sees the wallet's standard "could not add card" outcome. This control introduces no new cardholder-facing notification. ### Observe a decline A decline caused by the provisioning decline control is recorded on the digital wallet token. When you query the token's , the issuer decline reason appears in , alongside the wallet provider's own reasons in . See View token status and details to look up a token. That example doesn't select , so query that field directly to see the decline reasons above. ## Manage digital wallet tokens When a payment card is added to a digital wallet, a token provisioning request is sent to the digital wallet, network, and Highnote. The request may go to the state, which requires your account holder to verify their identity. The following verification methods may be configured for your product: - **Email**: A passcode is sent by Highnote to the customer's email, which the customer enters into the digital wallet. - **SMS**: A passcode is sent by Highnote to the customer's mobile phone, which the customer enters into the digital wallet. The following states are associated with a digital wallet token provisioning request: | Token State | Description | | :--------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | | | The account holder has requested a digital wallet token. | | | The account holder successfully tokenized the payment card without additional identity verification. The token is and ready for transaction use. | | | The payment card cannot be tokenized and may be due to the payment card's state or invalid data provided. | | | The wallet provider, network, or issuer has requested additional identity details from the account holder to validate their identity. | For information on how existing tokens behave when a card is reissued or closed, see Digital wallet tokens on reissue and Digital wallet tokens on close. ### Find a token You can search for digital wallet tokens on a given payment card or a digital wallet token's associated payment card using the following query: ### Suspend token Account holders can suspend a token temporarily or a customer support agent may suspend a token if additional verification is required by the account holder. Suspended tokens may have the following reasons associated with the token: | Suspended Reason | Description | | :------------------------ | :---------------------------------------------------------------------------- | | | Device is reported as lost. | | | Device is reported as stolen. | | | Fraudulent transactions have been reported by Highnote or the account holder. | | | Any other reason for suspending the card digital wallet token. | Use the following mutation to suspend a token: ### Unsuspend token You may provide your customer support agents or your account holders the ability to reactivate or unsuspend a token after it has been suspended. Suspended tokens that have been unsuspended or reactivated may have the following reasons associated with the token: | Unsuspend Reason | Description | | :---------------------------- | :------------------------------------------------------------------------------------------------------------------------ | | | A lost or stolen device has been found or recovered. | | | After reviewing transaction history, the account holder or Highnote confirmed that there were no fraudulent transactions. | | | Any other reason for reactivating the card digital wallet token. | Use the following mutation to unsuspend a token: ### Terminate token A token may be terminated by your customer support agents or account holders. Once a token is terminated, the token is deleted and can no longer be used to transact. A new token must be created once it is terminated. Terminated tokens may have the following reasons associated with the token: | Termination Reason | Description | | :------------------------ | :---------------------------------------------------------------------------- | | | Account holder has been deleted. | | | Device is reported as lost. | | | Device is reported as stolen. | | | Fraudulent transactions have been reported by Highnote or the account holder. | | | Any other reason for terminating the card digital wallet token. | Use the following mutation to terminate a token: ### View token status and details Find the status of a token and its historical state transitions using the following query: ## Simulate digital wallet token provisioning You can use Highnote's digital wallet token provisioning simulation to generate and activate a digital wallet token, and test token status events. For more information, see Simulate Digital Wallet Token Provisioning. ### GraphQL: AddPaymentCardToApplePayByDevicePushProvisioning Query: mutation AddPaymentCardToApplePayByDevicePushProvisioning( $input: AddPaymentCardToApplePayByDevicePushProvisioningInput! ) { addPaymentCardToApplePayByDevicePushProvisioning(input: $input) { __typename ... on PaymentCardDigitalWalletTokenApplePayDevicePushProvisioning { encryptedPassData activationData ephemeralPublicKey createdAt paymentCard { __typename id last4 } } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "paymentCardId": "MC4zOC5kd3RfMTIzNDU2Nzg5MA==", "deviceType": "MOBILE", "certificates": [ "MIIH/TCCBeWgAwIBAgIQaBYE3/M08XHYCnNVmcFBcjANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xETAPBgNVBAoMCFNTTCBDb3JwMS4wLAYDVQQDDCVTU0wuY29tIEVWIFNTTCBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIzMB4XDTIwMDQwMTAwNTgzM1oXDTIxMDcxNjAwNTgzM1owgb0xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxFjAUBgNVBAUTDU5WMjAwODE2MTQyNDMxFDASBgNVBAMMC3d3dy5zc2wuY29tMR0wGwYDVQQPDBRQcml2YXRlIE9yZ2FuaXphdGlvbjEXMBUGCysGAQQBgjc8AgECDAZOZXZhZGExEzARBgsrBgEEAYI3PAIBAxMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHheRkbb1FCc7xRKstwK0JIGaKY8t7JbS2bQ2b6YIJDgnHuIYHqBrCUV79oelikkokRkFvcvpaKinFHDQHUpWEI6RUERYmSCg3O8Wi42uOcV2B5ZabmXCkwdxY5Ecl51BbM8UnGdoAGbdNmiRmSmTjcs+lhMxg4fFY6lBpiEVFiGUjGRR+61R67Lz6U4KJeLNcCm07QwFYKBmpi08gdygSvRdUw55Jopredj+VGtjUkB4hFT4GQX/ght69Rlqz/+8u0dEQkhuUuucrqalm", "MIIH/TCCBeWgAwIBAgIQaBYE3/M08XHYCnNVmcFBcjANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xETAPBgNVBAoMCFNTTCBDb3JwMS4wLAYDVQQDDCVTU0wuY29tIEVWIFNTTCBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIzMB4XDTIwMDQwMTAwNTgzM1oXDTIxMDcxNjAwNTgzM1owgb0xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxFjAUBgNVBAUTDU5WMjAwODE2MTQyNDMxFDASBgNVBAMMC3d3dy5zc2wuY29tMR0wGwYDVQQPDBRQcml2YXRlIE9yZ2FuaXphdGlvbjEXMBUGCysGAQQBgjc8AgECDAZOZXZhZGExEzARBgsrBgEEAYI3PAIBAxMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHheRkbb1FCc7xRKstwK0JIGaKY8t7JbS2bQ2b6YIJDgnHuIYHqBrCUV79oelikkokRkFvcvpaKinFHDQHUpWEI6RUERYmSCg3O8Wi42uOcV2B5ZabmXCkwdxY5Ecl51BbM8UnGdoAGbdNmiRmSmTjcs+lhMxg4fFY6lBpiEVFiGUjGRR+61R67Lz6U4KJeLNcCm07QwFYKBmpi08gdygSvRdUw55Jopredj+VGtjUkB4hFT4GQX/ght69Rlqz/+8u0dEQkhuUuucrqalm" ], "nonce": "9c023092", "nonceSignature": "4082f883ae62d0700c283e225ee9d286713ef74456ba1f07376cf17d71bf0be013f926d486619394060ced56030f41f84df916eaab5504e456a8530dc9c821f6ed3e3af62b5d8f3e4a22ca2018670fee4e" } } Expected Result: { "data": { "addPaymentCardToApplePayByDevicePushProvisioning": { "__typename": "CardDigitalWalletTokenApplePayPushProvisioning", "encryptedPassData": "IHvigJx0b2tlblVuaXF1ZVJlZmVyZW5jZUluY2x1ZGVkIjoiWFhYWFgiLAogICAgIOKAnHNpZ25hdHVyZUFsZ29yaXRobSI6IlhYWFhYWFhYIiwKICAgICDigJxzaWduYXR1cmUiOiJYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWCIsCiAgICAg4oCcZXhwaXJhdGlvbkRhdGVJbmNsdWRlZCI6IlhYWFgiCn0=", "activationData": "ewoicGFuOiAiNDExMTExMTExMTExMTExMSIsCiJleHAiOiAiMTIyNiIKfQ====", "ephemeralPublicKey": "EPHEMERAL-PUBLIC-KEY", "createdAt": "2021-07-07T23:22:30.475Z", "paymentCard": { "__typename": "PaymentCard", "id": "MC4zOC5kd3RfMTIzNDU2Nzg5MA==", "last4": "1234" } } }, "extensions": { "requestId": "some-request-id" } } ### GraphQL: GenerateAppleWebPushProvisioningToken Query: mutation GenerateAppleWebPushProvisioningToken( $input: GenerateAppleWebPushProvisioningTokenInput! ) { generateAppleWebPushProvisioningToken(input: $input) { __typename ... on AppleWebPushProvisioningToken { jws { protected payload signature header { kid } } state expiresAt } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "paymentCardId": "" } } Expected Result: { "data": { "generateAppleWebPushProvisioningToken": { "__typename": "AppleWebPushProvisioningToken", "jws": { "protected": "eyJ4NXQjUzI1NiI6IlpXSmxPV1ZoWlRRNU5HUXpNalV5TjJNMU4yTTRZMlEzTmpBNFkyVXhNakJqWWpFME5URXdZMk16TlRBM04yRmxObVpsTkRZNU1UVTFZMlJoTVdZMlpnIiwiY3R5IjoiYXBwbGljYXRpb24vY3JlZGVudGlhbDtjaGFyc2V0PXV0Zi04IiwidHlwIjoiSk9TRStKU09OIiwiYWxnIjoiRVMyNTYifQ", "payload": "eyJhdWQiOiJBcHBsZSIsInN1YiI6InByb3Zpc2lvbmluZ1RhcmdldCIsImxpZCI6ImVuLVVTIiwiaXNzIjoiRGVtb0NhcmRDb25maWcxIiwiZXhwIjoxNzU3OTcxNzA0NjgwLCJpYXQiOjE3NTc5NjgxMDQ2ODAsImFpZCI6Ijk3NzdlZWE5ZjNjNGUxMzhiN2Y2ODJlMjUxMDllNTAwIiwianRpIjoiOTI3MjExZjAtODc5MC0xNzY5LWFiOTAtNmVkNDhmYTk2ODUxIn0", "signature": "99YU0TZ4n8XLbbeOsYttEq_LJjzr2VstlIJPXuKnZSg_Ktey9XwHYn__0JuQykmv5IyuLN_lqU7ySlwdgUCjbQ", "header": { "kid": "689ac97c-b566-473e-9e52-1b1caae187a2" } }, "state": "927211f0-8790-176a-ab90-6ed48fa96851", "expiresAt": "2026-09-15T21:28:24.680Z" } }, "extensions": { "requestId": "" } } ### GraphQL: AddPaymentCardToGooglePayByDevicePushProvisioning Query: mutation AddPaymentCardToGooglePayByDevicePushProvisioning( $input: AddPaymentCardToGooglePayByDevicePushProvisioningInput! ) { addPaymentCardToGooglePayByDevicePushProvisioning(input: $input) { __typename ... on PaymentCardDigitalWalletTokenGooglePayPushProvisioning { cardholderName { formattedName title givenName middleName familyName suffix } billingAddress { streetAddress extendedAddress locality region countryCodeAlpha3 postalCode } displayName network opaquePaymentCard paymentCard { __typename id last4 } tokenServiceProvider createdAt } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "paymentCardId": "", "deviceType": "MOBILE", "walletDetails": { "clientWalletProvider": "GOOGLE_PAY", "clientWalletAccountIdentifier": "1CFA8B242688E000", "clientDeviceIdentifier": "ed6abb56323ba656521ac476" } } } Expected Result: { "data": { "addPaymentCardToGooglePayByDevicePushProvisioning": { "__typename": "CardDigitalWalletTokenGooglePayDevicePushProvisioning", "cardholderName": { "formattedName": "John M Deo", "familyName": "Deo", "givenName": "John", "middleName": "M" }, "billingAddress": { "streetAddress": "123 main st", "extendedAddress": "Suite # 200", "postalCode": "94102", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" }, "displayName": "Subscriber App", "network": "MASTERCARD", "opaquePaymentCard": "IHvigJx0b2tlblVuaXF1ZVJlZmVyZW5jZUluY2x1ZGVkIjoiWFhYWFgiLAogICAgIOKAnHNpZ25hdHVyZUFsZ29yaXRobSI6IlhYWFhYWFhYIiwKICAgICDigJxzaWduYXR1cmUiOiJYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWCIsCiAgICAg4oCcZXhwaXJhdGlvbkRhdGVJbmNsdWRlZCI6IlhYWFgiCn0=", "paymentCard": { "__typename": "PaymentCard", "id": "", "last4": "1234" }, "tokenServiceProvider": "MASTERCARD", "createdAt": "2022-07-07T23:22:30.475Z" } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { id bin last4 expirationDate network status formFactor cardProductApplication { ... on Node { id } ... on AccountHolderCardProductApplication { id applicationState { status } } } cardDigitalWalletTokens(first: 10) { pageInfo { hasNextPage } edges { cursor node { __typename ... on CardDigitalWalletToken { id status createdAt updatedAt requesterName cardDigitalWalletTokenStateTransitions(first: 10) { pageInfo { hasNextPage } edges { cursor node { __typename ... on CardDigitalWalletTokenStateTransition { state reason createdAt updatedAt } } } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "bin": "531592", "last4": "4689", "expirationDate": "2026-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "formFactor": "PHYSICAL", "cardProductApplication": null, "cardDigitalWalletTokens": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "CardDigitalWalletToken", "id": "", "status": "TERMINATED", "createdAt": "2022-06-08T16:06:44.744Z", "updatedAt": "2022-06-08T17:58:22.930Z", "requesterName": "Google Pay", "cardDigitalWalletTokenStateTransitions": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "CardDigitalWalletTokenStateTransition", "state": "TERMINATED", "reason": "ACCOUNT_HOLDER_DELETED", "createdAt": "2022-06-08T17:58:22.889Z", "updatedAt": "2022-06-08T17:58:22.954Z" } }, { "cursor": "some-cursor", "node": { "__typename": "CardDigitalWalletTokenStateTransition", "state": "SUSPENDED", "reason": "DEVICE_LOST", "createdAt": "2022-06-08T16:07:36.701Z", "updatedAt": "2022-06-08T16:07:36.734Z" } }, { "cursor": "some-cursor", "node": { "__typename": "CardDigitalWalletTokenStateTransition", "state": "ACTIVE", "reason": null, "createdAt": "2022-06-08T16:07:17.742Z", "updatedAt": "2022-06-08T16:07:17.756Z" } }, { "cursor": "some-cursor", "node": { "__typename": "CardDigitalWalletTokenStateTransition", "state": "REQUESTED", "reason": null, "createdAt": "2022-06-08T16:06:44.749Z", "updatedAt": "2022-06-08T16:06:44.811Z" } } ] } } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: SuspendCardDigitalWalletToken Query: mutation SuspendCardDigitalWalletToken( $input: SuspendCardDigitalWalletTokenInput! ) { suspendCardDigitalWalletToken(input: $input) { __typename ... on CardDigitalWalletToken { id status createdAt updatedAt requesterName cardDigitalWalletTokenStateTransitions { edges { node { state reason updatedAt createdAt } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "cardDigitalWalletTokenId": "", "reason": "DEVICE_LOST" } } Expected Result: { "data": { "suspendCardDigitalWalletToken": { "__typename": "CardDigitalWalletToken", "id": "", "status": "SUSPENDED", "createdAt": "2022-06-12T07:30:18.346Z", "updatedAt": "2022-06-12T07:30:46.748Z", "requesterName": "Google Pay", "cardDigitalWalletTokenStateTransitions": { "edges": [ { "node": { "state": "SUSPENDED", "reason": "DEVICE_LOST", "updatedAt": "2022-06-12T07:30:46.753Z", "createdAt": "2022-06-12T07:30:46.717Z" } }, { "node": { "state": "ACTIVE", "reason": null, "updatedAt": "2022-06-12T07:30:34.455Z", "createdAt": "2022-06-12T07:30:34.446Z" } }, { "node": { "state": "REQUESTED", "reason": null, "updatedAt": "2022-06-12T07:30:18.729Z", "createdAt": "2022-06-12T07:30:18.362Z" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: UnsuspendCardDigitalWalletToken Query: mutation UnsuspendCardDigitalWalletToken( $input: UnsuspendCardDigitalWalletTokenInput! ) { unsuspendCardDigitalWalletToken(input: $input) { __typename ... on CardDigitalWalletToken { id status requesterName cardDigitalWalletTokenStateTransitions { edges { node { state reason updatedAt createdAt } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "cardDigitalWalletTokenId": "", "reason": "NON_FRAUDULENT_TRANSACTIONS" } } Expected Result: { "data": { "unsuspendCardDigitalWalletToken": { "__typename": "CardDigitalWalletToken", "id": "", "status": "ACTIVE", "requesterName": "Google Pay", "cardDigitalWalletTokenStateTransitions": { "edges": [ { "node": { "state": "ACTIVE", "reason": "NON_FRAUDULENT_TRANSACTIONS", "updatedAt": "2022-06-12T07:32:41.837Z", "createdAt": "2022-06-12T07:32:41.818Z" } }, { "node": { "state": "SUSPENDED", "reason": "DEVICE_LOST", "updatedAt": "2022-06-12T07:30:46.753Z", "createdAt": "2022-06-12T07:30:46.717Z" } }, { "node": { "state": "ACTIVE", "reason": null, "updatedAt": "2022-06-12T07:30:34.455Z", "createdAt": "2022-06-12T07:30:34.446Z" } }, { "node": { "state": "REQUESTED", "reason": null, "updatedAt": "2022-06-12T07:30:18.729Z", "createdAt": "2022-06-12T07:30:18.362Z" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: TerminateCardDigitalWalletToken Query: mutation TerminateCardDigitalWalletToken( $input: TerminateCardDigitalWalletTokenInput! ) { terminateCardDigitalWalletToken(input: $input) { __typename ... on CardDigitalWalletToken { id status requesterName cardDigitalWalletTokenStateTransitions { edges { node { state reason updatedAt createdAt } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "cardDigitalWalletTokenId": "", "reason": "FRAUDULENT_TRANSACTIONS" } } Expected Result: { "data": { "terminateCardDigitalWalletToken": { "__typename": "CardDigitalWalletToken", "id": "", "status": "TERMINATED", "requesterName": "Google Pay", "cardDigitalWalletTokenStateTransitions": { "edges": [ { "node": { "state": "TERMINATED", "reason": "FRAUDULENT_TRANSACTIONS", "updatedAt": "2022-06-12T07:34:20.433Z", "createdAt": "2022-06-12T07:34:20.420Z" } }, { "node": { "state": "ACTIVE", "reason": "NON_FRAUDULENT_TRANSACTIONS", "updatedAt": "2022-06-12T07:32:41.837Z", "createdAt": "2022-06-12T07:32:41.818Z" } }, { "node": { "state": "SUSPENDED", "reason": "DEVICE_LOST", "updatedAt": "2022-06-12T07:30:46.753Z", "createdAt": "2022-06-12T07:30:46.717Z" } }, { "node": { "state": "ACTIVE", "reason": null, "updatedAt": "2022-06-12T07:30:34.455Z", "createdAt": "2022-06-12T07:30:34.446Z" } }, { "node": { "state": "REQUESTED", "reason": null, "updatedAt": "2022-06-12T07:30:18.729Z", "createdAt": "2022-06-12T07:30:18.362Z" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: FindCardDigitalWalletToken Query: query FindCardDigitalWalletToken($id: ID!) { node(id: $id) { ... on CardDigitalWalletToken { __typename id status createdAt updatedAt requesterName requesterIdentifier tokenType sourceEntryMethod last4 expirationDate cardDigitalWalletTokenStateTransitions(first: 10) { edges { node { state reason createdAt updatedAt } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardDigitalWalletToken", "id": "", "status": "TERMINATED", "createdAt": "2022-06-12T07:30:18.346Z", "updatedAt": "2022-06-12T07:34:20.424Z", "requesterName": "Google Pay", "requesterIdentifier": "11223344", "tokenType": "ECOMMERCE", "sourceEntryMethod": "CARD_ON_FILE", "last4": "8744", "expirationDate": "2028-01-31T23:59:59Z", "cardDigitalWalletTokenStateTransitions": { "edges": [ { "node": { "state": "TERMINATED", "reason": "FRAUDULENT_TRANSACTIONS", "createdAt": "2022-06-12T07:34:20.420Z", "updatedAt": "2022-06-12T07:34:20.433Z" } }, { "node": { "state": "ACTIVE", "reason": "NON_FRAUDULENT_TRANSACTIONS", "createdAt": "2022-06-12T07:32:41.818Z", "updatedAt": "2022-06-12T07:32:41.837Z" } }, { "node": { "state": "SUSPENDED", "reason": "DEVICE_LOST", "createdAt": "2022-06-12T07:30:46.717Z", "updatedAt": "2022-06-12T07:30:46.753Z" } }, { "node": { "state": "ACTIVE", "reason": null, "createdAt": "2022-06-12T07:30:34.446Z", "updatedAt": "2022-06-12T07:30:34.455Z" } }, { "node": { "state": "REQUESTED", "reason": null, "createdAt": "2022-06-12T07:30:18.362Z", "updatedAt": "2022-06-12T07:30:18.729Z" } } ] } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/cards/issue/create-card-profile Title: Create Card Profile Section: Issuing Description: Create card profiles to control the appearance and behavior of virtual, physical, and tokenized cards. Apply a card profile set intent and associate profiles with card products. ## Overview **Card profiles** define the design and behavior of payment cards. Profiles are grouped into **card profile sets** — one virtual, one digital, and one physical profile per set. The **card profile set's intent** determines which profile types are available: allows only virtual, allows virtual and digital, and allows all three. **Payment cards** are issued from a profile set and inherit its profiles. Payment cards are accessed through **access devices** — the form factor a cardholder uses to make a payment, such as an app, digital wallet, plastic card, or embedded device like a wristband. ## Use cases Card profiles extend the flexibility of the Highnote platform by enabling several use cases for customizing and optimizing your card program. Refer to the following table of use cases and examples: | Use case | Example | | :--------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- | | Issue cards across multiple BIN types | A card program configured with dedicated BINs for specific customers, allowing for the tracking of transactions separately. | | Manage multiple sets of assets like logos and brand colors | Offer co-brand partnerships or different card designs for your account holders to choose from. | | Different card experiences for different customer segments | Offer metal cards to qualifying premium cardholders. | | Multiple card behavior configurations | Configure fleet-specific prompts for issued cards or purchase restrictions for each customer. | | Issue cards to embedded devices | Load virtual cards onto wristbands or other wearables via a Highnote-certified personalization vendor. | ## Card profiles To create a card profile, you must first submit your card art files to Highnote. The team will work with you during implementation to create your card profiles and assign them to a card profile set. Card profiles control the look, feel, and performance of payment cards issued through your card program. They define how your payment cards appear and behave in digital wallets, within your application, and in person. They also track the approval process required by the bank and payment network for issuing payment cards. Highnote offers three types of card profiles. - **Virtual cards**: Cards that are displayed in an app or website and used for online purchases. By default, all payment cards begin as virtual cards. - **Tokenized cards**: Cards that are provisioned to an account holder’s digital wallet, such as Apple Pay or Google Wallet. - **Physical cards**: Cards that are printed and used for in-person transactions. Highnote offers on-demand and premium physical cards, as well as cards issued to embedded devices like wristbands. ## Card profile sets Card profile sets let you assign a card profile to a card product. A card profile set cannot be applied to more than one card product. A card profile set always includes a virtual profile (since all cards start virtual) and optionally includes a digital or physical profile, depending on the set's intent. ## Default card profile set Each card product has a default card profile set, configured by the Highnote team during implementation. When a payment card is issued without a , the card product's default set is used automatically. ## Card profile set intent A card profile set's intent is configured by the Highnote team during implementation based on the card types the program needs to issue. The intent determines which profile types the set supports. For a program that plans to issue physical cards or cards to embedded devices, the intent is set to during implementation. This enables the set for all three profile types. The intent tiers are: - - Restricted tier (can issue virtual cards only) - - Limited access tier (can issue digital and virtual cards) - - Full access tier (can issue all card types) While all cards are first issued as virtual cards, a card profile set with intent can only issue virtual cards. Issuing digital or physical cards from that card product requires a new card profile set with a broader intent. ## Find card product card profile set After the Highnote team has configured your card profiles and card profile sets, you can use the Highnote API to display them in your application or website. Use the following query to find a specific card product's card profile set: ## Find all card profile sets Use the following query to find all card profile sets across your organization: ### GraphQL: FindCardProfileSet Query: query findCardProfileSet($id: ID!) { node(id: $id) { ... on CardProfileSet { id name status intent network preferredConfiguration createdAt updatedAt cardProduct { id name usage vertical commercial } physicalCardProfiles { ... on PhysicalCardProfile { id status createdAt updatedAt paymentNetworkStatus vendorStatus vendorName cardProduct { id name usage vertical commercial } cardPersonalization { format line1 { line type } line2 { line type } physicalCardType } defaultPaymentCardShipment { courier { method signatureRequiredOnDelivery } senderDetails { name { givenName middleName familyName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } cardArt { ... on CardArtDocument { id createdAt updatedAt documentType } } } } digitalCardProfiles { ... on DigitalCardProfile { id status createdAt updatedAt cardProduct { id name usage vertical commercial } colors { backgroundColor cardDescriptorColor } cardArt { ... on DigitalCardArtDocument { cardArt { id createdAt updatedAt documentType } digitalWalletProviders } } } } virtualCardProfiles { ... on VirtualCardProfile { id status createdAt updatedAt cardProduct { id name usage vertical commercial } personalization cardArt { ... on CardArtDocument { id createdAt updatedAt documentType } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "cardProfileSet": { "id": "", "name": "Test", "status": "PENDING", "intent": "DIGITAL", "network": "VISA", "preferredConfiguration": "true", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "cardProduct": { "id": "", "name": "Test", "usage": "MULTI_USE", "vertical": "SECURED_COMMERCIAL_CREDIT", "commercial": "true" }, "digitalCardProfiles": [ { "id": "", "status": "IN_REVIEW", "bankStatus": "IN_REVIEW", "paymentNetworkStatus": "IN_REVIEW", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "cardHolderAgreementId": "", "externalId": "", "defaultProfile": "false", "cardProduct": { "id": "", "name": "Test", "usage": "MULTI_USE", "vertical": "SECURED_COMMERCIAL_CREDIT", "commercial": "true" }, "cardArt": { "documents": [ { "id": "", "status": "PENDING", "documentType": "DIGITAL_FRONT_OF_CARD", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_BACKGROUND", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_LOGO", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_ICON", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" } ], "colors": { "panColor": "rgb(255, 165, 1)", "backgrounColor": "rgb(225, 15, 38)", "cardDescriptorColor": "rgb(5, 95, 38)" }, "provider": [ "IOS", "GOOGLE" ] } }, { "id": "", "status": "IN_REVIEW", "bankStatus": "IN_REVIEW", "paymentNetworkStatus": "IN_REVIEW", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "cardHolderAgreementId": "", "externalId": "", "defaultProfile": "false", "cardProduct": { "id": "", "name": "Test", "usage": "MULTI_USE", "vertical": "SECURED_COMMERCIAL_CREDIT", "commercial": "true" }, "cardArt": { "documents": [ { "id": "", "status": "PENDING", "documentType": "DIGITAL_FRONT_OF_CARD", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_BACKGROUND", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_LOGO", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_ICON", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" } ], "colors": { "panColor": "rgb(255, 165, 1)", "backgrounColor": "rgb(225, 15, 38)", "cardDescriptorColor": "rgb(5, 95, 38)" }, "provider": [ "IOS", "GOOGLE" ] } }, { "id": "", "status": "IN_REVIEW", "bankStatus": "IN_REVIEW", "paymentNetworkStatus": "IN_REVIEW", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "cardHolderAgreementId": "", "externalId": "", "defaultProfile": "true", "cardProduct": { "id": "", "name": "Test", "usage": "MULTI_USE", "vertical": "SECURED_COMMERCIAL_CREDIT", "commercial": "true" }, "cardArt": { "documents": [ { "id": "", "status": "PENDING", "documentType": "DIGITAL_FRONT_OF_CARD", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_BACKGROUND", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_LOGO", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" }, { "id": "", "status": "PENDING", "documentType": "DIGITAL_ICON", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" } ], "colors": { "panColor": "rgb(255, 165, 1)", "backgrounColor": "rgb(225, 15, 38)", "cardDescriptorColor": "rgb(5, 95, 38)" }, "provider": [ "IOS", "GOOGLE" ] } } ], "virtualCardProfiles": [ { "id": "", "status": "PENDING", "bankStatus": "PENDING", "paymentNetworkStatus": "PENDING", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "cardHolderAgreementId": "", "defaultProfile": "false", "cardProduct": { "id": "", "name": "Test", "usage": "MULTI_USE", "vertical": "SECURED_COMMERCIAL_CREDIT", "commercial": "true" }, "cardArt": { "documents": [ { "id": "", "status": "PENDING", "documentType": "VIRTUAL_FRONT_OF_CARD", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" } ] } }, { "id": "", "status": "PENDING", "bankStatus": "PENDING", "paymentNetworkStatus": "PENDING", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "cardHolderAgreementId": "", "defaultProfile": "false", "cardProduct": { "id": "", "name": "Test", "usage": "MULTI_USE", "vertical": "SECURED_COMMERCIAL_CREDIT", "commercial": "true" }, "cardArt": { "documents": [ { "id": "", "status": "PENDING", "documentType": "VIRTUAL_FRONT_OF_CARD", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" } ] } }, { "id": "", "status": "PENDING", "bankStatus": "PENDING", "paymentNetworkStatus": "PENDING", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "cardHolderAgreementId": "", "defaultProfile": "true", "cardProduct": { "id": "", "name": "Test", "usage": "MULTI_USE", "vertical": "SECURED_COMMERCIAL_CREDIT", "commercial": "true" }, "cardArt": { "documents": [ { "id": "", "status": "PENDING", "documentType": "VIRTUAL_FRONT_OF_CARD", "documentUploadSession": "", "createdAt": "2023-07-14T16:37:55.412Z", "updatedAt": "2023-07-14T16:37:55.412Z", "uploadUrl": "some_url", "downloadUrl": "some_url" } ] } } ] } } } ### GraphQL: CardProfileSets Query: query cardProfileSets( $first: Int $after: String $filterBy: FilteredCardProfileSetsInput! ) { cardProfileSets(first: $first, after: $after, filterBy: $filterBy) { ... on CardProfileSetConnection { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { __typename id name intent network status } } } } } Variables: { "filterBy": { "cardProductId": { "equals": "" }, "status": { "equals": "APPROVED" } } } Expected Result: { "data": { "cardProfileSets": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "04 NOV27 Card Profile Set", "intent": "PHYSICAL", "network": "MASTERCARD", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "04 NOV15 Card Profile Set", "intent": "PHYSICAL", "network": "MASTERCARD", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "04 NOV15 Card Profile Set", "intent": "PHYSICAL", "network": "MASTERCARD", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "03 NOV15 Card Profile Set", "intent": "DIGITAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "02 NOV15 Card Profile Set", "intent": "PHYSICAL", "network": "MASTERCARD", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "01 NOV15 Card Profile Set", "intent": "PHYSICAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "03 11142023 Card Profile Set", "intent": "VIRTUAL", "network": "MASTERCARD", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "02 11302023 Card Profile Set", "intent": "PHYSICAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "01 11302023 Card Profile Set", "intent": "PHYSICAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "Card Profile Set 4", "intent": "PHYSICAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "Card Profile Set 3", "intent": "DIGITAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "Card Profile Set 2", "intent": "VIRTUAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "Card Profile Set 1", "intent": "VIRTUAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "Virtual Intent Card Profile Set 2", "intent": "VIRTUAL", "network": "VISA", "status": "APPROVED" } }, { "cursor": "some-cursor", "node": { "__typename": "CardProfileSet", "id": "", "name": "Virtual Intent Card Profile Set", "intent": "VIRTUAL", "network": "VISA", "status": "APPROVED" } } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 22, "limit": 60060, "remaining": 60038 } } } --- URL: https://docs.highnote.com/docs/issuing/cards/issue/embedded-devices Title: Issue Cards to Embedded Devices Section: Issuing Description: Issue payment cards to embedded devices such as wristbands using a Highnote-certified personalization vendor. ## Overview After you issue a virtual payment card, your cardholder can load it onto an embedded device, such as a wristband, for contactless payments. Embedded devices are personalized through a Highnote-certified personalization vendor. Your personalization vendor retrieves the card details from the Highnote API, prepares the personalization data, and delivers it to the cardholder's device through your application. After successful personalization, you register the order with the Highnote platform. ## Prerequisites - A Highnote account - An API key or the API Explorer - A Highnote virtual card - A card product configured for embedded devices (for example, the form factor) - A Highnote-certified personalization vendor. ## How it works The following steps outline the embedded device personalization workflow: 1. You, the subscriber, issue a virtual payment card for the cardholder. 2. The cardholder opens your application and selects an embedded device such as a wristband. 3. Your application sends the device serial number and the Highnote payment card ID () to the personalization vendor. 4. The vendor retrieves the card details, including restricted details, using the Highnote API. See Retrieve card details for personalization. 5. The vendor calls to register the order in Highnote's system. See Create external physical card order. 6. The vendor prepares the personalization data, encrypted for the device serial number. 7. The cardholder taps the device to an NFC-enabled phone to personalize it through your application. Results: - On **success**, you call to mark the order complete. See Complete external physical card order. - On **failure**, you call [](/docs/issuing/cards/manage/manage-cards#close-a-card) to terminate the card. The cardholder must start the process again with a new virtual card. ## Retrieve card details for personalization Your personalization vendor uses a node query with the payment card ID to retrieve the card details needed for personalization. The query includes the field, which returns the full card number and CVV. ## Create external physical card order The vendor calls the mutation to register the order in Highnote's system. This mutation logs the payment card order and associates the embedded device details with the payment card. The mutation requires the following input: | Field | Data type | Description | | :---------------------------- | :-------- | :--------------------------------------------------------------------------- | | | String | The ID of the Highnote payment card with prefix | | | String | A unique key (e.g., UUIDv4) to prevent duplicate requests. 5–255 characters. | | (optional) | Object | The embedded device details. Contains the fields below. | | | String | URL to an image of the embedded device | | | String | Descriptor assigned to the embedded device by the user or application | | | String | Alphanumeric unique designator for the embedded device | | | String | A free-form field for additional information about the embedded device | ## Complete external physical card order After the cardholder successfully personalizes the embedded device, call the mutation to mark the order as . This confirms that the device is ready for contactless payments. ## Handle personalization failures If device personalization fails, the payment card should be terminated to prevent unauthorized use. Call the [](/docs/issuing/cards/manage/manage-cards#close-a-card) mutation to close the card. The cardholder must issue a new virtual card and restart the personalization process. Do not call for failed personalizations. ## Query embedded device cards Use the following query to find details from an external physical card order for a specific payment card, including the embedded device information: ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { id bin last4 expirationDate network status formFactor restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "bin": "547203", "last4": "9174", "expirationDate": "2026-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "formFactor": "WRISTBAND", "restrictedDetails": { "cvv": "714", "number": "5472XXXXXXXX9174" } } } } ### GraphQL: CreateExternalPhysicalPaymentCardOrder Query: mutation createExternalPhysicalPaymentCardOrder( $input: CreateExternalPhysicalPaymentCardOrderInput! ) { createExternalPhysicalPaymentCardOrder(input: $input) { ... on ExternalPhysicalPaymentCardOrder { id status paymentCard { id bin last4 expirationDate network status } embeddedDevice { formFactor image name serialNumber variant } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "paymentCardId": "", "embeddedDevice": { "image": "https://example.com/device-image.png", "name": "MyDevice", "serialNumber": "123abc", "variant": "Plastic" } } } Expected Result: { "data": { "createExternalPhysicalPaymentCardOrder": { "id": "", "status": "NEW", "paymentCard": { "id": "", "bin": "547203", "last4": "9232", "expirationDate": "2026-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE" }, "embeddedDevice": { "formFactor": "WRISTBAND", "image": "https://example.com/device-image.png", "name": "MyDevice", "serialNumber": "123abc", "variant": "Plastic" } } } } ### GraphQL: CompleteExternalPhysicalPaymentCardOrder Query: mutation completeExternalPhysicalPaymentCardOrder( $input: CompleteExternalPhysicalPaymentCardOrderInput! ) { completeExternalPhysicalPaymentCardOrder(input: $input) { ... on ExternalPhysicalPaymentCardOrder { id status paymentCard { id bin last4 expirationDate network status } embeddedDevice { formFactor image name serialNumber variant } } ... on UserError { errors { code } } } } Variables: { "input": { "externalPhysicalPaymentCardOrderId": "" } } Expected Result: { "data": { "completeExternalPhysicalPaymentCardOrder": { "id": "", "status": "COMPLETED", "paymentCard": { "id": "", "bin": "547203", "last4": "5856", "expirationDate": "2026-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE" }, "embeddedDevice": { "formFactor": "WRISTBAND", "image": "https://example.com/device-image.png", "name": "MyDevice", "serialNumber": "123abc", "variant": "Plastic" } } } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { id bin last4 expirationDate network status formFactor externalPhysicalPaymentCardOrders { id embeddedDevice { formFactor image name serialNumber variant } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "bin": "547203", "last4": "9174", "expirationDate": "2026-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "formFactor": "PHYSICAL", "externalPhysicalPaymentCardOrders": [ { "id": "", "embeddedDevice": { "formFactor": "WRISTBAND", "image": "https://example.com/device-image.png", "name": "MyDevice", "serialNumber": "123abc", "variant": "Plastic" } } ] } }, "extensions": { "requestId": "3a31dd25-aa8d-9b58-9393-64b8da6450c0", "rateLimit": { "cost": 2, "limit": 60060, "remaining": 60056 } } } --- URL: https://docs.highnote.com/docs/issuing/cards/issue/issue-preprinted-physical-cards Title: Issue Preprinted Physical Cards Section: Issuing Description: Issue preprinted physical cards for on-the-spot distribution using placeholder financial accounts. Assign cards to account holders and reissue personalized replacements. ## Overview Highnote offers preprinted, ready-to-use physical cards for on-the-spot distribution to users. This guide provides an overview of issuing preprinted physical cards to account holders. Preprinted cards use a **placeholder financial account** that allows you to issue the card, without it being activated or used right away. Once you have an account holder to assign the preprinted card to, you can reissue a new personalized payment card against the account holder's financial account. The following graphic outlines the typically process for issuing preprinted physical cards: ## Prerequisites - A Highnote account - Access to an API key or the API Explorer - An account holder with an approved application ## Issue a financial account Once you have an account holder with an approved application, you can issue a preprinted financial account to the account holder. A preprinted financial account acts as a placeholder that allows you to issue a preprinted card to an account holder. Use the following mutation to issue a preprinted financial account: ## Issue a virtual card After issuing a preprinted financial account, you can issue a virtual card. Virtual cards are available to account holders immediately for use at online retailers or to add to their digital wallets. By default, all payment cards begin as virtual cards. If you choose to, you can additionally create and send a physical card. For information on issuing virtual cards, see Issue a Virtual Card. ## Create physical cards You can use the regular physical card order flow to create preprinted cards for preprinted financial accounts. For more information on creating physical cards, refer to the following guides: - Print Physical Cards - Print Cards in Bulk ## Assign preprinted card to account holder To issue a preprinted card to an account holder, you must assign it to an account holder financial account. Use the following steps to issue an account holder financial account: 1. Onboard an account holder 2. Create an application 3. Issue a financial account for the account holder's application Once you create the account holder financial account, use the following mutation to assign the preprinted card to the account holder's financial account: ## Issue personalized card After assigning the preprinted card to the account holder financial account, you can issue a new payment card as the personalized card. The personalized card allows the account holder to use their account holder details for their card. Refer to the following guides to issue a new card and send personalized physical cards: - Issue Cards - Print Physical Cards - Print Cards in Bulk ## Reissue lost preprinted card There may be times when an account holder loses a preprinted card before they are issued or receive their personalized card. In this scenario, you must do the following: 1. Suspend the lost preprinted card. _Do not deactivate the lost card._ 2. Assign a new temporary preprinted card. 3. Issue the account holder's personalized payment card using the suspended card's PAN. _Do not issue the personalized card using the temporary preprinted card's PAN._ 4. Activate the new personalized payment card. This automatically deactivates the suspended card. The following graphic outlines these steps: For non-preprinted payment cards, see lost or stolen cards. ### GraphQL: IssuePreprintedPaymentCardFinancialAccountForApplication Query: mutation IssuePreprintedPaymentCardFinancialAccountForApplication( $input: IssuePreprintedPaymentCardFinancialAccountForApplicationInput! ) { issuePreprintedPaymentCardFinancialAccountForApplication(input: $input) { ... on FinancialAccount { id externalId name application { id } cardProduct { id } features { __typename enabled } owner { __typename ... on Node { id } ... on USBusinessAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "" } } Expected Result: { "data": { "issuePreprintedPaymentCardFinancialAccountForApplication": { "id": "", "externalId": "", "name": "Financial Account", "application": { "id": "" }, "cardProduct": { "id": "" }, "features": [ { "__typename": "PreprintedCardFinancialAccountFeature", "enabled": true } ], "owner": { "__typename": "USBusinessAccountHolder", "id": "" } } } } ### GraphQL: AssignPaymentCardToFinancialAccount Query: mutation AssignPaymentCardToFinancialAccount( $input: AssignPaymentCardToFinancialAccountInput! ) { assignPaymentCardToFinancialAccount(input: $input) { ... on PaymentCard { id bin last4 expirationDate network status financialAccounts { id } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "paymentCardId": "", "assignToFinancialAccountId": "", "options": { "activateOnAssignment": true } } } Expected Result: { "data": { "assignPaymentCardToFinancialAccount": { "id": "", "bin": "510515", "last4": "7162", "expirationDate": "2027-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "" } ] } } } --- URL: https://docs.highnote.com/docs/issuing/cards/issue/issue-virtual-cards Title: Issue Virtual Cards Section: Issuing Description: Issue financial accounts and virtual cards to approved account holders. Activate cards, set PINs, manage card lineage with PAR and PAN hierarchy, and configure card profile sets. ## Overview This guide provides an overview of issuing a financial account and virtual card product using the Highnote API. ## Prerequisites - A Highnote account - An API key or the API Explorer - An account holder with approved application ## Issue a financial account For security and compliance reasons, do not use the account holder's name when assigning a name to a financial account. Once you have an account holder with an approved application, you can issue a financial account. Financial accounts hold funds for an account holder's payment card(s). Use the following mutation to issue a financial account, using the approved application's as an input: ## Add account notes After issuing a financial account, you can use the following mutation to allow your agents to add notes to a financial account. Adding notes is useful for various internal servicing needs: ### Find account notes by financial account Use the following query to find and display notes on a financial account: ### Find account notes by account holder Use the following query to find the notes recorded for an account holder. A note appears when it's created with the account holder as its aggregate entity, as in the createGlobalNote mutation above. This example queries a person account holder. For a business account holder, query the same field on [](/docs/api-reference/object#USBusinessAccountHolder). ## Payment card lineage When a new payment card is issued, a hierarchy of cards called a "lineage" is established. This lineage is made up of a Payment Account Reference (PAR) and a unique primary account number (PAN): - **Payment Account Reference (PAR):** The highest level in the payment card lineage; a non-financial reference value assigned by the network to a lineage of payment cards - **Primary account number (PAN):** Sits under a PAR in the payment card lineage; refers to the card number of the cardholder's payment card A cardholder can only have one active payment card (PAN) in an existing lineage at a time. This is important to note for issuing new cards, reissuing cards, and terminating cards. Refer to the following examples for each use case: | Use Case | Example | Notes | | :--------------- | :----------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Issue a new card | An account holder applies for your card product and is issued a payment card for the first time. | When the new card is issued, a new PAR is established, with the new payment card number as the PAR's one active PAN. | | Reissue a card | An account holder's payment card is about to expire and they need a new card. | A payment card is reissued under the same lineage (PAR) and when activated, the old PAN is automatically deactivated. | | Close a card | An account holder's payment card was stolen and they need a new card. | Stolen cards are reported to the card network, which results in the PAN and any predecessors in the card lineage being deactivated. This ensures that the card network does not deactivate the new payment card for being associated with the stolen card's lineage. | ## Issue a virtual card All payment cards start as virtual cards, with the option to issue physical or tokenized cards. After creating a financial account for the account holder, you can issue them a virtual card. Refer to the following guidelines when issuing virtual cards: - If you are using card profiles, you can either specify the card profile for the virtual card or use the default card profile set. For more information on card profiles, see Manage Card Profiles. - You can create and send a physical card, issue preprinted physical cards, or issue to embedded devices after you've issued a virtual card. The following mutation can be used to issue a virtual card associated with a card profile set. If you are issuing a virtual card without a card profile set, remove the input variable: ## Activate a card You can either activate virtual cards at creation or provide an experience for account holders to activate their virtual cards from your app or website. The following graphic provides an overview of the card activation flow: Use the following mutation to activate a card: ## Set a PIN Payment cards must be activated before you set the PIN. Prepaid cards have debit capabilities, so they must have a PIN set after activation. This allows access to ATMs and/or receive cashback at checkout. You must create an interface for the account holder to set their PIN after activating their payment card. Refer to the following guides to create a PIN management interface: - For web-based integrations, Highnote recommends you set the PIN with the Secure Inputs SDK. - For native iOS and Android-based integrations, and non-native PCI-compliant environments, you can securely set a PIN from the API with a Client Token. Use the following mutation to set a PIN: ## Next steps When a virtual card is issued, you can print it is a physical card or issue a tokenized card. For more information, see the following guides: - Print Physical Card - Issue to Embedded Devices - Add Cards to Digital Wallets ### GraphQL: 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 Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: createGlobalNote Query: mutation createGlobalNote($input: CreateGlobalNoteInput!) { createGlobalNote(input: $input) { __typename ... on GlobalNote { id createdBy { id } message createdAt primaryEntity { __typename ... on Node { id } ... on FinancialAccount { id externalId } } aggregateEntity { __typename ... on USBusinessAccountHolder { id externalId } ... on USPersonAccountHolder { id externalId } } } ... on AccessDeniedError { message } ... on UserError { errors { __typename errorPath code description } } } } Variables: { "input": { "message": "This is a note!", "primaryEntity": { "primaryEntityId": "", "primaryEntityType": "FINANCIAL_ACCOUNT" }, "aggregateEntity": { "aggregateEntityId": "", "aggregateEntityType": "ACCOUNT_HOLDER" } } } Expected Result: { "data": { "createGlobalNote": { "__typename": "GlobalNote", "id": "", "createdBy": { "id": "" }, "message": "This is a high note!", "createdAt": "2024-06-28T18:13:26.620Z", "primaryEntity": { "__typename": "FinancialAccount", "id": "", "externalId": "2KRBVWEJY4" }, "aggregateEntity": { "__typename": "USPersonAccountHolder", "id": "", "externalId": "some-id" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60047 } } } ### GraphQL: FindFinancialAccount Query: query FindFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id globalNotes { ... on GlobalNoteConnection { pageInfo { hasNextPage hasPreviousPage } edges { node { message } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "globalNotes": { "pageInfo": { "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "node": { "message": "This is a note!" } } ] } } } } ### GraphQL: GetPersonAccountHolder Query: query getPersonAccountHolder($id: ID!) { node(id: $id) { ... on USPersonAccountHolder { id globalNotes { ... on GlobalNoteConnection { pageInfo { hasNextPage hasPreviousPage } edges { node { message } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "ACCOUNT_HOLDER", "globalNotes": { "pageInfo": { "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "node": { "message": "This is a note!" } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 23, "limit": 60060, "remaining": 60037 } } } ### GraphQL: IssuePaymentCardForFinancialAccount Query: mutation IssuePaymentCardForFinancialAccount( $input: IssuePaymentCardForFinancialAccountInput! ) { issuePaymentCardForFinancialAccount(input: $input) { ... on PaymentCard { id bin last4 expirationDate network status } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "financialAccountId": "", "options": { "activateOnCreate": true, "expirationDate": "2024-01-01T23:59:59Z", "cardProfileSetId": "" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "510520", "last4": "5968", "expirationDate": "2024-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE" } }, "extensions": { "requestId": "", "rateLimit": { "limit": 30030, "remaining": 30010, "cost": 12 } } } ### GraphQL: ActivatePaymentCard Query: mutation ActivatePaymentCard($input: ActivatePaymentCardInput!) { activatePaymentCard(input: $input) { ... on PaymentCard { status } ... on UserError { errors { code errorPath } } } } Variables: { "input": { "paymentCardId": "" } } Expected Result: { "data": { "status": "ACTIVE" } } ### GraphQL: SetPinForPaymentCard Query: mutation SetPinForPaymentCard($input: SetPinForPaymentCardInput!) { setPinForPaymentCard(input: $input) { __typename ... on PaymentCard { id } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "paymentCardId": "", "newPin": "1234" } } Expected Result: { "data": { "setPinForPaymentCard": { "__typename": "PaymentCard", "id": "" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/cards/issue/print-physical-cards-bulk Title: Print Physical Cards in Bulk Section: Issuing Description: Create group physical card orders for up to 500 cards per batch. Add personalized or blank cards, send orders to the printer, and track fulfillment status. ## Overview Group physical card orders are used to request an order for several physical cards at once. Group physical card orders are: - Packaged individually in a card carrier and shipped together in a single shipment. - Shipped to one location. Some use cases for group orders include prepaid cards, preprinted physical cards, and fleet cards you want to distribute in bulk. ## Prerequisites - A Highnote account - An API key or the API Explorer - A virtual card ## Create group physical card order When a group order is first created, it has a status of . The order lifecycle for group physical card orders is as follows: 1. Create a group order (ideally with an token). 2. Add payment cards to the group order. 3. Complete the order and send it to the vendor for printing. ### Create group physical card order with token Highnote recommends that you use this mutation when creating group physical card order as it requires a response token from the validateAddress mutation. It does not accept the raw address itself (validated or not), nor does it perform a regular expression check to validate address format. Use the following mutation to create a group physical card order with the response token from the validateAddress mutation. 1. Call to check if the shipping address is valid. 2. Copy the response token representing the validated address. 3. Call with the response token. For individual orders using a validated address token, see Print Physical Cards. ### Create group physical card order with token or address This mutation lets you use a validateAddress token or the validated address itself. For best results, Highnote recommends that you use the response token. Use the following mutation to create a group physical card order. 1. Call to check if the shipping address is valid. 2. Copy the response token representing the validated address or the address that you validated. 3. Call with either the token or the address. For individual card orders using a validated address token or raw validated address, see Print Physical Cards. ### Add cards to group order The maximum number of cards you may add to a single group order is 500. After creating a group order, you can add payment cards to it. Use the field in the response payload to ensure you add payment cards to the correct group order. Refer to the following guidelines when adding payment cards to a group order: - You may specify card personalization values or leave the payment cards blank with no personalization - If your card mailer includes address information for each card, you can specify addresses for each mailer when adding cards to the group order ### Complete the group order You can complete the order after adding payment cards to your group order. Once a group order is completed, Highnote sends the group order to your chosen card printer and notifies you of the shipping status. The cards will be packed in individual envelopes with card carriers and sent to the destination set on the group order in one shipment. At this point, the group order will have a status. Use the following mutation to completed a group order: ### Remove card from group order You can cancel a payment card's fulfillment to remove the physical card from a group order if the order status is still in the state. Once the order status has transitioned from a state, you can't remove a card from a group order. Use the following mutation to remove a payment card from a group order: ### Cancel a group order To edit group order attributes such as shipping address, you will need to create a new group order. Canceling a group order cancels the entire group order, including the fulfillment of all payment cards associated with it. Group orders can only be canceled in the state. Use the following mutation to cancel a group order: ### Find a group order Use the following query to find group orders: ### Find cards in a group order Use the following query to find individual payment cards in a group order: ## Search group orders You can use the Highnote API to search for group card orders for status tracking or display order history on your website or application. You can narrow search results using filters. The following sections provide an overview of searching for group card orders. For information on individual card orders, see Print Physical Cards. ### Group card order filters Group card order filters allow you to narrow search results based on information related to group card orders. These filters include the following: | Filter | Description | | :-------------------- | :----------------------------------------------------------------------------------- | | | Input to filter by the ID of your card product | | | Input to filter by the ID of the group order | | | Input to filter by physical card group order status | | | Input to filter by the shipping method of the group order | | | Input to filter by the creation date of the group order | | | Input to filter by the actual shipping date of the group order; in YYYY-MM-DD format | ### Example search query The following query is an example search query that returns group card orders for an organization, filtered using group card order filters: ## Simulate group order fulfillment You can simulate group order fulfillment in the Test environment without actually shipping cards. This is useful for simulating group order statuses and notifications. ### Send order to printer You can use the mutations provided in this guide to create and complete a group order. A completed order will have a status of . Use the following mutation to transition the group order to status: ### Approve shipment Once the group order has been , you can change the status to using the following mutation: ### Ship order For an overview of group order shipping methods, see Shipping Methods. After a group order is approved, you can use the following mutation to transition to the status. The shipping method and tracking number (if available) will be returned in the response payload: ### Fail order To design your system to handle failed Group Order shipments, you can simulate a status of . ### GraphQL: createPhysicalCardGroupOrderWithValidatedAddressToken Query: mutation createPhysicalCardGroupOrderWithValidatedAddressToken( $input: CreatePhysicalCardGroupOrderWithValidatedAddressTokenInput! ) { createPhysicalCardGroupOrderWithValidatedAddressToken(input: $input) { __typename ... on PhysicalCardGroupOrder { __typename id orderState { status } paymentCardShipment { courier { method } deliveryDetails { address { streetAddress extendedAddress locality postalCode region countryCodeAlpha3 } companyName name { givenName familyName } validatedAddress { id labels provided { streetAddress extendedAddress locality postalCode region countryCodeAlpha3 } } } } createdAt updatedAt } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "", "cardProductId": "", "courier": { "method": "USPS_GROUND", "signatureRequiredOnDelivery": false }, "deliveryDetails": { "name": { "givenName": "John", "familyName": "Doe" }, "validatedAddressId": "" } } } Expected Result: { "data": { "createPhysicalCardGroupOrderWithValidatedAddressToken": { "__typename": "PhysicalCardGroupOrder", "id": "", "orderState": { "status": "NEW" }, "paymentCardShipment": { "courier": { "method": "USPS_GROUND" }, "deliveryDetails": { "address": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "locality": "SAN FRANCISCO", "postalCode": "94107-2134", "region": "CA", "countryCodeAlpha3": "USA" }, "companyName": null, "name": { "givenName": "John", "familyName": "Doe" }, "validatedAddress": { "id": "", "labels": [ "BUSINESS" ], "provided": { "streetAddress": "24 Willie Mays Plz", "extendedAddress": "", "locality": "San Francisco", "postalCode": "94107-2134", "region": "CA", "countryCodeAlpha3": "USA" } } } }, "createdAt": "2024-06-18T19:47:57.062Z", "updatedAt": "2024-06-18T19:47:57.062Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60040 } } } ### GraphQL: CreatePhysicalCardGroupOrder Query: mutation CreatePhysicalCardGroupOrder( $input: CreatePhysicalCardGroupOrderInput! ) { createPhysicalCardGroupOrder(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "cardProductId": "", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false }, "requestedShipDate": "2022-08-03" } } Expected Result: { "data": { "createPhysicalCardGroupOrder": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 0, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "Givecard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "NEW" }, "stateHistory": [ { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: OrderPhysicalPaymentCardForGroup Query: mutation OrderPhysicalPaymentCardForGroup( $input: OrderPhysicalPaymentCardForGroupInput! ) { orderPhysicalPaymentCardForGroup(input: $input) { __typename ... on PhysicalPaymentCardOrder { id paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } cardPersonalization { textLines { line1 line2 } } stateHistory { previousStatus newStatus createdAt } paymentCard { id bin last4 expirationDate expirationMonth expirationYear network cardProduct { id } cardProductApplication { ... on Node { id } } status } groupOrder { id cardCount } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "paymentCardId": "", "groupOrderId": "", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "cardPersonalization": { "textLines": { "line1": "HOMER J SIMPSON", "line2": "line 2" } } } } Expected Result: { "data": { "orderPhysicalPaymentCardForGroup": { "__typename": "PhysicalPaymentCardOrder", "id": "", "groupOrderId": "", "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "NEW" }, "cardPersonalization": { "textLines": { "line1": "HOMER J SIMPSON", "line2": "line 2" } }, "stateHistory": [ { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "paymentCard": { "id": "", "bin": "547203", "last4": "0589", "expirationDate": "2025-01-01T23:59:59Z", "expirationMonth": "01", "expirationYear": "25", "network": "MASTERCARD", "cardProduct": { "id": "" }, "cardProductApplication": { "id": "" }, "status": "ACTIVE" }, "groupOrder": { "id": "", "cardCount": 1 }, "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } } } ### GraphQL: CompletePhysicalCardGroupOrder Query: mutation CompletePhysicalCardGroupOrder( $input: CompletePhysicalCardGroupOrderInput! ) { completePhysicalCardGroupOrder(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "" } } Expected Result: { "data": { "completePhysicalCardGroupOrder": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "NEW" }, "stateHistory": [ { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: CancelPhysicalPaymentCardOrder Query: mutation CancelPhysicalPaymentCardOrder( $input: CancelPhysicalPaymentCardOrderInput! ) { cancelPhysicalPaymentCardOrder(input: $input) { ... on PhysicalPaymentCardOrder { orderState { status } } } } Variables: { "input": { "physicalPaymentCardOrderId": "" } } Expected Result: { "data": { "cancelPhysicalPaymentCardOrder": { "orderState": { "status": "CANCELED" } } } } ### GraphQL: CancelPhysicalCardGroupOrder Query: mutation CancelPhysicalCardGroupOrder( $input: CancelPhysicalCardGroupOrderInput! ) { cancelPhysicalCardGroupOrder(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "" } } Expected Result: { "data": { "cancelPhysicalCardGroupOrder": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "NEW" }, "stateHistory": [ { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: GetPhysicalCardGroupsForProduct Query: query GetPhysicalCardGroupsForProduct( $cardProductId: ID! $firstGroupOrders: Int ) { node(id: $cardProductId) { ... on CardProduct { __typename id name usage groupOrders(first: $firstGroupOrders) { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { __typename id cardCount } } } } } } Variables: { "cardProductId": "", "firstGroupOrders": 1 } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "name": "AP Single Use product", "usage": "MULTI_USE", "groupOrders": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-curso", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "__typename": "PhysicalCardGroupOrder", "cursor": "some-cursor", "node": { "id": "", "cardCount": 1 } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: FindPhysicalPaymentCardGroupOrder Query: query FindPhysicalPaymentCardGroupOrder($id: ID!) { node(id: $id) { ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } physicalPaymentCardOrders(first: 1) { __typename pageInfo { endCursor hasNextPage hasPreviousPage startCursor } edges { cursor node { id orderState { status } } } } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "cardProductId": "", "cardCount": 3, "paymentCardShipment": { "courier": { "method": "FEDEX_OVERNIGHT", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2026-04-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "NEW" }, "physicalPaymentCardOrders": { "__typename": "PhysicalPaymentCardOrderConnection", "pageInfo": { "endCursor": "end-cursor", "hasNextPage": true, "hasPreviousPage": false, "startCursor": "start-cursor" }, "edges": [ { "cursor": "some-cursor", "node": { "id": "", "orderState": { "status": "NEW" } } } ] }, "stateHistory": [ { "previousStatus": null, "newStatus": "NEW", "createdAt": "2026-04-03T18:22:02.624Z" } ], "createdAt": "2026-04-03T18:22:02.624Z", "updatedAt": "2026-04-03T18:25:56.754Z" } }, "extensions": { "requestId": "" } } ### GraphQL: nodeOrganizationWithPhysicalPaymentCardGroupOrders Query: query nodeOrganizationWithPhysicalPaymentCardGroupOrders( $id: ID! $first: Int $after: String $filterBy: PhysicalPaymentCardGroupOrderFilterInput ) { node(id: $id) { __typename ... on Organization { id physicalPaymentCardGroupOrders( first: $first after: $after filterBy: $filterBy ) { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { ...physicalCardGroupOrder } } } } } } fragment physicalCardGroupOrder on PhysicalCardGroupOrder { __typename id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } Variables: { "id": "", "first": 10, "filterBy": { "cardProductId": { "equals": "" }, "groupOrderId": { "equals": "" }, "groupOrderState": { "equals": "SENT_TO_PRINTER" }, "shippingMethod": { "equals": "USPS_GROUND" } } } Expected Result: { "data": { "node": { "__typename": "Organization", "id": "", "physicalPaymentCardGroupOrders": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 0, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2000-01-01", "deliveryDetails": { "name": { "givenName": "Business User", "middleName": "Jay", "familyName": "BUS", "suffix": "", "title": "" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "", "postalCode": "60654", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "", "middleName": "", "familyName": "", "suffix": "", "title": "" }, "companyName": null, "address": { "streetAddress": "", "extendedAddress": "", "postalCode": "", "region": "", "locality": "", "countryCodeAlpha3": "" } } }, "orderState": { "status": "NEW" }, "stateHistory": [ { "previousStatus": null, "newStatus": "NEW", "createdAt": "2024-04-16T23:51:19.034Z" } ], "createdAt": "2024-04-16T23:51:19.032Z", "updatedAt": "2024-04-16T23:51:19.122Z" } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 113, "limit": 60060, "remaining": 59947 } } } ### GraphQL: SimulatePhysicalCardGroupOrderSendToPrinter Query: mutation SimulatePhysicalCardGroupOrderSendToPrinter( $input: SimulatePhysicalCardGroupOrderSendToPrinterInput! ) { simulatePhysicalCardGroupOrderSendToPrinter(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderSendToPrinter": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "SENT_TO_PRINTER" }, "stateHistory": [ { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulatePhysicalCardGroupOrderApproval Query: mutation SimulatePhysicalCardGroupOrderApproval( $input: SimulatePhysicalCardGroupOrderApprovalInput! ) { simulatePhysicalCardGroupOrderApproval(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderApproval": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "APPROVED" }, "stateHistory": [ { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulatePhysicalCardGroupOrderShipped Query: mutation SimulatePhysicalCardGroupOrderShipped( $input: SimulatePhysicalCardGroupOrderShippedInput! ) { simulatePhysicalCardGroupOrderShipped(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "", "trackingNumber": "94001234567890123456", "actualShipDate": "2026-04-03" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderShipped": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": { "trackingNumber": "94001234567890123456", "actualShipDateLocal": "2026-04-03" } }, "requestedShipDate": "2026-04-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "SHIPPED" }, "stateHistory": [ { "previousStatus": "SHIPPED", "newStatus": "SENT_TO_PRINTER", "createdAt": "2026-04-03T20:16:40.580Z" }, { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2026-04-03T20:16:40.580Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2026-04-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2026-04-03T20:16:40.580Z" } ], "createdAt": "2026-04-03T20:16:40.579Z", "updatedAt": "2026-04-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulatePhysicalCardGroupOrderShipmentFailed Query: mutation SimulatePhysicalCardGroupOrderShipmentFailed( $input: SimulatePhysicalCardGroupOrderShipmentFailedInput! ) { simulatePhysicalCardGroupOrderShipmentFailed(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "MC4yMi4xMjM=" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderShipmentFailed": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "SHIP_FAILED" }, "stateHistory": [ { "previousStatus": "APPROVED", "newStatus": "SHIP_FAILED", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "4a98f0d9-8590-9d59-9301-29f135a8e15a" } } --- URL: https://docs.highnote.com/docs/issuing/cards/issue/print-physical-cards Title: Print Physical Cards Section: Issuing Description: Order individual physical cards with cardholder personalization, CASS-certified address validation, and configurable shipping methods. Monitor order status and simulate fulfillment. ## Overview After you issue a virtual card, you can order physical cards for eligible, multi-use card products. The Highnote platform supports two kinds of physical cards: - **Personalized physical cards:** Payment cards that are personalized for the account holder - **Preprinted physical cards:** Generic cards that are not personalized for the account holder This guide provides an overview of printing personalized physical cards using the Highnote API. To issue cards to embedded devices such as wristbands, see Issue Cards to Embedded Devices. ## Prerequisites - A Highnote account - An API key or the API Explorer - A Highnote virtual card. ### Individual card orders Individual physical card orders let you print a single physical card. Physical card orders are: - Packaged with a card carrier - Shipped to a single location - Not connected to other orders at any time in the physical card order lifecycle Individual physical card orders are the most common order type across card products. For example, when issuing a card to a single account holder for a consumer debit product, you will use this order type. ### Group card orders Group physical card orders allow you to request several physical cards at once. Note the following about group physical card orders: - Packaged individually with a card carrier - Shipped in bulk as a single shipment to one location Group physical card orders are essentially a set of individual card orders that are packaged into a single shipment during the last step of the physical card order lifecycle. For information on group card orders, see Print Cards in Bulk. ## Card personalization Card personalization is dynamic information printed on a physical card that is unique to the cardholder. Line 1 and Line 2 represent the card personalization on a payment card: - **Line 1** is _required_ and used for the cardholder's name. Examples of cardholders include account holders and authorized users. - **Line 2** is _optional_ and can be used for any additional information. For example, a business account holder may use line 2 for the business name. Each line has minimum length of 1 and maximum length of 23. Valid characters are all alphanumeric characters, plus 7 special characters and space. ## Card order lifecycle You cannot cancel a card order after it has been sent to the printer. The following graphic shows the standard card order lifecycle, beginning with an order for a physical card and ending with a shipment received by the account holder: Each step in the card order lifecycle corresponds with a status. Refer to the following table for a description of each status in the card order lifecycle: | Status | Description | | :---------------- | :--------------------------------------------------------------------------------------------------------------------------- | | | A request for a physical card has been made. This is the only stage at which an order may be canceled. | | | The group order is ready to ship but has not yet been sent to the printer. This status is only applicable to _group orders_. | | | The order has successfully been sent to the printer. | | | The printer has approved the order. | | | The order has been shipped. All shipment methods besides USPS Ground return a tracking number. | | | You requested to cancel the order. | | | The order failed to reach the account holder. Failed orders are returned to the return address on file. | ## Fulfillment Highnote sends physical card fulfillment requests to the printer several times a day. The input variable accepts a date in format: - To schedule a future ship date, provide a date in format - To ship as soon as possible, omit the field If the date provided is in the past, the value is ignored and the order ships as soon as possible. ## Shipping methods {#shipping-method} You can choose various shipping methods for individual and group card orders. Shipping cost is based on the price outlined in your Highnote Master Services Agreement. For a general overview of the enum, see the API Reference. For which shipping methods trigger , see Physical card fees. ### USPS features {#usps} Note the following USPS features: - USPS is the only supported carrier for shipments to **P.O. boxes**. - USPS Priority Mail Express includes **Signature Confirmation** at no additional cost. If you do not want this feature, we recommend using another shipping method. - USPS Ground does _not_ provide **tracking numbers** for your shipped cards. ### FedEx delivery windows {#fedex} Both FedEx Overnight service levels arrive the next business day: - Priority Overnight: by 10:30 a.m. to most businesses, by noon to residences - Standard Overnight: by 5 p.m. to businesses, by 8 p.m. to residences ### Shipping individual orders Expedited and same-day processing incurs additional fees under your Master Services Agreement, separate from the account holder's —see Physical card fees. Confirm availability with Highnote support. The following table outlines the available couriers, shipping options, and expected shipping times for individual card orders. UPS availability depends on your card vendor and is not shown here—confirm with Highnote support if you don't see it as an option: | Courier | Shipment Option | Expected Transit Time | On-demand Card | Premium Card | | :------ | :--------------------------------------------------------------------------- | :------------------------------------------------------------- | :------------------------------------------------------: | :------------------------------------------------------: | | USPS | Ground
→ | 2-8 business days | !approved | !approved | | | Ground - Processed Same Day
→ | 2-8 business days | !approved | !denied | | | Priority Mail ®
→ | 1-3 business days | !approved | !approved | | | Priority Mail ® - Processed Same Day
→ | 1-3 business days | !approved | !denied | | | Priority Mail Express ®
→ | 1-2 business days | !approved | !denied | | FedEx | Ground
→ | 1-5 business days | !approved | !approved | | | Ground - Processed Same Day
→ | 1-5 business days | !approved | !denied | | | One Rate
→ | 2-3 business days | !denied | !approved | | | 2 Day
→ | 2 business days | !approved | !approved | | | Standard Overnight
→ | Next business day
→ by 5 p.m. / 8 p.m. | !approved | !approved | | | Standard Overnight - Processed Same Day
→ | Next business day
→ by 5 p.m. / 8 p.m. | !approved | !denied | | | Priority Overnight
→ | Next business day
→ by 10:30 a.m. / noon | !approved | !approved | | | International Priority
→ | 2-5 business days | !approved | !denied | ### Shipping group orders Expedited and same-day processing incurs additional fees under your Master Services Agreement, separate from the account holder's —see Physical card fees. Confirm availability with Highnote support. At this time, group card orders are only available for on-demand cards. The following table outlines the available couriers, shipping options, and expected shipping times for group card orders. UPS availability depends on your card vendor and is not shown here—confirm with Highnote support if you don't see it as an option: | Courier | Shipment Option | Expected Transit Time | | :------ | :--------------------------------------------------------------------------- | :------------------------------------------------------------- | | USPS | Ground
→ | 2-8 business days | | | Ground - Processed Same Day
→ | 2-8 business days | | | Priority Mail ®
→ | 1-3 business days | | | Priority Mail ® - Processed Same Day
→ | 1-3 business days | | FedEx | Ground
→ | 1-5 business days | | | Ground - Processed Same Day
→ | 1-5 business days | | | 2 Day
→ | 2 business days | | | Standard Overnight
→ | Next business day
→ by 5 p.m. / 8 p.m. | | | Standard Overnight - Processed Same Day
→ | Next business day
→ by 5 p.m. / 8 p.m. | | | Priority Overnight
→ | Next business day
→ by 10:30 a.m. / noon | | | International Priority
→ | 2-5 business days | ## Return address Your return address is configured by the Highnote team when your card product is set up. To view or update your return address, send a request to support@highnote.com. Orders that cannot be delivered are returned to the return address on file with Highnote. ## Validate shipping address Validated address tokens are cached for 24 hours. If they are not used, they expire. If they are used, they are converted to a permanent validated address record that can be reused anytime. Before submitting a physical card order, you can validate the card order's shipping address using the mutation. This mutation validates addresses using a CASS-certified service to ensure it is properly formatted to reduce possible shipping delays or returns. The Highnote API returns an response with the following results: - A validated address token - An error message explaining why the address is invalid ### Address validation responses When validating an address, the API will return a response that indicates whether the address is valid, incomplete, or invalid. Each response type has a corresponding "next step" to create a physical card order or re-validate a new address. Refer to the following table for an overview of address validation responses and their corresponding follow-up actions: | Response type | Description | Next step | | :---------------------------------- | :----------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | The address passed in is properly formatted and CASS-certified. | Use the returned address token to submit a physical card order for the validated address. | | | The address passed in has been modified to be properly formatted and CASS-certified. | Use the returned address token to submit a physical card order for the modified validated address. Alternatively, you may adjust the address and resubmit an address validation request to generate a new validated address token. | | | The address is missing critical components and cannot be CASS-certified. | You must adjust the address and resubmit an address validation request to generate a new validated address token. | | | The address passed in cannot be CASS-certified. | You must adjust the address and resubmit an address validation request to generate a new validated address token. | ### Address components and attributes #### Components The Highnote API uses the following components to validate an address: | Component | Description | | :--------------------- | :------------------------------------------------------------------------------------------------------------------ | | | The street number and street name of the address, including directionals. | | | Additional information such as suite and apartment numbers. | | | Typically refers to the city or town portion of the address. | | | The CLDR region code of the country or region of the address. For US addresses, this is the 2-character state code. | | | The zip or postal code of the address. | | | The three-character country code of the address. | #### Attributes When an address is validated, the API returns a list of attributes that you can use to determine whether to use the address for a shipment: | Response code | Description | | :----------------------------- | :--------------------------------------------------------------------------------------------------------------------- | | | Indicates the address of a PO box. | | | Indicates the address of a business. | | | Indicates the address of a residence. | | | Indicates the address of a Commercial Mail Receiving Agency, which is a private business receiving mail for customers. | | | Indicates the address is currently vacant. | | | Indicates the address is considered inactive. | | | Indicates that a door is accessible, but a package may not be left due to security concerns. | | | Indicates that the primary address is confirmed but the secondary address is not confirmed. | ### Example 1: Valid address In the following example, the address passed to the API is valid as is. The API returns the address and a valid address token: ### Example 2: Address with missing components In the following example, the address is missing a component: the suite number. The API returns a message detailing why the address is invalid: ### Example 3: Valid address with changes In the following example, the address passed is valid once the street address and postal code were changed. This is an example of an address that is valid with changes. The API returns the updated address and valid address token: ### Example 4: Invalid address In the following example, the address is invalid. The API returns a message detailing which components are invalid and need updating before re-attempting address validation: ### Simulate address validation To simulate address validation, see the Simulate Address Validation guide. ## Create physical card order You can only submit **one order for a given payment card**. If the order is canceled or fails, you can retry the order for the same card. If the order is successful and you need another physical card, you must issue a new payment card. After issuing a payment card, you can create an order for a physical card. When ordering a physical card, you can ship to the account holder's address on file or specify a different shipping address. Physical card orders require: - Card personalization details - Shipping address - Requested ship date - Shipping method and signature requirements ### Create physical card order with token Highnote recommends that you use this mutation when creating physical card order as it requires a response token from the validateAddress mutation. It does not accept the raw address itself (validated or not), nor does it perform a regular expression check to validate address format. Use the following mutation to create a physical card order with the response token from the validateAddress mutation. 1. Call to check if the shipping address is valid. 2. Copy the response token representing the validated address. 3. Call with the response token. For group orders with a validated address, see Print Physical Cards in Bulk. ### Create physical card order with token or address This mutation lets you use a validateAddress token or the validated address itself. For best results, Highnote recommends that you use the response token. Use the following mutation to create individual physical card orders. 1. Call to check if the shipping address is valid. 2. Copy the response token representing the validated address or the address that you validated. 3. Call with either the token or the address. For group card orders, see Print Physical Cards in Bulk. ## Monitor order status Once you have requested a physical card order you can use a query for updates on the order’s status. When the order has moved to status, you can query the tracking number to share with your customers. Use the following query to check the status of a physical card order: ### Cancel a card order Orders can only be canceled if they have the status, allowing you to cancel printing and shipment in the event a mistake was made. If you need to edit attributes such as shipping address or make changes after the order passes the status, contact support@highnote.com and create a new physical card order. Use the following mutation to cancel a physical card order: ### Order failures A status occurs when the physical card can not reach the provided address. When this occurs, you must contact the account holder for more information and create a new request with updated information. Use the following query to find the status of a physical card order: ## Search physical card orders You can use the Highnote API to search for physical card orders for status tracking or display order history on your website or application. You can narrow search results using filters for physical card order information or payment card details. The following sections provide an overview of searching for individual card orders. For information on group orders, see Print Cards in Bulk. ### Physical card order filters Physical card order filters allow you to narrow search results based on information related to individual card orders. These filters include the following: | Filter | Description | | :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Input to filter by the ID of the physical payment card order | | | Input to filter by the ID of your card product | | | Input to filter by the status of the card order; for a list of possible statuses, see the PaymentCardOrderStatus enum | | | Input to filter by the ID of the group order the individual payment card is in; _not applicable to individual card orders not included in a group order_ | | | Input to filter by the shipping method of the group order; for a list of possible statuses, see the PaymentCardShippingMethod enum | ### Payment card filters You can also narrow down search results using the input. These filters return data related to the payment card in the physical card order: | Filter | Description | | :-------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | | | Input to filter by the ID of an account holder | | | Input to filter by the ID of a payment card | | | Input to filter by the BIN of the payment card in the physical card order | | | Input to filter by the last four digits of the payment card in the physical card order | | | Input to filter by line 1 of the payment card's personalization details | | | Input to filter by line 2 of the payment card's personalization details | | | Input to filter by the status of the payment card in the physical card order | | | Input to filter by the ID of the cardholder; cardholders include account holders, authorized users, and primary authorized persons | | | Input to filter by the ID of the card profile set the payment card belongs to | ### Example search query The following query is an example search query that returns physical payment card orders for an organization, filtered using physical card order and payment card filters: ## Simulate card order fulfillment To simulate card order fulfillment for individual card orders, see the Simulate card order fulfillment guide. ### GraphQL: ValidateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "IDEMPOTENCY-KEY", "address": { "streetAddress": "24 Willie Mays Plz", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressValidatedResult", "token": { "id": "", "provided": { "streetAddress": "24 Willie Mays Plz", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" }, "standardized": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "locality": "SAN FRANCISCO", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" }, "labels": [ "BUSINESS" ], "createdAt": "2024-06-18T17:23:46.591Z" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 14 } } } ### GraphQL: ValidateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "", "address": { "streetAddress": "415 Mission St", "locality": "San Francisco", "region": "CA", "postalCode": "94111", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressIncompleteResult", "componentsMissing": [ "EXTENDED_ADDRESS" ], "provided": { "streetAddress": "415 Mission St", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94111", "countryCodeAlpha3": "USA" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 14 } } } ### GraphQL: ValidateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "", "address": { "streetAddress": "24 Willie Mays Plaza", "locality": "San Francisco", "region": "CA", "postalCode": "94107", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressValidatedWithChangesResult", "componentsChanged": [ "STREET_ADDRESS", "POSTAL_CODE" ], "token": { "id": "", "provided": { "streetAddress": "24 Willie Mays Plaza", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94107", "countryCodeAlpha3": "USA" }, "standardized": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "locality": "SAN FRANCISCO", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" }, "labels": [ "BUSINESS" ] } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 14 } } } ### GraphQL: ValidateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "", "address": { "streetAddress": "1 Willie Mays Plaza", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressInvalidResult", "componentsInvalid": [ "STREET_ADDRESS" ], "provided": { "streetAddress": "1 Willie Mays Plaza", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 14 } } } ### GraphQL: OrderPhysicalPaymentCardWithValidatedAddressToken Query: mutation orderPhysicalPaymentCardWithValidatedAddressToken( $input: OrderPhysicalPaymentCardWithValidatedAddressTokenInput! ) { orderPhysicalPaymentCardWithValidatedAddressToken(input: $input) { __typename ... on PhysicalPaymentCardOrder { __typename id orderState { status } paymentCardShipment { courier { method } deliveryDetails { address { streetAddress extendedAddress locality postalCode region countryCodeAlpha3 } companyName name { givenName familyName } validatedAddress { id provided { streetAddress extendedAddress locality postalCode region countryCodeAlpha3 } } } } createdAt updatedAt } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "", "paymentCardId": "", "deliveryDetails": { "name": { "givenName": "John", "middleName": "D", "familyName": "Doe" }, "companyName": "Highnote", "validatedAddressId": "" }, "requestedShipDate": "2026-04-03", "courier": { "method": "FEDEX_GROUND", "signatureRequiredOnDelivery": false }, "cardPersonalization": { "textLines": { "line1": "John Doe" } } } } Expected Result: { "data": { "orderPhysicalPaymentCardWithValidatedAddressToken": { "__typename": "PhysicalPaymentCardOrder", "id": "", "orderState": { "status": "NEW" }, "paymentCardShipment": { "courier": { "method": "FEDEX_GROUND" }, "deliveryDetails": { "address": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "locality": "SAN FRANCISCO", "postalCode": "94107-2134", "region": "CA", "countryCodeAlpha3": "USA" }, "companyName": "Highnote", "name": { "givenName": "John", "familyName": "Doe" }, "validatedAddress": { "id": "", "provided": { "streetAddress": "24 Willie Mays Plz", "extendedAddress": "", "locality": "San Francisco", "postalCode": "94107-2134", "region": "CA", "countryCodeAlpha3": "USA" } } } }, "createdAt": "2026-04-03T19:43:37.659Z", "updatedAt": "2026-04-03T19:43:37.659Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60042 } } } ### GraphQL: OrderPhysicalPaymentCard Query: mutation orderPhysicalPaymentCard($input: OrderPhysicalPaymentCardInput!) { orderPhysicalPaymentCard(input: $input) { ... on PhysicalPaymentCardOrder { id orderState { status } paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate } stateHistory { previousStatus newStatus createdAt } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "paymentCardId": "", "deliveryDetails": { "name": { "givenName": "John", "middleName": "D", "familyName": "Doe" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "requestedShipDate": "2026-04-03", "courier": { "method": "FEDEX_GROUND", "signatureRequiredOnDelivery": false }, "cardPersonalization": { "textLines": { "line1": "John Doe" } } } } Expected Result: { "data": { "orderPhysicalPaymentCard": { "id": "", "orderState": { "status": "SHIPPED" } }, "paymentCardShipment": { "courier": { "method": "FEDEX_GROUND", "signatureRequiredOnDelivery": false, "tracking": { "trackingNumber": "123456789012345", "actualShipDateLocal": "2026-04-03" } }, "requestedShipDate": "2026-04-03", "stateHistory": [ { "previousStatus": "NEW", "newStatus": "SENT_TO_VENDOR", "createdAt": "2026-04-03T17:47:23.303Z" }, { "previousStatus": "SENT_TO_VENDOR", "newStatus": "APPROVED", "createdAt": "2026-04-03T18:47:23.303Z" }, { "previousStatus": "APPROVED", "newStatus": "SHIPPED", "createdAt": "2026-04-03T18:47:23.303Z" } ] } } } ### GraphQL: FindPhysicalPaymentCardOrder Query: query FindPhysicalPaymentCardOrder($id: ID!) { node(id: $id) { ... on PhysicalPaymentCardOrder { id orderState { status } paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName familyName middleName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } stateHistory { previousStatus newStatus createdAt } } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "node": { "id": "", "orderState": { "status": "SHIPPED" } }, "paymentCardShipment": { "courier": { "method": "FEDEX_GROUND", "signatureRequiredOnDelivery": false, "tracking": { "trackingNumber": "123456789012345", "actualShipDateLocal": "2026-04-03" } }, "requestedShipDate": "2026-04-03", "deliveryDetails": { "name": { "givenName": "John", "middleName": "D", "familyName": "Doe" } }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "stateHistory": [ { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2026-04-03T17:47:23.303Z" }, { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2026-04-03T18:47:23.303Z" }, { "previousStatus": "APPROVED", "newStatus": "SHIPPED", "createdAt": "2026-04-03T18:47:23.303Z" } ] } } } ### GraphQL: CancelPhysicalPaymentCardOrder Query: mutation CancelPhysicalPaymentCardOrder( $input: CancelPhysicalPaymentCardOrderInput! ) { cancelPhysicalPaymentCardOrder(input: $input) { ... on PhysicalPaymentCardOrder { orderState { status } } } } Variables: { "input": { "physicalPaymentCardOrderId": "" } } Expected Result: { "data": { "cancelPhysicalPaymentCardOrder": { "orderState": { "status": "CANCELED" } } } } ### GraphQL: FindPhysicalPaymentCardOrder Query: query FindPhysicalPaymentCardOrder($id: ID!) { node(id: $id) { ... on PhysicalPaymentCardOrder { id orderState { status } } } } Variables: { "input": { "physicalPaymentCardOrderId": "" } } Expected Result: { "data": { "node": { "id": "", "orderState": { "status": "SHIP_FAILED" } } } } ### GraphQL: nodeOrganizationWithPhysicalPaymentCardOrders Query: query nodeOrganizationWithPhysicalPaymentCardOrders( $id: ID! $first: Int $after: String $filterBy: PhysicalPaymentCardOrderFilterInput ) { node(id: $id) { __typename ... on Organization { id physicalPaymentCardOrders( first: $first after: $after filterBy: $filterBy ) { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { ...physicalPaymentCardOrder } } } } } } fragment physicalPaymentCardOrder on PhysicalPaymentCardOrder { id orderState { status } cardPersonalization { textLines { line1 line2 } } paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate senderDetails { name { givenName middleName familyName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } deliveryDetails { name { givenName familyName middleName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } stateHistory { previousStatus newStatus createdAt } paymentCard { id bin last4 } createdAt updatedAt } Variables: { "id": "", "first": 0, "filterBy": { "physicalPaymentCardOrderId": { "equals": "" }, "cardProductId": { "equals": "" }, "paymentCardOrderStatus": { "equals": "SENT_TO_PRINTER" }, "groupOrderId": { "equals": "" }, "shippingMethod": { "equals": "USPS_GROUND" }, "paymentCardFilterBy": { "accountHolderId": { "equals": "" }, "paymentCardId": { "equals": "" }, "bin": { "equals": "BIN" }, "last4": { "equals": "PAN_LAST_4" }, "paymentCardPersonalizationLine1": { "equals": "LINE_1" }, "paymentCardPersonalizationLine2": { "equals": "LINE_2" }, "paymentCardStatus": { "equals": "ACTIVE" }, "paymentCardHolderId": { "equals": "" }, "cardProfileSetId": { "equals": "" } } } } Expected Result: { "data": { "node": { "__typename": "Organization", "id": "", "physicalPaymentCardOrders": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "id": "", "orderState": { "status": "NEW" }, "cardPersonalization": { "textLines": { "line1": "BUSINESS USER", "line2": "JAY" } }, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2000-01-01", "senderDetails": { "name": { "givenName": "John", "middleName": "James", "familyName": "Smith" }, "companyName": "Highnote", "address": { "streetAddress": "1234 Main St", "extendedAddress": "apt 6H", "postalCode": "94132", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "deliveryDetails": { "name": { "givenName": "Business User", "familyName": "BUS", "middleName": "Jay" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "", "postalCode": "60654", "region": "IL", "locality": "Chicago", "countryCodeAlpha3": "USA" } } }, "stateHistory": [ { "previousStatus": null, "newStatus": "NEW", "createdAt": "2024-04-16T22:52:03.617Z" } ], "paymentCard": { "id": "", "bin": "480753", "last4": "7990" }, "createdAt": "2024-04-16T22:52:03.616Z", "updatedAt": "2024-04-16T22:52:04.114Z" } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 143, "limit": 60060, "remaining": 59917 } } } --- URL: https://docs.highnote.com/docs/issuing/cards/manage/display-card-and-acct-details Title: Display Card and Account Details Section: Issuing Description: Display virtual card details using the Card Viewer SDK, show account balances from financial account ledgers, and retrieve account and routing numbers for direct deposit. ## Overview Virtual cards can be displayed in your application or website so the account holder can use their card or view their card information. ## Prerequisites - A Highnote account - An API key or the API Explorer - A payment card and financial account ## Display a card Use the following options for displaying a virtual card: - For web-based applications that want to show the full card information, including card number and expiration, use the Card Viewer SDK. - For native iOS and Android-based integrations, and non-native PCI-compliant environments, securely retrieve and display card details from the API with a Client Token. Use the following query to display a payment card: ## Display a balance Balances are held in a financial account's ledgers. You can display different ledger balances on your website or application so the account holder can monitor their account balance(s). To display balances, you can use a query to retrieve all ledgers on a financial account. Using the data returned from this query, use the or ledgers to display the financial account's balance. Use the following query to find a financial account and display a balance: ## Display account and routing number Prepaid cards have the feature enabled by default. Financial accounts with the 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: ### GraphQL: ViewPaymentCard Query: query ViewPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { id bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { number cvv } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "bin": "411111", "last4": "1111", "expirationDate": "2026-01-01T23:59:59Z", "restrictedDetails": { "number": "4111111111111111", "cvv": "222" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindAccount Query: query FindAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id accountStatus name ledgers { id name normalBalance debitBalance { value currencyCode } creditBalance { value currencyCode } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "status": "ACTIVE", "name": "John Doe - Account", "ledgers": [ { "id": "", "name": "CASH", "normalBalance": "DEBIT", "debitBalance": { "value": 0, "currency": "USD" }, "creditBalance": { "value": 0, "currency": "USD" } }, { "id": "", "name": "ADVANCE_PAYABLE", "normalBalance": "CREDIT", "debitBalance": { "value": 0, "currency": "USD" }, "creditBalance": { "value": 0, "currency": "USD" } } ] } } } ### GraphQL: ViewDirectDepositDetails Query: query ViewDirectDepositDetails($id: ID!) { node(id: $id) { ... on FinancialAccount { directDepositDetails { id restrictedDetails { __typename ... on DirectDepositDetailRestrictedDetails { number routingNumber } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "ExternalBankAccountDetail", "id": "", "last4": "2730", "type": "CHECKING", "restrictedDetails": { "number": "0493712730", "routingNumber": "89703965" } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/cards/manage/manage-cards Title: Manage Cards Section: Issuing Description: Change PINs, lock and unlock cards, reissue expiring or damaged cards, report lost or stolen cards, close cards, and locate surcharge-free ATMs. ## Overview Prepaid and debit cards must have a PIN set after they are issued, and the card must be to set the PIN. ## Change a PIN Cardholders can update their PIN after it has been initially set. - For web-based integrations, we recommend you change a PIN with the Secure Inputs SDK. - For native iOS and Android-based integrations, and non-native PCI-compliant environments, you can securely change a PIN from the API with a Client Token. Use the following mutation to set a PIN for a payment card: ## Lock a card Once a card is active, you can provide an interface for your account holders to lock their payment card. Locking a payment card is useful for scenarios when an account holder loses their card or is not actively using their card. You can connect the mutation to a toggle element in your website or application to create the lock card functionality: ## Unlock a card You can also provide an interface for your account holders to unlock their payment cards. Use the mutation to create the unlock card functionality for your website or application: ## Reissue a card When you **reissue** a card, you maintain card lineage by reusing the network-level Payment Account Reference (PAR). And depending on the reissue reason, you can either reuse or recreate the Primary Account Number (PAN) and Personal Identification Number (PIN). To minimize the risk of fraud, you should only reissue a card that meets the following criteria: - The original card is in possession of the cardholder, e.g., expiring/expired, damaged, or virtual. - The original card is not subject to fraud or potentially subject to fraud. ### Lost and stolen cards It is a best practice to **treat lost and stolen cards the same**, by breaking lineage and issuing a new card, rather than reissuing. #### Stolen Cards Do not reissue stolen cards under any conditions. Always establish a new card lineage. When a card is stolen, our platform reports it to the payment network; so the card should not be reissued, even with a new PAN. Instead, close the old card and issue a new one to **establish a new card lineage**. #### Lost Cards Reissuing a lost card is not a best practice. Consider issuing a new card instead. Highnote recommends that you do not reissue **lost cards** as they are no longer in the possession of the cardholder, and like stolen cards, subject to fraud. If your workflow requires that you maintain lineage for a lost card, you must: - Set = - Create a new PAN: = - Force the user to create a new PIN: = - Populate or an API error is thrown Contact support@highnote.com for help with lost card workflows. For preprinted cards, see Reissue lost preprinted card. ### How to reissue a card When reissuing a card, do not close the original card until you or the cardholder activates the new card. Otherwise, both cards may end up closed if the original card is accidentally closed before the reissued card is activated. Refer the following table when reissuing a card: | Reissue Scenario | Can Reuse PAN? | Can Reuse PIN? | Reissue Reason | Special Condition | | :--------------------------------------------------------------------------------- | :------------: | :------------: | :------------- | :----------------------------------------------------------------------------------- | | Current card is **expiring** soon | Yes | Yes | | must be later than that of original card | | The current card is **damaged**, and the cardholder has possession of the card | Yes | Yes | | | | Current card is **virtual** only and cardholder wants a physical card | Yes | Yes | | must be later than that of original card | | Current card is **lost** and cardholder does not have possession of the card **^** | No | No | | must be populated. must be false or API error is thrown. | ### Reissuing steps The following steps outline an example of how you reissue a card: 1. Start with an original payment card that is _**not**_ in the state. 2. Call to create a new payment card with the same network PAR. By default, new payment cards are virtual cards and attached to the same financial account as the original card. Depending on the reissue reason, you can copy or recreate the PAN and PIN from the original payment card. You can also reissue a physical card if necessary, using an existing or new address for shipping. 3. Recreate or reuse the PAN: If = true, the new payment card will have the same PAN as the original and you can set = true. If = false, the new payment card will have a different PAN from the original and you must (a) set = false, and (b) update to a new date in the future. **Note:** A new CVV is created when the PAN or expiration date changes. 4. When reissuing physical cards, the card should not be active during printing and shipping, as is set to . Even if it has the same card number, it will have a different expiration date and CVV. The virtual card remains active. **Important:** Never ship an active physical card. 5. When the physical card is delivered to the account holder, you may want to activate it. You can only maintain one active reissued payment card at a time. When you activate a reissued card, the old card is immediately deactivated and no longer accepts authorizations. Use the reissuePaymentCard mutation to reissue a card: ### Digital wallet tokens on reissue When you reissue a card, any digital wallet tokens already provisioned to the card (via Apple Pay, Google Wallet, or Samsung Pay) are automatically switched to the reissued card. This applies whether you reuse the PAN or recreate it, and you do not call any additional mutation. The switch happens automatically when the reissued card becomes active. The same token follows the card, so the cardholder can continue using their wallet without re-adding the card. In rare cases, a token might not finish switching to the reissued card. If the cardholder's wallet stops working after a reissue, they _do_ need to re-add the card to their wallet. Reissuing differs from closing a card and issuing a new one. Closing terminates the original card's wallet tokens, so the cardholder must re-provision the new card. ## Close a card Closing a payment card is permanent and closes both virtual cards and any associated physical cards. Use the following mutation to close a card: ### Digital wallet tokens on close Closing the card terminates any digital wallet tokens provisioned to it. Unlike a reissue, a newly issued card starts with no wallet tokens, so the cardholder must add it to their wallet again. ## View card status You can view the status of a payment card, including the suspensionFlags. The suspension must be removed by Highnote if an is on the payment card. Use the following query to lookup a payment card: ## Map ATM locations If you offer payment cards with cash withdrawal capabilities, you may want to provide your account holders with the ability to locate ATMs that do not have surcharges. Note the following when using the query: - Use a radius search when searching around a specific place (address, postal code, landmark, etc.) to retrieve the locations' latitude and longitude. - Set a distance to the radius of the search circle. The distance is expected to be in miles unless overridden. ### Filter ATM search results Filters allow you to refine your ATM location search by including or excluding certain ATM features. By default, the ATM features included are: - - - Use the following query to filter your ATM search results: ### Inclusive ATM filters When using the parameter, ATM location search results will be filtered to only the included values of available ATM features. In the following code snippet example, since the field was provided with the value of , the results from the API will return only the matching locations. ```json title="ATM Filter using includes" { "includes": ["OPEN_24_HOURS"] } ``` ### GraphQL: SetPinForPaymentCard Query: mutation SetPinForPaymentCard($input: SetPinForPaymentCardInput!) { setPinForPaymentCard(input: $input) { __typename ... on PaymentCard { id } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "paymentCardId": "", "newPin": "1234" } } Expected Result: { "data": { "setPinForPaymentCard": { "__typename": "PaymentCard", "id": "" } }, "extensions": { "requestId": "" } } ### GraphQL: SuspendPaymentCard Query: mutation SuspendPaymentCard($input: SuspendPaymentCardInput!) { suspendPaymentCard(input: $input) { ... on PaymentCard { __typename id status } } } Variables: { "input": { "paymentCardId": "" } } Expected Result: { "data": { "suspendPaymentCard": { "__typename": "PaymentCard", "id": "", "status": "SUSPENDED" } }, "extensions": { "requestId": "" } } ### GraphQL: ActivatePaymentCard Query: mutation ActivatePaymentCard($input: ActivatePaymentCardInput!) { activatePaymentCard(input: $input) { ... on PaymentCard { id status } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "paymentCardId": "" } } Expected Result: { "data": { "activatePaymentCard": { "id": "", "status": "ACTIVE" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 100000, "remaining": 99989 } } } ### GraphQL: ReissuePaymentCard Query: mutation ReissuePaymentCard($input: ReissuePaymentCardInput!) { reissuePaymentCard(input: $input) { ... on PaymentCard { id last4 expirationDate status originalPaymentCard { id } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "originalPaymentCardId": "", "options": { "activateOnCreate": false, "expirationDate": "2025-01-01T23:59:59Z", "reissueFeatures": { "copyNumber": true, "copyPin": false } } } } Expected Result: { "data": { "reissuePaymentCard": { "id": "", "last4": "4876", "expirationDate": "2025-01-01T23:59:59Z", "status": "ACTIVATION_REQUIRED", "originalPaymentCard": { "id": "" } } } } ### GraphQL: ClosePaymentCard Query: mutation ClosePaymentCard($input: ClosePaymentCardInput!) { closePaymentCard(input: $input) { ... on PaymentCard { __typename id status } } } Variables: { "input": { "paymentCardId": "" } } Expected Result: { "data": { "closePaymentCard": { "__typename": "PaymentCard", "id": "", "status": "CLOSED" } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { id bin last4 expirationDate network status formFactor suspensionFlags cardProductApplication { __typename ... on Node { id } ... on AccountHolderCardProductApplication { id applicationState { status } } } } } } Variables: { "input": { "paymentCardId": "" } } Expected Result: { "data": { "node": { "id": "", "bin": "510520", "last4": "5788", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "SUSPENDED", "formFactor": "VIRTUAL", "suspensionFlags": [ "PROGRAM_OWNER_INITIATED_SUSPENSION", "ISSUER_INITIATED_SUSPENSION" ], "cardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "APPROVED" } } } }, "extensions": { "requestId": "4c036a05-f2a3-9bee-bab6-0f85b89bca00", "rateLimit": { "cost": 20, "limit": 60060, "remaining": 60040 } } } ### GraphQL: FindATMLocationsForPaymentCardByRadius Query: query FindATMLocationsForPaymentCardByRadius( $paymentCardId: ID! $radius: ATMLocationRadiusInput! ) { node(id: $paymentCardId) { __typename ... on PaymentCard { id bin last4 atmLocations(radius: $radius) { ... on AtmLocationsResult { ... on ATMLocations { atmLocations { name description logo { brand } features address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } coordinates { latitude longitude } distance { length unit } } } ... on UserError { errors { errorPath code description } } } } } } } Variables: { "paymentCardId": "", "radius": { "coordinates": { "latitude": "41.40338", "longitude": "2.17403" }, "distance": { "length": 10, "unit": "MILE" } } } Expected Result: { "data": { "node": { "__typename": "PaymentCard", "id": "", "bin": "547203", "last4": "4841", "atmLocations": { "atmLocations": [ { "name": "7ELEVEN-FCTI", "description": "3519 N CLARK STREET, CHICAGO, IL 60657", "logo": { "brand": "MONEY_PASS" }, "features": [ "OPEN_24_HOURS" ], "address": { "streetAddress": "3519 N CLARK STREET", "extendedAddress": "", "postalCode": "60657", "region": "IL", "locality": "CHICAGO", "countryCodeAlpha3": "USA" }, "coordinates": { "latitude": "41.9462127640016", "longitude": "-87.6555914957832" }, "distance": { "length": 0.129139, "unit": "MILE" } }, { "name": "7ELEVEN-FCTI", "description": "1027 W ADDISON ST, CHICAGO, IL 60613", "logo": { "brand": "MONEY_PASS" }, "features": [ "OPEN_24_HOURS" ], "address": { "streetAddress": "1027 W ADDISON ST", "extendedAddress": "", "postalCode": "60613", "region": "IL", "locality": "CHICAGO", "countryCodeAlpha3": "USA" }, "coordinates": { "latitude": "41.9469968", "longitude": "-87.6554665" }, "distance": { "length": 0.183594, "unit": "MILE" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: FindATMLocationsForPaymentCardWithFilter Query: query FindATMLocationsForPaymentCardWithFilter( $paymentCardId: ID! $radius: ATMLocationRadiusInput! $filter: ATMLocationFilterInput! ) { node(id: $paymentCardId) { __typename ... on PaymentCard { id bin last4 atmLocations(radius: $radius, atmFilter: $filter) { ... on AtmLocationsResult { ... on ATMLocations { atmLocations { name description logo { brand } features address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } coordinates { latitude longitude } distance { length unit } } } ... on UserError { errors { errorPath code description } } } } } } } Variables: { "paymentCardId": "", "radius": { "coordinates": { "latitude": "41.40338", "longitude": "2.17403" }, "distance": { "length": 10, "unit": "MILE" } }, "filter": { "includes": [ "OPEN_24_HOURS" ] } } Expected Result: { "data": { "node": { "__typename": "PaymentCard", "id": "", "bin": "547203", "last4": "4841", "atmLocations": { "atmLocations": [ { "name": "7ELEVEN-FCTI", "description": "3519 N CLARK STREET, CHICAGO, IL 60657", "logo": { "brand": "MONEY_PASS" }, "features": [ "OPEN_24_HOURS" ], "address": { "streetAddress": "3519 N CLARK STREET", "extendedAddress": "", "postalCode": "60657", "region": "IL", "locality": "CHICAGO", "countryCodeAlpha3": "USA" }, "coordinates": { "latitude": "41.9462127640016", "longitude": "-87.6555914957832" }, "distance": { "length": 0.129139, "unit": "MILE" } }, { "name": "7ELEVEN-FCTI", "description": "1027 W ADDISON ST, CHICAGO, IL 60613", "logo": { "brand": "MONEY_PASS" }, "features": [ "OPEN_24_HOURS" ], "address": { "streetAddress": "1027 W ADDISON ST", "extendedAddress": "", "postalCode": "60613", "region": "IL", "locality": "CHICAGO", "countryCodeAlpha3": "USA" }, "coordinates": { "latitude": "41.9469968", "longitude": "-87.6554665" }, "distance": { "length": 0.183594, "unit": "MILE" } } ] } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/cards/manage/payment-card-revisions Title: Payment Card Revisions Section: Issuing Description: Query the revision history of a payment card to track status changes, form factor updates, and reissuance events for compliance and fraud detection. ## Overview When a payment card is issued or updated, the action is recorded in Highnote as a revision. A revision record captures the snapshot of the PaymentCard object before the changes to it were applied. The following types of payment card actions result in a revision: - Issue - Reissue - Activate/deactivate - Suspend - Terminate - Update other attributes: currently, only card form factor and card usage You can use the Highnote API to view the revision on a payment card. The following revision data types are supported: | Revision type | Description | | :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Card status | Available enums: , , , . See PaymentCardStatus | | Card form factor | Available enums: , . See CardFormFactor | | Expiration date | ISO 8601 UTC timestamp of payment card expiry date | | Card usage | Available enums: , . See CardUsage | | Updated timestamp | ISO 8601 UTC timestamp when the revision took place | | Status change reason | Available enums: , , , , . See PaymentCardStatusChangeReason | ## Use cases - **Traceability and Troubleshooting:** By tracking when these changes were made (with the timestamp), organizations can quickly trace the origins of issues or unauthorized modifications. - **Compliance and Auditing:** Maintaining a thorough record of all updates assists in compliance with financial regulations, providing auditors with a transparent view of the card's history. - **Security and Fraud Prevention:** Historical logs of status changes are invaluable for detecting patterns that may indicate fraudulent activity. - **Operational Insights:** Analysis of updates over time can reveal trends in card usage and lifecycle management, informing strategic decisions. ## Find payment card revisions You can use the following query to find revisions associated with a payment card. Additionally, the attribute can be included on queries that support the object. ### GraphQL: FindPaymentCardRevisionSnapshot Query: query FindPaymentCardRevisionSnapshot($id: ID!, $first: Int, $after: String) { node(id: $id) { __typename ... on PaymentCard { id revisionSnapshots(first: $first, after: $after) { edges { node { __typename ... on PaymentCardSnapshot { id expirationDate expirationMonth expirationYear status statusChangeReason statusChangeMemo formFactor usage updatedAt } } } } } } } Variables: { "id": "", "first": 10, "after": "" } Expected Result: { "data": { "node": { "__typename": "PaymentCard", "id": "", "revisionSnapshots": { "edges": [ { "node": { "__typename": "PaymentCardSnapshot", "id": "cdrev_1", "expirationDate": "2026-07-01T07:00Z", "expirationMonth": "07", "expirationYear": "26", "status": "ACTIVE", "statusChangeReason": "CREATED", "statusChangeMemo": "", "formFactor": "VIRTUAL", "usage": "MULTI_USE", "updatedAt": "2024-07-25T21:31:46.836Z" }, "__typename": "PaymentCardSnapshotEdge" } ], "__typename": "PaymentCardSnapshotConnection" } } }, "extensions": { "requestId": "7bb9234a-0fe8-9156-83f0-d28c2c84684d", "rateLimit": { "cost": 23, "limit": 60060, "remaining": 56603 } } } --- URL: https://docs.highnote.com/docs/issuing/cards/marketing/co-brands Title: Co-Brands Section: Issuing Description: Partner with other companies to create co-branded card products. Covers the Highnote and Partner Bank approval process. ### Working with co-brands You can partner with other companies to customize and issue cards to enhance customer loyalty and brand visibility. These partnered companies are referred to as **co-brands**. ### Launching co-brands Co-brands must be approved by Highnote and the Bank Partner for your card program. To launch a co-brand: 1. Contact your Highnote Customer Success Manager to enable co-brands on your program. 2. When you a ready to kick off the co-brand process, contact cobrands@highnote. Highnote will share additional information on what you need to submit. 3. See the supporting materials under Resources for additional details. ### Resources - Guidelines: Marketing and Collateral and Cards in Marketing - Supporting materials: - CFSB: - Cobranding with Highnote - Beneficial Ownership Certification Form - Sutton Bank: - Cobranding with Highnote - Vendor Ownership Information Sheet (2025) --- URL: https://docs.highnote.com/docs/issuing/cards/marketing/marketing-and-collateral Title: Marketing and Collateral Section: Issuing Description: Submit marketing materials and collateral for Highnote and Partner Bank approval. Covers regulatory requirements including UDAAP and CAN-SPAM compliance. ## Overview Marketing materials should accurately describe Subscriber card program offerings, utilize clear and conspicuous language to ensure applicants and/or cardholders understand important terms about the card offering (i.e., the costs associated with having and using the card), and ensure fairness in the marketing practices of the program. General guidance when it comes to these materials is that all customer facing materials must be reviewed and approved by Highnote and its Partner Bank. To submit marketing materials, Subscribers must email documents to collateral-review@highnote.com prior to production or use. ## Definitions - **Marketing Material**: Any digital or printed materials used to communicate, promote, or disseminate information about a Card Product - **Partner Bank**: The Highnote Partner Bank who approved the Subscriber Card Program - **Subscriber**: A bank-approved Highnote customer who is offering a specific Card Product - **Account Holder**, **Card Holder**, **Customer**, or **End User**: Any person or business entity to whom a card is issued and has agreed to the obligations set forth in the Subscriber Cardholder Agreement - **Network**: Refers to Visa or Mastercard card networks ## Material for review If an Account Holder or potential Account Holder is going to see or read anything related to the Payment Card or Card Product, it needs to undergo the collateral review process. Please note that items should be submitted even if there is a question or concern that may not be relevant. The following are required to be reviewed for collateral approval: - Card Designs, Virtual, Physical, and Tokenized - Card Inserts - Marketing and Advertisements, including websites/Subscriber landing pages, flyers, media releases, mailers, commercials (TV, radio, podcasts, online, social media, blog posts, etc.), and emails - Documents including Account Holder Agreements, Terms and Conditions (Terms of Use), Short Form Disclosures, Long Form Disclosures, Privacy Notice Form, Frequently Asked Questions, Privacy Policy, Rewards Terms and Conditions, Authorized User Terms, etc. Any other agreements or disclosures used must be approved by Highnote and its Partner Bank. - Customer communications/dispute resolution material, including IVR Flows, response templates, Adverse Action Notice Templates, Application screens for products, UX from mobile device app screens, Servicing/Account Dashboards, chat responses, call scripts, training materials, predetermined responses/scripts, reference documents It is important that verbiage across all of these materials is clear and conspicuous for the Account Holder (and/or consumer) to understand the terms of, as well as general details around, the Card Product. ## Review process Marketing materials cannot be published until the Subscriber’s Card Product application to work with Highnote has been approved. ## Review process notes Note the following regarding the review process: - Ensure your naming convention includes the name of your business and a brief description of the marketing item, for example, "Highnote.CardArt.pdf". - Materials are to be reviewed within five to 10 business days from the date of receipt confirmation by Highnote. Highnote often delivers marketing material responses sooner than the aforementioned time frame. - Materials are reviewed and approved by both Highnote and Partner Bank. - If any changes to the materials are required, such as wording or graphics, materials must be resubmitted for final approval prior to production and use. - A clean version, which when appropriate includes the approved date, must be sent back to Highnote for internal records and partner bank records. - Once approved, Highnote will respond back to the Subscriber with confirmation. - After approval, resubmission of materials is required when changes to the product or the information being communicated to the Account Holder is changed. - Resubmissions undergo the same five to 10 business day Service Level Agreement (SLA) timeframe. ## General guidelines General guidelines for marketing and collateral are included in this section. It is the responsibility of the Subscriber to ensure the submitted marketing materials comply with UDAP/UDAAP, CAN-SPAM, and any other applicable regulations. ### What to do - Ensure all marketing materials are clear and conspicuous. Be mindful of the 4 P's standard under UDAAP (placement, proximity, prominence, and presentation). - Ensure the Program name and Network name are the same text size. - Ensure the Program name utilizes proper capitalization and punctuation, following the approved Program with Highnote and the Partner Bank. For example, “Prepaid” instead of "Pre-paid" or "PrePaid". - For Mastercard Debit cards, “debit” should be utilized if listed on the front of the card with the Mastercard logo. - Ensure card details reflect the approved Program with Highnote and the Partner Bank. - The Partner Bank/Lender Issuing Statement must be included on any materials where the payment card is shown or referenced. For credit products, "subject to credit approval" disclosure must be included. - Ensure pictures and images in materials portray the Partner Bank as inclusive rather than exclusive with respect to race, color, religion, national origin, sex, marital status, age, or any right under the Consumer Credit Protection Act (the "Prohibited Bases"). - Include information about terms that are actually available; if marketing materials mention specific credit terms, you must provide those terms to applications qualifying for the offer. - Ensure fees or finance charges include an explanation about how the fee/finance charge and amount will be determined. ### What not to do - Include unfair, deceptive, abusive acts or practices (UDAP/UDAAP) information. - Use language suggesting the **Subscriber** is a bank or offers banking services; exceptions apply for Demand Deposit Accounts (DDA). - Language that states digital or mobile banking is permitted. - Reference offerings the Product does not offer. - Say "free" or "no fees" when there is a potential for fees. Language such as "no hidden fees" should also be avoided. - Include language that discourages a potential application from applying for credit based on one or more Prohibited Bases. - Use express claims that are not easily substantiated, such as "free" products or services: "no fees," "instant approval," etc. - Use comparison tables of rates, fees, or other credit terms. ## Use of “Bank” and “Banking” Refer to the following guidelines on the use of "Bank" and "Banking" in Marketing and Collateral materials: - A bank is a financial institution licensed to receive deposits and provide other services such as mortgage loans and individual retirement accounts. A chartered bank is a financial institution in the business of providing monetary transactions, such as safeguarding deposits and making loans. - “Bank” and ”Banking” cannot be used in URLs, documents, marketing materials, or other customer-facing materials that would represent the Subscriber as a licensed bank. - The Subscriber must clarify the program is a FinTech and make the distinction that it is not a bank in all publications and materials. Banking services are provided by the Partner Bank. - Marketing materials cannot use language stating, for example, “opening a [Subscriber] bank account” or “how to open a bank account with [Subscriber].” Instead, an option would be to say, "open an account through [Subscriber]." - Google search results must place a statement on Google or other ads that banking services are provided by Partner Bank. - Frequently Asked Questions (FAQs) must include a section that explains that accounts are held at the Partner Bank. - During account setup, there must be a clear and prominent statement to inform consumers that your company is a FinTech, not a bank and that banking services are provided by the Partner Bank. - Company description must be clear that you are not a bank. It is suggested to put a “What is [Company Name]” section in the FAQs. Subscribers should ensure that all marketing, disclosures, and communications accurately represent the nature of account features and protections, avoiding any misrepresentation regarding deposit insurance coverage or guarantees. ## Issuing statement Issuing statements are required to appear anytime the Program or the Network is identified or displayed in any form of marketing materials. Your Highnote Implementation and Customer Success Team can provide you with the specific statement for your Partner Bank and Network. ### Statement guidelines - When displaying Partner Banks, naming conventions must abide by approved formatting. - Similarly, if the Partner Bank is mentioned as a corporate organization, Highnote can provide an approved description. - For websites, the issuing statement must appear at the bottom of each website page where the Program or Network is identified or displayed. - For In-App/Virtual Cards, the issuing statement can be displayed on the app screen where the card, Program, or Network is identified. Other location options for the issuing statement include a link on the screen where the card, Program, or Network is mentioned that directs the customer to the issuing statement or an icon on the screen where the card, Program, or Card Network is mentioned in which the customer can touch or hover that displays the issuing statement. - For Commercials, the issuing statement must appear at the end of the commercial. - For Physical Cards, the issuing statement must appear on the Physical Card. - For emails, the issuing statement must appear at the bottom of each email. ## Registered trademark symbol At the first mention of the Network (Mastercard, Visa, or Discover), the registered trademark symbol (®) must be present. The registered trademark symbol (®) may stop being used when the Network is mentioned again in the same document. Brand marks may not be used in place of a brand name. ## Trademark statement The Trademark Statement should appear below the Issuing Statement on non-card materials that reference the Card Product. ### Mastercard Mastercard and the circles design are registered trademarks of Mastercard International Incorporated. ### Visa Visa is a registered trademark of Visa, U.S.A. Inc. All other trademarks and service marks belong to their respective owners. ## Lotteries, sweepstakes, and contests A Card Product cannot participate in any type of lottery, sweepstake, or contest without the express permission of Highnote, the Partner Bank, and Network brand. Common definitions to consider when evaluating lotteries, sweepstakes, and contests include: - Lottery is a promotion that will be considered a lottery if it has, consideration to enter, chance and/or a prize. - Sweepstake is a random drawing or a prize. - Contest is a true competition, skill replaces chance, such as a best photo contest. The FDIC and networks have strict guidelines relating to these practices. See FDIC Federal Deposit Insurance Act for more information. ## Rewards and promotions Any promotion and/or reward that is offered through a Subscriber product or service must be compliant with applicable laws and regulations and must be accompanied by the terms and conditions to receive such reward or promotion. The terms and conditions should be prominently displayed within close proximity to the advertised offer. At a minimum, the terms and conditions must include: - Description of the rewards of promotion; - Eligibility requirements that the customer must fulfill to obtain the reward or promotion; - Date range(s) the rewards or promotions offer will be valid; - Any restrictions that apply; - Instructions detailing the process for redeeming rewards; and - Details of any expiration of the rewards or promotions ## TILA/Reg Z triggering Terms If advertisements for consumer loans and other credit-related products contain certain terms from the credit agreement, whether in print, broadcast, or online, then the advertisement must also contain specified disclosures. This regulatory requirement is meant to protect consumers from predatory advertising and lending practices. If the following terms are used when advertising Closed-End Credit: - The amount of a down payment expressed as a percentage or a dollar amount (example: "As little as 3% down" or "90% financing"); - The amount of any payment expressed as a percentage or a dollar amount (example: "$20 per month" or "monthly payments of under $50"); - The number of payments (example: "36 monthly payments" or "10 small payments is all you owe"); - The total time required to pay and the period of repayment (example: "5-year loans available" or "just 36 low monthly payments"); Or - The finance charge amount (example: "Less than $300 interest" or "financing costs less than $100"); Then, the ad must disclose the following: - The amount or percentage of the downpayment; - The terms of repayment, which reflect the repayment obligations over the full term of the loan, including any balloon payment; and - The "annual percentage rate" using that term, and disclose (if applicable) that the APR may be increased after consummation. For Open-End Credit, if the finance charge and other payment terms required to be disclosed at account opening are included in an advertisement, then it must state the following additional disclosures: - The minimum, fixed, transaction, activity, or similar finance charge that could be imposed; - The periodic rate that may be applied expressed as an annual percentage rate (APR) - If the plan provides for variable rates, that must also be disclosed; and - The membership or participation fees that could be imposed. Keep in mind that triggering terms do not need to be explicitly stated; additional disclosures are required if the terms can be inferred from the advertisement. For instance, if an advertisement states, "80 percent financing available," it implies a 20 percent down payment is required, which qualifies as a triggering term. Negative, as well as affirmative, statements trigger the requirement for additional information. For example, stating that a plan has "no interest" or "no annual membership fee" in an advertisement would require additional disclosures. Additionally, if an advertisement references specific credit terms, it must only include terms the creditor is genuinely prepared to offer. For instance, a creditor cannot advertise an exceptionally low annual percentage rate that will never actually be available. This rule does not restrict the promotion of new credit programs but prohibits the advertising of terms that are unavailable or will never be offered. For example, a creditor may promote terms that will be available for a limited time or will take effect on a future date. Finally, disclosures must always be _clear and conspicuous_, and in a _reasonably understandable form_. --- URL: https://docs.highnote.com/docs/issuing/cards/marketing/advertising-guidelines Title: Cards in Marketing Section: Issuing Description: Display cards in marketing materials following Visa and Mastercard image standards. Includes sample card numbers, issuing statements, and acceptance language. ## Overview See the advertising guidelines below. If you have questions about additional standards, partner with Highnote to see if there are any other Card Network-approved variances. - Card Network image must be present. - Payment Card must be clear and legible. - Card Network symbol must be fully visible; a partial Card Network symbol is not permitted. - Payment Card image standards mentioned in the Physical Card section apply. - Payment Card image must be approved by Highnote and Partner Bank prior to use in marketing materials - Issuing statement must appear on the same page as the card image. - Acceptance language is to be included on all applicable collateral material except Card Art and Design, Activation Stickers, Envelopes, and other items designated by the partner bank. Example language, “The card may be used anywhere Mastercard is accepted. An account number is optional. If an account number is included, the expiration date and the cardholder name must be present. - For Mastercard, if a cardholder name is used, it must be Lee M. Cardholder, and the account number must be 5412 7512 3412 3456. - For Visa, the account number must be 4000 1234 5678 9010, and there is no required cardholder name for Visa. - For Discover, the account number must be 6011 0000 0000 0000, and there is no required cardholder name for Discover. - For Mastercard and Visa, the expiration date should go out at least three (3) years. Language should clearly be stated to ensure a consumer does not believe a line of credit or something similar is permitted. - Correct usage of applicable terms include: “Maximum value”, “Card value”, “Amount stored in your card account”, “Maximum load on your card” and “Funds available”. - Do not utilize phrases such as “Cash limit,” “Card limit,” and “Prepaid limit”. ## Virtual card/account {#virtual-card-account} A virtual account is established for online or mobile application commerce. A physical card is not issued for the account. ### Required items - Card Network Symbol - Primary Account Number (PAN) - Card Validation Code (CVC) - Expiration Date - Issuer Identification ### Prohibited items - Chip - Magnetic Strip - Signature Panel ### Card images Exact replica of corresponding physical card or neutral-color background. If there is no physical card for the Card Product, please abide by the following: Background images must contrast with the Network image, meaning the Network image should not blend in with the card art. **Prohibited background images include, but not limited to:** - Sexual subject matter - Political subject matter - Offensive racial/prejudicial/religious subject matter - Advertising - Self-promotion, meaning personal business card - Brand products - Solicitations ## Physical card Included are general guidelines for a physical card. The Card Network may have more specific guidance, and Subscribers can partner with Highnote should there be unique use cases where Network guidance is required. ### Required items - Card Network Symbol on front of card - Primary Account Number (PAN) on front or back of card - Card Validation Code (CVC) on back of card - Expiration date on front or back of card - Issuing statement on front or back of card - Magnetic Stripe on back of card - Customer Support contact information (phone number) on the back of the card ### Card images Background images must contrast with the Card Network image, meaning the Card Network image should not blend in with the card art **Prohibited background images include, but not limited to:** - Sexual subject matter - Political subject matter - Offensive racial/prejudicial/religious subject matter - Advertising - Self-promotion, meaning personal business card - Brand products - Solicitations ## Digital wallet A tokenized card is a representation of a physical card for display within a digital wallet. ### Required items - Card Network Symbol - Last four digits of Primary Account Number (PAN) (Mastercard tokenized only) - Full PAN, Card Validation Code (CVC), and expiration date (Mastercard non-tokenized only) ### Card images A replica of the corresponding physical card or neutral-color background. If there is no physical card for the Card Product, please abide by the following: Background images must contrast with the Card Network image, meaning the Network image should not blend in with the card art. **Prohibited background images include, but not limited to:** - Sexual subject matter - Political subject matter - Offensive racial/prejudicial/religious subject matter - Advertising - Self-promotion, meaning personal business card - Brand products - Solicitations --- URL: https://docs.highnote.com/docs/issuing/cards/simulations/sim-address-validation Title: Simulate Address Validation Section: Issuing Description: Simulate shipping address validation responses in the Test environment using keywords to trigger changed, incomplete, or invalid address results. ## Overview Do not enter production data in the Test environment. The Highnote Test environment is for exploring features and training. Use only dummy or test data. Before submitting a physical card order, you can validate the card order's shipping address to ensure it is properly formatted and CASS-certified. For more information on shipping address validation, see Validate shipping address. Highnote provides a simulation for validating a shipping address in the Test environment. This simulation can be used to test your card product's physical card order flow and notification events. This guide provides steps for simulating shipping address validation for card orders. ## Prerequisites - A Highnote account - An API key or the API Explorer - An individual card order or group card order ## Simulate valid address Use the following mutation to simulate a successful address validation: ## Simulate address with changes You can simulate an address with changes response by using the keyword in the field of an address validation query. Use the following mutation to simulate an response: ## Simulate incomplete address You can simulate an incomplete address response by using the keyword in the field of an address validation query. Use the following mutation to simulate an response: ## Simulate invalid address You can simulate an invalid address response by using the keyword in the field of an address validation query. Use the following mutation to simulate an response: ### GraphQL: validateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "IDEMPOTENCY-KEY", "address": { "streetAddress": "24 Willie Mays Plz", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressValidatedResult", "token": { "id": "", "provided": { "streetAddress": "24 Willie Mays Plz", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" }, "standardized": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "locality": "SAN FRANCISCO", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" }, "labels": [ "BUSINESS" ], "createdAt": "2024-06-18T17:23:46.591Z" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 14 } } } ### GraphQL: validateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "IDEMPOTENCY-KEY", "address": { "streetAddress": "changed", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressValidatedWithChangesResult", "componentsChanged": [ "STREET_ADDRESS", "POSTAL_CODE" ], "token": { "id": "", "provided": { "streetAddress": "changed", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94107", "countryCodeAlpha3": "USA" }, "standardized": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "locality": "SAN FRANCISCO", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" }, "labels": [ "BUSINESS" ] } } } }, "extensions": { "requestId": "b3b86ea0-fcaf-98d7-abe8-fa12660d8049", "rateLimit": { "cost": 14 } } } ### GraphQL: validateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "IDEMPOTENCY-KEY", "address": { "streetAddress": "changed", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressValidatedWithChangesResult", "componentsChanged": [ "STREET_ADDRESS", "POSTAL_CODE" ], "token": { "id": "", "provided": { "streetAddress": "changed", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94107", "countryCodeAlpha3": "USA" }, "standardized": { "streetAddress": "24 WILLIE MAYS PLZ", "extendedAddress": "", "locality": "SAN FRANCISCO", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" }, "labels": [ "BUSINESS" ] } } } }, "extensions": { "requestId": "b3b86ea0-fcaf-98d7-abe8-fa12660d8049", "rateLimit": { "cost": 14 } } } ### GraphQL: validateAddress Query: mutation validateAddress($input: ValidateAddressInput!) { validateAddress(input: $input) { __typename ... on AddressValidationResult { outcome { ... on AddressInvalidResult { __typename componentsInvalid provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressIncompleteResult { __typename componentsMissing provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } ... on AddressValidatedWithChangesResult { __typename componentsChanged token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } ... on AddressValidatedResult { __typename token { id provided { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } standardized { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } labels createdAt } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "idempotencyKey": "IDEMPOTENCY-KEY", "address": { "streetAddress": "invalid", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } Expected Result: { "data": { "validateAddress": { "__typename": "AddressValidationResult", "outcome": { "__typename": "AddressInvalidResult", "componentsInvalid": [ "STREET_ADDRESS" ], "provided": { "streetAddress": "invalid", "extendedAddress": "", "locality": "San Francisco", "region": "CA", "postalCode": "94107-2134", "countryCodeAlpha3": "USA" } } } }, "extensions": { "requestId": "7d078e74-7e17-9a0a-a3e3-2ef053deec75", "rateLimit": { "cost": 14 } } } --- URL: https://docs.highnote.com/docs/issuing/cards/simulations/sim-card-order-fulfillment Title: Simulate Card Order Fulfillment Section: Issuing Description: Simulate individual and group physical card order lifecycles in the Test environment by transitioning orders through fulfillment statuses. ## Overview Do not enter production data in the Test environment. The Highnote Test environment is for exploring features and training. Use only dummy or test data. Highnote offers simulations for individual and group physical card order fulfillment. In the Test environment, physical card orders are not physically shipped. You can use these simulations to test the following: - Your card product's physical card order flow - Notification events This guide provides steps for simulating physical card order fulfillment for individual and group card orders. ## Prerequisites - A Highnote account - An API key or the API Explorer - An individual card order or group card order ## Card order fulfillment lifecycle When any type of card order is placed, the order follows the following sequence: 1. Card order is sent to the printer. 2. The shipment is approved. 3. The card order is shipped. 4. _Optional_ - The card order fails. You can use the Highnote API to update the status of a physical card order and simulate the card order lifecycle to test your integration. ## Simulate individual card order fulfillment Use the following sections to simulate an individual card order. ### Send to printer Once you have created a physical card order with a status of , you can transition it to . Use the following mutation to simulate sending a physical payment card order to the printer: ### Approve shipment Once a physical card order has been , you can approve the order and change the status to . Use the following mutation to simulate approving a physical payment card order: ### Ship order Orders with a status of may be transitioned to and will return the shipping method, and if available, tracking number. Use the following mutation to simulate shipping a physical payment card order: ### Fail order To design your system to handle failed individual card order shipments, you can simulate a status of . ## Simulate group order fulfillment You can simulate group order fulfillment in the Test environment without actually shipping cards. This is useful for simulating group order statuses and notifications. ### Send order to printer You can use the mutations provided in this guide to create and complete a group order. A completed order will have a status of . Use the following mutation to transition the group order to status: ### Approve shipment Once the group order has been , you can change the status to using the following mutation: ### Ship order For an overview of group order shipping methods, see Shipping Methods. After a group order is approved, you can use the following mutation to transition to the status. The shipping method and tracking number (if available) will be returned in the response payload: ### Fail order To design your system to handle failed Group Order shipments, you can simulate a status of . ## Automate your integration To automate your integration, use the following notification events: - **Physical card fulfillment:** Use this notification event to stay notified when an individual card order ships or fails - **Physical card group order:** Use this notification to stay notified when a physical card group order ships or fails The details provided in the payloads from these events can be used for the following use cases: - Automate your application or website's card order fulfillment workflows - Create account holder notifications and alerts - Create status views for card orders in your application or website ### GraphQL: simulatePhysicalPaymentCardOrderSendToPrinter Query: mutation simulatePhysicalPaymentCardOrderSendToPrinter( $input: SimulatePhysicalPaymentCardSendToPrinterInput! ) { simulatePhysicalPaymentCardOrderSendToPrinter(input: $input) { __typename ... on PhysicalPaymentCardOrder { id orderState { status } cardPersonalization { textLines { line1 line2 } } paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate senderDetails { name { givenName middleName familyName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } deliveryDetails { name { givenName familyName middleName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } stateHistory { previousStatus newStatus createdAt } paymentCard { id bin last4 } createdAt updatedAt } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "physicalPaymentCardOrderId": "" } } Expected Result: { "data": { "simulatePhysicalPaymentCardOrderSendToPrinter": { "__typename": "PhysicalPaymentCardOrder", "id": "", "orderState": { "status": "SENT_TO_PRINTER" }, "cardPersonalization": { "textLines": { "line1": "RUSTY EARNHARDT", "line2": "" } }, "paymentCardShipment": { "courier": { "method": "USPS_GROUND", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-04-27", "senderDetails": { "name": { "givenName": "John", "middleName": "James", "familyName": "Smith" }, "companyName": "Highnote", "address": { "streetAddress": "1234 Main St", "extendedAddress": "apt 6H", "postalCode": "94132", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "deliveryDetails": { "name": { "givenName": "Rusty", "familyName": "Earnhardt", "middleName": "" }, "companyName": null, "address": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "12345", "region": "AL", "locality": "Anywhere", "countryCodeAlpha3": "USA" } } }, "stateHistory": [ { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-04-27T14:34:37.131Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-04-27T14:26:20.532Z" } ], "paymentCard": { "id": "", "bin": "511112", "last4": "0200" }, "createdAt": "2022-04-27T14:26:20.532Z", "updatedAt": "2022-04-27T14:34:37.138Z" } }, "extensions": { "requestId": "" } } ### GraphQL: simulatePhysicalPaymentCardOrderApproval Query: mutation simulatePhysicalPaymentCardOrderApproval( $input: SimulatePhysicalPaymentCardApprovalInput! ) { simulatePhysicalPaymentCardOrderApproval(input: $input) { __typename ... on PhysicalPaymentCardOrder { id orderState { status } cardPersonalization { textLines { line1 line2 } } paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate senderDetails { name { givenName middleName familyName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } deliveryDetails { name { givenName familyName middleName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } stateHistory { previousStatus newStatus createdAt } paymentCard { id bin last4 } createdAt updatedAt } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "physicalPaymentCardOrderId": "" } } Expected Result: { "data": { "simulatePhysicalPaymentCardOrderApproval": { "__typename": "PhysicalPaymentCardOrder", "id": "", "orderState": { "status": "APPROVED" }, "cardPersonalization": { "textLines": { "line1": "RUSTY EARNHARDT", "line2": "" } }, "paymentCardShipment": { "courier": { "method": "USPS_GROUND", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-04-27", "senderDetails": { "name": { "givenName": "John", "middleName": "James", "familyName": "Smith" }, "companyName": "Highnote", "address": { "streetAddress": "1234 Main St", "extendedAddress": "apt 6H", "postalCode": "94132", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "deliveryDetails": { "name": { "givenName": "Rusty", "familyName": "Earnhardt", "middleName": "" }, "companyName": null, "address": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "12345", "region": "AL", "locality": "Anywhere", "countryCodeAlpha3": "USA" } } }, "stateHistory": [ { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2022-04-27T14:37:47.691Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-04-27T14:34:37.131Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-04-27T14:26:20.532Z" } ], "paymentCard": { "id": "", "bin": "511112", "last4": "0200" }, "createdAt": "2022-04-27T14:26:20.532Z", "updatedAt": "2022-04-27T14:37:47.692Z" } }, "extensions": { "requestId": "" } } ### GraphQL: simulatePhysicalPaymentCardOrderShipped Query: mutation simulatePhysicalPaymentCardOrderShipped( $input: SimulatePhysicalPaymentCardShippedInput! ) { simulatePhysicalPaymentCardOrderShipped(input: $input) { __typename ... on PhysicalPaymentCardOrder { id orderState { status } cardPersonalization { textLines { line1 line2 } } paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate senderDetails { name { givenName middleName familyName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } deliveryDetails { name { givenName familyName middleName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } stateHistory { previousStatus newStatus createdAt } paymentCard { id bin last4 } createdAt updatedAt } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "physicalPaymentCardOrderId": "", "trackingNumber": "92001234567890123456", "actualShipDate": "2026-04-03" } } Expected Result: { "data": { "simulatePhysicalPaymentCardOrderShipped": { "__typename": "PhysicalPaymentCardOrder", "id": "", "orderState": { "status": "SHIPPED" }, "cardPersonalization": { "textLines": { "line1": "RUSTY EARNHARDT", "line2": "" } }, "paymentCardShipment": { "courier": { "method": "USPS_GROUND", "signatureRequiredOnDelivery": false, "tracking": { "trackingNumber": "92001234567890123456", "actualShipDateLocal": "2026-04-03" } }, "requestedShipDate": "2026-04-03", "senderDetails": { "name": { "givenName": "John", "middleName": "James", "familyName": "Smith" }, "companyName": "Highnote", "address": { "streetAddress": "1234 Main St", "extendedAddress": "apt 6H", "postalCode": "94132", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "deliveryDetails": { "name": { "givenName": "Rusty", "familyName": "Earnhardt", "middleName": "" }, "companyName": null, "address": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "12345", "region": "AL", "locality": "Anywhere", "countryCodeAlpha3": "USA" } } }, "stateHistory": [ { "previousStatus": "APPROVED", "newStatus": "SHIPPED", "createdAt": "2026-04-03T14:39:12.137Z" }, { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2026-04-03T14:37:47.691Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2026-04-03T14:34:37.131Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2026-04-03T14:26:20.532Z" } ], "paymentCard": { "id": "", "bin": "511112", "last4": "0200" }, "createdAt": "2026-04-03T14:26:20.532Z", "updatedAt": "2026-04-03T14:39:12.148Z" } }, "extensions": { "requestId": "" } } ### GraphQL: simulatePhysicalPaymentCardOrderShipmentFailed Query: mutation simulatePhysicalPaymentCardOrderShipmentFailed( $input: SimulatePhysicalPaymentCardShipmentFailedInput! ) { simulatePhysicalPaymentCardOrderShipmentFailed(input: $input) { __typename ... on PhysicalPaymentCardOrder { id orderState { status } cardPersonalization { textLines { line1 line2 } } paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate senderDetails { name { givenName middleName familyName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } deliveryDetails { name { givenName familyName middleName } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } stateHistory { previousStatus newStatus createdAt } paymentCard { id bin last4 } createdAt updatedAt } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "physicalPaymentCardOrderId": "" } } Expected Result: { "data": { "simulatePhysicalPaymentCardOrderShipmentFailed": { "__typename": "PhysicalPaymentCardOrder", "id": "", "orderState": { "status": "SHIP_FAILED" }, "cardPersonalization": { "textLines": { "line1": "JOE WOLFE", "line2": "" } }, "paymentCardShipment": { "courier": { "method": "USPS_GROUND", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2026-09-01", "senderDetails": { "name": { "givenName": "John", "middleName": "James", "familyName": "Smith" }, "companyName": "Highnote", "address": { "streetAddress": "1234 Main St", "extendedAddress": "apt 6H", "postalCode": "94132", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "deliveryDetails": { "name": { "givenName": "Joe", "familyName": "Wolfe", "middleName": "" }, "companyName": null, "address": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "95121", "region": "CA", "locality": "San Jose", "countryCodeAlpha3": "USA" } } }, "stateHistory": [ { "previousStatus": "APPROVED", "newStatus": "SHIP_FAILED", "createdAt": "2026-09-01T15:44:09.231Z" }, { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2026-09-01T15:40:55.451Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2026-09-01T15:40:52.610Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2026-09-01T15:40:47.927Z" } ], "paymentCard": { "id": "", "bin": "511114", "last4": "5891" }, "createdAt": "2026-09-01T15:40:47.927Z", "updatedAt": "2026-09-01T15:44:09.231Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulatePhysicalCardGroupOrderSendToPrinter Query: mutation SimulatePhysicalCardGroupOrderSendToPrinter( $input: SimulatePhysicalCardGroupOrderSendToPrinterInput! ) { simulatePhysicalCardGroupOrderSendToPrinter(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderSendToPrinter": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "SENT_TO_PRINTER" }, "stateHistory": [ { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulatePhysicalCardGroupOrderApproval Query: mutation SimulatePhysicalCardGroupOrderApproval( $input: SimulatePhysicalCardGroupOrderApprovalInput! ) { simulatePhysicalCardGroupOrderApproval(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderApproval": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "APPROVED" }, "stateHistory": [ { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulatePhysicalCardGroupOrderShipped Query: mutation SimulatePhysicalCardGroupOrderShipped( $input: SimulatePhysicalCardGroupOrderShippedInput! ) { simulatePhysicalCardGroupOrderShipped(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "", "trackingNumber": "94001234567890123456", "actualShipDate": "2026-04-03" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderShipped": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": { "trackingNumber": "94001234567890123456", "actualShipDateLocal": "2026-04-03" } }, "requestedShipDate": "2026-04-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "SHIPPED" }, "stateHistory": [ { "previousStatus": "SHIPPED", "newStatus": "SENT_TO_PRINTER", "createdAt": "2026-04-03T20:16:40.580Z" }, { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2026-04-03T20:16:40.580Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2026-04-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2026-04-03T20:16:40.580Z" } ], "createdAt": "2026-04-03T20:16:40.579Z", "updatedAt": "2026-04-03T20:16:40.586Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulatePhysicalCardGroupOrderShipmentFailed Query: mutation SimulatePhysicalCardGroupOrderShipmentFailed( $input: SimulatePhysicalCardGroupOrderShipmentFailedInput! ) { simulatePhysicalCardGroupOrderShipmentFailed(input: $input) { __typename ... on PhysicalCardGroupOrder { id cardProductId cardCount paymentCardShipment { courier { method signatureRequiredOnDelivery tracking { trackingNumber actualShipDateLocal } } requestedShipDate deliveryDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } senderDetails { name { givenName middleName familyName suffix title } companyName address { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } } } orderState { status } stateHistory { previousStatus newStatus createdAt } createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "groupOrderId": "MC4yMi4xMjM=" } } Expected Result: { "data": { "simulatePhysicalCardGroupOrderShipmentFailed": { "__typename": "PhysicalCardGroupOrder", "id": "", "cardProductId": "", "cardCount": 10, "paymentCardShipment": { "courier": { "method": "USPS_PRIORITY", "signatureRequiredOnDelivery": false, "tracking": null }, "requestedShipDate": "2022-08-03", "deliveryDetails": { "name": { "givenName": "Homer", "middleName": "Jay", "familyName": "Simpson", "suffix": "Sr", "title": "Mr" }, "companyName": "Highnote", "address": { "streetAddress": "123 Main St", "extendedAddress": "APT 2", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" } }, "senderDetails": { "name": { "givenName": "James", "middleName": "Jay", "familyName": "Smith", "suffix": "Jr", "title": "Mr" }, "companyName": "CherityCard", "address": { "streetAddress": "888 Main St", "extendedAddress": "APT 5", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" } } }, "orderState": { "status": "SHIP_FAILED" }, "stateHistory": [ { "previousStatus": "APPROVED", "newStatus": "SHIP_FAILED", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": "SENT_TO_PRINTER", "newStatus": "APPROVED", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": "NEW", "newStatus": "SENT_TO_PRINTER", "createdAt": "2022-08-03T20:16:40.580Z" }, { "previousStatus": null, "newStatus": "NEW", "createdAt": "2022-08-03T20:16:40.580Z" } ], "createdAt": "2022-08-03T20:16:40.579Z", "updatedAt": "2022-08-03T20:16:40.586Z" } }, "extensions": { "requestId": "4a98f0d9-8590-9d59-9301-29f135a8e15a" } } --- URL: https://docs.highnote.com/docs/issuing/cards/simulations/sim-digital-wallet-tokens Title: Simulate Digital Wallet Token Provisioning Section: Issuing Description: Simulate digital wallet token provisioning and activation in the Test environment to verify Apple Pay and Google Wallet integration. ## Overview When an account holder adds a payment card to a digital wallet such as Apple Pay or Google Pay, a **digital wallet token** is created. This token is a substitute for the card's primary account number (PAN) and is used for transactions instead of the real card number. In production, token provisioning is initiated by the account holder through their wallet app. In the Test environment, you can use the Highnote simulation to replicate this flow and verify your integration handles token lifecycle events correctly. The simulation walks through two steps: 1. **Generate** a digital wallet token — creates a token in status 2. **Activate** the token — transitions the token from to ## Prerequisites - A Highnote account - An API key or the API Explorer - An active payment card ## Generate a digital wallet token Do not enter production data in the Test environment. The Highnote Test environment is for exploring features and training. Use only dummy or test data. Generating a digital wallet token requires using the following mutation. This mutation creates a digital wallet token with a status of . The accepts the following optional fields: - — ID assigned to the token requester by the network. Defaults to Google Pay. - — Digital wallet token type. Defaults to . - — Method by which the card was added to the digital wallet. Defaults to . ## Activate a digital wallet token Use the following mutation to update a digital wallet token status from to : ## View token status and details Find the status of a token and its historical state transitions using the following query. The response includes the optional fields listed above, as well as: - — The last four digits of the token primary account number (TPAN). - — The exact date and time in UTC when the token expires. These two fields are only returned for tokens that have been or are in state awaiting identity verification. ## Automate your integration To automate your integration, subscribe to digital wallet token status notification events. The details provided in the payloads from digital wallet token status events can be used for the following use cases: - Automate your application or website's token provisioning workflows - Create account holder notifications and alerts - Create status views in your application or website ### GraphQL: SimulateCardDigitalWalletTokenActivation Query: mutation SimulateCardDigitalWalletTokenActivation( $input: SimulateCardDigitalWalletTokenActivationInput! ) { simulateCardDigitalWalletTokenActivation(input: $input) { __typename ... on CardDigitalWalletToken { id createdAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "paymentCardId": "", "requesterIdentifier": "11223344", "tokenType": "ECOMMERCE", "sourceEntryMethod": "CARD_ON_FILE" } } Expected Result: { "data": { "simulateCardDigitalWalletTokenActivation": { "__typename": "CardDigitalWalletToken", "id": "", "createdAt": null } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateCardDigitalWalletTokenActivated Query: mutation SimulateCardDigitalWalletTokenActivated( $input: SimulateCardDigitalWalletTokenActivatedInput! ) { simulateCardDigitalWalletTokenActivated(input: $input) { __typename ... on CardDigitalWalletToken { id createdAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "cardDigitalWalletTokenId": "" } } Expected Result: { "data": { "simulateCardDigitalWalletTokenActivated": { "__typename": "CardDigitalWalletToken", "id": "", "createdAt": null } }, "extensions": { "requestId": "" } } ### GraphQL: FindCardDigitalWalletToken Query: query FindCardDigitalWalletToken($id: ID!) { node(id: $id) { ... on CardDigitalWalletToken { __typename id status createdAt updatedAt requesterName requesterIdentifier tokenType sourceEntryMethod last4 expirationDate cardDigitalWalletTokenStateTransitions(first: 10) { edges { node { state reason createdAt updatedAt } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardDigitalWalletToken", "id": "", "status": "TERMINATED", "createdAt": "2022-06-12T07:30:18.346Z", "updatedAt": "2022-06-12T07:34:20.424Z", "requesterName": "Google Pay", "requesterIdentifier": "11223344", "tokenType": "ECOMMERCE", "sourceEntryMethod": "CARD_ON_FILE", "last4": "8744", "expirationDate": "2028-01-31T23:59:59Z", "cardDigitalWalletTokenStateTransitions": { "edges": [ { "node": { "state": "TERMINATED", "reason": "FRAUDULENT_TRANSACTIONS", "createdAt": "2022-06-12T07:34:20.420Z", "updatedAt": "2022-06-12T07:34:20.433Z" } }, { "node": { "state": "ACTIVE", "reason": "NON_FRAUDULENT_TRANSACTIONS", "createdAt": "2022-06-12T07:32:41.818Z", "updatedAt": "2022-06-12T07:32:41.837Z" } }, { "node": { "state": "SUSPENDED", "reason": "DEVICE_LOST", "createdAt": "2022-06-12T07:30:46.717Z", "updatedAt": "2022-06-12T07:30:46.753Z" } }, { "node": { "state": "ACTIVE", "reason": null, "createdAt": "2022-06-12T07:30:34.446Z", "updatedAt": "2022-06-12T07:30:34.455Z" } }, { "node": { "state": "REQUESTED", "reason": null, "createdAt": "2022-06-12T07:30:18.362Z", "updatedAt": "2022-06-12T07:30:18.729Z" } } ] } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/credit/about-credit Title: Credit Overview Section: Issuing Description: Configure credit plans for revolving credit and installment (BNPL) products. Offer purchase plans, installment agreements, and balance transfer options to account holders. ## Overview Credit products support different balance types: - Purchase - Installment / Buy Now, Pay Later (BNPL) - Balance transfer - Cash Advance Credit plans provide flexible and configurable terms for credit card products and can define payment structure, interest rate, type, and accrual method, as well as pricing and policy terms per balance type. The structure of your credit plans should align with the value proposition and pricing strategy of your credit product. For example, your card product might offer purchase and cash advance credit plans with distinct interest rates, rate types, and accrual methods to serve different customer needs. Credit plans are linked to financial accounts and determine payment obligations on billing statements. While financial accounts can be assigned to various credit plans, the terms must consistently match what was disclosed to your account holders in their Cardholder Agreement. ## Available plans Highnote currently supports purchase and post-purchase BNPL installment credit plans: - **Purchase credit plans** form the foundation of Highnote's revolving credit card products. They let you offer your account holders the ability to make flexible payments (above the minimum) while maintaining access to their full credit line. - **Installment credit plans** are Highnote's **Buy Now Pay Later** (BNPL) option. They let your account holders move cleared transactions from a flexible revolving balance into a structured payment plan with fixed installments. ## Installment offer flow The following diagram illustrates the flow of an installment plan from a cleared transaction event to a BNPL installment agreement: ## Creating credit plans To create any credit plan: 1. View the available credit plan templates. 2. Create a credit plan. 3. Create and attach fees if applicable (required for installment). 4. Activate the credit plan. Installment plans require that you create a purchase plan first, then the installment plan with fee schedule, and then an agreement per cleared transaction. ## Over-limit transactions Credit products can authorize purchases that exceed the financial account's credit limit using variance spend rules and the . See Over-Limit Transactions for prerequisites, configuration, and examples. ## Environments Highnote provides a Test environment for you to test your APIs and integration of your products. Use the **Test environment** to create credit plans on card products and overall card product integration. In the **Live environment**, Highnote creates credit plans for your card product. The following guides provide an overview for testing credit plans in the Test environment. --- URL: https://docs.highnote.com/docs/issuing/credit/account-delinquency Title: Account Delinquency Section: Issuing Description: Monitor and manage account delinquency status, receivables, and collections. Track days delinquent, suspend authorizations, and process charge-offs. ## Overview Your delinquency credit policy is set up by the Highnote team when configuring your card product. A financial account's delinquency state differs from its status. - Delinquency State represents the account's **receivables** and can be , , , . - Status represents the financial **account** itself and can be , , , , . Receivables are purchases that must be paid back and are represented by the account holder's outstanding account balance. When an account holder borrows against a line of credit, receivables are created against their account. When the account holder does not make the minimum payment on their billing statement by the due date, the receivables can become delinquent. ## Delinquency fields An account holder’s financial account displays the following fields for delinquencies: | Field | Description | | :--------------------- | :------------------------------------------------------------------------------------ | | | Due date of the oldest, delinquent billing statement on the financial account | | | Number of days since the oldest, delinquent billing statement’s due date, as of today | | | Total delinquent amount on the financial account, as of today | | | Number of billing cycles the financial account has been delinquent, as of today | Financial accounts also display billing cycles. A billing cycle displays the following information for delinquencies: | Field | Description | | :--------------- | :------------------------------------------------------------- | | | Number of days delinquent for the billing cycle, as of today | | | Past due amount for the cycle’s billing statement, as of today | | | State of the billing cycle at the | ## Financial account attributes Financial account attributes indicate the reason the account meets or exceeds your credit policy so that you can take action. When a financial account’s meets or exceeds your card product’s delinquency policy, an attribute is added. You can manage credit risk by notifying customers of delinquencies, performing collections, or suspending financial account authorizations. To automate cardholder communications and send push alerts or notifications to account holders, use the financial account attributes notification events. The following table includes supported financial account attributes with Test environment default settings. Settings in the Live environment may vary depending on your card product's delinquency policy: | Attribute | Description | Test Env Default Value | | :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------- | | | The financial account is considered delinquent based on your card product’s policy; no restrictions have been placed on the financial account. | >= 30 days | | | The financial account is excessively delinquent based on your card product’s policy and the financial account’s status is ; authorizations are blocked on all associated payment cards. | >= 90 days | | | The financial account has failed to make the minimum payment for X days, based on your card product's policy, and will be closed. The financial account attribute of is added and the financial account status is set to | >= 180 days | When a payment is made and a financial account’s no longer exceeds your delinquency policy, Highnote removes the financial account attributes and updates the account to current. ## Delinquency flow The following diagram is a high-level view demonstrating how a cardholder can get into and out of delinquency with a card that has been configured with Highnote delinquency attributes. The diagram shows the relationship of a financial account's delinquency state and status. The exact day when an account's receivables become delinquent varies depends on your configured policy. ## Clearing delinquency The following scenarios show two ways to clear a delinquency and restore a suspended card to an active status. ### Example: $10 initial fee **Scenario:** A minimum payment of $10 is past due for an initial card fee. The financial account delinquency state = and status = . **Workflow:** 1. The $10 initial fee is waived. 2. The minimum payment is considered fully paid. 3. Account delinquency state moves to (and clears from Dashboard view). 4. Account status moves to . ### Example: $10 initial fee + $100 transaction **Scenario:** A minimum payment of $25 is past due ($10 initial fee plus minimum payment of $15 for a $100 transaction). The financial account delinquency state = and status = . **Workflow:** 1. The $10 initial fee is waived. 2. The minimum payment is considered partially paid. 3. A minimum payment of $15 remains past due. 4. Account delinquency state stays and account status stays . 5. The cardholder pays off the remaining $15. 6. Account delinquency state moves to (and clears from Dashboard view). 7. Account status moves to . ## Find delinquency status You can view the and on an individual financial account. You can also view the and delinquent for an individual billing statement. If the financial account is current or newly created and does not have a closed billing cycle, Highnote returns no delinquency data. Use the following query to find a financial account's delinquency status: ## Charge off account We recommend that you notify the account holder if their account is being closed due to charge off. When a financial account's receivable balance is uncollectible based on your card product's credit policy, the balance is charged off as a write-off expense. A credit card balance is typically charged off when the account holder has not met the billing statement's minimum payment for 120 to 180 days. In the Live environment, this length of time will be determined by your card product's credit policy. When a charge-off occurs, the following events take place: 1. The financial account receives a attribute and the FinancialAccountStatus is updated to , , or . If the account receivables are delinquent for more than the configured , the Delinquency State is updated to . 2. The Highnote team charges off the balance and closes the financial account based on your credit policy: FinancialAccountStatus = . 3. Any unpaid balance, including the principal balance, fees, or interest charges are written off as an expense. 4. The Highnote team provides your team with monthly reporting. To receive charge off notifications, subscribe to financial account attribute charge off events. ## Simulate delinquency To simulate delinquency in the Test environment, see Simulate Delinquency. ### GraphQL: LookupFinancialAccountDelinquencyStatus Query: query LookupFinancialAccountDelinquencyStatus($id: ID!) { node(id: $id) { ... on FinancialAccount { id accountStatus accountAttributes delinquency { __typename totalAmount { value currencyCode } numberOfCycles totalDaysDelinquent delinquencyStartedOn currentDelinquentCycles { daysDelinquent statement { periodStart periodEnd openedAt closedAt primaryLedger { debitBalance { value } creditBalance { value } normalBalance } } amount { value currencyCode } state } } } } } Variables: { "input": { "id": "" } } Expected Result: { "id": "", "accountStatus": "ACTIVE", "accountAttributes": [ "DELINQUENT" ], "delinquency": { "delinquencyStartedOn": "2022-11-07T05:00:00.000Z", "totalDaysDelinquent": 57, "totalAmount": { "value": "300", "currencyCode": "USD" }, "numberOfCycles": 2, "currentDelinquentCycles": [ { "daysDelinquent": 57, "statement": { "periodStart": "2022-10-03T05:00:00.000Z", "periodEnd": "2022-11-03T05:00:00.000Z", "openedAt": "2023-01-03T23:17:14.983Z", "closedAt": "2023-01-03T23:23:17.546Z", "primaryLedger": { "debitBalance": { "value": 0 }, "creditBalance": { "value": 300 }, "normalBalance": "CREDIT" } }, "amount": { "value": 300, "currencyCode": "USD" }, "state": "DELINQUENT" }, { "daysDelinquent": 27, "statement": { "periodStart": "2022-11-03T05:00:00.000Z", "periodEnd": "2022-12-03T05:00:00.000Z", "openedAt": "2023-01-03T23:23:17.546Z", "closedAt": "2023-01-03T23:25:35.519Z", "primaryLedger": { "debitBalance": { "value": 0 }, "creditBalance": { "value": 300 }, "normalBalance": "CREDIT" } }, "amount": { "value": 0, "currencyCode": "USD" }, "state": "DELINQUENT" } ] } } --- URL: https://docs.highnote.com/docs/issuing/credit/collaborative-app-decisioning Title: Collaborative Application Decisioning Section: Issuing Description: Make collaborative underwriting decisions on credit applications with Highnote. Approve, deny, or extend alternative offers like secured cards to applicants. ## Overview Collaborative application decisioning is self-service in your Test environment. In the Live environment, the feature must be enabled for your card product by the Highnote team. With collaborative application decisioning, you or your underwriter can make a recommended decision of or for applications of your product based on your credit policy. Highnote will conduct regulatory checks on the application, including KYC, KYB, and OFAC, and use your recommended decision to arrive at a final decision. Highnote also allows for customization of the sequencing of application decisioning calls and rule execution to fit your product and credit policy. This guide assumes that you or your underwriter provide a recommended decision _after_ identity and fraud checks are run by Highnote. ## Enable collaborative application decisioning In the Live environment, the Highnote team will enable this feature for you. To request access to this feature, contact support@highnote.com. Use the following mutation to enable collaborative application decisioning in the Test environment: ## Receive a decision request You must set up notification targets to receive notification events. For more information, see Notifications. After an application is submitted to Highnote, you will receive the underwriting decision requested notification event. This notification event requests an underwriting decision from you or your underwriter. The following payload is an example of the notification event you will receive: ### Example notification event payload ```json { "data": { "node": { "__typename": "NotificationEvent", "createdAt": "2022-12-12T16:32:49.125Z", "id": "", "name": "CARD_PRODUCT_APPLICATION_UNDERWRITING_DECISION_REQUESTED", "node": { "__typename": "AccountHolderCardProductApplication", "applicationState": { "status": "PENDING" }, "createdAt": "2022-12-12T16:32:44.499Z", "id": "", "updatedAt": "2022-12-12T16:32:44.499Z" } } }, "extensions": { "signatureTimestamp": 1670862772620 } } ``` After receiving the event notification, Highnote waits for your response to the underwriting decision. ## Approve request To approve a collaborative application decision request, you must respond with the credit limit decision. If you are unsure about the initial credit limit during the underwriting decision, you can assign a credit limit of $0 and adjust it on the financial account later. Use the following mutation to approve a collaborative application decision request: ## Deny request When you deny a decision request, the overall application is and you must provide applicable adverse action reason(s) based on your credit policy. If a decision is not received within 30 days from the application creation date, the application status will transition to . For a complete list of adverse action reasons, see the API Reference. Use the following mutation to deny a decision request: ## Manage offers Please reach out to your Highnote representative to configure your card product for offer management. If an account holder's creditworthiness does not qualify them for the card product they applied for, you can extend an alternative offer for a different product. For example, you may want to offer a secured credit card instead of an unsecured one. For more information on Highnote's secured deposit feature, see Create Secured Deposit Offer. From the time of the first extended offer, the account holder will have 30 days to accept the offer before the application is systemically denied. You can disqualify an offer if the account holder does not meet the underwriting criteria. Alternatively, if the account holder does not accept the offer you extended, you can reject the offer. If all offers on the application are disqualified or rejected, the application will be denied. If your card product is configured for offer management, you should subscribe to events to be notified when an application has reached the offer management state and will require an input before the application can be decisioned. Use the following mutation to extend, disqualify, or reject an offer: ## Accept offer An offer must be before it can be . The primary offer will automatically be if underwriting is approved on the application. If your card product has offers, one offer must be accepted to approve the application by providing the account holder’s consent and the accepted , including the primary offer the account holder applied for. Once an account holder accepts an offer, the application will be approved and a financial account can be issued for their accepted card product. Use the following mutation to accept an offer: ## Check application status After an application decision is made, the application will be marked as while Highnote makes a final decision. To keep track of application status updates, you can use the query or subscribe to the application status events notification to get notified when the application’s status changes. Use the following query to check the status of an application: ### GraphQL: EnableCollaborativeApplicationUnderwritingFeature Query: mutation EnableCollaborativeApplicationUnderwritingFeature( $input: EnableCollaborativeApplicationUnderwritingFeatureInput! ) { enableCollaborativeApplicationUnderwritingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "" } } Expected Result: { "data": { "enableCollaborativeApplicationUnderwritingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "CollaborativeApplicationUnderwritingCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "" } } ### GraphQL: approveCreditProductApplicationUnderwriting Query: mutation approveCreditProductApplicationUnderwriting( $input: ApproveCreditProductApplicationUnderwritingInput! ) { approveCreditProductApplicationUnderwriting(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } accountHolderSnapshot { ... on USBusinessAccountHolderSnapshot { businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { status reason results { code } } currentCreditUnderwritingVerification { status } } } } updatedAt createdAt } } } Variables: { "input": { "applicationId": "", "decisionDate": "2022-10-12T23:53:52.860Z", "standardPurchaseCreditLimit": { "value": 400000, "currencyCode": "USD" } } } Expected Result: { "data": { "approveCreditProductApplicationUnderwriting": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "businessProfile": { "name": { "legalBusinessName": "HIGHNOTE", "doingBusinessAsName": "BlueJay Inc" }, "updatedAt": "2023-01-06T20:24:20.303Z", "createdAt": "2023-01-06T20:24:13.191Z", "currentVerification": { "status": "PASSED", "reason": "PASSED", "results": [] }, "currentCreditUnderwritingVerification": { "status": "PASSED" } } }, "updatedAt": "2023-01-06T20:24:20.303Z", "createdAt": "2023-01-06T20:24:13.191Z" } }, "extensions": { "requestId": "" } } ### GraphQL: denyCreditProductApplicationUnderwriting Query: mutation denyCreditProductApplicationUnderwriting( $input: DenyCreditProductApplicationUnderwritingInput! ) { denyCreditProductApplicationUnderwriting(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } adverseActionReasons { code description } accountHolderSnapshot { ... on USBusinessAccountHolderSnapshot { businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { status reason results { code } } } } } updatedAt createdAt } } } Variables: { "input": { "applicationId": "", "decisionDate": "2022-10-12T23:53:52.860Z", "adverseActionReasons": [ { "code": "INSUFFICIENT_INCOME" } ] } } Expected Result: { "data": { "denyCreditProductApplicationUnderwriting": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "adverseActionReasons": [ { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested" } ], "accountHolderSnapshot": { "businessProfile": { "name": { "legalBusinessName": "HIGHNOTE", "doingBusinessAsName": "BlueJay Inc" }, "updatedAt": "2023-01-06T21:39:03.273Z", "createdAt": "2023-01-06T21:38:54.572Z", "currentVerification": { "status": "PASSED", "reason": "PASSED", "results": [] } } }, "updatedAt": "2023-01-06T21:39:03.273Z", "createdAt": "2023-01-06T21:38:54.572Z" } }, "extensions": { "requestId": "" } } ### GraphQL: updateAccountHolderCardProductApplicationOffers Query: mutation updateAccountHolderCardProductApplicationOffers( $input: UpdateAccountHolderCardProductApplicationOffersInput! $filterByAccepted: AccountHolderCardProductApplicationOfferFilterByInput $filterByDisqualified: AccountHolderCardProductApplicationOfferFilterByInput $filterByExtended: AccountHolderCardProductApplicationOfferFilterByInput $filterByOpen: AccountHolderCardProductApplicationOfferFilterByInput $filterByRejected: AccountHolderCardProductApplicationOfferFilterByInput ) { updateAccountHolderCardProductApplicationOffers(input: $input) { __typename ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } acceptedOffers: offers(first: 10, filterBy: $filterByAccepted) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } disqualifiedOffers: offers(first: 10, filterBy: $filterByDisqualified) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } extendedOffers: offers(first: 10, filterBy: $filterByExtended) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } openOffers: offers(first: 10, filterBy: $filterByOpen) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } rejectedOffers: offers(first: 10, filterBy: $filterByRejected) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } } } } Variables: { "input": { "applicationId": "", "offerUpdates": [ { "offerId": "", "offerStatus": "REJECTED" }, { "offerId": "", "offerStatus": "EXTENDED" } ] }, "filterByAccepted": { "offerStatus": { "includes": [ "ACCEPTED" ] } }, "filterByDisqualified": { "offerStatus": { "includes": [ "DISQUALIFIED" ] } }, "filterByExtended": { "offerStatus": { "includes": [ "EXTENDED" ] } }, "filterByOpen": { "offerStatus": { "includes": [ "OPEN" ] } }, "filterByRejected": { "offerStatus": { "includes": [ "REJECTED" ] } } } Expected Result: { "data": { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "acceptedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "" }, "edges": [] }, "disqualifiedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "" }, "edges": [] }, "extendedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fZjNmNzc5ZmRiYzRiNGY4YmJiZGQ0ZDEwNGJhYWZiZTQ" }, "edges": [ { "cursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fZjNmNzc5ZmRiYzRiNGY4YmJiZGQ0ZDEwNGJhYWZiZTQ", "node": { "id": "", "name": "offer0", "status": "EXTENDED", "category": "SECURED_CREDIT" } } ] }, "openOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fMzM0NTExOTQ2Zjg2NGMzMWFmNzE2NDVlN2NmNmY5ZWY" }, "edges": [ { "cursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fMTYwZjdlYjQ4ZWFmNDg4MmFjOWYyYmQ0NDhkM2EzNTc", "node": { "id": "", "name": "offer1", "status": "OPEN", "category": "SECURED_CREDIT" } } ] }, "rejectedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "" }, "edges": [ { "cursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fMzM0NTExOTQ2Zjg2NGMzMWFmNzE2NDVlN2NmNmY5ZWY", "node": { "id": "", "name": "offer3", "status": "REJECTED", "category": "UNSECURED_CREDIT" } } ] } } } } ### GraphQL: acceptAccountHolderCardProductApplicationOffer Query: mutation acceptAccountHolderCardProductApplicationOffer( $input: AcceptAccountHolderCardProductApplicationOfferInput! $filterByAccepted: AccountHolderCardProductApplicationOfferFilterByInput $filterByOpen: AccountHolderCardProductApplicationOfferFilterByInput $filterByDisqualified: AccountHolderCardProductApplicationOfferFilterByInput $filterByExtended: AccountHolderCardProductApplicationOfferFilterByInput $filterByRejected: AccountHolderCardProductApplicationOfferFilterByInput ) { acceptAccountHolderCardProductApplicationOffer(input: $input) { __typename ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } acceptedOffers: offers(first: 10, filterBy: $filterByAccepted) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } disqualifiedOffers: offers(first: 10, filterBy: $filterByDisqualified) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } extendedOffers: offers(first: 10, filterBy: $filterByExtended) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } openOffers: offers(first: 10, filterBy: $filterByOpen) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } rejectedOffers: offers(first: 10, filterBy: $filterByRejected) { pageInfo { hasNextPage startCursor } edges { cursor node { id name status category } } } } } } Variables: { "input": { "applicationId": "", "offerId": "", "consentAgreement": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2024-12-22T17:10:55.662Z", "ipAddress": { "v6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" } } }, "filterByAccepted": { "offerStatus": { "includes": [ "ACCEPTED" ] } }, "filterByDisqualified": { "offerStatus": { "includes": [ "DISQUALIFIED" ] } }, "filterByExtended": { "offerStatus": { "includes": [ "EXTENDED" ] } }, "filterByOpen": { "offerStatus": { "includes": [ "OPEN" ] } }, "filterByRejected": { "offerStatus": { "includes": [ "REJECTED" ] } } } Expected Result: { "data": { "node": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "APPROVED" }, "cardProduct": { "id": "" }, "acceptedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "" }, "edges": [ { "cursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fZjNmNzc5ZmRiYzRiNGY4YmJiZGQ0ZDEwNGJhYWZiZTQ", "node": { "id": "", "name": "offer0", "status": "ACCEPTED", "category": "SECURED_CREDIT" } } ] }, "disqualifiedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "" }, "edges": [] }, "extendedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fZjNmNzc5ZmRiYzRiNGY4YmJiZGQ0ZDEwNGJhYWZiZTQ" }, "edges": [] }, "openOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fMzM0NTExOTQ2Zjg2NGMzMWFmNzE2NDVlN2NmNmY5ZWY" }, "edges": [ { "cursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fMTYwZjdlYjQ4ZWFmNDg4MmFjOWYyYmQ0NDhkM2EzNTc", "node": { "id": "", "name": "offer1", "status": "OPEN", "category": "SECURED_CREDIT" } } ] }, "rejectedOffers": { "pageInfo": { "hasNextPage": false, "startCursor": "" }, "edges": [ { "cursor": "dD0yMDI0LTEwLTA5VDE5JTNBMjMlM0E0Ny42NjMwMDAwMDBaJmk9cHJ2aW9fMzM0NTExOTQ2Zjg2NGMzMWFmNzE2NDVlN2NmNmY5ZWY", "node": { "id": "", "name": "offer3", "status": "REJECTED", "category": "UNSECURED_CREDIT" } } ] } } } } ### GraphQL: GetAccountHolderCardProductApplication Query: query GetAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } adverseActionReasons { code description } accountHolderSnapshot { ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id } primaryAuthorizedPerson { currentVerification { status reason results { code } } updatedAt createdAt } businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { adverseActionReasons { code description } status reason results { code } } currentCreditUnderwritingVerification { status decision { ... on UnderwriterPositiveDecision { creditLine { value currencyCode } } ... on UnderwriterAdverseDecision { adverseActionReasons { code description } } } } ultimateBeneficialOwners { currentVerification { status reason results { code } } updatedAt createdAt } } } } applicationHistory { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { applicationState { status } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "DENIED" }, "cardProduct": { "id": "" }, "adverseActionReasons": [ { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested" } ], "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "primaryAuthorizedPerson": { "currentVerification": { "status": "PASSED", "reason": "PASSED", "results": [ { "code": "PHONE_MATCH" }, { "code": "SSN_MATCH" }, { "code": "NAME_MATCH" }, { "code": "DOB_MATCH" }, { "code": "ADDRESS_MATCH" } ] }, "updatedAt": "2023-01-06T18:46:25.061Z", "createdAt": "2023-01-06T18:46:22.738Z" }, "businessProfile": { "name": { "legalBusinessName": "HIGHNOTE", "doingBusinessAsName": "BlueJay Inc" }, "updatedAt": "2023-01-06T18:46:59.510Z", "createdAt": "2023-01-06T18:46:22.737Z", "currentVerification": { "adverseActionReasons": [], "status": "PASSED", "reason": "PASSED", "results": [ { "code": "REPRESENTATIVE_MATCH" }, { "code": "FEIN_MATCH" }, { "code": "BUSINESS_VERIFICATION_SCORE_PASSED" }, { "code": "ADDRESS_MATCH" }, { "code": "BUSINESS_NAME_MATCH" } ] }, "currentCreditUnderwritingVerification": { "status": "DENIED", "decision": { "adverseActionReasons": [ { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested" } ] } }, "ultimateBeneficialOwners": [ { "currentVerification": { "status": "PASSED", "reason": "PASSED", "results": [ { "code": "PHONE_MATCH" }, { "code": "SSN_MATCH" }, { "code": "NAME_MATCH" }, { "code": "DOB_MATCH" }, { "code": "ADDRESS_MATCH" } ] }, "updatedAt": "2023-01-06T18:46:25.061Z", "createdAt": "2023-01-06T18:46:22.738Z" } ] } }, "applicationHistory": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } } ] }, "updatedAt": "2023-01-06T18:46:59.510Z", "createdAt": "2023-01-06T18:46:22.737Z" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/credit/over-limit-transactions Title: Over-Limit Transactions Section: Issuing Description: Authorize credit card purchases that exceed the financial account's credit limit using variance spend rules and the Credit Limit Variance product feature. ## Overview An **over-limit transaction** can be approved even when the account balance, with the transaction applied, would exceed the financial account's credit limit. Highnote supports over-limit transactions through two variance spend rules, gated by a card product feature that Highnote Operations enables on your behalf: - Amount variance: - Percent variance: Either rule can be attached at the Card Product, Financial Account, or Payment Card level. The rule applies to **authorized amounts**; reversals decrement the cumulative authorized amount, but refunds do not. Before enabling over-limit transactions, update your Cardholder Agreement to disclose how a cardholder opts in and to disclose any associated fees. The Credit CARD Act allows over-limit fees only when the cardholder has affirmatively consented. ## Prerequisites Both of the following must be true before you can use these spend rules: - Highnote Operations has enabled the on your card product. Contact your Highnote representative to enable it. - Your Cardholder Agreement reflects the over-limit terms and any associated fees. ## Spend rules | Spend Rule | Input | Use it to | | ---------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | | | Allow cumulative spend up to a fixed over the credit limit. | | | | Allow cumulative spend up to a whole-number percentage of the credit limit. A value of permits cumulative spend up to 150% of the limit. | Configure or to match your underwriting policy and the terms disclosed in your Cardholder Agreement. Highnote does not enforce an upper bound on either. - is an integer in **minor units** — is $10.99 USD, not $1,099. - is a whole-number percent above the credit limit — allows up to 150%. ::: ## Examples ### Maximum amount variance A subscriber wants to let a fleet — one financial account with ten payment cards — spend up to $500 over the financial account's credit limit. There are no restrictions on the number or dollar amount of individual transactions, as long as the cumulative over-limit total stays under $500. Create the spend rule: Then attach the rule to the financial account: ### Maximum percent variance A subscriber wants to let a financial account spend up to 20% over its credit limit — for example, $1,200 of cumulative spend against a $1,000 credit limit. Create the spend rule: Attach the rule to the financial account using the same mutation shown above. ### Combining with other spend rules A variance spend rule on its own caps the cumulative over-limit amount but does not constrain individual transactions. To layer per-transaction or per-window controls — for example, "$500 cumulative over-limit, but no single transaction over $250" — compose the variance rule with an AmountLimitSpendRule or wrap them in a VelocityRule. The variance rule continues to gate the cumulative over-limit amount; the additional rules constrain transaction shape. ### GraphQL: CreateMaximumAmountVarianceOnCreditLimitSpendRule Query: mutation CreateMaximumAmountVarianceOnCreditLimitSpendRule( $input: CreateMaximumAmountVarianceOnCreditLimitSpendRuleInput! ) { createMaximumAmountVarianceOnCreditLimitSpendRule(input: $input) { __typename ... on MaximumAmountVarianceOnCreditLimitSpendRule { id name version amountVariance { value currencyCode } createdAt updatedAt } ... on UserError { errors { code path } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "$500 cumulative over-limit allowance", "amountVariance": { "value": 50000, "currencyCode": "USD" } } } Expected Result: { "data": { "createMaximumAmountVarianceOnCreditLimitSpendRule": { "__typename": "MaximumAmountVarianceOnCreditLimitSpendRule", "id": "", "name": "$500 cumulative over-limit allowance", "version": "0", "amountVariance": { "value": 50000, "currencyCode": "USD" }, "createdAt": "2026-05-18T12:00:00.000Z", "updatedAt": "2026-05-18T12:00:00.000Z" } }, "extensions": { "requestId": "" } } ### GraphQL: AttachSpendRuleToFinancialAccount Query: mutation AttachSpendRuleToFinancialAccount( $input: AttachSpendRuleToFinancialAccountInput! ) { attachSpendRuleToFinancialAccount(input: $input) { __typename ... on FinancialAccount { id } ... on UserError { errors { code path } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "spendRule": { "id": "", "version": "LATEST" } } } Expected Result: { "data": { "attachSpendRuleToFinancialAccount": { "__typename": "FinancialAccount", "id": "" } }, "extensions": { "requestId": "" } } ### GraphQL: CreateMaximumPercentVarianceOnCreditLimitSpendRule Query: mutation CreateMaximumPercentVarianceOnCreditLimitSpendRule( $input: CreateMaximumPercentVarianceOnCreditLimitSpendRuleInput! ) { createMaximumPercentVarianceOnCreditLimitSpendRule(input: $input) { __typename ... on MaximumPercentVarianceOnCreditLimitSpendRule { id name version percentVariance createdAt updatedAt } ... on UserError { errors { code path } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "20% over-limit allowance", "percentVariance": 20 } } Expected Result: { "data": { "createMaximumPercentVarianceOnCreditLimitSpendRule": { "__typename": "MaximumPercentVarianceOnCreditLimitSpendRule", "id": "", "name": "20% over-limit allowance", "version": "0", "percentVariance": 20, "createdAt": "2026-05-18T12:00:00.000Z", "updatedAt": "2026-05-18T12:00:00.000Z" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/credit/schedule-repayments Title: Schedule Repayments Section: Issuing Description: Set up recurring and one-time ACH repayment schedules for credit account holders. Cancel, modify, and monitor scheduled payment status. ## Overview This guide covers how to set up one-time and recurring payment schedules for account holders. The Automated Clearing House (ACH) is an electronic funds transfer network that facilitates interbank transfers. Highnote utilizes ACH to send money from an account holder’s external bank account to their Highnote financial account when scheduling payments. The movement of funds using ACH typically takes three to five business days. For credit card products, it's important to provide cardholders with the ability to make payments toward outstanding balances or debts. The following payment options are available: - Recurring payments - One-time payments Payment schedules are created by the account holder. In the Live environment, you cannot create a payment schedule on an account holder's behalf. You can initiate an originated ACH pull, but must get the account holder's recorded authorization through . ## Repayment rules The rules for repayments on credit products, and loading funds on prepaid products, are as follows: | Product | FinancialAccountStatus | | :------ | :------------------------------------------------------------------------ | | Credit | Can repay with a financial account in any state except | | Prepaid | Can only load funds with a financial account in the state | ## Payment schedules For credit products, you can repay in any state except . For prepaid products, you can only load funds in the state. Refer to the following guidelines when creating payment schedules. ##### Scheduling payments To avoid a late payment, _initiate_ the payment on or before the due date. | Scheduled | Initiated | Processed | | :----------------------- | :---------------- | :---------------- | | Before 3 PM ET | Same calendar day | Same calendar day | | Before 11 PM ET | Same calendar day | Next business day | | Weekends & bank holidays | Same calendar day | Next business day | ##### Payment stages | Stage | Result | | :--------- | :---------------------------------------------------------------------- | | Initiation | A pending credit is recorded on the account holder's financial account | | Processing | The payment clears in 3-5 business days after processing | | Posting | The payment posts to the financial account after the funds have cleared | ##### On-time payments Depending on your program's credit policies, the available credit on a financial account may not be released until a payment has posted. ## Tips to avoid late payments Communicate the following to help your cardholders avoid late payments, fees, or impacts to their credit: - **Plan ahead**: Schedule payments at least 3-5 business days before the due date to account for processing time. - **Consider bank holidays**: Be mindful of weekends and bank holidays, as these can delay payment processing. - **Monitor pending credits**: Check your account to ensure the pending credit is recorded after initiating a payment. ## Create recurring payment schedule Scheduled payments are initiated by the account holder. You cannot schedule payments for account holders in the Live environment. Recurring payments occur on a set frequency and can be scheduled based on the outstanding balance or current amount due. In the Test environment, a transfer ID is generated within 5 minutes of scheduling a payment on the current date. Use the query to find a transfer event ID and simulate changing the transfer status: ## Create a one-time payment Scheduled payments are initiated by the account holder. You cannot schedule a payment for an account holder in the Live environment. One-time payments can be scheduled based on a balance amount or a custom amount. A scheduled payment will not be initiated if the financial account has an less than or equal to $0. In the Test environment, a transfer ID is generated within 5 minutes of scheduling a payment for today. Use the query to find a transfer event ID and simulate changing the status of the transfer: ### Schedule a payment for the due date Set transferDateStrategy to schedule the payment for the next available statement's payment due date. Provide instead of an explicit . The transfer date is calculated at execution time — for accounts with closed statements, it is the latest closed statement's due date; otherwise, it is the current open statement's due date. ```graphql input: { fromFinancialAccountId: "" toFinancialAccountId: "" descriptor: { ... } transferAgreementConsent: { ... } transferAmountStrategy: { ... } transferDateStrategy: { transferDateCalculationType: PAYMENT_DUE_DATE } } ``` ## Cancel a payment schedule To cancel a payment, you must do so before it is initiated, and before 9:00 AM ET on the day it is scheduled. If you attempt to cancel a recurring payment that has already been initiated, the current payment cannot be stopped, but all future payments on the recurring schedule will be canceled. Both one-time and recurring payment schedules can be canceled. To change a payment schedule (e.g., date, amount, or external bank account), you must first cancel the original scheduled payment and then create a new one-time or recurring payment schedule. Use the following mutation to cancel a payment: ## Find a scheduled payment Use the following query to find a scheduled payment. You can use this query to display scheduled payments in your website or application: ## Simulate repayments To simulate repayments in the Test environment, see Simulate Repayments. ### GraphQL: CreateRecurringAchTransfer Query: mutation CreateRecurringAchTransfer($input: CreateRecurringACHTransferInput!) { createRecurringACHTransfer(input: $input) { ... on RecurringACHTransfer { id fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } frequency balanceAmountType descriptor { companyEntryDescription individualName individualIdentificationNumber } transferAmount { ... on TransferAmountCalculation { calculatedType } } status nextScheduledTransferDate createdAt updatedAt } ... on UserError { errors { errorPath description code } } } } Variables: { "input": { "fromFinancialAccountId": "", "toFinancialAccountId": "", "frequency": "MONTHLY", "transferAmountStrategy": { "balanceAmountType": "OUTSTANDING_BALANCE" }, "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferDayOfMonth": 3, "transferAgreementConsent": { "consentTimestamp": "2022-02-09T17:10:55.662Z", "authorizedPersonId": "", "template": { "consentTemplateId": "your-template-id", "consentTemplateVersion": "0" } } } } Expected Result: { "data": { "id": "", "toFinancialAccount": { "id": "" }, "fromFinancialAccount": { "id": "" }, "frequency": "MONTHLY", "balanceAmountType": "OUTSTANDING_BALANCE", "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferAmount": { "calculatedType": "OUTSTANDING_BALANCE" }, "status": "SCHEDULED", "nextScheduledTransferDate": "2022-03-09T00:00:00.000Z", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z" } } ### GraphQL: CreateOneTimeAchTransfer Query: mutation CreateOneTimeAchTransfer($input: CreateOneTimeACHTransferInput!) { createOneTimeACHTransfer(input: $input) { ... on OneTimeACHTransfer { id fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } descriptor { companyEntryDescription individualName individualIdentificationNumber } transferAmount { ... on ManualTransferAmount { amount { value currencyCode } } } status scheduledTransferDate createdAt updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "fromFinancialAccountId": "", "toFinancialAccountId": "", "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferAmountStrategy": { "transferAmount": { "value": "9900", "currencyCode": "USD" } }, "transferDate": "2023-03-11", "transferAgreementConsent": { "consentTimestamp": "2022-03-10T17:10:55.662Z", "authorizedPersonId": "", "template": { "consentTemplateId": "your-template-id", "consentTemplateVersion": "0" } } } } Expected Result: { "data": { "id": "", "toFinancialAccount": { "id": "" }, "fromFinancialAccount": { "id": "" }, "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferAmount": { "amount": { "value": "9900", "currencyCode": "USD" } }, "status": "SCHEDULED", "scheduledTransferDate": "2022-03-09T00:00:00.000Z", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-10T17:10:56.662Z" } } ### GraphQL: CancelScheduledTransfer Query: mutation CancelScheduledTransfer($input: CancelScheduledTransferInput!) { cancelScheduledTransfer(input: $input) { ... on Node { id } ... on RecurringACHTransfer { id fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } frequency descriptor { companyEntryDescription individualName individualIdentificationNumber } transferAmount { ... on TransferAmountCalculation { calculatedType } } status nextScheduledTransferDate createdAt updatedAt } } } Variables: { "input": { "scheduledTransferId": "" } } Expected Result: { "data": { "id": "", "toFinancialAccount": { "id": "" }, "fromFinancialAccount": { "id": "" }, "frequency": "MONTHLY", "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferAmount": { "calculatedType": "OUTSTANDING_BALANCE" }, "status": "CANCELED", "nextScheduledTransferDate": null, "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-10T17:10:56.662Z" } } ### GraphQL: findScheduledTransfer Query: query findScheduledTransfer($id: ID!) { node(id: $id) { ... on RecurringACHTransfer { id fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } frequency balanceAmountType descriptor { companyEntryDescription individualName individualIdentificationNumber } transferAmount { ... on TransferAmountCalculation { calculatedType } } status nextScheduledTransferDate createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "toFinancialAccount": { "id": "" }, "fromFinancialAccount": { "id": "" }, "frequency": "MONTHLY", "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferAmount": { "calculatedType": "OUTSTANDING_BALANCE" }, "status": "ACTIVE", "nextScheduledTransferDate": "2022-03-09T00:00:00.000Z", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-09T17:10:56.662Z" } } } --- URL: https://docs.highnote.com/docs/issuing/credit/secured-deposit-offers Title: Create Secured Deposit Offer Section: Issuing Description: Offer secured card products as an alternative to unsecured cards. Collect deposits, transfer funds, and return deposits when account holders graduate to unsecured credit. ## Overview With Highnote’s secured deposit card product feature, you can offer secured card products as an alternative during the card product application process. Secured deposit offers provide an alternative card product offering for account holders who do not meet the creditworthiness requirements for your unsecured card product. The secured deposit card product feature works as follows: 1. An account holder applies for your unsecured card product and is . 2. The account holder receives an alternative offer for your secured card product and accepts the offer. 3. When the account holder accepts the alternative offer and their application is approved, an account holder financial account is issued. This financial account has the secured deposit feature attached to it. 4. After approving the account holder for the secured card product, you collect the secured deposit in your external payment system. 5. You can use a non-originated ACH transfer to move the account holder's secured deposit to your secured deposit product financial account. 6. To apply the secured deposit to an account holder's financial account, you can use an internal Highnote transfer to move the funds from your product financial account. This flow is outlined in the following graphic: ## Enable secured deposit feature The Highnote team must enable the secured deposit feature for your card product. Contact support@highnote.com for assistance with enabling the feature. ## View card product with secured deposit feature Once you have the secured deposit feature enabled for your card product, you can use the following query to view your card product feature settings: ## Create card product application During the application process, you can use the secured deposit feature to offer account holders a secured charge card as an alternative. If you are using collaborative application decisioning, see Manage offers. For information on opening an application, see Open an application. ## Issue a financial account When an account holder accepts an alternative offer and receives approval, you can create a financial account for the account holder. The financial account includes the secured deposit feature. Use the following mutation to issue a financial account to the account holder: ## Find secured deposit product financial account When an account holder is approved for a secured deposit card product, you collect funds in your external payment system and deposit them into the secured deposit product financial account. This account is used to send the secured deposit to account holders' financial accounts. In this transfer, the and financial accounts are as follows: - : Secured deposit product financial account - : Account holder financial account Use the following query to find the product financial account with the secured deposit feature: ## Add funds to secured deposit product financial account In the Live environment, you must initiate the funds transfer to add funds to your secured deposit product financial account. Use the following mutation to simulate funding a product financial account using non-originated ACH in the Test environment: ## Transfer secured deposit to account holder financial account Use the following mutation to transfer a secured deposit from your product financial account to the account holder’s financial account. In the query, the and financial accounts are as follows: - : Secured deposit product financial account - : Account holder financial account Use the input variable field as follows: - Use the value ## Reverse a secured deposit fund distribution In the event you need to reverse a secure deposit fund distribution, use the following mutation. Reversing a secured deposit fund distribution is helpful if an error was made during the funds distribution process, or you need to return a deposit to an account holder when they graduate from a secured to unsecured charge card. In the query, the and financial accounts are as follows: - : Account holder financial account - : Secured deposit product financial account Use the input variable field as follows: - Use the value ### GraphQL: ViewCardProductWithSecuredDepositFeature Query: query ViewCardProductWithSecuredDepositFeature($id: ID!) { node(id: $id) { ... on CardProduct { features { __typename ... on SecuredDepositCardProductFeature { enabled } } } } } Variables: { "id": "" } Expected Result: { "node": { "features": [ { "__typename": "SecuredDepositCardProductFeature", "enabled": "true" } ] } } ### GraphQL: IssueFinancialAccountForApplication Query: mutation IssueFinancialAccountForApplication( $input: IssueFinancialAccountForApplicationInput! ) { issueFinancialAccountForApplication(input: $input) { ... on FinancialAccount { id features { __typename enabled createdAt updatedAt } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "features": [ { "__typename": "SecuredDepositFinancialAccountFeature", "enabled": true, "createdAt": "2021-12-28T18:20:49.933Z", "updatedAt": "2021-12-28T18:20:49.933Z" } ] } } } ### GraphQL: GetSecuredDepositFinancialAccountOnCardProduct Query: query GetSecuredDepositFinancialAccountOnCardProduct( $id: ID! $filterBy: AccountHolderFinancialAccountsFilterInput! ) { node(id: $id) { ... on CardProduct { name accounts(filterBy: $filterBy) { edges { node { features { __typename enabled createdAt updatedAt } } } } } } } Variables: { "id": "", "filterBy": { "features": { "includes": [ "PRODUCT_SECURED_DEPOSIT" ] } } } Expected Result: { "data": { "node": { "name": "My Product", "accounts": { "edges": [ { "node": { "__typename": "FinancialAccount", "id": "", "features": [ { "__typename": "ProductSecuredDepositFinancialAccountFeature", "enabled": true, "createdAt": "2024-02-02T22:53:23.345Z", "updatedAt": "2024-02-02T22:53:23.345Z" } ] } } ] } } } } ### GraphQL: SimulateExternallyInitiatedACHTransfer Query: mutation SimulateExternallyInitiatedACHTransfer( $input: SimulateExternallyInitiatedACHTransferInput! ) { simulateExternallyInitiatedACHTransfer(input: $input) { __typename ... on Node { id } ... on CreditFunds { id amount { currencyCode value } createdAt updatedAt ledgers { id name normalBalance asOf debitBalance { value currencyCode } creditBalance { value currencyCode } } status { __typename ... on NonFailureExternallyInitiatedACHStatus { status } ... on FailureExternallyInitiatedACHStatus { status statusReasonCode } } toFinancialAccount { __typename ... on FinancialAccount { id name } } companyName descriptor { companyEntryDescription individualIdentificationNumber individualName } companyIdentifier settlementDate } ... on DebitFunds { id amount { currencyCode value } createdAt updatedAt ledgers { id name normalBalance asOf debitBalance { value currencyCode } creditBalance { value currencyCode } } status { __typename ... on NonFailureExternallyInitiatedACHStatus { status } ... on FailureExternallyInitiatedACHStatus { status statusReasonCode } } fromFinancialAccount { __typename ... on FinancialAccount { id name } } companyName descriptor { companyEntryDescription individualIdentificationNumber individualName } companyIdentifier settlementDate } ... on UserError { errors { errorPath code } } ... on AccessDeniedError { message } } } Variables: { "input": { "amount": { "value": 10000, "currencyCode": "USD" }, "transferType": "CREDIT", "financialAccountId": "" } } Expected Result: { "data": { "simulateNonOriginatedACHTransfer": { "__typename": "CreditFunds", "id": "", "amount": { "currencyCode": "USD", "value": 10000 }, "createdAt": "2022-05-10T01:16:56.652Z", "updatedAt": "2022-05-10T01:16:56.669Z", "ledgers": [], "status": { "__typename": "NonFailureExternallyInitiatedACHStatus", "status": "PENDING" }, "toFinancialAccount": { "__typename": "FinancialAccount", "id": "", "name": "Business Prepaid - Product Funding" }, "companyName": "THESAMPLECOMPANY", "descriptor": { "companyEntryDescription": "ENTRYDSCPT", "individualIdentificationNumber": "", "individualName": "THISISTHERECIEVEROFACH" }, "companyIdentifier": "1234567890", "settlementDate": "2022-05-10T01:16:56.491Z" } }, "extensions": { "requested": "" } } ### GraphQL: InitiateTransferBetweenFinancialAccounts Query: mutation InitiateTransferBetweenFinancialAccounts( $input: InitiateTransferBetweenFinancialAccountsInput! ) { initiateTransferBetweenFinancialAccounts(input: $input) { __typename ... on InterFinancialAccountTransfer { id status createdAt updatedAt memo purpose amount { value currencyCode } fromFinancialAccount { id } toFinancialAccount { id } } } } Variables: { "input": { "toFinancialAccountId": "", "fromFinancialAccountId": "", "purpose": "SECURED_DEPOSIT", "memo": "Set secured deposit", "amount": { "value": 10000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferBetweenFinancialAccounts": { "__typename": "InterFinancialAccountTransfer", "id": "", "status": "COMPLETED", "createdAt": "2024-01-29T03:40:07.230Z", "updatedAt": "2024-01-29T03:40:07.230Z", "memo": "Set secured deposit", "purpose": "SECURED_DEPOSIT", "amount": { "value": 10000, "currencyCode": "USD" }, "fromFinancialAccount": { "id": "" }, "toFinancialAccount": { "id": "" } } } } ### GraphQL: InitiateTransferBetweenFinancialAccounts Query: mutation InitiateTransferBetweenFinancialAccounts( $input: InitiateTransferBetweenFinancialAccountsInput! ) { initiateTransferBetweenFinancialAccounts(input: $input) { __typename ... on InterFinancialAccountTransfer { id status createdAt updatedAt memo purpose amount { value currencyCode } fromFinancialAccount { id } toFinancialAccount { id } } } } Variables: { "input": { "fromFinancialAccountId": "", "toFinancialAccountId": "", "purpose": "SECURED_DEPOSIT_REVERSAL", "memo": "Returning secured deposit", "amount": { "value": 10000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferBetweenFinancialAccounts": { "__typename": "InterFinancialAccountTransfer", "id": "", "status": "COMPLETED", "createdAt": "2024-01-29T03:40:07.230Z", "updatedAt": "2024-01-29T03:40:07.230Z", "memo": "Returning secured deposit", "purpose": "SECURED_DEPOSIT_REVERSAL", "amount": { "value": 10000, "currencyCode": "USD" }, "fromFinancialAccount": { "id": "" }, "toFinancialAccount": { "id": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/credit/revolving/credit-plans-bnpl Title: BNPL and Flexible Installments Section: Issuing Description: Create installment credit plans to convert cleared transactions into fixed payment schedules. Define transaction eligibility, attach fee schedules, and manage installment agreements. ## Overview of installment plans You must create a purchase credit plan before creating an installment credit plan. Installment credit plans let you offer your account holders the ability to spread their payments on a transaction over a set number of installments. They are post-purchase Buy Now Pay Later offerings that let account holders convert a cleared transaction from their regular revolving credit plan into a fixed installment plan. As such, Highnote installment credit plans are attached to an existing credit card product and require that you first create a standard credit plan before creating an credit plan. To begin offering BNPL installment payment plans on your card product, 1. Create and and activate a **purchase credit plan**. 1. Create and activate an **installment credit plan** with a fee schedule. 1. Per eligible and cleared transaction, create and activate an **installment agreement**. ## View installment credit plan templates Credit plans are created from credit plan templates. Use the following query to view credit plan templates available for your card product. This query includes an optional filter by balanceType of . ## Create installment credit plan **Once created, you cannot modify a credit plan**. This prevents an unauthorized change in terms from occurring on any financial accounts. From a **credit plan template**, you can create an installment credit plan and define the minimum and maximum transaction purchase amount allowed on the plan. The allowed transaction amount must fall within the minimum and maximum range defined on the template. Installment fees are based on a percentage of the transaction purchase amount, or a fixed amount. Optionally, you can attach an installment fee schedule when creating the installment plan, by either a. providing it as an input to this mutation when creating the plan, or b. attaching it after the plan is created as shown in the Attach a credit plan fee. Use the following mutation in your Test environment to create an installment credit plan: ## Create fee schedule for installment credit plan You can create fees for installment credit plans and assess a percentage of the cleared transaction amount. If you have multiple installment credit plans, they can share the same fee schedule or have different fee schedules. For more information on creating fees, see the Fees guide. The Highnote team will configure and activate fee schedules in your Live environment, but you can simulate creating fee schedules in your Test environment using the following mutation: ## Attach fee schedule to installment credit plan You can attach the fee schedule to the credit plan if you didn't attach a fee schedule when creating the credit plan. Only installment credit plans can have an attached fee schedule with a set to . ## Activate installment credit plan You cannot have two active **standard purchase** credit plans at the same time. After creating a credit plan for your card product, you must activate it for the rates and terms to apply to new financial accounts. When activating, you can optionally set an effective start and end date. If no values are provided for start and end date, the plan will be effective upon activation and utilized until a new credit plan with the same balance type is activated on your card product. You can have multiple, active installment credit plans on your card product; but you cannot have two active _standard purchase_ credit plans at the same time. A new credit plan can be activated and applied to newly issued financial accounts. If you have multiple credit plans, the account holder’s application date determines which credit plan to apply to the issued financial account based on the credit plan’s effective dates. Use the following mutation to activate a credit plan in your Test environment: ## View card product installment credit plans ## Overview of installment agreements After creating an installment plan, you can begin creating installment agreements per transaction. Installment plans can only be offered on cleared transactions. And you must activate the installment agreement to apply the plan’s payment terms on the transaction. ## View installment eligibility for transaction events You can look up whether a group of transaction events is eligible for installments without our system actually calculating the potential offers. ## View installment offers by transaction You can view which installment credit plans qualify for a given transaction. The credit plans will provide details on the payment amount, fees, and total cost based on the plan's settings and transaction amount. Installment plans can only be offered on cleared transactions and the purchase amount must be within the min and max range defined on the credit plan. Use the following query to lookup qualifying installment credit plans offers with a cleared transaction event ID. ## Activate installment agreement for transaction Once you or your account holder has selected an installment plan, you can activate an agreement to apply the installment plan payment terms on the transaction. Use the following mutation to create an installment agreement for a cleared transaction event: ## View installment agreement by financial account You can view a paginated list of installment agreements related to a financial account using the following query: ## View installment agreement Use the following query to view an installment agreement. The snapshot field includes a rollup of payments made and remaining, broken out by principal and fees. ### GraphQL: GetCardProductWithCreditPlanTemplates Query: query GetCardProductWithCreditPlanTemplates( $id: ID! $filterBy: CreditPlanTemplateFilterInput ) { node(id: $id) { ... on CardProduct { __typename id creditPlanTemplates(first: 20, filterBy: $filterBy) { edges { node { __typename id name status planType balanceType maximumCreditLimit { value currencyCode } installmentPolicy { numberOfPeriodsRange { minimumInclusive maximumInclusive } principalAmountRange { minimumInclusive { value currencyCode } maximumInclusive { value currencyCode } } } createdAt updatedAt } } } } } } Variables: { "id": "", "filterBy": { "balanceType": "INSTALLMENT" } } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "creditPlanTemplates": { "edges": [ { "node": { "__typename": "CreditPlanTemplate", "id": "", "name": "REVOLVING_STANDARD_INSTALLMENT_ZERO_APR_NO_INTEREST", "status": "ACTIVE", "planType": "STANDARD", "balanceType": "INSTALLMENT", "maximumCreditLimit": { "value": 10000, "currencyCode": "USD" }, "installmentPolicy": { "numberOfPeriodsRange": { "minimumInclusive": 2, "maximumInclusive": 12 }, "principalAmountRange": { "minimumInclusive": { "value": 100, "currencyCode": "USD" }, "maximumInclusive": { "value": 100000, "currencyCode": "USD" } } }, "createdAt": "2025-01-01T00:00:00.000Z", "updatedAt": "2025-01-01T00:00:00.000Z" } } ] } } }, "extensions": { "requestId": "e86cea7c-fbfc-9177-8bf5-b0fa04e51050", "rateLimit": { "cost": 123, "limit": 60060, "remaining": 59937 } } } ### GraphQL: CreateCardProductInstallmentCreditPlan Query: mutation createCardProductInstallmentCreditPlan( $input: CreateCardProductInstallmentCreditPlanInput! ) { createCardProductInstallmentCreditPlan(input: $input) { __typename ... on CreditPlan { id name status planType balanceType riskBasedPricingPolicy { isRiskBased } percentageOfCreditLimit installmentPolicy { numberOfPeriods principalAmountRange { minimumInclusive { value currencyCode } maximumInclusive { value currencyCode } } } feeSchedule { id feeConfigurations { feeActivityType feeChargeRules { value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } } } } effectiveFromDate effectiveThroughDate createdAt updatedAt } ... on UserError { errors { errorPath code } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "some-installment-credit-plan", "creditPlanTemplateId": "", "productId": "", "minimumPrincipalAmount": { "value": "10000", "currencyCode": "USD" }, "maximumPrincipalAmount": { "value": "10000000", "currencyCode": "USD" }, "numberOfInstallmentPeriods": "3", "fee": { "scheduleId": "" } } } Expected Result: { "data": { "createCardProductInstallmentCreditPlan": { "__typename": "CreditPlan", "id": "", "name": "credit-plan-standard-installment-none", "status": "INACTIVE", "planType": "STANDARD", "balanceType": "INSTALLMENT", "riskBasedPricingPolicy": { "isRiskBased": false }, "percentageOfCreditLimit": 100, "installmentPolicy": { "numberOfPeriods": 6, "principalAmountRange": { "minimumInclusive": { "value": 100, "currencyCode": "USD" }, "maximumInclusive": { "value": 100000, "currencyCode": "USD" } } }, "feeSchedule": { "id": "", "feeConfigurations": [ { "feeActivityType": "INSTALLMENT_FEE", "feeChargeRules": [ { "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 1000, "currencyCode": "USD" } } } ] } ] }, "effectiveFromDate": null, "effectiveThroughDate": null, "createdAt": "2025-02-26T17:55:57.628Z", "updatedAt": "2025-02-26T17:55:57.648Z" } }, "extensions": { "requestId": "a5fc9edf-7eb2-963e-9a15-8e8c86ed372e", "rateLimit": { "cost": 20, "limit": 60060, "remaining": 60040 } } } ### GraphQL: simulateCreateAndActivateFeeSchedule Query: mutation simulateCreateAndActivateFeeSchedule( $input: SimulateCreateAndActivateFeeScheduleInput! ) { simulateCreateAndActivateFeeSchedule(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on FeeSchedule { __typename id feeScheduleAssociatedTo { __typename ... on CardProduct { id } } feeConfigurations { id feeActivityType feeChargeRules { id name order value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } } conditions { __typename ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } maximumAmount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleCountCondition { id description condition { __typename ... on CountFeeCondition { value { __typename ... on CountFeeConditionValue { count } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } } createdAt updatedAt } createdAt updatedAt } activationDate status createdAt updatedAt } } } Variables: { "input": { "cardProductId": "", "feeConfigurations": [ { "feeActivityType": "INSTALLMENT_FEE", "feeAmount": { "feeAmount": { "value": 1000, "currencyCode": "USD" } } } ] } } Expected Result: { "data": { "simulateCreateAndActivateFeeSchedule": { "__typename": "FeeSchedule", "id": "", "feeScheduleAssociatedTo": { "__typename": "CardProduct", "id": "" }, "feeConfigurations": [ { "id": "", "feeActivityType": "INSTALLMENT_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_CREDIT_INSTALLMENT_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 1000, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2025-02-26T17:44:02.062Z", "updatedAt": "2025-02-26T17:44:02.062Z" } ], "createdAt": "2025-02-26T17:44:02.063Z", "updatedAt": "2025-02-26T17:44:02.063Z" } ], "createdAt": "2025-02-26T17:44:02.062Z", "updatedAt": "2025-02-26T17:44:02.062Z" } ], "activationDate": "2025-02-26T17:44:01.888Z", "status": "ACTIVE", "createdAt": "2025-02-26T17:44:01.937Z", "updatedAt": "2025-02-26T17:44:02.142Z" } }, "extensions": { "requestId": "562a646f-ef80-9e79-b8b9-9e6ae7a36330", "rateLimit": { "cost": 23, "limit": 60060, "remaining": 60037 } } } ### GraphQL: attachFeeToCreditPlan Query: mutation attachFeeToCreditPlan($input: AttachFeeToCreditPlanInput!) { attachFeeToCreditPlan(input: $input) { __typename ... on CreditPlan { __typename id name status planType balanceType percentageOfCreditLimit installmentPolicy { __typename principalAmountRange { __typename minimumInclusive { __typename value } maximumInclusive { __typename value } } numberOfPeriods } feeSchedule { __typename id activationDate createdAt status updatedAt feeScheduleAssociatedTo { __typename ... on CardProduct { id name usage vertical features { enabled __typename } accounts { edges { node { __typename id name features { enabled __typename } activeBillingCycleConfiguration { billingCycleStartDayOfMonth paymentDueDayOfMonth billingCycleStartDayOfMonth } } } } creditPlans { edges { node { __typename id name status planType balanceType riskBasedPricingPolicy { __typename isRiskBased } percentageOfCreditLimit effectiveFromDate effectiveThroughDate interestPolicy { __typename rateType accrualType accrualMethod assessmentSchedule defaultApr scraApr } createdAt updatedAt } } } creditConfiguration { __typename interest { __typename includesPurchase includesFees } repayment { __typename repaymentWaterfall } minimumPayment { __typename thresholdAmount { __typename value currencyCode } includesFeesCharged includesPastDueAmount includesInterestAmount } } } } feeConfigurations { id __typename feeChargeRules { id name order value { __typename ... on FixedFeeChargeValue { __typename amount { value } } ... on VariableFeeChargeValue { basisPoints __typename } } __typename conditions { ... on FeeChargeRuleCountCondition { __typename createdAt id description condition { __typename operator value { __typename count maximumCount } } } ... on FeeChargeRuleAmountCondition { __typename description createdAt condition { __typename operator value { amount { value } maximumAmount { value } __typename } } } } } } } effectiveFromDate effectiveThroughDate createdAt updatedAt } ... on UserError { errors { description code } } ... on AccessDeniedError { message } } } Variables: { "input": { "creditPlanId": "", "fee": { "scheduleId": "" } } } Expected Result: { "data": { "attachFeeToCreditPlan": { "__typename": "CreditPlan", "id": "", "name": "credit-plan-standard-installment-none", "status": "INACTIVE", "planType": "STANDARD", "balanceType": "INSTALLMENT", "percentageOfCreditLimit": 100, "installmentPolicy": { "__typename": "CreditPlanInstallmentPolicy", "principalAmountRange": { "__typename": "AmountRange", "minimumInclusive": { "__typename": "Amount", "value": 100 }, "maximumInclusive": { "__typename": "Amount", "value": 100000 } }, "numberOfPeriods": 6 }, "feeSchedule": { "__typename": "FeeSchedule", "id": "", "activationDate": "2025-02-26T17:44:01.888Z", "createdAt": "2025-02-26T17:44:01.937Z", "status": "ACTIVE", "updatedAt": "2025-02-26T17:44:02.142Z", "feeScheduleAssociatedTo": null, "feeConfigurations": [ { "id": "", "__typename": "FeeConfiguration", "feeChargeRules": [ { "id": "", "name": "Priority_10_CREDIT_INSTALLMENT_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 1000 } }, "__typename": "FeeChargeRule", "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "createdAt": "2025-02-26T17:44:02.062Z", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "operator": "GREATER_THAN_OR_EQUAL", "value": { "__typename": "CountFeeConditionValue", "count": 1, "maximumCount": null } } } ] } ] } ] }, "effectiveFromDate": null, "effectiveThroughDate": null, "createdAt": "2025-02-26T17:58:06.954Z", "updatedAt": "2025-02-26T17:58:06.954Z" } }, "extensions": { "requestId": "8401f11f-1b5a-917d-93bb-7674c1c70313", "rateLimit": { "cost": 75, "limit": 60060, "remaining": 59962 } } } ### GraphQL: ActivateCardProductCreditPlan Query: mutation ActivateCardProductCreditPlan( $input: ActivateCardProductCreditPlanInput! ) { activateCardProductCreditPlan(input: $input) { __typename ... on CreditPlan { id name status planType balanceType riskBasedPricingPolicy { isRiskBased } percentageOfCreditLimit installmentPolicy { numberOfPeriods principalAmountRange { minimumInclusive { value currencyCode } maximumInclusive { value currencyCode } } } feeSchedule { id feeConfigurations { feeActivityType feeChargeRules { value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } } } } effectiveFromDate effectiveThroughDate createdAt updatedAt } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "", "effectiveFromDate": "2023-10-12", "effectiveThroughDate": "2024-10-12" } } Expected Result: { "data": { "activateCardProductCreditPlan": { "__typename": "CreditPlan", "id": "", "name": "credit-plan-standard-installment-none", "status": "ACTIVE", "planType": "STANDARD", "balanceType": "INSTALLMENT", "riskBasedPricingPolicy": { "isRiskBased": false }, "percentageOfCreditLimit": 100, "interestPolicy": null, "installmentPolicy": { "numberOfPeriods": 6, "principalAmountRange": { "minimumInclusive": { "value": 100, "currencyCode": "USD" }, "maximumInclusive": { "value": 100000, "currencyCode": "USD" } } }, "feeSchedule": { "id": "", "feeConfigurations": [ { "feeActivityType": "INSTALLMENT_FEE", "feeChargeRules": [ { "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 1000, "currencyCode": "USD" } } } ] } ] }, "effectiveFromDate": "2024-11-09", "effectiveThroughDate": "2024-10-12", "createdAt": "2025-02-26T18:59:36.015Z", "updatedAt": "2025-02-26T18:59:36.015Z" } }, "extensions": { "requestId": "54d7fc2a-aebb-9620-b61a-d6c2fe953a3f", "rateLimit": { "cost": 22, "limit": 60060, "remaining": 60038 } } } ### GraphQL: GetCardProductWithCreditPlans Query: query GetCardProductWithCreditPlans( $id: ID! $filterBy: CreditPlanFilterInput ) { node(id: $id) { ... on CardProduct { __typename id creditPlans(first: 20, filterBy: $filterBy) { edges { node { __typename id name status planType balanceType percentageOfCreditLimit installmentPolicy { principalAmountRange { minimumExclusive { value currencyCode } maximumExclusive { value currencyCode } } numberOfPeriods } feeSchedule { id feeConfigurations { feeActivityType feeChargeRules { value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } } } } effectiveFromDate effectiveThroughDate createdAt updatedAt } } } } } } Variables: { "id": "", "filterBy": { "balanceType": "INSTALLMENT", "status": "ACTIVE" } } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "creditPlans": { "edges": [ { "node": { "__typename": "CreditPlan", "id": "", "name": "credit-plan-standard-installment-none", "status": "ACTIVE", "planType": "STANDARD", "balanceType": "INSTALLMENT", "percentageOfCreditLimit": 100, "installmentPolicy": { "principalAmountRange": { "minimumExclusive": { "value": "10000", "currencyCode": "USD" }, "maximumExclusive": { "value": "10000000", "currencyCode": "USD" } }, "numberOfPeriods": 6 }, "feeSchedule": { "id": "", "feeConfigurations": [ { "feeActivityType": "INSTALLMENT_FEE", "feeChargeRules": [ { "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 1000, "currencyCode": "USD" } } } ] } ] }, "effectiveFromDate": "2024-11-09", "effectiveThroughDate": null, "createdAt": "2025-02-26T18:59:36.015Z", "updatedAt": "2025-02-26T18:59:36.015Z" } }, { "node": { "__typename": "CreditPlan", "id": "", "name": "standard-installment-credit-plan-zero-apr-9-period", "status": "ACTIVE", "planType": "STANDARD", "balanceType": "INSTALLMENT", "percentageOfCreditLimit": 100, "installmentPolicy": { "principalAmountRange": { "minimumExclusive": { "value": "10000", "currencyCode": "USD" }, "maximumExclusive": { "value": "10000000", "currencyCode": "USD" } }, "numberOfPeriods": 9 }, "feeSchedule": null, "effectiveFromDate": "2024-11-09", "effectiveThroughDate": null, "createdAt": "2025-02-20T04:54:32.673Z", "updatedAt": "2025-02-20T04:54:32.674Z" } } ] } } }, "extensions": { "requestId": "a3807e5f-3e3f-968d-a657-ca5e662d1c18", "rateLimit": { "cost": 183, "limit": 60060, "remaining": 59877 } } } ### GraphQL: installmentEligibilityForTransactionEvents Query: query installmentEligibilityForTransactionEvents( $input: InstallmentEligibilityForTransactionEventsInput! ) { installmentEligibilityForTransactionEvents(input: $input) { __typename ... on InstallmentEligibilityForTransactionEvents { eligibilityByTransactionEvent { transactionEvent { __typename id } eligibility } } ... on UserError { errors { code description } } } } Variables: { "input": { "cardTransactionEventIds": [ "", "" ] } } Expected Result: { "data": { "installmentEligibilityForTransactionEvents": { "eligibilityByTransactionEvent": [ { "transactionEvent": { "__typename": "AuthorizationAndClearEvent", "id": "" }, "eligibility": "ELIGIBLE" }, { "transactionEvent": { "__typename": "ClearingEvent", "id": "" }, "eligibility": "NOT_ELIGIBLE" } ] } } } ### GraphQL: installmentOffersForTransactionEvent Query: query installmentOffersForTransactionEvent( $input: InstallmentOffersForTransactionEventInput! ) { installmentOffersForTransactionEvent(input: $input) { __typename ... on InstallmentOffersForTransactionEvent { transactionEvent { __typename id approvedAmount { value currencyCode } createdAt } offers { creditPlan { id installmentPolicy { __typename principalAmountRange { minimumInclusive { value currencyCode } maximumInclusive { value currencyCode } } numberOfPeriods } feeSchedule { id feeConfigurations { feeActivityType feeChargeRules { value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } } } } } details { totalCost { value currencyCode } totalPrincipal { value currencyCode } totalFees { value currencyCode } principalDuePerPeriod { value currencyCode } feesChargedPerPeriod { value currencyCode } } } } ... on UserError { errors { code description } } } } Variables: { "input": { "cardTransactionEventId": "" } } Expected Result: { "data": { "installmentOffersForTransactionEvent": { "__typename": "InstallmentOffersForTransactionEvent", "transactionEvent": { "__typename": "ClearingEvent", "id": "", "approvedAmount": { "value": 40000, "currencyCode": "USD" }, "createdAt": "2024-11-01T16:39:46.442Z" }, "offers": [ { "creditPlan": { "id": "", "installmentPolicy": { "__typename": "CreditPlanInstallmentPolicy", "principalAmountRange": { "minimumInclusive": { "value": 10000, "currencyCode": "USD" }, "maximumInclusive": { "value": 50000, "currencyCode": "USD" } }, "numberOfPeriods": 9 }, "feeSchedule": null }, "details": { "totalCost": { "value": 40000, "currencyCode": "USD" }, "totalPrincipal": { "value": 40000, "currencyCode": "USD" }, "totalFees": { "value": 0, "currencyCode": "USD" }, "principalDuePerPeriod": { "value": 4445, "currencyCode": "USD" }, "feesChargedPerPeriod": { "value": 0, "currencyCode": "USD" } } }, { "creditPlan": { "id": "", "installmentPolicy": { "__typename": "CreditPlanInstallmentPolicy", "principalAmountRange": { "minimumInclusive": { "value": 10000, "currencyCode": "USD" }, "maximumInclusive": { "value": 1000000, "currencyCode": "USD" } }, "numberOfPeriods": 6 }, "feeSchedule": null }, "details": { "totalCost": { "value": 40000, "currencyCode": "USD" }, "totalPrincipal": { "value": 40000, "currencyCode": "USD" }, "totalFees": { "value": 0, "currencyCode": "USD" }, "principalDuePerPeriod": { "value": 6667, "currencyCode": "USD" }, "feesChargedPerPeriod": { "value": 0, "currencyCode": "USD" } } }, { "creditPlan": { "id": "", "installmentPolicy": { "__typename": "CreditPlanInstallmentPolicy", "principalAmountRange": { "minimumInclusive": { "value": 10000, "currencyCode": "USD" }, "maximumInclusive": { "value": 2000000, "currencyCode": "USD" } }, "numberOfPeriods": 3 }, "feeSchedule": null }, "details": { "totalCost": { "value": 40000, "currencyCode": "USD" }, "totalPrincipal": { "value": 40000, "currencyCode": "USD" }, "totalFees": { "value": 0, "currencyCode": "USD" }, "principalDuePerPeriod": { "value": 13334, "currencyCode": "USD" }, "feesChargedPerPeriod": { "value": 0, "currencyCode": "USD" } } } ] } }, "extensions": { "requestId": "105e4525-249c-964d-8216-20a5b801e098", "rateLimit": { "cost": 20, "limit": 60060, "remaining": 60040 } } } ### GraphQL: activateInstallmentAgreementForTransactionEvent Query: mutation activateInstallmentAgreementForTransactionEvent( $input: ActivateInstallmentAgreementForTransactionEventInput! ) { activateInstallmentAgreementForTransactionEvent(input: $input) { __typename ... on InstallmentAgreement { id status agreement { creditPlan { id installmentPolicy { principalAmountRange { minimumInclusive { value currencyCode } maximumInclusive { value currencyCode } } numberOfPeriods } } details { totalCost { value currencyCode } totalPrincipal { value currencyCode } totalFees { value currencyCode } principalDuePerPeriod { value currencyCode } feesChargedPerPeriod { value currencyCode } } } transactionEvent { id } snapshot { asOf installmentPaymentsCompleted { principalBalancePaid { value currencyCode } feesPaid { value currencyCode } numberOfInstallmentsCompleted } installmentPaymentsRemaining { principalBalanceRemaining { value currencyCode } estimatedFeesRemaining { value currencyCode } numberOfInstallmentsRemaining } } installmentAgreementPeriodStart createdAt updatedAt } ... on UserError { errors { description code } } } } Variables: { "input": { "creditPlanId": "", "cardTransactionEventId": "" } } Expected Result: { "data": { "activateInstallmentAgreementForTransactionEvent": { "__typename": "InstallmentAgreement", "id": "", "status": "OPEN", "agreement": { "creditPlan": { "id": "", "installmentPolicy": { "principalAmountRange": { "minimumInclusive": { "value": 10000, "currencyCode": "USD" }, "maximumInclusive": { "value": 2000000, "currencyCode": "USD" } }, "numberOfPeriods": 3 } }, "details": { "totalCost": { "value": 0, "currencyCode": "USD" }, "totalPrincipal": { "value": 40000, "currencyCode": "USD" }, "totalFees": { "value": 0, "currencyCode": "USD" }, "principalDuePerPeriod": { "value": 13334, "currencyCode": "USD" }, "feesChargedPerPeriod": { "value": 0, "currencyCode": "USD" } } }, "transactionEvent": { "id": "" }, "snapshot": { "asOf": "2025-02-26T19:17:43.659Z", "installmentPaymentsCompleted": { "principalBalancePaid": { "value": 0, "currencyCode": "USD" }, "feesPaid": { "value": 0, "currencyCode": "USD" }, "numberOfInstallmentsCompleted": null }, "installmentPaymentsRemaining": { "principalBalanceRemaining": { "value": 40000, "currencyCode": "USD" }, "estimatedFeesRemaining": { "value": 0, "currencyCode": "USD" }, "numberOfInstallmentsRemaining": 3 } }, "installmentAgreementPeriodStart": "2025-02-26T19:17:43.536Z", "createdAt": "2025-02-26T19:17:43.536Z", "updatedAt": "2025-02-26T19:17:43.659Z" } }, "extensions": { "requestId": "66fb12da-1d1c-9c5a-bb35-845e254c02a0", "rateLimit": { "cost": 30, "limit": 60060, "remaining": 60028 } } } ### GraphQL: GetFinancialAccountWithInstallmentAgreements Query: query GetFinancialAccountWithInstallmentAgreements( $id: ID! $filterBy: InstallmentAgreementFilterInput ) { node(id: $id) { ... on FinancialAccount { __typename id installmentAgreements(first: 20, filterBy: $filterBy) { __typename pageInfo { hasNextPage hasPreviousPage } edges { cursor node { __typename ... on InstallmentAgreement { id installmentAgreementPeriodStart status agreement { creditPlan { __typename id } details { principalDuePerPeriod { value currencyCode } } } snapshot { __typename asOf installmentPaymentsCompleted { principalBalancePaid { value currencyCode } feesPaid { value currencyCode } numberOfInstallmentsCompleted } installmentPaymentsRemaining { principalBalanceRemaining { value currencyCode } estimatedFeesRemaining { value currencyCode } numberOfInstallmentsRemaining } } transactionEvent { __typename ... on ClearingEvent { approvedAmount { value currencyCode } } } statusHistory { __typename newStatus previousStatus } createdAt updatedAt } } } } } } } Variables: { "id": "", "filterBy": { "installmentAgreementStatus": "OPEN", "transactionEventIds": [ "", "" ] } } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "id": "", "installmentAgreements": { "__typename": "InstallmentAgreementConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "dD0yMDI1LTAyLTIwVDA0JTNBNTclM0E0OS45NDMwMDAwMDBaJmk9Y3JpbnNfNjMyNmQyZDFkZjVhNGE3MGI4MzIwMmZkMmYwMzQzN2Y", "node": { "__typename": "InstallmentAgreement", "id": "", "installmentAgreementPeriodStart": "2025-02-20T04:57:49.943Z", "status": "OPEN", "agreement": { "creditPlan": { "__typename": "CreditPlan", "id": "" }, "details": { "principalDuePerPeriod": { "value": 112, "currencyCode": "USD" } } }, "snapshot": { "__typename": "InstallmentAgreementSnapshot", "asOf": "2025-02-20T04:57:49.977Z", "installmentPaymentsCompleted": { "principalBalancePaid": { "value": 0, "currencyCode": "USD" }, "feesPaid": { "value": 0, "currencyCode": "USD" }, "numberOfInstallmentsCompleted": null }, "installmentPaymentsRemaining": { "principalBalanceRemaining": { "value": 1000, "currencyCode": "USD" }, "estimatedFeesRemaining": { "value": 0, "currencyCode": "USD" }, "numberOfInstallmentsRemaining": 9 } }, "transactionEvent": { "__typename": "ClearingEvent", "id": "", "approvedAmount": { "value": 1000, "currencyCode": "USD" } }, "statusHistory": null, "createdAt": "2025-02-20T04:57:49.943Z", "updatedAt": "2025-02-20T04:57:49.977Z" } } ] } } }, "extensions": { "requestId": "eb41af15-bb67-9f7c-a4d1-11652e686f99", "rateLimit": { "cost": 283, "limit": 60060, "remaining": 59777 } } } ### GraphQL: nodeInstallmentAgreement Query: query nodeInstallmentAgreement($id: ID!) { node(id: $id) { __typename ... on InstallmentAgreement { id installmentAgreementPeriodStart status agreement { creditPlan { __typename id name status planType balanceType riskBasedPricingPolicy { isRiskBased } percentageOfCreditLimit effectiveFromDate effectiveThroughDate feeSchedule { id feeConfigurations { feeActivityType feeChargeRules { value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } } } } createdAt updatedAt } details { principalDuePerPeriod { value currencyCode } feesChargedPerPeriod { value currencyCode } totalCost { value currencyCode } totalFees { value currencyCode } totalPrincipal { value currencyCode } } } snapshot { asOf installmentPaymentsCompleted { principalBalancePaid { value currencyCode } feesPaid { value currencyCode } numberOfInstallmentsCompleted } installmentPaymentsRemaining { principalBalanceRemaining { value currencyCode } estimatedFeesRemaining { value currencyCode } numberOfInstallmentsRemaining } __typename } transactionEvent { __typename ... on ClearingEvent { id approvedAmount { value currencyCode } } } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "InstallmentAgreement", "id": "", "installmentAgreementPeriodStart": "2025-02-20T04:57:49.943Z", "status": "OPEN", "agreement": { "creditPlan": { "__typename": "CreditPlan", "id": "", "name": "standard-installment-credit-plan-zero-apr-9-period", "status": "ACTIVE", "planType": "STANDARD", "balanceType": "INSTALLMENT", "riskBasedPricingPolicy": { "isRiskBased": false }, "percentageOfCreditLimit": 100, "effectiveFromDate": "2024-11-09", "effectiveThroughDate": null, "feeSchedule": null, "createdAt": "2025-02-20T04:54:32.673Z", "updatedAt": "2025-02-20T04:54:32.674Z" }, "details": { "principalDuePerPeriod": { "value": 112, "currencyCode": "USD" }, "feesChargedPerPeriod": { "value": 0, "currencyCode": "USD" }, "totalCost": { "value": 1000, "currencyCode": "USD" }, "totalFees": { "value": 0, "currencyCode": "USD" }, "totalPrincipal": { "value": 1000, "currencyCode": "USD" } } }, "snapshot": { "asOf": "2025-02-20T04:57:49.977Z", "installmentPaymentsCompleted": { "principalBalancePaid": { "value": 0, "currencyCode": "USD" }, "feesPaid": { "value": 0, "currencyCode": "USD" }, "numberOfInstallmentsCompleted": null }, "installmentPaymentsRemaining": { "principalBalanceRemaining": { "value": 1000, "currencyCode": "USD" }, "estimatedFeesRemaining": { "value": 0, "currencyCode": "USD" }, "numberOfInstallmentsRemaining": 9 }, "__typename": "InstallmentAgreementSnapshot" }, "transactionEvent": { "__typename": "ClearingEvent", "id": "", "approvedAmount": { "value": 1000, "currencyCode": "USD" } }, "createdAt": "2025-02-20T04:57:49.943Z", "updatedAt": "2025-02-20T04:57:49.977Z" } }, "extensions": { "requestId": "14f78d79-c715-99e4-a70c-8eba714a53ef", "rateLimit": { "cost": 24, "limit": 60060, "remaining": 60036 } } } --- URL: https://docs.highnote.com/docs/issuing/credit/revolving/credit-plans-standard-purchase Title: Standard Credit Purchase Section: Issuing Description: Create purchase credit plans for standard revolving credit. Define APR, credit limit usage, and payment terms using credit plan templates. ## Overview Purchase plans are standard revolving credit card products. They let you offer your account holders the ability to make flexible payments (above the minimum) while maintaining access to their full credit line. To begin offering purchase plans on your card product, create and activate a purchase credit plan from a credit plan template. ## View purchase credit plan templates Credit plans are created from credit plan templates. Use the following query to view credit plan templates available for your card product. This query includes an optional filter by balanceType of . ## Create purchase credit plan **Once created, you cannot modify a credit plan**. This prevents an unauthorized change of terms from occurring on any financial accounts. Newly created standard purchase credit plans cannot be applied to previously booked financial accounts. From a credit plan template, you can create a credit plan and define the APR and percentage of the available credit limit. The assigned APR must fall within the minimum and maximum range defined on the template. Refer to the following guidance when defining credit limit usage: - For credit plans with a balance type, you should allow the account holder to utilize 100% of their financial account's credit limit. - For credit plans with other balance types, such as cash advances, you may choose to allow only a portion of the financial account’s credit limit to be utilized. For example, you could allow 25% utilization. Use the following mutation in your Test environment to create a credit plan: ## Activate purchase credit plan You can activate credit plans in the Test environment. Highnote will activate your credit plans in the Live environment. After creating a credit plan for your card product, you must activate it for the rates and terms to apply to new financial accounts. In the Live environment, Highnote activates the credit plan on your behalf. When activating, you can optionally set an effective start and end date. If no values are provided for start and end date, the plan is effective when activated and usable until a new credit plan with the same balance type is activated on your card product. You cannot have two active credit plans that apply to the same balance type at the same time. However, a new credit plan can be activated and applied to newly issued financial accounts. If you have multiple credit plans, the account holder’s application date determines which credit plan to apply to the issued financial account based on the credit plan’s effective dates. Use the following mutation to activate a credit plan in your Test environment: ## View card product purchase credit plans You can view a paginated list of active and inactive purchase credit plans on your card product using the following query: ### GraphQL: getCardProductWithCreditPlanTemplatesRevolving Query: query GetCardProductWithCreditPlanTemplates( $id: ID! $filterBy: CreditPlanTemplateFilterInput ) { node(id: $id) { ... on CardProduct { __typename id creditPlanTemplates(first: 20, filterBy: $filterBy) { pageInfo { hasNextPage } edges { cursor node { __typename id name status planType balanceType interestPolicy { rateType accrualType accrualMethod assessmentSchedule aprRange { minimum maximum } variableAprIndex scraApr } maximumCreditLimit { value currencyCode } createdAt updatedAt } } } } } } Variables: { "id": "", "filterBy": { "balanceType": "PURCHASE" } } Expected Result: { "data": { "creditPlanTemplates": { "pageInfo": { "hasNextPage": "false" }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "CreditPlanTemplate", "id": "", "name": "some-template-name", "status": "INACTIVE", "planType": "STANDARD", "balanceType": "PURCHASE", "interestPolicy": { "rateType": "FIXED", "accrualType": "COMPOUND", "accrualMethod": "PAYMENT_DUE_DATE", "assessmentSchedule": "DAILY", "aprRange": { "minimum": "5.00", "maximum": "15.00" }, "variableAprIndex": "PRIME", "scraApr": "5.25" }, "maximumCreditLimit": { "value": "10000", "currencyCode": "USD" }, "createdAt": "2023-07-27T04:00:00.000Z", "updatedAt": "2023-07-27T04:00:00.000Z" } } ] } } } ### GraphQL: createCardProductCreditPlan Query: mutation createCardProductCreditPlan( $input: CreateCardProductCreditPlanInput! ) { createCardProductCreditPlan(input: $input) { __typename ... on CreditPlan { id name status planType balanceType riskBasedPricingPolicy { isRiskBased } percentageOfCreditLimit interestPolicy { rateType accrualType accrualMethod assessmentSchedule defaultApr scraApr } effectiveFromDate effectiveThroughDate createdAt updatedAt } } } Variables: { "input": { "name": "some-credit-plan", "creditPlanTemplateId": "", "productId": "", "percentageOfCreditLimit": 100, "defaultApr": 10 } } Expected Result: { "data": { "createCardProductCreditPlan": { "__typename": "CreditPlan", "id": "", "name": "some-credit-plan", "status": "INACTIVE", "planType": "STANDARD", "balanceType": "PURCHASE", "riskBasedPricingPolicy": { "isRiskBased": false }, "percentageOfCreditLimit": 100, "interestPolicy": { "rateType": "FIXED", "accrualType": "COMPOUND", "accrualMethod": "TRANSACTION_POST_DATE", "assessmentSchedule": "STATEMENT", "defaultApr": 10, "scraApr": 6 }, "effectiveFromDate": null, "effectiveThroughDate": null, "createdAt": "2023-10-12T20:21:40.164Z", "updatedAt": "2023-10-12T20:21:40.165Z" } }, "extensions": { "": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60048 } } } ### GraphQL: ActivateCardProductCreditPlan Query: mutation activateCardProductCreditPlan( $input: ActivateCardProductCreditPlanInput! ) { activateCardProductCreditPlan(input: $input) { __typename ... on CreditPlan { id name status planType balanceType riskBasedPricingPolicy { isRiskBased } percentageOfCreditLimit interestPolicy { rateType accrualType accrualMethod assessmentSchedule defaultApr scraApr } effectiveFromDate effectiveThroughDate createdAt updatedAt } } } Variables: { "input": { "id": "", "effectiveFromDate": "2023-10-12", "effectiveThroughDate": "2024-10-12" } } Expected Result: { "data": { "activateCardProductCreditPlan": { "__typename": "CreditPlan", "id": "", "name": "some-credit-plan", "status": "ACTIVE", "planType": "STANDARD", "riskBasedPricingPolicy": { "isRiskBased": false }, "percentageOfCreditLimit": 100, "interestPolicy": { "rateType": "FIXED", "accrualType": "COMPOUND", "accrualMethod": "TRANSACTION_POST_DATE", "assessmentSchedule": "STATEMENT", "defaultApr": 10, "scraApr": 6 }, "effectiveFromDate": "2023-10-12", "effectiveThroughDate": "2024-10-12", "createdAt": "2023-10-12T20:22:31.633Z", "updatedAt": "2023-10-12T20:22:31.636Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60048 } } } ### GraphQL: getCardProductWithCreditPlansRevolving Query: query GetCardProductWithCreditPlans( $id: ID! $filterBy: CreditPlanFilterInput ) { node(id: $id) { ... on CardProduct { __typename id creditPlans(first: 20, filterBy: $filterBy) { pageInfo { hasNextPage } edges { cursor node { __typename id name status planType balanceType riskBasedPricingPolicy { isRiskBased } percentageOfCreditLimit interestPolicy { rateType accrualType accrualMethod assessmentSchedule defaultApr scraApr } effectiveFromDate effectiveThroughDate createdAt updatedAt } } } } } } Variables: { "id": "", "filterBy": { "balanceType": "PURCHASE" } } Expected Result: { "data": { "creditPlans": { "pageInfo": { "hasNextPage": "false" }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "CreditPlan", "id": "", "name": "some-plan-name", "status": "INACTIVE", "planType": "STANDARD", "balanceType": "PURCHASE", "riskBasedPricingPolicy": { "isRiskBased": false }, "percentageOfCreditLimit": 50, "interestPolicy": { "rateCalculator": "FIXED", "accrualType": "COMPOUND", "accrualMethod": "PAYMENT_DUE_DATE", "assessmentSchedule": "DAILY", "defaultApr": "10.25", "scraApr": "5.0" }, "effectiveFromDate": "2025-01-01", "effectiveThroughDate": "2025-12-01", "createdAt": "2023-07-27T04:00:00.000Z", "updatedAt": "2023-07-27T04:00:00.000Z" } } ] } } } --- URL: https://docs.highnote.com/docs/issuing/credit/revolving/find-variable-interest-rates Title: Find Variable Interest Rates Section: Issuing Description: Look up variable interest rates for credit card products based on the Wall Street Journal (WSJ) Prime Rate. View rates on credit plans, applications, and financial accounts, and waive interest on transfer events. ## Overview Highnote supports variable interest rates for credit card products. We provide updated prime rates as necessary, and it is your responsibility to reflect accurate interest rates to your account holders. Highnote calculates APR by using the sum of the prime rate and the margin you provide. The prime rate used when calculating your APR reflects the Wall Street Journal's Prime Rate, published on December 25th, March 25th, June 25th, and September 25th. Updated rates take effect at the beginning of the next billing period: January, April, July, and October, respectively. ## Prerequisites - A Highnote account - A credit card product with the variable interest feature enabled - Access to the Highnote API or API Explorer ## Prime rate update schedule Refer to the following table for a breakdown of rate update schedules and effective dates. The example column shows two example statements, using an increase of 8.5% to 9.75%: | Rate update schedule | Effective date | Example | | :------------------- | :------------- | :--------------------------------------------------------------------------------------------- | | December 25th | January 1st | December 20th to January 19th statement: 8.5%, January 20th to February 19th statement: 9.75% | | March 25th | April 1st | March 20th to April 19th statement: 8.5%, April 20th to May 19th statement: 9.75% | | June 25th | July 1st | June 20th to July 19th statement: 8.5%, July 20th to August 19th statement: 9.75% | | September 25th | October 1st | September 20th to October 19th statement: 8.5%, October 20th to November 19th statement: 9.75% | ## Find credit plan interest rate When creating a credit plan in the Live environment, the Highnote team configures your interest rate. Use the following query to find a credit plan's interest rate and policy: ## View interest rate on application An interest rate is assigned during the account holder card product application process. You can use the following query to view the interest rate and policy to display them to your account holder during the application process: ## View interest on financial account An account holder's financial account displays their credit plan and interest rate. Use the following query to view the interest rate on a financial account: ## View credit card transfer event Use the following query to lookup a credit card transfer event and set the input to the desired value. ## Waive interest for credit card transfer event Use the following mutation to waive the interest for a credit card transfer event. ### GraphQL: LookupCreditPlanInterestRateIndex Query: query LookupCreditPlanInterestRateIndex($id: ID!) { node(id: $id) { ... on CreditPlan { id interestPolicy { rateType index { type value effectiveDate } } } } } Variables: { "id": "crppn_1" } Expected Result: { "data": { "__typename": "CreditPlan", "id": "", "interestPolicy": { "rateType": "VARIABLE", "interestRateIndex": { "type": "PRIME", "value": "8.5", "effectiveDate": "2023-10-01" } } } } ### GraphQL: GetAccountHolderCardProductApplication Query: query GetAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { currentCreditUnderwritingVerification { decision { ... on UnderwriterPositiveDecision { __typename creditLine { value currencyCode } creditPlanTerms { creditPlan { __typename id planType balanceType interestPolicy { rateType index { type value effectiveDate } } } interest { apr } } } } } } ... on USBusinessAccountHolderSnapshot { businessProfile { currentCreditUnderwritingVerification { decision { ... on UnderwriterPositiveDecision { __typename creditLine { value currencyCode } creditPlanTerms { creditPlan { __typename id planType balanceType interestPolicy { rateType index { type value effectiveDate } } } interest { apr } } } } } } } } } } } Variables: { "id": "ap_1" } Expected Result: { "data": { "__typename": "AccountHolderCardProductApplication", "id": "", "accountHolderSnapshot": { "currentCreditUnderwritingVerification": { "decision": { "__typename": "UnderwriterPositiveDecision", "creditLine": { "value": "10000", "currencyCode": "USD" }, "creditPlanTerms": [ { "creditPlan": { "__typename": "CreditPlan", "id": "", "planType": "STANDARD", "balanceType": "PURCHASE", "interestPolicy": { "rateType": "VARIABLE", "index": { "type": "PRIME", "value": "8.5", "effectiveDate": "2023-10-01" } } }, "interest": { "apr": "13.6" } }, { "creditPlan": { "__typename": "CreditPlan", "id": "", "planType": "STANDARD", "balanceType": "CASH_ADVANCE", "interestPolicy": { "rateType": "FIXED", "index": null } }, "interest": { "apr": "22.6" } } ] } } } } } ### GraphQL: LookupFinancialAccountCreditConfiguration Query: query LookupFinancialAccountCreditConfiguration($id: ID!) { node(id: $id) { ... on FinancialAccount { id creditConfiguration { interestRates { __typename balanceType interest { apr } creditPlan { __typename id planType interestPolicy { rateType index { type value effectiveDate } } } } } } } } Variables: { "id": "ac_1" } Expected Result: { "data": { "__typename": "FinancialAccount", "id": "", "creditConfiguration": { "interestRates": [ { "__typename": "CreditPlanFinancialAccountConfiguration", "balanceType": "PURCHASE", "interest": { "apr": "13.6" }, "creditPlan": { "__typename": "CreditPlan", "id": "", "planType": "STANDARD", "interestPolicy": { "rateType": "VARIABLE", "index": { "type": "PRIME", "value": "8.5", "effectiveDate": "2023-10-01" } } } }, { "__typename": "CreditPlanFinancialAccountConfiguration", "balanceType": "CASH_ADVANCE", "interest": { "apr": "10.5" }, "creditPlan": { "__typename": "CreditPlan", "id": "", "planType": "STANDARD", "interestPolicy": { "rateType": "FIXED", "index": null } } } ] } } } ### GraphQL: getCreditCardTransferEvent Query: query LookupCreditCardTransferEvent($id: ID!) { node(id: $id) { __typename ... on CreditCardTransferEvent { id creditCardInterestTransferEvent { __typename ... on CreditCardInterestReversal { transferAmount { value currencyCode } financialAccount { __typename id } cardProduct { __typename id } creditPlan { __typename id } statement { __typename id } sourceInterestAccrual { __typename id creditCardInterestTransferEvent { __typename ... on CreditCardInterestAccrual { transferAmount { value currencyCode } financialAccount { __typename id } cardProduct { __typename id } creditPlan { __typename id } statement { __typename id } apr createdAt } } } createdAt } ... on CreditCardInterestAccrual { transferAmount { value currencyCode } financialAccount { __typename id } cardProduct { __typename id } creditPlan { __typename id } statement { __typename id } apr createdAt } } } } } Variables: { "id": "sibal_1" } Expected Result: { "data": { "node": { "__typename": "CreditCardTransferEvent", "id": "", "creditCardInterestTransferEvent": { "__typename": "CreditCardInterestReversal", "transferAmount": { "value": 254, "currencyCode": "USD" }, "financialAccount": { "__typename": "FinancialAccount", "id": "" }, "cardProduct": { "__typename": "CardProduct", "id": "" }, "creditPlan": { "__typename": "CreditPlan", "id": "" }, "statement": { "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "id": "" }, "sourceInterestAccrual": { "__typename": "CreditCardTransferEvent", "id": "", "creditCardInterestTransferEvent": { "__typename": "CreditCardInterestAccrual", "transferAmount": { "value": 254, "currencyCode": "USD" }, "financialAccount": { "__typename": "FinancialAccount", "id": "" }, "cardProduct": { "__typename": "CardProduct", "id": "" }, "creditPlan": { "__typename": "CreditPlan", "id": "" }, "statement": { "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "id": "" }, "apr": 29.56, "createdAt": "2025-10-07T16:12:37.115Z" } }, "createdAt": "2025-10-07T16:13:22.856Z" } } }, "extensions": { "requestId": "25b73965-a977-9579-84ce-39f9a6d2ce38", "rateLimit": { "cost": 14, "limit": 2500, "remaining": 2486, "asOf": "2025-10-07T16:18:22.233Z", "complexity": { "limit": 2500, "remaining": 2486, "cost": 14 }, "count": { "limit": 100, "remaining": 99, "cost": 1 } } } } ### GraphQL: waiveInterestAmountForClosedStatement Query: mutation waiveInterestAmountForClosedStatement( $input: WaiveInterestAmountForClosedStatementInput! ) { waiveInterestAmountForClosedStatement(input: $input) { __typename ... on CreditCardTransferEvent { __typename id creditCardInterestTransferEvent { __typename ... on CreditCardInterestReversal { financialAccount { id } cardProduct { id } creditPlan { id } statement { id } transferAmount { value currencyCode } sourceInterestAccrual { __typename id creditCardInterestTransferEvent { __typename ... on CreditCardInterestAccrual { financialAccount { id } apr cardProduct { id } creditPlan { id } statement { id } transferAmount { value currencyCode } createdAt } } } createdAt } } } ... on UserError { __typename errors { code description errorPath } } ... on AccessDeniedError { __typename message } } } Variables: { "input": { "cardTransactionEventId": "sibal_1" } } Expected Result: { "data": { "__typename": "CreditCardTransferEvent", "id": "", "creditCardTransferEvent": { "__typename": "CreditCardTransferEvent", "id": "", "balanceType": "PURCHASE", "accountingDirection": "DEBIT", "statement": { "id": "" }, "creditPlan": { "id": "" }, "creditCardInterestTransferEvent": { "__typename": "CreditCardInterestReversal", "financialAccount": { "id": "" }, "cardProduct": { "id": "" }, "creditPlan": { "id": "" }, "statement": { "id": "" }, "transferAmount": { "value": "10000", "currencyCode": "USD" }, "createdAt": "2025-01-01T00:00:00.000Z", "sourceInterestAccrual": { "__typename": "CreditCardTransferEvent", "id": "", "creditCardInterestTransferEvent": { "__typename": "CreditCardInterestAccrual", "financialAccount": { "id": "" }, "apr": "25.5", "cardProduct": { "id": "" }, "creditPlan": { "id": "" }, "statement": { "id": "" }, "transferAmount": { "value": "10000", "currencyCode": "USD" }, "createdAt": "2025-01-01T00:00:00.000Z" } } } } } } --- URL: https://docs.highnote.com/docs/issuing/credit/revolving/reporting-credit-bureau-consumer Title: Credit Bureau Reporting Section: Issuing Description: Report account holder credit history and repayments to credit bureaus through Bloom Credit integration. ## Overview Credit programs require access to cardholders' credit data. Highnote has partnered with Bloom Credit to create integrated credit reporting and dispute management. Bloom reports account holder history and repayments to credit bureaus on your behalf. ## Enable Bloom Credit integration Highnote's Bloom Credit integration provides a seamless, hassle-free experience for credit reporting. With this integration enabled for your credit card product, Bloom will report account holder credit history and repayments to the credit bureaus on your behalf. To enable the Bloom Credit integration for your credit card product, contact our Sales team. --- URL: https://docs.highnote.com/docs/issuing/credit/revolving/scra-and-mla Title: SCRA and MLA Section: Issuing Description: Apply SCRA and MLA protections for active-duty service members including interest rate caps and fee restrictions. Verify military status for account holders. ## Overview Highnote will assist with establishing policies and procedures to verify MLA eligibility and SCRA requests for your account holders. The Service Members Civil Relief Act (SCRA) and Military Lending Act (MLA) protect active-duty service members and their families from financial hardships and predatory lending practices: - SCRA provides legal protections, such as interest rate caps and eviction protection. - MLA restricts the interest rates and fees lenders charge protected individuals and families. Compliance with SCRA and MLA is _mandatory_ for issuers and requires the following: - Adjusting interest rates accordingly - Providing protections in line with SCRA and MLA laws - Verifying military status for account holders to ensure fair treatment and financial stability for service members Highnote applies SCRA and MLA benefits to your eligible account holders' financial accounts. ## Lookup military status You can use the following query to find the military status on a financial account. This is essential to lookup if the financial account is eligible for SCRA or MLA benefits, and the effective dates to apply benefits. ### GraphQL: LookupFinancialAccountMilitaryStatus Query: query LookupFinancialAccountMilitaryStatus($id: ID!) { node(id: $id) { ... on FinancialAccount { id creditConfiguration { servicemembersCivilReliefAct { effectiveFrom effectiveThrough activeDutyFrom activeDutyThrough updatedAt createdAt } militaryLendingAct { effectiveFrom effectiveThrough updatedAt createdAt } } } } } Variables: { "input": { "financialAccountId": "" } } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "id": "", "creditConfiguration": { "servicemembersCivilReliefAct": { "effectiveFrom": "2024-01-01", "effectiveThrough": null, "activeDutyFrom": "2024-01-01", "activeDutyThrough": null, "updatedAt": "2023-12-01T00:00:00.000Z", "createdAt": "2023-12-01T00:00:00.000Z" }, "militaryLendingAct": { "effectiveFrom": "2023-01-01", "effectiveThrough": "2023-11-01", "updatedAt": "2023-01-01T00:00:00.000Z", "createdAt": "2023-01-01T00:00:00.000Z" } } } } } --- URL: https://docs.highnote.com/docs/issuing/credit/revolving/set-and-update-limits Title: Set and Update Credit Limits Section: Issuing Description: Set initial credit limits and create credit limit change requests. Approve or deny increases and decreases with underwriting decisions and adverse action reasons. ## Overview For credit, charge, and fleet card products, you can create or update a credit limit for an account holder's financial account based on your underwriting criteria, agreements, and product guidelines. The credit limit establishes a maximum spending limit for a given period, and authorizations exceeding the credit limit will be declined. Once you have created a credit limit, you can update it as you factor in new information, such as changes in your customers' financial situations. As part of this feature, Highnote tracks the total credit extended to your account holders' financial accounts and ensures the extended credit does not exceed your card product’s limits. ## Set credit limit Setting or updating a credit limit is an asynchronous process with the Highnote team to ensure your ledger balances and validations are accurate. To set a financial account credit limit, provide the and the credit limit amount and currency to assign to the financial account. Your product funding financial account must have funds equal to or exceeding any credit limit you extend to your account holders. Use the following mutation to set a credit limit: ## Check credit limit status Once you have requested to set or update the credit limit on a financial account, you can query for and display the following statuses: | Status | Description | | :----------- | :--------------------------------------------------------------------------------------------- | | | The platform is validating and executing the credit limit update. | | | The platform has started processing the credit limit update. | | | The platform has completed the credit limit update. | | | The platform could not complete the limit update. See for more information. | has the following values: | Status Reason Code | Description | | :---------------------------------------------- | :---------------------------------------------------------------------------------------------- | | | The associated product funding account or financial account is closed. | | | The financial account was not found. | | | The associated product funding account did not have enough funds to cover the requested amount. | | | The requested amount is more than the maximum product credit limit. | Use the following query to check the status of a credit limit update: ## Update a credit limit To increase or decrease a financial account credit limit, you must create a credit limit change request case. Credit limit updates fall into two categories: - **Proactive:** Requested by you - **Reactive:** Requested by your account holders Each credit limit update -- increase or decrease, proactive or reactive -- may have a credit policy associated with your card product. Creating a credit limit change request case triggers the workflows necessary to make an underwriting decision. The underwriting decision for a credit limit update may be executed by you or Highnote, depending on your card program's credit policies. ## Create credit limit change request To request a credit limit change for a financial account, you must provide: - Financial account ID - Requested change type, increase or decrease If you are running your own underwriting for credit limit updates, subscribe to the following notification event to receive updates when a credit limit change request is made: The following mutation can be used to create the credit limit change request: ## View credit limit change request To view the status of a credit limit change request, use the following query and the : ## Approve or deny the request If you are running your own underwriting, you must provide the variables required to decision a credit limit change request based on your credit policy. In the Test environment, use the following variables to approve or deny an increase or decrease credit limit change request. Note the following about credit limit change requests and adverse action reasons: - Credit limit decreases always require an Adverse Action reason - Credit limit increases always require an Adverse Action reason when the requestor is the customer and the request is denied | Credit limit change request type | Required variables | | :------------------------------- | :-------------------------------------------------- | | Credit limit increase | Annual income | | | Current debt obligations | | | Adverse Action reason (if denied) | | Credit limit decrease | External bank account balance | | | Adverse Action reasons (if the request is approved) | ### Approve credit limit increase Use the following mutation to approve a credit limit increase request: ### Deny credit limit increase Use the following mutation to deny a credit limit increase request: ### Approve credit limit decrease Use the following mutation to approve a credit limit decrease: ### Deny credit limit decrease Use the following mutation to deny a credit limit decrease: ## View credit limit request history Use the following query to view the history of credit limit change requests on a financial account: ### GraphQL: InitiateFinancialAccountCreditLimitUpdateFromProductFunding Query: mutation InitiateFinancialAccountCreditLimitUpdateFromProductFunding( $input: InitiateFinancialAccountCreditLimitUpdateFromProductFundingInput! ) { initiateFinancialAccountCreditLimitUpdateFromProductFunding(input: $input) { __typename ... on Node { id } ... on FinancialAccountCreditLimitUpdateFromProductFunding { id status statusReason createdAt updatedAt memo amount { value currencyCode } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "memo": "Set Limit", "amount": { "value": 100, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateFinancialAccountCreditLimitUpdateFromProductFunding": { "__typename": "FinancialAccountCreditLimitUpdateFromProductFunding", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2022-06-21T18:01:28.992Z", "updatedAt": "2022-06-21T18:01:28.993Z", "memo": null, "amount": { "value": 100, "currencyCode": "USD" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindFinancialAccountCreditLimitUpdate Query: query FindFinancialAccountCreditLimitUpdate($id: ID!) { node(id: $id) { ... on FinancialAccountCreditLimitUpdateFromProductFunding { id status statusReason amount { value } memo ledgers { name debitBalance { value } creditBalance { value } financialAccount { name } } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FinancialAccountCreditLimitUpdateFromProductFunding", "id": "", "status": "COMPLETED", "statusReason": null, "amount": { "value": 100 }, "memo": null, "ledgers": [ { "name": "CREDIT_OUTSTANDING", "debitBalance": { "value": 999800 }, "creditBalance": { "value": 0 }, "financialAccount": { "name": "Fleet - Product Funding Account" } }, { "name": "AVAILABLE_CREDIT", "debitBalance": { "value": 0 }, "creditBalance": { "value": 999800 }, "financialAccount": { "name": "Fleet - Product Funding Account" } }, { "name": "ALLOCATED_CREDIT_LIMIT", "debitBalance": { "value": 100 }, "creditBalance": { "value": 0 }, "financialAccount": { "name": "Fleet - Product Funding Account" } }, { "name": "CREDIT_OUTSTANDING", "debitBalance": { "value": 100 }, "creditBalance": { "value": 0 }, "financialAccount": { "name": "Fleet - Card Holder Account" } }, { "name": "AVAILABLE_CREDIT", "debitBalance": { "value": 0 }, "creditBalance": { "value": 100 }, "financialAccount": { "name": "Fleet - Card Holder Account" } }, { "name": "ACCOUNT_HOLDER_CREDIT_LIMIT", "debitBalance": { "value": 0 }, "creditBalance": { "value": 100 }, "financialAccount": { "name": "Fleet - Card Holder Account" } } ], "createdAt": "2022-06-21T00:46:49.747Z", "updatedAt": "2022-06-21T00:47:02.431Z" } }, "extensions": { "requestId": "" } } ### GraphQL: CreateCreditLimitChangeRequest Query: mutation createCreditLimitChangeRequest( $input: CreateCreditLimitChangeRequestInput! ) { createCreditLimitChangeRequest(input: $input) { __typename ... on AccountReview { ... on CreditLimitChangeRequest { id financialAccount { id externalId name } requestedChange { requestedChangeType requestedCreditLimit { value currencyCode } requestor } status createdAt updatedAt } } ... on UserError { __typename errors { description code } } } } Variables: { "input": { "financialAccountId": "", "requestedChange": { "requestedChangeType": "INCREASE", "requestedCreditLimit": { "value": 2000000, "currencyCode": "USD" }, "requestor": "SUBSCRIBER" } } } Expected Result: { "data": { "createCreditLimitChangeRequest": { "__typename": "CreditLimitChangeRequest", "id": "", "financialAccount": "", "status": "INITIATED", "requestedChange": { "requestedChangeType": "INCREASE", "requestedCreditLimit": { "value": "2500000", "currencyCode": "USD" }, "requestor": "SUBSCRIBER" }, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z" } } } ### GraphQL: nodeAccountReviewCase Query: query nodeAccountReviewCase($id: ID!) { node(id: $id) { __typename ... on AccountReview { ... on CreditLimitChangeRequest { id financialAccount { id externalId name } status statusHistory { previousStatus newStatus createdAt } requestedChange { requestedChangeType requestedCreditLimit { value currencyCode } requestor } existingCreditLimit { value currencyCode } updatedCreditLimit { value currencyCode } customerDetails { currentDebtObligations { value currencyCode } annualIncome { value currencyCode } externalFinancialAccountBalance { value currencyCode } adverseActionReasons { code } } createdAt updatedAt closedAt } } } } Variables: { "id": "" } Expected Result: { "data": { "lookupCreditLimitChangeRequest": { "__typename": "CreditLimitChangeRequest", "id": "", "financialAccount": "", "status": "INITIATED", "statusHistory": [ { "previousStatus": null, "newStatus": "INITIATED", "createdAt": "2024-01-01T00:00:00.000Z" } ], "requestedChange": { "requestedChangeType": "INCREASE", "requestedCreditLimit": { "value": "2500000", "currencyCode": "USD" }, "requestor": "SUBSCRIBER" }, "customerDetails": { "currentDebtObligations": { "value": "1000000" }, "annualIncome": { "value": "10000000" }, "adverseActionReasons": null }, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z" } } } ### GraphQL: ApproveCreditLimitIncrease Query: mutation approveCreditLimitIncrease($input: ApproveCreditLimitIncreaseInput!) { approveCreditLimitIncrease(input: $input) { __typename ... on AccountReview { ... on CreditLimitChangeRequest { id financialAccount { id externalId name } status statusHistory { previousStatus newStatus createdAt } requestedChange { requestedChangeType requestedCreditLimit { value currencyCode } requestor } existingCreditLimit { value currencyCode } customerDetails { currentDebtObligations { value currencyCode } annualIncome { value currencyCode } externalFinancialAccountBalance { value currencyCode } } createdAt updatedAt closedAt } } ... on UserError { errors { code description errorPath } } } } Variables: { "input": { "creditLimitChangeRequestId": "", "updatedCreditLimit": { "value": 2000000, "currencyCode": "USD" }, "customerDetails": { "currentDebtObligations": { "value": 1000000, "currencyCode": "USD" }, "annualIncome": { "value": 10000000, "currencyCode": "USD" } } } } Expected Result: { "data": { "approveCreditLimitIncrease": { "__typename": "CreditLimitChangeRequest", "id": "", "financialAccount": "", "status": "PENDING", "statusHistory": [ { "previousStatus": "INITIATED", "newStatus": "PENDING", "createdAt": "2024-01-01T00:00:00.000Z" } ], "requestedChange": { "requestedChangeType": "INCREASE", "requestedCreditLimit": { "value": "2500000", "currencyCode": "USD" }, "requestor": "SUBSCRIBER" }, "existingCreditLimit": { "value": "2000000", "currencyCode": "USD" }, "updatedCreditLimit": null, "customerDetails": { "currentDebtObligations": { "value": "1000000", "currencyCode": "USD" }, "annualIncome": { "value": "10000000", "currencyCode": "USD" }, "externalFinancialAccountBalance": { "value": "1000000", "currencyCode": "USD" }, "adverseActionReasons": null }, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "closedAt": "2024-01-01T00:00:00.000Z" } } } ### GraphQL: DenyCreditLimitIncrease Query: mutation denyCreditLimitIncrease($input: DenyCreditLimitIncreaseInput!) { denyCreditLimitIncrease(input: $input) { __typename ... on AccountReview { ... on CreditLimitChangeRequest { id financialAccount { id externalId name } status statusHistory { previousStatus newStatus createdAt } requestedChange { requestedChangeType requestedCreditLimit { value currencyCode } requestor } existingCreditLimit { value currencyCode } customerDetails { currentDebtObligations { value currencyCode } annualIncome { value currencyCode } externalFinancialAccountBalance { value currencyCode } } } createdAt updatedAt closedAt } ... on UserError { __typename errors { code description } } } } Variables: { "input": { "creditLimitChangeRequestId": "", "adverseActionReasons": [ "BANKRUPTCY" ], "customerDetails": { "currentDebtObligations": { "value": 1000000, "currencyCode": "USD" }, "annualIncome": { "value": 10000000, "currencyCode": "USD" } } } } Expected Result: { "data": { "denyCreditLimitIncrease": { "__typename": "CreditLimitChangeRequest", "id": "", "financialAccount": { "id": "", "externalId": "", "name": "" }, "status": "DENIED", "statusHistory": [ { "previousStatus": "INITIATED", "newStatus": "DENIED", "createdAt": "2024-01-01T00:00:00.000Z" } ], "requestedChange": { "requestedChangeType": "INCREASE", "requestedCreditLimit": { "value": "2500000", "currencyCode": "USD" }, "requestor": "CUSTOMER" }, "existingCreditLimit": { "value": "2000000", "currencyCode": "USD" }, "updatedCreditLimit": { "value": "2500000", "currencyCode": "USD" }, "customerDetails": { "currentDebtObligations": { "value": "1000000" }, "annualIncome": { "value": "10000000" }, "externalFinancialAccountBalance": { "value": "1000000" }, "adverseActionReasons": [ "BANKRUPTCY" ] }, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "closedAt": "2024-01-01T00:00:00.000Z" } } } ### GraphQL: ApproveCreditLimitDecrease Query: mutation approveCreditLimitDecrease($input: ApproveCreditLimitDecreaseInput!) { approveCreditLimitDecrease(input: $input) { __typename ... on AccountReview { ... on CreditLimitChangeRequest { id financialAccount { id externalId name } status statusHistory { previousStatus newStatus createdAt } requestedChange { requestedChangeType requestedCreditLimit { value currencyCode } requestor } existingCreditLimit { value currencyCode } customerDetails { currentDebtObligations { value currencyCode } annualIncome { value currencyCode } externalFinancialAccountBalance { value currencyCode } adverseActionReasons { code } } createdAt updatedAt closedAt } } ... on UserError { __typename errors { code description } } } } Variables: { "input": { "creditLimitChangeRequestId": "", "updatedCreditLimit": { "value": 1500000, "currencyCode": "USD" }, "adverseActionReasons": [ "BANKRUPTCY" ], "customerDetails": { "externalFinancialAccountBalance": { "value": 1000000, "currencyCode": "USD" } } } } Expected Result: { "data": { "approveCreditLimitDecrease": { "__typename": "CreditLimitChangeRequest", "id": "", "financialAccount": "", "status": "PENDING", "statusHistory": [ { "previousStatus": "INITIATED", "newStatus": "PENDING", "createdAt": "2024-01-01T00:00:00.000Z" } ], "requestedChange": { "requestedChangeType": "DECREASE", "requestedCreditLimit": { "value": "1500000", "currencyCode": "USD" }, "requestor": "SUBSCRIBER" }, "existingCreditLimit": { "value": "2000000", "currencyCode": "USD" }, "updatedCreditLimit": null, "customerDetails": { "externalFinancialAccountBalance": { "value": "1000000", "currencyCode": "USD" }, "adverseActionReasons": [ "BANKRUPTCY" ] }, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "closedAt": "2024-01-01T00:00:00.000Z" } } } ### GraphQL: DenyCreditLimitDecrease Query: mutation denyCreditLimitDecrease($input: DenyCreditLimitDecreaseInput!) { denyCreditLimitDecrease(input: $input) { __typename ... on AccountReview { ... on CreditLimitChangeRequest { id financialAccount { id externalId name } status statusHistory { previousStatus newStatus createdAt } requestedChange { requestedChangeType requestedCreditLimit { value currencyCode } requestor } existingCreditLimit { value currencyCode } customerDetails { currentDebtObligations { value currencyCode } annualIncome { value currencyCode } externalFinancialAccountBalance { value currencyCode } } createdAt updatedAt closedAt } } ... on UserError { __typename errors { code description } } } } Variables: { "input": { "creditLimitChangeRequestId": "", "customerDetails": { "externalFinancialAccountBalance": { "value": 1000000, "currencyCode": "USD" } } } } Expected Result: { "data": { "denyCreditLimitDecrease": { "__typename": "CreditLimitChangeRequest", "id": "", "financialAccount": "", "status": "DENIED", "statusHistory": [ { "previousStatus": "INITIATED", "newStatus": "DENIED", "createdAt": "2024-01-01T00:00:00.000Z" } ], "requestedChange": { "requestedChangeType": "DECREASE", "requestedCreditLimit": { "value": "2000000", "currencyCode": "USD" }, "requestor": "SUBSCRIBER" }, "existingCreditLimit": { "value": "2000000", "currencyCode": "USD" }, "updatedCreditLimit": { "value": "2000000", "currencyCode": "USD" }, "customerDetails": { "externalFinancialAccountBalance": { "value": "1000000", "currencyCode": "USD" }, "adverseActionReasons": [ "BANKRUPTCY" ] }, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "closedAt": "2024-01-01T00:00:00.000Z" } } } ### GraphQL: lookupCreditLimitRequestHistory Query: query lookupCreditLimitRequestHistory($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { id accountReviewHistory { __typename ... on AccountReviewConnection { pageInfo { hasNextPage hasPreviousPage endCursor startCursor } edges { cursor node { __typename ... on CreditLimitChangeRequest { id financialAccount { id externalId name } status statusHistory { previousStatus newStatus createdAt } requestedChange { requestedChangeType requestedCreditLimit { value currencyCode } requestor } existingCreditLimit { value currencyCode } updatedCreditLimit { value currencyCode } customerDetails { currentDebtObligations { value currencyCode } annualIncome { value currencyCode } externalFinancialAccountBalance { value currencyCode } adverseActionReasons { code } } createdAt updatedAt closedAt } } } } ... on UserError { __typename errors { errorPath code description } } ... on AccessDeniedError { __typename message } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "accountReviewHistory": [ { "__typename": "CreditLimitChangeRequest", "id": "", "status": "APPROVED", "requestedChange": { "requestedChangeType": "INCREASE", "requestedCreditLimit": { "value": "2500000", "currencyCode": "USD" }, "requestor": "SUBSCRIBER" }, "existingCreditLimit": { "value": "2000000", "currencyCode": "USD" }, "updatedCreditLimit": { "value": "2500000", "currencyCode": "USD" }, "customerDetails": { "currentDebtObligations": { "value": "1000000", "currencyCode": "USD" }, "annualIncome": { "value": "10000000", "currencyCode": "USD" }, "adverseActionReason": null }, "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "closedAt": "2024-01-01T00:00:00.000Z" } ] } } } --- URL: https://docs.highnote.com/docs/issuing/credit/simulations/sim-account-delinquency Title: Simulate Account Delinquency Section: Issuing Description: Simulate account delinquency scenarios in the Test environment. Age accounts backward, trigger delinquency attributes, and test charge-off at 180+ days. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. The delinquency simulator lets you view a financial account's delinquency status and receivables by simulating past purchase and payment scenarios. In the Test environment, this helps with testing and configuring notification events. The delinquency simulator allows you to test the following: - View the financial account's delinquency status and balances by billing cycle for agent servicing, portfolio analysis, and collections strategies. - Add the and financial account attributes when the financial account becomes delinquent and receive the associated notification events. - Remove the and financial account attributes when the financial account becomes current and receive the associated notification events ## Prerequisites - A Highnote account - API keys or the API Explorer - A credit card product for your Test environment - A new financial account for a credit card product - No closed billing cycles on the financial account ## Simulate delinquency Use the following steps to simulate delinquency in your Test environment: 1. Issue a new financial account on an existing approved application and set the financial account's credit limit. 2. Issue a payment card to the financial account. 3. To create receivables, simulate and clear the desired authorizations, resulting in a simulated billing statement. The simulated billing statement should not include any pending authorizations. 4. Use the account aging simulation to generate a statement and age the financial account. 5. _Optional_ - To clear the financial account's delinquency, make a payment for the past due . Repeat steps 3 and 4 to generate additional past billing statements. If you simulate multiple billing statements, you must generate simulated billing statements from oldest to newest. For example, you must start by generating the oldest of the three to generate three billing statements. ## Account aging simulation To simulate multiple billing statements, you must generate simulated billing statements from oldest to newest. You cannot simulate the same past billing cycle more than once. You can use the account aging simulation once you have simulated receivables and payments on a financial account. Refer to the following steps to use the account aging simulation: 1. To ensure your simulation results in a delinquent financial account, the ledger must be greater than $0. 2. Provide the number of past billing cycles you want the simulated billing statement to generate. The simulator considers the unique calendar days of the financial account's due date, billing period start date, and billing period end date. For a list of simulation values, see Simulation values. Note the following guidelines for using the account aging simulation: - The financial account being simulated must be in its first billing cycle and cannot have a closed billing statement. - We recommend issuing a new financial account each time you use the simulation. Use the following mutation to simulate account aging: ### Simulation values Use the following simulation actions for the account aging simulation: | Attribute | Action | | :--------------------------------------------- | :-------------------------------------------------------------------------------------------------------- | | Add | Shift the current billing cycle with a positive back two or more cycles. | | Add | Shift the current billing cycle with a positive back five or more cycles. | | Remove and | Make the account current by posting a payment greater than or equal to the . | ## Simulate repayment Repayments may take up to five minutes to update a financial account's delinquency status. You can simulate a repayment if your simulation results in a delinquent financial account. See Schedule Repayments for more information on simulating repayment. ## Simulate charge off In the Live environment, the Highnote team will close an account with a status due to a charge-off event. You can use the delinquency simulator in the Test environment to simulate a charge-off. Use the steps outlined in the Simulate Delinquency guide. In Step 4, shift an unpaid statement balance due back at least seven billing cycles to make the financial account's >= 180 days. With the set to 180 days the financial account attribute of will be added and the financial account status will be set to . ### GraphQL: SimulateBackwardShiftAndAgeCurrentFinancialAccountStatementPeriod Query: mutation SimulateBackwardShiftAndAgeCurrentFinancialAccountStatement( $input: SimulateBackwardShiftAndAgeCurrentFinancialAccountStatementPeriodInput! ) { simulateBackwardShiftAndAgeCurrentFinancialAccountStatementPeriod( input: $input ) { __typename ... on FinancialAccount { id createdAt delinquency { __typename totalAmount { value currencyCode } numberOfCycles totalDaysDelinquent delinquencyStartedOn currentDelinquentCycles { daysDelinquent statement { periodStart periodEnd openedAt closedAt primaryLedger { debitBalance { value } creditBalance { value } normalBalance } } amount { value currencyCode } state } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "financialAccountId": "", "numberOfCyclesToShiftCurrentStatementBackward": 3 } } Expected Result: { "data": { "simulateBackwardShiftAndAgeCurrentFinancialAccountStatementPeriod": { "__typename": "FinancialAccount", "id": "", "createdAt": null, "accountStatus": null, "accountAttributes": null, "delinquency": { "__typename": "CreditPayInFullFinancialAccountDelinquency", "totalAmount": { "value": 200, "currencyCode": "USD" }, "numberOfCycles": 2, "totalDaysDelinquent": 57, "delinquencyStartedOn": "2022-11-08T05:00:00.000Z", "currentDelinquentCycles": [ { "daysDelinquent": 57, "statement": { "periodStart": "2022-10-04T05:00:00.000Z", "periodEnd": "2022-11-04T05:00:00.000Z", "openedAt": "2023-01-04T18:46:25.912Z", "closedAt": "2023-01-04T18:56:01.157Z", "primaryLedger": { "debitBalance": { "value": 0 }, "creditBalance": { "value": 200 }, "normalBalance": "CREDIT" } }, "amount": null, "state": "DELINQUENT" }, { "daysDelinquent": 27, "statement": { "periodStart": "2022-11-04T05:00:00.000Z", "periodEnd": "2022-12-04T05:00:00.000Z", "openedAt": "2023-01-04T18:56:01.157Z", "closedAt": "2023-01-04T18:59:07.703Z", "primaryLedger": { "debitBalance": { "value": 0 }, "creditBalance": { "value": 200 }, "normalBalance": "CREDIT" } }, "amount": null, "state": "DELINQUENT" } ] } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/credit/simulations/sim-billing-statements Title: Simulate Billing Statements Section: Issuing Description: Simulate billing statement cycles in the Test environment by shifting end periods and rolling over to the next billing cycle. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. Billing statements reflect money movement, balances, and fees on an account holder's financial account. This guide provides steps for simulating the following actions for billing statements: - Shifting the billing statement end period - Rolling the billing statement over to the next billing cycle ## Prerequisites - A Highnote account - An API key or API Explorer - A credit or charge card product - A financial account with a generated billing statement - _Optional_ - Simulated transactions ## Simulate shifting the statement end period This simulation feature is only compatible with credit card products at this time. In the Test environment, you can end a financial account’s billing period early to simulate a billing statement. When performing this simulation, refer to the following guidelines: - Set the new period at least 60 seconds in the future. - If no is provided, the system defaults the statement’s to 60 seconds from now. To simulate changing a statement's end period for a consumer revolving credit card, use the following mutation: ## Simulate rolling over to the next billing cycle This simulation feature only works with credit card products at this time. In the Test environment, you can transition a financial account’s billing period to the next cycle, simulating the end of one billing cycle and the start of another. To retrieve the simulated current amount due, refer to the appropriate statement snapshot type: | Card product type | Statement snapshot | | :------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Commercial charge | [](/docs/api-reference/object#CreditPayInFullCardFinancialAccountStatementSnapshot) | | Consumer charge | [](/docs/api-reference/object#ConsumerChargeCardFinancialAccountStatementSnapshot) | | Consumer revolving credit | [](/docs/api-reference/object#ConsumerRevolvingCardFinancialAccountStatementSnapshot) | Use the following mutation to simulate rolling over the current statement period for a consumer revolving credit card: ## Automate your integration To automate your integration, subscribe to the financial account statement notification event. The details provided in the payloads from this event can be used for the following use cases: - Automate your application or website's transaction processing workflow - Create account holder notifications and alerts ### GraphQL: SimulateShiftCurrentStatementPeriod Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt createdAt updatedAt paymentDueOn pastDueAmount { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } } payOffWarning { paymentCycles { payOffType paymentDetails { estimatedPayOffPeriod estimatedTotal { value currencyCode } periodPayment { value currencyCode } } } } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value } startingPrimaryDebitBalance { value } endingPrimaryCreditBalance { value } endingPrimaryDebitBalance { value } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } } mutation SimulateShiftCurrentStatementPeriod( $input: SimulateShiftCurrentFinancialAccountStatementPeriodInput! ) { simulateShiftCurrentFinancialAccountStatementPeriod(input: $input) { __typename ... on FinancialAccount { id statementSnapshot { ... on ConsumerRevolvingCardFinancialAccountStatementSnapshot { __typename asOf currentOpenStatement { ...statement } latestClosedStatement { ...statement } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "financialAccountId": "", "periodBoundary": "2023-04-05T00:43:26.96" } } Expected Result: { "data": { "simulateShiftCurrentFinancialAccountStatementPeriod": { "__typename": "FinancialAccount", "id": "", "statementSnapshot": { "__typename": "ConsumerRevolvingCardFinancialAccountStatementSnapshot", "asOf": "2023-12-05T00:17:45.591Z", "currentOpenStatement": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-12-04T05:00:00.000Z", "periodEnd": "2023-12-05T00:43:26.960Z", "openedAt": "2023-12-05T00:17:45.529Z", "closedAt": null, "paymentDueOn": "2023-12-15T00:43:26.960Z", "pastDueAmount": null, "periodMinimumPaymentDue": null, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 3000, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": null, "periodPurchaseCreditPlan": [], "payOffWarning": { "paymentCycles": [] }, "secondaryLedger": { "id": "", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 47000, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingSecondaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" } } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 37, "limit": 60060, "remaining": 60023 } } } ### GraphQL: SimulateRolloverCurrentStatementPeriod Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffPeriod } } } secondaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingSecondaryCreditBalance { value currencyCode } startingSecondaryDebitBalance { value currencyCode } endingSecondaryCreditBalance { value currencyCode } endingSecondaryDebitBalance { value currencyCode } } mutation SimulateRolloverCurrentStatementPeriod( $input: SimulateRolloverCurrentFinancialAccountStatementPeriodInput! ) { simulateRolloverCurrentFinancialAccountStatementPeriod(input: $input) { __typename ... on FinancialAccount { id statementSnapshot { ... on ConsumerRevolvingCardFinancialAccountStatementSnapshot { __typename asOf currentAmountDue { value } latestClosedStatement { ...statement } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "financialAccountId": "" } } Expected Result: { "data": { "simulateRolloverCurrentFinancialAccountStatementPeriod": { "__typename": "FinancialAccount", "id": "", "statementSnapshot": { "__typename": "ConsumerRevolvingCardFinancialAccountStatementSnapshot", "asOf": "2023-12-05T00:48:34.468Z", "currentAmountDue": { "value": 0 }, "latestClosedStatement": { "id": "", "periodStart": "2023-09-30T05:00:00.000Z", "periodEnd": "2023-10-28T05:00:00.000Z", "openedAt": "2023-11-30T07:51:25.643Z", "closedAt": "2023-11-30T07:54:45.333Z", "paymentDueOn": "2023-11-05T05:00:00.000Z", "pastDueAmount": { "value": 5878, "currencyCode": "USD" }, "periodMinimumPaymentDue": { "value": 11862, "currencyCode": "USD" }, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835 }, "debitBalance": { "value": 0 } }, "startingPrimaryCreditBalance": { "value": 2473, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": { "value": 2484, "currencyCode": "USD" }, "periodPurchaseCreditPlan": [ { "balanceType": "PURCHASE", "balanceSubjectToInterestAmount": { "value": 129202, "currencyCode": "USD" }, "interestChargedAmount": { "value": 2484, "currencyCode": "USD" }, "apr": 23.99 } ], "payOffWarning": { "paymentCycles": [ { "payOffType": "MINIMUM_PAY_OFF", "paymentDetails": { "periodPayment": { "value": 11862, "currencyCode": "USD" }, "estimatedTotal": { "value": 149572, "currencyCode": "USD" }, "estimatedPayOffPeriod": "13 years, 1 month" } }, { "payOffType": "THREE_YEAR_PAY_OFF", "paymentDetails": { "periodPayment": { "value": 11862, "currencyCode": "USD" }, "estimatedTotal": { "value": 153470, "currencyCode": "USD" }, "estimatedPayOffPeriod": "2 years, 9 months" } } ] }, "secondaryLedger": { "id": "", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 85165 }, "debitBalance": { "value": 0 } }, "startingSecondaryCreditBalance": { "value": 200000 }, "startingSecondaryDebitBalance": { "value": 0 }, "endingSecondaryCreditBalance": { "value": 87649 }, "endingSecondaryDebitBalance": { "value": 0 } } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 38, "limit": 60060, "remaining": 60022 } } } --- URL: https://docs.highnote.com/docs/issuing/credit/simulations/sim-repayments Title: Simulate Repayments Section: Issuing Description: Simulate ACH repayment workflows in the Test environment. Create test payments, update transfer statuses, and verify ledger impact. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. Credit and charge card products use ACH transfers to drive repayments on the Highnote platform. For more information on repayments, see Schedule Repayments. Simulating repayments in the Test environment requires the following steps: 1. Creating a payment. 2. Updating the status of the transfer. 3. Processing a transfer. This guide provides steps for simulating repayments in the Test environment. ## Prerequisites - A Highnote account - An API key or API Explorer - A financial account with simulated transactions and an outstanding balance ## Create a one-time payment Scheduled payments are initiated by the account holder. You can not schedule a payment for an account holder in the Live environment. One-time payments can be scheduled based on a balance amount or a custom amount. A scheduled payment will not be initiated if the financial account has an less than or equal to $0. In the Test environment, a transfer ID will be generated within 5 minutes of scheduling a payment for today. Use the query to find a transfer event ID and simulate changing the status of the transfer: ## Update the transfer status In the Test environment, you can change the status of a fund in transfer from to using the transfer ID. The simulation will allow you to view the impacts to ledgers from initiating a transfer: ## Process a transfer In the Test environment, you can change the status of a fund in transfer from to using the transfer ID. The simulation will allow you to view the impacts to ledgers from processing a transfer: ## Automate your integration To automate your integration, subscribe to ACH notification events. The details provided in the payloads from this event can be used for the following use cases: - Automate your application or website's repayment workflows - Create account holder notifications or alerts - Create status views in your application or website ### GraphQL: CreateOneTimeAchTransfer Query: mutation CreateOneTimeAchTransfer($input: CreateOneTimeACHTransferInput!) { createOneTimeACHTransfer(input: $input) { ... on OneTimeACHTransfer { id fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id } } descriptor { companyEntryDescription individualName individualIdentificationNumber } transferAmount { ... on ManualTransferAmount { amount { value currencyCode } } } status scheduledTransferDate createdAt updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "fromFinancialAccountId": "", "toFinancialAccountId": "", "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferAmountStrategy": { "transferAmount": { "value": "9900", "currencyCode": "USD" } }, "transferDate": "2023-03-11", "transferAgreementConsent": { "consentTimestamp": "2022-03-10T17:10:55.662Z", "authorizedPersonId": "", "template": { "consentTemplateId": "your-template-id", "consentTemplateVersion": "0" } } } } Expected Result: { "data": { "id": "", "toFinancialAccount": { "id": "" }, "fromFinancialAccount": { "id": "" }, "descriptor": { "companyEntryDescription": "CompanyDes", "individualName": "IndivName", "individualIdentificationNumber": "112345" }, "transferAmount": { "amount": { "value": "9900", "currencyCode": "USD" } }, "status": "SCHEDULED", "scheduledTransferDate": "2022-03-09T00:00:00.000Z", "createdAt": "2022-02-09T17:10:56.662Z", "updatedAt": "2022-02-10T17:10:56.662Z" } } ### GraphQL: SimulateProcessingIntegratorInitiatedStatusChange Query: mutation SimulateProcessingIntegratorInitiatedStatusChange( $input: SimulateProcessingIntegratorInitiatedStatusChangeInput! ) { simulateProcessingIntegratorInitiatedStatusChange(input: $input) { __typename ... on Node { id } ... on IntegratorInitiatedFundsDepositACHTransfer { id amount { currencyCode value } createdAt updatedAt ledgers { id name normalBalance asOf debitBalance { value currencyCode } creditBalance { value currencyCode } } status { __typename ... on NonFailureIntegratorInitiatedACHStatus { status } ... on FailureIntegratorInitiatedACHStatus { status statusReasonCode } } fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id name } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id name } } companyName descriptor { companyEntryDescription individualIdentificationNumber individualName } companyIdentifier settlementDate } ... on UserError { errors { errorPath code } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "simulateProcessedIntegratorInitiatedStatusChange": { "__typename": "SecureDepositACHTransfer", "id": "", "amount": { "currencyCode": "USD", "value": 10000 }, "createdAt": "2022-04-21T19:15:43.441Z", "updatedAt": "2022-04-21T19:18:37.369Z", "ledgers": [ { "id": "", "name": "SECURED_DEPOSIT_PAYABLE", "normalBalance": "CREDIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 860300, "currencyCode": "USD" } }, { "id": "", "name": "ACH_PENDING_SETTLEMENT_OUT", "normalBalance": "CREDIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 860300, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "SECURED_DEPOSIT_RECEIVABLE", "normalBalance": "DEBIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 860300, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "ACH_PENDING_SETTLEMENT", "normalBalance": "CREDIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 860300, "currencyCode": "USD" } } ], "status": { "__typename": "NonFailureIntegratorInitiatedACHStatus", "status": "PROCESSING" }, "fromFinancialAccount": { "id": "", "name": "source-account" }, "toFinancialAccount": { "id": "", "name": "first-account" }, "companyName": "HIGHNOTEPLATFORM", "descriptor": { "companyEntryDescription": "entryDesc", "individualIdentificationNumber": "", "individualName": "indName" }, "companyIdentifier": "1852922649", "settlementDate": "2022-04-21T19:15:43.439Z" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateProcessedIntegratorInitiatedStatusChange Query: mutation SimulateProcessedIntegratorInitiatedStatusChange( $input: SimulateProcessedIntegratorInitiatedStatusChangeInput! ) { simulateProcessedIntegratorInitiatedStatusChange(input: $input) { __typename ... on Node { id } ... on SecureDepositACHTransfer { id amount { currencyCode value } createdAt updatedAt ledgers { id name normalBalance asOf debitBalance { value currencyCode } creditBalance { value currencyCode } } status { __typename ... on NonFailureIntegratorInitiatedACHStatus { status } ... on FailureIntegratorInitiatedACHStatus { status statusReasonCode } } fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id name } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id name } } companyName descriptor { companyEntryDescription individualIdentificationNumber individualName } companyIdentifier settlementDate } ... on SecureCardBalanceRepaymentACHTransfer { id amount { currencyCode value } createdAt updatedAt ledgers { id name normalBalance asOf debitBalance { value currencyCode } creditBalance { value currencyCode } } status { __typename ... on NonFailureIntegratorInitiatedACHStatus { status } ... on FailureIntegratorInitiatedACHStatus { status statusReasonCode } } fromFinancialAccount { ... on Node { id } ... on FinancialAccount { id name } } toFinancialAccount { ... on Node { id } ... on FinancialAccount { id name } } companyName descriptor { companyEntryDescription individualIdentificationNumber individualName } companyIdentifier settlementDate } ... on UserError { errors { errorPath code } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "simulateProcessedIntegratorInitiatedStatusChange": { "__typename": "SecureDepositACHTransfer", "id": "", "amount": { "currencyCode": "USD", "value": 10000 }, "createdAt": "2022-04-21T19:15:43.441Z", "updatedAt": "2022-04-21T19:18:37.369Z", "ledgers": [ { "id": "", "name": "SECURED_DEPOSIT_PAYABLE", "normalBalance": "CREDIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 860300, "currencyCode": "USD" } }, { "id": "", "name": "ACH_PENDING_SETTLEMENT_OUT", "normalBalance": "CREDIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 860300, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "SECURED_DEPOSIT_RECEIVABLE", "normalBalance": "DEBIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 860300, "currencyCode": "USD" }, "creditBalance": { "value": 0, "currencyCode": "USD" } }, { "id": "", "name": "ACH_PENDING_SETTLEMENT", "normalBalance": "CREDIT", "asOf": "2022-04-21T19:15:49.553Z", "debitBalance": { "value": 0, "currencyCode": "USD" }, "creditBalance": { "value": 860300, "currencyCode": "USD" } } ], "status": { "__typename": "NonFailureIntegratorInitiatedACHStatus", "status": "PROCESSED" }, "fromFinancialAccount": { "id": "", "name": "source-account" }, "toFinancialAccount": { "id": "", "name": "first-account" }, "companyName": "HIGHNOTEPLATFORM", "descriptor": { "companyEntryDescription": "entryDesc", "individualIdentificationNumber": "", "individualName": "indName" }, "companyIdentifier": "1852922649", "settlementDate": "2022-04-21T19:15:43.439Z" } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/credit/simulations/sim-underwriting-decisions Title: Simulate Underwriting Decisions Section: Issuing Description: Simulate underwriting decisions in the Test environment including credit line assignment, application denial, credit report freezes, fraud alerts, and MLA eligibility. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. Highnote provides simulations for credit application underwriting. This is useful for testing your integration and credit policy, configuring notifications, and simulating the cardholder experience. This guide provides an overview for simulating underwriting decisions using the Test environment. ## Assign a credit line Your credit policy may allow for dynamic allocation of credit limits on approved applications. You can test various credit line assignments on approved applications using the Test environment. Simulating credit line assignment requires two steps: 1. Onboard an account holder and provide a simulation value for the or fields. To onboard an account holder, see Onboard an account holder. 1. Open an application for the account holder. When the application is approved, the credit line will reflect the simulation value used during onboarding. To open an application, see Open an application. ### Simulation values The following table provides simulation values for simulating credit line assignment: | Account holder type | Field | Simulation value | Credit line assignment | | :------------------------- | :------------------ | :--------------- | :--------------------- | | US business account holder | | $1,000,000 | $1,000 | | | | $10,000,000 | $10,000 | | | | $100,000,000 | $100,000 | | US person account holder | | $1,000,000 | $1,000 | | | | $10,000,000 | $10,000 | | | | $100,000,000 | $100,000 | ### Lookup application After simulating credit line assignment, you can use the following query to lookup the application to verify the credit line: ## Deny application While an application may have multiple reasons for being denied, Highnote only returns the primary adverse action reason. This reason _must_ be provided to the account holder. Adverse action codes are specific to underwritten credit applications. For the general application denial reasons that apply to all card product applications — including inactivity denials — see Application Denials. In the **Test environment**, opening applications for credit card products lets you test adverse action reasons for responses. Testing adverse action reasons consists of the following steps: 1. Create a business or person account holder in your Test environment using an adverse action simulation value. 2. Open an application for the account holder. In both the **Test and Live environments**, a application may have one or more adverse action reasons, but only the primary reason is returned. For example, if a cardholder's identity cannot be verified (), and they were denied because their credit score is too low (), Highnote only returns the primary reason: `. ### Adverse action values The following table provides adverse action values for simulating the denial of an account holder application: | Field | Simulation value | Adverse action response code | | :----------------------------- | :--------------- | :--------------------------------------------------------------------------------------------- | | **US Business Account Holder** | | | | | | Cannot verify applicant's identity | | | | | | | | Applicant's income is insufficient for the requested credit amount | | | | Applicant has delinquent past or present credit obligations | | | | and | | | | Applicant does not meet the minimum length of business incorporation | | **US Person Account Holder** | | | | | | Cannot verify applicant's identity | | | | | | | | Applicant's income is insufficient for the requested credit amount | | | | Applicant has delinquent past or present credit obligations | | | | Applicant is reported as deceased | | | | Applicant does not have a credit history | | | | and | | | | Applicant has a bankruptcy in their credit report | | | | Applicant has a tradeline sent to collections in their credit report | | | | Applicant has excessive debt obligations | | | | Applicant has excessive obligations to their income | | | | Applicant has limited credit experience | | | | Applicant’s credit score is below the acceptable level | | | | Applicant has opened too many credit account recently | | | | Applicant has too many recent credit inquiries | | | | Applicant has a high credit utilization ratio | | | | Applicant does not meet line position requirement | | | | Applicant’s length of employment is limited or unstable | | | | Applicant’s length of time at residence is limited or unstable | | | | We do not offer credit to this industry | | | | Applicant has withdrawn their card product application | | | | Unable to verify applicant's employment | | | | Incomplete identity information of owner | | | | Cannot verify the applicant's identity | | | | Cannot verify applicant’s income | ### Credit report PII mismatch values Some Credit Policies have Credit Bureau credit report Personally identifiable information (PII) verification enabled. The following table lists values for simulating outcomes that trigger a manual review due to PII mismatches. | Field | Simulation value | PII code | Outcome | | :------------------ | :--------------- | :----------------- | :------------ | | | | | Manual review | | | | | Manual review | | | | | Manual review | | | | | Manual review | ### Lookup application adverse action To automate your integration, use notification event to send notifications when an application is denied. See Account holder application status. After simulating denial with adverse action reasons, use the following query to find a card product application: ## Credit report inquiries If your credit policy requires credit report inquiries, you must collect additional consent from the account holder during the card product application flow. If you are not using collaborative application decisioning, your card product's credit policy is executed on your behalf by Highnote. For credit policies that perform credit report inquiries, you must monitor and manage credit report freezes and fraud alerts for your account holders. Refer to the following to resolve credit report freezes and fraud alerts for your account holders: - **Credit report freezes:** The account holder must contact the applicable credit bureau and remove the freeze on their credit report. - **Credit report fraud alerts:** You must contact the account holder and verify their identity. ### View credit score reason codes For credit policies that use a credit bureau's risk score, use the following query to view an application's credit creditScoreReasons: ## Freezes, Flags, and Fraud Alerts In some scenarios, account holders may have a freeze or fraud alert on their credit report, or be flagged for MLA eligibility. Using the Test environment, you can simulate a credit report freeze, fraud alert, or MLA flag on an application response. Simulating these scenarios requires the following steps: 1. Onboard an account holder and provide a simulation value (just below) for the field. See Onboard an account holder. 2. Open an application for the account holder. When the application processes, it creates a fraud alert, credit report freeze, or MLA eligibility flag in the response payload. ### Simulation values The following table provides simulation values for creating an account holder to simulate credit freezes, credit report fraud alerts, and MLA eligibility. The same simulation values apply to both US business and person account holders: | Field | Simulation value | Response | | :------------ | :--------------- | :-------------------------- | | | 1111111111 | | | | 2222222222 | | | | 3333333333 | | ### Simulate fraud alert After creating an account holder using the simulation value, use the following mutation to open an application. The fraud alert is noted in the response payload: ### Simulate credit report freeze After creating an account holder using the simulation value, use the following mutation to open an application. The credit report freeze is noted in the response payload: ### Simulate MLA eligibility After creating an account holder using the simulation value, open an application with the mutation. Unlike a fraud alert or credit report freeze, MLA eligibility does not require manual review — the application is approved automatically, with recorded in on the credit underwriting verification. Use the following query to view the approved application: ## Managing fraud alerts Memos are now global. As a best practice, add context to your memos so they make sense when queried on different parts of an application. When a credit report inquiry returns a , indicating the the account holder may have a freeze on their credit report, you can use the following set of queries to: - Find the account holder of an application. - Verify account holder information on an application. - Confirm the status of an updated application. In the Highnote API, the field is now supported by a [](/docs/api-reference/object#GlobalNote) object that can be added and viewed anywhere across a card product application, not just the entity to which is was applied. Global notes are stored centrally and encrypted at rest. With this added flexibility, consider adding context to your notes so that when you run a query on an unrelated part of the application, the note makes sense. ## View fraud alert Use the following query to lookup an application. The response's and fields include account holder information that you can use to reach out to and verify the identity of the account holder: ## Verify fraud alert If an account holder has a fraud alert on their credit report, you must contact the account holder to verify that their **name**, **date of birth**, and **address** match that on the application. If the account holder can't verify the information provided on their application, the application will be denied. Use the following mutation to verify an account holder for a fraud alert: ## Confirm unfrozen credit report If the account holder has a freeze on their credit report, you must contact the account holder and instruct them to remove the freeze from their report. Once the account holder has confirmed they removed a freeze, you can use the following mutation to confirm and re-run the application decisioning workflow: ### GraphQL: GetAccountHolderCardProductApplication Query: query GetAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } adverseActionReasons { code description } accountHolderSnapshot { ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id } primaryAuthorizedPerson { currentVerification { status reason results { code } } updatedAt createdAt } businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { adverseActionReasons { code description } status reason results { code } } currentCreditUnderwritingVerification { status decision { ... on UnderwriterPositiveDecision { creditLine { value currencyCode } } ... on UnderwriterAdverseDecision { adverseActionReasons { code description } } } } ultimateBeneficialOwners { currentVerification { status reason results { code } } updatedAt createdAt } } } } applicationHistory { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { applicationState { status } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "DENIED" }, "cardProduct": { "id": "" }, "adverseActionReasons": [ { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested" } ], "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "primaryAuthorizedPerson": { "currentVerification": { "status": "PASSED", "reason": "PASSED", "results": [ { "code": "PHONE_MATCH" }, { "code": "SSN_MATCH" }, { "code": "NAME_MATCH" }, { "code": "DOB_MATCH" }, { "code": "ADDRESS_MATCH" } ] }, "updatedAt": "2023-01-06T18:46:25.061Z", "createdAt": "2023-01-06T18:46:22.738Z" }, "businessProfile": { "name": { "legalBusinessName": "HIGHNOTE", "doingBusinessAsName": "BlueJay Inc" }, "updatedAt": "2023-01-06T18:46:59.510Z", "createdAt": "2023-01-06T18:46:22.737Z", "currentVerification": { "adverseActionReasons": [], "status": "PASSED", "reason": "PASSED", "results": [ { "code": "REPRESENTATIVE_MATCH" }, { "code": "FEIN_MATCH" }, { "code": "BUSINESS_VERIFICATION_SCORE_PASSED" }, { "code": "ADDRESS_MATCH" }, { "code": "BUSINESS_NAME_MATCH" } ] }, "currentCreditUnderwritingVerification": { "status": "DENIED", "decision": { "adverseActionReasons": [ { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested" } ] } }, "ultimateBeneficialOwners": [ { "currentVerification": { "status": "PASSED", "reason": "PASSED", "results": [ { "code": "PHONE_MATCH" }, { "code": "SSN_MATCH" }, { "code": "NAME_MATCH" }, { "code": "DOB_MATCH" }, { "code": "ADDRESS_MATCH" } ] }, "updatedAt": "2023-01-06T18:46:25.061Z", "createdAt": "2023-01-06T18:46:22.738Z" } ] } }, "applicationHistory": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } } ] }, "updatedAt": "2023-01-06T18:46:59.510Z", "createdAt": "2023-01-06T18:46:22.737Z" } }, "extensions": { "requestId": "" } } ### GraphQL: GetAccountHolderCardProductApplication Query: query GetAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id name } adverseActionReasons { code description } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } billingAddress { streetAddress } currentVerification { status reason adverseActionReasons { code description } } dateOfBirth currentCreditUnderwritingVerification { __typename status decisionResults reviewReasonDetails { memo reviewReason } decision { __typename ... on UnderwriterPositiveDecision { creditLine { value currencyCode } creditPlanTerms { interest { apr } creditPlan { id } } } ... on UnderwriterAdverseDecision { adverseActionReasons { code description __typename } } } decisionDate } } } applicationHistory { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { applicationState { status } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "DENIED" }, "cardProduct": { "id": "", "name": "Test Credit Consumer Charge" }, "adverseActionReasons": [ { "code": "DELINQUENT_CREDIT_OBLIGATIONS", "description": "Delinquent past or present credit obligations" }, { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested" } ], "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "billingAddress": { "streetAddress": "123 Main Street" }, "currentVerification": { "status": "PASSED", "reason": "PASSED", "adverseActionReasons": null }, "dateOfBirth": "1980-09-01", "currentCreditUnderwritingVerification": { "__typename": "CreditUnderwritingVerification", "status": "DENIED", "decisionResults": [ "NO_LIMIT_SET", "CURRENT_DEBT_OBLIGATIONS", "RECENT_CHARGE_OFF", "RECENT_BANKRUPTCY" ], "reviewReasonDetails": null, "decision": { "__typename": "UnderwriterAdverseDecision", "adverseActionReasons": [ { "code": "DELINQUENT_CREDIT_OBLIGATIONS", "description": "Delinquent past or present credit obligations", "__typename": "AdverseActionReason" }, { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested", "__typename": "AdverseActionReason" } ] }, "decisionDate": "2022-10-12T23:53:52.860Z" } }, "applicationHistory": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } } ] }, "updatedAt": "2023-09-11T04:53:10.834Z", "createdAt": "2023-09-11T04:52:54.162Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 35 } } } ### GraphQL: GetAccountHolderCardProductApplication Query: query GetAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id name } adverseActionReasons { code description } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } accountHolderCurrent { id } billingAddress { streetAddress } currentVerification { status reason adverseActionReasons { code description } } dateOfBirth currentCreditUnderwritingVerification { __typename status decisionResults reviewReasonDetails { memo reviewReason } creditScoreDetails { creditBureau creditReportPullDate creditScoreModels { creditScoreReasons creditScore creditScoreType } } decision { __typename ... on UnderwriterPositiveDecision { creditLine { value currencyCode } creditPlanTerms { interest { apr } creditPlan { id } } } ... on UnderwriterAdverseDecision { adverseActionReasons { code description __typename } } } decisionDate } } } applicationHistory { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { applicationState { status } } } } updatedAt createdAt } } } Variables: { "id": "ap_1" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "APPROVED" }, "cardProduct": { "id": "", "name": "Test Credit Consumer Charge" }, "adverseActionReasons": null, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "billingAddress": { "streetAddress": "123 Main Street" }, "currentVerification": { "status": "PASSED", "reason": "PASSED", "adverseActionReasons": null }, "dateOfBirth": "1980-09-01", "currentCreditUnderwritingVerification": { "__typename": "CreditUnderwritingVerification", "status": "PASSED", "decisionResults": [], "creditScoreDetails": { "creditBureau": "EXPERIAN", "creditReportPullDate": "2025-10-08T16:44:19.089Z", "creditScoreModels": [ { "creditScore": "700", "creditScoreType": "V4", "creditScoreReasons": [ "Total of credit limits and loan amounts is too low" ] } ] }, "decision": { "__typename": "UnderwriterAdverseDecision", "creditLine": { "value": 100000, "currencyCode": "USD" }, "adverseActionReasons": null }, "decisionDate": "2022-10-12T23:53:52.860Z" } }, "applicationHistory": { "pageInfo": { "startCursor": "dD0yMDIzLTA5LTExVDA0JTNBNTIlM0E1NC4xNjIwMDAwMDBaJmk9YXBfY2Q2NThmMjBlNDg0NDQwY2E1ZWQ3ZmI4MjM5ZThhY2Q", "endCursor": "dD0yMDIzLTA5LTExVDA0JTNBNTIlM0E1NC4xNjIwMDAwMDBaJmk9YXBfNDNhNjgxNWIyZDlkNDNjNWIwMjY2YTU5ZDYwMTRkYjQ", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "dD0yMDIzLTA5LTExVDA0JTNBNTIlM0E1NC4xNjIwMDAwMDBaJmk9YXBfY2Q2NThmMjBlNDg0NDQwY2E1ZWQ3ZmI4MjM5ZThhY2Q", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "dD0yMDIzLTA5LTExVDA0JTNBNTIlM0E1NC4xNjIwMDAwMDBaJmk9YXBfYjRmN2I0NWZjYjY1NDM4MTlkMjVhYWI1ZjI1YjQ4MGQ", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "dD0yMDIzLTA5LTExVDA0JTNBNTIlM0E1NC4xNjIwMDAwMDBaJmk9YXBfMDUxZDdmZGM4OWI3NDU1MDkwZjc1NGY5MmE1MmQzZmM", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "dD0yMDIzLTA5LTExVDA0JTNBNTIlM0E1NC4xNjIwMDAwMDBaJmk9YXBfNDNhNjgxNWIyZDlkNDNjNWIwMjY2YTU5ZDYwMTRkYjQ", "node": { "applicationState": { "status": "PENDING" } } } ] }, "updatedAt": "2023-09-11T04:53:10.834Z", "createdAt": "2023-09-11T04:52:54.162Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 35 } } } ### GraphQL: createAccountHolderCardProductApplication Query: mutation createAccountHolderCardProductApplication( $input: CreateAccountHolderCardProductApplicationInput! ) { createAccountHolderCardProductApplication(input: $input) { __typename ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } adverseActionReasons { code description } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } name { givenName familyName } billingAddress { streetAddress locality region countryCodeAlpha3 postalCode } currentVerification { reason results { code description } status } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id } primaryAuthorizedPerson { currentVerification { status } updatedAt createdAt } businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { status adverseActionReasons { code description } } currentCreditUnderwritingVerification { __typename status reviewReasonDetails { reviewReason memo } decision { ... on UnderwriterPositiveDecision { __typename creditLine { value currencyCode } creditPlanTerms { creditPlan { __typename id } interest { apr } } } ... on UnderwriterAdverseDecision { __typename adverseActionReasons { code description } } } decisionDate decisionResults } ultimateBeneficialOwners { currentVerification { status } updatedAt createdAt } } } } updatedAt createdAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" }, "accountHolderCreditReportPullConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "billingAddress": { "streetAddress": "123 Main Street", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA", "postalCode": "60654" }, "currentVerification": { "reason": "PENDING", "results": [], "status": "PENDING" }, "currentCreditUnderwritingVerification": { "__typename": "CreditUnderwritingVerification", "status": "IN_REVIEW", "reviewReasonDetails": { "reviewReason": "AWAITING_FRAUD_ALERT_REVIEW", "memo": "" }, "decision": { "__typename": "UnderwriterPositiveDecision", "creditLine": { "value": 15000000, "currencyCode": "USD" }, "creditPlanTerms": { "creditPlan": { "__typename": "CreditPlan", "id": "credit-plan-id" }, "interest": { "apr": 15.9 } } }, "decisionDate": "2022-10-12T23:53:52.860Z", "decisionResults": [ "CREDIT_REPORT_FRAUD_ALERT" ] } }, "updatedAt": "2023-09-22T18:45:10.401Z", "createdAt": "2023-09-22T18:45:10.186Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19, "limit": 100, "remaining": 78 } } } ### GraphQL: createAccountHolderCardProductApplication Query: mutation createAccountHolderCardProductApplication( $input: CreateAccountHolderCardProductApplicationInput! ) { createAccountHolderCardProductApplication(input: $input) { __typename ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } adverseActionReasons { code description } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } name { givenName familyName } billingAddress { streetAddress locality region countryCodeAlpha3 postalCode } currentVerification { reason results { code description } status } } ... on USBusinessAccountHolderSnapshot { accountHolderCurrent { id } primaryAuthorizedPerson { currentVerification { status } updatedAt createdAt } businessProfile { name { legalBusinessName doingBusinessAsName } updatedAt createdAt currentVerification { status adverseActionReasons { code description } } currentCreditUnderwritingVerification { __typename status reviewReasonDetails { reviewReason memo } decision { ... on UnderwriterPositiveDecision { __typename creditLine { value currencyCode } creditPlanTerms { creditPlan { __typename id } interest { apr } } } ... on UnderwriterAdverseDecision { __typename adverseActionReasons { code description } } } decisionDate decisionResults } ultimateBeneficialOwners { currentVerification { status } updatedAt createdAt } } } } updatedAt createdAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "accountHolderId": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" }, "accountHolderCreditReportPullConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "billingAddress": { "streetAddress": "123 Main Street", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA", "postalCode": "60654" }, "currentVerification": { "reason": "PENDING", "results": [], "status": "PENDING" }, "currentCreditUnderwritingVerification": { "__typename": "CreditUnderwritingVerification", "status": "IN_REVIEW", "reviewReasonDetails": { "reviewReason": "AWAITING_FRAUD_ALERT_REVIEW", "memo": "" }, "decision": { "__typename": "UnderwriterPositiveDecision", "creditLine": { "value": 15000000, "currencyCode": "USD" }, "creditPlanTerms": { "creditPlan": { "__typename": "CreditPlan", "id": "credit-plan-id" }, "interest": { "apr": 15.9 } } }, "decisionDate": "2022-10-12T23:53:52.860Z", "decisionResults": [ "CREDIT_REPORT_FRAUD_ALERT" ] } }, "updatedAt": "2023-09-22T18:45:10.401Z", "createdAt": "2023-09-22T18:45:10.186Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19, "limit": 100, "remaining": 78 } } } ### GraphQL: GetAccountHolderCardProductApplication Query: query GetAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id name } adverseActionReasons { code description } applicationConfiguration { applicantBillingCycleOverride { billingCycleType } } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } accountHolderCurrent { id } billingAddress { streetAddress } currentVerification { status reason adverseActionReasons { code description } } dateOfBirth currentCreditUnderwritingVerification { __typename status decisionResults reviewReasonDetails { memo reviewReason } creditScoreDetails { creditBureau creditReportPullDate creditScoreModels { creditScore creditScoreType creditScoreReasons } } decision { __typename ... on UnderwriterPositiveDecision { creditLine { value currencyCode } creditPlanTerms { interest { apr } creditPlan { id } } } ... on UnderwriterAdverseDecision { adverseActionReasons { code description __typename } } } decisionDate } } } applicationHistory { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { applicationState { status } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "APPROVED" }, "cardProduct": { "id": "", "name": "Test Credit Consumer Revolving" }, "adverseActionReasons": null, "applicationConfiguration": null, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "billingAddress": { "streetAddress": "123 Main Street" }, "currentVerification": { "status": "PASSED", "reason": "PASSED", "adverseActionReasons": null }, "dateOfBirth": "1990-01-01", "currentCreditUnderwritingVerification": { "__typename": "CreditUnderwritingVerification", "status": "PASSED", "decisionResults": [ "MLA_ELIGIBLE" ], "reviewReasonDetails": null, "creditScoreDetails": { "creditBureau": null, "creditReportPullDate": "2025-10-16T15:41:07.639Z", "creditScoreModels": [] }, "decision": { "__typename": "UnderwriterPositiveDecision", "creditLine": { "value": 100000, "currencyCode": "USD" }, "creditPlanTerms": [ { "interest": { "apr": 29.56 }, "creditPlan": { "id": "" } } ] }, "decisionDate": "2025-10-16T15:41:07.639Z" } }, "applicationHistory": { "pageInfo": { "startCursor": "dD0yMDI1LTEwLTE2VDE1JTNBNDElM0EwMy4yMzMwMDAwMDBaJmk9YXBfZDY0MmJhODk4NTY2NGE2MGEwOTI5NDE2NTAzODI2NzI", "endCursor": "dD0yMDI1LTEwLTE2VDE1JTNBNDElM0EwMy4yMzMwMDAwMDBaJmk9YXBfZjY5MzI0YmVmZmI3NGYxZjlkNjExNTQ2MTk3YTFhZDI", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "dD0yMDI1LTEwLTE2VDE1JTNBNDElM0EwMy4yMzMwMDAwMDBaJmk9YXBfZDY0MmJhODk4NTY2NGE2MGEwOTI5NDE2NTAzODI2NzI", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "dD0yMDI1LTEwLTE2VDE1JTNBNDElM0EwMy4yMzMwMDAwMDBaJmk9YXBfZjY5MzI0YmVmZmI3NGYxZjlkNjExNTQ2MTk3YTFhZDI", "node": { "applicationState": { "status": "PENDING" } } } ] }, "updatedAt": "2025-10-16T15:41:10.312Z", "createdAt": "2025-10-16T15:41:03.233Z" } }, "extensions": { "requestId": "4222048c-fc1a-9ab1-8cae-886c8e767590", "rateLimit": { "cost": 43, "limit": 60060, "remaining": 60017, "asOf": "2025-10-16T15:46:35.651Z", "complexity": { "limit": 60060, "remaining": 60017, "cost": 43 }, "count": { "limit": 60060, "remaining": 60059, "cost": 1 } } } } ### GraphQL: GetAccountHolderCardProductApplication Query: query GetAccountHolderCardProductApplication($id: ID!) { node(id: $id) { ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id name } adverseActionReasons { code description } globalNotes { ... on GlobalNoteConnection { edges { node { primaryEntity { __typename ... on Node { id } ... on AccountHolderCardProductApplication { id } } createdBy { ... on User { id } } createdAt message } } } } accountHolderSnapshot { ... on USPersonAccountHolderSnapshot { accountHolderCurrent { id } accountHolderCurrent { id } billingAddress { streetAddress } currentVerification { status reason adverseActionReasons { code description } } dateOfBirth currentCreditUnderwritingVerification { __typename status decisionResults reviewReasonDetails { memo reviewReason } decision { __typename ... on UnderwriterPositiveDecision { creditLine { value currencyCode } creditPlanTerms { interest { apr } creditPlan { id } } } ... on UnderwriterAdverseDecision { adverseActionReasons { code description __typename } } } decisionDate } } } applicationHistory { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { applicationState { status } } } } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "applicationState": { "status": "DENIED" }, "cardProduct": { "id": "", "name": "Test Credit Consumer Charge" }, "adverseActionReasons": [ { "code": "DELINQUENT_CREDIT_OBLIGATIONS", "description": "Delinquent past or present credit obligations" }, { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested" } ], "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "billingAddress": { "streetAddress": "123 Main Street" }, "currentVerification": { "status": "PASSED", "reason": "PASSED", "adverseActionReasons": null }, "dateOfBirth": "1980-09-01", "currentCreditUnderwritingVerification": { "__typename": "CreditUnderwritingVerification", "status": "DENIED", "decisionResults": [ "NO_LIMIT_SET", "CURRENT_DEBT_OBLIGATIONS", "RECENT_CHARGE_OFF", "RECENT_BANKRUPTCY" ], "reviewReasonDetails": null, "decision": { "__typename": "UnderwriterAdverseDecision", "adverseActionReasons": [ { "code": "DELINQUENT_CREDIT_OBLIGATIONS", "description": "Delinquent past or present credit obligations", "__typename": "AdverseActionReason" }, { "code": "INSUFFICIENT_INCOME", "description": "Income insufficient for the amount of credit requested", "__typename": "AdverseActionReason" } ] }, "decisionDate": "2022-10-12T23:53:52.860Z" } }, "applicationHistory": { "pageInfo": { "startCursor": "start-cursor", "endCursor": "end-cursor", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } }, { "cursor": "some-cursor", "node": { "applicationState": { "status": "PENDING" } } } ] }, "updatedAt": "2023-09-11T04:53:10.834Z", "createdAt": "2023-09-11T04:52:54.162Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 35 } } } ### GraphQL: confirmVerificationOfCreditProductApplicationForFraudAlert Query: mutation confirmVerificationOfCreditProductApplicationForFraudAlert( $input: ConfirmVerificationOfCreditProductApplicationForFraudAlertInput! ) { confirmVerificationOfCreditProductApplicationForFraudAlert(input: $input) { ... on AccountHolderCardProductApplication { __typename id applicationState { status } cardProduct { id } globalNotes { ... on GlobalNoteConnection { edges { node { primaryEntity { __typename ... on Node { id } ... on AccountHolderCardProductApplication { id } } createdBy { ... on User { id } } createdAt message } } } } createdAt updatedAt } } } Variables: { "input": { "applicationId": "", "verificationResult": { "accountHolderInitiatedApplication": true, "name": true, "dateOfBirth": true, "address": true }, "memo": "Fraud note" } } Expected Result: { "data": { "confirmVerificationOfCreditProductApplicationForFraudAlert": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "creditReportFraudAlertVerificationResult": { "accountHolderInitiatedApplication": true, "name": true, "dateOfBirth": true, "address": true }, "globalNotes": { "edges": [ { "node": { "primaryEntity": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "createdBy": { "id": "" }, "createdAt": "2025-02-14T18:25:59.684Z", "message": "Fraud note" } } ] }, "updatedAt": "2024-04-10T21:41:09.137Z", "createdAt": "2024-04-10T21:37:56.455Z" } }, "extensions": { "requestId": "5951d35e-0316-9e78-9acc-9aa2dbbbf1c0", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60004 } } } ### GraphQL: confirmCreditReportUnfrozen Query: mutation confirmCreditReportUnfrozen( $input: ConfirmCreditReportUnfrozenInput! ) { confirmCreditReportUnfrozen(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on AccountHolderCardProductApplication { id applicationState { status } cardProduct { id } globalNotes { ... on GlobalNoteConnection { edges { node { primaryEntity { __typename ... on Node { id } ... on AccountHolderCardProductApplication { id } } createdBy { ... on User { id } } createdAt message } } } } updatedAt createdAt } } } Variables: { "input": { "applicationId": "", "subscriberNote": "credit report confirmed unfrozen" } } Expected Result: { "data": { "confirmCreditReportUnfrozen": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "globalNotes": { "edges": [ { "node": { "primaryEntity": { "__typename": "AccountHolderCardProductApplication", "id": "" }, "createdBy": { "id": "" }, "createdAt": "2025-02-14T18:25:59.684Z", "message": "credit report confirmed unfrozen" } } ] }, "updatedAt": "2024-04-10T21:41:09.137Z", "createdAt": "2024-04-10T21:37:56.455Z" } }, "extensions": { "requestId": "5951d35e-0316-9e78-9acc-9aa2dbbbf1c0", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60004 } } } --- URL: https://docs.highnote.com/docs/issuing/credit/statements/credit-statement-rev-consumer Title: Deliver Revolving Consumer Credit Statements Section: Issuing Description: Generate and deliver revolving consumer credit billing statements. View amount due, payment dates, statement entries, interest charges, and pay-off warnings. ## Overview Billing statements reflect money movement, balances, and fees for an account holder's financial account. Billing statements are often required for credit card products. This guide provides steps for generating and simulating billing statements using the Highnote API. ## Prerequisites - A Highnote account - An API key or the API Explorer - A card product, financial account, and payment card - _Optional_ - Real or simulated transactions ## Generating billing statements Billing statements are typically available within 48 hours of the end of a billing cycle. The billing period and end date for credit card products may vary across accounts. To be notified when billing statements are ready for financial accounts, use the financial account statement notification. To generate a billing statement, query the object as follows: - **To generate billing statements with posted transactions and balances for a billing period:** Query the and use the . - **To generate billing statements with transactions for the current billing period and their upcoming due date:** Query the and use the . Refer to the appropriate statement snapshot type based on your card product: | Card product type | Statement snapshot | | :-------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | | Commercial revolving credit | [](/docs/api-reference/object#CommercialRevolvingCardFinancialAccountStatementSnapshot) | | Commercial charge | [](/docs/api-reference/object#CreditPayInFullCardFinancialAccountStatementSnapshot) | | Consumer charge | [](/docs/api-reference/object#ConsumerChargeCardFinancialAccountStatementSnapshot) | | Consumer revolving credit | [](/docs/api-reference/object#ConsumerRevolvingCardFinancialAccountStatementSnapshot) | ## Current amount due When a balance is due, the on the statement snapshot reflects payments or refunds made between the billing period end date and the payment due date. Use to display the account holder's balance on your website or application outside of their billing statements. ## Period and payment due dates Payment due dates are determined by (1) the financial account's creation date, and (2) the card product's grace period. Billing dates are set with timestamps at the beginning or end of the day: - **Period Dates** occur at the beginning of the day at Eastern Time (EST/EDT). - **Payment Due Date** occurs at the end of the day at Eastern Time (EST/EDT). The Highnote API response returns these values in Coordinated Universal Time (UTC), which means that you mean need to adjust the Payment Due Date before displaying to card holders in select regions. #### Adjusting due date for North America The **paymentDueOn field is in UTC** and represents the time in . For example, if = , then EDT = (America/New_York) and EST = . You must adjust the date when presenting to account holders in North America. This is because (1) the actual end date occurs at Eastern Time, and (2) the value in the API response is in UTC which moves it to the next day. #### EST Example | Field | Internal Date (EST) | API Response (UTC) | Action Needed | Your Display (EST) | | :----------- | :-------------------- | :-------------------- | :----------------- | :-------------------- | | Period Start | | | Leave as is | | | Period End | | | Leave as is | | | Payment Due | | | Subtract 1 cal day | | ### Examples of due date adjustments The following tables demonstrate adjusting the period due date for card holders in North America. #### Legend - Start Date (Account activation time) - End Date (Beginning of day 12am EST/EDT) - Due Date (End of day 11:59:59pm EST/EDT) - Start Date of next cycle (Beginning of day 12am EST/EDT) - End date of next cycle (Beginning of day 12am EST/EDT) - Due Date (End of day 11:59:59pm EST/EDT) #### Grace Period = 21 Days | Start Date | End Date (12am ET) | Due Date (11:59:59pm) | Start Date Next Cycle | End date Next Cycle (12am ET) | Due Date Next Cycle (11:59:59pm ET) | | :--------- | :----------------- | :-------------------- | :-------------------- | :---------------------------- | :---------------------------------- | | Aug 1 | Sep 1 | 9/22 | Sep 1 | Oct 1 | 10/22 | | Aug 2 | Sep 2 | 9/23 | Sep 2 | Oct 2 | 10/23 | | Aug 3 | Sep 3 | 9/24 | Sep 3 | Oct 3 | 10/24 | | Aug 4 | Sep 4 | 9/25 | Sep 4 | Oct 4 | 10/25 | | Aug 5 | Sep 5 | 9/26 | Sep 5 | Oct 5 | 10/26 | | Aug 6 | Sep 6 | 9/27 | Sep 6 | Oct 6 | 10/27 | | Aug 7 | Sep 7 | 9/28 | Sep 7 | Oct 7 | 10/28 | | Aug 8 | Sep 8 | 9/29 | Sep 8 | Oct 8 | 10/29 | | Aug 9 | Sep 9 | 9/30 | Sep 9 | Oct 9 | 10/30 | | Aug 10 | Sep 10 | 10/1 | Sep 10 | Oct 10 | 10/31 | | Aug 11 | Sep 11 | 10/2 | Sep 11 | Oct 11 | 11/1 | | Aug 12 | Sep 12 | 10/3 | Sep 12 | Oct 12 | 11/2 | | Aug 13 | Sep 13 | 10/4 | Sep 13 | Oct 13 | 11/3 | | Aug 14 | Sep 14 | 10/5 | Sep 14 | Oct 14 | 11/4 | | Aug 15 | Sep 15 | 10/6 | Sep 15 | Oct 15 | 11/5 | | Aug 16 | Sep 16 | 10/7 | Sep 16 | Oct 16 | 11/6 | | Aug 17 | Sep 17 | 10/8 | Sep 17 | Oct 17 | 11/7 | | Aug 18 | Sep 18 | 10/9 | Sep 18 | Oct 18 | 11/8 | | Aug 19 | Sep 19 | 10/10 | Sep 19 | Oct 19 | 11/9 | | Aug 20 | Sep 20 | 10/11 | Sep 20 | Oct 20 | 11/10 | | Aug 21 | Sep 21 | 10/12 | Sep 21 | Oct 21 | 11/11 | | Aug 22 | Sep 22 | 10/13 | Sep 22 | Oct 22 | 11/12 | | Aug 23 | Sep 23 | 10/14 | Sep 23 | Oct 23 | 11/13 | | Aug 24 | Sep 24 | 10/15 | Sep 24 | Oct 24 | 11/14 | | Aug 25 | Sep 25 | 10/16 | Sep 25 | Oct 25 | 11/15 | | Aug 26 | Sep 26 | 10/17 | Sep 26 | Oct 26 | 11/16 | | Aug 27 | Sep 27 | 10/18 | Sep 27 | Oct 27 | 11/17 | | Aug 28 | Sep 28 | 10/19 | Sep 28 | Oct 28 | 11/18 | | Aug 29 | Sep 28 | 10/19 | Sep 28 | Oct 28 | 11/18 | | Aug 30 | Sep 28 | 10/19 | Sep 28 | Oct 28 | 11/18 | | Aug 31 | Sep 28 | 10/19 | Sep 28 | Oct 28 | 11/18 | #### Grace Period = 10 Days | Start Date | End Date (12am ET) | Due Date (11:59:59pm) | | :--------- | :----------------- | :-------------------- | | Aug 1 | Aug 15 | 8/25 | | Aug 2 | Aug 16 | 8/26 | | Aug 3 | Aug 17 | 8/27 | | Aug 4 | Aug 18 | 8/28 | | Aug 5 | Aug 19 | 8/29 | | Aug 6 | Aug 20 | 8/30 | | Aug 7 | Aug 21 | 8/31 | | Aug 8 | Aug 22 | 9/1 | | Aug 9 | Aug 23 | 9/2 | | Aug 10 | Aug 24 | 9/3 | | Aug 11 | Aug 25 | 9/4 | | Aug 12 | Aug 26 | 9/5 | | Aug 13 | Aug 27 | 9/6 | | Aug 14 | Aug 28 | 9/7 | | Aug 15 | Aug 29 | 9/8 | | Aug 16 | Aug 30 | 9/9 | | Aug 17 | Aug 31 | 9/10 | | Aug 18 | Sep 1 | 9/11 | | Aug 19 | Sep 2 | 9/12 | | Aug 20 | Sep 3 | 9/13 | | Aug 21 | Sep 4 | 9/14 | | Aug 22 | Sep 5 | 9/15 | | Aug 23 | Sep 6 | 9/16 | | Aug 24 | Sep 7 | 9/17 | | Aug 25 | Sep 8 | 9/18 | | Aug 26 | Sep 9 | 9/19 | | Aug 27 | Sep 10 | 9/20 | | Aug 28 | Sep 11 | 9/21 | | Aug 29 | Sep 12 | 9/22 | | Aug 30 | Sep 13 | 9/23 | | Aug 31 | Sep 14 | 9/24 | #### Grace Period = 5 Days | Start Date | End Date (12am ET) | Due Date (11:59:59pm) | | :--------- | :----------------- | :-------------------- | | Aug 1 | Aug 8 | 8/13 | | Aug 2 | Aug 9 | 8/14 | | Aug 3 | Aug 10 | 8/15 | | Aug 4 | Aug 11 | 8/16 | | Aug 5 | Aug 12 | 8/17 | | Aug 6 | Aug 13 | 8/18 | | Aug 7 | Aug 14 | 8/19 | | Aug 8 | Aug 15 | 8/20 | | Aug 9 | Aug 16 | 8/21 | | Aug 10 | Aug 17 | 8/22 | | Aug 11 | Aug 18 | 8/23 | | Aug 12 | Aug 19 | 8/24 | | Aug 13 | Aug 20 | 8/25 | | Aug 14 | Aug 21 | 8/26 | | Aug 15 | Aug 22 | 8/27 | | Aug 16 | Aug 23 | 8/28 | | Aug 17 | Aug 24 | 8/29 | | Aug 18 | Aug 25 | 8/30 | | Aug 19 | Aug 26 | 8/31 | | Aug 20 | Aug 27 | 9/1 | | Aug 21 | Aug 28 | 9/2 | | Aug 22 | Aug 29 | 9/3 | | Aug 23 | Aug 30 | 9/4 | | Aug 24 | Aug 31 | 9/5 | | Aug 25 | Sep 1 | 9/6 | | Aug 26 | Sep 2 | 9/7 | | Aug 27 | Sep 3 | 9/8 | | Aug 28 | Sep 4 | 9/9 | | Aug 29 | Sep 5 | 9/10 | | Aug 30 | Sep 6 | 9/11 | | Aug 31 | Sep 7 | 9/12 | ### Update the due date You can **change the day of the month** a payment is due with updateFinancialAccountBillingCycleConfiguration. The new value applies to future billing cycles only — the current open cycle and any past cycles are unaffected. The new value must be different from the current due date. Payment due date cannot be changed more than once in three billing cycles — approximately every 90 days for monthly billing. The window begins from the prior change's effective due date. Updates apply to future billing cycles only — you cannot change the current cycle. ```graphql mutation UpdateFinancialAccountBillingCycleConfiguration { updateFinancialAccountBillingCycleConfiguration( input: { financialAccountId: "" paymentDueDayOfMonth: 15 } ) { ... on FinancialAccount { id } ... on UserError { errors { path type } } } } ``` is an integer between 1 and 28. ## Generate current billing statement Use the following query to generate the current billing statement for an account holder: ## Find billing statement history To display billing statement history, you can look up past billing statements for up to 24 months. To filter data, you can search by or of the billing period. If there is no data for a specific period, the query will return no results. Use the following query to find billing statement history for a consumer revolving credit card. If you are querying for billing statement history for commercial or consumer charge, you must update the statement snapshot type for your card product. ## Fetch statement details You can search for details on a billing statement using a statement ID. Billing statement details include the following: - Information from financial events in the statement's billing cycle period - Summary-level balances The following table provides an overview of data from the summary statement balance that can be retrieved from a billing statement. Use the objects in the column in your query to return specific data: | SUMMARY STATEMENT BALANCE | FIELD | DESCRIPTION | | :------------------------- | :-------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- | | Beginning balance | or | Initial outstanding balance at the start of the statement's billing cycle | | Total purchases | | Total purchases posted to the financial account during the billing cycle | | Total payments and refunds | | Sum of payments, returns, and refunds posted to the financial account during the billing cycle | | Total fees | | The total fees assessed during the billing cycle | | Total interest charges | | The total interest charges for the billing cycle | | Ending balance | or | Final outstanding balance on the financial account at the end of the billing cycle | | Past due balance | | Overdue balance at the close of the statement's billing cycle | For consumer revolving credit card products, a statement includes detailed balances, interest charges, and transactions for each credit plan, categorized by balance type. It also includes a field, which shows the monthly payment amount, estimated days to pay off the balance, and total balance to be paid in the following scenarios: - If the minimum payment amount is made monthly - If the total balance is paid off over three years Use the following query to fetch statement details by ID: ## Filter statement entries Statement entries are presented in a paginated format. You can filter these entries based on their posting date and by distinguishing between credit and debit transactions. The following query applies these filters to statement entries for a consumer revolving credit card product: ## Simulate shifting billing statement end period In the Test environment, you can end a financial account's billing period early to simulate a billing statement. When performing this simulation, refer to the following guidelines: - Set the new period at least 60 seconds in the future. - If no is provided, the system defaults the statement’s to 60 seconds from now. To simulate changing a statement's end period for a consumer revolving credit card, use the following mutation: ## Simulate rolling to next billing statement cycle In the Test environment, you can transition a financial account's billing period to the next cycle, simulating the end of one billing cycle and the start of another. To retrieve the simulated current amount due, refer to the appropriate statement snapshot type: | Card product type | Statement snapshot | | :------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------- | | Commercial charge | [](/docs/api-reference/object#CreditPayInFullCardFinancialAccountStatementSnapshot) | | Consumer charge | [](/docs/api-reference/object#ConsumerChargeCardFinancialAccountStatementSnapshot) | | Consumer revolving credit | [](/docs/api-reference/object#ConsumerRevolvingCardFinancialAccountStatementSnapshot) | Use the following mutation to simulate rolling over the current statement period for a consumer revolving credit card: ### GraphQL: FindFinancialAccount Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffPeriod } } } secondaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingSecondaryCreditBalance { value currencyCode } startingSecondaryDebitBalance { value currencyCode } endingSecondaryCreditBalance { value currencyCode } endingSecondaryDebitBalance { value currencyCode } accumulatedAccountInterestAndFees { yearToDateAccumulatedInterestDebit { value currencyCode } yearToDateAccumulatedInterestCredit { value currencyCode } yearToDateAccumulatedFeesDebit { value currencyCode } yearToDateAccumulatedFeesCredit { value currencyCode } } } query FindFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id statementSnapshot { ... on ConsumerRevolvingCardFinancialAccountStatementSnapshot { currentAmountDue { value } } ... on FinancialAccountStatementSnapshot { asOf currentOpenStatement { ...statement } latestClosedStatement { ...statement } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "statementSnapshot": { "currentAmountDue": { "value": 114835 }, "asOf": "2023-11-30T07:54:46.011Z", "currentOpenStatement": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-11-30T05:00:00.000Z", "periodEnd": "2023-12-28T05:00:00.000Z", "openedAt": "2023-11-30T07:54:45.333Z", "closedAt": null, "paymentDueOn": "2024-01-05T05:00:00.000Z", "pastDueAmount": null, "periodMinimumPaymentDue": null, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": null, "periodPurchaseCreditPlan": null, "payOffWarning": null, "secondaryLedger": null, "startingSecondaryCreditBalance": null, "startingSecondaryDebitBalance": null, "endingSecondaryCreditBalance": null, "endingSecondaryDebitBalance": null, "accumulatedAccountInterestAndFees": null } } } } } ### GraphQL: FindBillingStatementHistory Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffPeriod } } } secondaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingSecondaryCreditBalance { value currencyCode } startingSecondaryDebitBalance { value currencyCode } endingSecondaryCreditBalance { value currencyCode } endingSecondaryDebitBalance { value currencyCode } } query FindFinancialAccount( $id: ID! $filterStatementsBy: FinancialAccountStatementFilterInput ) { node(id: $id) { ... on FinancialAccount { id activeBillingCycleConfiguration { billingCycleStartDayOfMonth billingCycleEndDayOfMonth from paymentDueDayOfMonth } createdAt statements(first: 10, filterBy: $filterStatementsBy) { edges { node { ...statement } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } } } } Variables: { "id": "", "filterStatementsBy": { "periodEnd": { "lessThan": "2023-11-30T04:00:00.000Z", "greaterThan": "2023-09-29T04:00:00.000Z" } } } Expected Result: { "data": { "node": { "id": "", "activeBillingCycleConfiguration": { "billingCycleStartDayOfMonth": 1, "billingCycleEndDayOfMonth": 28, "from": "2023-09-01", "paymentDueDayOfMonth": 5 }, "createdAt": "2023-09-01T00:00:00.000Z", "statements": { "edges": [ { "node": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-09-30T05:00:00.000Z", "periodEnd": "2023-10-28T05:00:00.000Z", "openedAt": "2023-11-30T07:51:25.643Z", "closedAt": "2023-11-30T07:54:45.333Z", "paymentDueOn": "2023-11-05T05:00:00.000Z", "pastDueAmount": { "value": 5878, "currencyCode": "USD" }, "periodMinimumPaymentDue": { "value": 11862, "currencyCode": "USD" }, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 2473, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": { "value": 2484, "currencyCode": "USD" }, "periodPurchaseCreditPlan": null, "payOffWarning": null, "secondaryLedger": null, "startingSecondaryCreditBalance": null, "startingSecondaryDebitBalance": null, "endingSecondaryCreditBalance": null, "endingSecondaryDebitBalance": null }, "cursor": "cursor_value" } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "start_cursor", "endCursor": "end_cursor" } } } } } ### GraphQL: LookupStatement Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffPeriod } } } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } accumulatedAccountInterestAndFees { yearToDateAccumulatedInterestCredit { value currencyCode decimalPlaces } } } fragment ledgerEntry on LedgerEntry { __typename id memo creditBalanceAtLedgerEntry { value currencyCode } debitBalanceAtLedgerEntry { value currencyCode } amount { value currencyCode } financialEvent { ... on Node { id } ... on ClearingEvent { id approvedAmount { value currencyCode } } ... on FeeTransferEvent { id feeTransfer { __typename ... on ChargedFeeTransfer { feeActivityType feeAmount { value currencyCode } } ... on ReversedFeeTransfer { transferedFeeAmount { value currencyCode } } } } } } query LookupStatement( $id: ID! $filterBy: FinancialAccountStatementEntriesFilterInput ) { node(id: $id) { ...statement ... on ConsumerRevolvingCardFinancialAccountStatement { statementEntries(first: 20, filterBy: $filterBy) { edges { node { __typename postDate creditAmount { value } debitAmount { value } primaryCreditBalance { value } primaryDebitBalance { value } ledgerEntry { ...ledgerEntry } } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-09-30T05:00:00.000Z", "periodEnd": "2023-10-28T05:00:00.000Z", "openedAt": "2023-11-30T07:51:25.643Z", "closedAt": "2023-11-30T07:54:45.333Z", "paymentDueOn": "2023-11-05T05:00:00.000Z", "pastDueAmount": { "value": 5878, "currencyCode": "USD" }, "periodMinimumPaymentDue": { "value": 11862, "currencyCode": "USD" }, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835 }, "debitBalance": { "value": 0 } }, "startingPrimaryCreditBalance": { "value": 2473, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": { "value": 2484, "currencyCode": "USD" }, "periodPurchaseCreditPlan": null, "payOffWarning": null, "secondaryLedger": null, "startingSecondaryCreditBalance": null, "startingSecondaryDebitBalance": null, "endingSecondaryCreditBalance": null, "endingSecondaryDebitBalance": null, "accumulatedAccountInterestAndFees": null, "statementEntries": { "edges": [], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": null, "endCursor": null } } } } } ### GraphQL: FilterStatementEntries Query: fragment statementEntry on FinancialAccountStatementEntry { __typename postDate creditAmount { value } debitAmount { value } primaryCreditBalance { value } primaryDebitBalance { value } ledgerEntry { ...ledgerEntry } } fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffPeriod } } } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } statementEntries(first: 20, filterBy: $filterBy) { edges { node { ...statementEntry } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } } fragment ledgerEntry on LedgerEntry { __typename id memo creditBalanceAtLedgerEntry { value currencyCode } debitBalanceAtLedgerEntry { value currencyCode } amount { value currencyCode } ledger { id } financialEvent { __typename ... on ClearingEvent { merchantDetails { name description category } } } } query LookupStatement( $id: ID! $filterBy: FinancialAccountStatementEntriesFilterInput ) { node(id: $id) { ...statement } } Variables: { "id": "", "filterBy": { "postDate": { "lessThan": "2023-12-01T22:21:50.108Z" }, "isCredit": { "equals": true } } } Expected Result: { "data": { "node": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-09-30T05:00:00.000Z", "periodEnd": "2023-10-28T05:00:00.000Z", "openedAt": "2023-11-30T07:51:25.643Z", "closedAt": "2023-11-30T07:54:45.333Z", "paymentDueOn": "2023-11-05T05:00:00.000Z", "pastDueAmount": { "value": 5878, "currencyCode": "USD" }, "periodMinimumPaymentDue": { "value": 11862, "currencyCode": "USD" }, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835 }, "debitBalance": { "value": 0 } }, "startingPrimaryCreditBalance": { "value": 2473, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": { "value": 2484, "currencyCode": "USD" }, "periodPurchaseCreditPlan": null, "payOffWarning": null, "secondaryLedger": null, "startingSecondaryCreditBalance": null, "startingSecondaryDebitBalance": null, "endingSecondaryCreditBalance": null, "endingSecondaryDebitBalance": null, "statementEntries": { "edges": [], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": null, "endCursor": null } } } } } ### GraphQL: SimulateShiftCurrentStatementPeriod Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt createdAt updatedAt paymentDueOn pastDueAmount { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } } payOffWarning { paymentCycles { payOffType paymentDetails { estimatedPayOffPeriod estimatedTotal { value currencyCode } periodPayment { value currencyCode } } } } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value } startingPrimaryDebitBalance { value } endingPrimaryCreditBalance { value } endingPrimaryDebitBalance { value } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } } mutation SimulateShiftCurrentStatementPeriod( $input: SimulateShiftCurrentFinancialAccountStatementPeriodInput! ) { simulateShiftCurrentFinancialAccountStatementPeriod(input: $input) { __typename ... on FinancialAccount { id statementSnapshot { ... on ConsumerRevolvingCardFinancialAccountStatementSnapshot { __typename asOf currentOpenStatement { ...statement } latestClosedStatement { ...statement } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "financialAccountId": "", "periodBoundary": "2023-04-05T00:43:26.96" } } Expected Result: { "data": { "simulateShiftCurrentFinancialAccountStatementPeriod": { "__typename": "FinancialAccount", "id": "", "statementSnapshot": { "__typename": "ConsumerRevolvingCardFinancialAccountStatementSnapshot", "asOf": "2023-12-05T00:17:45.591Z", "currentOpenStatement": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-12-04T05:00:00.000Z", "periodEnd": "2023-12-05T00:43:26.960Z", "openedAt": "2023-12-05T00:17:45.529Z", "closedAt": null, "createdAt": "2023-12-05T00:17:45.529Z", "updatedAt": "2023-12-05T00:17:45.591Z", "paymentDueOn": "2023-12-15T00:43:26.960Z", "pastDueAmount": null, "periodInterestCharges": null, "periodPurchaseCreditPlan": null, "payOffWarning": null, "periodMinimumPaymentDue": null, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 3000 }, "debitBalance": { "value": 0 } }, "startingPrimaryCreditBalance": { "value": 0 }, "startingPrimaryDebitBalance": { "value": 0 }, "endingPrimaryCreditBalance": { "value": 0 }, "endingPrimaryDebitBalance": { "value": 0 }, "secondaryLedger": null, "startingSecondaryCreditBalance": null, "startingSecondaryDebitBalance": null, "endingSecondaryCreditBalance": null, "endingSecondaryDebitBalance": null } } } } } ### GraphQL: SimulateRolloverCurrentStatementPeriod Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffPeriod } } } secondaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingSecondaryCreditBalance { value currencyCode } startingSecondaryDebitBalance { value currencyCode } endingSecondaryCreditBalance { value currencyCode } endingSecondaryDebitBalance { value currencyCode } } mutation SimulateRolloverCurrentStatementPeriod( $input: SimulateRolloverCurrentFinancialAccountStatementPeriodInput! ) { simulateRolloverCurrentFinancialAccountStatementPeriod(input: $input) { __typename ... on FinancialAccount { id statementSnapshot { ... on ConsumerRevolvingCardFinancialAccountStatementSnapshot { __typename asOf currentAmountDue { value } latestClosedStatement { ...statement } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "financialAccountId": "" } } Expected Result: { "data": { "simulateRolloverCurrentFinancialAccountStatementPeriod": { "__typename": "FinancialAccount", "id": "", "statementSnapshot": { "__typename": "ConsumerRevolvingCardFinancialAccountStatementSnapshot", "asOf": "2023-12-05T00:17:45.591Z", "currentAmountDue": { "value": 114835 }, "latestClosedStatement": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-11-30T05:00:00.000Z", "periodEnd": "2023-12-28T05:00:00.000Z", "openedAt": "2023-11-30T07:54:45.333Z", "closedAt": "2023-12-05T00:17:45.333Z", "paymentDueOn": "2024-01-05T05:00:00.000Z", "pastDueAmount": null, "periodMinimumPaymentDue": { "value": 11486, "currencyCode": "USD" }, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": null, "periodPurchaseCreditPlan": null, "payOffWarning": null, "secondaryLedger": null, "startingSecondaryCreditBalance": null, "startingSecondaryDebitBalance": null, "endingSecondaryCreditBalance": null, "endingSecondaryDebitBalance": null } } } } } --- URL: https://docs.highnote.com/docs/issuing/credit/statements/prepaid-statement Title: Deliver Prepaid Statements Section: Issuing Description: Generate and deliver prepaid card statements with up to 24 months of history. View remaining fund balance, period dates, and statement entries. ## Overview This page explains how to generate a statement for consumer prepaid card products. For credit card statements, see Deliver Credit Statements. In the prepaid context, there is no concept of an "amount due" or "amount owing" -- this is not a "billing" statement -- as funds must be preloaded onto the account. You can show card holders the remaining balance of those funds by adding to the request. As with credit statements, use the appropriate statement snapshot based on your card product configuration to access transaction or balance details: - ConsumerPrepaidCardFinancialAccountStatementSnapshot ## Period dates The period start and end dates occur at midnight Eastern Time (EST or EDT) and are presented in the API response in Coordinated Universal Time (UTC), for example, 12am EST => 5am UTC. | Field | Internal Date (EST) | API Response (UTC) | | :----------- | :-------------------- | :-------------------- | | Period Start | | | | Period End | | | ## Generate current prepaid statement Use the following query to generate the current prepaid statement for an account holder: ## Find prepaid statement history To filter data, search by or of the period. If there is no data for a specific period, the query returns no results. You can look up past statements for up to 24 months. ## Fetch prepaid statement by ID You can search for details on a prepaid statement using a statement ID. Prepaid statement details include: - Information from financial events during the statement period - Summary-level balances Use the following query to fetch statement details by ID: ## Filter prepaid statement entries Statement entries are presented in a paginated format. You can filter these entries based on their posting date. The following query applies these filters to statement entries for a consumer prepaid card product: ## Simulate shifting prepaid end period In the Test environment, you can end a financial account's period early to simulate a statement. When performing this simulation, refer to the following guidelines: - Set the new period at least 60 seconds in the future. - If no is provided, the system defaults the statement’s to 60 seconds from now. To simulate changing a statement's end period for a consumer prepaid card, use the following mutation: ## Simulate rolling to next prepaid cycle As with credit cards, you can transition the statement period of a prepaid financial account to the next cycle, simulating the end of one statement cycle and the start of another. Use the following mutation to simulate rolling over the current statement period for a consumer prepaid card, and use the [](/docs/api-reference/object#ConsumerPrepaidCardFinancialAccountStatementSnapshot). ### GraphQL: FindFinancialAccount Query: fragment statement on ConsumerPrepaidCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt createdAt updatedAt primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value } startingPrimaryDebitBalance { value } endingPrimaryCreditBalance { value } endingPrimaryDebitBalance { value } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } } query FindFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id statementSnapshot { ... on ConsumerPrepaidCardFinancialAccountStatementSnapshot { asOf currentOpenStatement { ...statement } latestClosedStatement { ...statement } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "statementSnapshot": { "asOf": "2025-08-27T15:26:04.095Z", "currentOpenStatement": { "id": "", "__typename": "ConsumerPrepaidCardFinancialAccountStatement", "periodStart": "2025-08-27T15:25:08.395Z", "periodEnd": "2025-09-27T15:25:08.395Z", "openedAt": "2025-08-27T15:26:03.368Z", "closedAt": null, "createdAt": "2025-08-27T12:23:10.058Z", "updatedAt": "2025-08-27T15:26:04.053Z", "primaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 71000 } }, "startingPrimaryCreditBalance": { "value": 0 }, "startingPrimaryDebitBalance": { "value": 71000 }, "endingPrimaryCreditBalance": { "value": 0 }, "endingPrimaryDebitBalance": { "value": 0 }, "secondaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 0 } }, "startingSecondaryCreditBalance": { "value": 0 }, "startingSecondaryDebitBalance": { "value": 0 }, "endingSecondaryCreditBalance": { "value": 0 }, "endingSecondaryDebitBalance": { "value": 0 } }, "latestClosedStatement": { "id": "", "__typename": "ConsumerPrepaidCardFinancialAccountStatement", "periodStart": "2025-08-27T12:19:48.368Z", "periodEnd": "2025-08-27T15:25:08.395Z", "openedAt": "2025-08-27T12:23:09.790Z", "closedAt": "2025-08-27T15:26:03.368Z", "createdAt": "2025-08-27T12:18:32.116Z", "updatedAt": "2025-08-27T15:26:04.053Z", "primaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 71000 } }, "startingPrimaryCreditBalance": { "value": 0 }, "startingPrimaryDebitBalance": { "value": 88000 }, "endingPrimaryCreditBalance": { "value": 0 }, "endingPrimaryDebitBalance": { "value": 71000 }, "secondaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 0 } }, "startingSecondaryCreditBalance": { "value": 0 }, "startingSecondaryDebitBalance": { "value": 0 }, "endingSecondaryCreditBalance": { "value": 0 }, "endingSecondaryDebitBalance": { "value": 0 } } } } }, "extensions": { "requestId": "569e6a0b-d14e-9a40-85c6-6f4a1e038883", "rateLimit": { "cost": 32, "limit": 60060, "remaining": 60028, "asOf": "2025-08-27T15:30:47.262Z", "complexity": { "limit": 60060, "remaining": 60028, "cost": 32 }, "count": { "limit": 60060, "remaining": 60059, "cost": 1 } } } } ### GraphQL: FindPrepaidStatementHistory Query: fragment statement on ConsumerPrepaidCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt createdAt updatedAt primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value } startingPrimaryDebitBalance { value } endingPrimaryCreditBalance { value } endingPrimaryDebitBalance { value } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } } query FindFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id createdAt statements(first: 10) { edges { node { ...statement } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "createdAt": "2025-08-27T12:12:03.733Z", "statements": { "edges": [ { "node": { "id": "", "__typename": "ConsumerPrepaidCardFinancialAccountStatement", "periodStart": "2025-08-27T12:19:48.368Z", "periodEnd": "2025-08-27T15:25:08.395Z", "openedAt": "2025-08-27T12:23:09.790Z", "closedAt": "2025-08-27T15:26:03.368Z", "createdAt": "2025-08-27T12:18:32.116Z", "updatedAt": "2025-08-27T15:26:04.053Z", "primaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 71000 } }, "startingPrimaryCreditBalance": { "value": 0 }, "startingPrimaryDebitBalance": { "value": 88000 }, "endingPrimaryCreditBalance": { "value": 0 }, "endingPrimaryDebitBalance": { "value": 71000 }, "secondaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 0 } }, "startingSecondaryCreditBalance": { "value": 0 }, "startingSecondaryDebitBalance": { "value": 0 }, "endingSecondaryCreditBalance": { "value": 0 }, "endingSecondaryDebitBalance": { "value": 0 } }, "cursor": "cursor_value" } ], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "start_cursor", "endCursor": "end_cursor" } } } } } ### GraphQL: LookupStatement Query: fragment statement on ConsumerPrepaidCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt periodPurchasesAmount { value } periodRefundsAndPaymentsAmount { value } primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } statementEntries(first: 20, filterBy: $filterBy) { edges { node { __typename postDate creditAmount { value } debitAmount { value } primaryCreditBalance { value } primaryDebitBalance { value } ledgerEntry { ...ledgerEntry } } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } } fragment ledgerEntry on LedgerEntry { __typename id memo creditBalanceAtLedgerEntry { value currencyCode } debitBalanceAtLedgerEntry { value currencyCode } amount { value currencyCode } financialEvent { ... on Node { id } ... on ClearingEvent { id approvedAmount { value currencyCode } } ... on FeeTransferEvent { id feeTransfer { __typename ... on ChargedFeeTransfer { feeActivityType feeAmount { value currencyCode } } ... on ReversedFeeTransfer { feeTransferAmount { value currencyCode } } } } } } query LookupStatement( $id: ID! $filterBy: FinancialAccountStatementEntriesFilterInput ) { node(id: $id) { ...statement } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "__typename": "ConsumerPrepaidCardFinancialAccountStatement", "periodStart": "2025-08-27T12:19:48.368Z", "periodEnd": "2025-08-27T15:25:08.395Z", "openedAt": "2025-08-27T12:23:09.790Z", "closedAt": "2025-08-27T15:26:03.368Z", "periodPurchasesAmount": { "value": 19500 }, "periodRefundsAndPaymentsAmount": { "value": 2500 }, "primaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 71000 } }, "startingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 88000, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 71000, "currencyCode": "USD" }, "secondaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 0 } }, "startingSecondaryCreditBalance": { "value": 0 }, "startingSecondaryDebitBalance": { "value": 0 }, "endingSecondaryCreditBalance": { "value": 0 }, "endingSecondaryDebitBalance": { "value": 0 }, "statementEntries": { "edges": [], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": null, "endCursor": null } } } } } ### GraphQL: FilterPrepaidStatementEntries Query: fragment statement on ConsumerPrepaidCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt periodPurchasesAmount { value } periodRefundsAndPaymentsAmount { value } primaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } secondaryLedger { id name normalBalance creditBalance { value } debitBalance { value } } startingSecondaryCreditBalance { value } startingSecondaryDebitBalance { value } endingSecondaryCreditBalance { value } endingSecondaryDebitBalance { value } statementEntries(first: 20, filterBy: $filterBy) { edges { node { __typename postDate creditAmount { value } debitAmount { value } primaryCreditBalance { value } primaryDebitBalance { value } ledgerEntry { ...ledgerEntry } } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } } fragment ledgerEntry on LedgerEntry { __typename id memo creditBalanceAtLedgerEntry { value currencyCode } debitBalanceAtLedgerEntry { value currencyCode } amount { value currencyCode } financialEvent { ... on Node { id } ... on ClearingEvent { id approvedAmount { value currencyCode } } ... on FeeTransferEvent { id feeTransfer { __typename ... on ChargedFeeTransfer { feeActivityType feeAmount { value currencyCode } } ... on ReversedFeeTransfer { feeTransferAmount { value currencyCode } } } } } } query LookupStatement( $id: ID! $filterBy: FinancialAccountStatementEntriesFilterInput ) { node(id: $id) { ...statement } } Variables: { "id": "", "filterBy": { "postDate": { "lessThan": "2026-06-07T22:21:50.108Z" }, "isCredit": { "equals": true } } } Expected Result: { "data": { "node": { "id": "", "__typename": "ConsumerPrepaidCardFinancialAccountStatement", "periodStart": "2025-08-27T12:19:48.368Z", "periodEnd": "2025-08-27T15:25:08.395Z", "openedAt": "2025-08-27T12:23:09.790Z", "closedAt": "2025-08-27T15:26:03.368Z", "periodPurchasesAmount": { "value": 19500 }, "periodRefundsAndPaymentsAmount": { "value": 2500 }, "primaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 71000 } }, "startingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 88000, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 71000, "currencyCode": "USD" }, "secondaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 0 }, "debitBalance": { "value": 0 } }, "startingSecondaryCreditBalance": { "value": 0 }, "startingSecondaryDebitBalance": { "value": 0 }, "endingSecondaryCreditBalance": { "value": 0 }, "endingSecondaryDebitBalance": { "value": 0 }, "statementEntries": { "edges": [], "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": null, "endCursor": null } } } } } ### GraphQL: SimulateShiftCurrentStatementPeriod Query: fragment statement on ConsumerPrepaidCardFinancialAccountStatement { id periodEnd } mutation SimulateShiftCurrentStatementPeriod( $input: SimulateShiftCurrentFinancialAccountStatementPeriodInput! ) { simulateShiftCurrentFinancialAccountStatementPeriod(input: $input) { __typename ... on FinancialAccount { id statementSnapshot { ... on ConsumerPrepaidCardFinancialAccountStatementSnapshot { __typename asOf currentOpenStatement { ...statement } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "financialAccountId": "", "periodBoundary": "2025-08-05T00:43:26.96" } } Expected Result: { "data": { "simulateShiftCurrentFinancialAccountStatementPeriod": { "__typename": "FinancialAccount", "id": "", "statementSnapshot": { "__typename": "ConsumerPrepaidCardFinancialAccountStatementSnapshot", "asOf": "2025-08-27T15:24:03.557Z", "currentOpenStatement": { "id": "", "periodEnd": "2025-08-27T15:25:08.395Z" } } } } } ### GraphQL: SimulateRolloverCurrentStatementPeriod Query: fragment statement on ConsumerPrepaidCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt primaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } secondaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingSecondaryCreditBalance { value currencyCode } startingSecondaryDebitBalance { value currencyCode } endingSecondaryCreditBalance { value currencyCode } endingSecondaryDebitBalance { value currencyCode } } mutation SimulateRolloverCurrentStatementPeriod( $input: SimulateRolloverCurrentFinancialAccountStatementPeriodInput! ) { simulateRolloverCurrentFinancialAccountStatementPeriod(input: $input) { __typename ... on FinancialAccount { id statementSnapshot { ... on ConsumerPrepaidCardFinancialAccountStatementSnapshot { __typename asOf latestClosedStatement { ...statement } } } } ... on UserError { errors { errorPath code } } } } Variables: { "input": { "financialAccountId": "" } } Expected Result: { "data": { "simulateRolloverCurrentFinancialAccountStatementPeriod": { "__typename": "FinancialAccount", "id": "", "statementSnapshot": { "__typename": "ConsumerPrepaidCardFinancialAccountStatementSnapshot", "asOf": "2025-08-27T15:26:04.095Z", "latestClosedStatement": { "id": "", "__typename": "ConsumerPrepaidCardFinancialAccountStatement", "periodStart": "2025-08-27T12:19:48.368Z", "periodEnd": "2025-08-27T15:25:08.395Z", "openedAt": "2025-08-27T12:23:09.790Z", "closedAt": "2025-08-27T15:26:03.368Z", "primaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a003", "name": "CASH", "normalBalance": "DEBIT", "creditBalance": { "value": 0, "currencyCode": "USD" }, "debitBalance": { "value": 71000, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 88000, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 71000, "currencyCode": "USD" }, "secondaryLedger": { "id": "ac_c02215bf2edade754e0586df0cc407f2285f_a030", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 0, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingSecondaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" } } } } } } --- URL: https://docs.highnote.com/docs/issuing/flexible-credential/about-flex-creds Title: About Flexible Credentials Section: Issuing Description: How Flexible Credential works: one card the cardholder carries, backed by a primary and a secondary credential, and how selection, spend rules, and reissue behave. ## What is Flexible Credential? A **credential** is the pairing of a and a . A **flexible credential** holds both a primary and secondary credential. And cardholders carry the payment card for the primary credential. On your side of the API, each credential's , referred to as a **member card**, has its own Primary Account Number (PAN). Where the cardholder has one card, you have two cards and two accounts, all visible through the Highnote API and in the Dashboard. Cardholders use their payment card like any other, and at authorization, Highnote decides which credential funds the transaction. The cardholder never sees a secondary PAN. ## How it's structured A holds exactly one primary and, currently, exactly one secondary one. Provisioning more than one secondary credential fails validation. Each credential is represented as a with the fields: , , , and . ```text FlexibleCredential ├── FlexibleCredentialCard │ ├── paymentCard ← the PAN cardholders carry │ ├── defaultFinancialAccount ← e.g., debit │ ├── isPrimary: true │ └── createdAt └── FlexibleCredentialCard ├── paymentCard ├── defaultFinancialAccount ← e.g., revolving credit ├── isPrimary: false └── createdAt ``` A object also carries , , , , , and . The field has two values, and . The remaining fields reach the rest of the object: , , , , , and . Highnote issues both the primary and any secondary credential in a single [](/docs/issuing/flexible-credential/create-flex-creds) call. There is no operation to add a credential to an existing flexible credential. Secondary credentials are not for cardholder presentation. Highnote does not issue Digital Wallet Tokens (DWTs) for their member cards, and or reissue does not apply. A cardholder never holds a secondary PAN, so there is nothing for them to report lost or stolen. ## Credential selection The primary credential is always eligible to fund a transaction, and you can configure which secondary credentials do so. Highnote configures the order in which eligible credentials are attempted for your organization. **It settles the authorization on the first credential that approves it**. A credential that declines for any reason is passed over, and the next credential is attempted. This means that insufficient funds is not the only thing that triggers fallback. The reason can be a spend rule, a velocity control, or the card's own status. Highnote does not split or aggregate a single authorization across credentials, so whichever credential approves must cover the full amount on its own. Exactly one credential is debited or charged. The example below uses an order that attempts the secondary credential first and falls back to the primary. Your organization's configured order may differ. | Authorization | Secondary
(tried first) | Primary
(fallback) | Result | | ------------- | ---------------------------- | ----------------------- | ------------------------------------------------------------------------------------------- | | $35 | $40 | $60 | **Approved on secondary credential**. It approves the full amount. | | $50 | $40 | $60 | **Approved on primary credential**. The secondary declines, so Highnote falls back. | | $100 | $40 | $60 | **Declined.** Neither credential approves $100 on its own, and Highnote does not aggregate. | You can exercise this selection logic against your own configuration in the Test environment. See Simulate Flexible Credentials. ## Spend Rules and Velocity Controls Spend rules apply per credential. Because each credential has its own and , attaching a spend rule with [](/docs/issuing/spend-controls/spend-rules#attach-spend-rule-to-a-payment-card) or [](/docs/issuing/spend-controls/spend-rules#attach-spend-rule-to-a-financial-account) scopes it to that credential alone. A spend rule on a secondary credential redirects a purchase rather than blocking it. That credential declines, Highnote passes it over, and the purchase falls through to the next credential in your configured order. For example, where a debit primary is attempted after a credit secondary, a rule blocking grocery merchants on the secondary sends grocery purchases to the primary. Attaching at the card product level applies the rule to every credential instead. Velocity controls attach to either side of a credential — its with [](/docs/issuing/spend-controls/velocity-controls#attach-velocity-control-to-a-financial-account), or its member card with [](/docs/issuing/spend-controls/velocity-controls#attach-velocity-control-to-a-payment-card). Either way, the rule's , set when you create it, decides what its counters aggregate over. A rule attached to a credential's defaults to , which scopes it to that credential alone. Use when a cap should survive a member card reissue, or to share one cap across everything the account holder spends, including accounts outside this flexible credential. ## Transactions restricted to primary credential Some transactions are not eligible for credential selection. Rather than declining them, Highnote removes the secondary credentials from consideration and authorizes against the primary credential alone, following the card network's flexible credential rules. The primary still has to approve the transaction on its own. Two classes of transaction trigger this restriction: - **Installment transactions**, identified by the installment payment indicator or an installment point-of-sale environment. - **Transactions at merchant categories the network excludes from credential selection**, such as cash access and quasi-cash, money transfer, brokerage, collections, and automated fuel dispensers. The authoritative list is the card network's, not Highnote's. On Visa, for example, the eligible merchant categories are defined in the Visa flexible credential implementation guide. Contact your Visa representative for the current version. Plan for this when you choose which credential is primary. A fuel purchase at an automated dispenser, for example, is authorized against the primary credential even when a secondary credential would otherwise have been selected. ## Refunds, returns, credits, and reversals Highnote responds with the same credential used for the original purchase. When Highnote cannot identify the original credential the secondary credential is used. For example, a standalone credit that does not reference a prior purchase. ## Disputes Flexible credential transactions follow Highnote's standard Issuing dispute flow. Subscribers observe dispute lifecycle events on the underlying transaction. Highnote operates the dispute. ## Reissuing member cards Reissuing a member card () behaves as it does for any Highnote card: it maintains card lineage by reusing the network-level Payment Account Reference (PAR), and and decide whether the replacement reuses or recreates the PAN and PIN. Use to replace the member cards on a flexible credential. The reissue criteria and lost/stolen guidance in Manage Cards apply unchanged. In particular, do not reissue stolen cards, and close the card and issue a new one instead so the replacement starts a new lineage. The flexible credential must not be . What flexible credential adds is that member cards are replaced through one operation rather than card by card. states which of them the request covers, and has no default: | Scope | Behavior | | ------------------ | ---------------------------------------------------------------------------------------------- | | | Replaces every member card on one shared set of . Omit . | | | Replaces only the member cards named in , each free to override the shared . | **Prefer .** Reissuing the whole flexible credential on one set of options keeps its member cards in step, with one expiration date, one activation state, and one reissue reason. Once they diverge, expirations fall due separately and replacing a cardholder's card becomes several requests instead of one. Reach for only when a member card genuinely needs different treatment, such as replacing a single damaged physical card while the rest of the flexible credential stays in force. --- URL: https://docs.highnote.com/docs/issuing/flexible-credential/create-flex-creds Title: Create and Provision Flexible Credentials Section: Issuing Description: Create and provision a flexible credential from an approved Application, issuing the member cards for its primary and secondary credentials in one call. ## Overview This page explains how to create and provision a flexible credential and its member cards in a single call. has exactly two values, and . There is no observable state in which a credential exists but isn't yet provisioned. The mutation runs against an in the state and completes synchronously, so there is no polling step. A returned always represents a finished request. Failures surface as or in the payload union rather than as transport errors. ## Before you start You need the following: - An **application** in the state. The flexible credential's and its owning are both derived from that application, so you do not pass either one. Provisioning against an application in any other state fails with . - A **card profile set** for each credential you intend to issue. You need one card profile set for the primary, and one for the secondary. The card profile set does more than style the card; it determines the role each member card plays, and the role must match the backing account. A card profile set on a **debit or prepaid BIN** classifies as the primary, one on a **credit BIN** classifies as the secondary. Highnote currently supports exactly one secondary credential, and intends to relax that limit. is a list so the request shape does not have to change when it does, but sending more than one fails validation today. ## Describe the cards The field takes a single card slot and takes a list of them. Every slot needs the same three fields: | Field | Notes | | ------------------ | ---------------------------------------------------------------------------------------------------------------------- | | | The card profile set for this card. Also determines the card's role, and so which backs it. | | | Required on every slot, in ISO 8601 format. Flexible credential issuance has no product-level default to fall back on. | | | Whether this card is usable immediately. A card created inactive must be activated separately before it can be used. | Three behaviors are worth knowing before you build the request: - **Each slot's role must match its backing account.** Highnote derives a role from the slot's and rejects the request if a slot's role does not match the account it would back. You do not choose the pairing directly; the card profile set determines it: debit and prepaid BINs classify as primary, credit BINs as secondary. - **The array is required and non-null.** A credential issued with no secondary still has to send . - **The flag only holds back the card.** The backing and the parent flexible credential are always materialized active. Setting it per slot lets you issue a live primary alongside an inactive secondary. This is useful when a secondary credential is enabled only after the cardholder opts in. ## Provision the credential The example below issues a live debit primary alongside a live revolving credit secondary. The mutation returns the new , so you can select the card and account IDs in the same request instead of following up with a read. ## Name and external ID The field is required and holds a human-friendly label for the credential. The field is optional and is yours to supply for your own reconciliation. It must be unique per organization and tenant, and Highnote generates one if you omit it. ## Send an idempotency key Send a UUIDv4 with every request. Highnote processes only the first request carrying a given key and returns that original response to repeats for 24 hours. A retry after a timeout cannot issue a second set of cards. ## Handle failures Provisioning failures come back as in the payload union rather than as a transport error, so check before reading the credential. | Code | Meaning | | -------------------------- | ----------------------------------------------------------------------------- | | | The is not . Provisioning cannot proceed until it is. | | | A field failed validation, e.g., an that is not ISO 8601. | The locates the offending field, including its position in a list, so a bad expiration on the primary member card returns . Read it rather than parsing the description. ## Next steps The credential is active and its cards are issued. From here, find it and fetch what's attached to it using the returned ID, or exercise credential selection in the Test environment before you send live traffic. ### GraphQL: ProvisionFlexibleCredential Query: mutation ProvisionFlexibleCredential( $input: ProvisionFlexibleCredentialInput! ) { provisionFlexibleCredential(input: $input) { ... on FlexibleCredential { id name externalId status createdAt cards { isPrimary paymentCard { id last4 expirationDate } defaultFinancialAccount { id name } } } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "applicationId": "APPLICATION_ID", "name": "Cardholder Flexible Credential", "idempotencyKey": "IDEMPOTENCY_KEY", "primaryCard": { "cardProfileSetId": "CARD_PROFILE_SET_ID_DEBIT", "expirationDate": "2030-01-01T00:00:00Z", "activateOnCreate": true }, "secondaryCards": [ { "cardProfileSetId": "CARD_PROFILE_SET_ID_CREDIT", "expirationDate": "2030-06-01T00:00:00Z", "activateOnCreate": true } ] } } Expected Result: { "data": { "provisionFlexibleCredential": { "id": "FLEXIBLE_CREDENTIAL_ID", "name": "Cardholder Flexible Credential", "externalId": "EXTERNAL_ID", "status": "ACTIVE", "createdAt": "2026-04-01T15:30:00.000Z", "cards": [ { "isPrimary": true, "paymentCard": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242", "expirationDate": "2030-01-01T00:00:00.000Z" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_DEBIT", "name": "Debit Account" } }, { "isPrimary": false, "paymentCard": { "id": "PAYMENT_CARD_ID_SECONDARY", "last4": "1881", "expirationDate": "2030-06-01T00:00:00.000Z" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_CREDIT", "name": "Revolving Credit Account" } } ] } } } --- URL: https://docs.highnote.com/docs/issuing/flexible-credential/instant-credit Title: Activate Instant Credit Section: Issuing Description: Selectively enable the credit credential on a flexible credential for a bounded window, and control its available credit and how long it stays active. ## Overview Instant Credit turns on the credit credential of a flexible credential for a bounded window. Outside that window the credit credential is not eligible, and transactions run on the primary credential as usual. Activating Instant Credit sets three things: - **Whether the credit credential is on** — it becomes eligible for authorization. - **Its available credit** — how much it can spend. - **How long it stays on** — the activation window. The mutation is asynchronous. It returns an activation with status , and the credit credential becomes eligible once the activation reaches . Instant Credit governs whether the credit credential can spend and how much. It does not move money or settle a balance. Repayment is its own flow. ## How it works While Instant Credit is active, the credit credential is eligible for authorization for the window you set. It joins credential selection like any other eligible credential: Highnote attempts it in your organization's configured order and uses the first credential that approves the full amount. The credit credential is attempted whenever the activation window is open. If its available credit doesn't cover the amount, it declines and selection falls through to the next credential. When the window ends — by expiry or cancellation — the credit credential stops being eligible and drops out of selection on the next authorization. ## Before you start To activate Instant Credit, the flexible credential needs a **credit secondary credential** — a secondary credential issued on a **credit BIN** and backed by **JIT funding with a pseudo balance**. You set this up when you provision the flexible credential; there is nothing to activate without it. Highnote currently supports exactly one credit secondary per flexible credential. ## Activate Instant Credit Call with the credential's ID, the available-credit adjustment, and the window. The response is a carrying an and a . Failures surface as or in the response rather than as transport errors, so check before reading the activation. ### Set the available credit decides how is applied. is an — a in the currency's minor units and a required . is $50.00. | Mode | Effect | Window | | ----------- | ------------------------------------------------------ | -------------------------------------------------- | | | Replace the available credit with (absolute). | Requires . Opens or replaces the window. | | | Add to the current available credit. | Requires an already-active window. | Use to start a window, or to resize the credit and the window together. Use to top up the credit during a window that is already open. ### Set the window is a and a (, , , or ). The window runs from now to . - ** requires .** The new expiry is . - ** takes optionally.** Omit it to keep the current expiry, or provide one to extend the window. A shorter expiry is rejected — use to shorten. - ** cancels now.** The window closes immediately and the credit credential stops being eligible on the next authorization. ## Read the activation status The mutation returns immediately with status . Observe the outcome two ways. The activation's own : | Status | Meaning | | ---------- | ---------------------------------------------------------- | | | Accepted and in progress. | | | Finished. The credit credential is enabled for the window. | | | The activation did not take effect. | And the current strategy on the flexible credential. Read and filter on . An with and an in the future means the credit credential is currently enabled. ## Change or cancel a window While a window is open, you can act on it without waiting for it to expire: | Goal | Call | | ---------------------------- | ------------------------------------------------------------ | | Add available credit | with a positive , no . | | Extend the window | with a later than the current expiry. | | Add credit and extend | with a positive and a later . | | Replace credit and/or window | with the new and . | | Cancel now | . | A window you do nothing to simply expires at . ## Send an idempotency key Send a UUIDv4 with every request. Highnote processes only the first request carrying a given key and returns that original response to repeats for up to 24 hours. Retry a timed-out request with the **same** key — a new key can start a second activation. A second activation on a credential whose activation is still in progress is rejected with . Retry once the first reaches a terminal status. ## Handle failures Recoverable failures come back as in the response — check , then read each error's and human-readable . | Code | Meaning | | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | | was sent without a . | | | was sent with no window open. | | | An would end the window earlier than it does now. Use to shorten. | | | with and no — nothing to do. | | / | is negative. | | | Another activation on this credential is still in progress. | A transient service error does not return a ; the mutation returns no activation. Retry with the same . An activation that starts and then fails reaches rather than returning a synchronous error. ## Next steps - Review how the credit credential participates once enabled in Credential selection. - Confirm the behavior against a live window with Simulate Flexible Credentials. - Scope what the credit credential can buy with spend rules and velocity controls. ### GraphQL: ActivateFlexibleCredentialInstantCredit Query: mutation ActivateFlexibleCredentialInstantCredit( $input: ActivateFlexibleCredentialInstantCreditInput! ) { activateFlexibleCredentialInstantCredit(input: $input) { __typename ... on FlexibleCredentialInstantCreditActivation { id status flexibleCredential { id strategies { __typename id status effectiveFrom effectiveThrough } } } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "flexibleCredentialId": "FLEXIBLE_CREDENTIAL_ID", "availableCredit": { "mode": "SET", "amount": { "value": 5000, "currencyCode": "USD" } }, "duration": { "value": 1, "units": "DAYS" }, "idempotencyKey": "00000000-0000-4000-8000-000000000000" } } Expected Result: { "data": { "activateFlexibleCredentialInstantCredit": { "__typename": "FlexibleCredentialInstantCreditActivation", "id": "INSTANT_CREDIT_ACTIVATION_ID", "status": "PENDING", "flexibleCredential": { "id": "FLEXIBLE_CREDENTIAL_ID", "strategies": null } } } } ### GraphQL: FlexibleCredentialStrategies Query: query FlexibleCredentialStrategies($id: ID!) { node(id: $id) { ... on FlexibleCredential { id strategies { __typename id status effectiveFrom effectiveThrough } } } } Variables: { "id": "FLEXIBLE_CREDENTIAL_ID" } Expected Result: { "data": { "node": { "id": "FLEXIBLE_CREDENTIAL_ID", "strategies": [ { "__typename": "InstantCreditFlexibleCredentialStrategy", "id": "INSTANT_CREDIT_STRATEGY_ID", "status": "ACTIVE", "effectiveFrom": "2026-04-01T15:30:00.000Z", "effectiveThrough": "2026-04-02T15:30:00.000Z" } ] } } } --- URL: https://docs.highnote.com/docs/issuing/flexible-credential/query-flex-creds Title: Find and Fetch Flexible Credentials Section: Issuing Description: Find a flexible credential from its own ID, a card, a financial account, or an account holder, then fetch the activity and statements attached to it. ## Overview This page explains how to read a flexible credential and everything attached to it, including member cards, activity, statements, and the events that record which credentials a transaction tried. There is no root query for , so every read starts from an ID you already have. First find the credential from its own ID, a , a , or an account holder. Then fetch the activity and statements attached to it. Transactions carry their own record of which credentials were tried, so that read starts from the transaction instead. Resolve the credential through with an inline fragment, or follow the reverse pointer from a card or account. For the object model, see How it's structured. The connections on this page paginate on different objects, which changes how cursors behave. See Pagination. ## Find a credential Each starting point reaches the credential through a different field. and each carry a reverse pointer, which resolves to when that card or account is not part of one. Refer to the examples just below. | Starting from ID | Use node(id) on | Resulting field | | ------------------------------------------------------------------------------------ | ----------------------- | ------------------------------ | | ID | | | | ID | | or | | ID | | or | | , , , or ID | | |
From a Flexible Credential ID ```graphql query FlexibleCredentialById($id: ID!) { node(id: $id) { ... on FlexibleCredential { id status } } } ``` Full query and response: Find a credential by ID.
From a Payment Card ID ```graphql query FlexibleCredentialFromPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { flexibleCredential { id } } } } ``` Returns when the card is not part of a flexible credential. Full query and response: Find the credential for a card.
From a Financial Account ID ```graphql query FlexibleCredentialFromFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { flexibleCredential { id } } } } ``` Returns when the account does not back a member card. Full query and response: Find the credential for a financial account.
From an account holder ID ```graphql query FlexibleCredentialsForAccountHolder($id: ID!) { node(id: $id) { ... on USPersonAccountHolder { flexibleCredentials(first: 20) { edges { node { id } } pageInfo { hasNextPage endCursor } } } } } ``` Full query and response: Find credentials for an account holder.
### Find a credential by ID You can fetch a and unpack every member card on it, including the primary. ### Find the credential for a card Given a ID, you can resolve its parent and list every sibling card on the credential. The result is when the card is not part of a flexible credential. ### Find the credential for a financial account Given a ID, you can resolve the whose member card it backs, along with every card on that credential. The result is when the account does not back a member card. ### Find credentials for an account holder To find credentials for any account holder, the connection is exposed on , , , and . The page size is bounded by Highnote's standard pagination limit (1 to 20 items per page). ## Fetch what the credential holds Once you have the credential, you can retrieve the activity and statements of its member accounts. ### Fetch activity across a credential answers what is happening across the credential now. It returns the activity of every member financial account as a single, chronologically ordered feed, so you do not have to fetch each member account's activity separately and interleave the results yourself. Each row carries , which attributes it to the account it came from. This connection is aggregated at the flexible credential, so its cursors span the whole feed and pages through every member account together. ### Fetch statements across a credential returns the closed statements across a credential's member accounts as a single paginated feed, so you do not have to fetch each member account's statements separately and combine them yourself. Each row carries , which attributes the statement to the account it belongs to. Only closed statements appear in this feed, and only from member accounts that produce them — a debit-backed member account has none, so it never contributes a row. To read the current open statement for a member account, follow on that . Statements from different accounts can interleave, so do not rely on the feed being grouped or ordered by statement period. Narrow the feed to a date range with . The on each row is a , so its concrete type depends on the member account it came from. Read the fields common to every statement directly, and use an inline fragment such as for the fields specific to one account type. only reads statements that already exist. Generating a statement, billing cycles and payment due dates, statement entries, and simulating a cycle roll are documented per financial account, and apply to each member account of a credential. See Deliver Revolving Consumer Credit Statements for a credit member account and Deliver Prepaid Statements for a prepaid one, including the full field set for each statement type. This connection is aggregated at the flexible credential, so its cursors span the whole feed and pages through every member account together. ## Trace a transaction's routing This read starts from a transaction rather than a credential. ### Find attempt events on a transaction Highnote records a on the transaction for each credential that is tried and declines. Every transaction also carries exactly one , which holds the final outcome on the last credential tried, whether that credential approved or declined. This is how you reconstruct, after the fact, which credentials were tried and how each one responded. A credential that is never tried produces no attempt event. Transactions restricted to the primary credential drop the secondaries before selection runs, and a card verification failure skips selection entirely. Filter a transaction's events with to read them. Requesting in the same call gives you the full picture: every credential that declined, plus the final outcome. The object identifies which credential the attempt ran against, and gives the decline reason. When a spend rule caused the fallback, names the rule that produced it. It is the observable counterpart to credential selection, where a decline for any reason moves to the next credential. Attempt events do not settle. They share the approved event's transaction, so they show up as part of that transaction's history rather than as transactions of their own. ## Pagination The three connections on this page paginate on different objects. | Connection | Paginates on | A cursor is valid for | | ------------------------------ | ----------------------- | -------------------------- | | | the account holder | that account holder's list | | | the flexible credential | the whole combined feed | | | the flexible credential | the whole combined feed | The mechanics are the same in every case. Request up to 20 items with , pass the previous page's as , and check to know when to stop. What differs is the scope of the cursor, which is why a cursor from one account holder's list cannot be used against a credential's combined feed. ### GraphQL: FlexibleCredentialByNode Query: query FlexibleCredentialByNode($id: ID!) { node(id: $id) { ... on FlexibleCredential { id externalId name status createdAt updatedAt primaryPaymentCard { id last4 } cards { isPrimary paymentCard { id last4 } defaultFinancialAccount { id name } } accountHolder { ... on USPersonAccountHolder { id } ... on USBusinessAccountHolder { id } ... on Business { id } ... on Organization { id } } cardProduct { id name } } } } Variables: { "id": "FLEXIBLE_CREDENTIAL_ID" } Expected Result: { "data": { "node": { "id": "FLEXIBLE_CREDENTIAL_ID", "externalId": "EXTERNAL_ID", "name": "Cardholder Flexible Credential", "status": "ACTIVE", "createdAt": "2026-04-01T15:30:00.000Z", "updatedAt": "2026-04-01T15:30:00.000Z", "primaryPaymentCard": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242" }, "cards": [ { "isPrimary": true, "paymentCard": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_DEBIT", "name": "Debit Account" } }, { "isPrimary": false, "paymentCard": { "id": "PAYMENT_CARD_ID_SECONDARY", "last4": "1881" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_CREDIT", "name": "Revolving Credit Account" } } ], "accountHolder": { "id": "ACCOUNT_HOLDER_ID" }, "cardProduct": { "id": "CARD_PRODUCT_ID", "name": "Flexible Credential Card Product" } } } } ### GraphQL: FlexibleCredentialFromPaymentCard Query: query FlexibleCredentialFromPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { id last4 flexibleCredential { id status cards { isPrimary paymentCard { id last4 } defaultFinancialAccount { id name } } } } } } Variables: { "id": "PAYMENT_CARD_ID_PRIMARY" } Expected Result: { "data": { "node": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242", "flexibleCredential": { "id": "FLEXIBLE_CREDENTIAL_ID", "status": "ACTIVE", "cards": [ { "isPrimary": true, "paymentCard": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_DEBIT", "name": "Debit Account" } }, { "isPrimary": false, "paymentCard": { "id": "PAYMENT_CARD_ID_SECONDARY", "last4": "1881" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_CREDIT", "name": "Revolving Credit Account" } } ] } } } } ### GraphQL: FlexibleCredentialFromFinancialAccount Query: query FlexibleCredentialFromFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id name flexibleCredential { id status cards { isPrimary paymentCard { id last4 } defaultFinancialAccount { id name } } } } } } Variables: { "id": "FINANCIAL_ACCOUNT_ID_DEBIT" } Expected Result: { "data": { "node": { "id": "FINANCIAL_ACCOUNT_ID_DEBIT", "name": "Debit Account", "flexibleCredential": { "id": "FLEXIBLE_CREDENTIAL_ID", "status": "ACTIVE", "cards": [ { "isPrimary": true, "paymentCard": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_DEBIT", "name": "Debit Account" } }, { "isPrimary": false, "paymentCard": { "id": "PAYMENT_CARD_ID_SECONDARY", "last4": "1881" }, "defaultFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_CREDIT", "name": "Revolving Credit Account" } } ] } } } } ### GraphQL: FlexibleCredentialsForAccountHolder Query: query FlexibleCredentialsForAccountHolder( $id: ID! $first: Int! = 20 $after: String ) { node(id: $id) { ... on USPersonAccountHolder { id flexibleCredentials(first: $first, after: $after) { edges { cursor node { id name status primaryPaymentCard { id last4 } } } pageInfo { hasNextPage endCursor startCursor } } } } } Variables: { "id": "US_PERSON_ACCOUNT_HOLDER_ID", "first": 20 } Expected Result: { "data": { "node": { "id": "US_PERSON_ACCOUNT_HOLDER_ID", "flexibleCredentials": { "edges": [ { "cursor": "CURSOR_1", "node": { "id": "FLEXIBLE_CREDENTIAL_ID", "name": "Cardholder Flexible Credential", "status": "ACTIVE", "primaryPaymentCard": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242" } } } ], "pageInfo": { "hasNextPage": false, "endCursor": "CURSOR_1", "startCursor": "CURSOR_1" } } } } } ### GraphQL: FlexibleCredentialActivities Query: query FlexibleCredentialActivities( $id: ID! $first: Int! = 20 $after: String ) { node(id: $id) { ... on FlexibleCredential { id flexibleCredentialActivities(first: $first, after: $after) { edges { cursor node { sourceFinancialAccount { id name } activity { createdAt sign isComplete pendingAmount { value currencyCode } postedAmount { value currencyCode } } } } pageInfo { hasNextPage endCursor } } } } } Variables: { "id": "FLEXIBLE_CREDENTIAL_ID", "first": 20 } Expected Result: { "data": { "node": { "id": "FLEXIBLE_CREDENTIAL_ID", "flexibleCredentialActivities": { "edges": [ { "cursor": "CURSOR_1", "node": { "sourceFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_CREDIT", "name": "Revolving Credit Account" }, "activity": { "createdAt": "2026-04-01T15:30:00.000Z", "sign": "NEGATIVE", "isComplete": false, "pendingAmount": { "value": 3500, "currencyCode": "USD" }, "postedAmount": null } } }, { "cursor": "CURSOR_2", "node": { "sourceFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_DEBIT", "name": "Debit Account" }, "activity": { "createdAt": "2026-03-30T09:12:00.000Z", "sign": "NEGATIVE", "isComplete": true, "pendingAmount": null, "postedAmount": { "value": 1250, "currencyCode": "USD" } } } } ], "pageInfo": { "hasNextPage": false, "endCursor": "CURSOR_2" } } } } } ### GraphQL: FlexibleCredentialStatements Query: query FlexibleCredentialStatements( $id: ID! $first: Int! = 20 $after: String $filterBy: FinancialAccountStatementFilterInput ) { node(id: $id) { ... on FlexibleCredential { id flexibleCredentialStatements( first: $first after: $after filterBy: $filterBy ) { edges { cursor node { sourceFinancialAccount { id name } statement { id __typename periodStart periodEnd closedAt endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } ... on ConsumerRevolvingCardFinancialAccountStatement { paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } } } } } pageInfo { hasNextPage endCursor } } } } } Variables: { "id": "FLEXIBLE_CREDENTIAL_ID", "first": 20, "filterBy": { "periodEnd": { "greaterThan": "2026-03-01T00:00:00.000Z", "lessThan": "2026-05-01T00:00:00.000Z" } } } Expected Result: { "data": { "node": { "id": "FLEXIBLE_CREDENTIAL_ID", "flexibleCredentialStatements": { "edges": [ { "cursor": "CURSOR_1", "node": { "sourceFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_CREDIT", "name": "Revolving Credit Account" }, "statement": { "id": "STATEMENT_ID_CREDIT", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2026-04-01T05:00:00.000Z", "periodEnd": "2026-04-30T05:00:00.000Z", "closedAt": "2026-05-01T07:00:00.000Z", "endingPrimaryCreditBalance": { "value": 42500, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "paymentDueOn": "2026-05-25T05:00:00.000Z", "pastDueAmount": { "value": 0, "currencyCode": "USD" }, "periodMinimumPaymentDue": { "value": 3500, "currencyCode": "USD" } } } }, { "cursor": "CURSOR_2", "node": { "sourceFinancialAccount": { "id": "FINANCIAL_ACCOUNT_ID_PREPAID", "name": "Prepaid Account" }, "statement": { "id": "STATEMENT_ID_PREPAID", "__typename": "ConsumerPrepaidCardFinancialAccountStatement", "periodStart": "2026-03-01T05:00:00.000Z", "periodEnd": "2026-03-31T05:00:00.000Z", "closedAt": "2026-04-01T07:00:00.000Z", "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 12500, "currencyCode": "USD" } } } } ], "pageInfo": { "hasNextPage": false, "endCursor": "CURSOR_2" } } } } } ### GraphQL: FlexibleCredentialAttempts Query: query FlexibleCredentialAttempts($id: ID!) { node(id: $id) { ... on DebitTransaction { id transactionEvents( eventTypes: [FLEXIBLE_CREDENTIAL_ATTEMPT_EVENT, AUTHORIZATION_EVENT] ) { __typename ... on FlexibleCredentialAttemptEvent { id createdAt responseCode requestedAmount { value currencyCode } paymentCard { id last4 } spendRuleResults(first: 20) { edges { node { recommendation message attachedLevel } } } } ... on AuthorizationEvent { id createdAt responseCode approvedAmount { value currencyCode } paymentCard { id last4 } } } } } } Variables: { "id": "DEBIT_TRANSACTION_ID" } Expected Result: { "data": { "node": { "id": "DEBIT_TRANSACTION_ID", "transactionEvents": [ { "__typename": "FlexibleCredentialAttemptEvent", "id": "FLEXIBLE_CREDENTIAL_ATTEMPT_EVENT_ID", "createdAt": "2026-04-01T15:30:00.000Z", "responseCode": "DO_NOT_HONOR", "requestedAmount": { "value": 3500, "currencyCode": "USD" }, "paymentCard": { "id": "PAYMENT_CARD_ID_SECONDARY", "last4": "1881" }, "spendRuleResults": { "edges": [ { "node": { "recommendation": "BLOCK", "message": "Merchant category not permitted on this account", "attachedLevel": "ACCOUNT" } } ] } }, { "__typename": "AuthorizationEvent", "id": "AUTHORIZATION_EVENT_ID", "createdAt": "2026-04-01T15:30:00.100Z", "responseCode": "APPROVED", "approvedAmount": { "value": 3500, "currencyCode": "USD" }, "paymentCard": { "id": "PAYMENT_CARD_ID_PRIMARY", "last4": "4242" } } ] } } } --- URL: https://docs.highnote.com/docs/issuing/flexible-credential/sim-flex-creds Title: Simulate Flexible Credentials Section: Issuing Description: Simulate card and digital wallet token authorizations in the Test environment to exercise credential selection before you send live traffic. ## Overview This page explains how to simulate an authorization against a flexible credential in the Test environment, so you can see which credential funds a transaction before you send live traffic. Two mutations do this, one for a card and one for a digital wallet token. Both run the same credential-selection logic Highnote applies in production and return the same union as a real authorization — , , or . ## Prerequisites - A Highnote account - An API key or the API Explorer - A provisioned flexible credential and the ID of its primary member card - A digital wallet token on that primary member card, to simulate the digital wallet token flow ## Simulate a card authorization Use to simulate an authorization against a flexible credential. For an authorization driven by a digital wallet token, use Simulate a digital wallet token authorization instead. Pass the ID of the primary member card as . The input is ; only and are required. The secondary credential is not always eligible. A credit secondary enters credential selection only while its Instant Credit strategy is enabled and the activation window is open. Even then it approves only if its available credit covers the full amount; otherwise it declines and selection falls through to the next credential. Outside the window it drops out of selection and the authorization runs on the primary credential. Both examples below assume an enabled strategy inside an open window, and an order that attempts the secondary credential before the primary. Highnote configures that order for your organization, so yours may differ. See Credential selection. ### Approved on the secondary credential A $35 authorization against a credential whose credit secondary has $40 of available credit. The secondary is attempted first, approves the full amount, and the transaction settles there. ### Declined on every credential A $100 authorization with $40 of available credit on the credit secondary and $60 on the debit primary. The secondary is attempted first and declines, and so does the primary on fallback. Highnote does not aggregate across credentials, so the transaction declines. ## Simulate a digital wallet token authorization Use to simulate an authorization driven by a digital wallet token. The required input is , the ID of a whose underlying is the primary member card of a flexible credential. The token resolves to the primary member card and routing proceeds from there. Highnote does not issue digital wallet tokens for the member cards of secondary credentials. ## What simulators prove about your integration The simulators run the same credential-selection routing logic as production authorizations. Successful runs in the Test environment exercise the following: - **Credential eligibility.** A credit secondary is attempted only while its Instant Credit window is open, and it approves only if its available credit covers the full amount. - **Credential-selection order.** Highnote attempts eligible credentials in the order configured for your organization, and settles on the first one that approves. - **Mutually exclusive routing.** Each transaction debits or charges exactly one credential. - **Primary-credential restriction.** Installment transactions and transactions at restricted merchant categories authorize against the primary credential instead of entering credential selection. See Transactions restricted to primary credential. Treat the simulator decline reasons as the contract for production decline reasons. The simulators do not, however, exercise downstream settlement, clearing, or chargeback flows. Those follow the standard Issuing transaction lifecycle and are out of scope for these mutations. ## Automate your integration To automate your integration, subscribe to the following notification events: - Payment card authorization approved - Payment card authorization declined - Payment card cleared The details provided in the payloads from these events can be used for the following use cases: - Automate your application or website's transaction processing workflows - Create account holder notifications and alerts - Reconcile which credential funded each transaction ### GraphQL: SimulateFlexibleCredentialAuthorization Query: mutation SimulateFlexibleCredentialAuthorization( $input: SimulateFlexibleCredentialAuthorizationInput! ) { simulateFlexibleCredentialAuthorization(input: $input) { __typename ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode approvedAmount { value currencyCode } merchantDetails { countryCodeAlpha3 category name description } pointOfServiceDetails { terminalSupportsPartialApproval } createdAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 3500, "currencyCode": "USD" }, "cardId": "PAYMENT_CARD_ID_PRIMARY", "merchantDetails": { "name": "HIGHNOTE_PLATFORM", "description": "FLEXIBLE_CREDENTIAL_SINGLE_SOURCE", "category": "GENERAL_SERVICES", "countryCodeAlpha3": "USA" }, "pointOfServiceDetails": { "terminalSupportsPartialApproval": true } } } Expected Result: { "data": { "simulateFlexibleCredentialAuthorization": { "__typename": "AuthorizationEvent", "id": "TRANSACTION_EVENT_ID", "transaction": { "id": "TRANSACTION_ID" }, "responseCode": "APPROVED", "approvedAmount": { "value": 3500, "currencyCode": "USD" }, "merchantDetails": { "countryCodeAlpha3": "USA", "category": "GENERAL_SERVICES", "name": "HIGHNOTE_PLATFORM", "description": "FLEXIBLE_CREDENTIAL_SINGLE_SOURCE" }, "pointOfServiceDetails": { "terminalSupportsPartialApproval": true }, "createdAt": "2026-04-01T15:30:00.000Z" } } } ### GraphQL: SimulateFlexibleCredentialAuthorization Query: mutation SimulateFlexibleCredentialAuthorization( $input: SimulateFlexibleCredentialAuthorizationInput! ) { simulateFlexibleCredentialAuthorization(input: $input) { __typename ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode approvedAmount { value currencyCode } merchantDetails { countryCodeAlpha3 category name description } pointOfServiceDetails { terminalSupportsPartialApproval } createdAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 10000, "currencyCode": "USD" }, "cardId": "PAYMENT_CARD_ID_PRIMARY", "merchantDetails": { "name": "HIGHNOTE_PLATFORM", "description": "FLEXIBLE_CREDENTIAL_AGGREGATE_NEED", "category": "GENERAL_SERVICES", "countryCodeAlpha3": "USA" }, "pointOfServiceDetails": { "terminalSupportsPartialApproval": true } } } Expected Result: { "data": { "simulateFlexibleCredentialAuthorization": { "__typename": "AuthorizationEvent", "id": "TRANSACTION_EVENT_ID", "transaction": { "id": "TRANSACTION_ID" }, "responseCode": "INSUFFICIENT_FUNDS", "approvedAmount": { "value": 0, "currencyCode": "USD" }, "merchantDetails": { "countryCodeAlpha3": "USA", "category": "GENERAL_SERVICES", "name": "HIGHNOTE_PLATFORM", "description": "FLEXIBLE_CREDENTIAL_AGGREGATE_NEED" }, "pointOfServiceDetails": { "terminalSupportsPartialApproval": true }, "createdAt": "2026-04-01T15:30:00.000Z" } } } ### GraphQL: SimulateDigitalWalletTokenFlexibleCredentialAuthorization Query: mutation SimulateDigitalWalletTokenFlexibleCredentialAuthorization( $input: SimulateDigitalWalletTokenFlexibleCredentialAuthorizationInput! ) { simulateDigitalWalletTokenFlexibleCredentialAuthorization(input: $input) { __typename ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode approvedAmount { value currencyCode } merchantDetails { countryCodeAlpha3 category name description } pointOfServiceDetails { terminalSupportsPartialApproval } createdAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 3500, "currencyCode": "USD" }, "cardDigitalWalletTokenId": "CARD_DIGITAL_WALLET_TOKEN_ID", "merchantDetails": { "name": "HIGHNOTE_PLATFORM", "description": "FLEXIBLE_CREDENTIAL_DWT", "category": "GENERAL_SERVICES", "countryCodeAlpha3": "USA" }, "pointOfServiceDetails": { "terminalSupportsPartialApproval": true } } } Expected Result: { "data": { "simulateDigitalWalletTokenFlexibleCredentialAuthorization": { "__typename": "AuthorizationEvent", "id": "TRANSACTION_EVENT_ID", "transaction": { "id": "TRANSACTION_ID" }, "responseCode": "APPROVED", "approvedAmount": { "value": 3500, "currencyCode": "USD" }, "merchantDetails": { "countryCodeAlpha3": "USA", "category": "GENERAL_SERVICES", "name": "HIGHNOTE_PLATFORM", "description": "FLEXIBLE_CREDENTIAL_DWT" }, "pointOfServiceDetails": { "terminalSupportsPartialApproval": true }, "createdAt": "2026-04-01T15:30:00.000Z" } } } --- URL: https://docs.highnote.com/docs/issuing/reporting/about-reporting Title: About Highnote Reporting Section: Issuing Description: List, retrieve, and download pre-built reports for your card program through the Highnote API. Covers report types, usage limits, status tracking, and authentication. ## Overview _New columns_ may be introduced to existing reports as business or processing requirements evolve. _Existing columns_ will not be removed or renamed without appropriate communication. Subscribers are expected to design their data ingestion pipelines to tolerate the presence of new, previously undocumented fields. Implementations that rely on fixed column positions, strict column counts, or fail on unrecognized fields are not supported. **These additions are considered non-breaking changes. We recommend consuming report data by column name rather than ordinal position.** Highnote provides on-demand reports that empower you with data to drive your critical business decisions. This guide is provides on overview on using the Highnote GraphQL API to list and generate reports, check report statuses, and download reports. ## List report usage You can generate up to three reports per day. The allowance resets daily at 12 AM Eastern Time (ET). Use the query to retrieve the following data: - : Displays the type of report - : Displays your report usage limit; the default daily limit is three. - : Displays how many reports are remaining from your usage limit; for example, if you have generated one report from your limit, this line would display 2 as your remaining limit - : The date and time when your usage limit resets Use the following query to retrieve report usage data: ## Generate a report Generated reports have a lifespan of 1 day, to enhance security and ensure data freshness. Afterward, they are no longer be valid or usable. You can generate a report using the mutation. When generating a report, you must provide the , and all required or optional parameters. If required parameters are missing, a validation message is sent indicating which fields are missing. Use the following mutation to generate a report: ## Get report details Using a report ID, you can query the node to get report details for a single report. Important details to note include the and : ## List reports To list all existing reports and their details, query the object. You can filter the query by and to narrow down results if necessary. Use the following query to list reports: ## Download a report The Report Download Service (RDS) provides a secure and authenticated way to download reports. To use the RDS, you must provide your API key and the that you received from either a notification or from using the API. With a provided, RDS will provide a data stream of your report that you can use to download all report data. ## Authorization The Report Download Service (RDS) supports a base64 encoded API key for authorization: | Authorization Type | Description | Type | | :--------------------- | :--------------------------------------------------------------------------------- | :----- | | base64 encoded API Key | Provided in the header of the request as Basic auth: | String | ### Download report API #### Request **Endpoint**: | Field Name | Description | Type | | :--------- | :-------------------------------------------------------- | :----- | | | The identified of the report the client wants to download | String | ##### Header | Header Name | Value | Description | | :-------------- | :----------------------------------------- | :------------------------------- | | | Basic | N/A | | | Optional client provided unique request id | Helps with tracing the operation | ##### Body - n/a #### Response ##### Header | Header Name | Value | Description | | :-------------- | :-------------------------------- | :------------------------------------ | | | Client provided unique request id | Same value provided in | | | | Server supplied report content type | ##### Body - Stream of bytes ##### Response status - HTTP status codes returned in case of errors | HTTP Status Code | Description | | :--------------- | :-------------------------------------------------------------------------------------------- | | | Bad request. Usually occurs if the report id is invalid or user doesn’t own the given report. | | | Authentication error. Occurs if the token is invalid or expired. | | | Occurs if report is not found for the given . | | | Internal server error. | ### Usage The URL used to download reports differs whether you are using the Test or Live Environment. The following example requests represent use cases for downloading reports using either a specific name or in the Live environment: ```sh ## Download a file with a specific name export TOKEN= curl https://download.us.highnote.com/reports/ -H "Authorization: Basic ${TOKEN}" -H "x-request-id: " -v --output output.csv ## Download a file with the filename equal to the reportId export TOKEN= curl https://download.us.highnote.com/reports/ -H "Authorization: Basic ${TOKEN}" -H "x-request-id: " -O ``` ### GraphQL: ReportUsage Query: query ReportUsage { reportUsage { ... on ReportUsage { reportType limit limitRemaining periodEnd } } } Variables: { "input": { "status": { "includes": [ "COMPLETED" ] }, "reportType": { "includes": [ "CARD_TRANSACTION_ACTIVITY" ] } } } Expected Result: { "data": { "reportUsage": [ { "reportType": "CARD_TRANSACTION_ACTIVITY", "limit": 3, "limitRemaining": 2, "periodEnd": "2023-06-21T04:00:00.000Z" } ] }, "extensions": { "requestId": "" } } ### GraphQL: InitiateReport Query: mutation InitiateReport($input: InitiateOrganizationReportInput!) { initiateOrganizationReport(input: $input) { __typename ... on Report { __typename id status statusReason reportType createdAt updatedAt } ... on UserError { __typename errors { errorPath code description } } } } Variables: { "input": { "reportType": "CARD_TRANSACTION_ACTIVITY", "parameters": { "between": { "start": "2023-03-10T00:37:31+0000", "end": "2023-04-10T00:37:31+0000" } } } } Expected Result: { "data": { "initiateOrganizationReport": { "__typename": "Report", "id": "", "status": "IN_PROGRESS", "statusReason": null, "reportType": "CARD_TRANSACTION_ACTIVITY", "createdAt": "2023-06-21T17:30:07.196Z", "updatedAt": "2023-06-21T18:44:52.006Z" } }, "extensions": { "requestId": "" } } ### GraphQL: Report Query: query Report($id: ID!) { node(id: $id) { ... on Report { __typename id status reportType download { url } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "Report", "id": "", "status": "COMPLETED", "reportType": "CARD_TRANSACTION_ACTIVITY", "download": { "url": "https://download.us.highnote.com/rptjb_b826e41aefc147b79be9c08f1f7952fa" }, "createdAt": "2023-06-21T17:30:07.196Z", "updatedAt": "2023-06-21T17:30:49.348Z" } }, "extensions": { "requestId": "" } } ### GraphQL: Reports Query: query Reports($first: Int, $after: String, $input: ReportFilterInput) { reports(first: $first, after: $after, filterBy: $input) { ... on ReportConnection { edges { ... on ReportEdge { node { __typename id status reportType download { url } createdAt updatedAt } } } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } } } } Variables: { "input": { "status": { "includes": [ "COMPLETED" ] }, "reportType": { "includes": [ "CARD_TRANSACTION_ACTIVITY" ] } } } Expected Result: { "data": { "reports": { "edges": [ { "node": { "__typename": "Report", "id": "", "status": "COMPLETED", "reportType": "CARD_TRANSACTION_ACTIVITY", "download": { "url": "https://download.us.highnote.com/rptjb_105f3fc4683c4c74ab8f1ab009af4c26" }, "createdAt": "2023-07-05T22:36:32.081Z", "updatedAt": "2023-07-05T22:36:52.894Z" } }, { "node": { "__typename": "Report", "id": "", "status": "COMPLETED", "reportType": "CARD_TRANSACTION_ACTIVITY", "download": { "url": "https://download.us.highnote.com/rptjb_c390e0d3483b4f3697d57621dcf855fa" }, "createdAt": "2023-07-05T22:55:34.899Z", "updatedAt": "2023-07-05T22:55:39.457Z" } } ], "pageInfo": { "hasNextPage": true, "hasPreviousPage": false, "startCursor": "dD0yMDIzLTA3LTA1VDIyJTNBMzYlM0E1Mi45MDc3OTYwMDBaJmk9cnB0amJfMTA1ZjNmYzQ2ODNjNGM3NGFiOGYxYWIwMDlhZjRjMjY", "endCursor": "dD0yMDIzLTA3LTA1VDIyJTNBNTUlM0EzOS40NjY3MzEwMDBaJmk9cnB0amJfYzM5MGUwZDM0ODNiNGYzNjk3ZDU3NjIxZGNmODU1ZmE" } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/reporting/ach-event-activity-report Title: ACH Event Activity Report Section: Issuing Description: Track ACH event activity across financial accounts including originated and non-originated transfers, settlement dates, and return status. ## Overview This report contains all ACH event activities across all financial accounts for your organization. ReportType enum: ## Data availability Data for this report is available as follows: - **Earliest available**: 18 months from today - **Latest available**: One (1) day from today ## Report fields | Field Name | Data Type | Description | | :-------------------------------- | :---------------------------------------- | :------------------------------------------------------------------------------------------------------------------------- | | financial_event_id | String | Unique identifier of the financial event | | financial_event | String | Activity type of the financial event (e.g., , ). | | transaction_id | String | Transaction lifecycle identifier, used to group multiple events under the same ACH process | | created_at | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the financial event was created | | amount | Decimal | Amount of the ACH transfer | | amount_direction | String | Direction of the change amount. Possible values are or . | | amount_currency_code | String | ISO 4217 currency code (e.g., ) | | settlement_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Settlement date and time specified by the originating company of the ACH transfer | | return_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | The date and time on which the ACH transfer was returned | | funds_available_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | The date and time at which the transfer will transition to processed status and the associated funds become available | | status | String | Status of the ACH transfer | | company_name | String | The name of the company that originated the ACH transfer | | company_identifier | String | The ID of the company that originated the ACH transfer | | company_entry_description | String | ACH transaction type as designated by the originating company | | individual_name | String | Name of the individual receiver associated with the transaction | | individual_identification_number | String | Unique identifier of the individual receiver associated with the transaction | | from_financial_account_id | String | Unique identifier of the account from which the funds are being sent | | from_financial_account_name | String | Name of the account from which the funds are being sent | | to_financial_account_id | String | Unique identifier of the account to which the funds are being received | | to_financial_account_name | String | Name of the account to which the funds are being received | | from_external_bank_account_last_4 | String | Last 4 digits of the originating bank account number | | to_external_bank_account_last_4 | String | Last 4 digits of the receiving bank account number | --- URL: https://docs.highnote.com/docs/issuing/reporting/card-interchange-activity-report Title: Card Interchange Activity Report Section: Issuing Description: View transaction-level card interchange and settlement activity including interchange amounts, network rate codes, and merchant details. ## Overview The Card Interchange Activity report contains transaction-level card interchange and settlement activity across all financial accounts for your organization. ATM and manual cash-related transactions are excluded from this report because they are billed differently, e.g., withdrawals, deposits, and balance inquiries. ReportType enum: ## Data availability Data for this report is available as follows: - **Earliest available**: September 1, 2023 and after - **Latest available**: Five (5) days from today ## Report fields | Field Name | Data type | Description | | :------------------------------------------ | :---------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | created_at | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the transaction was posted to the financial account | | platform_settlement_date | Date | Date when the transaction was settled on the platform, with a cutoff of 5 PM Pacific Time (PT) | | card_product_id | String | Unique identifier of the card product | | card_product_name | String | Name of the card product associated with the ledger entry | | public_card_profile_set_id | String | Unique identifier of the card profile for a given card product | | payment_network | String | Name of the card network provider (Visa, Mastercard) | | bin_classification | String | Classification of the network BIN product type (consumer, commercial, business, etc.) | | bin_funding_type | String | Card funding type of the network BIN product (credit, prepaid, debit) | | payment_card_id | String | Unique identifier of the card | | processing_network_code | String | Card transaction network. Possible values: (Visanet), (Mastercard Dual Message), (Maestro Single Message), (PULSE), or (Moneypass) | | financial_event_id | String | Unique identifier of the financial event | | financial_event | String | Activity type of the financial event (e.g., , , , ) | | transaction_id | String | Transaction lifecycle identifier. Example: Two transaction events ( and ) make up one transaction lifecycle, so both events share the same transaction lifecycle ID. Multi-clearing transaction events with different s share the same . | | transaction_settlement_amount | Decimal | Amount of the transaction that was settled. A positive entry is a debit transaction, for example, purchases. A negative entry is a credit transaction, for example, returns. | | transaction_settlement_amount_currency_code | String | ISO 4217 code representing the currency of the settlement amount | | interchange_amount | Decimal | Interchange amount of the transaction: positive for income, negative for expense | | interchange_amount_currency_code | String | ISO 4217 code representing the currency of the interchange amount | | network_interchange_rate_code | String | Code provided by the card network that denotes the interchange category or rate applied to the transaction. Only available for VNT and MCC. | | merchant_category_code | String | 4-digit ISO 18245 code representing retail financial services. MCCs classify businesses by the type of goods or services they provide. | | merchant_name | String | Name of the merchant where the transaction took place | | merchant_description | String | Location of the merchant where the transaction took place | | merchant_country | String | ISO 3166 Alpha-3 code representing the country where the merchant is located | | is_international_transaction | Boolean | True if the transaction is considered international; otherwise False | | acquirer_country | String | ISO 3166 Alpha-3 code representing the country where the acquirer is located | ## Sample report The following sample is representative of an actual report: identifier columns are masked, and merchant names and locations are illustrative, but the timestamps, amounts, networks, interchange figures, rate codes, and categories reflect real reported activity. This sample includes: - A refund, with a negative and . - An international transaction, where is and is populated. - A range of Mastercard interchange rate codes. The column is populated only for dual message processing networks, and in this case, only Mastercard Dual Message (). ```csv created_at,platform_settlement_date,card_product_id,card_product_name,public_card_profile_set_id,payment_network,bin_classification,bin_funding_type,payment_card_id,processing_network_code,financial_event_id,financial_event,transaction_id,transaction_settlement_amount,transaction_settlement_amount_currency_code,interchange_amount,interchange_amount_currency_code,network_interchange_rate_code,merchant_category_code,merchant_name,merchant_description,merchant_country,is_international_transaction,acquirer_country 2026-03-01 01:33:46.699 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0001,CLEAR,tx_2403...0001,376.8,USD,8.01,USD,3B,5200,Home Improvement Warehouse,1200 COMMERCE BLVD PORTLAND ORUS,USA,FALSE, 2026-03-01 01:33:46.815 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0002,CLEAR,tx_2403...0002,220.3,USD,5.72,USD,3N,3357,Metro Car Rental,4500 AIRPORT WAY JACKSONVILLE FLUS,USA,FALSE, 2026-03-01 01:33:48.235 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0003,CLEAR,tx_2403...0003,24.88,USD,0.5,USD,IP,5814,Quick Service Cafe,100 PLAZA CARR 153 SANTA ISABEL PRPR,PRI,FALSE,PRI 2026-03-01 01:33:59.297 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0004,CLEAR,tx_2403...0004,75,USD,1.68,USD,3B,5542,National Fuel Station,1475 HIGHWAY 20 HAMPTON GAUS,USA,FALSE, 2026-03-01 01:34:09.616 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,BUSINESS,DEBIT,cd_2d7b...a639,MCC,te_2403...0005,CLEAR,tx_2403...0005,46,USD,0.23,USD,MM,5942,Online Marketplace,500 COMMERCE AVE SEATTLE WAUS,USA,FALSE, 2026-03-01 01:34:29.837 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0006,CLEAR,tx_2403...0006,999,USD,28.57,USD,3A,5200,Home Improvement Warehouse,2400 RETAIL PKWY DAYTONA BCH FLUS,USA,FALSE, 2026-03-01 01:34:32.123 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0007,CLEAR,tx_2403...0007,0.99,USD,0.01,USD,MM,5818,Digital Goods Service,1 TECH PARK WAY CUPERTINO CAUS,USA,FALSE, 2026-03-01 01:34:32.787 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0008,CLEAR,tx_2403...0008,386.19,USD,7.71,USD,IP,7361,Recruiting Services,10 HARBOUR ST DUBLIN IRIE,IRL,TRUE,IRL 2026-03-01 01:34:47.723 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0009,CLEAR,tx_2403...0009,952.41,USD,24.39,USD,3N,3000,Continental Airlines Co,600 AIRPORT BLVD HOUSTON TXUS,USA,FALSE, 2026-03-01 01:34:50.489 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0010,CLEAR,tx_2403...0010,-20.69,USD,-0.49,USD,39,5814,Casual Dining Restaurant,8300 CENTRE DR WOODBURY MNUS,USA,FALSE, 2026-03-01 01:34:50.563 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0011,CLEAR,tx_2403...0011,500,USD,10.1,USD,CH,8398,Community Nonprofit,33 CHARITY ST NEWNAN GAUS,USA,FALSE, 2026-03-01 01:34:51.171 UTC,2026-03-01,pd_4df7...10c6,CCP,icpse_c291...6296,MASTERCARD,COMMERCIAL,CREDIT,cd_2d7b...a639,MCC,te_2403...0012,CLEAR,tx_2403...0012,35.61,USD,0.85,USD,3B,5734,Cloud Software Provider,101 NETWORK ST SAN FRANCISCOCAUS,USA,FALSE, ``` --- URL: https://docs.highnote.com/docs/issuing/reporting/card-transaction-activity-report Title: Card Transaction Activity Report Section: Issuing Description: View card transaction event activity across accounts including authorization details, settlement dates, merchant information, and AVS and CVV response codes. ## Overview This report contains all card transaction event activities across all financial accounts for the organization. ReportType enum: ## Data availability Data for this report is available as follows: - **Earliest available**: 18 months from today - **Latest available**: One (1) day from today ## Report fields | Field Name | Data Type | Description | | :----------------------------- | :---------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | created_at | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the transaction was posted to the financial account; timestamped at the creation of the transaction record | | card_product_id | String | Unique identifier of the card product | | card_product_name | String | Name of the card product associated with the ledger entry | | public_card_profile_set_id | String | Unique identifier of the card profile for a given card product | | payment_network | String | Name of the card network provider (Visa, Mastercard) | | bin_classification | String | Classification of the network BIN product type (consumer, commercial, business, etc.) | | bin_funding_type | String | Card funding type of the network BIN product (credit, prepaid, debit) | | payment_card_id | String | Unique identifier of the card | | bin | String | First 6 digits of the bank identification number (BIN) | | payment_card_number_last_4 | String | Last 4 digits of the PAN | | account_holder_id | String | Unique identifier of the account holder | | financial_account_id | String | Unique identifier of the financial account | | authorization_date_time | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the transaction was first authorized on the financial account, if applicable | | platform_settlement_date | Date | Date when the transaction was settled on the platform, with a cutoff of 5 PM Pacific Time (PT) | | processing_network_code | String | Card transaction network. Possible values: (Visanet), (Mastercard Dual Message), (Maestro Single Message), (PULSE), or (Moneypass) | | financial_event_id | String | Unique identifier of the financial event | | financial_event | String | Activity type of the financial event (e.g., , , , ) | | processing_type | String | Type of card transaction being processed | | transaction_id | String | Transaction lifecycle identifier. Example: Two transaction events ( and ) make up one transaction lifecycle, so both events share the same transaction lifecycle ID. Multi-clearing transaction events with different s will share the same . | | merchant_id | String | Identifier of the merchant | | merchant_category_code | String | 4-digit ISO 18245 code representing retail financial services. MCCs classify businesses by the type of goods or services they provide. | | merchant_category | String | Text description for the merchant category code () | | merchant_name | String | Name of the merchant where the transaction took place | | merchant_description | String | Location of the merchant where the transaction took place | | merchant_country | String | ISO 3166 Alpha-3 code representing the country where the card was accepted | | response_code | Enum | Highnote response code | | avs_response_code | Enum | Code representing the result of an address verification check | | cvv_response_code | Enum | Code representing the result of a card verification value (CVV) check | | postal_code_response_code | Enum | Code representing the result of postal code verification check | | is_partial | Boolean | Whether this authorization, clear, or reverse was for a partial or full amount | | is_settlement | Boolean | Flag identifying cleared transactions to settle at the bank | | approved_amount | Decimal | Funds approved and posted to the Highnote ledger for the transaction. Appears as in the GraphQL response. Includes fees. | | approved_amount_currency_code | String | ISO 4217 code representing the currency of the transaction approved amount | | surcharge_fee | Decimal | Fee associated with the for each transaction event type | | surcharge_fee_currency_code | String | ISO 4217 code representing the currency of the surcharge fee | | requested_amount | Decimal | Funds requested from the network for the transaction, not including the surcharge fee | | requested_amount_currency_code | String | ISO 4217 code representing the currency of the transaction requested amount | | is_international_transaction | Boolean | True if the transaction is considered international; otherwise False | | acquirer_country | String | ISO 3166 Alpha-3 code representing the country where the acquirer is located | --- URL: https://docs.highnote.com/docs/issuing/reporting/credit-loan-tape-report Title: Credit Loan Tape Report Section: Issuing Description: Track your consumer credit card portfolio with point-in-time snapshots of account status, delinquency, credit limits, utilization, and charge-off information. ## Overview A Credit Loan Tape report includes all transaction event activity for Consumer Revolving Credit Card products. It is account-level data and captured as a point-in-time snapshot of your portfolio. ReportType enum: The Credit Loan Tape report is not self-service. Contact your Highnote representative to request it. ## Data availability Data for this report is available as follows: - **Earliest available**: 18 months from today - **Latest available**: One (1) day from today ## Report fields | Field Name | Data Type | Description | | :---------------------------------------- | :---------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- | | as_of_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Effective snapshot of account, balance, transaction, or performance metrics as of the specified day for this report | | financial_account_id | String | Unique identifier of the financial account | | origination_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the financial account was opened | | card_product_id | String | Unique identifier of the card product | | card_product_name | String | Name of the card product | | account_holder_id | String | Unique identifier of the account holder | | bank_name | String | Name of the issuing bank | | financial_account_status | String | Financial account status | | is_charged_off | Boolean | True if the account is charged-off; otherwise False | | origination_credit_score | Integer | Credit score at account origination | | origination_credit_limit | Decimal | Credit limit assigned at account origination | | origination_apr | Decimal | Interest rate assigned at account origination | | current_balance | Decimal | Current balance amount on the | | current_balance_currency_code | String | ISO 4217 currency code of | | current_delinquent_amount | Decimal | Amount by which the payment is delinquent | | current_delinquent_amount_currency_code | String | ISO 4217 currency code of | | delinquent_days | Integer | Number of days that the payment is delinquent | | delinquency_status | String | Delinquency status | | delinquency_update_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the deliquency status was last updated | | charge_off_amount | Decimal | Total balance officially written off as a loss on the account due to delinquency, default, or other uncollectible status | | charge_off_amount_currency_code | String | ISO 4217 currency code of | | charge_off_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Date of the | | current_purchase_apr | Decimal | Current interest rate on the | | current_credit_limit | Decimal | Credit limit amount on the | | current_credit_limit_currency_code | String | ISO 4217 currency code of | | last_statement_is_over_limit | Boolean | True if the total purchases exceed the available credit, as of the last statement; otherwise False | | last_statement_over_limit_amount | Decimal | Amount over the credit limit, as of the last statement | | last_statement_over_limit_currency_code | String | ISO 4217 currency code of | | current_address_state | String | State of the current address of the account holder | | last_statement_credit_utilization | Number | Credit utilization as a percentage, as of the last statement | | last_pull_credit_score | String | Account holder’s Experian credit score, as of the last credit pull | | last_pull_credit_score_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | Date of | | year_to_date_fee_amount | Decimal | Year-to-date fee amount, as of the last statement | | year_to_date_fee_currency_code | String | ISO 4217 currency code of | | year_to_date_interest_amount | Decimal | Year-to-date interest amount, as of the last statement | | year_to_date_interest_currency_code | String | ISO 4217 currency code of | | has_recurring_payments_scheduled | Boolean | True if the account has scheduled recurring payments set; otherwise False | | statement_id | String | Unique identifier of the statement | | statement_period_start | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp of the period start date on the last statement | | statement_period_end | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp of the period end date on the last statement | | statement_date | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp of the date when the statement was generated | | statement_payment_due_on | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp of the payment due date on the last statement | | starting_statement_balance | Decimal | Primary balance on the last statement | | starting_statement_balance_currency_code | String | ISO 4217 currency code of | | ending_statement_balance | Decimal | Ending primary balance, as of the last statement | | ending_statement_balance_currency_code | String | ISO 4217 currency code of | | statement_purchase_apr | Decimal | Annual percentage rate, as of the last statement | | period_minimum_payment_amount | Decimal | Minimum payment amount due, as of the last statement | | period_minimum_payment_currency_code | String | ISO 4217 currency code of | | period_purchases_amount | Decimal | Total purchase amount, as of the last statement | | period_purchases_currency_code | String | ISO 4217 currency code of | | period_credit_amount | Decimal | Amount of total credit, as of the last statement. Includes payments, refunds, rewards and credited as statement credit, manual adjustments, etc. | | period_credit_currency_code | String | ISO 4217 currency code of | | period_interest_charge_amount | Decimal | Interest amount on the last statement | | period_interest_charge_currency_code | String | ISO 4217 currency code of | | period_interest_credit_amount | Decimal | Interest credited amount on the last statement | | period_interest_credit_currency_code | String | ISO 4217 currency code of | | period_fee_charge_amount | Decimal | Fee amount, as of the last statement | | period_fee_charge_currency_code | String | ISO 4217 currency code of | | period_fee_credit_amount | Decimal | Fee credited amount on the last closed statement | | period_fee_credit_currency_code | String | ISO 4217 currency code of | | statement_delinquent_amount | Decimal | Past due amount of the last statement | | statement_delinquent_amount_currency_code | String | ISO 4217 currency code of | | ending_reward_points | Number | Number of reward points, as of the last statement | | ending_credit_limit_amount | Decimal | Ending credit limit amount, as of the last statement | | ending_credit_limit_currency_code | String | ISO 4217 currency code of | | mla_eligible | Boolean | True if the cardholder is a servicemember qualifying for MLA protection; otherwise False | | scra_eligible | Boolean | True if the cardholder is a servicemember qualifying for SCRA protection; otherwise False | | has_lifetime_bankruptcy | Boolean | True if the account holder has ever filed for bankruptcy in their lifetime as of the last credit pull; otherwise False | | has_lifetime_charge_off | Boolean | True if the account holder has ever had a credit account charge-off as of the last credit pull; otherwise False | | has_current_bankruptcy | Boolean | True if the account holder has a current bankruptcy on their credit report as of the last credit pull; otherwise False | | is_fraudulent | Boolean | True if the account was identified as fraudulent | | is_modified | Boolean | True if the account was modified | --- URL: https://docs.highnote.com/docs/issuing/reporting/fleet-enhanced-data-summary-report Title: Fleet Enhanced Data Summary Report Section: Issuing Description: Track Level 2 and Level 3 enhanced data from Visa and Mastercard for cleared fleet transactions including fuel type, quantity, and driver and vehicle identifiers. ## Overview This report contains all level 2 and 3 enhanced data sent by Visa and Mastercard for cleared fleet transactions. Report data can be obtained for a specific time period. ReportType enum: ## Data availability Data for this report is available as follows: - **Earliest available**: 18 months from today - **Latest available**: Current day and time ## Report fields In standard reports and Data Share, includes fees. In the GraphQL API, does not include fees, e.g., see PaymentCardClearedEvent. | Field name | Data type | Description | | :-------------------------------- | :---------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | created_at | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the transaction was posted to the financial account | | card_product_id | String | Unique identifier of the card product | | card_product_name | String | Name of the card product | | card_profile_set_id | String | Unique identifier of the card profile for a given card product | | network_name | String | Name of the card network provider (Visa, Mastercard) | | classification | String | Classification of the network BIN product type (consumer, commercial, business, etc.) | | funding_type | String | Card funding type of the network BIN product (credit, prepaid, debit) | | account_holder_id | String | Unique identifier of the account holder | | payment_card_id | String | Unique identifier of the payment card | | payment_network | String | The payment network: or | | financial_event_id | String | Unique identifier of the financial event | | transaction_id | String | Transaction lifecycle identifier. Example: Two transaction events ( and ) make up one transaction lifecycle, so both events share the same transaction lifecycle ID. Multi-clearing transaction events with different s share the same . | | network_reference_id | String | Value used by the payment network to reference the transaction -- may not be unique across all network transactions | | merchant_category_code | String | 4-digit ISO 18245 code representing retail financial services. MCCs classify businesses by the type of goods or services they provide. | | merchant_id | Number | Identifier of the merchant | | merchant_name | String | Name of the merchant where the transaction took place | | merchant_description | String | Location of the merchant where the transaction took place | | requested_amount | Decimal | Funds requested from the network for the transaction | | requested_amount_currency_code | String | ISO 4217 code representing the currency of the | | approved_amount | Decimal | Funds approved and posted to the Highnote ledger for the transaction | | approved_amount_currency_code | String | ISO 4217 code representing the currency of the | | total_posted_amount | Decimal | Amount that Highnote posts to the Highnote Ledger for each cleared transaction event | | total_posted_amount_currency_code | String | ISO 4217 code representing the currency of the | | purchase_type | String | Specifies whether the transaction was fuel only or mixed (fuel and non-fuel) | | fuel_sale_amount | Decimal | Total amount for only fuel purchased | | fuel_sale_amount_currency_code | String | ISO 4217 code representing the currency of the | | fuel_unit_price | Decimal | Price per unit of fuel purchased | | fuel_unit_price_currency_code | String | ISO 4217 code representing the currency of the | | fuel_unit_of_measure | String | Unit of measure utilized for fuel purchased | | fuel_quantity | Decimal | Quantity of fuel purchased | | fuel_type | String | Product code of fuel purchased | | odometer_reading | Number | Odometer reading if entered by the cardholder | | fleet_id | String | Alphanumeric value representing either a vehicle, driver, or generic ID if entered by the cardholder | --- URL: https://docs.highnote.com/docs/issuing/reporting/ledger-entry-report Title: Ledger Entry Report Section: Issuing Description: View ledger entries across all financial accounts including financial events, change amounts, balance direction, and ledger type. ## Overview This report contains ledger entries across all financial accounts for your organization. ReportType enum: ## Data availability Data for this report is available as follows: - **Earliest available**: 18 months from today - **Latest available**: One (1) day from today ## Report fields | Field Name | Data Type | Description | | :-------------------------- | :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | created_at | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the ledger entry was created | | card_product_id | String | Unique identifier of the card product | | card_product_name | String | Name of the card product associated with the ledger entry | | financial_account_id | String | Unique identifier of the financial account associated with the ledger entry | | financial_account_name | String | Name of the financial account associated with the ledger entry | | transaction_id | String | Transaction lifecycle identifier. Example: Two transaction events ( and ) make up one transaction lifecycle, so both events share the same transaction lifecycle ID. | | financial_event | String | Activity type of the financial event (e.g., , , , ) | | financial_event_id | String | Unique identifier of the financial event that the results from | | ledger_name | String | Type of ledger (e.g., , ) | | ledger_entry_id | String | Unique identifier of the ledger entry | | change_amount | String | Amount by which the ledger balance changed | | change_amount_currency_code | String | ISO 4217 currency code (e.g., ) | | change_amount_direction | String | Direction of the change amount. Possible values are or . | | normal_balance | Decimal | Expected balance type of an account. Possible values are or . | | balance_at_ledger_entry | Decimal | Balance of the account after the ledger entry | --- URL: https://docs.highnote.com/docs/issuing/reporting/negative-account-balance-report Title: Negative Account Balance Report Section: Issuing Description: Monitor negative balances across financial accounts with aging duration, latest balance updates, and date turned negative. ## Overview This report lets subscribers monitor their negative balances. ReportType enum: ## Data availability Data for this report is generated daily. ## Report fields | Field Name | Data Type | Description | | :-------------------- | :-------- | :-------------------------------------------------------------------------------------------------------- | | program_name | String | Name of the card program or product associated with the account | | product_name | String | Name of the card product associated with the account | | financial_account_id | String | Unique public identifier for the financial account | | account_type_code | String | Code indicating the type of account (e.g., 'C0' for credit accounts, 'OG' for organization accounts) | | account_status | String | Current status of the account | | balance_amount | String | Current negative balance amount in the account (converted from micro-units by dividing by 1,000,000) | | turn_to_negative_date | String | Timestamp when the account first turned negative (transitioned from zero or positive to negative balance) | | latest_update_date | String | Timestamp of the most recent balance update for this account | | aging_days | String | Number of days the account has had a negative balance (current timestamp minus turn_to_negative_date) | --- URL: https://docs.highnote.com/docs/issuing/reporting/receivable-sale-reports Title: Receivable Sale Reports Section: Issuing Description: Review receivable sale statements, account-level sales, and transaction-level sales data. Generated automatically on business days. ## Overview This page describes the data fields for three Receivable Sale report types: Statements, Accounts, and Transactions. These reports are automatically generated, and only if applicable to your product. We also generate your Receivable Sale Agreement with every publication of your reports. The agreement is identified by the ReportType enum: . ## Receivable Sale Statements This report contains the overall amount being sold on a given business day. ReportType enum: ### Data availability This report is generated on business days between 10:30 AM and 12:15 PM ET. ### Report fields | Field Name | Data Type | Description | | :------------------------------------------ | :-------- | :--------------------------------------------------------------------------------------------------- | | organization_id | String | Unique identifier of the organization | | organization_name | String | Name of the organization | | product_id | String | Unique identifier of the product | | product_name | String | Name of the product | | receivables_settlement_date | Date | Date the receivable was settled | | receivables_purchase_date | Date | Date the receivable was purchased | | outstanding_principal_balance_of_receivable | Decimal | Total amount of receivables for the day | | percent | Number | Percent of receivables being purchased | | purchase_price | Decimal | Total amount of receivables being purchased (outstanding_principal_balance_of_receivable \* percent) | ## Receivable Sale Accounts This report contains the breakdown of each financial account’s receivables being sold on a given business day (sum to the amount in the Receivable Sale report). ReportType enum: ### Data availability This report is generated on business days between 10:30 AM and 12:15 PM ET. ### Report fields | Field Name | Data Type | Description | | :------------------------------------------ | :-------- | :--------------------------------------------------------------------------------------------------- | | organization_id | String | Unique identifier of the organization | | organization_name | String | Name of the organization | | product_id | String | Unique identifier of the product | | product_name | String | Name of the product | | public_financial_account_id | String | Unique identifier of the financial account | | public_account_holder_id | String | Unique identifier of the account holder | | receivables_settlement_date | Date | Date the receivable was settled | | receivables_purchase_date | Date | Date the receivable was purchased | | outstanding_principal_balance_of_receivable | Decimal | Total amount of receivables for the day | | percent | Number | Percent of receivables being purchased | | purchase_price | Decimal | Total amount of receivables being purchased (outstanding_principal_balance_of_receivable \* percent) | ## Receivable Sale Transactions This report contains the breakdown of each transaction’s receivables being sold on a given business day (sum to the amount in the Receivable Sale report). ReportType enum: ### Data availability This report is generated on business days between 10:30 AM and 12:15 PM ET. ### Report fields | Field Name | Data Type | Description | | :------------------------------------------ | :-------- | :--------------------------------------------------------------------------------------------------- | | organization_id | String | Unique identifier of the organization | | organization_name | String | Name of the organization | | product_id | String | Unique identifier of the product | | product_name | String | Name of the product | | public_financial_account_id | String | Unique identifier of the financial account | | public_account_holder_id | String | Unique identifier of the account holder | | ledger_entry_id | String | Unique identifier of the ledger entry | | transaction_id | String | Unique identifier of the transaction | | receivables_settlement_date | Date | Date the receivable was settled | | receivables_purchase_date | Date | Date the receivable was purchased | | outstanding_principal_balance_of_receivable | Decimal | Total amount of receivables for the day | | percent | Number | Percent of receivables being purchased | | purchase_price | Decimal | Total amount of receivables being purchased (outstanding_principal_balance_of_receivable \* percent) | --- URL: https://docs.highnote.com/docs/issuing/reporting/summary-metrics Title: Summary Metrics Section: Issuing Description: Query application and transaction metrics for your card products including approval rates, decline reasons, and cleared transaction volumes. ## Overview Highnote provides summary metrics for applications and transactions that empower you with essential data to drive your critical business decisions. You can retrieve summary metrics from the Highnote Dashboard or using the Highnote API. ## Data freshness Note the following about Highnote’s summary metrics API’s data freshness rules: - Summary metrics data is available within one hour, on the hour. For example, if you request data at 2:45PM, the API will return data up to 1 PM. - The summary metrics API provides a data freshness timestamp in the results field. - The default sorting of summary metrics results is _descending_. ## Get application metrics Application metrics show account holder and authorized user application data across card products. You can use the query to retrieve the following data: | Data type | Description | | :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | timeRange | Requested start and end timestamp | | asOf | Data freshness timestamp | | createdApplications | New applications that have been submitted | | approvedApplications | Applications that have been approved. Once an application has been approved, a financial account can be used to the account holder | | deniedApplications | Applications that have failed one or more card product policies. When an application is denied, a payment card cannot be issued to the account holder. Customer notification of the denial and denial reason may be required | | inReviewApplications | Applications may be flagged for manual review because fraud is suspected or the information provided appears incorrect. This status indicates a Highnote agent is reviewing the application to determine a decision or if additional information is required from the account holder | | pendingApplications | Applications that have been received, and are being verified by the system | | closedApplications | Applications that have been processed or withdrawn | Use the following query to retrieve application metrics: ## Get transaction metrics Transaction metrics show payment card transaction data across card products. You can use the query to retrieve the following data: | Data type | Description | | :--------------------------- | :---------------------------------------------------------- | | timeRange | Requested start and end timestamp | | asOf | Data freshness timestamp | | approvedAuthorization | An authorization has been approved | | declinedAuthrorization | An authorization has been declined | | approvedAuthorizationAmount | The total dollar amount of approved authorizations | | declinedAuthrorizationAmount | The total dollar amount of declined authorizations | | Top N declinedAuthorization | Top N declined authorizations | | clearedTransactions | A transaction has been successfully processed and finalized | | clearedTransactionsAmount | A transaction has been successfully processed and finalized | | Top N clearedTransactions | Top N cleared transactions | Use the following query to retrieve transaction metrics: ### GraphQL: CardProductApplicationBusinessMetric Query: query cardProductApplicationBusinessMetric( $input: CardProductApplicationBusinessMetricFilterInput ) { cardProductApplicationBusinessMetric(filterBy: $input) { __typename ... on CardProductApplicationBusinessMetricResult { timeRange { start end } asOf cardProductApplicationBusinessMetrics { timeRange { start end } createdApplications { total authorizedUsers accountHolders } approvedApplications { total authorizedUsers accountHolders } deniedApplications inReviewApplications pendingApplications closedApplications } } } } Variables: { "input": { "cardProductIds": [ "" ], "timeRange": { "start": "2023-12-22T08:30:00.000Z", "end": "2023-12-23T08:30:00.000Z" } } } Expected Result: { "data": { "cardProductApplicationBusinessMetric": { "__typename": "CardProductApplicationBusinessMetricResult", "timeRange": { "start": "2023-12-22T08:30:00.000Z", "end": "2023-12-23T08:30:00.000Z" }, "asOf": "2023-12-23T07:00:00.000Z", "cardProductApplicationBusinessMetrics": [ { "timeRange": { "start": "2023-12-22T08:30:00.000Z", "end": "2023-12-23T08:30:00.000Z" }, "createdApplications": { "total": 187, "authorizedUsers": 0, "accountHolders": 187 }, "approvedApplications": { "total": 134, "authorizedUsers": 0, "accountHolders": 134 }, "deniedApplications": 27, "inReviewApplications": 26, "pendingApplications": 0, "closedApplications": 0 } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 6 } } } ### GraphQL: PaymentCardTransactionBusinessMetric Query: query paymentCardTransactionBusinessMetric( $input: PaymentCardTransactionBusinessMetricFilterInput ) { paymentCardTransactionBusinessMetric(filterBy: $input) { __typename ... on PaymentCardTransactionBusinessMetricResult { timeRange { start end } asOf paymentCardTransactionBusinessMetrics { timeRange { start end } approvedAuthorization { count amount { value currencyCode } } declinedAuthorization { count amount { value currencyCode } responseCode { sortedDirection responseCodeAttributes { count amount { value currencyCode } responseCode } } } clearedTransactions { count amount { value currencyCode } topMerchantCategory { sortedDirection topMerchantCategoryAttributes { count amount { value currencyCode } merchantCategory } } topMerchantName { sortedDirection topMerchantNameAttributes { count amount { value currencyCode } merchantName } } } } } } } Variables: { "input": { "cardProductIds": [ "" ], "timeRange": { "start": "2022-12-14T08:30:00.000Z", "end": "2023-12-21T08:50:00.000Z" }, "merchantCategoryCodes": [ "6011", "5999" ], "merchantNames": [] } } Expected Result: { "data": { "paymentCardTransactionBusinessMetric": { "__typename": "PaymentCardTransactionBusinessMetricResult", "timeRange": { "start": "2022-12-14T08:30:00.000Z", "end": "2024-01-08T08:50:00.000Z" }, "asOf": "2024-01-08T07:00:00.000Z", "paymentCardTransactionBusinessMetrics": [ { "timeRange": { "start": "2022-12-14T08:30:00.000Z", "end": "2024-01-08T08:50:00.000Z" }, "approvedAuthorization": { "count": 44759, "amount": { "value": 82898778, "currencyCode": "USD" } }, "declinedAuthorization": { "count": 10941, "amount": { "value": 11473384, "currencyCode": "USD" }, "responseCode": { "sortedDirection": "DESCENDING", "responseCodeAttributes": [ { "count": 848, "amount": { "value": 5000, "currencyCode": "USD" }, "responseCode": "TRANSACTION_NOT_PERMITTED" }, { "count": 5324, "amount": { "value": 1234, "currencyCode": "USD" }, "responseCode": "INSUFFICIENT_FUNDS" }, { "count": 1329, "amount": { "value": 1000, "currencyCode": "USD" }, "responseCode": "DO_NOT_HONOR" }, { "count": 859, "amount": { "value": 1000, "currencyCode": "USD" }, "responseCode": "RE_ENTER_TRANSACTION" }, { "count": 427, "amount": { "value": 1000, "currencyCode": "USD" }, "responseCode": "RESTRICTED_LOCATION" }, { "count": 1272, "amount": { "value": 1000, "currencyCode": "USD" }, "responseCode": "EXCEEDS_APPROVAL_AMOUNT_LIMIT" }, { "count": 882, "amount": { "value": 1000, "currencyCode": "USD" }, "responseCode": "BAD_CVV2" } ] } }, "clearedTransactions": { "count": 20857, "amount": { "value": 71425394, "currencyCode": "USD" }, "topMerchantCategory": { "sortedDirection": "DESCENDING", "topMerchantCategoryAttributes": [ { "count": 25512, "amount": { "value": 60425394, "currencyCode": "USD" }, "merchantCategory": "MISCELLANEOUS_SPECIALTY_RETAIL" } ] }, "topMerchantName": { "sortedDirection": "DESCENDING", "topMerchantNameAttributes": [ { "count": 160, "amount": { "value": 5100000, "currencyCode": "USD" }, "merchantName": "Verify Highnote Signature" } ] } } } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19 } } } --- URL: https://docs.highnote.com/docs/issuing/reporting/transfer-event-activity-report Title: Transfer Event Activity Report Section: Issuing Description: Track transfer event activity across financial accounts including status, activity type, purpose, and transfer direction. ## Overview This report contains all transfer event activities across all financial accounts for your organization. ReportType enum: ## Data availability Data for this report is available as follows: - **Earliest available**: 18 months from today - **Latest available**: One (1) day from today ## Report fields | Field Name | Data Type | Description | | :-------------------------- | :---------------------------------------- | :----------------------------------------------------------------------------------------------- | | financial_event_id | String | Unique identifier of the financial event | | financial_event | String | Activity type of the financial event | | transaction_id | String | Transaction lifecycle identifier, used to group multiple events under the same internal transfer | | created_at | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the financial event was created | | updated_at | DateTime (ISO 8601: YYYY-MM-DDTHH:MM:SSZ) | UTC timestamp when the financial event was updated | | amount | Decimal | Amount of the transfer | | amount_direction | String | Direction of the change amount. Possible values are or . | | amount_currency_code | String | ISO 4217 currency code (e.g., ) | | status | String | Current status of the transfer | | transfer_activity_type | String | Type of activity associated with the transfer | | purpose | String | Stated purpose for the transfer. | | memo | String | A memo providing a brief description of the transfer for reference purposes | | from_financial_account_id | String | Unique identifier of the account from which the funds are being sent | | from_financial_account_name | String | Name of the account from which the funds are being sent | | to_financial_account_id | String | Unique identifier of the account to which the funds are being received | | to_financial_account_name | String | Name of the account to which the funds are being received | --- URL: https://docs.highnote.com/docs/issuing/rewards/adjust-and-find-rewards Title: Adjust and Find Rewards Section: Issuing Description: Create manual reward point adjustments and query reward point balances and transfer history on financial accounts. ## Overview Highnote supports manual reward adjustment. A manual reward adjustment is useful if reward points are redeemed outside of Highnote. With manual adjustment, you can adjust rewards in Highnote outside of the standard reward redemption flow. You can also query reward point transfer to build a transfer feed for your account holder, or to monitor transfers for your organization. ## Create reward point adjustment Use the following mutation to create a manual reward point adjustment: ## Find reward point transfers You can query for reward point transfers on a financial account to check the status of reward point transfers, or monitor reward point transfer history. Use the following query to find reward point transfers on a financial account: ## View reward point balance You can use a ledger balance query to create a reward point balance view, or transaction feed in your website or application. There are two ledgers that you can use for this purpose: - ledger - ledger ### Find ledger ID To query for a rewards point ledger, you must find the ledger ID. When querying for a financial account, all ledger IDs are listed in the response. Use the following query to find a financial account and its associated ledgers: ### View reward point ledger Use the following query to view reward points balance for a financial account: ### View redeemable reward point ledger Use the following query to view reward points balance for a financial account: ### GraphQL: CreateRewardPointsAdjustment Query: mutation CreateRewardPointsAdjustment( $input: CreateRewardPointsAdjustmentInput! ) { createRewardPointsAdjustment(input: $input) { __typename ... on RewardPointsTransfer { id rewardPointsValue { currencyCode value } rewardPointsAmount { currencyCode value } createdAt updatedAt ledgers { name } status { ... on RewardPointsTransferSuccessStatus { status } ... on RewardPointsTransferFailureStatus { status statusReasonCode } } activity memo } } } Variables: { "input": { "financialAccountId": "", "activity": "DEDUCT", "pointsToAdjust": 100, "memo": "memo" } } Expected Result: { "data": { "createRewardPointsAdjustment": { "__typename": "RewardPointsTransfer", "activity": "DEDUCT", "createdAt": "2022-03-12T00:00:00.000Z", "id": "adjustmentId", "ledgers": [ { "id": "" } ], "memo": "memo", "rewardPointsAmount": { "currencyCode": "XHP", "value": 1 }, "rewardPointsValue": { "currencyCode": "USD", "value": 1 }, "status": { "__typename": "RewardPointsTransferSuccessStatus", "status": "COMPLETED" }, "updatedAt": "2022-03-12T00:00:00.000Z" }, "extensions": { "requestId": "" } } } ### GraphQL: FindFinancialAccountWithRewardPointsTransfers Query: query FindFinancialAccountWithRewardPointsTransfers($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { id ledgers(ledgerNames: [REWARDS_POINTS]) { id name debitBalance { value currencyCode } ledgerEntries { edges { node { financialEvent { __typename ... on Node { id } ... on RewardPointsTransfer { id redemptionConfiguration { id } rewardEarnRule { id } rewardPointsAmount { value currencyCode } status { ... on RewardPointsTransferSuccessStatus { status } ... on RewardPointsTransferFailureStatus { status statusReasonCode } } activity source memo externalTransactionIdentifier } } amount { value } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "id": "", "ledgers": [ { "id": "", "name": "REWARDS_POINTS", "debitBalance": { "value": 500, "currencyCode": "XHP" }, "ledgerEntries": { "edges": [ { "node": { "financialEvent": { "__typename": "RewardPointsTransfer", "id": "", "redemptionConfiguration": null, "rewardEarnRule": { "id": "" }, "rewardPointsAmount": { "value": 500, "currencyCode": "XHP" }, "status": { "status": "COMPLETED" }, "activity": "AWARD", "source": "CARD_TRANSACTION", "memo": "Card transaction", "externalTransactionIdentifier": null }, "amount": { "value": 500 } } } ] } } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 125, "limit": 60060, "remaining": 59935 } } } ### GraphQL: FindFinancialAccountLedgers Query: query FindFinancialAccountLedgers($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { id ledgers(ledgerNames: [REWARDS_POINTS]) { id name debitBalance { value currencyCode } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": {} }, "extensions": { "requestId": "", "rateLimit": { "cost": 9, "limit": 100, "remaining": 99991 } } } ### GraphQL: FindLedger Query: query FindLedger($id: ID!) { node(id: $id) { ... on Ledger { id name ledgerEntries(first: 1) { edges { node { __typename id amount { value } journalEntry { credits { amount { value } } debits { amount { value } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "name": "REWARDS_POINTS", "ledgerEntries": { "edges": [ { "node": { "__typename": "CreditLedgerEntry", "id": "", "amount": { "value": 1000 }, "journalEntry": { "credits": [ { "amount": { "value": 1000 } } ], "debits": [ { "amount": { "value": 1000 } } ] } } } ] } } } } ### GraphQL: FindLedger Query: query FindLedger($id: ID!) { node(id: $id) { ... on Ledger { id name ledgerEntries(first: 1) { edges { node { __typename id amount { value } journalEntry { credits { amount { value } } debits { amount { value } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "name": "REWARDS_POINTS", "ledgerEntries": { "edges": [ { "node": { "__typename": "CreditLedgerEntry", "id": "", "amount": { "value": 1000 }, "journalEntry": { "credits": [ { "amount": { "value": 1000 } } ], "debits": [ { "amount": { "value": 1000 } } ] } } } ] } } } } --- URL: https://docs.highnote.com/docs/issuing/rewards/config-reward-redemption Title: Configure Reward Redemption Section: Issuing Description: Create reward redemption configurations with conversion rates and attach them to card products for statement credit redemption. ## Overview After you create a reward earn rule, you can configure how to redeem rewards. You can do this by using redemption configurations. Each redemption configuration contains units for conversion. For example, you can redeem reward points for an equivalent statement credit. In addition to conversion units, you can configure redemption timelines. They dictate when an account holder can start redeeming rewards. ## Create reward redemption configuration Once your rewards program is approved, the Highnote team will assist with creating your reward redemptions in the Live environment. Reward redemption configurations are used to create reward redemption configurations. You can create a single reward redemption configuration, or multiple configurations of the same type. For example, you can create one reward redemption configuration for 1x and another for 0.5x. Then, you can use these configurations to offer different redemption rules, with both remaining active at the same time. When redeeming rewards in this scenario, you will reference the for each reward redemption configuration. Use the following mutation to create a reward redemption configuration in the Test environment. Use the input field to create your reward unit conversion rate: ## Attach reward redemption to card product Once your rewards program is approved, the Highnote team will assist with attaching your reward redemptions to your card product(s) in the Live environment. You must attach redemption configurations to card products. This enables account holders to redeem rewards. Use the following mutation to attach a redemption configuration to a card product in the Test environment: ## Update reward redemption configuration The updated date must be now or in the future. If a reward redemption configuration needs deactivating, you can update the attachment's date to end the configuration's availability. Use the following mutation to update the attachment between reward redemption configuration attachment in the Test environment: ## Find reward redemption configuration You can query for a reward redemption configuration to display it in your website or application. You can query for a reward earn rule using the following methods: - via reward redemption configuration ID - via card product ID - via organization ID ### via reward redemption configuration ID Use the following query to find a reward redemption configuration using the redemption configuration ID: ### via card product ID Use the following query to find a reward redemption configuration via card product ID: ### via organization ID Use the following query to find a reward redemption configuration via organization ID: ### GraphQL: CreateRewardRedemptionConfiguration Query: mutation CreateRewardRedemptionConfiguration( $input: CreateRewardRedemptionConfigurationInput! ) { createRewardRedemptionConfiguration(input: $input) { __typename ... on RewardRedemptionConfiguration { id type name rewardPointRedemption { rate } attachments { ... on RewardRedemptionConfigurationAttachmentConnection { pageInfo { hasNextPage hasPreviousPage endCursor startCursor } edges { node { effectiveFrom effectiveThrough redemptionConfiguration { id } ... on RewardRedemptionConfigurationProductAttachment { cardProduct { id } } } } } } createdAt updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "name": "configName", "rewardPointRedemption": { "rate": "1.0" } } } Expected Result: { "data": { "createRewardRedemptionConfiguration": { "__typename": "RewardRedemptionConfiguration", "id": "", "type": "STATEMENT_CREDIT", "name": "configName", "rewardPointRedemption": { "rate": "1.0" }, "attachments": { "__typename": "RewardRedemptionConfigurationAttachmentConnection", "edges": [], "pageInfo": { "hasNextPage": false, "endCursor": "", "hasPreviousPage": false, "startCursor": "" } }, "createdAt": "1970-01-01T00:00:00.000Z", "updatedAt": "1970-01-01T00:00:00.000Z" } }, "extensions": { "requestId": "" } } ### GraphQL: AttachRewardRedemptionConfigurationToProduct Query: mutation AttachRewardRedemptionConfigurationToProduct( $input: AttachRewardRedemptionConfigurationToProductInput! ) { attachRewardRedemptionConfigurationToProduct(input: $input) { __typename ... on RewardRedemptionConfigurationProductAttachment { redemptionConfiguration { id } cardProduct { id } effectiveFrom effectiveThrough } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "redemptionConfiguration": { "id": "" }, "cardProductId": "", "effectiveFrom": "2023-01-01T00:00:00.000Z", "effectiveThrough": "2023-01-02T00:00:00.000Z" } } Expected Result: { "data": { "attachRewardRedemptionConfigurationToProduct": { "__typename": "RewardRedemptionConfigurationProductAttachment", "redemptionConfiguration": { "id": "" }, "cardProduct": { "id": "" }, "effectiveFrom": "2023-01-01T00:00:00.000Z", "effectiveThrough": "2023-01-02T00:00:00.000Z" } }, "extensions": { "requestId": "" } } ### GraphQL: UpdateRewardRedemptionConfigurationAttachment Query: mutation UpdateRewardRedemptionConfigurationAttachment( $input: UpdateRewardRedemptionConfigurationAttachmentInput! ) { updateRewardRedemptionConfigurationAttachment(input: $input) { __typename ... on RewardRedemptionConfigurationProductAttachment { id cardProduct { id } redemptionConfiguration { id } effectiveFrom effectiveThrough } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "attachmentId": "", "effectiveThrough": "2023-03-24T00:00:00.000Z" } } Expected Result: { "data": { "updateRewardRedemptionConfigurationAttachment": { "__typename": "RewardRedemptionConfigurationProductAttachment", "id": "", "cardProduct": { "id": "" }, "redemptionConfiguration": { "id": "configId" }, "effectiveFrom": "2023-01-01T00:00:00.000Z", "effectiveThrough": "2023-03-24T00:00:00.000Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 12 } } } ### GraphQL: FindRewardRedemptionConfigurationById Query: query FindRewardRedemptionConfigurationById($id: ID!) { node(id: $id) { __typename ... on RewardRedemptionConfiguration { id type name rewardPointRedemption { rate } attachments { ... on RewardRedemptionConfigurationAttachmentConnection { pageInfo { hasNextPage hasPreviousPage endCursor startCursor } edges { node { effectiveFrom effectiveThrough redemptionConfiguration { id } ... on RewardRedemptionConfigurationProductAttachment { cardProduct { id } } } } } } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "RewardRedemptionConfiguration", "id": "", "type": "STATEMENT_CREDIT", "name": "configName", "rewardPointRedemption": { "rate": "1.0" }, "attachments": { "__typename": "RewardRedemptionConfigurationAttachmentConnection", "edges": [ { "node": { "__typename": "RewardRedemptionConfigurationProductAttachment", "redemptionConfiguration": { "id": "" }, "cardProduct": { "id": "" }, "effectiveFrom": "2023-01-01T00:00:00.000Z", "effectiveThrough": "2023-01-02T00:00:00.000Z" } } ], "pageInfo": { "hasNextPage": false, "endCursor": "", "hasPreviousPage": false, "startCursor": "" } }, "createdAt": "1970-01-01T00:00:00.000Z", "updatedAt": "1970-01-01T00:00:00.000Z" } }, "extensions": { "requestId": "" } } ### GraphQL: FindCardProductWithRewardRules Query: query FindCardProductWithRewardRules($id: ID!) { node(id: $id) { __typename ... on CardProduct { attachedRewardRedemptionConfigurations { ... on RewardRedemptionConfigurationAttachmentConnection { pageInfo { startCursor hasNextPage } edges { node { __typename effectiveFrom effectiveThrough redemptionConfiguration { ... on RewardRedemptionConfiguration { id type name rewardPointRedemption { rate } attachments { ... on RewardRedemptionConfigurationAttachmentConnection { pageInfo { hasNextPage hasPreviousPage endCursor startCursor } edges { cursor node { effectiveFrom effectiveThrough redemptionConfiguration { id } ... on RewardRedemptionConfigurationProductAttachment { cardProduct { id } } } } } } createdAt updatedAt } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardProduct", "attachedRewardRedemptionConfigurations": { "pageInfo": { "startCursor": "dD0yMDI0LTAxLTIzVDA2JTNBNTUlM0E0MC44NTgwMDAwMDBaJmk9cndkcm1fNWE2MTQ5MzYwY2Q4NDBlZmI5OGIzNWIzOTAwZDg5ZjE", "hasNextPage": false }, "edges": [ { "node": { "__typename": "RewardRedemptionConfigurationProductAttachment", "cardProduct": { "id": "" }, "effectiveFrom": "2023-01-01T00:00:00.000Z", "effectiveThrough": "2023-01-02T00:00:00.000Z", "redemptionConfiguration": { "__typename": "RewardRedemptionConfiguration", "id": "", "type": "STATEMENT_CREDIT", "name": "configName", "rewardPointRedemption": { "rate": "1.0" }, "attachments": { "__typename": "RewardRedemptionConfigurationAttachmentConnection", "edges": [ { "cursor": "cursor", "node": { "attachRewardRedemptionConfigurationToProduct": { "__typename": "RewardRedemptionConfigurationProductAttachment", "redemptionConfiguration": { "id": "" }, "cardProduct": { "id": "" }, "effectiveFrom": "2023-01-01T00:00:00.000Z", "effectiveThrough": "2023-01-02T00:00:00.000Z" } } } ], "pageInfo": { "hasNextPage": false, "endCursor": "", "hasPreviousPage": false, "startCursor": "" } }, "createdAt": "1970-01-01T00:00:00.000Z", "updatedAt": "1970-01-01T00:00:00.000Z" } } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 503 } } } ### GraphQL: FindOrganizationWithRedemptionConfigurations Query: query FindOrganizationWithRedemptionConfigurations( $id: ID! $first: Int $after: String ) { node(id: $id) { __typename ... on Organization { rewardRedemptionConfigurations(first: $first, after: $after) { ... on RewardRedemptionConfigurationConnection { edges { node { __typename ... on RewardRedemptionConfiguration { id rewardPointRedemption { rate } attachments { ... on RewardRedemptionConfigurationAttachmentConnection { pageInfo { hasNextPage hasPreviousPage endCursor startCursor } edges { node { effectiveFrom effectiveThrough redemptionConfiguration { id } ... on RewardRedemptionConfigurationProductAttachment { cardProduct { id } redemptionConfiguration { id } effectiveFrom effectiveThrough } } } } } createdAt updatedAt } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "Organization", "rewardRedemptionConfigurations": { "pageInfo": { "startCursor": "startCursor", "hasNextPage": false }, "edges": [ { "node": { "__typename": "RewardRedemptionConfiguration", "id": "configId", "type": "STATEMENT_CREDIT", "name": "configName", "rewardPointRedemption": { "rate": "1.0" }, "attachments": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "endCursor": "endCursor", "startCursor": "startCursor" }, "edges": [ { "node": { "redemptionConfiguration": { "id": "" }, "cardProduct": { "id": "" }, "effectiveFrom": "2023-01-01T00:00:00.000Z", "effectiveThrough": "2023-01-02T00:00:00.000Z" } } ] }, "createdAt": "1970-01-01T00:00:00.000Z", "updatedAt": "1970-01-01T00:00:00.000Z" } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 1263 } } } --- URL: https://docs.highnote.com/docs/issuing/rewards/create-reward-earn-rule Title: Create Reward Earn Rule Section: Issuing Description: Create MCC-based and default reward earn rules, attach rules to card products, and configure earning rates per dollar spent. ## Overview Highnote's rewards feature supports creating rewards programs for your card products. The rewards feature works by using configurable reward earn rules. Once you attach a reward earn rule to your card product, account holders can earn rewards. They can then redeem these rewards through reward redemptions. Reward earn rules define how account holders earn rewards points. Highnote supports two types of reward earn rule configurations: - **MCC-based reward earn rules:** Earn rewards for dollars spent at specific MCCs - **Default reward earn rules:** Earn rewards for transactions that don’t qualify for specific earning rules You can use both MCC-based and default reward earn rules to create a robust rewards system. For example, you could use MCC-based earn rules to offer 3% cash back on travel. Then, you could use default earn rules to offer 1% cash back on everything else. Note the following guidelines when creating an MCC-based earn rule: - If a card product uses both MCC-based and default earn rules, Highnote prioritizes the MCC-based earn rule. - You can't create two different MCC-based earn rules with the same MCC (ex: a restaurant with 3% cash back and a different restaurant with 2% cash back). ## Enable the feature To offer rewards for your card product, you must contact support@highnote.com to request access to the feature. The feature is enabled in the Test environment by default for all consumer revolving credit card products. To use the feature for your card product(s) in the Live environment, you must complete the following requirements: - Work with your Highnote Implementation team to define your reward program's policies and rules. - Get your rewards program approved by Highnote and the Partner Bank. - Once approved, work with your Highnote Implementation team to configure your reward earn rules and redemptions in your Live environment. The Test environment allows you to fully test the feature before going live. ## Reward point earnings When creating reward earn rules, you must set reward point earnings. Reward point earnings set your reward rate. For example, if you set a reward point earning of 2, your account holders will earn 2 points for every $1 spent. Highnote rounds down fractional reward points. For example, the following scenarios outline examples of a reward point earning rate of 1.57: - A cardholder who spends $100 would earn 157 reward points. - Another cardholder who spends $11.50 on a transaction would earn 18.055 reward points. Highnote rounds this number down to 18 reward points in the reward points ledger. ## Create MCC-based reward earn rule Once your rewards program is approved, the Highnote team will assist with creating reward earn rules in the Live environment. Use the following mutation to create an MCC-based reward earn rule in the Test environment. Adjust the rate according to your own reward point logic: ## Create default reward earn rule Once your rewards program is approved, the Highnote team will assist with creating reward earn rules in the Live environment. Use the following mutation to create a default reward earn rule in the Test environment. Adjust the rate according to your own reward point logic: ## Attach reward earn rule to card product Once your rewards program is approved, the Highnote team will assist with attaching your earn rules to your card product(s) in the Live environment. After creating a reward earn rule, you must attach it to a card product. This allows all account holders for that card product to start earning rewards. Use the following mutation to attach a reward earn rule to a card product in the Test environment: ## Update reward earn rule When updating the date, the data must be _now or in the future_. If a rule needs to be “deactivated” from earn reward points, the attachment’s date can be updated to stop earning points at a given time. Use the following mutation to update the attachment between the reward earn rule and the product in the Test environment: ## Find reward earn rule You can query for a reward earn rule to display it in your website or application. You can query for a reward earn rule using the following methods: - via reward earn rule ID - via card product ID - via organization ID ### via reward earn rule ID Use the following mutation to query for a reward earn rule using the reward earn rule ID: ### via product ID Use the following mutation to query for a reward earn rule using your card product ID: ### via organization Use the following mutation to query for a reward earn rule using your organization ID: ### GraphQL: CreateRewardMerchantCategoryEarnRule Query: mutation CreateRewardMerchantCategoryEarnRule( $input: CreateRewardMerchantCategoryEarnRuleInput! $firstAttachments: Int $afterAttachments: String ) { createRewardMerchantCategoryEarnRule(input: $input) { __typename ... on RewardMerchantCategoryEarnRule { id type name attachments(first: $firstAttachments, after: $afterAttachments) { __typename ... on RewardRuleAttachmentConnection { pageInfo { hasNextPage } edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { rewardEarnRule { id } cardProduct { id } } } } } } rewardPointEarning { rate } createdAt allowedList updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "name": "ruleName", "rewardPointEarning": { "rate": "1.5" }, "allowedList": [ "EATING_PLACES_RESTAURANTS", "FAST_FOOD_RESTAURANTS" ] } } Expected Result: { "data": { "createRewardMerchantCategoryEarnRule": { "__typename": "RewardMerchantCategoryEarnRule", "id": "", "name": "ruleName", "type": "PER_TRANSACTION_SPEND_AMOUNT", "attachments": { "__typename": "RewardRuleAttachmentConnection", "pageInfo": { "hasNextPage": false }, "edges": [] }, "rewardPointEarning": { "rate": "1.5" }, "createdAt": "2023-02-23T00:00:00.000Z", "allowedList": [ "EATING_PLACES_RESTAURANTS", "FAST_FOOD_RESTAURANTS" ], "updatedAt": "2023-02-23T00:00:00.000Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 54 } } } ### GraphQL: CreateRewardDefaultEarnRule Query: mutation CreateRewardDefaultEarnRule( $input: CreateRewardDefaultEarnRuleInput! ) { createRewardDefaultEarnRule(input: $input) { __typename ... on RewardDefaultEarnRule { id type name attachments { __typename ... on RewardRuleAttachmentConnection { pageInfo { hasNextPage hasPreviousPage endCursor startCursor } edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { rewardEarnRule { id } cardProduct { id } } } } } } rewardPointEarning { rate } createdAt updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "name": "ruleName", "rewardPointEarning": { "rate": "1.5" } } } Expected Result: { "data": { "createRewardDefaultEarnRule": { "__typename": "RewardDefaultEarnRule", "id": "", "type": "PER_TRANSACTION_SPEND_AMOUNT", "name": "ruleName", "attachments": { "__typename": "RewardRuleAttachmentConnection", "pageInfo": { "endCursor": "", "hasNextPage": false, "hasPreviousPage": false, "startCursor": "" }, "edges": [] }, "rewardPointEarning": { "rate": "1.5" }, "createdAt": "2023-02-23T00:00:00.000Z", "updatedAt": "2023-02-23T00:00:00.000Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 54 } } } ### GraphQL: AttachRewardEarnRuleToProduct Query: mutation AttachRewardEarnRuleToProduct( $input: AttachRewardEarnRuleToProductInput! ) { attachRewardEarnRuleToProduct(input: $input) { __typename ... on RewardRuleProductAttachment { effectiveFrom effectiveThrough rewardEarnRule { id } ... on RewardRuleProductAttachment { cardProduct { id } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "rewardRule": { "id": "" }, "effectiveFrom": "2023-02-23T00:00:00.000Z", "effectiveThrough": "2023-03-23T00:00:00.000Z" } } Expected Result: { "data": { "attachRewardEarnRuleToProduct": { "__typename": "RewardRuleProductAttachment", "cardProduct": { "id": "" }, "rewardEarnRule": { "id": "rer_abc123" }, "effectiveFrom": "2023-02-23T00:00:00.000Z", "effectiveThrough": "2023-03-23T00:00:00.000Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 12 } } } ### GraphQL: UpdateRewardRuleAttachment Query: mutation UpdateRewardRuleAttachment($input: UpdateRewardRuleAttachmentInput!) { updateRewardRuleAttachment(input: $input) { __typename ... on RewardRuleProductAttachment { id cardProduct { id } rewardEarnRule { id } effectiveFrom effectiveThrough } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "attachmentId": "", "effectiveThrough": "2023-03-24T00:00:00.000Z" } } Expected Result: { "data": { "updateRewardRuleAttachment": { "__typename": "RewardRuleProductAttachment", "id": "", "cardProduct": { "id": "" }, "rewardEarnRule": { "id": "" }, "effectiveFrom": "2023-02-23T00:00:00.000Z", "effectiveThrough": "2023-03-24T00:00:00.000Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 12 } } } ### GraphQL: FindRewardEarnRulesById Query: query FindRewardEarnRulesById($id: ID!, $first: Int, $after: String) { node(id: $id) { __typename ... on RewardMerchantCategoryEarnRule { id type name attachments(first: $first, after: $after) { __typename ... on RewardRuleAttachmentConnection { edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { cardProduct { id } } } } } } rewardPointEarning { rate } createdAt allowedList updatedAt } ... on RewardDefaultEarnRule { id type name attachments { __typename ... on RewardRuleAttachmentConnection { edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { cardProduct { id } } } } } } rewardPointEarning { rate } createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "createRewardMerchantCategoryEarnRule": { "__typename": "RewardMerchantCategoryEarnRule", "id": "", "type": "PER_TRANSACTION_SPEND_AMOUNT", "name": "ruleName", "attachments": { "__typename": "RewardRuleAttachmentConnection", "pageInfo": { "hasNextPage": false }, "edges": [ { "node": { "effectiveFrom": "2023-02-23T00:00:00.000Z", "effectiveThrough": "2023-03-23T00:00:00.000Z", "rewardEarnRule": { "id": "" }, "cardProduct": { "id": "" } } } ] }, "rewardPointEarning": { "rate": "1.5" }, "createdAt": "2023-02-23T00:00:00.000Z", "allowedList": [ "EATING_PLACES_RESTAURANTS", "FAST_FOOD_RESTAURANTS" ], "updatedAt": "2023-02-23T00:00:00.000Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 54 } } } ### GraphQL: FindCardProductWithRewardRules Query: query FindCardProductWithRewardRules($id: ID!) { node(id: $id) { __typename ... on CardProduct { attachedRewardRules { ... on RewardRuleAttachmentConnection { pageInfo { startCursor hasNextPage } edges { node { __typename effectiveFrom effectiveThrough rewardEarnRule { ... on RewardMerchantCategoryEarnRule { id type name attachments { __typename ... on RewardRuleAttachmentConnection { edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { cardProduct { id } } } } } } rewardPointEarning { rate } createdAt allowedList updatedAt } ... on RewardDefaultEarnRule { id type name attachments { __typename ... on RewardRuleAttachmentConnection { edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { cardProduct { id } } } } } } rewardPointEarning { rate } createdAt updatedAt } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "attachedEarnRules": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "dD0yMDIzLTA4LTEwVDIxJTNBNDclM0ExNC42NDYzMDQ0MDFaJmk9Y3JwcHRfN2EzYWM5YTdiMmQ5NGZjYzllOWVkODFhODhhNWM3MzY", "node": { "__typename": "RewardMerchantCategoryEarnRule", "id": "", "type": "PER_TRANSACTION_SPEND_AMOUNT", "name": "ruleName", "attachments": { "__typename": "RewardRuleAttachmentConnection", "pageInfo": { "hasNextPage": false }, "edges": [ { "node": { "effectiveFrom": "2023-02-23T00:00:00.000Z", "effectiveThrough": "2023-03-23T00:00:00.000Z", "rewardEarnRule": { "id": "" }, "cardProduct": { "id": "" } } } ] }, "rewardPointEarning": { "rate": "1.5" }, "createdAt": "2023-02-23T00:00:00.000Z", "allowedList": [ "EATING_PLACES_RESTAURANTS", "FAST_FOOD_RESTAURANTS" ], "updatedAt": "2023-02-23T00:00:00.000Z" } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 54 } } } ### GraphQL: FindOrganizationWithRewardRules Query: query FindOrganizationWithRewardRules($id: ID!) { node(id: $id) { __typename ... on Organization { rewardEarnRules { ... on RewardEarnRuleConnection { edges { node { __typename ... on RewardMerchantCategoryEarnRule { id type name attachments { __typename ... on RewardRuleAttachmentConnection { edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { cardProduct { id } } } } } } rewardPointEarning { rate } allowedList createdAt updatedAt } ... on RewardDefaultEarnRule { id type name attachments { __typename ... on RewardRuleAttachmentConnection { edges { node { effectiveFrom effectiveThrough ... on RewardRuleProductAttachment { cardProduct { id } } } } } } rewardPointEarning { rate } createdAt updatedAt } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "Organization", "rewardEarnRules": { "edges": [ { "node": { "__typename": "RewardMerchantCategoryEarnRule", "id": "rer_abcdef", "type": "PER_TRANSACTION_SPEND_AMOUNT", "name": "ruleName", "attachments": { "__typename": "RewardRuleAttachmentConnection", "pageInfo": { "hasNextPage": false }, "edges": [ { "node": { "effectiveFrom": "2023-02-23T00:00:00.000Z", "effectiveThrough": "2023-03-23T00:00:00.000Z", "cardProduct": { "id": "" }, "rewardEarnRule": { "id": "rer_abcdef" } } } ] }, "rewardPointEarning": { "rate": "1.5" }, "allowedList": [ "EATING_PLACES_RESTAURANTS", "FAST_FOOD_RESTAURANTS" ], "createdAt": "2023-02-23T00:00:00.000Z", "updatedAt": "2023-02-23T00:00:00.000Z" } } ] } } }, "extensions": { "requested": "", "rateLimit": { "cost": 463 } } } --- URL: https://docs.highnote.com/docs/issuing/rewards/redeem-rewards Title: Redeem Rewards Section: Issuing Description: Redeem reward points for statement credit using a reward redemption configuration. ## Overview Once an account holder earns reward points, they can redeem rewards. They can redeem rewards based on the redemption configurations you have added to your card product. At this time, rewards can be redeemed for statement credit. ## Redeem rewards for statement credit Use the following mutation to redeem rewards for statement credit. If your rewards program has more than one reward redemption configuration, reference the correct to ensure the correct redemption rule is applied: ### GraphQL: RedeemRewardsForStatementCredit Query: mutation RedeemRewards($input: RedeemRewardsForStatementCreditInput!) { redeemRewardsForStatementCredit(input: $input) { __typename ... on RewardPointsTransfer { id rewardPointsValue { currencyCode value } rewardPointsAmount { currencyCode value } createdAt updatedAt ledgers { name } status { ... on RewardPointsTransferSuccessStatus { status } ... on RewardPointsTransferFailureStatus { status statusReasonCode } } activity memo } } } Variables: { "input": { "financialAccountId": "", "redemption": { "redemptionConfigurationId": "", "pointsToRedeem": "REWARD POINTS" }, "memo": "memo", "externalTransactionIdentifier": "external-id" } } Expected Result: { "data": { "redeemRewardsForStatementCredit": { "__typename": "RewardPointsTransfer", "id": "", "rewardPointsValue": { "currencyCode": "USD", "value": 100 }, "rewardPointsAmount": { "currencyCode": "USD", "value": 10000 }, "createdAt": "2024-06-10T12:34:56Z", "updatedAt": "2024-06-10T12:34:56Z", "ledgers": [ { "name": "Main Ledger" } ], "status": { "__typename": "RewardPointsTransferSuccessStatus", "status": "COMPLETED" }, "activity": "REDEMPTION", "memo": "memo" } } } --- URL: https://docs.highnote.com/docs/issuing/spend-controls/collaborative-authorization-fleet Title: Collaborative Authorization Fleet Data Section: Issuing Description: Access Visa and Mastercard fleet data in collaborative authorization requests including purchase type, driver ID, vehicle ID, odometer reading, and fuel product details. ## Overview Highnote provides fleet-specific data from Visa and Mastercard during authorization requests, which can be used to enhance your collaborative authorization decision-making process. For an overview of the collaborative authorization feature, see Collaborative Authorization. This guide provides an overview of each card network's fleet-specific data, examples of request bodies, and resources to simulate fleet transactions in your Test environment. ## Fleet Data When a cardholder initiates a transaction, Highnote sends a collaborative authorization request to your endpoint that contains transaction data. Fleet collaborative authorization requests contain a field called or depending on the network. You can configure your collaborative authorization flow to use this data in decisioning. Note the following about fleet-specific collaborative authorization data: - Fleet data fields may be if the payment card is not configured to prompt the cardholder or POS did not return fleet information in the authorization message. - Fleet data provided by Visa and Mastercard differ. ## Visa For an overview of Visa product codes, see the Visa Fleet 2.0 Global Implementation Guide V1.2. The following data is available for Visa fleet card products: | Field | Description | Possible values | | :--------------------------------------- | :---------------------------------------------------------------------------------------------------- | :------------------------------------------------------------- | | | Indicates whether fuel or non-fuel items are included in the transaction | , , , | | | Indicates whether the transactions took place at a self-service or full-service station | , , | | | Indicates whether is an order or invoice number | | | | An alphanumeric value representing an order or invoice number provided by the cardholder | | | | An alphanumeric value representing either a vehicle, driver, or generic ID provided by the cardholder | | | | The odometer value provided by the cardholder | | | | An alphanumeric value representing the employee's ID number | | | | An alphanumeric value representing the trailer's ID number | | | | An alphanumeric value representing the answer to a custom prompt | | | | An alphanumeric value representing the answer to a custom prompt | | | | A list of non-fuel product codes for the products purchased | | | | Indicates whether the POS supports host-based restriction processing | | ## Mastercard For an overview of Mastercard prompt values and product codes, see the Mastercard Fleet Implementation Guide v4. The following data is available for Mastercard fleet card products: | Field | Description | | :--------------------------------------------- | :--------------------------------------------------------------------------------- | | | An alphanumeric value representing a driver ID provided by the cardholder | | | An alphanumeric value representing a vehicle ID provided by the cardholder | | | A list of prompt codes and cardholder-entered values | | | A list of fuel products purchased | | | A list of non-fuel products purchased | | | Indicates whether the POS supports overriding the fleet spend controls on the card | ## Request body When you receive a collaborative authorization request for a fleet card product, the request body contains fleet-specific data you can use in decisioning. Each request body has network-specific or . Note, some fields in a fleet collaborative authorization request body may be in the following scenarios: - The card is not configured to prompt the cardholder. - The POS did not return fleet information in the authorization message. ### Visa Request Example The following payload is an example of a Visa fleet collaborative authorization request body: ```json { "data": { "collaborativeAuthorizationRequest": { "id": "", "transaction": { "id": "" }, "transactionTimestamp": "2024-03-20T02:59:36.160Z", "paymentCard": { "id": "" }, "transactionAmount": { "value": 100, "currencyCode": "USD" }, "settlementAmount": { "value": 100, "currencyCode": "USD" }, "requestedAmount": { "value": 15000, "currencyCode": "USD" }, "surchargeFee": null, "merchantDetails": { "merchantId": "merchantId", "category": "AUTOMATED_FUEL_DISPENSERS", "categoryCode": "5542", "countryCodeAlpha3": "USA", "description": "KWIK TRIP 123456", "name": "My Awesome Fuel", "address": { "streetAddress": "", "extendedAddress": "", "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "responseCode": "PARTIAL_AMOUNT_APPROVED", "avsResponseCode": "NOT_PROVIDED", "postalCodeResponseCode": "NOT_PROVIDED", "cvvResponseCode": "MATCH", "pointOfServiceDetails": { "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true, "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAGNETIC_STRIPE" }, "createdAt": "2024-03-20T02:59:36.160Z", "visaFleetData": { "purchaseType": "FUEL_PURCHASE", "serviceType": "HIGH_SPEED_DISPENSE", "purchaseIdFormat": "INVOICE", "purchaseId": "purchaseIdentifier", "fleetId": "fleetIdentifier", "odometer": "odometer", "employeeNumber": "employeeNumber", "trailerNumber": "trailerNumber", "customPrompt1": "customPrompt1", "customPrompt2": "customPrompt2", "nonFuelProductCodes": [ "BATTERIES", "OIL_CHANGE", "LUBE", "ENGINE_SERVICE" ], "purchaseRestrictionsFlag": true }, "__typename": "PaymentCardAuthorizationRequest" } }, "extensions": { "signatureTimestamp": 1710903576292 } } ``` ### Mastercard example payload The following payload is an example of a Mastercard fleet collaborative authorization request body: ```json { "data": { "collaborativeAuthorizationRequest": { "id": "", "transaction": { "id": "" }, "transactionTimestamp": "2024-03-20T04:41:03.948Z", "paymentCard": { "id": "" }, "transactionAmount": { "value": 100, "currencyCode": "USD" }, "settlementAmount": { "value": 100, "currencyCode": "USD" }, "requestedAmount": { "value": 17500, "currencyCode": "USD" }, "surchargeFee": null, "merchantDetails": { "merchantId": "merchantId", "category": "AUTOMATED_FUEL_DISPENSERS", "categoryCode": "5542", "countryCodeAlpha3": "USA", "description": "The awesomest awesome fuel dispensers of all time super deluxe", "name": "My Awesome Fuel", "address": { "streetAddress": "", "extendedAddress": "", "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "responseCode": "PARTIAL_AMOUNT_APPROVED", "avsResponseCode": "NOT_PROVIDED", "postalCodeResponseCode": "NOT_PROVIDED", "cvvResponseCode": "MATCH", "pointOfServiceDetails": { "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true, "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAGNETIC_STRIPE" }, "createdAt": "2024-03-20T04:41:03.948Z", "mastercardFleetData": { "driverId": "driverIdentifier", "vehicleId": "vehicleIdentifier", "prompts": [ { "code": "BATTERY_VOLTAGE", "value": "500" }, { "code": "ODOMETER", "value": "1000000" } ], "fuelProducts": [ { "code": "PREMIUM_SUPER", "unitPrice": 1234, "unitPricePrecision": 3, "unitOfMeasure": "GALLONS", "quantity": 2345, "quantityPrecision": 3, "saleAmount": { "value": 200, "currencyCode": "USD" } }, { "code": "PREMIUM_DIESEL_1", "unitPrice": 34567, "unitPricePrecision": 4, "unitOfMeasure": "GALLONS", "quantity": 4567, "quantityPrecision": 3, "saleAmount": { "value": 300, "currencyCode": "USD" } } ], "nonFuelProducts": [ { "code": "BATTERIES", "unitOfMeasure": "EACH", "quantity": 5678, "quantityPrecision": 3, "extendedItemAmount": { "value": 400, "currencyCode": "USD" } }, { "code": "VEHICLE_PARKING", "unitOfMeasure": "HOURS", "quantity": 678, "quantityPrecision": 2, "extendedItemAmount": { "value": 500, "currencyCode": "USD" } } ], "spendControlOverrideFlag": true }, "__typename": "PaymentCardAuthorizationRequest" } }, "extensions": { "signatureTimestamp": 1710909664039 } } ``` ## Simulate fleet transactions To simulate collaborative authorization fleet data, you can use the fleet transaction simulator to simulate transactions in the Test environment. For more information, see Simulate Fleet Transactions. --- URL: https://docs.highnote.com/docs/issuing/spend-controls/collaborative-authorization Title: Collaborative Authorization Section: Issuing Description: Approve or decline transactions in real time using collaborative authorization webhooks. Register endpoints, verify HMAC signatures, and configure stand-in settings for timeouts. ## Overview Collaborative authorization lets you approve or decline transactions in real time based on your business logic. Where Spend Rules and Velocity Controls are declarative rules that you configure, Collaborative Authorization is a real-time webhook-style feature where you respond with an approve or decline decision for each transaction. It runs after Highnote's built-in checks pass, giving you a final say before the authorization goes through. Collaborative authorization requests are for initial authorizations only, not refund authorizations. This guide covers how to configure and activate a collaborative authorization endpoint, verify requests, make real-time authorization decisions, and simulate authorizations in the Test environment. ## Collaborative authorization flow The following steps demonstrate how collaborative authorization typically works on a card product: 1. An account holder makes a purchase which is sent to Highnote. 2. The purchase is passed through financial account balance checks and spend rules configured on the Highnote platform. 3. If the purchase passes these, an HTTPS POST request is sent to your collaborative authorization endpoint for approval. 4. You respond to the request with an approval or denial decision. 5. The authorization response is sent to the merchant with the decision. These steps are depicted in the following graphic: ## Enable the feature Collaborative authorization is self-service in your Test environment. In the Live environment, this feature must be enabled for your product by the Highnote team. To start using collaborative authorization, you must complete the following steps: 1. Have the Highnote team enable the feature for your card product. Contact support@highnote.com. 2. Register a collaborative authorization endpoint. 3. Activate the collaborative authorization endpoint. 4. Configure your request and response process. 5. _Optional_ - Test the feature. ## Manage endpoints You can manage collaborative authorization endpoints using the Highnote Dashboard or API. ### via the Dashboard When managing collaborative authorization endpoints using the Highnote Dashboard, refer to Collaborative authorization in the Support docs. ### via the Highnote API When managing collaborative authorization endpoints using the Highnote API, note the following: - You can have up to **5** collaborative authorization endpoints, but only **1** endpoint can be active at a time. - Collaborative authorization requests are sent as HTTPS POST requests with JSON bodies. The following headers are included on each request: - : - : The result of computing an HMAC 256 signature of the request body - : Always use constant-time comparison (like timingSafeEqual) to prevent timing attacks. ## Register an endpoint Use the following mutation to register and add a collaborative authorization endpoint. By default, collaborative authorization endpoints are _inactive_ at creation. When registering a collaborative authorization endpoint, refer to the following requirements: - Make the endpoint highly available. - The endpoint must be capable of returning a response. All other status codes result in the transaction being declined. - The endpoint requests and responses must be served via HTTPS. ## Activate an endpoint Only **1** endpoint can be at a time. Activating an endpoint automatically deactivates any existing active endpoints. Once a collaborative authorization endpoint has been registered, you must activate and verify it. Use the following mutation to activate a collaborative authorization endpoint: ## Request and response guidelines The is an idempotent key. In the event of a retry, Highnote resends the same request to your collaborative authorization endpoint with the same . Collaborative authorization request events differ from payment card authorization notification events. Refer to the following guidelines for handling collaborative authorization requests and responses: - You have up to **2** seconds to respond to a collaborative authorization request with an approval or denial decision. - Returning any HTTP response code except 2XX causes the collaborative authorization request to fail and trigger your stand-in authorization settings. - Failure to respond to a request within 2 seconds causes the collaborative authorization request to fail and trigger your stand-in authorization settings. When your endpoint fails to respond (timeout or non-2XX), Highnote uses your card product's **stand-in settings** to approve or decline the transaction. Contact support@highnote.com to configure stand-in behavior. ## Request body A collaborative authorization request is an HTTPS POST request with a JSON body. ### Amount fields A collaborative authorization request body has several amount fields relating to a transaction's money movement. These amount fields may differ from one request to another. | Field | Description | | :---------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | | transactionAmount | The amount the merchant requested for the transaction, displayed in the local (transaction) currency. | | settlementAmount | The converted to the settlement currency. | | requestedAmount | The amount of funds approved by the issuer in the settlement currency. May include surcharge fees. In some use cases, this value can exceed . | | cashBackAmount | Cash back the cardholder requested at the point of sale, in the transaction currency. Present only when the transaction includes cash back; omitted otherwise. | ### Other notes - The field refers to Highnote's preliminary authorization decision before calling your endpoint. - The object contains metadata about the request, specifically the which is the Unix timestamp (milliseconds) when the request was signed. Use this to verify request freshness and prevent replay attacks. - The , , and fields are omitted from the request body when they don't apply to the transaction, rather than sent as . ### Point-of-service details The object describes the terminal and entry conditions for the transaction, including (the point-of-service category) and . The object is omitted from the request body when no point-of-service details are available. ### Additional network data The object carries network-specific identifiers for the transaction. Its shape depends on the card network, identified by the field: - — includes a . - — includes a . Both types share , , and . The object is omitted from the request body when no network data is available. ### Cashback When a cardholder requests cash back at the point of sale, the request body includes a in the transaction currency. The field is omitted when the transaction has no cash back. ```json title="Cashback example" { "cashBackAmount": { "value": 500, "currencyCode": "USD" } } ``` ### Example - US request payload The following code snippet provides an example of a collaborative authorization request body. ```json { "data": { "collaborativeAuthorizationRequest": { "__typename": "PaymentCardAuthorizationRequest", "id": "te_01", "transaction": { "id": "tx_01" }, "transactionTimestamp": "2022-12-07T20:57:26.052Z", "paymentCard": { "id": "cd_01" }, "transactionAmount": { "value": 1000, "currencyCode": "USD" }, "settlementAmount": { "value": 1000, "currencyCode": "USD" }, "requestedAmount": { "value": 1000, "currencyCode": "USD" }, "surchargeFee": null, "merchantDetails": { "merchantId": "301100000m2d1gz", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "7399", "countryCodeAlpha3": "USA", "description": "HNT*Highnote Biz Servi San Francisco USA", "name": "HNT*Highnote Biz Servi", "address": { "streetAddress": "", "extendedAddress": null, "postalCode": "94107", "region": "CA", "locality": "SAN FRANCISCO", "countryCodeAlpha3": "USA" } }, "responseCode": "APPROVED", "avsResponseCode": "MATCH", "postalCodeResponseCode": "MATCH", "cvvResponseCode": "MATCH", "pointOfServiceDetails": { "panEntryMode": "CONTACTLESS_VIA_CHIP_RULES", "pinEntryMode": null, "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "isRecurring": null, "terminalSupportsPartialApproval": false, "category": "ECOMMERCE", "cardDataInputCapability": "CONTACTLESS_READ_VIA_CHIP_RULES" }, "additionalNetworkData": { "__typename": "MastercardData", "retrievalReferenceNumber": "010000123456", "acquiringInstitutionIdentificationCode": "012345", "paymentFacilitatorIdentifier": null, "fraudScore": null }, "createdAt": "2022-12-07T20:57:26.052Z" } }, "extensions": { "signatureTimestamp": 1670446646658 } } ``` ### Example - Cross-border request payload The following code snippet provides an example of a cross-border collaborative authorization request body: ```json { "data": { "collaborativeAuthorizationRequest": { "__typename": "PaymentCardAuthorizationRequest", "id": "te_02", "transaction": { "id": "tx_02" }, "transactionTimestamp": "2022-12-07T20:57:26.052Z", "paymentCard": { "id": "cd_02" }, "transactionAmount": { "value": 1200, "currencyCode": "CAD" }, "settlementAmount": { "value": 1000, "currencyCode": "USD" }, "requestedAmount": { "value": 1000, "currencyCode": "USD" }, "surchargeFee": null, "merchantDetails": { "merchantId": "040080092661007", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5651", "countryCodeAlpha3": "CAN", "description": "HOMESENSE 013 ETOBICOKE CA", "name": "HOMESENSE 013", "address": { "streetAddress": "", "extendedAddress": null, "postalCode": "M9C5H5000", "region": 67, "locality": "ETOBICOKE", "countryCodeAlpha3": "CAN" } }, "responseCode": "APPROVED", "avsResponseCode": "MATCH", "postalCodeResponseCode": "MATCH", "cvvResponseCode": "MATCH", "pointOfServiceDetails": { "panEntryMode": "CONTACTLESS_VIA_CHIP_RULES", "pinEntryMode": null, "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "isRecurring": null, "terminalSupportsPartialApproval": false, "category": "ECOMMERCE", "cardDataInputCapability": "CONTACTLESS_READ_VIA_CHIP_RULES" }, "additionalNetworkData": { "__typename": "VisaData", "retrievalReferenceNumber": "020000654321", "acquiringInstitutionIdentificationCode": "067890", "paymentFacilitatorIdentifier": null, "riskScore": null }, "createdAt": "2022-12-07T20:57:26.052Z" } }, "extensions": { "signatureTimestamp": 1670446646658 } } ``` ## Response Collaborative authorization response bodies may have the following fields: | Field | Description | | :----------------- | :---------------------------------------------------- | | | Unique identifier of the transaction | | | Transaction authorization response | | | An Amount object | For a full list of collaborative authorization response codes, see CollaborativeAuthorizationResponseCode in the API reference. ### Approved response When your endpoint responds with the following payload, an will reflect a status of . The following code snippet provides an example response body: ```json title="Approved response" { "transaction": { "id": "tx_03" }, "responseCode": "APPROVED" } ``` ### Partial amount approved response For partial approvals, the cannot be greater than the and must be expressed in the same currency. When your endpoint responds with the following payload, an reflects a status of . The merchant must report whether their point of sale can accept a partial amount via the field in the object: ```json title="Partial amount approved response" { "transaction": { "id": "tx_04" }, "authorizedAmount": { "value": 100, "currencyCode": "USD" }, "responseCode": "PARTIAL_AMOUNT_APPROVED" } ``` ### Declined response When you need to decline an , your endpoint passes back an appropriate response code reflecting why your system declined the authorization: ```json title="Declined response" { "transaction": { "id": "tx_05" }, "responseCode": "INSUFFICIENT_FUNDS" } ``` ## Response codes During collaborative authorization, when Highnote receives an authorization from the payment network, Highnote responds with one of three initial response codes: - - - You will only see a collaborative authorization request in your system if Highnote sends an or response. When your system responds to the collaborative authorization request, the resulting response code from Highnote's platform follows the pattern described in the following tables. ### Approved response codes The following table provides an overview of scenarios when Highnote provides an response to a : | Initial Highnote response | Your system's response | Final Highnote platform response code | | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------ | | | Your system returns an response without or with equal to | | | | Your system returns an response with less than and the POS supports partial approval | | | | Your system returns an response with less than and POS does not support partial approval | | | | Your system returns an response with more than | | | | Your system responds with an response and is _not_ equal to and POS does not support partial approval | | | | Your system returns a response without | | | | Your system returns a response with equal to | | | | Your system returns a response with more than | | | | Your system returns a response with less than | | | | Your system returns a and is _not_ equal to and POS does not support partial approval | | | | Your system returns a response with a different currency code than | | ### Partial amount approved response codes The following table provides an overview of scenarios when Highnote provides an response to a : | Initial Highnote response | Your system's response | Final Highnote platform response code | | :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------ | | | Your system returns an response without or with equal to | | | | Your system returns an response with less than | | | | Your system returns an response with more than | | | | Your system returns an response without | | | | Your system returns a response with equal to | | | | Your system returns a response with more than | | | | Your system returns a response with less than | | | | Your system returns a response and is _not_ equal to and POS does not support partial approval | | | | Your system returns a response with a different currency code than | | ## Find collaborative authorization key When you register a collaborative authorization endpoint, the API returns a secret key. If you need to retrieve this key again, you can query the object to retrieve the field. Use the following query to retrieve a collaborative authorization endpoint's secret key: ## Simulate collaborative authorization Use the collaborative authorization simulation to test your endpoints in the Test environment. For more information, see Simulate Collaborative Authorization. ### GraphQL: AddCollaborativeAuthorizationEndpoint Query: mutation AddCollaborativeAuthorizationEndpoint( $input: AddCollaborativeAuthorizationEndpointInput! ) { addCollaborativeAuthorizationEndpoint(input: $input) { ... on CollaborativeAuthorizationEndpoint { id name uri status signingKeys { id secret } createdAt updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "name": "My Collaborative Auth Endpoint", "uri": "https://webhook.site" } } Expected Result: { "data": { "addCollaborativeAuthorizationEndpoint": { "__typename": "CollaborativeAuthorizationEndpoint", "id": "", "name": "My Collaborative Auth Endpoint", "uri": "https://webhook.site", "createdAt": "2021-11-19T19:16:23.477Z", "updatedAt": "2021-11-19T19:16:23.477Z", "status": "PENDING_VERIFICATION", "signingKeys": [ { "id": "", "secret": "some_secret" } ] } }, "extensions": { "requestId": "" } } ### GraphQL: ActivateCollaborativeAuthorizationEndpoint Query: mutation ActivateCollaborativeAuthorizationEndpoint( $input: ActivateCollaborativeAuthorizationEndpointInput! ) { activateCollaborativeAuthorizationEndpoint(input: $input) { ... on CollaborativeAuthorizationEndpoint { id name uri status } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "endpointId": "" } } Expected Result: { "data": { "activateCollaborativeAuthorizationEndpoint": { "__typename": "CollaborativeAuthorizationEndpoint", "id": "", "name": "My Collaborative Auth Endpoint", "uri": "https://webhook.site", "status": "ACTIVE" } }, "extensions": { "requestId": "" } } ### GraphQL: CollaborativeAuthorizationEndpoint Query: query CollaborativeAuthorizationEndpoint($id: ID!) { node(id: $id) { __typename ... on CollaborativeAuthorizationEndpoint { id signingKeys { id secret createdAt } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CollaborativeAuthorizationEndpoint", "id": "", "signingKeys": [ { "id": "", "secret": "", "createdAt": "2024-06-06T16:12:20.800Z" } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 2, "limit": 100000, "remaining": 99998 } } } --- URL: https://docs.highnote.com/docs/issuing/spend-controls/spend-rules Title: Configure Spend Rules Section: Issuing Description: Create and attach spend rules to card products, individual payment cards, or financial accounts. Configure over 15 rule types including amount limits, MCC restrictions, CVV requirements, and merchant country controls. ## Overview Spend rules apply logic to **authorized amounts** (not requested amounts). Reversals impact the cumulative authorized amount; but refunds do not. Spend rule & velocity control results may not be visible for up to 15 seconds after a Transaction Event. See Spend rule latency. Spend rules let you automate logic on authorizations that permit or restrict transactions. You can configure that logic on merchant category codes (MCC), dollar amount, authorization count, and more. The following graphic shows how a spend rule is created at the organization level, applied to a card product and to payment cards under that card product: Spend rules can be coupled with velocity controls. Velocity controls let you set time boundary constraints to established spend rules. For more information on velocity controls, see Configure velocity controls. You can create spend rules from the Highnote Dashboard or by using the Highnote API. This guide provides an overview of creating spend rules using the Highnote API. ## Spend rule latency Spend Rule results are not updated immediately. Due to a synchronization between databases, there may be a 15 second delay after a Transaction Event before changes are visible. Affected Transaction Events are: - IssuerPreliminaryAuthorizationEvent - AuthorizationEvent - AuthorizationAndClearEvent - VerificationEvent - BalanceInquiryEvent ## Spend rules for authorized users Only authorized users with their own dedicated financial account can maintain unique spend rules. Spend rules and velocity controls can be applied to different user types such as an authorized user. To configure a spend rule for an authorized user, add the field to the mutation and input to . For examples, try out this small test using the snippets below: 1. Create spend rule for Merchant category code. 2. Copy the spendRuleId () from the response. 3. Paste the spendRuleId as input to Update spend rules (which is set to update the MCC rule). ## Authorization hold configuration An authorization hold reserves funds on a card when a transaction is authorized, releasing them if the transaction is not cleared within a set window. At the product level, Highnote can customize how authorization holds behave for specific MCC groupings: - Hold expiration time: how long a hold persists before it expires and the reserved funds are released. - Additional hold amount: for card-present authorizations in tip-related merchant categories such as restaurants, an extra percentage held on top of the authorized amount to cover anticipated gratuity, where the cleared amount often exceeds the initial authorization. To customize your product's authorization hold configuration, contact Highnote Support. ## Create spend rules To create spend rules using the Highnote API, you must call the API using the spend rule's unique mutation and input variables. ### Amount limit We recommend factoring in potential ATM fees when creating an amount spend rule. For example, if you want to create an amount spend rule of $500, we recommend setting the spend rule at $505 or $510 to avoid potential declines due to ATM fees. Amount limit spend rules are used to set limits on the maximum dollar amount a cardholder can spend in a single transaction. For example, if you create an amount limit spend rule of $100 for business expenses, the cardholder can purchase $100 worth of business expenses per transaction. Use the following mutation to create amount limit spend rules: ### Maximum amount variance on credit limit The maximum **amount variance** spend rule allows cumulative spend up to a fixed amount over a credit financial account's credit limit. This rule requires the and a Cardholder Agreement that discloses how cardholders opt in to over-limit transactions. See Over-Limit Transactions for prerequisites, configuration, and examples. ### Maximum percent variance on credit limit The maximum **percent variance** spend rule allows cumulative spend up to a whole-number percentage of a credit financial account's credit limit. A value of permits cumulative spend up to 150% of the limit. This rule requires the and a Cardholder Agreement that discloses how cardholders opt in to over-limit transactions. See Over-Limit Transactions for prerequisites, configuration, and examples. ### Authorization count limit You must attach authorization count spend rules to a velocity control. For more information on creating velocity controls, see Configure Velocity Controls. Authorization count limit spend rules set the maximum number of transactions a cardholder can authorize within a given period. Authorization count limit spend rules must be used with velocity controls to create the desired time restriction. For example, you may want to limit cardholders to three transactions per week. To create this limit, you must create an authorization count limit spend rule for three and attach the spend rule to a velocity control with a weekly window. Use the following mutation to create an authorization count limit spend rule: ### Card data input capability Card data input capability spend rules restrict or block payments based on how a point of service (POS) accepts payments. For example, you can block all payments where a POS terminal only supports . For a full list of card data input capabilities, see the API reference. The following mutation is an example of a spend rule that blocks POS terminals that only accept payments: ### Card transaction processing type A card transaction processing type refers to the method used to process a card event, such as a purchase or withdrawal. A card transaction processing type rule is a spend rule that allows or blocks card transaction processing types. For a full list of card transaction processing types, see the CardTransactionProcessingType enum in the API Reference. Use the following mutation to create a card transaction processing type rule: ### Card verification value (CVV) Card verification value (CVV) spend rules require cardholders to enter their payment card's CVV at the point of purchase to reduce the risk of fraudulent transactions. When a mismatched CVV is entered at checkout, this spend rule blocks authorizations. Use the following mutation to create a card verification value spend rule: ### Conditional rule You must pair conditional rules with a velocity control. For more information on creating velocity controls, see Configuring Velocity Controls. A conditional rule is a spend rule that combines multiple spend rules together in an all-or-nothing approach. Conditional rules are always paired with velocity rules. For a conditional rule to pass, it must meet the following requirements: - All rules contained within the velocity control must pass - All rules contained within the velocity control must fail Use the following mutation to create a conditional rule: ### Deposit amount A deposit amount spend rule limits the dollar amount that an account holder can deposit in their Highnote financial account. Use the following mutation to create a deposit amount spend rule: ### Deposit count You must pair deposit count spend rules with a velocity control. For more information on creating velocity controls, see Configuring Velocity Controls. A deposit count spend rule limits the numbers of times a cash deposit can be made within a set period. Deposit count spend rules must be combined with a velocity control. Use the following mutation to create a deposit count spend rule: ### Deposit processing network A deposit processing network spend rule limits which deposit processing networks can be used to make a deposit. For a full list of deposit processing networks, see the DepositProcessingNetwork enum in the API Reference. Use the following example to create a deposit processing network spend rule: ### Merchant category code (MCC) Merchant category code (MCC) spend rules limit spending based on the type of merchant a cardholder transacts with, identified by the merchant's four-digit MCC. You can allow or block spending by MCC code using /, or by the higher-level grouping using /. For a full list of merchant categories, see the MerchantCategory enum in the API Reference. Use the following mutation to create a merchant category spend rule: ### Merchant identifier (MID) You can add up to 200 MIDs to a MerchantIdentifierSpendRule object. When processing transactions, some merchants supply an identifier called the merchant identifier (MID). In the Highnote API, the merchant identifier field accepts the input of merchant or card acceptor identifiers. A merchant identifier spend rule allows you to limit transactions for specific merchant identifiers. For example, you can restrict cardholders from using their payment cards at a particular online retailer. Use the following mutation to create a merchant identifier spend rule: ### Merchant country Merchant country spend rules limit spending based on merchants' geographical locations. For example, you can create a merchant country spend rule that blocks cardholders from using their payment cards at merchants located in a specific country that your business has deemed high risk. For a full list of countries that can be blocked using spend rules, see the ISO3166Alpha3Country enum in the API Reference. Use the following mutation to create a merchant country spend rule: ### PAN entry mode A PAN entry mode spend rule can restrict or block payments based on the method the cardholder used to enter their card information. For example, you can block payments for manual entries, or . For a full list of PAN entry modes, see the API reference. The following mutation is an example of a PAN entry spend rule that blocks mag stripe transactions: ### Point of service category Point of service category spend rules can permit or restrict purchases at certain types of payment terminals, such as ATMs or gas station fuel dispensers. For a full list of point of service categories, see the PointOfServiceCategory enum in the API Reference. Use the following mutation to create a point of service category spend rule: ### Postal code verification Postal code verification spend rules specify which zip codes are allowed or blocked during address verification services (AVS). Use the following mutation to create a postal code verification spend rule: ### Street address Street address spend rules require cardholders to enter their payment card's associated address at the point of checkout for address validation service (AVS). AVS reduces the risk of fraud for card-not-present transactions, such as online transactions. When an address mismatch is entered at checkout, this spend rule blocks authorizations. Use the following mutation to create a street address spend rule: ## Attach spend rule to a card product Once you have created a spend rule, you can attach it to a card product. Spend rules attached to card products apply to _all_ payment cards issued to the card product. Use the following mutation to attach a spend rule to a card product: ## Attach spend rule to a payment card Once you have created a spend rule, you can attach it to a payment card. Spend rules attached to payment cards apply to only that specific payment card. Use the following mutation to attach a spend rule to a payment card: ## Attach spend rule to a financial account Once you have created a spend rule, you can attach it to a financial account. Spend rules attached to financial accounts apply to _all_ payment cards linked to the financial account. Use the following mutation to attach a spend rule to a financial account: ## Attach new spend rule version You can create different versions of spend rules. For example, you may want to update a spend rule without affecting existing card products, payment cards, or financial accounts. By creating a new version of a spend rule, you can attach the new version to new card products, payment cards, or financial accounts without affecting the already applied spend rules on existing ones. To create and attach different versions of spend rules, refer to the following steps: 1. Use the unique mutation for each spend rule to create a spend rule. 2. In the input variable field, add the input field and provide a version number. 3. Run the mutation. 4. Use the , , or mutations to attach a spend rule to your card product, payment card, or financial account. 5. In the input variable field, add the input field and provide the version number of your new spend rule. 6. _Optional_ - Use instead of the version number to ensure the card product, payment card, or financial account always uses the latest version. 7. Run the mutation. ## Detach spend rule from a card product Use the following mutation to detach a spend rule from a card product: ## Detach spend rule from a payment card Use the following mutation to detach a spend rule from a payment card: ## Detach spend rule from a financial account Use the following mutation to detach a spend rule from a financial account: ## View spend rule results You can query s to view the results of an authorization decision and any associated spend rules associated with an authorization. Use the following query to view spend rule results: ## Update spend rules To update a spend rule: 1. Use the spend rule's unique mutation. 2. Assign the updated spend rule a new version number. 3. Attach the new version to any card products or payment cards using the original spend rule. For a full list of available mutations, refer to the following API Reference links: - updateConditionalRuleSetSpendRule - updateCountLimitSpendRule - updateCVVSpendRule - updateDepositAmountLimitSpendRule - updateDepositCountLimitSpendRule - updateDepositProcessingNetworkSpendRule - updateMerchantCategorySpendRule - updateMerchantCountrySpendRule - updateMerchantIdentifierSpendRule - updatePointOfServiceCategorySpendRule - updateStreetAddressSpendRule The following code snippet provides an example of how you would update a merchant category spend rule: ### GraphQL: CreateAmountLimitSpendRule Query: mutation CreateAmountLimitSpendRule($input: CreateAmountLimitSpendRuleInput!) { createAmountLimitSpendRule(input: $input) { __typename ... on AmountLimitSpendRule { id name version maximumAmount { value currencyCode } createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My amount Rule", "maximumAmount": { "value": 1000, "currencyCode": "USD" }, "userType": "AUTHORIZED_USER" } } Expected Result: { "data": { "createAmountLimitSpendRule": { "__typename": "AmountLimitSpendRule", "id": "", "name": "My amount Rule", "version": "0", "maximumAmount": { "value": 10000, "currencyCode": "USD" }, "createdAt": "2022-08-19T21:07:32.121Z", "updatedAt": "2022-08-19T21:07:32.121Z", "userType": "AUTHORIZED_USER" } }, "extensions": { "requestId": "" } } ### GraphQL: CreateCountLimitSpendRule Query: mutation createCountLimitSpendRule($input: CreateCountLimitSpendRuleInput!) { createCountLimitSpendRule(input: $input) { __typename ... on CountLimitSpendRule { id name maximumCount version createdAt updatedAt userType } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Count Rule", "maximumCount": 3 } } Expected Result: { "data": { "createCountSpendRule": { "__typename": "CountLimitSpendRule", "id": "", "name": "My Count Rule", "version": "0", "maximumCount": 3, "createdAt": "2022-08-19T21:07:32.121Z", "updatedAt": "2022-08-19T21:07:32.121Z", "userType": null } }, "extensions": { "requestId": "" } } ### GraphQL: CreateCardDataInputCapabilitySpendRule Query: mutation CreateCardDataInputCapabilitySpendRule( $input: CreateCardDataInputCapabilitySpendRuleInput! ) { createCardDataInputCapabilitySpendRule(input: $input) { __typename ... on CardDataInputCapabilitySpendRule { id name allowed blocked version createdAt updatedAt userType } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My CardDataInputCapability Spend Rule", "allowed": [ "MAG_STRIPE_READER_AND_EMV_ICC" ], "blocked": [ "MAGNETIC_STRIPE" ] } } Expected Result: { "data": { "createCardDataInputCapabilitySpendRule": { "__typename": "CardDataInputCapabilitySpendRule", "id": "", "name": "My CardDataInputCapability Spend Rule", "allowed": [ "MAG_STRIPE_READER_AND_EMV_ICC" ], "blocked": [ "MAGNETIC_STRIPE" ], "version": "0", "createdAt": "2024-07-19T21:08:13.423Z", "updatedAt": "2024-07-19T21:08:13.423Z", "userType": null } }, "extensions": { "requestId": "8ac2df8d-a976-907f-a940-f2f9d7b1e698", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60049 } } } ### GraphQL: CreateCardTransactionProcessingTypeConditionSpendRule Query: mutation CreateCardTransactionProcessingTypeConditionSpendRule( $input: CreateCardTransactionProcessingTypeConditionSpendRuleInput! ) { createCardTransactionProcessingTypeConditionSpendRule(input: $input) { __typename ... on CardTransactionProcessingTypeConditionSpendRule { id name allowed blocked version createdAt updatedAt userType revisions { edges { node { id } } } } } } Variables: { "input": { "name": "My Rule", "allowed": "CASH", "blocked": "PIN_CHANGE" } } Expected Result: { "data": { "createCardTransactionProcessingTypeConditionSpendRule": { "__typename": "CardTransactionProcessingTypeConditionSpendRule", "id": "", "name": "My Rule", "allowed": "CASH", "blocked": "GOODS_AND_SERVICES", "version": "0", "createdAt": "2024-01-03T19:38:02.998Z", "updatedAt": "2024-01-03T19:38:02.998Z", "userType": null, "revisions": { "edges": [] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 32, "limit": 100, "remaining": 99968 } } } ### GraphQL: CreateCVVSpendRule Query: mutation CreateCardVerificationValueRule($input: CreateCVVSpendRuleInput!) { createCVVSpendRule(input: $input) { __typename ... on CVVSpendRule { id name version allowed blocked createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My CVV Rule", "allowed": [ "MATCH" ] } } Expected Result: { "data": { "createCVVSpendRule": { "__typename": "CVVSpendRule", "id": "", "name": "My CVV Rule", "version": "0", "allowed": [ "MATCH" ], "blocked": [], "createdAt": "2022-08-23T14:11:16.882Z", "updatedAt": "2022-08-23T14:11:16.882Z", "userType": null } }, "extensions": { "requestId": "" } } ### GraphQL: CreateConditionalRuleSetSpendRule Query: mutation CreateConditionalRuleSetSpendRule( $input: CreateConditionalRuleSetSpendRuleInput! ) { createConditionalRuleSetSpendRule(input: $input) { __typename ... on ConditionalRuleSetSpendRule { id name allow version createdAt updatedAt userType revisions { edges { node { id } } } } } } Variables: { "input": { "name": "My Rule", "allow": true } } Expected Result: { "data": { "createConditionalRuleSetSpendRule": { "__typename": "ConditionalRuleSetSpendRule", "id": "", "name": "My Rule", "allow": true, "version": "0", "createdAt": "2024-01-03T19:38:02.998Z", "updatedAt": "2024-01-03T19:38:02.998Z", "userType": null, "revisions": { "edges": [] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 32, "limit": 100, "remaining": 99968 } } } ### GraphQL: CreateDepositAmountLimitSpendRule Query: mutation CreateDepositAmountLimitSpendRule( $input: CreateDepositAmountLimitSpendRuleInput! ) { createDepositAmountLimitSpendRule(input: $input) { __typename ... on DepositAmountLimitSpendRule { id name maximumAmount { value currencyCode } version createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Rule", "maximumAmount": { "value": 1000, "currencyCode": "USD" } } } Expected Result: { "data": { "createDepositAmountLimitSpendRule": { "__typename": "DepositAmountLimitSpendRule", "id": "", "name": "My Rule", "maximumAmount": { "value": 1000, "currencyCode": "USD" }, "version": "0", "createdAt": "2024-01-03T18:29:48.309Z", "updatedAt": "2024-01-03T18:29:48.310Z", "userType": null } }, "extensions": { "requestId": "", "rateLimit": { "cost": 33, "limit": 100, "remaining": 99967 } } } ### GraphQL: CreateDepositCountLimitSpendRule Query: mutation CreateDepositCountLimitSpendRule( $input: CreateDepositCountLimitSpendRuleInput! ) { createDepositCountLimitSpendRule(input: $input) { __typename ... on DepositCountLimitSpendRule { id name maximumCount version createdAt updatedAt userType revisions { edges { node { id } } } } } } Variables: { "input": { "name": "My Rule", "maximumCount": 10 } } Expected Result: { "data": { "createDepositCountLimitSpendRule": { "__typename": "DepositCountLimitSpendRule", "id": "", "name": "My Rule", "maximumCount": 10, "version": "0", "createdAt": "2024-01-03T18:42:41.555Z", "updatedAt": "2024-01-03T18:42:41.556Z", "userType": null, "revisions": { "edges": [] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 32, "limit": 100, "remaining": 99968 } } } ### GraphQL: CreateDepositProcessingNetworkSpendRule Query: mutation CreateDepositProcessingNetworkSpendRule( $input: CreateDepositProcessingNetworkSpendRuleInput! ) { createDepositProcessingNetworkSpendRule(input: $input) { __typename ... on DepositProcessingNetworkSpendRule { id name allowed blocked version createdAt updatedAt userType revisions { edges { node { id } } } } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Rule", "allowed": "MAESTRO", "blocked": "UNKNOWN" } } Expected Result: { "data": { "createDepositProcessingNetworkSpendRule": { "__typename": "DepositProcessingNetworkSpendRule", "id": "", "name": "My Rule", "allowed": [ "MAESTRO" ], "blocked": [ "UNKNOWN" ], "version": "0", "createdAt": "2024-01-03T18:36:57.388Z", "updatedAt": "2024-01-03T18:36:57.388Z", "userType": null, "revisions": { "edges": [] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 32, "limit": 100, "remaining": 99968 } } } ### GraphQL: CreateMerchantCategorySpendRule Query: mutation CreateMerchantCategorySpendRule( $input: CreateMerchantCategorySpendRuleInput! ) { createMerchantCategorySpendRule(input: $input) { __typename ... on MerchantCategorySpendRule { id name version allowed blocked createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Rule", "allowed": [ "AUTOMATED_FUEL_DISPENSERS" ], "blocked": [], "userType": "AUTHORIZED_USER" } } Expected Result: { "data": { "createMerchantCategorySpendRule": { "__typename": "MerchantCategorySpendRule", "id": "", "name": "My Rule", "version": "0", "allowed": [ "AUTOMATED_FUEL_DISPENSERS" ], "blocked": [], "createdAt": "2021-08-12T21:15:32.551Z", "updatedAt": "2021-08-12T21:15:32.551Z", "userType": "AUTHORIZED_USER" } } } ### GraphQL: CreateMerchantIdentifierSpendRule Query: mutation CreateMerchantIdentifierSpendRule( $input: CreateMerchantIdentifierSpendRuleInput! ) { createMerchantIdentifierSpendRule(input: $input) { __typename ... on MerchantIdentifierSpendRule { id name version allowed blocked createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "Enabled Merchant IDs", "allowed": [ "1234567898765432", "1234567898765433" ] } } Expected Result: { "data": { "createMerchantIdentifierSpendRule": { "__typename": "MerchantIdentifierSpendRule", "id": "", "name": "Enabled Merchant IDs", "version": "0", "allowed": [ "1234567898765432", "1234567898765433" ], "blocked": [], "createdAt": "2022-08-23T14:13:30.989Z", "updatedAt": "2022-08-23T14:13:30.989Z", "userType": null } }, "extensions": { "requestId": "" } } ### GraphQL: CreateMerchantCountrySpendRule Query: mutation CreateMerchantCountryRule( $input: CreateMerchantCountrySpendRuleInput! ) { createMerchantCountrySpendRule(input: $input) { __typename ... on MerchantCountrySpendRule { id name version allowed blocked createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Merchant Country Rule", "allowed": [ "USA" ] } } Expected Result: { "data": { "createMerchantCountrySpendRule": { "__typename": "MerchantCountrySpendRule", "id": "", "name": "My Merchant Country Rule", "version": "0", "allowed": [ "USA" ], "blocked": [], "createdAt": "2022-08-23T14:09:17.165Z", "updatedAt": "2022-08-23T14:09:17.165Z", "userType": null } }, "extensions": { "requestId": "" } } ### GraphQL: CreatePanEntryModeSpendRule Query: mutation CreatePanEntryModeSpendRule( $input: CreatePanEntryModeSpendRuleInput! ) { createPanEntryModeSpendRule(input: $input) { __typename ... on PanEntryModeSpendRule { id name allowed blocked version createdAt updatedAt userType } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Pan Entry Mode Spend Rule", "allowed": [ "INTEGRATED_CIRCUIT_CARD" ], "blocked": [ "MAGNETIC_STRIPE" ] } } Expected Result: { "data": { "createPanEntryModeSpendRule": { "__typename": "PanEntryModeSpendRule", "id": "", "name": "My Pan Entry Mode Spend Rule", "allowed": [ "INTEGRATED_CIRCUIT_CARD" ], "blocked": [ "MAGNETIC_STRIPE" ], "version": "0", "createdAt": "2024-07-19T21:04:24.549Z", "updatedAt": "2024-07-19T21:04:24.549Z", "userType": null } }, "extensions": { "requestId": "62384733-2e27-98bb-8fa1-af92a7bff8fb", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60049 } } } ### GraphQL: CreatePointOfServiceCategorySpendRule Query: mutation CreatePointOfServiceCategorySpendRule( $input: CreatePointOfServiceCategorySpendRuleInput! ) { createPointOfServiceCategorySpendRule(input: $input) { __typename ... on PointOfServiceCategorySpendRule { id name version allowed blocked createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "Allow Automated Fuel Device and ATMs only", "allowed": [ "AUTOMATED_TELLER_MACHINE", "AUTOMATED_FUEL_DISPENSER" ] } } Expected Result: { "data": { "createPointOfServiceCategorySpendRule": { "__typename": "PointOfServiceCategorySpendRule", "id": "", "name": "Allow Automated Fuel Device and ATMs only", "version": "0", "allowed": [ "AUTOMATED_TELLER_MACHINE", "AUTOMATED_FUEL_DISPENSER" ], "blocked": [], "createdAt": "2022-08-23T14:13:30.989Z", "updatedAt": "2022-08-23T14:13:30.989Z", "userType": null } }, "extensions": { "requestId": "" } } ### GraphQL: CreatePostalCodeVerificationSpendRule Query: mutation createPostalCodeVerificationSpendRule( $input: CreatePostalCodeVerificationSpendRuleInput! ) { createPostalCodeVerificationSpendRule(input: $input) { __typename ... on PostalCodeVerificationSpendRule { name allowed blocked } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My spend rule", "allowed": [ "MATCH" ], "blocked": [ "NO_MATCH" ] } } Expected Result: { "data": { "createPostalCodeVerificationSpendRule": { "__typename": "PostalCodeVerificationSpendRule", "name": "My spend rule", "allowed": [ "MATCH" ], "blocked": [ "NO_MATCH" ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 100, "remaining": 99989 } } } ### GraphQL: CreateStreetAddressSpendRule Query: mutation CreateStreetAddressRule($input: CreateStreetAddressSpendRuleInput!) { createStreetAddressSpendRule(input: $input) { __typename ... on StreetAddressSpendRule { id name version allowed blocked createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Street Address Rule", "allowed": [ "MATCH" ] } } Expected Result: { "data": { "createStreetAddressSpendRule": { "__typename": "StreetAddressSpendRule", "id": "", "name": "My Street Address Rule", "version": "0", "allowed": [ "MATCH" ], "blocked": [], "createdAt": "2022-08-23T14:13:30.989Z", "updatedAt": "2022-08-23T14:13:30.989Z", "userType": null } }, "extensions": { "requestId": "" } } ### GraphQL: AttachSpendRuleToCardProduct Query: mutation AttachSpendRuleToCardProduct( $input: AttachSpendRuleToCardProductInput! ) { attachSpendRuleToCardProduct(input: $input) { ... on CardProduct { id attachedSpendRules { edges { node { ... on SpendRule { id name } } } } } ... on UserError { errors { code } } } } Variables: { "input": { "cardProductId": "", "spendRule": { "id": "", "version": "0" } } } Expected Result: { "data": { "attachSpendRuleToCardProduct": { "id": "", "attachedSpendRules": { "edges": [ { "node": { "id": "", "name": "My Rule" } } ] } } } } ### GraphQL: AttachSpendRuleToPaymentCard Query: mutation AttachSpendRuleToPaymentCard( $input: AttachSpendRuleToPaymentCardInput! ) { attachSpendRuleToPaymentCard(input: $input) { ... on PaymentCard { id attachedSpendRules { edges { node { ... on SpendRule { id name } } } } } ... on UserError { errors { code } } } } Variables: { "input": { "paymentCardId": "", "spendRule": { "id": "", "version": "0" } } } Expected Result: { "data": { "attachSpendRuleToPaymentCard": { "id": "", "attachedSpendRules": { "edges": [ { "node": { "id": "", "name": "My Rule" } } ] } } } } ### GraphQL: AttachSpendRuleToFinancialAccount Query: mutation AttachSpendRuleToFinancialAccount( $input: AttachSpendRuleToFinancialAccountInput! ) { attachSpendRuleToFinancialAccount(input: $input) { __typename ... on FinancialAccount { id } ... on UserError { errors { code path } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "spendRule": { "id": "", "version": "LATEST" } } } Expected Result: { "data": { "attachSpendRuleToFinancialAccount": { "__typename": "FinancialAccount", "id": "" } }, "extensions": { "requestId": "" } } ### GraphQL: DetachSpendRuleFromCardProduct Query: mutation DetachSpendRuleFromCardProduct( $input: DetachSpendRuleFromCardProductInput! ) { detachSpendRuleFromCardProduct(input: $input) { __typename ... on UserError { errors { code errorPath description __typename } __typename } } } Variables: { "input": { "cardProductId": "", "spendRule": { "id": "" } } } Expected Result: { "data": { "detachSpendRuleFromCardProduct": { "__typename": "CardProduct" } }, "extensions": { "requestId": "" } } ### GraphQL: DetachSpendRuleFromPaymentCard Query: mutation DetachSpendRuleFromPaymentCard( $input: DetachSpendRuleFromPaymentCardInput! ) { detachSpendRuleFromPaymentCard(input: $input) { __typename ... on UserError { errors { code errorPath description __typename } __typename } } } Variables: { "input": { "paymentCardId": "", "spendRule": { "id": "" } } } Expected Result: { "data": { "detachSpendRuleFromPaymentCard": { "__typename": "PaymentCard" } }, "extensions": { "requestId": "" } } ### GraphQL: DetachSpendRuleFromFinancialAccount Query: mutation DetachSpendRuleFromFinancialAccount( $input: DetachSpendRuleFromFinancialAccountInput! ) { detachSpendRuleFromFinancialAccount(input: $input) { __typename ... on FinancialAccount { id } ... on UserError { errors { code path } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "spendRule": { "id": "" } } } Expected Result: { "data": { "detachSpendRuleFromFinancialAccount": { "__typename": "FinancialAccount", "id": "" } }, "extensions": { "requestId": "" } } ### GraphQL: NodeAuthorizationEventWithSpendRuleResults Query: query nodeAuthorizationEventWithSpendRuleResults($id: ID!) { node(id: $id) { __typename ... on AuthorizationEvent { id transaction { ... on Node { id } } spendRuleResults { edges { node { __typename ... on SpendRuleResult { recommendation message } ... on VelocityRuleResult { recommendation message velocityRule { __typename id version } } } } } } } } Variables: { "id": "" } Expected Result: { "node": { "__typename": "AuthorizationEvent", "id": "", "transaction": { "node": { "id": "" } }, "spendRuleResults": { "edges": { "node": { "__typename": "VelocityRuleResult", "recommendation": "ALLOW", "message": "", "velocityRule": { "__typename": "VelocityRule", "id": "", "version": "0" } } } } } } ### GraphQL: UpdateMerchantCategorySpendRule Query: mutation UpdateMerchantCategorySpendRule( $input: UpdateMerchantCategorySpendRuleInput! ) { updateMerchantCategorySpendRule(input: $input) { __typename ... on MerchantCategorySpendRule { id name version allowed blocked createdAt updatedAt userType } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "spendRuleId": "", "allowed": [ "AUTOMATED_FUEL_DISPENSERS" ], "blocked": [], "userType": "AUTHORIZED_USER" } } Expected Result: { "data": { "updateMerchantCategorySpendRule": { "__typename": "MerchantCategorySpendRule", "id": "", "name": "My Rule", "version": "1", "allowed": [ "AUTOMATED_FUEL_DISPENSERS" ], "blocked": [], "createdAt": "2021-08-12T21:15:32.551Z", "updatedAt": "2021-08-12T21:42:22.412Z", "userType": "AUTHORIZED_USER" } } } --- URL: https://docs.highnote.com/docs/issuing/spend-controls/velocity-controls Title: Configure Velocity Controls Section: Issuing Description: Add time-based limits to spend rules with velocity controls. Configure daily, weekly, monthly, or per-transaction windows and attach them to card products, financial accounts, or individual cards. ## Overview Spend rule & velocity control results may not be visible for up to 15 seconds after a Transaction Event. See Spend rule latency. Velocity controls allow time boundary constraints to be applied to a spend rule. The following example explains the difference between velocity controls and spend rules: The following example explains the difference between velocity controls and spend rules: - A payment card has a spend rule to decline all authorizations over $1,000. - For the same payment card, a velocity control is added to decline any authorizations that exceed $1,000 within a calendar week. - This creates a velocity control that enforces a weekly spending limit of $1,000. The following graphic shows how a velocity control is created and applied at the card product and payment card levels: ## Velocity control windows You can set velocity control time frames using several time windows. The following table describes available velocity control windows: | Velocity Rule Window | Description | | :------------------- | :-------------------------------------------------------------------------------------------------------------- | | DAILY | One calendar day, 00:00:00 UTC to 11:59.59:00 UTC | | WEEKLY | One calendar week, UTC start of week (Monday) to UTC end of week (Sunday) | | MONTHLY | One calendar month, UTC start of month to UTC end of month | | NINETY_DAYS | 90 calendar days moving window. One calendar day is from 00:00:00 UTC to 11:59.59:00 UTC | | QUARTERLY | One calendar quarter, UTC start of quarter to UTC end of quarter | | | Q1: Jan - March, Q2: April - June, Q3: July - September, Q4: October - December | | YEARLY | One calendar year, UTC start of year to UTC end of year | | PER_TRANSACTION | Velocity Rule is evaluated on every transaction individually | | COOLDOWN_MINUTE | Cooldown period of one minute, e.g., with count rule of 1, cardholder must wait one minute between transactions | | COOLDOWN_HOUR | Cooldown period of one hour, e.g., with count rule of 1, cardholder must wait one hour between transactions | ## Limits You can add _three_ spend rules to a velocity control. Additionally, velocity controls have limits at the card product, financial account, and payment card levels: - **Card product:** Limit of 10 velocity controls per card product - **Financial account:** Limit of 10 velocity controls per financial account - **Payment card:** Limit of 10 velocity controls per payment card ## Velocity controls for authorized users To create velocity controls for an authorized user, ensure that the spend rules for that authorized user were created with . Other than that, there is no difference from the standard velocity control. ## Create velocity control An amount spend rule, or cumulative rule, is required to create a velocity control. To create a velocity control, you must first create spend rules, one of which must be an amount rule. You can add up to three spend rules to a velocity control. Create the velocity rule with the spend rule IDs. Velocity controls authorize transactions based on whether the associated spend rule's conditions are met within the velocity control window. The following example uses multiple spend rules to create a velocity control for airline purchases: 1. Create an amount limit spend rule for $1000. 2. Create a MCC spend rule for airline purchases. 3. Add both spend rules to a monthly velocity control. 4. Your velocity control will limit _only_ airline purchases to $1000 a month. Use the following mutation to create a velocity control: ## Attach velocity control to a card product Velocity controls can be attached to a card product, a financial account, or an individual payment card. Attaching a velocity control to a card product applies the spend rules and velocity control to all financial accounts and payment cards for your card product. Use the following mutation to create a velocity control for a card product: ## Attach velocity control to a payment card Velocity controls can be attached to a card product, a financial account, or an individual payment card. Velocity controls attached to a payment card only apply to that specific payment card. Use the following mutation to attach a velocity control to a payment card: ## Attach velocity control to a financial account Velocity controls can be attached to a card product, a financial account, or an individual payment card. Velocity controls attached to a financial account apply to _all_ payment cards linked to the financial account. Use the following mutation to attach a velocity control to a financial account: ## Detach velocity control from a card product If you detach and re-attach a velocity, the balance on the "count" and "windows" of the velocity control will reset. Use the following mutation to detach a velocity control from a card product: ## Detach velocity control from a payment card If you detach and re-attach a velocity, the balance on the "count" and "windows" of the velocity control will reset. Use the following mutation to detach a velocity control from a payment card: ## Detach velocity control from a financial account If you detach and re-attach a velocity, the balance on the "count" and "windows" of the velocity control will reset. Use the following mutation to detach a velocity control from a financial account: ## Edit a velocity control Editing a velocity control resets its balance, the same as detaching and re-attaching it. This includes changing the limit on one of its spend rules and renaming the velocity control itself — both trigger the reset, even a name-only change with no limit change. Spend already counted in the current window does not carry over. Use or to change the limit on a spend rule's cumulative rule. Use to rename a velocity control or change its user type; it does not accept a limit, but it still resets the balance. The reset takes effect on the next authorization that evaluates the velocity control, not immediately. A velocity control balance query made right after the edit can still return the pre-edit accumulated amount until that next transaction runs. ## List velocity controls Use the following query to find all velocity controls for your organization: ## Find velocity control balance Velocity controls track how much money has been spent within a certain window to help troubleshoot declined transactions. You can check the "balance" of a velocity control for a payment card or financial account. The balance reflects the total amount spent. Use the following query to find the velocity control balance on a financial account: ### GraphQL: CreateVelocityRule Query: mutation CreateVelocityRule($input: CreateVelocityRuleInput!) { createVelocityRule(input: $input) { __typename ... on VelocityRule { id name version velocityRuleWindow cumulativeRule { id } spendRules { id } createdAt updatedAt } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "name": "My Rule", "velocityRuleWindow": "DAILY", "cumulativeRule": { "id": "", "version": "0" }, "spendRules": [ { "id": "", "version": "0" } ] } } Expected Result: { "data": { "createVelocityRule": { "__typename": "VelocityRule", "id": "", "name": "My Rule", "version": "0", "cumulativeRule": { "id": "", "name": "dollar amount rule", "version": "0" }, "spendRules": [ { "id": "", "name": "Merchant Rule", "version": "0" } ], "createdAt": "2021-08-12T21:09:25.475Z", "updatedAt": "2021-08-12T21:09:25.476Z" } } } ### GraphQL: AttachCardProductVelocityRule Query: mutation AttachCardProductVelocityRule( $input: AttachCardProductVelocityRuleInput! ) { attachCardProductVelocityRule(input: $input) { __typename ... on VelocityRuleAssociation { velocityRule { id name version cumulativeRule { id name version } createdAt updatedAt } associatedTo { ... on Node { id } ... on CardProduct { id } } } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "cardProductId": "", "velocityRule": { "velocityRuleId": "" } } } Expected Result: { "data": { "attachCardProductVelocityRule": { "__typename": "VelocityRuleAssociation", "velocityRule": { "id": "", "name": "My Rule", "version": "0", "cumulativeRule": { "id": "", "name": "dollar amount rule", "version": "0" }, "createdAt": "2021-08-12T21:09:25.475Z", "updatedAt": "2021-08-12T21:09:25.476Z" }, "associatedTo": { "__typename": "CardProduct", "id": "" } } } } ### GraphQL: AttachPaymentCardVelocityRule Query: mutation AttachPaymentCardVelocityRule( $input: AttachPaymentCardVelocityRuleInput! ) { attachPaymentCardVelocityRule(input: $input) { __typename ... on VelocityRuleAssociation { velocityRule { id name version cumulativeRule { id name version } createdAt updatedAt } associatedTo { ... on Node { id } ... on PaymentCard { id } } } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "paymentCardId": "", "velocityRule": { "velocityRuleId": "" } } } Expected Result: { "data": { "attachPaymentCardVelocityRule": { "__typename": "VelocityRuleAssociation", "velocityRule": { "id": "", "name": "My Rule", "version": "0", "cumulativeRule": { "id": "", "name": "dollar amount rule", "version": "0" }, "createdAt": "2021-08-12T21:09:25.475Z", "updatedAt": "2021-08-12T21:09:25.476Z" }, "associatedTo": { "__typename": "PaymentCard", "id": "" } } } } ### GraphQL: AttachVelocityRuleToFinancialAccount Query: mutation AttachVelocityRuleToFinancialAccount( $input: AttachVelocityRuleToFinancialAccountInput! ) { attachVelocityRuleToFinancialAccount(input: $input) { __typename ... on FinancialAccount { id attachedVelocityRules { edges { node { id name version } } } } ... on UserError { errors { code path } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "velocityRule": { "velocityRuleId": "" } } } Expected Result: { "data": { "attachVelocityRuleToFinancialAccount": { "__typename": "FinancialAccount", "id": "", "attachedVelocityRules": { "edges": [ { "node": { "id": "", "name": "My Rule", "version": "0" } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: DetachCardProductVelocityRule Query: mutation DetachCardProductVelocityRule( $input: DetachCardProductVelocityRuleInput! ) { detachCardProductVelocityRule(input: $input) { __typename ... on VelocityRuleAssociation { velocityRule { id name version cumulativeRule { id name version } createdAt updatedAt } associatedTo { ... on Node { id } ... on CardProduct { id } } } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "cardProductId": "", "velocityRule": { "velocityRuleId": "" } } } Expected Result: { "data": { "detachCardProductVelocityRule": { "__typename": "VelocityRuleAssociation", "velocityRule": { "id": "", "name": "My Rule", "version": "0", "cumulativeRule": { "id": "", "name": "dollar amount rule", "version": "0" }, "createdAt": "2021-08-12T21:09:25.475Z", "updatedAt": "2021-08-12T21:09:25.476Z" }, "associatedTo": { "__typename": "CardProduct", "id": "" } } } } ### GraphQL: DetachPaymentCardVelocityRule Query: mutation DetachPaymentCardVelocityRule( $input: DetachPaymentCardVelocityRuleInput! ) { detachPaymentCardVelocityRule(input: $input) { __typename ... on VelocityRuleAssociation { velocityRule { id name version cumulativeRule { id name version } createdAt updatedAt } associatedTo { ... on Node { id } ... on PaymentCard { id } } } ... on UserError { errors { code errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "paymentCardId": "", "velocityRule": { "velocityRuleId": "" } } } Expected Result: { "data": { "detachPaymentCardVelocityRule": { "__typename": "VelocityRuleAssociation", "velocityRule": { "id": "", "name": "My Rule", "version": "0", "cumulativeRule": { "id": "", "name": "dollar amount rule", "version": "0" }, "createdAt": "2021-08-12T21:09:25.475Z", "updatedAt": "2021-08-12T21:09:25.476Z" }, "associatedTo": { "__typename": "PaymentCard", "id": "" } } } } ### GraphQL: DetachVelocityRuleFromFinancialAccount Query: mutation DetachVelocityRuleFromFinancialAccount( $input: DetachVelocityRuleFromFinancialAccountInput! ) { detachVelocityRuleFromFinancialAccount(input: $input) { __typename ... on FinancialAccount { id attachedVelocityRules { edges { node { id name version } } } } ... on UserError { errors { code path } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "velocityRule": { "velocityRuleId": "" } } } Expected Result: { "data": { "detachVelocityRuleFromFinancialAccount": { "__typename": "FinancialAccount", "id": "", "attachedVelocityRules": { "edges": [] } } }, "extensions": { "requestId": "" } } ### GraphQL: NodeOrganizationWithVelocityRules Query: query nodeOrganizationWithVelocityRules($id: ID!, $velocityRulesFirst: Int) { node(id: $id) { __typename ... on Organization { id velocityRules(first: $velocityRulesFirst) { pageInfo { hasNextPage hasPreviousPage } edges { node { __typename ... on VelocityRule { id name } } } } } } } Variables: { "id": "", "velocityRulesFirst": 1 } Expected Result: { "node": { "id": "", "velocityRules": { "pageInfo": { "hasNextPage": false }, "edges": [ { "node": { "__typename": "VelocityRule", "id": "", "name": "My Velocity Rule" } } ] } } } ### GraphQL: NodeFinancialAccountWithVelocityBalance Query: query nodeFinancialAccountWithVelocityBalance($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { id velocitySpendRuleBalances { ... on VelocitySpendRuleAmountBalance { __typename currentBalance { currencyCode value } remainingBalance { currencyCode value } velocityRule { id version name } } } } } } Variables: { "id": "" } Expected Result: { "node": { "id": "", "velocitySpendRuleBalances": { "currentBalance": { "value": "200", "currencyCode": "USD" }, "remainingBalance": { "value": "400", "currencyCode": "USD" }, "velocityRule": { "id": "", "name": "My Rule", "version": "0" } } } } --- URL: https://docs.highnote.com/docs/issuing/spend-controls/sim-collaborative-authorization Title: Simulate Collaborative Authorization Section: Issuing Description: Simulate collaborative authorization requests in the Test environment to verify your endpoint integration before going live. ## Overview Do not enter production data in the Test environment. The Highnote Test environment is for exploring features and training. Use only dummy or test data. Simulating collaborative authorization allows you to test your integration and notification events. This simulation requires the following steps: 1. Enable the collaborative authorization endpoint in your Test environment. 2. Register a collaborative authorization endpoint. 3. Activate a collaborative authorization endpoint. 4. Simulate an authorization. ## Prerequisites - A Highnote account - An API key or API Explorer - An active test payment card ## Enable collaborative authorization in test You can enable the collaborative authorization feature in your Test environment using the Highnote dashboard. For steps, see Enable collaborative authorization. ## Register an endpoint You can use the following mutation to register and add a collaborative authorization endpoint. By default, collaborative authorization endpoints are _inactive_ at creation. Refer to the following requirements when registering a collaborative authorization endpoint: - Make the endpoint highly available. - The endpoint must be capable of returning a response. All other status codes will result in the transaction being declined. - The endpoint requests and responses must be served via HTTPS. ## Activate an endpoint Activating an endpoint will automatically deactivate any existing endpoints. Only one endpoint can be at a time. Once a collaborative authorization endpoint has been registered, you must activate and verify it. Use the following mutation to activate a collaborative authorization endpoint: ## Simulate authorization Collaborative authorization works by sending a collaborative authorization request to your active endpoint. Use the following mutation to simulate an authorization and kick off your collaborative authorization workflow: ### GraphQL: AddCollaborativeAuthorizationEndpoint Query: mutation AddCollaborativeAuthorizationEndpoint( $input: AddCollaborativeAuthorizationEndpointInput! ) { addCollaborativeAuthorizationEndpoint(input: $input) { ... on CollaborativeAuthorizationEndpoint { id name uri status signingKeys { id secret } createdAt updatedAt } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "name": "My Collaborative Auth Endpoint", "uri": "https://webhook.site" } } Expected Result: { "data": { "addCollaborativeAuthorizationEndpoint": { "__typename": "CollaborativeAuthorizationEndpoint", "id": "", "name": "My Collaborative Auth Endpoint", "uri": "https://webhook.site", "createdAt": "2021-11-19T19:16:23.477Z", "updatedAt": "2021-11-19T19:16:23.477Z", "status": "PENDING_VERIFICATION", "signingKeys": [ { "id": "", "secret": "some_secret" } ] } }, "extensions": { "requestId": "" } } ### GraphQL: ActivateCollaborativeAuthorizationEndpoint Query: mutation ActivateCollaborativeAuthorizationEndpoint( $input: ActivateCollaborativeAuthorizationEndpointInput! ) { activateCollaborativeAuthorizationEndpoint(input: $input) { ... on CollaborativeAuthorizationEndpoint { id name uri status } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "endpointId": "" } } Expected Result: { "data": { "activateCollaborativeAuthorizationEndpoint": { "__typename": "CollaborativeAuthorizationEndpoint", "id": "", "name": "My Collaborative Auth Endpoint", "uri": "https://webhook.site", "status": "ACTIVE" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateAuthorization Query: mutation SimulateAuthorization($input: SimulateAuthorizationInput!) { simulateAuthorization(input: $input) { ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode avsResponseCode postalCodeResponseCode cvvResponseCode merchantDetails { countryCodeAlpha3 category name description } pointOfServiceDetails { terminalSupportsPartialApproval } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 2000, "currencyCode": "USD" }, "cardId": "", "merchantDetails": { "name": "HIGHNOTE_PLATFORM", "description": "COLLABORATIVE AUTHORIZATION TEST", "category": "GENERAL_SERVICES", "countryCodeAlpha3": "USA" }, "pointOfServiceDetails": { "terminalSupportsPartialApproval": true } } } Expected Result: { "data": { "collaborativeAuthorizationRequest": { "__typename": "PaymentCardAuthorizationRequest", "id": "", "transaction": { "id": "" }, "transactionTimestamp": "2022-06-15T20:01:35.390Z", "paymentCard": { "id": "" }, "transactionAmount": { "value": 1000, "currencyCode": "USD" }, "settlementAmount": { "value": 1000, "currencyCode": "USD" }, "requestedAmount": { "value": 1000, "currencyCode": "USD" }, "surchargeFee": null, "merchantDetails": { "merchantId": null, "category": "GENERAL_SERVICES", "countryCodeAlpha3": null, "description": null, "name": "HIGHNOTE_PLATFORM", "address": { "streetAddress": null, "extendedAddress": null, "postalCode": "00000", "region": null, "locality": null, "countryCodeAlpha3": null } }, "responseCode": null, "avsResponseCode": null, "postalCodeResponseCode": null, "cvvResponseCode": null, "pointOfServiceDetails": { "panEntryMode": null, "pinEntryMode": null, "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "isRecurring": null, "terminalSupportsPartialApproval": true, "category": null, "cardDataInputCapability": null }, "createdAt": "2022-06-15T20:01:35.390Z" } }, "extensions": { "signatureTimestamp": 1655323295581 } } --- URL: https://docs.highnote.com/docs/issuing/spend-controls/suspend-account Title: Suspend an Account Section: Issuing Description: Suspend a financial account to decline all authorizations and block card issuance. Remove the suspension to resume operations. ## Overview You can suspend a financial account for various risk management use cases not addressed by spend rules or velocity controls. Suspending a financial account does the following: - Declines authorizations on all associated payment cards - Blocks issuance or re-issuance of payment cards Suspending a financial account works by adding a financial account attribute. To automate your integration, you can subscribe to financial account attribute events. This will notify you when a specific financial account attribute is added or removed, so you can trigger your suspension workflow. ## Suspend financial account Use the following mutation to suspend a financial account: ## Remove account suspension Other financial account attributes may exist on an account that could prevent it from moving to an status. After a financial account is reviewed, you can remove the financial account attribute from the account using the following mutation. Removing this financial account attribute resumes authorizations and allows payment card issuance: ## Find financial account status and attributes Highnote strongly recommends not exposing fraud or risk-related to account holders, because this information can facilitate further risky behavior. Use the following query to find account status and attributes: ### GraphQL: SuspendFinancialAccount Query: mutation suspendFinancialAccount($input: SuspendFinancialAccountInput!) { suspendFinancialAccount(input: $input) { ... on FinancialAccount { id accountStatus accountAttributes financialAccountAttributesWithReason { attribute reason } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "", "memo": "suspension requested", "suspensionReason": "ACCOUNT_HOLDER_REQUEST" } } Expected Result: { "data": { "suspendFinancialAccount": { "id": "", "accountStatus": "SUSPENDED", "accountAttributes": [ "PROGRAM_OWNER_INITIATED_SUSPENSION" ], "financialAccountAttributesWithReason": [ { "attribute": "PROGRAM_OWNER_INITIATED_SUSPENSION", "reason": "PROGRAM_OWNER_INITIATED_SUSPENSION_REASON_ACCOUNT_HOLDER_REQUEST" } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11 } } } ### GraphQL: UnsuspendFinancialAccount Query: mutation unsuspendFinancialAccount($input: UnsuspendFinancialAccountInput!) { unsuspendFinancialAccount(input: $input) { ... on FinancialAccount { id accountStatus accountAttributes financialAccountAttributesWithReason { attribute reason } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "", "memo": "unsuspension requested" } } Expected Result: { "data": { "unsuspendFinancialAccount": { "id": "", "accountStatus": "ACTIVE", "accountAttributes": [], "financialAccountAttributesWithReason": [] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11 } } } ### GraphQL: GetFinancialAccount Query: query GetFinancialAccount($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { id name accountStatus accountAttributes financialAccountAttributesWithReason { attribute reason } updatedAt createdAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "accountStatus": "SUSPENDED", "accountAttributes": [ "PROGRAM_OWNER_INITIATED_SUSPENSION" ], "financialAccountAttributesWithReason": [ { "attribute": "PROGRAM_OWNER_INITIATED_SUSPENSION", "reason": "PROGRAM_OWNER_INITIATED_SUSPENSION_REASON_ACCOUNT_HOLDER_REQUEST" } ], "globalNotes": { "pageInfo": { "hasNextPage": true, "hasPreviousPage": false }, "edges": [ { "node": { "message": "test suspension again", "primaryEntity": { "__typename": "FinancialAccount" }, "aggregateEntity": { "__typename": "USPersonAccountHolder" } } }, { "node": { "message": "test unsuspension", "primaryEntity": { "__typename": "FinancialAccount" }, "aggregateEntity": { "__typename": "USPersonAccountHolder" } } } ] } } } } --- URL: https://docs.highnote.com/docs/issuing/templates/ap-automation Title: AP Automation Template Section: Issuing Description: Create virtual card products for accounts payable automation. Onboard business account holders, issue cards with on-demand funding, and configure pseudo balance spending limits. ## Overview AP automation card products allow you to issue cards to employees using a financial account owned by your business. AP automation cards are virtual payment cards that you can make available on your application or website. They are typically issued for specific transactions, controlled by spend rules and/or collaborative authorization. The following graphic provides an overview of how an AP automation card product funds a virtual payment card: This guide provides an overview of creating and setting up an AP automation card product in your Test environment. ## Create a card product Use the following mutation to create an AP automation card product. Use as the input variable: ## Fund your card program AP automation card products use a product funding account to send 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: 1. Retrieve the product funding account ID. 2. 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: ### Initiate a wire transfer Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Enable on-demand funding AP automation card products use on-demand funding to fund account holder financial accounts. When you create an AP automation card product, your product funding account is used as the source account for on-demand funding. On-demand funding has an optional feature called pseudo balance. Pseudo balance lets you set a spending limit on a financial account to ensure account holders cannot spend over a specific amount. When a transaction is initiated for a financial account with a pseudo balance, Highnote checks the ledger to approve or decline the authorization. If the pseudo balance feature is not enabled, Highnote checks the balance of your product funding account during authorization. Use the following mutation to enable on-demand funding and use a boolean value to enable pseudo balance: ## Issue financial account Financial accounts for AP automation card products must have an on-demand funding source. The on-demand funding source is what enables the transfer of funds from your product funding account to the account holder's financial account. Use the following mutation to issue a financial account with an on-demand funding source: ## Initiate pseudo balance update If you have pseudo balance enabled for your AP automation card product, you must initiate a pseudo balance update after issuing a financial account. This sets the pseudo balance, or spending limit, for the financial account. Use the following guide for managing pseudo balance limits and balances: - Manage Pseudo Limit and Balance ## Issue payment card AP automation cards are virtual cards that can be made available on your application or website. Use the following mutation to issue a virtual card: ## 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: ## 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. - Setup notifications to automate your integration. ### GraphQL: 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": "AP Automation", "vertical": "AP_INVOICE_AUTOMATION" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "Y2FyZHBy", "name": "Invoice Automation", "usage": "MULTI_USE" } }, "extensions": { "requestId": "b85fc1ec-e770-9d06-922f-16b7486a690e" } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "node": { "id": "", "features": [ { "enabled": true, "__typename": "ProductFundingFinancialAccountFeature" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60041 } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... 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": "", "memo": "Consumer Credit product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "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": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60040 } } } ### GraphQL: EnableOnDemandFundingFeature Query: mutation EnableOnDemandFundingFeature( $input: EnableOnDemandFundingFeatureInput! ) { enableOnDemandFundingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled ... on OnDemandFundingCardProductFeature { pseudoBalanceEnabled } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "pseudoBalanceEnabled": true } } Expected Result: { "data": { "enableOnDemandFundingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "CollaborativeAuthorizationCardProductFeature", "enabled": true }, { "__typename": "DisputeChargebackCardProductFeature", "enabled": true }, { "__typename": "OnDemandFundingCardProductFeature", "enabled": true, "pseudoBalanceEnabled": true }, { "__typename": "AuthorizedUserCardProductFeature", "enabled": false } ] } }, "extensions": { "requestId": "f332c811-82e7-965d-b0e6-17519a7bd4b1", "rateLimit": { "cost": 11, "limit": 2500, "remaining": 2484, "asOf": "2025-06-06T16:06:09.019Z", "complexity": { "limit": 2500, "remaining": 2484, "cost": 11 }, "count": { "limit": 100, "remaining": 94, "cost": 1 } } } } ### GraphQL: IssueFinancialAccountForApplicationWithOnDemandFundingSource Query: mutation IssueFinancialAccountForApplicationWithOnDemandFundingSource( $input: IssueFinancialAccountForApplicationWithOnDemandFundingSourceInput! ) { issueFinancialAccountForApplicationWithOnDemandFundingSource(input: $input) { ... on FinancialAccount { id externalId name createdAt updatedAt application { id createdAt } cardProduct { id vertical } features { __typename enabled createdAt updatedAt ... on OnDemandFundingFinancialAccountFeature { sourceFinancialAccountId } } directDepositDetails { id restrictedDetails { __typename ... on DirectDepositDetailRestrictedDetails { number routingNumber bank { name } } } } owner { __typename ... on Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "", "sourceFinancialAccountId": "" } } Expected Result: { "data": { "IssueFinancialAccountForApplicationWithOnDemandFundingSource": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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" }, { "__typename": "OnDemandFundingFinancialAccountFeature", "enabled": true, "createdAt": "2021-12-28T18:20:49.933Z", "updatedAt": "2021-12-28T18:20:49.933Z", "sourceFinancialAccountId": "" } ], "directDepositDetails": { "id": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: IssuePaymentCardForFinancialAccount Query: mutation IssuePaymentCardForFinancialAccount( $input: IssuePaymentCardForFinancialAccountInput! ) { issuePaymentCardForFinancialAccount(input: $input) { ... on PaymentCard { id bin last4 expirationDate network status financialAccounts { id } restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } ... on AccessDeniedError { message } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "financialAccountId": "", "options": { "activateOnCreate": true, "expirationDate": "2027-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "510515", "last4": "7162", "expirationDate": "2027-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "" } ], "restrictedDetails": { "message": "Access is denied" } } } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/templates/commercial-charge Title: Commercial Charge Template Section: Issuing Description: Create commercial charge card products with pay-in-full terms. Onboard business account holders, open applications, issue cards, and schedule repayments. ## Overview Commercial charge cards do not charge interest and require account holders to pay their statement balance in full by the due date of each billing cycle. Highnote supports the following types of commercial charge cards: | Configuration | Description | | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Unsecured | Offer a line of credit without requiring collateral. This configuration requires you or a debt facility to provide sufficient capital based on the lines of credit extended to your cardholders. | | Secured | Offer a line of credit backed by an account holder's secure deposit. Credit processing-only model This model uses the Highnote platform to fund credit products on-demand, bypassing full ledger capabilities and repayment services. For more information on this model, contact support@highnote.com. | The following graphic provides an overview of the process for issuing a commercial charge card: ## Create card product Highnote supports unsecured and secured commercial charge card products. This guide provides an overview of creating an unsecured commercial charge card product. ### Unsecured commercial charge Use the following mutation to create a commercial charge card product in the Test environment. When creating your card product, use as the input variable: ### Secured commercial charge You can create a secured commercial charge card product using Highnote's secured deposit feature. This feature is enabled for your card product by the Highnote team and requires cardholders to provide collateral in the form of a secure deposit to back their line of credit. For more information on enabling this feature and integration steps, see Create Secured Deposit Offer. ### Add charge feature After creating a card product, use the following mutation to add the feature. This feature enables pay-in-full terms for cardholders: ## Fund your card program Unsecured commercial charge card products use a product funding account to issue lines of credit. The product funding account is where you deposit the capital that you or your debt facility provide to back lines of credit. In the Test environment, you can simulate depositing funds into your product funding account. Simulating deposits doesn't require connecting a verified bank account. Funding your product funding account requires the following steps: 1. Retrieve the product funding account ID. 2. 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: ### Initiate a wire transfer The transfer field displays information about a given transfer. You can edit this field in the Test environment but not in the Live environment. Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Create an account holder Commercial charge card products are used by business account holders. US business account holders must provide business details and a primary authorized person, with the option to add beneficial owners. For more information on onboarding US business account holders, see Onboard a US business account holder. Before issuing a line of credit, you may want to collect inputs in the credit application. These fields can be used to simulate credit line assignment or adverse action reasons. For more information on these simulations, see the following guides: - Simulate Credit Line Assignment - Simulate Adverse Action Declines Use the following mutation to create a business account holder: ## Account holder applications Application approval for credit card products in the Live environment uses one of the following workflows: - Highnote runs your credit policy for you and approves or denies applications based on your credit policy. - You participate in collaborative application decisioning to provide a recommended approval or denied application response. ### Enable collaborative application decisioning By default, in the Test environment, you can simulate credit application decisions with various values. These simulation values are used when onboarding an account holder. Use this default setting if Highnote will be executing your credit policy on your behalf. For more information, see the Simulate Underwriting Decision guide. Alternatively, you or your underwriter can use collaborative application decisioning. This feature allows you to recommend an approval or denial based on your credit policy. For more information, see Collaborative Application Decisioning. Enable collaborative application decisioning in the Highnote dashboard, or using the API with the following mutation: ### Open an application When an account holder application is submitted, it triggers an application decision request. If you use collaborative application decisioning, you can respond with a recommended or decision. 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: ### Simulate application decision The Test environment does not run identity verification checks on applications. During testing, you can simulate application approvals or denials using simulation values. These simulation values product tags that result in the following application statuses: - - - For more information on using this simulation, see Simulate Underwriting Decision. ## Issue a financial account Financial accounts hold the balance for payment cards. To create a new financial account, pass the of a verified application. Financial accounts have an variable field that allows you to tie the Financial account to an entity in your system. If you do not pass in an , Highnote will generate one. Use the following mutation to issue a financial account for an application: ## Set credit limit Setting or updating a credit limit is an asynchronous process with the Highnote team to ensure your ledger balances and validations are in check. You can set a financial account's credit limit by providing the and the credit limit you want to assign to the financial account. Your product funding financial account must have funds equal to or exceeding any credit limit you extend to your account holders. Use the following mutation to set a credit limit: ## 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: ### 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. ## 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: ## Schedule repayments Charge card products account holders to repay their balance in full. An account holder needs to connect a verified external bank account to Highnote to schedule a repayment. Once a verified account is linked, the account holder can use ACH transfers to schedule payments. Highnote supports the following types of payment schedules: - Recurring payments - One-time payments ### Connect a verified external bank account Account holders must have a verified external bank account connected to Highnote to schedule repayments. For more information on connecting external accounts, see Connect External Accounts. ### Create a payment schedule Payment due dates are determined by (1) the financial account's creation date, and (2) the card product's grace period. You can establish one-time or recurring payment schedules, enabling your customers to schedule payments on their monthly due date or a customized calendar day. Recurring payment schedules are based on a point-in-time balance, such as an outstanding balance, and the ACH transfer amount will be calculated on the scheduled date. See the scheduled repayments guide for more information on managing, viewing, and canceling payment schedules. ## Generate a billing statement Billing statement data is created on financial accounts and becomes available at the end of a billing cycle. For charge and credit card products, the billing period end date may vary across financial accounts on your portfolio. Statement data is typically available within 48 hours of a billing period end date. For more information on generating a billing statement, see Generate Current Billing Statement. ## 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. ## Simulate delinquency Highnote's delinquency simulator lets you view a financial account's current delinquency status and receivables by simulating past purchase and payment scenarios. In the Test environment, this helps with understanding delinquency scenarios and testing notification events. Use the Simulate Delinquency guide for more information on using the Highnote API to simulate delinquency in the Test environment. ## 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. - Setup notifications to automate your integration. ### GraphQL: 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": "Business Credit Card", "usage": "MULTI_USE", "vertical": "COMMERCIAL_CREDIT" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "", "name": "Business Credit Card", "usage": "MULTI_USE" } }, "extensions": { "requestId": "" } } ### GraphQL: EnableCreditCardFeature Query: mutation EnableCreditCardFeature($input: EnableCreditCardFeatureInput!) { enableCreditCardFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "feature": "CHARGE" } } Expected Result: { "data": { "enableCreditCardFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "ChargeCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60045 } } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "name": "Test PIF Commercial Credit", "usage": "MULTI_USE", "accounts": { "edges": [ { "node": { "id": "", "name": "Test PIF Commercial Credit - Product Funding", "features": [ { "__typename": "ProductFundingFinancialAccountFeature", "enabled": true } ], "accountStatus": "ACTIVE", "owner": { "__typename": "Organization" } } }, { "node": { "id": "", "name": "Test PIF Commercial Credit - Product Reserve", "features": [ { "__typename": "ProductReserveFinancialAccountFeature", "enabled": true } ], "accountStatus": "ACTIVE", "owner": { "__typename": "Organization" } } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... on Transfer { id status statusReason amount { value currencyCode } createdAt updatedAt ledgers { name } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "amount": { "value": 1750000, "currencyCode": "USD" }, "source": "WIRE", "toFinancialAccountId": "", "memo": "PIF product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "Transfer", "id": "", "status": "PENDING", "statusReason": null, "amount": { "value": 1750000, "currencyCode": "USD" }, "createdAt": "2022-09-26T23:25:04.142Z", "updatedAt": "2022-09-26T23:25:04.143Z", "ledgers": null } }, "extensions": { "requestId": "" } } ### GraphQL: CreateUSBusinessAccountHolder Query: mutation CreateUSBusinessAccountHolder( $input: CreateUSBusinessAccountHolderInput! ) { createUSBusinessAccountHolder(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on USBusinessAccountHolder { externalId id primaryAuthorizedPerson { id email } businessProfile { id ultimateBeneficialOwners { id email } } } } } Variables: { "input": { "externalId": "user-id-in-your-system", "primaryAuthorizedPerson": { "name": { "givenName": "Bill", "familyName": "Smith" }, "email": "billsmith@example.com", "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "homeAddress": { "streetAddress": "123 Main Street", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-67-1111", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "1980-09-01", "authorizingPersonTitle": "PRESIDENT" }, "businessProfile": { "name": { "legalBusinessName": "HIGHNOTE", "doingBusinessAsName": "BlueJay Inc" }, "billingAddress": { "streetAddress": "123 Main Street", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" }, "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "identificationDocument": { "employerIdentificationNumber": { "number": "11-2343256", "countryCodeAlpha3": "USA" } }, "businessType": "PARTNERSHIP", "creditRiskAttributes": { "annualRevenue": { "value": "100000", "currencyCode": "USD" } }, "ultimateBeneficialOwners": [ { "name": { "givenName": "James", "familyName": "Smith" }, "email": "james@example.com", "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "homeAddress": { "streetAddress": "123 Main Street", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-67-1325", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "1982-09-01", "percentageOwnership": 25 } ] } } } Expected Result: { "data": { "createUSBusinessAccountHolder": { "__typename": "USBusinessAccountHolder", "externalId": "user-id-in-your-system", "id": "", "primaryAuthorizedPerson": { "id": "", "email": "billsmith@example.com" }, "businessProfile": { "id": "", "ultimateBeneficialOwners": [ { "id": "", "email": "james@example.com" } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: EnableCollaborativeApplicationUnderwritingFeature Query: mutation EnableCollaborativeApplicationUnderwritingFeature( $input: EnableCollaborativeApplicationUnderwritingFeatureInput! ) { enableCollaborativeApplicationUnderwritingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "" } } Expected Result: { "data": { "enableCollaborativeApplicationUnderwritingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "CollaborativeApplicationUnderwritingCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "billingAddress": { "streetAddress": "123 Main Street", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA", "postalCode": "60654" }, "currentVerification": { "reason": "PENDING", "results": [], "status": "PENDING" } }, "updatedAt": "2023-09-01T22:27:06.896Z", "createdAt": "2023-09-01T22:27:06.760Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60023 } } } ### GraphQL: 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 Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: InitiateFinancialAccountCreditLimitUpdateFromProductFunding Query: mutation InitiateFinancialAccountCreditLimitUpdateFromProductFunding( $input: InitiateFinancialAccountCreditLimitUpdateFromProductFundingInput! ) { initiateFinancialAccountCreditLimitUpdateFromProductFunding(input: $input) { __typename ... on Node { id } ... on FinancialAccountCreditLimitUpdateFromProductFunding { id status statusReason createdAt updatedAt memo amount { value currencyCode } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "memo": "Set Limit", "amount": { "value": 100, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateFinancialAccountCreditLimitUpdateFromProductFunding": { "__typename": "FinancialAccountCreditLimitUpdateFromProductFunding", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2022-06-21T18:01:28.992Z", "updatedAt": "2022-06-21T18:01:28.993Z", "memo": null, "amount": { "value": 100, "currencyCode": "USD" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489661", "last4": "9602", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "", "name": "Test Consumer Credit Account" } ], "restrictedDetails": { "message": "Access is denied" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/templates/consumer-charge Title: Consumer Charge Template Section: Issuing Description: Create consumer charge card products with pay-in-full terms. Onboard account holders, open applications, issue cards, and schedule repayments. ## Overview Consumer charge cards do not charge interest and require account holders to pay their statement balance in full by the due date of each billing cycle. Highnote supports the following types of consumer charge cards: | Configuration | Description | | :----------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Unsecured charge card products | These credit card products are not backed by an account holder deposit and require adequate capital to fund lines of credit. You can provide capital on your behalf or through a debt facility. | | Secured charge card products | These credit card products are backed by an account holder's secure deposit. | | Credit processing-only model | This model uses the Highnote platform to fund charge and credit products on-demand, bypassing full ledger capabilities and repayment services. For more information on this model, contact support@highnote.com. | This guide provides an overview of creating and setting up an unsecured consumer charge card product using the Highnote API in the Test environment. In the Live environment, the Highnote team will assist with creating your card product. ## Create card product To enable secure deposits or use the credit processing-only model, contact support@highnote.com. Use the following mutation to create an unsecured consumer charge card product in the Test environment. Use as the input variable: ### Add charge feature After creating a card product, use the following mutation to add the feature. This feature enables pay-in-full terms for account holders. ### View credit features In the Test environment, credit and charge card products are automatically assigned credit features and settings. These features and settings are similar to a live program's credit policies, which are configured by the Highnote team during program setup. The following table outlines the default features and settings for consumer credit card products in the Test environment: | Credit policy | Description | Test Environment Default Setting | | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ | | | This setting controls your Test environment's delinquency policy. | Delinquent when >= 30 days | | | This setting controls your Test environment's policy for account suspension. | Suspended when >= 90 days | | | This setting controls your Test environment's charge-off policy. | Balance charged off when >= 180 days | | | This setting controls the minimum payment for account holders. The minimum payment is the greater of $25 or 1% of the statement balance, plus interest charges, fees, and any past amount due. If the balance is less than $25, the minimum payment is equal to the statement balance. | Minimum payment is = 1%, = $25 | Use the following query to view credit features for your credit card product in the Test environment: ## Fund your card program Unsecured consumer charge card products use a product funding account to issue lines of credit. The product funding account is where you deposit the capital that you or your debt facility provide to back lines of credit. In the Test environment, you can simulate depositing funds into your product funding account. Simulating deposits doesn't require connecting a verified bank account. Funding your product funding account requires the following steps: 1. Retrieve the product funding account ID. 2. 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: ### Initiate a wire transfer Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Create an account holder Your credit policy dictates the data required to issue a line of credit in the Live environment. Some credit policies require more data than the and . Before issuing a line of credit, you should collect and from your applicants. These fields are inputs for the object. There are two recommended methods for collecting this information: - Collect from the account holder when they are completing their application. - Update the account holder with the necessary details after they've submitted their application. Use the following mutation to create an account holder for a consumer credit card product. Provide as necessary: ## Account holder applications Application approval for credit card products in the Live environment uses one of the following workflows: - Highnote runs your credit policy for you and approves or denies applications based on your credit policy. - You participate in collaborative application decisioning to provide a recommended approval or denied application response. ### Enable collaborative application decisioning By default, in the Test environment, you can simulate credit application decisions with various values. These simulation values are used when onboarding an account holder. Use this default setting if Highnote will be executing your credit policy on your behalf. For more information, see the Simulate Underwriting Decision guide. Alternatively, you or your underwriter can use collaborative application decisioning. This feature allows you to recommend an approval or denial based on your credit policy. For more information, see Collaborative Application Decisioning. Enable collaborative application decisioning in the Highnote dashboard, or using the API with the following mutation: ### Open an application When an account holder application is submitted, it triggers an application decision request. If you use collaborative application decisioning, you can respond with a recommended or decision. 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: ### Simulate application decision The Test environment does not run identity verification checks on applications. During testing, you can simulate application approvals or denials using simulation values. These simulation values product tags that result in the following application statuses: - - - For more information on using this simulation, see Simulate Underwriting Decision. ## Issue a financial account Financial accounts hold the balance for payment cards. To create a new financial account, pass the of a verified application. Financial accounts have an variable field that allows you to tie the Financial account to an entity in your system. If you do not pass in an , Highnote will generate one. Use the following mutation to issue a financial account for an application: ## Set credit limit Setting or updating a credit limit is an asynchronous process with the Highnote team to ensure your ledger balances and validations are in check. You can set a financial account's credit limit by providing the and the credit limit you want to assign to the financial account. Your product funding financial account must have funds equal to or exceeding any credit limit you extend to your account holders. Use the following mutation to set a credit limit: ## 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: ### 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. ## Schedule repayments Charge card products account holders to repay their balance in full. An account holder needs to connect a verified external bank account to Highnote to schedule a repayment. Once a verified account is linked, the account holder can use ACH transfers to schedule payments. Highnote supports the following types of payment schedules: - Recurring payments - One-time payments ### Connect a verified external bank account Account holders must have a verified external bank account connected to Highnote to schedule repayments. For more information on connecting external accounts, see Connect External Accounts. ### Create a payment schedule Payment due dates are determined by (1) the financial account's creation date, and (2) the card product's grace period. You can establish one-time or recurring payment schedules, enabling your customers to schedule payments on their monthly due date or a customized calendar day. Recurring payment schedules are based on a point-in-time balance, such as an outstanding balance, and the ACH transfer amount will be calculated on the scheduled date. See the scheduled repayments guide for more information on managing, viewing, and canceling payment schedules. ## Generate a billing statement Billing statement data is created on financial accounts and becomes available at the end of a billing cycle. For charge and credit card products, the billing period end date may vary across financial accounts on your portfolio. Statement data is typically available within 48 hours of a billing period end date. For more information on generating a billing statement, see Generate Current Billing Statement. ## 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. ## Simulate delinquency Highnote's delinquency simulator lets you view a financial account's current delinquency status and receivables by simulating past purchase and payment scenarios. In the Test environment, this helps with understanding delinquency scenarios and testing notification events. Use the Simulate Delinquency guide for more information on using the Highnote API to simulate delinquency in the Test environment. ## 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. - Setup notifications to automate your integration. ### GraphQL: 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 Credit Card", "usage": "MULTI_USE", "vertical": "CONSUMER_CREDIT" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "", "name": "Consumer Credit Card", "usage": "MULTI_USE", "vertical": "CONSUMER_CREDIT" } }, "extensions": { "requestId": "" } } ### GraphQL: EnableCreditCardFeature Query: mutation EnableCreditCardFeature($input: EnableCreditCardFeatureInput!) { enableCreditCardFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "feature": "CHARGE" } } Expected Result: { "data": { "enableCreditCardFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "ChargeCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60045 } } } ### GraphQL: GetCardProductWithCreditConfiguration Query: query GetCardProductWithCreditConfiguration($id: ID!) { node(id: $id) { __typename ... on CardProduct { id creditConfiguration { ... on CreditCardProductConfiguration { accountAging { delinquentInDays suspendedInDays chargeOffInDays lateFeeGracePeriodInDays } minimumPayment { percentage thresholdAmount { value currencyCode } includesPastDueAmount includesInterestAmount includesFeesCharged } repayment { repaymentWaterfall } interest { includesPurchase includesFees } billingCycleConfiguration { billingCyclePeriod billingCycleGracePeriodType billingCycleGracePeriodInDays } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "creditConfiguration": { "accountAging": { "delinquentInDays": 30, "suspendedInDays": 60, "chargeOffInDays": 90, "lateFeeGracePeriodInDays": 10 }, "minimumPayment": { "percentage": 10, "thresholdAmount": { "value": 2000, "currencyCode": "USD" }, "includesPastDueAmount": true, "includesInterestAmount": false, "includesFeesCharged": true }, "repayment": { "repaymentWaterfall": [ "PURCHASE", "INTEREST", "FEES" ] }, "interest": { "includesPurchase": true, "includesFees": true }, "billingCycleConfiguration": { "billingCyclePeriod": "MONTHLY", "billingCycleGracePeriodType": "FLOATING", "billingCycleGracePeriodInDays": 10 } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 8 } } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "node": { "id": "", "features": [ { "enabled": true, "__typename": "ProductFundingFinancialAccountFeature" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60041 } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... 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": "", "memo": "Consumer Credit product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "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": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60040 } } } ### GraphQL: 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": "some-id" } } } Expected Result: { "data": { "createUSPersonAccountHolder": { "__typename": "USPersonAccountHolder", "id": "", "email": "gerrytest1@abc.com", "dateOfBirth": "1980-09-01", "externalId": "some-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": "", "countryCodeAlpha3": "USA" } }, "personCreditRiskAttributes": { "totalAnnualIncome": [ { "value": 1000, "currencyCode": "USD" } ], "currentDebtObligations": [ { "value": 1000, "currencyCode": "USD" } ], "employmentStatus": "EMPLOYED" } } }, "extensions": { "requestId": "" } } ### GraphQL: EnableCollaborativeApplicationUnderwritingFeature Query: mutation EnableCollaborativeApplicationUnderwritingFeature( $input: EnableCollaborativeApplicationUnderwritingFeatureInput! ) { enableCollaborativeApplicationUnderwritingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "" } } Expected Result: { "data": { "enableCollaborativeApplicationUnderwritingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "CollaborativeApplicationUnderwritingCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "billingAddress": { "streetAddress": "123 Main Street", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA", "postalCode": "60654" }, "currentVerification": { "reason": "PENDING", "results": [], "status": "PENDING" } }, "updatedAt": "2023-09-01T22:27:06.896Z", "createdAt": "2023-09-01T22:27:06.760Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60023 } } } ### GraphQL: 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 Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: InitiateFinancialAccountCreditLimitUpdateFromProductFunding Query: mutation InitiateFinancialAccountCreditLimitUpdateFromProductFunding( $input: InitiateFinancialAccountCreditLimitUpdateFromProductFundingInput! ) { initiateFinancialAccountCreditLimitUpdateFromProductFunding(input: $input) { __typename ... on Node { id } ... on FinancialAccountCreditLimitUpdateFromProductFunding { id status statusReason createdAt updatedAt memo amount { value currencyCode } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "memo": "Set Limit", "amount": { "value": 100, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateFinancialAccountCreditLimitUpdateFromProductFunding": { "__typename": "FinancialAccountCreditLimitUpdateFromProductFunding", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2022-06-21T18:01:28.992Z", "updatedAt": "2022-06-21T18:01:28.993Z", "memo": null, "amount": { "value": 100, "currencyCode": "USD" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489661", "last4": "9602", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "", "name": "Test Consumer Credit Account" } ], "restrictedDetails": { "message": "Access is denied" } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/templates/commercial-credit Title: Commercial Credit Template Section: Issuing Description: Create commercial revolving credit card products. Onboard business account holders, open applications, set credit limits, issue cards, and generate statements. ## Overview Commercial credit card products support revolving lines of credit, which require account holders to make minimum payments by their billing cycle due date. Additionally, you can assess interest charges on revolving balances. Highnote supports the following configurations for commercial credit card products: | Configuration | Description | | :----------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Unsecured credit card products | These credit card products are not backed by an account holder deposit and require adequate capital to fund lines of credit. You can provide capital on your behalf or through a debt facility. | | Secured credit card products | These credit card products are backed by an account holder's secure deposit. | | Credit processing-only model | This model uses the Highnote platform to fund credit products on-demand, bypassing full ledger capabilities and repayment services. For more information on this model, contact support@highnote.com. | This guide provides an overview of creating and setting up an unsecured commercial credit card product using the Highnote API in the Test environment. In the Live environment, the Highnote team will assist with creating your card product. ## Create card product Use the following mutation to create an unsecured commercial credit card product in the Test environment. Use as the input variable: ### Add credit feature After creating a card product, use the following mutation to add the feature. This feature enables minimum payment terms and revolving balance capabilities for financial accounts: ### View credit features In the Test environment, credit and charge card products are automatically assigned credit features and settings. These features and settings are similar to a live program's credit policies, which are configured by the Highnote team during program setup. The following table outlines the default features and settings for consumer credit card products in the Test environment: | Credit policy | Description | Test Environment Default Setting | | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ | | | This setting controls your Test environment's delinquency policy. | Delinquent when >= 30 days | | | This setting controls your Test environment's policy for account suspension. | Suspended when >= 90 days | | | This setting controls your Test environment's charge-off policy. | Balance charged off when >= 180 days | | | This setting controls the minimum payment for account holders. The minimum payment is the greater of $25 or 1% of the statement balance, plus interest charges, fees, and any past amount due. If the balance is less than $25, the minimum payment is equal to the statement balance. | Minimum payment is = 1%, = $25 | Use the following query to view credit features for your credit card product in the Test environment: ## 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: 1. Retrieve the product funding account ID. 2. 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: ### Initiate a wire transfer Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Create credit plans Credit plans allows you to meet unique needs of your account holders by providing flexible and configurable terms on credit card products. Credit plans define the following: - Interest rate - Interest rate type - Interest accrual method - Pricing and policy terms for specific balance types You can create credit plans in the Test environment to test your card product. For more information on creating credit plans, see Create Credit Plans. The Highnote team will create credit plans for your card product in the Live environment. ## Create an account holder Before issuing lines of credit, you will want to consider which [](/docs/api-reference/object#BusinessCreditRiskAttributes) fields you want to collect from an account holder. For example, you may want to collect for use during application decisioning. There are two recommended methods for collecting this information: - Collect from the account holder when they are completing their application. - Update the account holder with the necessary details after they've submitted their application. Use the following mutation to create a business account holder. Provide as needed: ## Account holder applications Application approval for credit card products in the Live environment uses one of the following workflows: - Highnote runs your credit policy for you and approves or denies applications based on your credit policy. - You participate in collaborative application decisioning to provide a recommended approval or denied application response. ### Enable collaborative application decisioning By default, in the Test environment, you can simulate credit application decisions with various values. These simulation values are used when onboarding an account holder. Use this default setting if Highnote will be executing your credit policy on your behalf. For more information, see the Simulate Underwriting Decision guide. Alternatively, you or your underwriter can use collaborative application decisioning. This feature allows you to recommend an approval or denial based on your credit policy. For more information, see Collaborative Application Decisioning. Enable collaborative application decisioning in the Highnote dashboard, or using the API with the following mutation: ### Open an application When an account holder application is submitted, it triggers an application decision request. If you use collaborative application decisioning, you can respond with a recommended or decision. 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: ### Simulate application decision The Test environment does not run identity verification checks on applications. During testing, you can simulate application approvals or denials using simulation values. These simulation values product tags that result in the following application statuses: - - - For more information on using this simulation, see Simulate Underwriting Decision. ## Issue a financial account With an application, create a financial account by providing the as an input variable in the following mutation: ## Set a credit limit Setting or updating a credit limit is an asynchronous process to ensure your ledger balances and validations are in check. You can set or update a financial account’s credit limit by providing the and the credit limit you want to assign to the financial account. Your product funding financial account must have funds equal to or exceeding any credit limit you extend to your account holders. Use the following mutation to set or update a credit limit: ## 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: ## 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: ## Schedule repayments Commercial credit card products require regular repayments. An account holder needs to connect a verified external bank account to Highnote to schedule a repayment. Once a verified account is linked, the account holder can use ACH transfers to schedule payments. Highnote supports the following types of payment schedules: - Recurring payments - One-time payments Payment schedules are created by the account holder. In the Live environment, you cannot create a payment schedule on an account holder's behalf. You can initiate an originated ACH pull, but must get the account holder's recorded authorization through . ### Connect a verified external bank account Account holders must have a verified external bank account connected to Highnote to schedule repayments. For more information on connecting external accounts, see Connect External Accounts. ### Create a payment schedule Payment due dates are determined by (1) the financial account's creation date, and (2) the card product's grace period. You can establish one-time or recurring payment schedules, enabling your customers to schedule payments on their monthly due date or a customized calendar day. Recurring payment schedules are based on a point-in-time balance, such as an outstanding balance, and the ACH transfer amount will be calculated on the scheduled date. See the scheduled repayments guide for more information on managing, viewing, and canceling payment schedules. ## Generate a billing statement Highnote provides essential data for generating billing statements for financial accounts. To create a billing statement, we recommend creating a template and using the data Highnote provides to fill in the template. For more information on billing statements, see Deliver Statements. Refer to the following guidelines for creating a billing statement: - Billing statement data is available at the close of a billing cycle. Credit card product billing period end dates may vary across financial accounts. Typically, statement data is available within 48 hours after the billing period ends. - To retrieve the current amount due for your card product, reference the . This balance can be presented to your customers outside the billing statement, for example, on your website or application's "account page". Use the following query to fetch billing statement data: ## 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. ## Simulate delinquency Highnote's delinquency simulator lets you view a financial account's current delinquency status and receivables by simulating past purchase and payment scenarios. In the Test environment, this helps with understanding delinquency scenarios and testing notification events. Use the Simulate Delinquency guide for more information on using the Highnote API to simulate delinquency in the Test environment. ## 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. ### GraphQL: CreateCardProduct Query: mutation CreateCardProduct($input: CreateCardProductInput!) { createCardProduct(input: $input) { __typename ... on CardProduct { id name usage vertical } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProduct": { "name": "Commercial Credit Card", "usage": "MULTI_USE", "vertical": "COMMERCIAL_CREDIT" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "", "name": "Commercial Credit Card", "usage": "MULTI_USE", "vertical": "COMMERCIAL_CREDIT" } }, "extensions": { "requestId": "" } } ### GraphQL: EnableCreditCardFeature Query: mutation EnableCreditCardFeature($input: EnableCreditCardFeatureInput!) { enableCreditCardFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "feature": "REVOLVING" } } Expected Result: { "data": { "enableCreditCardFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "RevolvingCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60045 } } } ### GraphQL: GetCardProductWithCreditConfiguration Query: query GetCardProductWithCreditConfiguration($id: ID!) { node(id: $id) { __typename ... on CardProduct { id creditConfiguration { ... on CreditCardProductConfiguration { accountAging { delinquentInDays suspendedInDays chargeOffInDays lateFeeGracePeriodInDays } minimumPayment { percentage thresholdAmount { value currencyCode } includesPastDueAmount includesInterestAmount includesFeesCharged } repayment { repaymentWaterfall } interest { includesPurchase includesFees } billingCycleConfiguration { billingCyclePeriod billingCycleGracePeriodType billingCycleGracePeriodInDays } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "creditConfiguration": { "accountAging": { "delinquentInDays": 30, "suspendedInDays": 60, "chargeOffInDays": 90, "lateFeeGracePeriodInDays": 10 }, "minimumPayment": { "percentage": 10, "thresholdAmount": { "value": 2000, "currencyCode": "USD" }, "includesPastDueAmount": true, "includesInterestAmount": false, "includesFeesCharged": true }, "repayment": { "repaymentWaterfall": [ "PURCHASE", "INTEREST", "FEES" ] }, "interest": { "includesPurchase": true, "includesFees": true }, "billingCycleConfiguration": { "billingCyclePeriod": "MONTHLY", "billingCycleGracePeriodType": "FLOATING", "billingCycleGracePeriodInDays": 10 } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 8 } } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "node": { "id": "", "features": [ { "enabled": true, "__typename": "ProductFundingFinancialAccountFeature" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60041 } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... 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": "", "memo": "Consumer Credit product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "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": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60040 } } } ### GraphQL: createUSBusinessAccountHolder Query: mutation CreateUSBusinessAccountHolder( $input: CreateUSBusinessAccountHolderInput! ) { createUSBusinessAccountHolder(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on USBusinessAccountHolder { externalId id createdAt updatedAt primaryAuthorizedPerson { id email dateOfBirth percentageOwnership authorizingPersonTitle createdAt updatedAt name { givenName familyName title suffix middleName } homeAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } identificationDocument { socialSecurityNumber { numberHash countryCodeAlpha3 } } } businessProfile { id website businessType businessCreditRiskAttributes { annualRevenue { value currencyCode } } createdAt updatedAt name { legalBusinessName doingBusinessAsName } billingAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } identificationDocument { employerIdentificationNumber { numberHash countryCodeAlpha3 } } ultimateBeneficialOwners { id percentageOwnership dateOfBirth email createdAt updatedAt name { givenName familyName title suffix middleName } homeAddress { streetAddress extendedAddress postalCode region locality countryCodeAlpha3 } phoneNumbers { countryCode number label } identificationDocument { socialSecurityNumber { numberHash countryCodeAlpha3 } } } } } } } Variables: { "input": { "externalId": "bluejay", "primaryAuthorizedPerson": { "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "email": "gerrytest1@example.com", "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "homeAddress": { "streetAddress": "123 Main Street", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-67-1111", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "1980-09-01", "authorizingPersonTitle": "PRESIDENT" }, "businessProfile": { "name": { "legalBusinessName": "HIGHNOTE", "doingBusinessAsName": "BlueJay Inc" }, "billingAddress": { "streetAddress": "123 Main Street", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" }, "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "identificationDocument": { "employerIdentificationNumber": { "number": "11-2343256", "countryCodeAlpha3": "USA" } }, "businessCreditRiskAttributes": { "annualRevenue": { "value": "1000", "currencyCode": "USD" } }, "businessType": "PARTNERSHIP", "ultimateBeneficialOwners": [ { "name": { "givenName": "James", "familyName": "Smith" }, "email": "james@example.com", "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "homeAddress": { "streetAddress": "123 Main Street", "postalCode": "95121", "locality": "San Jose", "region": "CA", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-67-1325", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "1982-09-01", "percentageOwnership": 25 } ] } } } Expected Result: { "data": { "createUSBusinessAccountHolder": { "__typename": "USBusinessAccountHolder", "externalId": "bluejay", "id": "", "createdAt": "2024-08-26T20:34:54.819Z", "updatedAt": "2024-08-26T20:34:54.887Z", "primaryAuthorizedPerson": { "id": "", "email": "gerrytest1@example.com", "dateOfBirth": "1980-09-01", "percentageOwnership": null, "authorizingPersonTitle": "PRESIDENT", "createdAt": "2024-08-26T20:34:54.821Z", "updatedAt": "2024-08-26T20:34:54.889Z", "name": { "givenName": "Gerry", "familyName": "Wolfe", "title": "", "suffix": "", "middleName": "" }, "homeAddress": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "95121", "region": "CA", "locality": "San Jose", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "5555555555", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": { "numberHash": "", "countryCodeAlpha3": "USA" } } }, "businessProfile": { "id": "", "website": "", "businessType": "PARTNERSHIP", "businessCreditRiskAttributes": { "annualRevenue": [ { "value": 1000, "currencyCode": "USD" } ] }, "createdAt": "2024-08-26T20:34:54.819Z", "updatedAt": "2024-08-26T20:34:54.887Z", "name": { "legalBusinessName": "HIGHNOTE", "doingBusinessAsName": "BlueJay Inc" }, "billingAddress": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "95121", "region": "CA", "locality": "San Jose", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "5555555555", "label": "MOBILE" } ], "identificationDocument": { "employerIdentificationNumber": { "numberHash": "", "countryCodeAlpha3": "USA" } }, "ultimateBeneficialOwners": [ { "id": "", "percentageOwnership": 25, "dateOfBirth": "1982-09-01", "email": "james@example.com", "createdAt": "2024-08-26T20:34:54.821Z", "updatedAt": "2024-08-26T20:34:54.889Z", "name": { "givenName": "James", "familyName": "Smith", "title": "", "suffix": "", "middleName": "" }, "homeAddress": { "streetAddress": "123 Main Street", "extendedAddress": "", "postalCode": "95121", "region": "CA", "locality": "San Jose", "countryCodeAlpha3": "USA" }, "phoneNumbers": [ { "countryCode": "1", "number": "5555555555", "label": "MOBILE" } ], "identificationDocument": { "socialSecurityNumber": { "numberHash": "", "countryCodeAlpha3": "USA" } } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 30, "limit": 2500, "remaining": 2469 } } } ### GraphQL: EnableCollaborativeApplicationUnderwritingFeature Query: mutation EnableCollaborativeApplicationUnderwritingFeature( $input: EnableCollaborativeApplicationUnderwritingFeatureInput! ) { enableCollaborativeApplicationUnderwritingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "" } } Expected Result: { "data": { "enableCollaborativeApplicationUnderwritingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "CollaborativeApplicationUnderwritingCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "billingAddress": { "streetAddress": "123 Main Street", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA", "postalCode": "60654" }, "currentVerification": { "reason": "PENDING", "results": [], "status": "PENDING" } }, "updatedAt": "2023-09-01T22:27:06.896Z", "createdAt": "2023-09-01T22:27:06.760Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60023 } } } ### GraphQL: IssueFinancialAccountForApplication Query: mutation IssueFinancialAccountForApplication( $input: IssueFinancialAccountForApplicationInput! ) { issueFinancialAccountForApplication(input: $input) { ... on FinancialAccount { id name createdAt updatedAt cardProductApplication { ... on AccountHolderCardProductApplication { applicationState { status } } } cardProduct { id vertical } activeBillingCycleConfiguration { billingCycleStartDayOfMonth paymentDueDayOfMonth id __typename } features { __typename enabled createdAt updatedAt } owner { __typename ... on Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Test Commercial Revolving Credit Account", "externalId": "ABC123456" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "name": "Test Commercial Revolving Credit Account", "createdAt": "2024-08-09T16:50:45.647Z", "updatedAt": "2024-08-09T16:50:45.647Z", "application": { "id": "", "createdAt": "2024-08-07T19:51:59.225Z" }, "cardProduct": { "id": "", "vertical": "COMMERCIAL_CREDIT" }, "activeBillingCycleConfiguration": null, "features": [ { "__typename": "CreditPaymentCardFinancialAccountFeature", "enabled": true, "createdAt": "2024-08-09T16:50:45.647Z", "updatedAt": "2024-08-09T16:50:45.647Z" }, { "__typename": "CreditCardAccountFeature", "enabled": true, "createdAt": "2024-08-09T16:50:45.647Z", "updatedAt": "2024-08-09T16:50:45.647Z" } ], "owner": { "__typename": "USBusinessAccountHolder", "id": "" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 15 } } } ### GraphQL: InitiateFinancialAccountCreditLimitUpdateFromProductFunding Query: mutation InitiateFinancialAccountCreditLimitUpdateFromProductFunding( $input: InitiateFinancialAccountCreditLimitUpdateFromProductFundingInput! ) { initiateFinancialAccountCreditLimitUpdateFromProductFunding(input: $input) { __typename ... on Node { id } ... on FinancialAccountCreditLimitUpdateFromProductFunding { id status statusReason createdAt updatedAt memo amount { value currencyCode } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "amount": { "value": 450000, "currencyCode": "USD" }, "financialAccountId": "", "memo": "Assign Credit Limit to Financial Account" } } Expected Result: { "data": { "initiateFinancialAccountCreditLimitUpdateFromProductFunding": { "__typename": "FinancialAccountCreditLimitUpdateFromProductFunding", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2022-09-26T23:26:36.887Z", "updatedAt": "2022-09-26T23:26:36.887Z", "memo": "Assign Credit Limit to Financial Account", "amount": { "value": 450000, "currencyCode": "USD" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489661", "last4": "9602", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "", "name": "Test Consumer Credit Account" } ], "restrictedDetails": { "message": "Access is denied" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } ### GraphQL: FindFinancialAccount Query: fragment statement on CommercialRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffDays } } } secondaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingSecondaryCreditBalance { value currencyCode } startingSecondaryDebitBalance { value currencyCode } endingSecondaryCreditBalance { value currencyCode } endingSecondaryDebitBalance { value currencyCode } } query FindFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id statementSnapshot { ... on ConsumerRevolvingCardFinancialAccountStatementSnapshot { currentAmountDue { value } } ... on FinancialAccountStatementSnapshot { asOf currentOpenStatement { ...statement } latestClosedStatement { ...statement } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "statementSnapshot": { "asOf": "2024-08-07T19:58:15.560Z", "currentOpenStatement": { "id": "", "__typename": "CommercialRevolvingCardFinancialAccountStatement", "periodStart": "2024-08-07T04:00:00.000Z", "periodEnd": "2024-09-07T04:00:00.000Z", "openedAt": "2024-08-07T19:58:15.280Z", "closedAt": null, "paymentDueOn": "2024-09-17T04:00:00.000Z", "pastDueAmount": null, "periodMinimumPaymentDue": null, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 150000, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 150000, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": null, "periodPurchaseCreditPlan": [], "payOffWarning": { "paymentCycles": [] }, "secondaryLedger": { "id": "", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 50000, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingSecondaryCreditBalance": { "value": 50000, "currencyCode": "USD" }, "startingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" } }, "latestClosedStatement": { "id": "", "__typename": "CommercialRevolvingCardFinancialAccountStatement", "periodStart": "2024-02-07T04:00:00.000Z", "periodEnd": "2024-03-07T04:00:00.000Z", "openedAt": "2024-08-07T19:53:59.517Z", "closedAt": "2024-08-07T19:58:15.280Z", "paymentDueOn": "2024-03-17T04:00:00.000Z", "pastDueAmount": null, "periodMinimumPaymentDue": { "value": 2500, "currencyCode": "USD" }, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 150000, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 150000, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": { "value": 0, "currencyCode": "USD" }, "periodPurchaseCreditPlan": [ { "balanceType": "PURCHASE", "balanceSubjectToInterestAmount": { "value": 150000, "currencyCode": "USD" }, "interestChargedAmount": { "value": 0, "currencyCode": "USD" }, "apr": 19.56 } ], "payOffWarning": { "paymentCycles": [ { "payOffType": "MINIMUM_PAY_OFF", "paymentDetails": { "periodPayment": { "value": 2500, "currencyCode": "USD" }, "estimatedTotal": { "value": 272925, "currencyCode": "USD" }, "estimatedPayOffDays": 3030 } }, { "payOffType": "THREE_YEAR_PAY_OFF", "paymentDetails": { "periodPayment": { "value": 5255, "currencyCode": "USD" }, "estimatedTotal": { "value": 195839, "currencyCode": "USD" }, "estimatedPayOffDays": 1095 } } ] }, "secondaryLedger": { "id": "", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 50000, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingSecondaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "startingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryCreditBalance": { "value": 50000, "currencyCode": "USD" }, "endingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" } } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 55, "limit": 60060, "remaining": 60005 } } } --- URL: https://docs.highnote.com/docs/issuing/templates/consumer-credit Title: Consumer Credit Template Section: Issuing Description: Create consumer revolving credit card products. Onboard account holders, open applications, set credit limits, issue cards, schedule repayments, and generate statements. ## Overview Consumer credit card products support revolving lines of credit, which require account holders to make minimum payments by their billing cycle due date. Additionally, you can assess interest charges on revolving balances. Highnote supports the following consumer credit card products: | Configuration | Description | | :----------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Unsecured credit card products | These credit card products are not backed by an account holder deposit and require adequate capital to fund lines of credit. You can provide capital on your behalf or through a debt facility. | | Secured credit card products | These credit card products are backed by an account holder's secure deposit. | | Credit processing-only model | This model uses the Highnote platform to fund credit products on-demand, bypassing full ledger capabilities and repayment services. For more information on this model, contact support@highnote.com. | This guide provides an overview of creating and setting up an unsecured consumer credit card product using the Highnote API in the Test environment. In the Live environment, the Highnote team will assist with creating your card product. ## Create card product To enable secure deposits or use the credit processing-only model, contact support@highnote.com Use the following mutation to create an unsecured credit card product in the Test environment. To create a consumer credit card product, use as the input variable: ### Add credit feature After creating a card product, use the following mutation to add the feature. This feature enables minimum payment terms and revolving balance capabilities for financial accounts: ### View credit features In the Test environment, credit and charge card products are automatically assigned credit features and settings. These features and settings are similar to a live program's credit policies, which are configured by the Highnote team during program setup. The following table outlines the default features and settings for consumer credit card products in the Test environment: | Credit policy | Description | Test Environment Default Setting | | :----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------ | | | This setting controls your Test environment's delinquency policy. | Delinquent when >= 30 days | | | This setting controls your Test environment's policy for account suspension. | Suspended when >= 90 days | | | This setting controls your Test environment's charge-off policy. | Balance charged off when >= 180 days | | | This setting controls the minimum payment for account holders. The minimum payment is the greater of $25 or 1% of the statement balance, plus interest charges, fees, and any past amount due. If the balance is less than $25, the minimum payment is equal to the statement balance. | Minimum payment is = 1%, = $25 | Use the following query to view credit features for your credit card product in the Test environment: ## Fund your card program Unsecured credit card products use a product funding account to issue lines of credit. The product funding account is where you deposit the capital that you or your debt facility provide to back lines of credit. 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: 1. Retrieve the product funding account ID. 2. 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: ### Initiate a wire transfer Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Create credit plans Credit plans allows you to meet unique needs of your account holders by providing flexible and configurable terms on credit card products. Credit plans define the following: - Interest rate - Interest rate type - Interest accrual method - Pricing and policy terms for specific balance types You can create credit plans in the Test environment to test your card product. For more information on creating credit plans, see Create Credit Plans. The Highnote team will create credit plans for your card product in the Live environment. ## Create an account holder Your credit policy dictates the data required to issue a line of credit in the Live environment. Some credit policies require more data than the and . Before issuing a line of credit, you should collect and from your applicants. These fields are inputs for the object. There are two recommended methods for collecting this information: - Collect from the account holder when they are completing their application. - Update the account holder with the necessary details after they've submitted their application. Use the following mutation to create an account holder for a consumer credit card product. Provide as necessary: ## Account holder applications Application approval for credit card products in the Live environment uses one of the following workflows: - Highnote runs your credit policy for you and approves or denies applications based on your credit policy. - You participate in collaborative application decisioning to provide a recommended approval or denied application response. ### Enable collaborative application decisioning By default, in the Test environment, you can simulate credit application decisions with various values. These simulation values are used when onboarding an account holder. Use this default setting if Highnote will be executing your credit policy on your behalf. For more information, see the Simulate Underwriting Decision guide. Alternatively, you or your underwriter can use collaborative application decisioning. This feature allows you to recommend an approval or denial based on your credit policy. For more information, see Collaborative Application Decisioning. Enable collaborative application decisioning in the Highnote dashboard, or using the API with the following mutation: ### Open an application When an account holder application is submitted, it triggers an application decision request. If you use collaborative application decisioning, you can respond with a recommended or decision. 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: ### Simulate application decision If Highnote runs your credit policy for you, use the following input variables when creating applications: - - For more information on credit application simulations, see Simulate Underwriting Decision. ## Issue financial account With an application, you can create a financial account using the following mutation: ## Set a credit limit Setting or updating a credit limit is an asynchronous process to ensure your ledger balances and validations are in check. You can set or update a financial account’s credit limit by providing the and the credit limit you want to assign to the financial account. Your product funding financial account must have funds equal to or exceeding any credit limit you extend to your account holders. Use the following mutation to set or update a credit limit: ## Issue a payment card Once you have created a financial account with a credit limit, you can issue a payment card. By default, all payment cards start as virtual cards. Highnote supports the following types of payment cards: - Virtual cards - Physical cards - Digital wallets ### Virtual cards Use the following mutation to issue a virtual card: ### 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. ## 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: ## Schedule repayments Consumer credit card products require regular repayments. An account holder needs to connect a verified external bank account to Highnote to schedule a repayment. Once a verified account is linked, the account holder can use ACH transfers to schedule payments. Highnote supports the following types of payment schedules: - Recurring payments - One-time payments ### Connect a verified external bank account Account holders must have a verified external bank account connected to Highnote to schedule repayments. For more information on connecting external accounts, see Connect External Accounts. ### Create a payment schedule Payment due dates are determined by (1) the financial account's creation date, and (2) the card product's grace period. You can establish one-time or recurring payment schedules, enabling your customers to schedule payments on their monthly due date or a customized calendar day. Recurring payment schedules are based on a point-in-time balance, such as an outstanding balance, and the ACH transfer amount will be calculated on the scheduled date. See the scheduled repayments guide for more information on managing, viewing, and canceling payment schedules. ## Generate a billing statement Highnote provides essential data for generating billing statements for financial accounts. To create a billing statement, we recommend creating a template and using the data Highnote provides to fill in the template. For more information on billing statements, see Deliver Statements. Refer to the following guidelines for creating a billing statement: - Billing statement data is available at the close of a billing cycle. Credit card product billing period end dates may vary across financial accounts. Typically, statement data is available within 48 hours after the billing period ends. - To retrieve the current amount due for your card product, reference the . This balance can be presented to your customers outside the billing statement, for example, on your website or application's "account page". Use the following query to fetch billing statement data: ## 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. ## Simulate delinquency Highnote's delinquency simulator lets you view a financial account's current delinquency status and receivables by simulating past purchase and payment scenarios. In the Test environment, this helps with understanding delinquency scenarios and testing notification events. Use the Simulate Delinquency guide for more information on using the Highnote API to simulate delinquency in the Test environment. ## 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. - Setup notifications to automate your integration. ### GraphQL: CreateCardProduct Query: mutation CreateCardProduct($input: CreateCardProductInput!) { createCardProduct(input: $input) { __typename ... on CardProduct { id name usage vertical } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProduct": { "name": "Consumer Credit Card", "usage": "MULTI_USE", "vertical": "CONSUMER_CREDIT" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "", "name": "Consumer Credit Card", "usage": "MULTI_USE", "vertical": "CONSUMER_CREDIT" } }, "extensions": { "requestId": "" } } ### GraphQL: EnableCreditCardFeature Query: mutation EnableCreditCardFeature($input: EnableCreditCardFeatureInput!) { enableCreditCardFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "feature": "REVOLVING" } } Expected Result: { "data": { "enableCreditCardFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "RevolvingCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60045 } } } ### GraphQL: GetCardProductWithCreditConfiguration Query: query GetCardProductWithCreditConfiguration($id: ID!) { node(id: $id) { __typename ... on CardProduct { id creditConfiguration { ... on CreditCardProductConfiguration { accountAging { delinquentInDays suspendedInDays chargeOffInDays lateFeeGracePeriodInDays } minimumPayment { percentage thresholdAmount { value currencyCode } includesPastDueAmount includesInterestAmount includesFeesCharged } repayment { repaymentWaterfall } interest { includesPurchase includesFees } billingCycleConfiguration { billingCyclePeriod billingCycleGracePeriodType billingCycleGracePeriodInDays } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "creditConfiguration": { "accountAging": { "delinquentInDays": 30, "suspendedInDays": 60, "chargeOffInDays": 90, "lateFeeGracePeriodInDays": 10 }, "minimumPayment": { "percentage": 10, "thresholdAmount": { "value": 2000, "currencyCode": "USD" }, "includesPastDueAmount": true, "includesInterestAmount": false, "includesFeesCharged": true }, "repayment": { "repaymentWaterfall": [ "PURCHASE", "INTEREST", "FEES" ] }, "interest": { "includesPurchase": true, "includesFees": true }, "billingCycleConfiguration": { "billingCyclePeriod": "MONTHLY", "billingCycleGracePeriodType": "FLOATING", "billingCycleGracePeriodInDays": 10 } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 8 } } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "node": { "id": "", "features": [ { "enabled": true, "__typename": "ProductFundingFinancialAccountFeature" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60041 } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... 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": "", "memo": "Consumer Credit product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "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": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60040 } } } ### GraphQL: 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": "some-id" } } } Expected Result: { "data": { "createUSPersonAccountHolder": { "__typename": "USPersonAccountHolder", "id": "", "email": "gerrytest1@abc.com", "dateOfBirth": "1980-09-01", "externalId": "some-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": "", "countryCodeAlpha3": "USA" } }, "personCreditRiskAttributes": { "totalAnnualIncome": [ { "value": 1000, "currencyCode": "USD" } ], "currentDebtObligations": [ { "value": 1000, "currencyCode": "USD" } ], "employmentStatus": "EMPLOYED" } } }, "extensions": { "requestId": "" } } ### GraphQL: EnableCollaborativeApplicationUnderwritingFeature Query: mutation EnableCollaborativeApplicationUnderwritingFeature( $input: EnableCollaborativeApplicationUnderwritingFeatureInput! ) { enableCollaborativeApplicationUnderwritingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "" } } Expected Result: { "data": { "enableCollaborativeApplicationUnderwritingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "CollaborativeApplicationUnderwritingCardProductFeature", "enabled": true } ] } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "cardProduct": { "id": "" }, "accountHolderSnapshot": { "accountHolderCurrent": { "id": "" }, "name": { "givenName": "Gerry", "familyName": "Wolfe" }, "billingAddress": { "streetAddress": "123 Main Street", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA", "postalCode": "60654" }, "currentVerification": { "reason": "PENDING", "results": [], "status": "PENDING" } }, "updatedAt": "2023-09-01T22:27:06.896Z", "createdAt": "2023-09-01T22:27:06.760Z" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60023 } } } ### GraphQL: IssueFinancialAccountForApplication Query: mutation IssueFundingFinancialAccountForApplication( $input: IssueFinancialAccountForApplicationInput! ) { issueFinancialAccountForApplication(input: $input) { ... on FinancialAccount { id name createdAt updatedAt cardProductApplication { ... on AccountHolderCardProductApplication { applicationState { status } } } cardProduct { id vertical } features { __typename enabled createdAt updatedAt ... on CreditCardAccountFeature { enabled createdAt updatedAt creditLimit { value currencyCode } } } owner { __typename ... on Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "ABC123456" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "id": "", "vertical": "CONSUMER_CREDIT" }, "features": [ { "__typename": "CreditPaymentCardFinancialAccountFeature", "enabled": true, "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.932Z" }, { "__typename": "CreditCardAccountFeature", "enabled": true, "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.932Z", "creditLimit": null } ], "owner": { "__typename": "USPersonAccountHolder", "id": "" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 15, "limit": 60060, "remaining": 60045 } } } ### GraphQL: InitiateFinancialAccountCreditLimitUpdateFromProductFunding Query: mutation InitiateFinancialAccountCreditLimitUpdateFromProductFunding( $input: InitiateFinancialAccountCreditLimitUpdateFromProductFundingInput! ) { initiateFinancialAccountCreditLimitUpdateFromProductFunding(input: $input) { __typename ... on Node { id } ... on FinancialAccountCreditLimitUpdateFromProductFunding { id status statusReason createdAt updatedAt memo amount { value currencyCode } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "amount": { "value": 450000, "currencyCode": "USD" }, "financialAccountId": "", "memo": "Assign Credit Limit to Financial Account" } } Expected Result: { "data": { "initiateFinancialAccountCreditLimitUpdateFromProductFunding": { "__typename": "FinancialAccountCreditLimitUpdateFromProductFunding", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2022-09-26T23:26:36.887Z", "updatedAt": "2022-09-26T23:26:36.887Z", "memo": "Assign Credit Limit to Financial Account", "amount": { "value": 450000, "currencyCode": "USD" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489661", "last4": "9602", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "", "name": "Test Consumer Credit Account" } ], "restrictedDetails": { "message": "Details" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } ### GraphQL: FindFinancialAccount Query: fragment statement on ConsumerRevolvingCardFinancialAccountStatement { id __typename periodStart periodEnd openedAt closedAt paymentDueOn pastDueAmount { value currencyCode } periodMinimumPaymentDue { value currencyCode } primaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingPrimaryCreditBalance { value currencyCode } startingPrimaryDebitBalance { value currencyCode } endingPrimaryCreditBalance { value currencyCode } endingPrimaryDebitBalance { value currencyCode } periodInterestCharges { value currencyCode } periodPurchaseCreditPlan { balanceType balanceSubjectToInterestAmount { value currencyCode } interestChargedAmount { value currencyCode } apr } payOffWarning { paymentCycles { payOffType paymentDetails { periodPayment { value currencyCode } estimatedTotal { value currencyCode } estimatedPayOffDays } } } secondaryLedger { id name normalBalance creditBalance { value currencyCode } debitBalance { value currencyCode } } startingSecondaryCreditBalance { value currencyCode } startingSecondaryDebitBalance { value currencyCode } endingSecondaryCreditBalance { value currencyCode } endingSecondaryDebitBalance { value currencyCode } } query FindFinancialAccount($id: ID!) { node(id: $id) { ... on FinancialAccount { id statementSnapshot { ... on ConsumerRevolvingCardFinancialAccountStatementSnapshot { currentAmountDue { value } } ... on FinancialAccountStatementSnapshot { asOf currentOpenStatement { ...statement } latestClosedStatement { ...statement } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "statementSnapshot": { "currentAmountDue": { "value": 114835 }, "asOf": "2023-11-30T07:54:46.011Z", "currentOpenStatement": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-11-30T05:00:00.000Z", "periodEnd": "2023-12-28T05:00:00.000Z", "openedAt": "2023-11-30T07:54:45.333Z", "closedAt": null, "paymentDueOn": "2024-01-05T05:00:00.000Z", "pastDueAmount": null, "periodMinimumPaymentDue": null, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": null, "periodPurchaseCreditPlan": [], "payOffWarning": { "paymentCycles": [] }, "secondaryLedger": { "id": "", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 85165, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingSecondaryCreditBalance": { "value": 87649, "currencyCode": "USD" }, "startingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryCreditBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" } }, "latestClosedStatement": { "id": "", "__typename": "ConsumerRevolvingCardFinancialAccountStatement", "periodStart": "2023-09-30T05:00:00.000Z", "periodEnd": "2023-10-28T05:00:00.000Z", "openedAt": "2023-11-30T07:51:25.643Z", "closedAt": "2023-11-30T07:54:45.333Z", "paymentDueOn": "2023-11-05T05:00:00.000Z", "pastDueAmount": { "value": 5878, "currencyCode": "USD" }, "periodMinimumPaymentDue": { "value": 11862, "currencyCode": "USD" }, "primaryLedger": { "id": "", "name": "OUTSTANDING_BALANCE_PAYABLE", "normalBalance": "CREDIT", "creditBalance": { "value": 114835, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingPrimaryCreditBalance": { "value": 2473, "currencyCode": "USD" }, "startingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingPrimaryCreditBalance": { "value": 114835, "currencyCode": "USD" }, "endingPrimaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "periodInterestCharges": { "value": 2484, "currencyCode": "USD" }, "periodPurchaseCreditPlan": [ { "balanceType": "PURCHASE", "balanceSubjectToInterestAmount": { "value": 129202, "currencyCode": "USD" }, "interestChargedAmount": { "value": 2484, "currencyCode": "USD" }, "apr": 23.99 } ], "payOffWarning": { "paymentCycles": [ { "payOffType": "MINIMUM_PAY_OFF", "paymentDetails": { "periodPayment": { "value": 11862, "currencyCode": "USD" }, "estimatedTotal": { "value": 149572, "currencyCode": "USD" }, "estimatedPayOffDays": 990 } }, { "payOffType": "THREE_YEAR_PAY_OFF", "paymentDetails": { "periodPayment": { "value": 11862, "currencyCode": "USD" }, "estimatedTotal": { "value": 153470, "currencyCode": "USD" }, "estimatedPayOffDays": 1095 } } ] }, "secondaryLedger": { "id": "", "name": "AVAILABLE_CREDIT", "normalBalance": "CREDIT", "creditBalance": { "value": 85165, "currencyCode": "USD" }, "debitBalance": { "value": 0, "currencyCode": "USD" } }, "startingSecondaryCreditBalance": { "value": 200000, "currencyCode": "USD" }, "startingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" }, "endingSecondaryCreditBalance": { "value": 87649, "currencyCode": "USD" }, "endingSecondaryDebitBalance": { "value": 0, "currencyCode": "USD" } } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 55, "limit": 60060, "remaining": 60005 } } } --- URL: https://docs.highnote.com/docs/issuing/templates/fleet-credit Title: Fleet Credit Template Section: Issuing Description: End-to-end template for issuing fleet credit cards, from account holder onboarding to card product creation and virtual card issuance. ## Overview Fleet credit card products allow businesses to use payment cards to purchase fuel and vehicle maintenance-related services. Fleet cards are useful for the following features: - Track spending on fuel, mileage driven, and maintenance schedules - Restrict purchases to fueling stations - Designate payment cards to vehicles - Report enhanced transaction data metrics The following graphic provides an overview of the processing for issuing fleet cards: ## How it works Fleet card products are credit card products that have specialized features and settings. Fleet card products use the following features and settings: - **Required**: Spend rules to limit how payment cards may be used - _Optional_: Collaborative authorization for approving and denying transactions in real-time For clearing events, fleet cards return enhanced data using specialized clearing messages. This data is split into three levels: - **Level 1**: Contains standard payment network transaction data provided by merchants. Level 1 data is the same for all transaction types and merchants. No enhanced data is captured or provided at this level. - **Level 2**: Contains enhanced data captured at the point of sale and sent with transactions. Level 2 data is always sent with clearing records. - **Level 3**: Contains detailed enhanced data for transactions and is generally used to send specifics for non-fuel products and services. Level 3 data is sent anywhere from 24 hours to 48 hours after a transaction clears. For simulating enhanced data, see Simulate Fleet Transactions. ## Create a card product Use the following mutation to create a fleet card product in the Test environment. Use as the input variable: ## Fund your card program Fleet card products use a product funding account to issue lines of credit. The product funding account is where you deposit the capital that you or your debt facility provide to back lines of credit. In the Test environment, you can simulate depositing funds into your product funding account. Simulating deposits doesn't require connecting a verified bank account. Funding your product funding account requires the following steps: 1. Retrieve the product funding account ID. 2. 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: ### Initiate a wire transfer Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Create an account holder Fleet card products are used by **business account holders**. US business account holders must provide business details and a primary authorized person, with the option to add beneficial owners. Before issuing a line of credit, you may want to collect inputs in the credit application. These fields can be used to simulate credit line assignment or simulate adverse action reasons. ### Fuel tax exemption {#fuel-tax-exemption} Be careful. The fuel tax exemption attribute must be set during account holder creation. It cannot be added or updated after onboarding. For non-exempt fleets, omit (which is optional). For fuel tax exempt fleets, pass in the input with: - set to - set to - date in format. When the fuel tax exemption is enabled, Highnote's platform tracks the Fleet's qualifying transactions to enable fuel tax reclamation reporting. Use the following mutation to create a business account holder. The [](/docs/api-reference/mutation#tokenizeUSBusinessAccountHolder) mutation accepts the same input, so can be included in the tokenized flow. ### Query fuel tax exemption status You can read back the fuel tax exemption status by querying the business account holder's : ## 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: ## Simulate application decision The Test environment does not run identity verification checks on applications. During testing, you can simulate application approvals or denials using simulation values. These simulation values produce tags that result in the following application statuses: - - - For more information on using this simulation, see Simulate Underwriting Decision. ## Issue a financial account Financial accounts hold the balance for payment cards. To create a new financial account, pass the of a verified application. Financial accounts have an variable field that allows you to tie the financial account to an entity in your system. If you do not pass in an , Highnote will generate one. Use the following mutation to issue a financial account for an application: ## Set credit limit Setting or updating a credit limit is an asynchronous process with the Highnote team to ensure your ledger balances and validations are in check. You can set a financial account's credit limit by providing the and the credit limit you want to assign to the financial account. Your product funding financial account must have funds equal to or exceeding any credit limit you extend to your account holders. Use the following mutation to set a credit limit: ### Available credit After setting a credit limit for a financial account, account holders can use their payment cards for fuel and maintenance purchases. Each transaction results in ledger entries that reflect adjustments to the ledger. To reflect repayment and adjustments, you must update the ledger to reflect the available funds the account holder can spend. ### Increase available credit When an account holder repays their balance, you can increase their ledger using the following mutation: ### Decrease available credit To reduce the balance of the ledger, use the following mutation: ## 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. See Issue Virtual Cards. Use the following mutation to issue a virtual card: ### Physical cards Highnote also supports issuing personalized payment cards to account holders. 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. See Add Cards to Digital Wallets. ## Display payment card data Highnote recommends using the Card Viewer SDK to securely display payment card data and reduce your PCI scope. 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: ## Configure spend rules Fleet card products use spend rules and velocity controls to control spending for the following common use cases: - Spending amount limits - Authorization count limits - Merchant category code (MCC) limits - Merchant identifier (MID) limits - Point of service category controls For more information on configuring spend rules and velocity controls, see the following guides: - Configure Spend Rules - Configure Velocity Controls ## Simulate transactions After configuring your fleet card product, we recommend simulating transactions. Simulating transactions is useful for testing your card program's configurations and settings. For more information on simulating transactions, see Simulate Fleet Transactions. ## Simulate delinquency Highnote's delinquency simulator lets you view a financial account's current delinquency status and receivables by simulating past purchase and payment scenarios. In the Test environment, this helps with understanding delinquency scenarios and testing notification events. See Simulate Delinquency for more information on using the Highnote API to simulate delinquency in the Test environment. ## Expand your integration After configuring your card product and simulating transactions, you can use the following features to further expand your integration: - Create a rewards program for your card product. - Set up notifications to automate your integration. ### GraphQL: 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": "Fleet Credit", "usage": "MULTI_USE", "vertical": "FLEET" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "Y2FyZHBy", "name": "Fleet Credit", "usage": "MULTI_USE" } }, "extensions": { "requestId": "b85fc1ec-e770-9d06-922f-16b7486a690e" } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "node": { "id": "", "features": [ { "enabled": true, "__typename": "ProductFundingFinancialAccountFeature" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60041 } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... 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": "", "memo": "Consumer Credit product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "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": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60040 } } } ### GraphQL: CreateUSBusinessAccountHolder Query: mutation CreateUSBusinessAccountHolder( $input: CreateUSBusinessAccountHolderInput! ) { createUSBusinessAccountHolder(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on USBusinessAccountHolder { id externalId createdAt updatedAt businessProfile { id name { legalBusinessName doingBusinessAsName } businessType operatingDetails { indicatorAttributes { type value reportedAt } } } } } } Variables: { "input": { "primaryAuthorizedPerson": { "name": { "givenName": "", "familyName": "" }, "dateOfBirth": "1980-01-01", "homeAddress": { "streetAddress": "123 Main St", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-11-1111", "countryCodeAlpha3": "USA" } } }, "businessProfile": { "name": { "legalBusinessName": "LEGAL_BUSINESS_NAME" }, "businessType": "LIMITED_LIABILITY_COMPANY", "billingAddress": { "streetAddress": "456 Commerce Blvd", "postalCode": "90210", "locality": "Los Angeles", "region": "CA", "countryCodeAlpha3": "USA" }, "identificationDocument": { "employerIdentificationNumber": { "number": "12-3456789", "countryCodeAlpha3": "USA" } }, "businessPlanAttributes": [ { "indicatorAttribute": { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } } ] } } } Expected Result: { "data": { "createUSBusinessAccountHolder": { "__typename": "USBusinessAccountHolder", "id": "", "externalId": null, "createdAt": "2026-03-26T18:00:00.000Z", "updatedAt": "2026-03-26T18:00:00.000Z", "businessProfile": { "id": "", "name": { "legalBusinessName": "LEGAL_BUSINESS_NAME", "doingBusinessAsName": null }, "businessType": "LIMITED_LIABILITY_COMPANY", "operatingDetails": { "indicatorAttributes": [ { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } ] } } } }, "extensions": { "requestId": "1ab32e1c-4949-9421-8240-c39ca4123jkl" } } ### GraphQL: GetBusinessAccountHolder Query: query GetBusinessAccountHolder($id: ID!) { node(id: $id) { ... on USBusinessAccountHolder { id businessProfile { name { legalBusinessName } operatingDetails { indicatorAttributes { type value reportedAt } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "id": "", "businessProfile": { "name": { "legalBusinessName": "Fuel Corp." }, "operatingDetails": { "indicatorAttributes": [ { "type": "FUEL_TAX_EXEMPT", "value": true, "reportedAt": "2026-03-15" } ] } } } }, "extensions": { "requestId": "a23de4f1-8821-4b3c-9a17-6c4f82d19e05" } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "createdAt": "2021-07-07T23:22:30.475Z", "updatedAt": "2021-07-07T23:22:30.475Z" } }, "extensions": { "requestId": "" } } ### GraphQL: 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 Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: InitiateFinancialAccountCreditLimitUpdateFromProductFunding Query: mutation InitiateFinancialAccountCreditLimitUpdateFromProductFunding( $input: InitiateFinancialAccountCreditLimitUpdateFromProductFundingInput! ) { initiateFinancialAccountCreditLimitUpdateFromProductFunding(input: $input) { __typename ... on Node { id } ... on FinancialAccountCreditLimitUpdateFromProductFunding { id status statusReason createdAt updatedAt memo amount { value currencyCode } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "financialAccountId": "", "memo": "Set Limit", "amount": { "value": 100, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateFinancialAccountCreditLimitUpdateFromProductFunding": { "__typename": "FinancialAccountCreditLimitUpdateFromProductFunding", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2022-06-21T18:01:28.992Z", "updatedAt": "2022-06-21T18:01:28.993Z", "memo": null, "amount": { "value": 100, "currencyCode": "USD" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "fromFinancialAccountId": "", "memo": "", "amount": { "value": 6000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccount": { "__typename": "InterFinancialAccountTransfer", "id": "", "status": "PENDING", "statusReason": null, "createdAt": "2022-09-09T00:09:02.864Z", "updatedAt": "2022-09-09T00:09:02.867Z", "memo": "", "amount": { "value": 6000, "currencyCode": "USD" } } }, "extensions": { "requestId": "24f2f37c-4414-46d3-9e66-a031f30113af" } } ### GraphQL: 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": "", "fromFinancialAccountId": "", "memo": "unload card", "amount": { "value": 5000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccount": { "__typename": "InterFinancialAccountTransfer", "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" } } } } ### GraphQL: 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": "", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489661", "last4": "9602", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "", "name": "Test Consumer Credit Account" } ], "restrictedDetails": { "message": "Access is denied" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/templates/commercial-prepaid Title: Commercial Prepaid Template Section: Issuing Description: Create commercial prepaid card products for business expenses and disbursements. Onboard business account holders, issue cards, and fund accounts via ACH or direct deposit. ## Overview Commercial prepaid card products allow businesses to cover general business and employee expenses, track purchases and set limits, facilitate gig economy on-demand disbursements, or execute gift card donations. Commercial prepaid card products have the following features: - Debit card capabilities - A predefined amount of funds - Funded from a designated bank account Commercial prepaid cards require funding through a bank account. When additional funds are needed, a transfer is initiated to the account holder's financial account in Highnote, making the funds ready for use. This guide provides an overview of creating and setting up a commercial prepaid card product in the Test environment. ## Create a card product Use the following mutation to create a commercial prepaid card product. Use as the input variable: ## Create an account holder Commercial prepaid cards are used by US business account holders. Use the following mutation to create a US business account holder: ## 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: ## Issue a financial account Financial accounts hold the balance for payment cards. To create a new financial account, pass the of a verified application. Financial accounts have an variable field that allows you to tie the Financial account to an entity in your system. If you do not pass in an , Highnote will generate one. Use the following mutation to issue a financial account for an application: ## 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: ### 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 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: - If is in the past, the transfer processes immediately and is not held. - If is in the future, you must follow up with or to progress or fail the transfer. ::: ## Display account and routing number Prepaid cards have the feature enabled by default. Financial accounts with the 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: ## 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: ## 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. ### GraphQL: 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": "Commercial Prepaid", "usage": "MULTI_USE", "vertical": "COMMERCIAL_PREPAID" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "Y2FyZHByb2R1Y3RfcGRfNjI3YjEzYjAyMDI5NDJlN9FkOTBjZGJjNmQzYmY0NDE=", "name": "Commercial Prepaid", "usage": "MULTI_USE" } }, "extensions": { "requestId": "b85fc1ec-e770-9d06-922f-16b7486a699i" } } ### GraphQL: CreateUSBusinessAccountHolder Query: mutation CreateUSBusinessAccountHolder( $input: CreateUSBusinessAccountHolderInput! ) { createUSBusinessAccountHolder(input: $input) { __typename ... on USBusinessAccountHolder { externalId id primaryAuthorizedPerson { id email createdAt updatedAt } businessProfile { id createdAt updatedAt ultimateBeneficialOwners { id email createdAt updatedAt } } } } } Variables: { "input": { "primaryAuthorizedPerson": { "name": { "givenName": "Bill", "familyName": "Someone" }, "email": "foo@example.com", "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "homeAddress": { "streetAddress": "123 Main Street", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "number": "111-11-1111", "countryCodeAlpha3": "USA" } }, "dateOfBirth": "1980-09-01", "percentageOwnership": 25, "authorizingPersonTitle": "PRESIDENT" }, "businessProfile": { "name": { "legalBusinessName": "Foo Inc.", "doingBusinessAsName": "Foo Inc." }, "phoneNumber": { "countryCode": "1", "number": "5555555555", "label": "MOBILE", "extension": "312" }, "billingAddress": { "streetAddress": "123 Main Street", "postalCode": "60654", "locality": "Chicago", "region": "IL", "countryCodeAlpha3": "USA" }, "identificationDocument": { "employerIdentificationNumber": { "number": "12-3456789", "countryCodeAlpha3": "USA" } }, "website": "https://www.foowebsite.com", "businessType": "PARTNERSHIP", "ultimateBeneficialOwners": [ { "email": "foobo@example.com", "name": { "givenName": "Scott", "familyName": "Someone" }, "homeAddress": { "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" } }, "dateOfBirth": "1980-09-01", "percentageOwnership": 75 } ] }, "externalId": "user-id-in-your-system" } } Expected Result: { "data": { "createUSBusinessAccountHolder": { "__typename": "USBusinessAccountHolder", "externalId": "user-id-in-your-system", "id": "", "primaryAuthorizedPerson": { "id": "", "email": "foo@example.com", "createdAt": "2023-01-26T15:14:21.891Z", "updatedAt": "2023-01-26T15:14:22.070Z" }, "businessProfile": { "id": "", "createdAt": "2023-01-26T15:14:21.891Z", "updatedAt": "2023-01-26T15:14:22.070Z", "ultimateBeneficialOwners": [ { "id": "", "email": "james@example.com", "createdAt": "2023-01-26T15:14:21.891Z", "updatedAt": "2023-01-26T15:14:22.070Z" } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "createdAt": "2021-07-07T23:22:30.475Z", "updatedAt": "2021-07-07T23:22:30.475Z" } }, "extensions": { "requestId": "" } } ### GraphQL: 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 Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "externalId": "ABC123456" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: 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": "", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489661", "last4": "9602", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "", "name": "Test Consumer Credit Account" } ], "restrictedDetails": { "message": "Access is denied" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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" } } Expected Result: { "data": { "simulateNonOriginatedAchTransfer": { "__typename": "NonOriginatedAchTransfer", "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 } } } ### GraphQL: ViewDirectDepositDetails Query: query ViewDirectDepositDetails($id: ID!) { node(id: $id) { ... on FinancialAccount { directDepositDetails { id restrictedDetails { __typename ... on DirectDepositDetailRestrictedDetails { number routingNumber } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "ExternalBankAccountDetail", "id": "", "last4": "2730", "type": "CHECKING", "restrictedDetails": { "number": "0493712730", "routingNumber": "89703965" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/templates/consumer-prepaid Title: Consumer Prepaid Template Section: Issuing Description: Create consumer prepaid card products. Onboard account holders, issue cards, fund accounts via ACH or direct deposit, and add cards to digital wallets. ## 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 as the input variable: ## 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: 1. Retrieve the product funding account ID. 2. 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: ### Initiate a wire transfer Using the following mutation, simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Create an account holder Consumer cards are used by US person account holders. Use the following mutation to create a US person account holder: ## 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: ## Issue a financial account Financial accounts hold the balance for payment cards. To create a financial account, pass the of the account holder's approved application. Financial accounts have an variable field that allows you to tie the account to an entity in your system. If you do not pass in an , Highnote will generate one. Use the following mutation to issue a financial account for an application: ## 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: ### 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 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: - If is in the past, the transfer processes immediately and is not held. - If is in the future, you must follow up with or to progress or fail the transfer. ::: ### 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: - : Account holder's financial account ID - : Product funding account ID Use the following mutation to initiate a transfer from your product funding account: ## 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: - : Product funding account ID - : Account holder's payment card financial account ID ## Display account and routing number Prepaid cards have the feature enabled by default. Financial accounts with the 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: ## 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: ## 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. ### GraphQL: 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" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "G8FyZHByb2R1Y3RfcGRfNjI3YjEzYjAyMDI5NDJlN9FkOTBjZGJjNmQzYmY0TYU=", "name": "Consumer Prepaid", "usage": "MULTI_USE" } }, "extensions": { "requestId": "b85fc1ec-e770-9d06-922f-16b7486a677i" } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "node": { "id": "", "features": [ { "enabled": true, "__typename": "ProductFundingFinancialAccountFeature" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60041 } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... 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": "", "memo": "Consumer Credit product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "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": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60040 } } } ### GraphQL: 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": "" } } } Expected Result: { "data": { "createUSPersonAccountHolder": { "__typename": "USPersonAccountHolder", "id": "", "email": "gerrytest1@abc.com", "dateOfBirth": "1980-09-01", "externalId": "", "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": "" } } ### GraphQL: 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": "", "cardProductId": "", "cardHolderAgreementConsent": { "primaryAuthorizedPersonId": "", "consentTimestamp": "2021-12-22T17:10:55.662Z" } } } Expected Result: { "data": { "createAccountHolderCardProductApplication": { "__typename": "AccountHolderCardProductApplication", "id": "", "applicationState": { "status": "PENDING" }, "createdAt": "2021-07-07T23:22:30.475Z", "updatedAt": "2021-07-07T23:22:30.475Z" } }, "extensions": { "requestId": "" } } ### GraphQL: 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 Node { id } ... on USPersonAccountHolder { id } } } } } Variables: { "input": { "applicationId": "", "name": "Financial Account", "externalId": "" } } Expected Result: { "data": { "issueFinancialAccountForApplication": { "id": "", "externalId": "ABC123456", "name": "John Doe - Account", "createdAt": "2021-12-28T18:20:49.932Z", "updatedAt": "2021-12-28T18:20:49.960Z", "application": { "id": "", "createdAt": "2021-12-20T17:59:33.570Z" }, "cardProduct": { "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": "", "restrictedDetails": { "__typename": "AccessDeniedError" } }, "owner": { "__typename": "USPersonAccountHolder", "id": "" } } } } ### GraphQL: 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": "", "options": { "activateOnCreate": true, "expirationDate": "2023-01-01T23:59:59Z" } } } Expected Result: { "data": { "issuePaymentCardForFinancialAccount": { "id": "", "bin": "489661", "last4": "9602", "expirationDate": "2025-01-01T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "", "name": "Test Consumer Credit Account" } ], "restrictedDetails": { "message": "Access is denied" } } }, "extensions": { "requestId": "" } } ### GraphQL: 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" } } Expected Result: { "data": { "simulateNonOriginatedAchTransfer": { "__typename": "NonOriginatedAchTransfer", "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 } } } ### GraphQL: 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": "", "fromFinancialAccountId": "", "memo": "Fund Financial Account #1", "amount": { "value": 10000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferFromFundingFinancialAccountToPaymentCardFinancialAccount": { "__typename": "InterFinancialAccountTransfer", "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" } } } } ### GraphQL: 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": "", "fromFinancialAccountId": "", "memo": "unload card", "amount": { "value": 5000, "currencyCode": "USD" } } } Expected Result: { "data": { "initiateTransferFromPaymentCardFinancialAccountToFundingFinancialAccount": { "__typename": "InterFinancialAccountTransfer", "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" } } } } ### GraphQL: ViewDirectDepositDetails Query: query ViewDirectDepositDetails($id: ID!) { node(id: $id) { ... on FinancialAccount { directDepositDetails { id restrictedDetails { __typename ... on DirectDepositDetailRestrictedDetails { number routingNumber } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "ExternalBankAccountDetail", "id": "", "last4": "2730", "type": "CHECKING", "restrictedDetails": { "number": "0493712730", "routingNumber": "89703965" } } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/templates/vcx Title: Virtual Card Express Template Section: Issuing Description: Issue virtual cards for AP automation with minimal integration. Use the VCX quick start mutation to create a financial account and card in one step, set pseudo balance spending limits, and display card details with the Card Viewer SDK. ## Overview Virtual Card Express (VCX) is **built for fast onboarding and minimal integration**. VCX uses a subset of Highnote's issuing and funding capabilities to provide: - Mutations that issue a financial account and virtual card together. - Per-card spending limits via pseudo balance. - Secure card detail display using the Card Viewer SDK. VCX is **designed for issuing virtual cards for invoice or AP payments**. ## Integration options You have two ways to get started with VCX: - **No-code** — Contact your Highnote representative for support. - **Low-code** — Follow the steps below to integrate VCX into your application. For custom flows such as multiple card usages, complex routing, or deeply customized spend rules at issuance time, see the AP Automation template. This guide walks through the low-code path. It explains how to create and configure a VCX card product in your Test environment. ## Create a card product Create an AP Automation card product that VCX uses for issuing virtual cards. Use as the input variable: ## Fund your card program AP Automation card products use a product funding account to send funds to financial accounts. In the Test environment, you can simulate depositing funds into your product funding account without connecting a verified external bank account. Funding your product funding account requires the following steps: 1. Retrieve the product funding account ID. 2. Initiate a wire transfer to the product funding account. ### Find product funding account Use the following query to find your product funding account ID: ### Initiate wire transfer Simulate a wire transfer in the Test environment using the product funding account ID as the input variable: ## Enable on-demand funding AP Automation card products use on-demand funding to fund account holder financial accounts. When you create an AP Automation card product, your product funding account is used as the source account for on-demand funding. On-demand funding has an optional feature called pseudo balance. Pseudo balance lets you set a spending limit on a financial account to ensure account holders cannot spend over a specific amount. When a transaction is initiated for a financial account with a pseudo balance, Highnote checks the ledger to approve or decline the authorization. If the pseudo balance feature is not enabled, Highnote checks the balance of your product funding account during authorization. Use the following mutation to enable on-demand funding with pseudo balance: ## Issue payment card (VCX quick start) With VCX, you have two options when issuing a payment card: - VCX quick start (recommended) – one mutation to issue a financial account and a virtual payment card together. - Standard AP Automation flow – issue the financial account first, then issue a card for that account. The VCX quick start mutation issues a financial account and virtual payment card in a single step from an approved application. This is the recommended approach for VCX integrations. To issue the financial account and card independently, use followed by . See the AP Automation template for that flow. ## Set pseudo balance After issuing a card, set the pseudo balance (spending limit) for the associated financial account. This controls how much the cardholder can spend on the card in total. Use with so the available balance is not automatically reset: To adjust the pseudo balance during a card's lifetime — for example, when an invoice amount changes — use , , or . For details on each mutation and the available cadence options, see Manage pseudo limit and balance. ## Display payment card data With VCX, there are two methods for displaying payment card data on your website or application: - Use the Card Viewer SDK (recommended) - VCX low‑code pattern. - Fetch payment card data directly from the Highnote API - for PCI‑compliant environments only. Highnote recommends using the Card Viewer SDK to securely display payment card data and reduce PCI non-compliance risk. ### Generate a client token Generate a short-lived client token on your backend, then pass it to your frontend to render card details securely: ### Integrate Card Viewer SDK Install the SDK: ```bash npm install @highnoteplatform/card-viewer@alpha ``` The package is . An earlier version of this page said , which is not a package anyone can install — the scope is Highnote's internal registry, not public npm. Add container elements to your HTML: ```html
``` Initialize the SDK with your client token: ```javascript async function showCardDetails(clientToken, paymentCardId) { const viewer = createCardViewer({ getClientToken: async () => clientToken, paymentCardId, elements: { cardNumber: { selector: "#card-number" }, expirationDate: { selector: "#card-expiration" }, cvv: { selector: "#card-cvv" }, }, }); viewer.on("error", (error) => { console.error("Card Viewer error", error); }); await viewer.mount(); } ``` For full configuration options, see the Card Viewer SDK documentation. ### Fetch payment card data If your environment is PCI-compliant, you can fetch payment card data directly from the API: ## Simulate transactions After configuring your card product and issuing VCX virtual cards, simulate transactions to test your card program's configuration, including on-demand funding behavior, pseudo balance enforcement, and card authorization flows. 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 VCX integration: - Create spend rules to manage spending by merchant category, geography, and more. - Set up notifications to automate your integration and alert internal teams about card activity. - For a more robust solution, see the AP Automation template. ### GraphQL: 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": "AP Automation", "vertical": "AP_INVOICE_AUTOMATION" } } } Expected Result: { "data": { "createCardProduct": { "__typename": "CardProduct", "id": "Y2FyZHBy", "name": "Invoice Automation", "usage": "MULTI_USE" } }, "extensions": { "requestId": "b85fc1ec-e770-9d06-922f-16b7486a690e" } } ### GraphQL: 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": "" } Expected Result: { "data": { "node": { "id": "", "accounts": { "edges": [ { "node": { "id": "", "features": [ { "enabled": true, "__typename": "ProductFundingFinancialAccountFeature" } ] } } ] } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60041 } } } ### GraphQL: SimulateDeposit Query: mutation SimulateDeposit($input: SimulateDepositInput!) { simulateDeposit(input: $input) { __typename ... on Node { id } ... 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": "", "memo": "Consumer Credit product funding wire deposit" } } Expected Result: { "data": { "simulateDeposit": { "__typename": "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": "", "rateLimit": { "cost": 12, "limit": 60060, "remaining": 60040 } } } ### GraphQL: EnableOnDemandFundingFeature Query: mutation EnableOnDemandFundingFeature( $input: EnableOnDemandFundingFeatureInput! ) { enableOnDemandFundingFeature(input: $input) { __typename ... on CardProduct { id features { __typename enabled ... on OnDemandFundingCardProductFeature { pseudoBalanceEnabled } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "cardProductId": "", "pseudoBalanceEnabled": true } } Expected Result: { "data": { "enableOnDemandFundingFeature": { "__typename": "CardProduct", "id": "", "features": [ { "__typename": "CollaborativeAuthorizationCardProductFeature", "enabled": true }, { "__typename": "DisputeChargebackCardProductFeature", "enabled": true }, { "__typename": "OnDemandFundingCardProductFeature", "enabled": true, "pseudoBalanceEnabled": true }, { "__typename": "AuthorizedUserCardProductFeature", "enabled": false } ] } }, "extensions": { "requestId": "f332c811-82e7-965d-b0e6-17519a7bd4b1", "rateLimit": { "cost": 11, "limit": 2500, "remaining": 2484, "asOf": "2025-06-06T16:06:09.019Z", "complexity": { "limit": 2500, "remaining": 2484, "cost": 11 }, "count": { "limit": 100, "remaining": 94, "cost": 1 } } } } ### GraphQL: IssuePaymentCardForApplicationWithOnDemandFundingSource Query: mutation IssuePaymentCardForApplicationWithOnDemandFundingSource( $input: IssuePaymentCardForApplicationWithOnDemandFundingSourceInput! ) { issuePaymentCardForApplicationWithOnDemandFundingSource(input: $input) { __typename ... on PaymentCard { id bin last4 expirationDate network status financialAccounts { id } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "applicationId": "", "externalId": "INVOICE_12345", "options": { "activateOnCreate": true, "expirationDate": "2028-01-01T23:59:59Z" }, "sourceFinancialAccountId": "" } } Expected Result: { "data": { "issuePaymentCardForApplicationWithOnDemandFundingSource": { "__typename": "PaymentCard", "id": "", "bin": "444433", "last4": "1234", "expirationDate": "2028-12-31T23:59:59Z", "network": "MASTERCARD", "status": "ACTIVE", "financialAccounts": [ { "id": "" } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SetPseudoLimit Query: mutation SetPseudoLimit($input: SetPseudoLimitInput!) { setPseudoLimit(input: $input) { __typename ... on InterFinancialAccountTransfer { toFinancialAccount { id ledgers { name creditBalance { value } } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "financialAccountId": "", "amount": { "value": 500000, "currencyCode": "USD" }, "cadence": "LIFETIME", "resetAvailableBalance": true } } Expected Result: { "data": { "setPseudoLimit": { "__typename": "InterFinancialAccountTransfer", "toFinancialAccount": { "id": "", "ledgers": [ { "name": "ACCOUNT_HOLDER_PSEUDO_LIMIT", "creditBalance": { "value": 500000 } }, { "name": "PSEUDO_AVAILABLE_CASH", "creditBalance": { "value": 500000 } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: GeneratePaymentCardClientToken Query: mutation GeneratePaymentCardClientToken( $input: GeneratePaymentCardClientTokenInput! ) { generatePaymentCardClientToken(input: $input) { ... on ClientToken { value expirationDate } } } Variables: { "input": { "paymentCardId": "", "permissions": [ "READ_RESTRICTED_DETAILS" ] } } Expected Result: { "data": { "generatePaymentCardClientToken": { "value": "TOKEN", "expirationDate": "2022-02-07T20:04:50.633Z" } }, "extensions": { "requestId": "" } } ### GraphQL: FindPaymentCard Query: query FindPaymentCard($id: ID!) { node(id: $id) { ... on PaymentCard { bin last4 expirationDate restrictedDetails { ... on PaymentCardRestrictedDetails { cvv number } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "bin": "BIN", "last4": "LAST_4", "expirationDate": "", "restrictedDetails": { "cvv": "CVV", "number": "" } } } } --- URL: https://docs.highnote.com/docs/issuing/transactions/transaction-feed Title: Build a Transaction Feed Section: Issuing Description: Query financial account activity to build transaction feeds for your account holders. Retrieve associated ledgers and display transaction history across all cards on an account. ## Overview Financial account activity is recorded in the Highnote ledger. To build a transaction feed for your account holders, query a financial account to return its account activity and associated ledgers. Building transaction feeds against a financial account ensures financial account activity carries across all payment cards associated with the financial account. ## Prerequisites - A Highnote account - An API key or the API Explorer - A card product, financial account, and payment card - _Optional_ - Real or simulated transactions ## View financial account activity Note the following when querying for financial account activity: - **For financial accounts with no activities:** The Highnote API returns four specific ledgers, , , , . - **For financial accounts with activities:** The Highnote API only returns ledgers that have at least one activity on them. Use the following query to return financial account activity: ### GraphQL: FindFinancialAccount Query: query FindFinancialAccount( $id: ID! $firstActivities: Int $activitiesAfterCursor: String ) { node(id: $id) { __typename ... on FinancialAccount { __typename id financialAccountActivities( first: $firstActivities after: $activitiesAfterCursor ) { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename sign isComplete pendingAmount { value currencyCode } postedAmount { value currencyCode } createdAt source { ... on Node { id } ... on DebitTransaction { __typename id transactionEvents { __typename ... on Node { id } ... on AuthorizationEvent { merchantDetails { category name } } ... on IssuerPreliminaryAuthorizationEvent { merchantDetails { category name } } ... on ClearingEvent { merchantDetails { category name } } ... on BalanceInquiryEvent { merchantDetails { category name } } ... on VerificationEvent { merchantDetails { category name } } ... on AuthorizationAndClearEvent { merchantDetails { category name } } ... on ReversalEvent { merchantDetails { category name } } } } ... on CreditTransaction { __typename id transactionEvents { __typename ... on Node { id } ... on AuthorizationEvent { merchantDetails { category name } } ... on IssuerPreliminaryAuthorizationEvent { merchantDetails { category name } } ... on ClearingEvent { merchantDetails { category name } } ... on BalanceInquiryEvent { merchantDetails { category name } } ... on VerificationEvent { merchantDetails { category name } } ... on AuthorizationAndClearEvent { merchantDetails { category name } } ... on ReversalEvent { merchantDetails { category name } } } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "id": "", "financialAccountActivities": { "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "dD0yM...hYmY", "endCursor": "dD0yM...hYmY" }, "edges": [ { "cursor": "dD0yM...hYmY", "node": { "__typename": "FinancialAccountActivity", "sign": "NEGATIVE", "isComplete": true, "pendingAmount": { "value": 0, "currencyCode": "USD" }, "postedAmount": { "value": 0, "currencyCode": "USD" }, "createdAt": "2022-12-02T03:14:37.892Z", "source": { "__typename": "DebitTransaction", "id": "", "transactionEvents": [ { "__typename": "ReversalEvent", "id": "", "merchantDetails": { "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "name": "WALGREENS" } }, { "__typename": "AuthorizationEvent", "id": "", "merchantDetails": { "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "name": "WALGREENS" } } ] } } } ] } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/transactions/disputes Title: Disputes and Chargebacks Section: Issuing Description: Handle account holder disputes for fraud, authorization errors, and processing issues. Issue provisional credits, update dispute cases, and resolve chargebacks. ## Overview This guide explains the dispute and chargeback process and how to simulate it in the Test environment using the Highnote API. - A **dispute** can be submitted by an account holder when they believe they didn't receive the goods and services they paid for, or when there was unauthorized activity on their financial account. - A **chargeback** is issued if the account holder wins the dispute case and the disputed transaction is reversed. Card networks have strict rules and timelines for responding to and investigating disputes. Highnote's in-house **Disputes Team** helps subscribers with the following dispute and chargeback-related processes: - Handling dispute intakes from account holders - Managing dispute-related documentation requests and receivables for account holders - Investigating dispute claims - Filing chargebacks for disputed transactions - Providing direct support to account holders on the status of disputes and chargebacks - Issuing and settling provisional credits - Monitoring and maintaining regulatory requirements and timelines ## Provisional credits Provisional credits are issued to an account holder during a dispute case investigation. Depending on your card product type, provisional credits may or may not be required: - **Consumer card products:** Required by Regulation E - **Commercial card products:** Optional Provisional credits are issued from your product funding account to an account holder's financial account using an internal Highnote transfer. Internal transfers must be done using the Highnote API. See Transfer between Financial Accounts. ## Dispute categories Disputes fall into different categories, which must be noted when submitting a dispute case. | Dispute Case Category | Description | Example | | :-------------------- | :--------------------------------------------------------------------- | :---------------------------------------------------------------------------------- | | | Card program attempted to collect funds spent by the account holder | A clearing transaction without an authorization event | | | Account holder claims a transaction is fraudulent | An account holder’s payment card is compromised and used for fraudulent purchases | | | Account holder claims they did not receive paid-for goods and services | An account holder purchased a product from an online merchant and never received it | | | Transaction data is incorrect | A duplicate charge on an account holder’s financial account | ## Account holder submitted dispute cases In the Live environment, dispute cases may be initiated by the account holder (via a provided intake form), and the full dispute lifecycle is managed by Highnote's Disputes Team. Highnote provides you with an embedded form that you can place into your application. There may be some required parameters for you to prefill. Your implementation team will guide you through the setup process. To monitor case status and credit updates in your integration, subscribe to the related notification events. See Chargebacks and disputes in the Events Reference. ## Simulate a dispute case In the Test environment, you can create dispute cases and simulate the full lifecycle with the API. Simulating disputes and chargebacks triggers financial account activity related to provisional, dispute, or chargeback credits and the associated notification events for case creation and resolution. When creating a dispute case in the Test environment, you must include the following: - **Dispute category:** See Dispute categories. - **Dispute eligibility:** The disputed transaction must be cleared and disputed within 180 days of the clearing event. - **If multiple transactions are disputed:** A separate dispute case must be submitted for each transaction. - **If a dispute is unrelated to fraud:** The account holder should contact the merchant to resolve it before submitting it to Highnote. - **If a dispute is related to fraud:** You must close any compromised payment cards associated with the account holder's financial account. Use the following mutation to simulate the creation of a dispute case in the Test environment: ### Open a chargeback case Chargeback cases are linked to the parent dispute case and are created if a dispute qualifies for filing with the card network. If the disputed transaction is below the card product's minimum chargeback amount (set at $25 in the Test environment), a chargeback case is not initiated. Instead, a dispute credit is issued to the financial account. To simulate a chargeback, use the following mutation with and as input variables: ### Issue provisional credits For disputed transactions, provisional credits may be issued to a financial account during the investigation. In the Test environment, all consumer card products can issue these credits after a chargeback case has been created. For credit card products, disputed transactions are removed from the account's balance due, but the available credit may not be released until the dispute is resolved in the account holder's favor. If the chargeback case is won, the provisional credit remains. If lost, the provisional credit is revoked. Use the following mutation to simulate issuing a provisional credit for a dispute case: ### Issue dispute credits If the disputed amount is below the card product's minimum chargeback threshold, a dispute credit can be issued instead of a provisional credit. The minimum chargeback amount varies by card product and is listed in the feature settings. If the disputed amount qualifies for a chargeback, a dispute credit cannot be issued. In the Test environment, the disputed amount must be less than $25 to issue a dispute credit. You can optionally indicate the liability of the dispute expense: or : - If is selected, a dispute expense is recorded on the product funding account. - If is selected, it is assumed that the dispute was paid for by the network and no expense is recorded. - If no liability input is provided, liability is assumed to be on the issuer. Use the following mutation to simulate issuing a dispute credit: ### Update a dispute case Updating dispute case elements does not impact an associated chargeback case. You can update the dispute case status to trigger additional notification events such as and . Use the following mutation to simulate updating a dispute case, providing the desired status as an input variable: ### Resolve a chargeback case Resolving a chargeback case finalizes any provisional credit issued during the investigation and automatically resolves the associated dispute case. The outcome determines ledger entries and money movement. If no provisional credit was issued for a commercial card, a credit is issued to the financial account when the chargeback is resolved. Provide the following input: - : Dispute case ID. - : Amount used to finalize the provisional credit. - : Party that absorbs the dispute expense. Defaults to . - records the expense on the product funding account. - assumes the network paid for it and records no issuer expense. ## Dispute credit status Dispute credits are exposed as [](/docs/api-reference/object#PaymentCardTransactionDisputeCredit) objects on a dispute's field. Each credit carries a of type [](/docs/api-reference/enum#PaymentCardDisputeCreditStatus), which tracks whether the credit has been issued to the cardholder's financial account or reversed. A dispute credit is distinct from a _provisional credit_, which is issued during investigation and tracked separately on the dispute's field using the [](/docs/api-reference/enum#PaymentCardProvisionalCreditStatus) enum. Highnote issues a dispute credit in the following scenarios: - **Below the minimum chargeback threshold.** When the disputed amount falls below the card product's minimum chargeback threshold, no chargeback case is filed and a dispute credit is issued directly to the financial account. - **Chargeback won on a card product without provisional credits.** When a chargeback case is won on a card product that does not issue provisional credits, a dispute credit is issued as the resolution. For the full list of enum values, see [](/docs/api-reference/enum#PaymentCardDisputeCreditStatus) in the API Reference. ### Watch for status changes To respond to dispute credit activity in an integration — for example, to notify a cardholder when a credit is posted — subscribe to notification events instead of polling the status field. The following events fire when a dispute credit's status changes: | Notification Event | Fires When | | :------------------------------------------------- | :---------------------------------------------------------------- | | | A dispute credit is posted to the cardholder's financial account. | | | A previously posted dispute credit is reversed. | For the full list of dispute-related events, see Events Reference — Chargebacks and disputes. ## Find dispute cases You can find dispute cases by querying the following objects: - A financial account - The transaction event associated with the dispute case - Card product ### via financial account You can search for dispute cases and their associated transactions on a financial account using the following query: ### via transaction event You can find a related dispute case from the associated or transaction event using the following query: ### via card product You can also view a paginated list of dispute cases associated with a card product with the following query: ### GraphQL: simulateInitiateCardTransactionDispute Query: mutation simulateInitiateCardTransactionDispute( $input: SimulateInitiateCardTransactionDisputeInput! ) { simulateInitiateCardTransactionDispute(input: $input) { __typename ... on PaymentCardTransactionDispute { id status category amount { currencyCode value } fromDate throughDate } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "cardTransactionEventId": "", "category": "FRAUD", "amount": { "currencyCode": "USD", "value": "2000" } } } Expected Result: { "data": { "simulateInitiateCardTransactionDispute": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "INITIATED", "category": "FRAUD", "amount": { "currencyCode": "USD", "value": 2000 }, "fromDate": "2024-02-07T17:46:17.713Z", "throughDate": null } }, "extensions": { "requestId": "", "rateLimit": { "cost": 13, "limit": 60060, "remaining": 60046 } } } ### GraphQL: simulateInitiateCardTransactionChargeback Query: mutation simulateInitiateCardTransactionChargeback( $input: SimulateInitiateCardTransactionChargebackInput! ) { simulateInitiateCardTransactionChargeback(input: $input) { __typename ... on PaymentCardTransactionDispute { id status chargebacks { id requestedAmount { currencyCode value } receivedAmount { currencyCode value } status fromDate throughDate } fromDate throughDate } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "disputeId": "", "amount": { "currencyCode": "USD", "value": "3500" } } } Expected Result: { "data": { "simulateInitiateCardTransactionChargeback": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "IN_PROGRESS", "chargebacks": [ { "id": "", "requestedAmount": { "currencyCode": "USD", "value": 3500 }, "receivedAmount": null, "status": "SUBMITTED", "fromDate": "2023-10-18T20:10:08.544Z", "throughDate": null } ], "fromDate": "2023-10-18T20:09:53.397Z", "throughDate": null } } } ### GraphQL: simulateIssueProvisionalCreditForCardTransactionDispute Query: mutation simulateIssueProvisionalCreditForCardTransactionDispute( $input: SimulateIssueProvisionalCreditForCardTransactionDisputeInput! ) { simulateIssueProvisionalCreditForCardTransactionDispute(input: $input) { __typename ... on PaymentCardTransactionDispute { id status chargebacks { id creditStatus requestedAmount { currencyCode value } receivedAmount { currencyCode value } status fromDate throughDate } fromDate throughDate } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "", "chargebackId": "" } } Expected Result: { "data": { "simulateIssueProvisionalCreditForCardTransactionDispute": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "IN_PROGRESS", "chargebacks": [ { "id": "", "requestedAmount": { "currencyCode": "USD", "value": 3500 }, "receivedAmount": null, "status": "SUBMITTED", "creditStatus": "PROVISIONAL_CREDIT_PENDING_ISSUED", "fromDate": "2023-10-18T20:07:51.969Z", "throughDate": null } ], "fromDate": "2023-10-18T20:07:44.301Z", "throughDate": null } } } ### GraphQL: simulateIssueCreditForCardTransactionDispute Query: mutation simulateIssueCreditForCardTransactionDispute( $input: SimulateIssueCreditForCardTransactionDisputeInput! ) { simulateIssueCreditForCardTransactionDispute(input: $input) { __typename ... on PaymentCardTransactionDispute { id status category amount { currencyCode value } fromDate throughDate } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "issueCreditForCardTransactionDispute": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "IN_PROGRESS", "category": "FRAUD", "amount": { "currencyCode": "USD", "value": 2000 }, "provisionalCreditHistory": null, "disputeCreditHistory": [ { "__typename": "PaymentCardTransactionDisputeCredit", "creditStatus": "CREDIT_ISSUED", "requestedAmount": { "currencyCode": "USD", "value": 2000 }, "receivedAmount": { "currencyCode": "USD", "value": 2000 }, "creditIssueFromDate": "2024-07-25T20:38:20.064Z" } ], "liablity": "ISSUER_LIABLE", "fromDate": "2024-07-25T20:38:20.064Z", "throughDate": null } }, "extensions": { "requestId": "a1937cc0-905d-980f-a12f-be240f68dfb5", "rateLimit": { "cost": 11, "limit": 60060, "remaining": 60047 } } } ### GraphQL: simulateUpdateCardTransactionDispute Query: mutation simulateUpdateCardTransactionDispute( $input: SimulateUpdateCardTransactionDisputeInput! ) { simulateUpdateCardTransactionDispute(input: $input) { __typename ... on PaymentCardTransactionDispute { id status category amount { currencyCode value } fromDate throughDate } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "status": "CANCELLED" } } Expected Result: { "data": { "simulateUpdateCardTransactionDispute": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "CANCELLED", "category": "FRAUD", "amount": { "currencyCode": "USD", "value": 3500 }, "fromDate": "2023-10-18T19:09:42.589Z", "throughDate": null } } } ### GraphQL: simulateFinalizeProvisionalCreditForCardTransactionDispute Query: mutation simulateFinalizeProvisionalCreditForCardTransactionDispute( $input: SimulateFinalizeProvisionalCreditForCardTransactionDisputeInput! ) { simulateFinalizeProvisionalCreditForCardTransactionDispute(input: $input) { __typename ... on PaymentCardTransactionDispute { id status disputeCreditHistory { creditStatus creditAmount { currencyCode value } createdAt updatedAt } provisionalCreditHistory { creditStatus creditAmount { currencyCode value } createdAt updatedAt } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "id": "", "liability": "ISSUER_LIABLE", "amount": { "value": 3500, "currencyCode": "USD" } } } Expected Result: { "data": { "simulateFinalizeProvisionalCreditForCardTransactionDispute": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "WON", "disputeCreditHistory": [ { "creditStatus": "ISSUED", "creditAmount": { "currencyCode": "USD", "value": 3500 }, "createdAt": "2026-05-27T19:10:13.120Z", "updatedAt": "2026-05-27T19:10:13.120Z" } ], "provisionalCreditHistory": [ { "creditStatus": "FINALIZED", "creditAmount": { "currencyCode": "USD", "value": 3500 }, "createdAt": "2026-05-27T19:09:42.589Z", "updatedAt": "2026-05-27T19:10:13.120Z" } ] } } } ### GraphQL: getDisputeForFinancialAccount Query: query getDisputeForFinancialAccount($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { id paymentCardTransactionDisputes { ... on PaymentCardTransactionDisputeConnection { edges { node { id amount { value currencyCode } category status chargebacks { id requestedAmount { value } receivedAmount { value } creditStatus status } fromDate throughDate } } } } } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "cardTransactionDisputesForFinancialAccount": { "__typename": "PaymentCardTransactionDisputeConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "start-cursor", "endCursor": "end-cursor" }, "edges": [ { "cursor": "some-cursor", "node": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "INITIATED", "category": "FRAUD", "amount": { "currencyCode": "USD", "value": 100 }, "chargebacks": [], "fromDate": "2023-03-17T22:39:18.060Z", "throughDate": "2023-03-17T22:39:18.060Z" } } ] } } } ### GraphQL: getClearingDispute Query: query getClearingDispute($id: ID!) { node(id: $id) { __typename ... on TransactionEvent { id transaction { __typename } createdAt ... on ClearingEvent { disputes { __typename id ... on PaymentCardTransactionDispute { amount { value currencyCode } category status chargebacks { id requestedAmount { value } receivedAmount { value } creditStatus status } fromDate throughDate } } } } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "node": { "__typename": "ClearingEvent", "id": "", "transaction": { "__typename": "DebitTransaction" }, "approvedAmount": { "value": 1500 }, "createdAt": "2023-05-18T20:47:46.787Z", "disputes": [ { "id": "", "amount": { "value": 1500, "currencyCode": "USD" }, "category": "FRAUD", "status": "WON", "chargebacks": [ { "id": "", "requestedAmount": { "value": 1500 }, "receivedAmount": { "value": 1500 }, "creditStatus": "CREDIT_WON", "status": "WON" } ], "fromDate": "2023-05-18T20:42:29.939Z", "throughDate": null } ] } }, "extensions": { "requestId": "" } } ### GraphQL: getProduct Query: query getProduct($id: ID!) { node(id: $id) { ... on CardProduct { __typename id name paymentCardTransactionDisputes { __typename ... on PaymentCardTransactionDisputeConnection { __typename pageInfo { hasNextPage hasPreviousPage } edges { node { __typename id ... on PaymentCardTransactionDispute { status category amount { value currencyCode } } } } } } features { __typename enabled ... on DisputeChargebackCardProductFeature { __typename chargebackMinimumThreshold { __typename value currencyCode } chargebackProvisionalCreditEnabled disputeMaximumDaySinceTransaction } } } } } Variables: { "input": { "id": "" } } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "name": "A Consumer Prepaid", "paymentCardTransactionDisputes": { "__typename": "PaymentCardTransactionDisputeConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "node": { "__typename": "PaymentCardTransactionDispute", "id": "", "status": "RESOLVED", "category": "FRAUD", "amount": { "value": 1500, "currencyCode": "USD" } } } ] }, "features": [ { "__typename": "DisputeChargebackCardProductFeature", "enabled": true, "chargebackMinimumThreshold": { "__typename": "Amount", "value": 2500, "currencyCode": "USD" }, "chargebackProvisionalCreditEnabled": true, "disputeMaximumDaySinceTransaction": 180 }, { "__typename": "AuthorizedUserCardProductFeature", "enabled": false } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 25, "limit": 100, "remaining": 75 } } } --- URL: https://docs.highnote.com/docs/issuing/transactions/fees Title: Fees Section: Issuing Description: View and manage fees for your card products. Query fee schedules, monitor fee activity on financial accounts, search collected fees, and waive fees. Simulate fee schedules in the Test environment. ## Overview The Highnote platform supports the ability to charge fees for your card product. Fees can serve as an additional revenue stream for your card program. This guide provides an overview of fee schedules, fee activity types, and steps for viewing and managing fees for your card product. The Highnote team and partner bank must review and approve any fees you wish to charge, as well as your Cardholder Agreements and Disclosures. Once your fees are approved, Highnote configures the fees for your card product and creates a fee schedule. ## Fee schedules and activities Fee schedules represent all the fees for your card product and are configured by the Highnote team. - Individual fees within a fee schedule are referred to as _fee activity types_. - Fee activity types are triggered by a _fee charge activity_. When a transaction or event matches a fee charge activity, a fee schedule is activated and a fee is applied to the account holder's financial account. For an overview of fee activity types and charge activities, see the Fee schedules support guide. For physical card fee trigger conditions specifically, see Physical card fees below. ## Simulate create fee schedule Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. The Highnote team will configure and activate fee schedules in your Live environment, but you can simulate creating fee Schedules in your Test environment using the following query: Once a fee schedule is created and activated, there is no mutation to edit, delete, or deactivate it, in either the Test or Live environment. Calling again for the same card product does not replace or supersede the existing schedule. Both schedules remain active, and this causes a fee-evaluation error on the next fee-triggering event for that card product. If you need to change a fee schedule's configuration, contact your Highnote representative. ## International and foreign exchange fees You can include two fee activity types for international transactions in a simulated fee schedule: - : Charged when a clearing transaction event is processed with a merchant located outside the U.S. - : Charged when a clearing transaction event is processed with a merchant located outside the U.S. _and_ currency exchange is required. The foreign exchange fee applies only to international transactions that also require currency exchange. When both fees are configured in a schedule, a transaction that requires currency exchange is charged **both** fees. When currency exchange is required, the exchange rate is set by the card network (Visa or Mastercard), not Highnote. The rate is reflected in the cardholder billing amount on the clearing transaction event. The following example creates a schedule with both fees, each configured as a percentage in basis points—an international transaction fee of 200 basis points (2%) and a foreign exchange fee of 300 basis points (3%). ## Physical card fees Two fee activity types apply to physical card orders: and . Their trigger conditions are independent, and both fees can apply to the same order. **** is charged when a physical card is reissued with a new PAN. A same-PAN card renewal does not trigger this fee. Shipping method, and whether the order was placed individually or as part of a group card order, do not affect this fee. **** is charged when a physical card order ships via an expedited shipping method _and_ is placed as an individual order rather than part of a group card order. This applies to first-time card orders as well as reissues—reissue status does not affect this fee. , charged to the account holder's financial account, never applies to cards ordered as part of a group card order, even when an expedited shipping method is used. Expedited-processing costs billed to you under your Master Services Agreement are a separate program cost and may still apply for group orders—see Print Physical Cards. If a card order is a reissue, ships via an expedited method, and is placed individually, both fees are charged together. The following values, and only these, count as expedited: , , , , , , , , , —the values speed up card processing, and the rest are next-day-or-faster shipping couriers. Notably, (1-2 business days) does not qualify despite its name. UPS availability depends on your card vendor; contact Highnote support if you don't see it as a shipping option. ## View fee schedule In addition to displaying fees, you must display the appropriate Cardholder Agreements and Disclosures for your account holders. Once a fee schedule is configured for your card product, you can query the configuration to display on your website or application for your account holders. Each fee schedule has an active date and a status to determine if the schedule is active. The following query can be used to view a fee schedule: ## Test your fee schedule In the Test environment, you cannot simulate fees for ATM withdrawals, ATM balance inquiries, international transactions, and monthly fees. Once the Highnote team configures fees, you can test the configuration to ensure the fees are assigned properly to your users. Testing your fee schedule consists of the following: - View fees on financial account activity - View fee collection activity - Query for fee balances - Search for collected fees ### View financial account activity Fees associated with transaction events are stored as financial account activities. Note the following when querying for financial account activities: - **For financial accounts with no activities:** The Highnote API returns four specific ledgers: , , , and . - **For financial accounts with activities:** The Highnote API only returns ledgers that have at least one activity on them. Use the following query to view financial account activity. Fees are listed in the results payload: ### Query card product income balance Fees are collected from an account holder's financial account immediately and transferred to an Income Account for each card product. You view the balance of fees collected for your card product by querying the ledgers associated with your card product income account. Use the following query to query the balance on an income account: ### Search for collected fees You can query for a group of fees collected, and filter by account holder financial accounts. Use the following query to search for fees collected on a card product: ## Waive fees When you waive a fee, the entire fee amount from the original fee transfer event is reversed. The following mutation creates a ReversedFeeTransfer event that starts in a state, and can either or successfully. ### GraphQL: simulateCreateAndActivateFeeSchedule Query: mutation simulateCreateAndActivateFeeSchedule( $input: SimulateCreateAndActivateFeeScheduleInput! ) { simulateCreateAndActivateFeeSchedule(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on FeeSchedule { __typename id feeScheduleAssociatedTo { __typename ... on CardProduct { id } } feeConfigurations { id feeActivityType feeChargeRules { id name order value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } conditions { __typename ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } maximumAmount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleCountCondition { id description condition { __typename ... on CountFeeCondition { value { __typename ... on CountFeeConditionValue { count } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } } createdAt updatedAt } createdAt updatedAt } activationDate status createdAt updatedAt } } } Variables: { "input": { "cardProductId": "", "feeConfigurations": [ { "feeActivityType": "ATM_BALANCE_INQUIRY_OUT_OF_NETWORK_FEE", "feeAmount": { "feeAmount": { "value": 100, "currencyCode": "USD" } } }, { "feeActivityType": "ATM_DECLINE_FEE", "feeAmount": { "feeAmount": { "value": 100, "currencyCode": "USD" } } }, { "feeActivityType": "MONTHLY_ACCOUNT_ANNIVERSARY_FEE", "feeAmount": { "feeAmount": { "value": 500, "currencyCode": "USD" } } }, { "feeActivityType": "PHYSICAL_CARD_REISSUE_FEE", "feeAmount": { "feeAmount": { "value": 500, "currencyCode": "USD" } } }, { "feeActivityType": "VIRTUAL_CARD_REISSUE_FEE", "feeAmount": { "feeAmount": { "value": 500, "currencyCode": "USD" } } } ] } } Expected Result: { "data": { "simulateCreateAndActivateFeeSchedule": { "__typename": "FeeSchedule", "id": "", "feeScheduleAssociatedTo": { "__typename": "CardProduct", "id": "" }, "feeConfigurations": [ { "id": "", "feeActivityType": "ATM_BALANCE_INQUIRY_OUT_OF_NETWORK_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_TRANSACTION_ATM_BALANCE_INQUIRY_OUT_OF_NETWORK_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 100, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "ID", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:32:27.473Z", "updatedAt": "2023-04-26T20:32:27.479Z" } ], "createdAt": "2023-04-26T20:32:27.569Z", "updatedAt": "2023-04-26T20:32:27.570Z" } ], "createdAt": "2023-04-26T20:32:27.344Z", "updatedAt": "2023-04-26T20:32:27.366Z" }, { "id": "ID", "feeActivityType": "MONTHLY_ACCOUNT_ANNIVERSARY_FEE", "feeChargeRules": [ { "id": "ID", "name": "Priority_10_ACCOUNT_SERVICING_ACCOUNT_SERVICING_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 500, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "ID", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:32:27.822Z", "updatedAt": "2023-04-26T20:32:27.822Z" } ], "createdAt": "2023-04-26T20:32:27.824Z", "updatedAt": "2023-04-26T20:32:27.824Z" } ], "createdAt": "2023-04-26T20:32:27.818Z", "updatedAt": "2023-04-26T20:32:27.819Z" }, { "id": "ID", "feeActivityType": "ATM_DECLINE_FEE", "feeChargeRules": [ { "id": "ID", "name": "Priority_10_TRANSACTION_ATM_DECLINE_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 100, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "ID", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:32:27.700Z", "updatedAt": "2023-04-26T20:32:27.700Z" } ], "createdAt": "2023-04-26T20:32:27.702Z", "updatedAt": "2023-04-26T20:32:27.702Z" } ], "createdAt": "2023-04-26T20:32:27.697Z", "updatedAt": "2023-04-26T20:32:27.697Z" }, { "id": "ID", "feeActivityType": "PHYSICAL_CARD_REISSUE_FEE", "feeChargeRules": [ { "id": "ID", "name": "Priority_10_FULFILLMENT_PHYSICAL_CARD_REISSUE_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 500, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "ID", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:32:27.995Z", "updatedAt": "2023-04-26T20:32:27.996Z" } ], "createdAt": "2023-04-26T20:32:27.997Z", "updatedAt": "2023-04-26T20:32:27.997Z" } ], "createdAt": "2023-04-26T20:32:27.992Z", "updatedAt": "2023-04-26T20:32:27.993Z" }, { "id": "ID", "feeActivityType": "VIRTUAL_CARD_REISSUE_FEE", "feeChargeRules": [ { "id": "ID", "name": "Priority_10_ISSUANCE_VIRTUAL_CARD_REISSUE_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 500, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "ID", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:32:28.118Z", "updatedAt": "2023-04-26T20:32:28.118Z" } ], "createdAt": "2023-04-26T20:32:28.119Z", "updatedAt": "2023-04-26T20:32:28.119Z" } ], "createdAt": "2023-04-26T20:32:28.116Z", "updatedAt": "2023-04-26T20:32:28.116Z" } ], "activationDate": "2023-04-26T20:32:23.690Z", "status": "ACTIVE", "createdAt": "2023-04-26T20:32:25.071Z", "updatedAt": "2023-04-26T20:32:28.429Z" } }, "extensions": { "requestId": "" } } ### GraphQL: simulateCreateAndActivateFeeSchedule - Foreign Exchange Query: mutation simulateCreateAndActivateFeeSchedule( $input: SimulateCreateAndActivateFeeScheduleInput! ) { simulateCreateAndActivateFeeSchedule(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on FeeSchedule { __typename id feeScheduleAssociatedTo { __typename ... on CardProduct { id } } feeConfigurations { id feeActivityType feeChargeRules { id name order value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } conditions { __typename ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } maximumAmount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleCountCondition { id description condition { __typename ... on CountFeeCondition { value { __typename ... on CountFeeConditionValue { count } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } } createdAt updatedAt } createdAt updatedAt } activationDate status createdAt updatedAt } } } Variables: { "input": { "cardProductId": "", "feeConfigurations": [ { "feeActivityType": "INTERNATIONAL_TRANSACTION_FEE", "feeAmount": { "feeBasisPoints": 200 } }, { "feeActivityType": "FOREIGN_EXCHANGE_FEE", "feeAmount": { "feeBasisPoints": 300 } } ] } } Expected Result: { "data": { "simulateCreateAndActivateFeeSchedule": { "__typename": "FeeSchedule", "id": "", "feeScheduleAssociatedTo": { "__typename": "CardProduct", "id": "" }, "feeConfigurations": [ { "id": "", "feeActivityType": "INTERNATIONAL_TRANSACTION_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_TRANSACTION_INTERNATIONAL_TRANSACTION_FEE", "order": 10, "value": { "__typename": "VariableFeeChargeValue", "basisPoints": 200 }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:32:27.473Z", "updatedAt": "2023-04-26T20:32:27.479Z" } ], "createdAt": "2023-04-26T20:32:27.569Z", "updatedAt": "2023-04-26T20:32:27.570Z" } ], "createdAt": "2023-04-26T20:32:27.344Z", "updatedAt": "2023-04-26T20:32:27.366Z" }, { "id": "", "feeActivityType": "FOREIGN_EXCHANGE_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_TRANSACTION_FOREIGN_EXCHANGE_FEE", "order": 10, "value": { "__typename": "VariableFeeChargeValue", "basisPoints": 300 }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:32:27.473Z", "updatedAt": "2023-04-26T20:32:27.479Z" } ], "createdAt": "2023-04-26T20:32:27.569Z", "updatedAt": "2023-04-26T20:32:27.570Z" } ], "createdAt": "2023-04-26T20:32:27.344Z", "updatedAt": "2023-04-26T20:32:27.366Z" } ], "activationDate": "2023-04-26T20:32:23.690Z", "status": "ACTIVE", "createdAt": "2023-04-26T20:32:25.071Z", "updatedAt": "2023-04-26T20:32:28.429Z" } }, "extensions": { "requestId": "" } } ### GraphQL: FindFeeSchedule Query: query FindFeeSchedule($id: ID!) { node(id: $id) { ... on FeeSchedule { __typename id feeScheduleAssociatedTo { __typename ... on CardProduct { id } } feeConfigurations { id feeActivityType feeChargeRules { id name order value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } conditions { __typename ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } maximumAmount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleCountCondition { id description condition { __typename ... on CountFeeCondition { value { __typename ... on CountFeeConditionValue { count } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } } createdAt updatedAt } createdAt updatedAt } activationDate status createdAt updatedAt } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FeeSchedule", "id": "", "feeScheduleAssociatedTo": { "__typename": "CardProduct", "id": "" }, "feeConfigurations": [ { "id": "", "feeActivityType": "VIRTUAL_CARD_REISSUE_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_ISSUANCE_VIRTUAL_CARD_REISSUE_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 500, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:42:10.839Z", "updatedAt": "2023-04-26T20:42:10.839Z" } ], "createdAt": "2023-04-26T20:42:10.840Z", "updatedAt": "2023-04-26T20:42:10.840Z" } ], "createdAt": "2023-04-26T20:42:10.837Z", "updatedAt": "2023-04-26T20:42:10.838Z" }, { "id": "", "feeActivityType": "ATM_BALANCE_INQUIRY_OUT_OF_NETWORK_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_TRANSACTION_ATM_BALANCE_INQUIRY_OUT_OF_NETWORK_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 100, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:42:10.311Z", "updatedAt": "2023-04-26T20:42:10.318Z" } ], "createdAt": "2023-04-26T20:42:10.393Z", "updatedAt": "2023-04-26T20:42:10.394Z" } ], "createdAt": "2023-04-26T20:42:10.203Z", "updatedAt": "2023-04-26T20:42:10.217Z" }, { "id": "", "feeActivityType": "ATM_DECLINE_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_TRANSACTION_ATM_DECLINE_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 100, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:42:10.571Z", "updatedAt": "2023-04-26T20:42:10.571Z" } ], "createdAt": "2023-04-26T20:42:10.573Z", "updatedAt": "2023-04-26T20:42:10.573Z" } ], "createdAt": "2023-04-26T20:42:10.567Z", "updatedAt": "2023-04-26T20:42:10.567Z" }, { "id": "", "feeActivityType": "MONTHLY_ACCOUNT_ANNIVERSARY_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_ACCOUNT_SERVICING_ACCOUNT_SERVICING_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 500, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:42:10.732Z", "updatedAt": "2023-04-26T20:42:10.732Z" } ], "createdAt": "2023-04-26T20:42:10.733Z", "updatedAt": "2023-04-26T20:42:10.733Z" } ], "createdAt": "2023-04-26T20:42:10.729Z", "updatedAt": "2023-04-26T20:42:10.730Z" }, { "id": "", "feeActivityType": "PHYSICAL_CARD_REISSUE_FEE", "feeChargeRules": [ { "id": "", "name": "Priority_10_FULFILLMENT_PHYSICAL_CARD_REISSUE_FEE", "order": 10, "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 500, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1 }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-04-26T20:42:10.785Z", "updatedAt": "2023-04-26T20:42:10.786Z" } ], "createdAt": "2023-04-26T20:42:10.787Z", "updatedAt": "2023-04-26T20:42:10.788Z" } ], "createdAt": "2023-04-26T20:42:10.783Z", "updatedAt": "2023-04-26T20:42:10.783Z" } ], "activationDate": "2023-04-26T20:42:06.036Z", "status": "ACTIVE", "createdAt": "2023-04-26T20:42:07.508Z", "updatedAt": "2023-04-26T20:42:11.081Z" } }, "extensions": { "requestId": "" } } ### GraphQL: FindFinancialAccount Query: query FindFinancialAccount($id: ID!) { node(id: $id) { __typename ... on FinancialAccount { id feeTransferEvents(first: 10) { __typename pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id feeTransfer { __typename ... on ChargedFeeTransfer { originatingAccount { id } receivingAccount { id } cardProduct { id } feeActivityType feeAmount { value currencyCode } transferedFeeAmount { value currencyCode } transferDate status { ... on NonFailureFeeTransferStatus { status } ... on FailureFeeTransferStatus { status reasonDetails { type reason } } } feeChargeRule { __typename id name value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } ... on VariableFeeChargeValue { basisPoints } } conditions { __typename ... on FeeChargeRuleAmountCondition { id description condition { __typename ... on AmountFeeCondition { value { __typename ... on AmountFeeConditionValue { amount { value currencyCode } maximumAmount { value currencyCode } } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } ... on FeeChargeRuleCountCondition { id description condition { __typename ... on CountFeeCondition { value { __typename ... on CountFeeConditionValue { count maximumCount } } operator } } aggregatedAt aggregationDuration createdAt updatedAt } } createdAt updatedAt } feeChargeActvity { __typename ... on PhysicalPaymentCardOrder { id } ... on PaymentCard { id } ... on FinancialAccount { id } ... on SecureDepositACHTransfer { id } ... on SecureCardBalanceRepaymentACHTransfer { id } ... on IntegratorInitiatedFundsWithdrawalACHTransfer { id } ... on IntegratorInitiatedFundsDepositACHTransfer { id } ... on AuthorizationAndClearEvent { id } ... on ClearingEvent { id } ... on BalanceInquiryEvent { id } } } ... on ReversedFeeTransfer { originatingAccount { id } receivingAccount { id } transferedFeeAmount { value currencyCode } transferDate status { ... on NonFailureFeeTransferStatus { status } ... on FailureFeeTransferStatus { status reasonDetails { type reason } } } sourceFeeTransferEvent { id } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "FinancialAccount", "id": "", "feeTransferEvents": { "__typename": "FeeTransferEventConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "", "endCursor": "" }, "edges": [ { "cursor": "", "node": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer", "originatingAccount": { "id": "" }, "receivingAccount": { "id": "" }, "cardProduct": { "id": "" }, "feeActivityType": "ATM_DECLINE_FEE", "feeAmount": { "value": 20, "currencyCode": "USD" }, "transferedFeeAmount": { "value": 20, "currencyCode": "USD" }, "transferDate": "2023-05-03T01:52:56.563Z", "status": { "status": "COMPLETE" }, "feeChargeRule": { "__typename": "FeeChargeRule", "id": "", "name": "ATM Decline Fee", "value": { "__typename": "VariableFeeChargeValue", "basisPoints": 100 }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1, "maximumCount": null }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-05-03T01:33:29.831Z", "updatedAt": "2023-05-03T01:33:29.831Z" } ], "createdAt": "2023-05-03T01:33:29.832Z", "updatedAt": "2023-05-03T01:33:29.832Z" }, "feeChargeActvity": { "__typename": "AuthorizationAndClearEvent", "id": "" } } } }, { "cursor": "", "node": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer", "originatingAccount": { "id": "" }, "receivingAccount": { "id": "" }, "cardProduct": { "id": "" }, "feeActivityType": "ATM_DECLINE_FEE", "feeAmount": { "value": 50, "currencyCode": "USD" }, "transferedFeeAmount": { "value": 50, "currencyCode": "USD" }, "transferDate": "2023-05-03T01:53:01.046Z", "status": { "status": "COMPLETE" }, "feeChargeRule": { "__typename": "FeeChargeRule", "id": "", "name": "ATM Decline Fee", "value": { "__typename": "VariableFeeChargeValue", "basisPoints": 100 }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1, "maximumCount": null }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-05-03T01:33:29.831Z", "updatedAt": "2023-05-03T01:33:29.831Z" } ], "createdAt": "2023-05-03T01:33:29.832Z", "updatedAt": "2023-05-03T01:33:29.832Z" }, "feeChargeActvity": { "__typename": "AuthorizationAndClearEvent", "id": "" } } } }, { "cursor": "", "node": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer", "originatingAccount": { "id": "" }, "receivingAccount": { "id": "" }, "cardProduct": { "id": "" }, "feeActivityType": "EXPEDITED_PHYSICAL_CARD_FEE", "feeAmount": { "value": 2000, "currencyCode": "USD" }, "transferedFeeAmount": { "value": 2000, "currencyCode": "USD" }, "transferDate": "2023-05-03T01:51:56.598Z", "status": { "status": "COMPLETE" }, "feeChargeRule": { "__typename": "FeeChargeRule", "id": "", "name": "Expedited Physical Card Fee", "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 2000, "currencyCode": "USD" } }, "conditions": [ { "__typename": "FeeChargeRuleCountCondition", "id": "", "description": "COUNT GREATER THAN OR EQUAL TO 1 CONDITION SET", "condition": { "__typename": "CountFeeCondition", "value": { "__typename": "CountFeeConditionValue", "count": 1, "maximumCount": null }, "operator": "GREATER_THAN_OR_EQUAL" }, "aggregatedAt": "ACCOUNT", "aggregationDuration": "LIFETIME", "createdAt": "2023-05-03T01:33:29.943Z", "updatedAt": "2023-05-03T01:33:29.943Z" } ], "createdAt": "2023-05-03T01:33:29.944Z", "updatedAt": "2023-05-03T01:33:29.944Z" }, "feeChargeActvity": { "__typename": "PhysicalPaymentCardOrder", "id": "" } } } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: GetCardProductWithLedgers Query: query GetCardProductWithLedgers( $cardProductId: ID! $firstLedgerEntries: Int $ledgerEntriesAfterCursor: String $filterBy: AccountHolderFinancialAccountsFilterInput ) { node(id: $cardProductId) { ... on CardProduct { __typename id name accounts(first: 20, filterBy: $filterBy) { pageInfo { endCursor hasNextPage startCursor hasPreviousPage __typename } edges { cursor node { createdAt id name updatedAt features { __typename enabled createdAt updatedAt } ledgers { id normalBalance asOf name creditBalance { value currencyCode __typename } debitBalance { value currencyCode __typename } ledgerEntries( first: $firstLedgerEntries after: $ledgerEntriesAfterCursor ) { __typename pageInfo { hasNextPage hasPreviousPage startCursor endCursor __typename } edges { __typename cursor node { id __typename } } } __typename } __typename } __typename } __typename } } __typename } } Variables: { "cardProductId": "", "filterBy": { "features": { "equals": "INCOME_ACCOUNT" } } } Expected Result: { "data": { "node": { "__typename": "CardProduct", "id": "", "name": "Consumer Prepaid", "accounts": { "pageInfo": { "endCursor": "", "hasNextPage": false, "startCursor": "", "hasPreviousPage": false, "__typename": "PageInfo" }, "edges": [ { "cursor": "", "node": { "createdAt": "2023-02-02T22:12:32.850Z", "id": "", "name": "Consumer Prepaid - Income", "updatedAt": "2023-02-02T22:12:32.850Z", "features": [ { "__typename": "IncomeAccountFinancialAccountFeature", "enabled": true, "createdAt": "2023-02-02T22:12:32.850Z", "updatedAt": "2023-02-02T22:12:32.850Z" } ], "ledgers": [ { "id": "", "normalBalance": "CREDIT", "asOf": "2023-05-03T01:53:04.775Z", "name": "AVAILABLE_CASH", "creditBalance": { "value": 4070, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": { "__typename": "LedgerEntryConnection", "pageInfo": { "hasNextPage": true, "hasPreviousPage": false, "startCursor": "", "endCursor": "", "__typename": "PageInfo" }, "edges": [ { "__typename": "LedgerEntryEdge", "cursor": "", "node": { "id": "", "__typename": "CreditLedgerEntry" } } ] }, "__typename": "Ledger" }, { "id": "", "normalBalance": "DEBIT", "asOf": "2023-05-03T01:53:04.775Z", "name": "CASH", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 4070, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": { "__typename": "LedgerEntryConnection", "pageInfo": { "hasNextPage": true, "hasPreviousPage": false, "startCursor": "", "endCursor": "", "__typename": "PageInfo" }, "edges": [ { "__typename": "LedgerEntryEdge", "cursor": "", "node": { "id": "", "__typename": "DebitLedgerEntry" } } ] }, "__typename": "Ledger" }, { "id": "", "normalBalance": "CREDIT", "asOf": "2023-05-03T02:23:37.174Z", "name": "DEPOSIT_HOLD", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": null, "__typename": "Ledger" }, { "id": "", "normalBalance": "CREDIT", "asOf": "2023-05-03T02:23:37.174Z", "name": "REFUND_HOLD", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": null, "__typename": "Ledger" }, { "id": "", "normalBalance": "CREDIT", "asOf": "2023-05-03T02:23:37.174Z", "name": "FUND_IN_HOLD", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": null, "__typename": "Ledger" }, { "id": "", "normalBalance": "CREDIT", "asOf": "2023-05-03T02:23:37.174Z", "name": "DEPOSIT_AUTHORIZATION", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": null, "__typename": "Ledger" }, { "id": "", "normalBalance": "CREDIT", "asOf": "2023-05-03T02:23:37.174Z", "name": "REFUND_AUTHORIZATION", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": null, "__typename": "Ledger" }, { "id": "", "normalBalance": "CREDIT", "asOf": "2023-05-03T02:23:37.174Z", "name": "FEE_AUTHORIZATION", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": null, "__typename": "Ledger" }, { "id": "ac_og222c975277c978475098739055c6fb772b_a004", "normalBalance": "CREDIT", "asOf": "2023-05-03T02:23:37.174Z", "name": "AUTHORIZATION", "creditBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "debitBalance": { "value": 0, "currencyCode": "USD", "__typename": "Amount" }, "ledgerEntries": null, "__typename": "Ledger" } ], "__typename": "FinancialAccount" }, "__typename": "FinancialAccountEdge" } ], "__typename": "FinancialAccountConnection" } } }, "extensions": { "requestId": "" } } ### GraphQL: ListFeeTransferEvents Query: query ListFeeTransferEvents( $first: Int $after: String $filterBy: FeeTransferEventFilterInput ) { feeTransferEvents(first: $first, after: $after, filterBy: $filterBy) { pageInfo { startCursor endCursor hasNextPage hasPreviousPage } edges { cursor node { ...feeTransferEvent } } } } fragment feeTransferEvent on FeeTransferEvent { __typename id feeTransfer { __typename ... on ChargedFeeTransfer { originatingAccount { id accountStatus feeTransferEvents { pageInfo { hasNextPage } edges { cursor node { id feeTransfer { __typename } } } } } receivingAccount { id accountStatus } cardProduct { id name } feeActivityType feeAmount { value currencyCode } transferedFeeAmount { value currencyCode } transferDate status { __typename ... on NonFailureFeeTransferStatus { status } } feeChargeRule { id name value { __typename ... on FixedFeeChargeValue { amount { value currencyCode } } } } feeChargeActvity { __typename ... on PhysicalPaymentCardOrder { id } ... on PaymentCard { id } ... on FinancialAccount { id } ... on SecureDepositACHTransfer { id } ... on SecureCardBalanceRepaymentACHTransfer { id } ... on IntegratorInitiatedFundsWithdrawalACHTransfer { id } ... on IntegratorInitiatedFundsDepositACHTransfer { id } ... on AuthorizationAndClearEvent { id transaction { __typename ... on CreditTransaction { id } ... on DebitTransaction { id } } } ... on ClearingEvent { id transaction { __typename ... on CreditTransaction { id } ... on DebitTransaction { id } } } ... on BalanceInquiryEvent { id transaction { __typename ... on CreditTransaction { id } ... on DebitTransaction { id } } } } } ... on ReversedFeeTransfer { originatingAccount { id } receivingAccount { id } transferedFeeAmount { value currencyCode } transferDate sourceFeeTransferEvent { __typename id ... on FeeTransferEvent { id feeTransfer { __typename ... on ChargedFeeTransfer { originatingAccount { id } feeAmount { value currencyCode } } } } } } } } Variables: { "first": 20, "filterBy": { "cardProductId": { "equals": "" }, "createDate": { "between": { "start": "2023-05-01T00:00:00.000Z", "end": "2023-05-31T23:59:59.999Z" } } } } Expected Result: { "data": { "feeTransferEvents": { "pageInfo": { "startCursor": "", "endCursor": "", "hasNextPage": false, "hasPreviousPage": false }, "edges": [ { "cursor": "", "node": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer", "originatingAccount": { "id": "", "accountStatus": "ACTIVE", "feeTransferEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } }, { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } }, { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } } ] } }, "receivingAccount": { "id": "", "accountStatus": "ACTIVE" }, "cardProduct": { "id": "", "name": "Consumer Prepaid" }, "feeActivityType": "ATM_DECLINE_FEE", "feeAmount": { "value": 20, "currencyCode": "USD" }, "transferedFeeAmount": { "value": 20, "currencyCode": "USD" }, "transferDate": "2023-05-03T01:52:56.563Z", "status": { "__typename": "NonFailureFeeTransferStatus", "status": "COMPLETE" }, "feeChargeRule": { "id": "", "name": "ATM Decline Fee", "value": { "__typename": "VariableFeeChargeValue" } }, "feeChargeActvity": { "__typename": "AuthorizationAndClearEvent", "id": "", "transaction": { "__typename": "DebitTransaction", "id": "" } } } } }, { "cursor": "", "node": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer", "originatingAccount": { "id": "", "accountStatus": "ACTIVE", "feeTransferEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } }, { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } }, { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } } ] } }, "receivingAccount": { "id": "", "accountStatus": "ACTIVE" }, "cardProduct": { "id": "", "name": "Consumer Prepaid" }, "feeActivityType": "ATM_DECLINE_FEE", "feeAmount": { "value": 50, "currencyCode": "USD" }, "transferedFeeAmount": { "value": 50, "currencyCode": "USD" }, "transferDate": "2023-05-03T01:53:01.046Z", "status": { "__typename": "NonFailureFeeTransferStatus", "status": "COMPLETE" }, "feeChargeRule": { "id": "", "name": "ATM Transaction Fee", "value": { "__typename": "VariableFeeChargeValue" } }, "feeChargeActvity": { "__typename": "AuthorizationAndClearEvent", "id": "", "transaction": { "__typename": "DebitTransaction", "id": "" } } } } }, { "cursor": "", "node": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer", "originatingAccount": { "id": "", "accountStatus": "ACTIVE", "feeTransferEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } }, { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } }, { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } } ] } }, "receivingAccount": { "id": "", "accountStatus": "ACTIVE" }, "cardProduct": { "id": "", "name": "Consumer Prepaid" }, "feeActivityType": "EXPEDITED_PHYSICAL_CARD_FEE", "feeAmount": { "value": 2000, "currencyCode": "USD" }, "transferedFeeAmount": { "value": 2000, "currencyCode": "USD" }, "transferDate": "2023-05-03T01:51:56.598Z", "status": { "__typename": "NonFailureFeeTransferStatus", "status": "COMPLETE" }, "feeChargeRule": { "id": "", "name": "Expedited Physical Card Fee", "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 2000, "currencyCode": "USD" } } }, "feeChargeActvity": { "__typename": "PhysicalPaymentCardOrder", "id": "" } } } }, { "cursor": "", "node": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer", "originatingAccount": { "id": "", "accountStatus": "ACTIVE", "feeTransferEvents": { "pageInfo": { "hasNextPage": false }, "edges": [ { "cursor": "", "node": { "id": "", "feeTransfer": { "__typename": "ChargedFeeTransfer" } } } ] } }, "receivingAccount": { "id": "", "accountStatus": "ACTIVE" }, "cardProduct": { "id": "", "name": "Consumer Prepaid" }, "feeActivityType": "EXPEDITED_PHYSICAL_CARD_FEE", "feeAmount": { "value": 2000, "currencyCode": "USD" }, "transferedFeeAmount": { "value": 2000, "currencyCode": "USD" }, "transferDate": "2023-05-03T01:50:26.690Z", "status": { "__typename": "NonFailureFeeTransferStatus", "status": "COMPLETE" }, "feeChargeRule": { "id": "", "name": "Expedited Physical Card Fee", "value": { "__typename": "FixedFeeChargeValue", "amount": { "value": 2000, "currencyCode": "USD" } } }, "feeChargeActvity": { "__typename": "PhysicalPaymentCardOrder", "id": "" } } } } ] } }, "extensions": { "requestId": "" } } ### GraphQL: waiveFeeTransfer Query: mutation waiveFeeTransfer($input: WaiveFeeTransferInput!) { waiveFeeTransfer(input: $input) { __typename ... on FeeTransferEvent { __typename id feeTransfer { ... on ReversedFeeTransfer { originatingAccount { id } receivingAccount { id } feeTransferAmount { value currencyCode } transferDate status { __typename ... on NonFailureFeeTransferStatus { status } } sourceFeeTransferEvent { id } } } } ... on UserError { errors { code } } } } Variables: { "input": { "feeTransferEventId": "", "idempotencyKey": "key123232322", "memo": "first test" } } Expected Result: { "data": { "waiveFeeTransfer": { "__typename": "FeeTransferEvent", "id": "", "feeTransfer": { "__typename": "ReversedFeeTransfer", "originatingAccount": { "id": "" }, "receivingAccount": { "id": "" }, "transferedFeeAmount": { "value": 500, "currencyCode": "USD" }, "transferDate": "2025-05-05T20:31:08.213Z", "status": { "status": "COMPLETE" }, "memo": "first test", "sourceFeeTransferEvent": { "id": "" } } } }, "extensions": { "requestId": "0412e3d7-0461-98a3-861c-0897fc84180f", "rateLimit": { "cost": 13 } } } --- URL: https://docs.highnote.com/docs/issuing/transactions/sim-fleet-transactions Title: Simulate Fleet Transactions Section: Issuing Description: Simulate Visa and Mastercard fleet authorizations, clearing events, and Level 2 and Level 3 enhanced data in the Test environment. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. Fleet transactions include enhanced data that may arrive at different points in the transaction lifecycle. You can use the Highnote API to simulate fleet transactions in the Test environment. Simulating fleet transactions helps test the following use cases and card product settings: - Different merchants - Different merchant category codes (MCCs) - Enhanced data - Authorization advice - Spend rules and velocity controls - Collaborative authorization flow This guide provides steps for simulating fleet transactions using the Highnote API. ## Prerequisites - Review Transaction Lifecycle guide - A Highnote account - An API key or the API Explorer - A fleet card product, financial account, and payment card ## Merchant category codes Fleet cards can be restricted to specific purchase types using MCC-based authorization controls. For an overview of MCC-based spend controls, see Configure Spend Rules. Purchase types are defined as follows for Visa and Mastercard: | Card network | Purchase type | Description | | :----------- | :-------------------- | :--------------------------------------------------- | | Visa | Open, No restrictions | Allows all fuel, maintenance, and non-fuel purchases | | | Fleet | Allows fuel and maintenance purchases only | | | Fuel only | Only allows fuel purchases | | Mastercard | Open, No restrictions | Allows all fuel, maintenance, and non-fuel purchases | | | Fuel only | Allows only fuel purchases | All fleet cards _must_ accept fleet/fuel MCCs. It is _optional_ to configure your authorization controls to accept maintenance MCCs. The following tables provide an overview of fleet/fuel and maintenance MCCs for reference: ### Fleet/Fuel MCCs | CODE | DESCRIPTION | | :--- | :--------------------------------------------------------------------------- | | 4468 | Marinas, Marine service/supplies | | 5499 | Miscellaneous food stores; Convenience stores, markets, and specialty stores | | 5541 | Service stations (with or without ancillary services) | | 5542 | Fuel dispenser, automated | | 5983 | Fuel dealers – Coal, fuel oil, liquefied petroleum, wood | ### Maintenance MCCs | CODE | DESCRIPTION | | :--- | :------------------------------------------------------------------------- | | 5013 | Motor vehicle supplies and new parts | | 5511 | Automobile and truck dealers – Sales, service, repairs, parts, and leasing | | 5531 | Auto stores, home supply stores | | 5532 | Automotive tire stores | | 5533 | Automotive parts, accessories stores | | 5599 | Miscellaneous automotive, aircraft, and farm equipment dealers | | 7531 | Automotive body repair shops | | 7534 | Tire retreading and repair shops | | 7535 | Automotive paint shops | | 7538 | Automotive service shops (non-dealer) | | 7542 | Car washes | | 7549 | Towing services | | 7692 | Welding | | 7699 | Miscellaneous repair shops and related services | ## Fleet data levels Fleet transactions follow the standard authorization and clearing data flow and include enhanced data specific to the fleet vertical. Both Visa and Mastercard define multiple levels of fleet data, but each network delivers the data differently. ### When fleet data arrives The following table shows when fleet data is delivered for each network: | Network | Data | When it arrives | | :--------- | :-------------------- | :------------------------------------------------------------------ | | Both | Level 1 (standard) | Authorization and clearing | | Visa | Level 2 (enhanced) | Authorization, authorization advice, or clearing (acquirer decides) | | Visa | Level 3 (line items) | 24–48 hours after the transaction | | Mastercard | Level 2 + 3 (bundled) | End of business day (ET), in a single event | You can set up a Notification Event to alert you when enhanced data has been added to a transaction. For airline, lodging, car rental, rail, and travel agency enhanced data, see Simulate Travel Transactions. ### Level 1 data Level 1 data contains standard payment network transaction data provided by merchants. This data includes: - Merchant details - Point of Service details - Billing zip code - Total purchase amount - Purchase date Level 1 data is the same for all transaction types and merchants. No enhanced data is captured or provided at this level. ### Visa fleet data Visa delivers Level 2 and Level 3 data separately, at different points in the transaction lifecycle. #### Level 2 data Level 2 data contains enhanced data captured at the point of sale. Acquirers can send Level 2 data with both authorization and clearing messages. Highnote includes fleet data in the field on the [](/docs/api-reference/object#AuthorizationEvent) and [](/docs/api-reference/object#ReversalEvent) in addition to the [](/docs/api-reference/object#ClearingEvent). An event may include either or both of the following fleet data types: - [](/docs/api-reference/object#VisaFleetAuthorizationData) — prompt responses, fleet identifiers, odometer readings, and purchase type captured at authorization or authorization advice time - [](/docs/api-reference/object#VisaFleetL2TransactionData) — fuel line items, tax data, and purchase totals Visa sends Level 2 fuel line items on only one event in the transaction lifecycle—either the authorization, the reversal, or the clearing, depending on when the acquirer provides the data. Your integration should check for Level 2 data on the , , and to ensure you capture it regardless of when it arrives. Refer to the API Reference for more information on Visa Level 2 Purchase Data Fields. #### Level 3 data Level 3 data is typically sent 24 to 48 hours after the transaction and contains specific data related to non-fuel products and services. Merchants are not required to report enhanced data for fuel-only transactions. Level 3 data follows an invoice structure with invoice summary information and invoice line item detail information. Refer to the API Reference for more information on Visa Level 3 Enhanced Data Fields. ### Mastercard fleet data Mastercard delivers Level 2 and Level 3 data together in a single event—either an or a —at the end of the business day (ET). Highnote surfaces this data in the field on the event. The payload includes fuel and non-fuel line items, tax data, and fleet identifiers. Refer to the API Reference for more information on Mastercard Enhanced Data Fields. ## Simulate an authorization In the Test environment, authorizations are approved or declined based on your card product logic and authorization controls. Highnote offers two types of authorization controls for fleet payment cards: - Controls baked into the EMV chip in the physical card - Controls enforced through Spend Rules and Velocity Controls EMV chip controls have a product restriction code encoded into the EMV chip to allow fuel purchases and other approved products. The product restriction code may also prevent purchasing non-fleet items, such as food, at fuel stops. ### via Visa {#sim-auth-via-visa} Use the following query to simulate a fleet authorization with Visa: ### via Mastercard {#sim-auth-via-mc} Use the following query to simulate a fleet authorization with Mastercard: ## Simulate authorization advice For purchases at Automated Fuel Dispensers (AFDs), the full transaction amount may not be known at authorization. Instead, a $1 or estimated amount is sent for authorization at the time of purchase, and authorization advice is sent to confirm the total amount at a later time. Simulating authorization advice is _optional_. Visa supports a real-time clearing program, which does not require authorization advice. We recommend skipping simulating authorization advice in the following scenarios: - Simulating a real-time clearing event - Simulating an in-store pre-pay transaction - Simulating a transaction where the merchant incorrectly did not send authorization advice ### via Visa {#sim-auth-advice-via-visa} Use the following mutation to simulate authorization advice with Visa: ### via Mastercard {#sim-auth-advice-via-mc} Use the following query to simulate authorization advice with Mastercard: ## Simulate clearing Use the following mutations to simulate fleet clearing events. ### via Visa {#sim-clearing-via-visa} Visa sends Level 1 and Level 2 data together in clearing events. If the acquirer already provided Level 2 data at authorization time, the clearing event may contain only Level 1 data. Use the following mutation to simulate clearing with Visa: ### via Mastercard {#sim-clearing-via-mc} Mastercard only sends Level 1 data in clearing events. Use the following query to simulate a clearing with Mastercard: ## Simulate Level 3 enhanced data Use the following mutations to simulate Level 3 enhanced data events. ### via Visa {#sim-l3-via-visa} Visa Level 3 data is typically sent between 24 to 48 hours after the transaction takes place. Merchants are not required to report enhanced data for fuel-only transactions. Use the following mutation to simulate Visa fleet enhanced data: ### via Mastercard {#sim-l3-via-mc} Mastercard defines enhanced data as Level 2 and Level 3 data. Mastercard Level 2 and Level 3 data is sent at the end of the business day (ET). Use the following mutation to simulate Mastercard fleet enhanced data: ## Automate your integration To automate your integration, subscribe to the following notification events: - Payment card authorization - Payment authorization and clear - Payment card cleared - Payment card verification - Payment card transaction enhanced data The details provided in the payloads from these events can be used for the following use cases: - Automate your application or website's transaction processing workflows - Create account holder notifications and alerts ### GraphQL: SimulateVisaFleetAuthorization Query: mutation SimulateVisaFleetAuthorization( $input: SimulateVisaFleetAuthorizationInput! ) { simulateVisaFleetAuthorization(input: $input) { __typename ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode requestedAmount { value currencyCode } cvvResponseCode merchantDetails { countryCodeAlpha3 category name description merchantId categoryCode address { postalCode region locality countryCodeAlpha3 } } pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent terminalSupportsPartialApproval isRecurring } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } transactionProcessingType currentFinancialAccountAvailableToSpendAmount { currencyCode value } currentFinancialAccountMaximumBalanceAmount { currencyCode value } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "amount": { "value": 100, "currencyCode": "USD" }, "cardId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false } } } Expected Result: { "data": { "simulateVisaFleetAuthorization": { "__typename": "AuthorizationEvent", "id": "", "transaction": { "id": "" }, "responseCode": "APPROVED_FOR_PARTIAL_AMOUNT", "networkResponseCode": "00", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "123456" }, "transactionProcessingType": "GOODS_AND_SERVICES", "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 500 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 30000 }, "requestedAmount": { "value": 100, "currencyCode": "USD" }, "cvvResponseCode": "MATCH" } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateMastercardFleetAuthorization Query: mutation SimulateMastercardFleetAuthorization( $input: SimulateMastercardFleetAuthorizationInput! ) { simulateMastercardFleetAuthorization(input: $input) { __typename ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode createdAt requestedAmount { value currencyCode } approvedAmount { value currencyCode } cvvResponseCode merchantDetails { address { countryCodeAlpha3 locality postalCode region } category categoryCode countryCodeAlpha3 name merchantId description } currentFinancialAccountMaximumBalanceAmount { value currencyCode } currentFinancialAccountAvailableToSpendAmount { value currencyCode } transactionProcessingType pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent isRecurring terminalSupportsPartialApproval } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "amount": { "value": 100, "currencyCode": "USD" }, "cardId": "", "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "countryCodeAlpha3": "USA", "name": "My Awesome Fuel", "merchantId": "merchantId", "category": "AUTOMATED_FUEL_DISPENSERS", "description": "The awesomest awesome fuel dispensers of all time super deluxe" }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true } } } Expected Result: { "data": { "simulateMastercardFleetAuthorization": { "__typename": "AuthorizationEvent", "id": "", "transaction": { "id": "" }, "responseCode": "APPROVED_FOR_PARTIAL_AMOUNT", "requestedAmount": { "value": 100, "currencyCode": "USD" }, "approvedAmount": { "value": 50000, "currencyCode": "USD" }, "cvvResponseCode": "MATCH", "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "category": "AUTOMATED_FUEL_DISPENSERS", "countryCodeAlpha3": "USA", "name": "My Awesome Fuel", "merchantId": "merchantId", "description": "The awesomest awesome fuel dispensers of all time super deluxe" }, "currentFinancialAccountMaximumBalanceAmount": { "value": 500000, "currencyCode": "USD" }, "currentFinancialAccountAvailableToSpendAmount": { "value": 420000, "currencyCode": "USD" }, "transactionProcessingType": "GOODS_AND_SERVICES", "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true }, "additionalNetworkData": null } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60040 } } } ### GraphQL: SimulateVisaFleetAuthorizationAdvice Query: mutation SimulateVisaFleetAuthorizationAdvice( $input: SimulateVisaFleetAuthorizationAdviceInput! ) { simulateVisaFleetAuthorizationAdvice(input: $input) { __typename ... on ReversalEvent { id responseCode originalAmount { value currencyCode } approvedAmount { value currencyCode } transaction { ... on Node { id } } } ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode approvedAmount { value currencyCode } requestedAmount { value currencyCode } avsResponseCode postalCodeResponseCode cvvResponseCode merchantDetails { countryCodeAlpha3 category name description merchantId categoryCode address { postalCode region locality countryCodeAlpha3 } } pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent terminalSupportsPartialApproval isRecurring } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } transactionProcessingType currentFinancialAccountAvailableToSpendAmount { currencyCode value } currentFinancialAccountMaximumBalanceAmount { currencyCode value } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false } } } Expected Result: { "data": { "simulateVisaFleetAuthorizationAdvice": { "__typename": "ReversalEvent", "id": "", "responseCode": "APPROVED", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "123456" }, "transactionProcessingType": "PAYMENT_DEBIT", "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 500 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 30000 }, "originalAmount": { "value": 50000, "currencyCode": "USD" }, "approvedAmount": { "value": 1000, "currencyCode": "USD" }, "transaction": { "id": "" } } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateMastercardFleetAuthorizationAdvice Query: mutation SimulateMastercardFleetAuthorizationAdvice( $input: SimulateMastercardFleetAuthorizationAdviceInput! ) { simulateMastercardFleetAuthorizationAdvice(input: $input) { __typename ... on ReversalEvent { id responseCode createdAt approvedAmount { value currencyCode } transaction { ... on Node { id } } paymentCard { id } merchantDetails { address { countryCodeAlpha3 locality postalCode region } category countryCodeAlpha3 name merchantId description } currentFinancialAccountMaximumBalanceAmount { value currencyCode } currentFinancialAccountAvailableToSpendAmount { value currencyCode } transactionProcessingType pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent isRecurring terminalSupportsPartialApproval } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } partial issuerExpiredAuthorization } ... on AuthorizationEvent { id transaction { ... on Node { id } } responseCode createdAt approvedAmount { value currencyCode } merchantDetails { address { countryCodeAlpha3 locality postalCode region } category countryCodeAlpha3 name merchantId description } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "amount": { "value": 10000, "currencyCode": "USD" }, "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "category": "AUTOMATED_FUEL_DISPENSERS", "countryCodeAlpha3": "USA", "name": "My Awesome Fuel", "merchantId": "Merchant Id", "description": "The awesomest awesome fuel dispensers" }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true } } } Expected Result: { "data": { "simulateMastercardFleetAuthorizationAdvice": { "__typename": "ReversalEvent", "id": "", "responseCode": "APPROVED", "approvedAmount": { "value": 40000, "currencyCode": "USD" }, "transaction": { "id": "" }, "paymentCard": null, "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "category": "AUTOMATED_FUEL_DISPENSERS", "countryCodeAlpha3": "USA", "name": "My Awesome Fuel", "merchantId": "Merchant Id", "description": "The awesomest awesome fuel dispensers" }, "currentFinancialAccountMaximumBalanceAmount": { "value": 500000, "currencyCode": "USD" }, "currentFinancialAccountAvailableToSpendAmount": { "value": 490000, "currencyCode": "USD" }, "transactionProcessingType": "GOODS_AND_SERVICES", "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true }, "additionalNetworkData": null, "partial": true, "issuerExpiredAuthorization": false } }, "extensions": { "requestId": "", "rateLimit": { "cost": 19 } } } ### GraphQL: SimulateVisaFleetClearing Query: mutation SimulateVisaFleetClearing($input: SimulateVisaFleetClearingInput!) { simulateVisaFleetClearing(input: $input) { __typename ... on ClearingEvent { id responseCode approvedAmount { value currencyCode } requestedAmount { value currencyCode } originalAmount { value currencyCode } merchantDetails { countryCodeAlpha3 category name description merchantId categoryCode address { postalCode region locality countryCodeAlpha3 } } pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent terminalSupportsPartialApproval isRecurring } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } transactionProcessingType currentFinancialAccountAvailableToSpendAmount { currencyCode value } currentFinancialAccountMaximumBalanceAmount { currencyCode value } additionalTransactionData { ... on VisaFleetL2TransactionData { id visaFuelPurchaseType visaFuelServiceType visaFuelType visaFuelQuantity visaFuelUnitOfMeasure visaFuelUnitCost visaFuelNetAmount visaFuelGrossAmount visaNonFuelNetAmount visaNonFuelGrossAmount visaTaxRate visaExpandedFuelType visaAdditionalDataIndicator visaFleetIdentifier visaOdometerReading visaPurchaseIdentifierFormat visaPurchaseIdentifier visaFleetEmployeeNumber visaFleetTrailerNumber visaFleetCustomPrompt1 visaFleetCustomPrompt2 visaNonFuelProductCodes } } transaction { ... on Node { id } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "visaFleetL2TransactionData": { "visaFuelPurchaseType": "FUEL_PURCHASE", "visaFuelServiceType": "SELF_SERVICE", "visaFuelType": "UNKNOWN", "visaFuelQuantity": 1000, "visaFuelUnitOfMeasure": "GALLON", "visaFuelUnitCost": 2000, "visaFuelNetAmount": 3000, "visaFuelGrossAmount": 4000, "visaNonFuelNetAmount": 5000, "visaNonFuelGrossAmount": 6000, "visaTaxRate": 7000, "visaExpandedFuelType": "PREMIUM_SUPER", "visaAdditionalDataIndicator": false, "visaFleetIdentifier": "visaFleetIdentifier", "visaOdometerReading": 1234567, "visaPurchaseIdentifierFormat": "ORDER", "visaPurchaseIdentifier": "visaPurchaseIdentifier", "visaFleetEmployeeNumber": "visaFleetEmployeeNDmber", "visaFleetTrailerNumber": "visaFleetTrailerNumber", "visaFleetCustomPrompt1": "visaFleetCustomPrompt1", "visaFleetCustomPrompt2": "visaFleetCustomPrompt2", "visaNonFuelProductCodes": [ "OIL_CHANGE", "WASHER_FLUID", "BRAKE_FLUID", "BATTERIES" ] } } } Expected Result: { "data": { "simulateVisaFleetClearing": { "__typename": "ClearingEvent", "id": "", "responseCode": "APPROVED", "approvedAmount": { "value": 1000, "currencyCode": "USD" }, "requestedAmount": { "value": 1000, "currencyCode": "USD" }, "originalAmount": { "value": 1000, "currencyCode": "USD" }, "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "123456" }, "transactionProcessingType": "PAYMENT_DEBIT", "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 500 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 30000 }, "additionalTransactionData": [ { "id": "", "visaFuelPurchaseType": "FUEL_PURCHASE", "visaFuelServiceType": "SELF_SERVICE", "visaFuelType": "UNKNOWN", "visaFuelQuantity": 1000, "visaFuelUnitOfMeasure": "GALLON", "visaFuelUnitCost": 2000, "visaFuelNetAmount": 3000, "visaFuelGrossAmount": 4000, "visaNonFuelNetAmount": 5000, "visaNonFuelGrossAmount": 6000, "visaTaxRate": 7000, "visaExpandedFuelType": "PREMIUM_SUPER", "visaAdditionalDataIndicator": false, "visaFleetIdentifier": "visaFleetIdentifier", "visaOdometerReading": 1234567, "visaPurchaseIDFormat": "ORDER", "visaPurchaseIdentifier": "visaPurchaseIdentifier", "visaFleetEmployeeNumber": "visaFleetEmployeeNDmber", "visaFleetTrailerNumber": "visaFleetTrailerNumber", "visaFleetCustomPrompt1": "visaFleetCustomPrompt1", "visaFleetCustomPrompt2": "visaFleetCustomPrompt2", "visaNonFuelProductCodes": [ "OIL_CHANGE", "WASHER_FLUID", "BRAKE_FLUID", "BATTERIES" ] } ], "transaction": { "id": "" } } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateMastercardFleetClearing Query: mutation SimulateMastercardFleetClearing( $input: SimulateMastercardFleetClearingInput! ) { simulateMastercardFleetClearing(input: $input) { __typename ... on ClearingEvent { id transaction { ... on Node { id } } responseCode createdAt approvedAmount { value currencyCode } merchantDetails { address { countryCodeAlpha3 locality postalCode region } category countryCodeAlpha3 name merchantId description } currentFinancialAccountMaximumBalanceAmount { value currencyCode } currentFinancialAccountAvailableToSpendAmount { value currencyCode } transactionProcessingType pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent isRecurring terminalSupportsPartialApproval } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } partial } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "amount": { "value": 10000, "currencyCode": "USD" }, "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "category": "AUTOMATED_FUEL_DISPENSERS", "countryCodeAlpha3": "USA", "name": "My Awesome Fuel", "merchantId": "Merchant Id", "description": "The awesomest awesome fuel dispensers" }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true } } } Expected Result: { "data": { "simulateMastercardFleetClearing": { "__typename": "ClearingEvent", "id": "", "transaction": { "id": "" }, "responseCode": "APPROVED", "createdAt": "2023-10-10T19:53:20.024Z", "approvedAmount": { "value": 10000, "currencyCode": "USD" }, "merchantDetails": { "address": { "countryCodeAlpha3": "USA", "locality": "San Francisco", "postalCode": "94105", "region": "CA" }, "category": "AUTOMATED_FUEL_DISPENSERS", "countryCodeAlpha3": "USA", "name": "My Awesome Fuel", "merchantId": "Merchant Id", "description": "The awesomest awesome fuel dispensers" }, "currentFinancialAccountMaximumBalanceAmount": { "value": 500000, "currencyCode": "USD" }, "currentFinancialAccountAvailableToSpendAmount": { "value": 460000, "currencyCode": "USD" }, "transactionProcessingType": "GOODS_AND_SERVICES", "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_ENTRY_CAPABILITY", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": true }, "additionalNetworkData": null, "partial": true } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60039 } } } ### GraphQL: SimulateVisaFleetL3EnhancedData Query: mutation SimulateVisaFleetL3EnhancedData( $input: SimulateVisaFleetL3EnhancedDataInput! ) { simulateVisaFleetL3EnhancedData(input: $input) { __typename ... on EnhancedDataEvent { id transaction { ... on Node { id } } responseCode additionalTransactionData { ... on VisaFleetL3EnhancedData { id discount { amount { value currencyCode } signage treatment } duty { amount { value currencyCode } signage } shipping { amount { value currencyCode } signage taxAmount { value currencyCode } taxAmountSignage taxRate } tax { treatment } invoice { referenceNumber authorizationCode destinationPostalCode destinationCountryCode orderDate shipFromPostalCode lineItems { commodityCode descriptor productCode quantity unitOfMeasure unitCost { value currencyCode } discountPerItem { value currencyCode } lineItemDetailIndicator lineItemDiscountTreatment taxAmount { value currencyCode } taxRate lineItemTotal { value currencyCode } } } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "discount": { "amount": { "value": 100, "currencyCode": "USD" }, "amountSignage": "CREDIT", "treatment": "POST_DISCOUNT" }, "duty": { "amount": { "value": 200, "currencyCode": "USD" }, "amountSignage": "DEBIT" }, "invoice": { "authorizationCode": "authorizationCode", "destinationCountryCode": "USA", "destinationPostalCode": "12345", "orderDate": "2023-01-01", "referenceNumber": "invoiceReferenceNumber", "shipFromPostalCode": "98765", "lineItems": [ { "commodityCode": "BATTERIES", "descriptor": "itemDescriptor", "detailIndicator": "NORMAL", "discountPerItem": { "value": 100, "currencyCode": "USD" }, "discountTreatment": "POST_DISCOUNT", "productCode": "productCode", "quantity": 20000, "taxAmount": { "value": 200, "currencyCode": "USD" }, "taxRate": 1234, "total": { "value": 600, "currencyCode": "USD" }, "unitCost": { "value": 300, "currencyCode": "USD" }, "unitOfMeasure": "unitOfMeasure" } ] }, "shipping": { "amount": { "value": 300, "currencyCode": "USD" }, "amountSignage": "DEBIT", "taxAmount": { "value": 400, "currencyCode": "USD" }, "taxAmountSignage": "CREDIT", "taxRate": 2345 }, "tax": { "treatment": "GLL" } } } Expected Result: { "data": { "simulateVisaFleetL3EnhancedData": { "__typename": "EnhancedDataEvent", "id": "", "transaction": { "id": "" }, "responseCode": "APPROVED", "additionalTransactionData": [ { "id": "", "discount": { "amount": { "value": 100, "currencyCode": "USD" }, "signage": "CREDIT", "treatment": "POST_DISCOUNT" }, "duty": { "amount": { "value": 200, "currencyCode": "USD" }, "signage": "DEBIT" }, "shipping": { "amount": { "value": 300, "currencyCode": "USD" }, "signage": "DEBIT", "taxAmount": { "value": 400, "currencyCode": "USD" }, "taxAmountSignage": "CREDIT", "taxRate": 2345 }, "tax": { "treatment": "GLL" }, "invoice": { "referenceNumber": "invoiceReferenceNumber", "authorizationCode": "authorizationCode", "destinationPostalCode": "12345", "destinationCountryCode": "USA", "orderDate": "2023-01-01", "shipFromPostalCode": "98765", "lineItems": [ { "commodityCode": "BATTERIES", "descriptor": "itemDescriptor", "productCode": "productCode", "quantity": 20000, "unitOfMeasure": "unitOfMeasure", "unitCost": { "value": 300, "currencyCode": "USD" }, "discountPerItem": { "value": 100, "currencyCode": "USD" }, "lineItemDetailIndicator": "NORMAL", "lineItemDiscountTreatment": "POST_DISCOUNT", "taxAmount": { "value": 200, "currencyCode": "USD" }, "taxRate": 1234, "lineItemTotal": { "value": 600, "currencyCode": "USD" } } ] } } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateMastercardFleetEnhancedData Query: mutation SimulateMastercardFleetEnhancedData( $input: SimulateMastercardFleetEnhancedDataInput! ) { simulateMastercardFleetEnhancedData(input: $input) { __typename ... on EnhancedDataEvent { id transaction { ... on Node { id } } responseCode createdAt additionalTransactionData { ... on MastercardFleetEnhancedData { __typename id fuelBrand purchaseTime fuelServiceType fuelType fuelUnitPrice { value currencyCode } fuelUnitOfMeasure fuelQuantity fuelSaleAmount { value currencyCode } odometerReading vehicleNumber driverIdentification productType fuelDiscountAmount { value currencyCode } taxAmount1 { value currencyCode } taxAmount2 { value currencyCode } lineItems { productCode description unitOfMeasure unitPrice { value currencyCode } itemAmount { value currencyCode } creditOrDebit } } } responseCode } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "fuelBrand": "SINCLAIR", "purchaseTime": "1234", "fuelServiceType": "FULL_SERVICE", "fuelType": "PREMIUM", "fuelUnitPrice": { "value": 100, "currencyCode": "USD" }, "fuelUnitOfMeasure": "GALLONS", "fuelQuantity": 12.345, "fuelSaleAmount": { "value": 200, "currencyCode": "USD" }, "odometerReading": "123456", "vehicleNumber": "vehicleNumber", "driverIdentification": "driverIdentification", "productType": "PROMPT_FOR_DRIVER_NUMBER_AND_ODOMETER", "fuelDiscountAmount": { "value": 300, "currencyCode": "USD" }, "taxAmount1": { "value": 400, "currencyCode": "USD" }, "taxAmount2": { "value": 500, "currencyCode": "USD" }, "fuelLocationDetails": { "openTwentyFourHours": true, "eighteenWheelerAccess": true, "dieselSites": true, "interstateAccess": true, "convenienceStore": true, "restaurant": true, "hotel": true, "showers": true, "repairBays": true, "vehicleWash": true, "aviationLocation": true, "marinaLocation": true, "alternativeFuel": true, "payAtPump": true }, "lineItems": [ { "productCode": "BATTERIES", "description": "Really good batteries", "unitOfMeasure": "EACH", "unitPrice": { "value": 600, "currencyCode": "USD" }, "itemAmount": { "value": 700, "currencyCode": "USD" }, "creditOrDebit": "CREDIT" } ] } } Expected Result: { "data": { "simulateMastercardFleetEnhancedData": { "__typename": "EnhancedDataEvent", "id": "", "transaction": { "id": "" }, "additionalTransactionData": [ { "__typename": "MastercardFleetEnhancedData", "id": "", "fuelBrand": "SINCLAIR", "purchaseTime": "1234", "fuelServiceType": "FULL_SERVICE", "fuelType": "PREMIUM", "fuelUnitPrice": { "value": 100, "currencyCode": "USD" }, "fuelUnitOfMeasure": "GALLONS", "fuelQuantity": 12.345, "fuelSaleAmount": { "value": 200, "currencyCode": "USD" }, "odometerReading": "123456", "vehicleNumber": "vehicleNumber", "driverIdentification": "driverIdentification", "productType": "PROMPT_FOR_DRIVER_NUMBER_AND_ODOMETER", "fuelDiscountAmount": { "value": 300, "currencyCode": "USD" }, "taxAmount1": { "value": 400, "currencyCode": "USD" }, "taxAmount2": { "value": 500, "currencyCode": "USD" }, "lineItems": [ { "productCode": "BATTERIES", "description": "Really good batteries", "unitOfMeasure": "EACH", "unitPrice": { "value": 600, "currencyCode": "USD" }, "itemAmount": { "value": 700, "currencyCode": "USD" }, "creditOrDebit": "CREDIT" } ] } ], "responseCode": "APPROVED" } }, "extensions": { "requestId": "", "rateLimit": { "cost": 20, "limit": 60060, "remaining": 60036 } } } --- URL: https://docs.highnote.com/docs/issuing/transactions/sim-transactions Title: Simulate Transactions Section: Issuing Description: Simulate authorizations, clearing, reversals, refunds, and adjustments in the Test environment. Includes 3D Secure verification for Visa and Mastercard. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. You can use the Highnote API to simulate transactions in the Test environment. Simulating transactions helps test the following use cases and card product settings: - Transactions at different merchant types - Different transaction amounts - International transactions - Spend rules and velocity controls - Collaborative authorization flow This guide provides steps for simulating transactions using the Highnote API. For steps on simulating transactions in the dashboard, see Simulate authorizations. ## Prerequisites This guide can be used for any card product, except fleet card products. To simulate transactions for fleet card products, see Simulate Fleet Transactions. - A Highnote account - An API Key or the API Explorer - A card product, financial account, and payment card ## Simulate an authorization Simulated authorizations use the same logic as real authorizations from card networks such as Mastercard and Visa. In the Test environment, authorizations are approved or declined based on your card product logic and authorization controls. Use the following mutation to simulate an authorization in your Test environment: ## Simulate a 3DS verification You can simulate a 3-D Secure (3DS) verification preceding an authorization by including the object in the input. The object contains network-specific sub-objects for Visa and Mastercard, each with three fields relevant to 3DS. The 3DS field values are echoed on the authorization response. To simulate a failed 3DS verification, set the first field to the failed value — the authorization will be declined with . ### Visa To simulate a passed 3DS verification for a Visa card, include the following in your input: ```json title="Visa — Passed 3DS verification" "additionalNetworkData": { "visa": { "cavvResultCode": "PASSED", "motoAndElectronicCommerceIndicator": "SECURE_ELECTRONIC_COMMERCE_TRANSACTION", "threeDSecureIndicator": "FRICTIONLESS" } } ``` To simulate a failed 3DS verification, set to : ```json title="Visa — Failed 3DS verification" "additionalNetworkData": { "visa": { "cavvResultCode": "FAILED", "motoAndElectronicCommerceIndicator": "SECURE_ELECTRONIC_COMMERCE_TRANSACTION", "threeDSecureIndicator": "FRICTIONLESS" } } ``` ### Mastercard To simulate a passed 3DS verification for a Mastercard card, include the following in your input: ```json title="Mastercard — Passed 3DS verification" "additionalNetworkData": { "mastercard": { "aavResultCode": "AAV_PASSED_VALIDATION", "threeDSecureCardholderAuthentication": "CARDHOLDER_CERTIFICATE_NOT_USED", "ucafCollectionIndicator": "UCAF_DATA_SUPPORTED" } } ``` To simulate a failed 3DS verification, set to : ```json title="Mastercard — Failed 3DS verification" "additionalNetworkData": { "mastercard": { "aavResultCode": "AAV_FAILED_VALIDATION", "threeDSecureCardholderAuthentication": "CARDHOLDER_CERTIFICATE_NOT_USED", "ucafCollectionIndicator": "UCAF_DATA_SUPPORTED" } } ``` ### 3DS verification flow The following diagram shows the 3DS verification and authorization flow, including both frictionless and step-up challenge paths. The Access Control Server (ACS) performs the 3DS authentication on behalf of the issuer using Risk-Based Authentication (RBA) to determine whether to approve frictionlessly or require a one-time password (OTP) challenge. ## Simulate a clearing event Once a transaction clears, funds are transferred to the merchant from the account holder's financial account. Clearing occurs in one of the following ways: - With an authorization, immediately after - In batches after authorizations are approved Use the following mutation to simulate clearing. For partial clearings, set the input variable to an amount less than the original transaction, for example: ```json "amount": { "currencyCode": "USD", "value": "100" } ``` ## Simulate an authorization and clear Some transactions send authorization and clearing events in a single message. Use the following mutation to simulate an authorization and clearing event: ## Simulate a reversal An authorization can be reversed if it has not cleared. Reversing an authorization releases funds from "pending" status and returns the funds to the account holder. Specifically: - You can do a full or partial reversal. - You _cannot_ reverse after a partial clearing, nor clear after a partial reversal. Use the following mutation to simulate a reversal. Full reversals are the default. For partial reversals, set the input variable to an amount less than the original authorization, for example: ```json "amount": { "currencyCode": "USD", "value": "100" } ``` ## Simulate a refund You cannot simulate refunds linked to a previous transaction. Simulating a refund results in a new transaction with its own and . Refunds can be simulated for cleared transactions. When simulating a refund, you can refund the total or partial amount of the original transaction. When you use the mutation, you will receive a in response. Use the following mutation to simulate a refund: ## Simulate an adjustment event You can simulate Adjustment events from the payment networks using the mutation. ## Automate your integration To automate your integration, subscribe to the following notification events: - Payment card authorization - Payment authorization and clear - Payment card cleared The details provided in the payloads from these events can be used for the following use cases: - Automate your application or website's transaction processing workflows - Create account holder notifications and alerts ### GraphQL: SimulateAuthorization Query: mutation SimulateAuthorization($input: SimulateAuthorizationInput!) { simulateAuthorization(input: $input) { ... on AuthorizationEvent { id responseCode postalCodeResponseCode cvvResponseCode merchantDetails { countryCodeAlpha3 category name description merchantId categoryCode address { postalCode region locality countryCodeAlpha3 } } pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent terminalSupportsPartialApproval isRecurring } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } transactionProcessingType transaction { ... on Node { id } } currentFinancialAccountAvailableToSpendAmount { currencyCode value } currentFinancialAccountMaximumBalanceAmount { currencyCode value } } } } Variables: { "input": { "amount": { "value": 1000, "currencyCode": "USD" }, "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT", "cardId": "" } } Expected Result: { "data": { "simulateAuthorization": { "id": "", "responseCode": "APPROVED", "postalCodeResponseCode": "NOT_PROVIDED", "cvvResponseCode": "MATCH", "networkResponseCode": "00", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "123456" }, "transactionProcessingType": "PAYMENT_DEBIT", "transaction": { "id": "" }, "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 500 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 30000 } } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateClearing Query: mutation SimulateClearing($input: SimulateClearingInput!) { simulateClearing(input: $input) { ... on ClearingEvent { id responseCode merchantDetails { countryCodeAlpha3 category name description merchantId categoryCode address { postalCode region locality countryCodeAlpha3 } } pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent terminalSupportsPartialApproval isRecurring } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } transactionProcessingType transaction { ... on Node { id } } currentFinancialAccountAvailableToSpendAmount { currencyCode value } currentFinancialAccountMaximumBalanceAmount { currencyCode value } } } } Variables: { "input": { "transactionId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT" } } Expected Result: { "data": { "simulateClearing": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "123456" }, "transactionProcessingType": "PAYMENT_DEBIT", "transaction": { "id": "" }, "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 500 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 30000 } } } } ### GraphQL: SimulateSingleStepAuthAndClear Query: mutation SimulateSingleStepAuthAndClear( $input: SimulateSingleStepAuthAndClearInput! ) { simulateSingleStepAuthAndClear(input: $input) { ... on AuthorizationAndClearEvent { id transaction { ... on Node { __typename id } } originalAmount { value currencyCode } requestedAmount { value currencyCode } approvedAmount { value currencyCode } responseCode partial merchantDetails { address { locality region countryCodeAlpha3 postalCode } countryCodeAlpha3 category categoryCode name merchantId description } currentFinancialAccountMaximumBalanceAmount { value currencyCode } currentFinancialAccountAvailableToSpendAmount { value currencyCode } transactionProcessingType pointOfServiceDetails { category panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent isRecurring terminalSupportsPartialApproval } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } paymentCardSnapshot { createdAt status paymentCardCurrent { id expirationDate last4 } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "amount": { "value": 1000, "currencyCode": "USD" }, "cardId": "", "merchantDetails": { "address": { "locality": "Redmond", "region": "WA", "postalCode": "98053", "countryCodeAlpha3": "USA" }, "name": "HIGHNOTE_PLATFORM 1234", "merchantId": "1234567890", "description": "HIGHNOTE SF CA US 1234", "category": "AUTOMATED_CASH_DISBURSE", "countryCodeAlpha3": "USA" }, "transactionProcessingType": "CASH", "pointOfServiceDetails": { "category": "AUTOMATED_TELLER_MACHINE", "panEntryMode": "INTEGRATED_CIRCUIT_CARD", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "UNATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": false } } } Expected Result: { "data": { "simulateSingleStepAuthAndClear": { "id": "", "transaction": { "__typename": "DebitTransaction", "id": "" }, "originalAmount": null, "requestedAmount": { "value": 1000, "currencyCode": "USD" }, "approvedAmount": { "value": 1000, "currencyCode": "USD" }, "responseCode": "APPROVED", "partial": false, "merchantDetails": { "address": { "locality": "Redmond", "region": "WA", "countryCodeAlpha3": "USA", "postalCode": "98053" }, "countryCodeAlpha3": "USA", "category": "AUTOMATED_CASH_DISBURSE", "categoryCode": "6011", "name": "HIGHNOTE_PLATFORM 1234", "merchantId": "1234567890", "description": "HIGHNOTE SF CA US 1234" }, "currentFinancialAccountMaximumBalanceAmount": { "value": 50000000, "currencyCode": "USD" }, "currentFinancialAccountAvailableToSpendAmount": { "value": 49930000, "currencyCode": "USD" }, "transactionProcessingType": "CASH", "pointOfServiceDetails": { "category": "AUTOMATED_TELLER_MACHINE", "panEntryMode": "INTEGRATED_CIRCUIT_CARD", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "UNATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "isRecurring": false, "terminalSupportsPartialApproval": false }, "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "a72be1cc26ea444697b8fa171f6bab6f" }, "paymentCardSnapshot": { "createdAt": "2024-02-14T19:45:04.386Z", "status": "ACTIVE", "paymentCardCurrent": { "id": "", "expirationDate": "2025-01-01T23:59:59Z", "last4": "9662" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 22 } } } ### GraphQL: SimulateReversal Query: mutation SimulateReversal($input: SimulateReversalInput!) { simulateReversal(input: $input) { ... on ReversalEvent { id responseCode merchantDetails { countryCodeAlpha3 category name description merchantId categoryCode address { postalCode region locality countryCodeAlpha3 } } pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent terminalSupportsPartialApproval isRecurring } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } transactionProcessingType transaction { ... on Node { id } } currentFinancialAccountAvailableToSpendAmount { currencyCode value } currentFinancialAccountMaximumBalanceAmount { currencyCode value } } } } Variables: { "input": { "transactionId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT" } } Expected Result: { "data": { "simulateAuthorizationReversal": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointofServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "additionalNetworkData": { "__typename": "VisaData", "transactionIdentifier": "123456" }, "transactionProcessingType": "PAYMENT_DEBIT", "transaction": { "id": "" }, "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 500 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 30000 } } } } ### GraphQL: SimulateRefund Query: mutation SimulateRefund($input: SimulateRefundInput!) { simulateRefund(input: $input) { ... on ClearingEvent { id responseCode merchantDetails { countryCodeAlpha3 category name description merchantId categoryCode address { postalCode region locality countryCodeAlpha3 } } pointOfServiceDetails { category cardDataInputCapability panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent terminalSupportsPartialApproval isRecurring } additionalNetworkData { __typename ... on VisaData { transactionIdentifier } } transactionProcessingType transaction { ... on Node { id } } currentFinancialAccountAvailableToSpendAmount { currencyCode value } currentFinancialAccountMaximumBalanceAmount { currencyCode value } } } } Variables: { "input": { "transactionId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "transactionProcessingType": "RETURNS" } } Expected Result: { "data": { "simulateRefund": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "merchantId": "000000000011111", "name": "Safeway", "description": "Safeway - SF", "category": "MISCELLANEOUS_SPECIALTY_RETAIL", "categoryCode": "5514", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointofServiceDetails": { "category": "AUTOMATED_FUEL_DISPENSER", "cardDataInputCapability": "MAG_STRIPE_READER_AND_EMV_ICC", "panEntryMode": "MAGNETIC_STRIPE", "pinEntryMode": "PIN_VERIFIED_BY_TERMINAL_DEVICE", "terminalAttendance": "ATTENDED", "isCardHolderPresent": true, "isCardPresent": true, "terminalSupportsPartialApproval": true, "isRecurring": false }, "visaData": { "transactionIdentifier": 123456 }, "transactionProcessingType": "RETURNS", "transaction": { "id": "" }, "currentFinancialAccountAvailableToSpendAmount": { "currencyCode": "USD", "value": 500 }, "currentFinancialAccountMaximumBalanceAmount": { "currencyCode": "USD", "value": 30000 } } } } ### GraphQL: SimulateAdjustment Query: mutation SimulateAdjustment($input: SimulateAdjustmentInput!) { simulateAdjustment(input: $input) { ... on AdjustmentEvent { __typename id transaction { ... on Node { __typename id } } responseCode merchantDetails { address { locality region countryCodeAlpha3 postalCode } countryCodeAlpha3 category categoryCode name merchantId description } transactionProcessingType pointOfServiceDetails { category panEntryMode pinEntryMode terminalAttendance isCardHolderPresent isCardPresent isRecurring terminalSupportsPartialApproval cardDataInputCapability } additionalNetworkData { __typename ... on VisaData { transactionIdentifier authorizationCode acquiringInstitutionIdentificationCode retrievalReferenceNumber systemTraceAuditNumber networkTransmissionDateAndTime } ... on MastercardData { banknetReferenceNumber authorizationCode acquiringInstitutionIdentificationCode retrievalReferenceNumber systemTraceAuditNumber networkTransmissionDateAndTime } } paymentCardSnapshot { __typename createdAt status paymentCardCurrent { id last4 formFactor network status } } } ... on UserError { errors { errorPath code description } } } } Variables: { "input": { "transactionId": "", "amount": { "value": 500, "currencyCode": "USD" }, "transactionProcessingType": "ADJUSTMENT_DEBIT" } } Expected Result: { "data": { "simulateAdjustment": { "__typename": "AdjustmentEvent", "id": "", "transaction": { "__typename": "DebitTransaction", "id": "" }, "responseCode": "APPROVED", "merchantDetails": { "address": { "locality": "San Francisco", "region": "CA", "countryCodeAlpha3": "USA", "postalCode": "" }, "countryCodeAlpha3": "USA", "category": "BAKERIES", "categoryCode": "5462", "name": "Some merchant name", "merchantId": "12345678", "description": "HIGHNOTE SF CA US" }, "transactionProcessingType": "ADJUSTMENT_DEBIT", "pointOfServiceDetails": { "category": null, "panEntryMode": null, "pinEntryMode": null, "terminalAttendance": null, "isCardHolderPresent": false, "isCardPresent": false, "isRecurring": false, "terminalSupportsPartialApproval": false, "cardDataInputCapability": null }, "additionalNetworkData": null, "paymentCardSnapshot": { "__typename": "PaymentCardSnapshot", "createdAt": "2024-11-25T19:00:18.570Z", "status": "ACTIVE", "paymentCardCurrent": { "id": "", "last4": "9803", "formFactor": "VIRTUAL", "network": "MASTERCARD", "status": "ACTIVE" } } } }, "extensions": { "requestId": "6896af4c-0b38-9f0d-8a75-085a8d5be838", "rateLimit": { "cost": 17 } } } --- URL: https://docs.highnote.com/docs/issuing/transactions/sim-travel-transactions Title: Simulate Travel Transactions Section: Issuing Description: Simulate Visa and Mastercard travel enhanced data for airline, lodging, car rental, rail, and travel agency purchases in the Test environment. ## Overview Do not enter production data in the Highnote Test environment, which is for exploring features and training. Use only dummy or test data. Travel merchants send enhanced data describing the purchase itself—the ticket, the itinerary, the folio, the rental agreement. Highnote surfaces that data on the transaction whenever a merchant provides it. You can use the Highnote API to simulate travel enhanced data in the Test environment. Simulating travel transactions helps test the following use cases and card product settings: - Airline, lodging, car rental, rail, and travel agency enhanced data - Itemized taxes, fees, and extra charges - Refunds and reversals that carry enhanced data - Per-network differences between Visa and Mastercard - Spend rules and velocity controls on travel merchant category codes (MCCs) This guide provides steps for simulating travel transactions using the Highnote API. ## Prerequisites - Review Transaction Lifecycle guide - Review Simulate Transactions guide - A Highnote account - An API key or the API Explorer - A commercial credit card product, financial account, and payment card ## Merchant category codes Travel enhanced data is reported by merchants operating under travel MCCs. For an overview of MCC-based spend controls, see Configure Spend Rules. The following table maps the travel MCCs to the [](/docs/api-reference/enum#MerchantCategory) value you pass in : | CODE | DESCRIPTION | MERCHANTCATEGORY | | :--------------------------- | :-------------------------------- | :------------------------------- | | 3003 – 3291 (selected codes) | Airlines, air carriers | | | 3356 – 3440 (selected codes) | Car rentals | | | 4112 | Passenger railways | | | 4411 | Cruise lines | | | 4511 | Airlines, air carriers | | | 4722 | Travel agencies, tour operators | | | 5812 | Eating places, restaurants | | | 5814 | Fast food restaurants | | | 7011 | Hotels, motels, and resorts | | | 7512 | Car rental agencies | | | 7513 | Truck and utility trailer rentals | | The 3000-series codes are not contiguous. Many of them map to brand-specific members instead— is and is . When you pass one of the generic members above, Highnote sends the first MCC in that member's set, so produces categoryCode rather than . Highnote does not validate the enhanced data type against the merchant category you supply. A simulation that attaches lodging data to an airline MCC succeeds, and the data is stored and returned as sent. Set to a category the data belongs to, so your simulated transactions match what you receive in Live. ## Travel data by network Travel enhanced data reaches Highnote through the field on a transaction event. That field is a list of the [](/docs/api-reference/interface#AdditionalTransactionData) interface, so it can carry travel data, fleet data, or both. Discriminate on and select the fields you need through an inline fragment. Visa and Mastercard model travel data differently, and they deliver it at different points in the transaction lifecycle. ### When travel data arrives | Network | Data | When it arrives | | :--------- | :-------------------------------------------- | :----------------------------------------------------------------------------------------------- | | Visa | One industry record per transaction | Authorization, reversal, clearing, or—for late Level 3 detail—an | | Mastercard | All industry records together, in one wrapper | Clearing stream only, on a or an | You can set up a Notification Event to alert you when enhanced data has been added to a transaction. For fuel, non-fuel, and other fleet-related enhanced data, see Simulate Fleet Transactions. ### Visa travel data Visa reports one industry record per transaction, and the three verticals are mutually exclusive. An event carries at most one of the following types: - [](/docs/api-reference/object#VisaAirlineData) — ticket number, fare, taxes and fees, travel agency, and per-leg itinerary detail in - [](/docs/api-reference/object#VisaLodgingData) — check-in and check-out dates, room nights, room rate, room tax, and extra-charge indicators - [](/docs/api-reference/object#VisaCarRentalData) — days rented, daily and weekly rates, insurance, fuel, and extra-charge indicators Visa data can arrive on an [](/docs/api-reference/object#AuthorizationEvent), a [](/docs/api-reference/object#ReversalEvent), or a [](/docs/api-reference/object#ClearingEvent), depending on when the acquirer provides it. It can also arrive later, out of band, on an [](/docs/api-reference/object#EnhancedDataEvent)—this is how Level 3 detail is typically delivered. Check all four so you capture it regardless of when it arrives. Visa spells the same value differently on input and output. Most pairs follow the same rule—drop the suffix, as with and . These six do not: | Read field | Input field | | :---------------------------- | :----------------------- | | | | | | | | | | | | | | | | | | | The first five drop the suffix and pluralize; keeps the suffix on both sides. Check the type reference rather than transforming a name by rule, and do not reuse input field names in a response selection set. Mastercard has no such asymmetry: its input and read field names match. ### Mastercard travel data Mastercard reports every industry record together, under a single [](/docs/api-reference/object#MastercardEnhancedTravelData) wrapper. Its five industry fields populate independently: - — a single [](/docs/api-reference/object#MastercardPassengerTransportData) object holding the ticket-level details, with per-leg detail nested under - — a list of [](/docs/api-reference/object#MastercardRailData), one element per trip leg - — a list of [](/docs/api-reference/object#MastercardCarRentalData) - — a list of [](/docs/api-reference/object#MastercardLodgingData) - — a list of [](/docs/api-reference/object#MastercardTravelAgencyData) Only the fields the merchant reported are populated. An event that carries no travel records produces no entry at all, so can be empty on a Mastercard clearing. Mastercard transmits travel data only on the clearing message, never on an authorization or a reversal. Simulate it through or only. On the read side it arrives on a [](/docs/api-reference/object#ClearingEvent) or an [](/docs/api-reference/object#EnhancedDataEvent), including the a refund returns. Check both, because the event that carries the data depends on when the acquirer supplies it. Two Mastercard details are worth noting when you read the data back. The wrapper's is the id of the enhanced data record, so a single event reporting an airline ticket, a rail leg, and a hotel stay returns one wrapper with one . And returns when the network reports a tax whose type it does not identify, so treat as an expected value rather than an error. ## Simulate an airline transaction ### via Visa {#sim-airline-via-visa} Airline data covers the ticket and its itinerary. Highnote assigns from the order of the list, so you do not send it. Use the following mutation to simulate an airline authorization with Visa: ### via Mastercard {#sim-airline-via-mc} Mastercard reports airline purchases as passenger transport data. See Simulate a clearing with Mastercard, which carries passenger transport data alongside the other four industries. ## Simulate a lodging transaction ### via Visa {#sim-lodging-via-visa} Lodging data describes the stay and the folio. The indicators are individual booleans rather than a single code, so set each one you want to report. Use the following mutation to simulate a lodging clearing with Visa: ### via Mastercard {#sim-lodging-via-mc} Mastercard reports lodging as a list under . See Simulate a refund with Mastercard for a lodging-only example. ## Simulate a car rental transaction ### via Visa {#sim-car-rental-via-visa} Car rental data describes the rental agreement. Daily and weekly rates are separate fields rather than a rate plus a frequency code. Use the following mutation to simulate a car rental reversal with Visa: ### via Mastercard {#sim-car-rental-via-mc} Mastercard describes the two ends of the rental separately: is a [](/docs/api-reference/object#MastercardRentalCheckout) and is a [](/docs/api-reference/object#MastercardRentalReturn). Both carry the same five fields—, , , , and . is an and is a , not strings. Mastercard also reports the rate frequency in a separate field of type [](/docs/api-reference/enum#MastercardRentalRateFrequency), rather than inferring it from which rate field is populated as Visa does. See Simulate a clearing with Mastercard. ## Simulate a clearing ### via Visa {#sim-clearing-via-visa} Visa clearing carries at most one industry record. See Simulate a lodging transaction via Visa for a clearing example, and swap for or to simulate a different vertical. ### via Mastercard {#sim-clearing-via-mc} Mastercard transmits travel data only on the clearing message, never on an authorization or a reversal, as noted above. All five industry records travel together in one value, so a single mutation can report an airline ticket, a rail leg, a car rental, a hotel stay, and a travel agency fee at once. Use the following mutation to simulate a travel clearing with Mastercard: ## Simulate a refund ### via Visa {#sim-refund-via-visa} accepts , so a refund can carry Visa airline, lodging, or car rental data using the same input shape shown in Simulate a lodging transaction via Visa. Send the vertical that matches the original purchase. ### via Mastercard {#sim-refund-via-mc} A refund is transmitted on the same clearing message as a purchase and returns the same type, so it accepts Mastercard travel data. Amounts that represent a credit are signed, so a refunded charge is a negative value. Use the following mutation to simulate a travel refund with Mastercard: ## Read travel data back is a heterogeneous list, so a consumer must discriminate on before selecting fields. In Live, Visa Level 3 data, which is the line-item detail an acquirer sends after the transaction, and Mastercard enhanced data arrive after the original authorization, so query the transaction event again rather than relying on the response to the authorization. Enhanced data that arrives out of band lands on an rather than on the original authorization or clearing. The following query discriminates the four event types this page simulates travel data on. The fragment is shared across all four branches, so each selects every travel type; combinations the tables above rule out simply return nothing. exposes a field, but it is always null on that type, so the query omits it there. Use the following query to read travel enhanced data from a transaction event: ## Errors and limitations The following behaviors apply when you simulate travel enhanced data: | Behavior | Result | | :----------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | More than one industry type in a single value | Rejected. The input accepts exactly one of its fields. | | on , , or | with code | | , , or on | Accepted and forwarded, but does not expose at all | | Enhanced data type that does not match | Accepted. Highnote does not validate the pairing. | | A field the merchant did not report | Returns . Lists return rather than an empty list. | Simulation confirms that your integration accepts and reads travel enhanced data correctly. It does not model whether a given acquirer sends the data in Live, or whether a transaction qualifies for commercial interchange. In Live, enhanced data exists only when the acquirer provides it. ## Automate your integration To automate your integration, subscribe to the following notification events: - Payment card authorization - Payment authorization and clear - Payment card cleared - Payment card transaction enhanced data The details provided in the payloads from these events can be used for the following use cases: - Automate your application or website's transaction processing workflows - Create account holder notifications and alerts ### GraphQL: SimulateVisaAirlineAuthorization Query: mutation SimulateVisaAirlineAuthorization($input: SimulateAuthorizationInput!) { simulateAuthorization(input: $input) { ... on AuthorizationEvent { id responseCode merchantDetails { category categoryCode name } transaction { ... on Node { id } } additionalTransactionData { __typename ... on VisaAirlineData { id ticketNumber ticketIssueDate electronicTicketIndicator travelAgencyCode travelAgencyName totalFareAmount { value currencyCode } totalTaxAmount { value currencyCode } totalFeeAmount { value currencyCode } legs { legSequenceNumber carrierCode flightNumber serviceClassCode originationCityAirportCode destinationCityAirportCode departureDate departureTime arrivalTime stopOverIndicator fareBasisCode } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "cardId": "", "amount": { "value": 45000, "currencyCode": "USD" }, "merchantDetails": { "merchantId": "000000000011111", "name": "HIGHNOTE AIRWAYS", "description": "HIGHNOTE AIRWAYS - SFO", "category": "AIRLINES_AIR_CARRIERS", "address": { "postalCode": "94128", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "ECOMMERCE", "cardDataInputCapability": "KEY_ENTERED", "panEntryMode": "MANUAL", "pinEntryMode": "NO_PIN_ENTRY_CAPABILITY", "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "terminalSupportsPartialApproval": false, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT", "additionalTransactionData": { "visaAirlineData": { "ticketNumber": "0161234567890", "ticketIssueDate": "2026-08-01", "electronicTicketIndicator": true, "internetIndicator": true, "restrictedTicketIndicator": false, "travelAgencyCode": "TA123", "travelAgencyName": "HIGHNOTE TRAVEL", "computerizedReservationSystemCode": "SABR", "totalFare": { "value": 39500, "currencyCode": "USD" }, "totalTax": { "value": 4200, "currencyCode": "USD" }, "totalFee": { "value": 1300, "currencyCode": "USD" }, "legs": [ { "carrierCode": "HN", "flightNumber": "0100", "serviceClassCode": "Y", "originationCityAirportCode": "SFO", "destinationCityAirportCode": "JFK", "departureDate": "2026-09-14", "departureTime": "0930", "arrivalTime": "1745", "stopOverIndicator": false, "fareBasisCode": "YCA14" }, { "carrierCode": "HN", "flightNumber": "0101", "serviceClassCode": "Y", "originationCityAirportCode": "JFK", "destinationCityAirportCode": "SFO", "departureDate": "2026-09-21", "departureTime": "1810", "arrivalTime": "2135", "stopOverIndicator": false, "fareBasisCode": "YCA14" } ] } } } } Expected Result: { "data": { "simulateAuthorization": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "category": "AIRLINES_AIR_CARRIERS", "categoryCode": "3003", "name": "HIGHNOTE AIRWAYS" }, "transaction": { "id": "" }, "additionalTransactionData": [ { "__typename": "VisaAirlineData", "id": "", "ticketNumber": "0161234567890", "ticketIssueDate": "2026-08-01", "electronicTicketIndicator": true, "travelAgencyCode": "TA123", "travelAgencyName": "HIGHNOTE TRAVEL", "totalFareAmount": { "value": 39500, "currencyCode": "USD" }, "totalTaxAmount": { "value": 4200, "currencyCode": "USD" }, "totalFeeAmount": { "value": 1300, "currencyCode": "USD" }, "legs": [ { "legSequenceNumber": 1, "carrierCode": "HN", "flightNumber": "0100", "serviceClassCode": "Y", "originationCityAirportCode": "SFO", "destinationCityAirportCode": "JFK", "departureDate": "2026-09-14", "departureTime": "0930", "arrivalTime": "1745", "stopOverIndicator": false, "fareBasisCode": "YCA14" }, { "legSequenceNumber": 2, "carrierCode": "HN", "flightNumber": "0101", "serviceClassCode": "Y", "originationCityAirportCode": "JFK", "destinationCityAirportCode": "SFO", "departureDate": "2026-09-21", "departureTime": "1810", "arrivalTime": "2135", "stopOverIndicator": false, "fareBasisCode": "YCA14" } ] } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateVisaLodgingClearing Query: mutation SimulateVisaLodgingClearing($input: SimulateClearingInput!) { simulateClearing(input: $input) { ... on ClearingEvent { id responseCode merchantDetails { category categoryCode name } transaction { ... on Node { id } } additionalTransactionData { __typename ... on VisaLodgingData { id checkInDate checkOutDate roomNights serviceDate noShowIndicator purchaseIdentifier averageDailyRoomRateAmount { value currencyCode } totalRoomTaxAmount { value currencyCode } totalTaxAmount { value currencyCode } foodAndBeverageChargeAmount { value currencyCode } prepaidExpensesAmount { value currencyCode } folioCashAdvanceAmount { value currencyCode } extraChargeRestaurantIndicator extraChargeGiftShopIndicator extraChargeMinibarIndicator extraChargeTelephoneIndicator extraChargeLaundryIndicator extraChargeOtherIndicator localTaxIndicator localTaxAmount { value currencyCode } nationalTaxIndicator nationalTaxAmount { value currencyCode } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "HIGHNOTE HOTEL SF", "description": "HIGHNOTE HOTEL - SF", "category": "HOTELS_MOTELS_AND_RESORTS", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "ECOMMERCE", "cardDataInputCapability": "KEY_ENTERED", "panEntryMode": "MANUAL", "pinEntryMode": "NO_PIN_ENTRY_CAPABILITY", "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "terminalSupportsPartialApproval": false, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT", "additionalTransactionData": { "visaLodgingData": { "checkInDate": "2026-09-14", "checkOutDate": "2026-09-17", "roomNights": 3, "serviceDate": "2026-09-14", "noShowIndicator": false, "purchaseIdentifier": "FOLIO-88213", "averageDailyRoomRate": { "value": 25000, "currencyCode": "USD" }, "totalRoomTax": { "value": 9000, "currencyCode": "USD" }, "totalTax": { "value": 11250, "currencyCode": "USD" }, "foodAndBeverageCharges": { "value": 6400, "currencyCode": "USD" }, "prepaidExpenses": { "value": 0, "currencyCode": "USD" }, "folioCashAdvances": { "value": 0, "currencyCode": "USD" }, "extraChargeRestaurantIndicator": true, "extraChargeGiftShopIndicator": false, "extraChargeMinibarIndicator": true, "extraChargeTelephoneIndicator": false, "extraChargeLaundryIndicator": false, "extraChargeOtherIndicator": false, "localTaxIndicator": true, "localTax": { "value": 2250, "currencyCode": "USD" }, "nationalTaxIndicator": false, "merchantPostalCode": "94105", "timeOfPurchase": "1102", "customerReferenceNumber": "CRN-4471" } } } } Expected Result: { "data": { "simulateClearing": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "category": "HOTELS_MOTELS_AND_RESORTS", "categoryCode": "7011", "name": "HIGHNOTE HOTEL SF" }, "transaction": { "id": "" }, "additionalTransactionData": [ { "__typename": "VisaLodgingData", "id": "", "checkInDate": "2026-09-14", "checkOutDate": "2026-09-17", "roomNights": 3, "serviceDate": "2026-09-14", "noShowIndicator": false, "purchaseIdentifier": "FOLIO-88213", "averageDailyRoomRateAmount": { "value": 25000, "currencyCode": "USD" }, "totalRoomTaxAmount": { "value": 9000, "currencyCode": "USD" }, "totalTaxAmount": { "value": 11250, "currencyCode": "USD" }, "foodAndBeverageChargeAmount": { "value": 6400, "currencyCode": "USD" }, "prepaidExpensesAmount": { "value": 0, "currencyCode": "USD" }, "folioCashAdvanceAmount": { "value": 0, "currencyCode": "USD" }, "extraChargeRestaurantIndicator": true, "extraChargeGiftShopIndicator": false, "extraChargeMinibarIndicator": true, "extraChargeTelephoneIndicator": false, "extraChargeLaundryIndicator": false, "extraChargeOtherIndicator": false, "localTaxIndicator": true, "localTaxAmount": { "value": 2250, "currencyCode": "USD" }, "nationalTaxIndicator": false, "nationalTaxAmount": null } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateVisaCarRentalReversal Query: mutation SimulateVisaCarRentalReversal($input: SimulateReversalInput!) { simulateReversal(input: $input) { ... on ReversalEvent { id responseCode merchantDetails { category categoryCode name } transaction { ... on Node { id } } additionalTransactionData { __typename ... on VisaCarRentalData { id daysRented carClassCode serviceDate noShowIndicator purchaseIdentifier dailyRentalRateAmount { value currencyCode } weeklyRentalRateAmount { value currencyCode } insuranceChargeAmount { value currencyCode } fuelChargeAmount { value currencyCode } oneWayDropOffChargeAmount { value currencyCode } extraChargeGasIndicator extraChargeMileageIndicator extraChargeLateReturnIndicator extraChargeOneWayIndicator extraChargeParkingViolationIndicator localTaxIndicator localTaxAmount { value currencyCode } nationalTaxIndicator nationalTaxAmount { value currencyCode } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "HIGHNOTE CAR RENTAL", "description": "HIGHNOTE CAR RENTAL - OAK", "category": "CAR_RENTAL_AGENCIES", "address": { "postalCode": "94621", "region": "CA", "locality": "Oakland", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "ECOMMERCE", "cardDataInputCapability": "KEY_ENTERED", "panEntryMode": "MANUAL", "pinEntryMode": "NO_PIN_ENTRY_CAPABILITY", "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "terminalSupportsPartialApproval": false, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT", "additionalTransactionData": { "visaCarRentalData": { "daysRented": 5, "carClassCode": "ICAR", "serviceDate": "2026-09-14", "noShowIndicator": false, "purchaseIdentifier": "RA-770145", "dailyRentalRate": { "value": 4500, "currencyCode": "USD" }, "insuranceCharges": { "value": 3500, "currencyCode": "USD" }, "fuelCharges": { "value": 2800, "currencyCode": "USD" }, "oneWayDropOffCharges": { "value": 7500, "currencyCode": "USD" }, "extraChargeGasIndicator": true, "extraChargeMileageIndicator": false, "extraChargeLateReturnIndicator": false, "extraChargeOneWayIndicator": true, "extraChargeParkingViolationIndicator": false, "localTaxIndicator": true, "localTax": { "value": 1980, "currencyCode": "USD" }, "nationalTaxIndicator": false, "merchantPostalCode": "94621", "timeOfPurchase": "1615" } } } } Expected Result: { "data": { "simulateReversal": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "category": "CAR_RENTAL_AGENCIES", "categoryCode": "7512", "name": "HIGHNOTE CAR RENTAL" }, "transaction": { "id": "" }, "additionalTransactionData": [ { "__typename": "VisaCarRentalData", "id": "", "daysRented": 5, "carClassCode": "ICAR", "serviceDate": "2026-09-14", "noShowIndicator": false, "purchaseIdentifier": "RA-770145", "dailyRentalRateAmount": { "value": 4500, "currencyCode": "USD" }, "weeklyRentalRateAmount": null, "insuranceChargeAmount": { "value": 3500, "currencyCode": "USD" }, "fuelChargeAmount": { "value": 2800, "currencyCode": "USD" }, "oneWayDropOffChargeAmount": { "value": 7500, "currencyCode": "USD" }, "extraChargeGasIndicator": true, "extraChargeMileageIndicator": false, "extraChargeLateReturnIndicator": false, "extraChargeOneWayIndicator": true, "extraChargeParkingViolationIndicator": false, "localTaxIndicator": true, "localTaxAmount": { "value": 1980, "currencyCode": "USD" }, "nationalTaxIndicator": false, "nationalTaxAmount": null } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateMastercardTravelClearing Query: mutation SimulateMastercardTravelClearing($input: SimulateClearingInput!) { simulateClearing(input: $input) { ... on ClearingEvent { id responseCode merchantDetails { category categoryCode name } transaction { ... on Node { id } } additionalTransactionData { __typename ... on MastercardEnhancedTravelData { id passengerTransportData { ticketNumber issuingCarrier totalFareAmount { value currencyCode } totalTaxesAmount { value currencyCode } totalFeeAmount { value currencyCode } tripLegs { travelDate carrierCode flightNumber serviceClassCode originationCityAirportCode destinationCityAirportCode departureTime arrivalTime fareAmount { value currencyCode } } } railData { ticketNumber startStation destinationStation ticketClass } carRentalData { rentalAgreementNumber rentalRateFrequency rentalRateAmount { value currencyCode } rentalCheckout { city stateOrProvince country locationIdentifier date } rentalReturn { city stateOrProvince country locationIdentifier date } detailTaxAmounts { taxType taxAmount { value currencyCode } } } lodgingData { folioNumber arrivalDate departureDate totalAmountChargedOnCreditCard { value currencyCode } } travelAgencyData { travelAgencySequenceNumber travelAgencyFeeDescription travelAgencyFeeAmount { value currencyCode } customIdentifier { customIdentifierType customIdentifierValue } } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "HIGHNOTE AIRWAYS", "description": "HIGHNOTE AIRWAYS - SFO", "category": "AIRLINES_AIR_CARRIERS", "address": { "postalCode": "94128", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "ECOMMERCE", "cardDataInputCapability": "KEY_ENTERED", "panEntryMode": "MANUAL", "pinEntryMode": "NO_PIN_ENTRY_CAPABILITY", "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "terminalSupportsPartialApproval": false, "isRecurring": false }, "transactionProcessingType": "PAYMENT_DEBIT", "additionalTransactionData": { "mastercardEnhancedTravelData": { "passengerTransportData": { "ticketNumber": "0017890123456", "issuingCarrier": "HN", "totalFareAmount": { "value": 39500, "currencyCode": "USD" }, "totalTaxesAmount": { "value": 4200, "currencyCode": "USD" }, "totalFeeAmount": { "value": 1300, "currencyCode": "USD" }, "tripLegs": [ { "travelDate": "2026-09-14", "carrierCode": "HN", "flightNumber": "0100", "serviceClassCode": "Y", "originationCityAirportCode": "SFO", "destinationCityAirportCode": "JFK", "departureTime": "0930", "arrivalTime": "1745", "fareAmount": { "value": 39500, "currencyCode": "USD" } } ] }, "railData": [ { "ticketNumber": "9912345678", "startStation": "Union Station", "destinationStation": "Penn Station", "ticketClass": "1" } ], "carRentalData": [ { "rentalAgreementNumber": "RA-770145", "rentalRateFrequency": "DAILY", "rentalRateAmount": { "value": 5000, "currencyCode": "USD" }, "rentalCheckout": { "city": "Oakland", "stateOrProvince": "CA", "country": "USA", "locationIdentifier": "OAK01", "date": "2026-09-14" }, "rentalReturn": { "city": "San Francisco", "stateOrProvince": "CA", "country": "USA", "locationIdentifier": "SFO01", "date": "2026-09-19" }, "detailTaxAmounts": [ { "taxType": "STATE_SALES_TAX", "taxAmount": { "value": 1980, "currencyCode": "USD" } } ] } ], "lodgingData": [ { "folioNumber": "FOLIO-88213", "arrivalDate": "2026-09-14", "departureDate": "2026-09-17", "totalAmountChargedOnCreditCard": { "value": 80000, "currencyCode": "USD" } } ], "travelAgencyData": [ { "travelAgencySequenceNumber": "1", "travelAgencyFeeDescription": "Booking fee", "travelAgencyFeeAmount": { "value": 500, "currencyCode": "USD" }, "customIdentifier": { "customIdentifierType": "RECORD_LOCATOR", "customIdentifierValue": "LOC-1" } } ] } } } } Expected Result: { "data": { "simulateClearing": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "category": "AIRLINES_AIR_CARRIERS", "categoryCode": "3003", "name": "HIGHNOTE AIRWAYS" }, "transaction": { "id": "" }, "additionalTransactionData": [ { "__typename": "MastercardEnhancedTravelData", "id": "", "passengerTransportData": { "ticketNumber": "0017890123456", "issuingCarrier": "HN", "totalFareAmount": { "value": 39500, "currencyCode": "USD" }, "totalTaxesAmount": { "value": 4200, "currencyCode": "USD" }, "totalFeeAmount": { "value": 1300, "currencyCode": "USD" }, "tripLegs": [ { "travelDate": "2026-09-14", "carrierCode": "HN", "flightNumber": "0100", "serviceClassCode": "Y", "originationCityAirportCode": "SFO", "destinationCityAirportCode": "JFK", "departureTime": "0930", "arrivalTime": "1745", "fareAmount": { "value": 39500, "currencyCode": "USD" } } ] }, "railData": [ { "ticketNumber": "9912345678", "startStation": "Union Station", "destinationStation": "Penn Station", "ticketClass": "1" } ], "carRentalData": [ { "rentalAgreementNumber": "RA-770145", "rentalRateFrequency": "DAILY", "rentalRateAmount": { "value": 5000, "currencyCode": "USD" }, "rentalCheckout": { "city": "Oakland", "stateOrProvince": "CA", "country": "USA", "locationIdentifier": "OAK01", "date": "2026-09-14" }, "rentalReturn": { "city": "San Francisco", "stateOrProvince": "CA", "country": "USA", "locationIdentifier": "SFO01", "date": "2026-09-19" }, "detailTaxAmounts": [ { "taxType": "STATE_SALES_TAX", "taxAmount": { "value": 1980, "currencyCode": "USD" } } ] } ], "lodgingData": [ { "folioNumber": "FOLIO-88213", "arrivalDate": "2026-09-14", "departureDate": "2026-09-17", "totalAmountChargedOnCreditCard": { "value": 80000, "currencyCode": "USD" } } ], "travelAgencyData": [ { "travelAgencySequenceNumber": "1", "travelAgencyFeeDescription": "Booking fee", "travelAgencyFeeAmount": { "value": 500, "currencyCode": "USD" }, "customIdentifier": { "customIdentifierType": "RECORD_LOCATOR", "customIdentifierValue": "LOC-1" } } ] } ] } }, "extensions": { "requestId": "" } } ### GraphQL: SimulateMastercardTravelRefund Query: mutation SimulateMastercardTravelRefund($input: SimulateRefundInput!) { simulateRefund(input: $input) { ... on ClearingEvent { id responseCode merchantDetails { category categoryCode name } transaction { ... on Node { id } } additionalTransactionData { __typename ... on MastercardEnhancedTravelData { id lodgingData { folioNumber arrivalDate departureDate roomRateAmount { value currencyCode } totalAmountChargedOnCreditCard { value currencyCode } customIdentifier { customIdentifierType customIdentifierValue } } } } } ... on UserError { errors { errorPath code description } } ... on AccessDeniedError { message } } } Variables: { "input": { "transactionId": "", "merchantDetails": { "merchantId": "000000000011111", "name": "HIGHNOTE HOTEL SF", "description": "HIGHNOTE HOTEL - SF", "category": "HOTELS_MOTELS_AND_RESORTS", "address": { "postalCode": "94105", "region": "CA", "locality": "San Francisco", "countryCodeAlpha3": "USA" } }, "pointOfServiceDetails": { "category": "ECOMMERCE", "cardDataInputCapability": "KEY_ENTERED", "panEntryMode": "MANUAL", "pinEntryMode": "NO_PIN_ENTRY_CAPABILITY", "terminalAttendance": "UNATTENDED", "isCardHolderPresent": false, "isCardPresent": false, "terminalSupportsPartialApproval": false, "isRecurring": false }, "transactionProcessingType": "RETURNS", "additionalTransactionData": { "mastercardEnhancedTravelData": { "lodgingData": [ { "folioNumber": "FOLIO-88213", "arrivalDate": "2026-09-14", "departureDate": "2026-09-17", "roomRateAmount": { "value": 25000, "currencyCode": "USD" }, "totalAmountChargedOnCreditCard": { "value": -25000, "currencyCode": "USD" }, "customIdentifier": { "customIdentifierType": "FOLIO_NUMBER", "customIdentifierValue": "FOLIO-88213" } } ] } } } } Expected Result: { "data": { "simulateRefund": { "id": "", "responseCode": "APPROVED", "merchantDetails": { "category": "HOTELS_MOTELS_AND_RESORTS", "categoryCode": "7011", "name": "HIGHNOTE HOTEL SF" }, "transaction": { "id": "" }, "additionalTransactionData": [ { "__typename": "MastercardEnhancedTravelData", "id": "", "lodgingData": [ { "folioNumber": "FOLIO-88213", "arrivalDate": "2026-09-14", "departureDate": "2026-09-17", "roomRateAmount": { "value": 25000, "currencyCode": "USD" }, "totalAmountChargedOnCreditCard": { "value": -25000, "currencyCode": "USD" }, "customIdentifier": { "customIdentifierType": "FOLIO_NUMBER", "customIdentifierValue": "FOLIO-88213" } } ] } ] } }, "extensions": { "requestId": "" } } ### GraphQL: FindTravelEnhancedData Query: query FindTravelEnhancedData($id: ID!) { node(id: $id) { __typename ... on ClearingEvent { id merchantDetails { category categoryCode } additionalTransactionData { ...TravelEnhancedData } } ... on EnhancedDataEvent { id additionalTransactionData { ...TravelEnhancedData } } ... on AuthorizationEvent { id merchantDetails { category categoryCode } additionalTransactionData { ...TravelEnhancedData } } ... on ReversalEvent { id merchantDetails { category categoryCode } additionalTransactionData { ...TravelEnhancedData } } } } fragment TravelEnhancedData on AdditionalTransactionData { __typename ... on VisaAirlineData { id ticketNumber totalFareAmount { value currencyCode } legs { legSequenceNumber carrierCode flightNumber originationCityAirportCode destinationCityAirportCode } } ... on VisaLodgingData { id checkInDate checkOutDate roomNights averageDailyRoomRateAmount { value currencyCode } } ... on VisaCarRentalData { id daysRented carClassCode dailyRentalRateAmount { value currencyCode } } ... on MastercardEnhancedTravelData { id passengerTransportData { ticketNumber issuingCarrier totalFareAmount { value currencyCode } totalTaxesAmount { value currencyCode } totalFeeAmount { value currencyCode } } railData { ticketNumber startStation destinationStation } carRentalData { rentalAgreementNumber rentalRateFrequency rentalCheckout { city stateOrProvince country locationIdentifier date } rentalReturn { city stateOrProvince country locationIdentifier date } } lodgingData { folioNumber arrivalDate departureDate } travelAgencyData { travelAgencySequenceNumber travelAgencyFeeDescription } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "EnhancedDataEvent", "id": "", "additionalTransactionData": [ { "__typename": "MastercardEnhancedTravelData", "id": "", "passengerTransportData": { "ticketNumber": "0017890123456", "issuingCarrier": "HN", "totalFareAmount": { "value": 39500, "currencyCode": "USD" }, "totalTaxesAmount": { "value": 4200, "currencyCode": "USD" }, "totalFeeAmount": { "value": 1300, "currencyCode": "USD" } }, "railData": [ { "ticketNumber": "9912345678", "startStation": "Union Station", "destinationStation": "Penn Station" } ], "carRentalData": null, "lodgingData": null, "travelAgencyData": null } ] } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/issuing/transactions/transaction-lifecycle Title: Transaction Lifecycle Section: Issuing Description: Understand the transaction lifecycle from authorization through clearing and settlement. Covers single-message and dual-message flows, reversals, refunds, and pending fund expiration. ## Overview This guide provides an overview of the transaction lifecycle on the Highnote platform, details on how Highnote interprets network messages, and examples of common transaction scenarios. A Transaction is an electronic message that originates from a cardholder attempting payment online or in-store. These messages are sent to Highnote based on logic set by merchants and networks. The Highnote platform interprets them using the object. ## Transactions vs transaction events One transaction can contain multiple transaction events. - A Transaction groups related transaction events for a single purchase, refund, or other card activity. - A TransactionEvent is an individual event within that group, such as an authorization, clearing, or reversal. When reconciling, use for granularity. ```sh title="Transaction vs TransactionEvent" Transaction (transactionId: tx_abc123) ├── AuthorizationEvent (transactionEventId: te_001) — $50.00 DEBIT ├── ClearingEvent (transactionEventId: te_002) — $50.00 DEBIT └── ReversalEvent (transactionEventId: te_003) — $10.00 CREDIT Transaction (transactionId: tx_def456) ├── AuthorizationAndClearEvent (transactionEventId: te_004) — $25.00 DEBIT └── ClearingEvent (transactionEventId: te_005) — $15.00 CREDIT (refund) ``` ## Transactions at the network level At the network level, the typical transaction lifecycle occurs as follows: - **Authorization:** The network checks the card's validity and confirms funds availability. The transaction amount is put on hold. - **Clearing:** The network finalizes the hold and posts the transaction on the cardholder's account. - **Settlement:** The network transfers funds between the acquiring and issuing banks. Authorizations fall into two categories: - **A single-message transaction:** The network sends a single message to authorize, clear, and settle the transaction. - **A dual-message transaction:** The network sends an message to process an authorization. A separate message is sent for clearing and settlement. The following graphics outline how Highnote receives and interprets single and dual-message authorizations throughout the transaction lifecycle: ### Single-message authorization flow ### Dual-message authorization flow ## Transaction events on the Highnote platform The following section provides an overview of transaction events for card products _not_ using collaborative authorization. For more information on the transaction lifecycle for card programs with collaborative authorization enabled, see Card products with collaborative authorization. Highnote interprets electronic messages from the network using the object. The table below shows how Highnote interprets network transaction messages. It also shows the related Highnote notification events: | Network transaction message | Description | Highnote transaction event | Notification event | | :----------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------- | :------------------------------------------------------------------------------------------- | | Verification | The network sends a message to Highnote to validate card details: cardholder name or address, spend rules, zip code, etc. | | Notification reference | | Pre-authorization | The network sends a message to Highnote to reserve a specific amount of money on a cardholder's account to ensure funds availability. | | Notification reference | | Authorization | The network sends a dual-message request to Highnote to decide whether to approve the transaction. Later, the network sends additional information to Highnote to finalize the transaction. | | Notification reference | | | The network sends a single-message request to Highnote with the necessary data to approve and finalize the transaction in one step. | | Notification reference | | Clearing | The network sends the second half of a dual-message request to Highnote to finalize a transaction. | | Notification reference | | Settlement | The process of moving money between the merchant's and cardholder's banks. Highnote uses clearing events to represent clearing and settlement. | | Notification reference | | Reversals | This type of transaction occurs when a merchant cancels a transaction _before_ a clearing event takes place. Reversals can be for the full transaction amount or a partial amount. | | N/A | | Refunds | The network sends an authorization event to Highnote to process a refund. The refund is reflected as a credit to the cardholder's account. | | Notification reference | | | The network sends an authorization and clearing event to Highnote to process a refund. The refund is reflected as a credit to the cardholder's account. | | Notification reference | | | The network sends a clearing event to Highnote to process a refund. The refund is reflected as a credit to the cardholder's account. | | Notification reference | ### Card products with collaborative authorization Collaborative authorization allows you to approve or decline transactions in real-time based on your business logic. In card products that use collaborative authorization, an precedes s. The following steps represent a common flow for transaction messages sent to Highnote for a card product using collaborative authorization: 1. The cardholder makes a purchase. 2. The network sends a message to Highnote to approve the transaction. 3. Highnote creates an before calling the card product's collaborative authorization endpoint. An holds funds to cover the amount requested by the network. 4. Highnote sends an HTTPS POST request to the card product's collaborative authorization endpoint for approval. 5. The collaborative authorization endpoint responds with approval. 6. The Highnote platform creates an . ## Verification events Highnote interprets network verifications as . Verifications are typically done to prevent fraud and validate a payment card in the following common scenarios: - A cardholder adds their payment card to a digital wallet - A cardholder saves their payment card as a payment method online - A cardholder adds their payment card to a peer-to-peer payments app Verifications may be declined for several reasons. Examples include, but are not limited to: - Incorrect name or address provided - Merchant Category Code (MCC) blocked for card or product - Wrong zip code provided When a is declined, Highnote provides a Response Code explaining why. ## Authorization events Highnote interprets the following types of transaction messages as : - Pre-authorizations - Dual-message authorizations - Single-message authorizations Authorizations may reflect different requested and approved amounts. When an authorization is approved, the amount reflected on the Highnote ledger is the approved amount. These amounts are defined as follows: - : The amount of funds requested from the network for the transaction. - : The amount of funds approved and posted to the Highnote ledger for the transaction. ### Approvals Authorizations are decisioned by Highnote based on your card product logic and settings. They can be approved or denied based on several factors. You can participate in the authorization flow using Collaborative Authorization. Collaborative authorization allows you to approve or decline the transaction before it reaches Highnote for decisioning. When a transaction is approved, Highnote typically returns an response code. For a full list of transaction response codes, see the API Reference. ### Declines Declines occur for several reasons, including but not limited to the following common decline reasons: - Insufficient funds in the account holder's financial account - Incorrect PIN or CVV - Expired payment card When an authorization is declined, the merchant will receive a response code for the decline reason. These response codes are typically used by the merchant and displayed to the cardholder. For a full list of transaction response codes, see the API Reference. ### Other types of authorizations In some scenarios, other types of authorizations may take place. The following table provides examples of other authorization types: | Type | Description | | :------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Pre-authorization | An authorization that acts as a hold for a specific amount of funds. | | Automated Fuel Dispenser (AFD) transactions | Automated fuel dispensers (AFDs) typically have an authorization amount defined by card product or network rules. | | $0 authorization | Merchants may send an authorization for a zero dollar amount to validate card details. This authorization typically happens when a card is saved for future payments. | ### Pending funds When an authorization is approved, it acts as a hold for the authorized amount. Typically, funds on hold are displayed as "pending" in an application or website. Note the following about pending authorizations: - Expiration periods are set by the merchant, card product logic, or network rules; with most authorizations expiring after seven days - Some authorizations, like hotel stays or car rentals, may have longer expiration periods. - When an authorization expires, the funds are automatically decreased on the account holder's authorization ledger and increased on their cash available ledger. If you participate in authorization via Collaborative Authorization, Highnote responds to a transaction event with an to temporarily fund the requested authorization until your collaborative authorization response is received. ## Reversal events Reversal logic is defined by the card network (not Highnote) and can vary across different merchants. Once reversal conditions are met—for example, an authorization expires—Highnote executes the appropriate reversal action, ensuring the transaction is canceled in accordance with the established network rules, merchant configurations, and scenario-specific requirements. Reversals are used when a transaction needs to be canceled. Reversals can be done for the full amount of the transaction or a partial amount. Reversals typically occur in the following scenarios: - An authorization expires before clearing - An item is out of stock - A transaction is identified as fraud - The cardholder cancels their order before a clearing event occurs - The original authorization is no longer valid - A duplicate transaction occurred - Disputed transactions - Merchant error If a reversal occurs after an authorization-and-clear transaction, the transaction has already cleared and settled. Treat these reversals as refunds in your system; the cardholder receives a credit rather than a release of held funds. ## Clearing events Once an authorization event is confirmed, a clearing event takes place to transfer the funds from the account holder's financial account to the merchant. When the funds are transferred, the account holder's authorization ledger is updated and the cash ledger is decreased. Note the following about clearing events: - Most clearing events are associated with an authorization event. - If a clearing event is received without an authorization event, this is called a "forced post". Highnote monitors these types of clearing events to ensure fraud is not occurring. ### How Highnote links clearing events to authorizations Highnote does not force-link events when the network identifiers do not align. Highnote links clearing events to their corresponding authorization events using network-provided identifiers, such as the Visa transaction ID and settlement date for Visa transactions, or the Banknet Reference Number and other identifiers for Mastercard and Mastercard Networks Exchange (NEX) transactions. In rare cases, the network-provided identifiers on the clearing event do not match the authorization event. When this happens, the clearing event is not linked to the authorization and appears as a separate transaction event. Do not rely solely on network reference IDs to correlate authorization and clearing events. Network identifiers are not guaranteed to be consistent across the lifecycle of a transaction. ## Adjustment events Adjustment events are post-clearing corrections issued by the card network that modify a previously cleared transaction. Unlike reversals, which cancel a pending authorization, adjustments apply after a transaction has fully cleared and settled. Adjustments can be either debits or credits: - **Adjustment credit** (): Returns funds to the cardholder's account. For example, a network-initiated correction for an overcharge. - **Adjustment debit** (): Removes additional funds from the cardholder's account. For example, a correction for an undercharge. When an adjustment occurs, Highnote sends a notification event with a payload. The field indicates whether the adjustment is a credit or debit. See Payment card adjustment in the events reference for an example payload. ## Refunds Refunds occur when a merchant refunds a purchase that has already cleared. Refunds are typically sent in the following ways: - The merchant sends a new authorization event with the refund amount provided as a credit - The merchant sends a clearing event with no authorization for the amount to be refunded as a credit - The merchant sends an authorization and clearing event for the amount to be refunded as a credit ### Reconciling refunds Do not assume a one-to-one mapping between refund values and original purchases. Transaction IDs do not always map one-to-one with purchases when processing refunds: - **Unlinked refunds:** The network may send refund events with different IDs from the original authorization, or without a reference to the original transaction at all. In these cases, the refund appears as a standalone credit on the cardholder's account. - **Grouped refunds:** When the card network assigns the same network transaction ID to multiple refund clearing events, Highnote groups them under a single . This can happen when refunds for different original purchases are batched together by the network. Use individual values to reconcile refunds against original charges. ## Simulate transactions Refer to the following guides to simulate transactions using the Highnote API: - For all card products, except fleet: Simulate Transactions - For fleet card products: Simulate Fleet Transactions ## Common message sequences In addition to the transaction happy paths: - (single) - → (dual) ... there are other paths that a transaction can take. The following table lists some of the most common transaction message sequences. Sequences are not mutually exclusive and can overlap. | Message Sequence | Description | | :------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------- | | **Single message** | | | | Debit card transaction, ATM & PIN purchase | | **Dual message** | | | → | Normal purchase transaction | | → (higher / lower) | Normal purchase transaction (with tips, &c.) | | **Pre-auth / Incremental auth** | | | → (incremental auth) → | Pre-authorization and incremental authorization | | **Authorization advice** | | | → (advice) → | AFD transaction with optional auth advice | | → (advice - timeout) → (advice – stand-in approved) → | Auth timeout → network stand-in **approved** | | → (advice - timeout) → (advice – stand-in declined) | Auth timeout → network stand-in **declined** | | (approved) → (advice - timeout) → (advice - stand-in declined) → (stand-in) | Network stand-in declined → auth timeout → stand-in **reversal** | | **Multiple clearing** | | | → (1st) → (final) | Multiple clearing | | → (final) → (1st) | Multiple clearing – out of order | | → (1st) → (by auth exp job) | Multiple clearing but final clear never received | | **Reversal** | | | → | Specific use case, such as broken ATM | | → | Authorization and reversal authorization | | → (partial) → | Partial reversal before clearing | | → (by auth expiration job) | Auth without clear or reversal - expiration job triggered | | **Credit** | | | (CREDIT) → (CREDIT) | Refund, but with authorize first | | (CREDIT) → (CREDIT) | Cancelled refund, but with authorize first and reversal | | → → (CREDIT) | Auth & clear, then refund w/same RRN & STAN (that can be reversed by auth expiration job) | | **Clearing only** | | | | Force clear | | (CREDIT) | Usually refund | | (no account found) | Force clear into Highnote force clear account | | **Other** | | | | Check current available balance in Financial Account | | | Verify account, usually with transaction amount $0 | --- URL: https://docs.highnote.com/docs/acquiring/about-acquiring Title: About Acquiring Payments Section: Acquiring Description: Accept payments with the Highnote acquiring platform using tokenized or PCI SAQ-D compliant integration paths. Supports one-time, recurring, and digital wallet payments. ## Overview The Highnote platform lets you accept and disburse payments with full control, regardless of payment method. Whether you want to accept one-time payments online, set up recurring payments, or process digital wallet payments, the Highnote API enables seamless and dependable payment processing directly from your website or mobile application. ## PCI Compliance To accept online payments, you must create a payment form for your website or application that lets customers input their sensitive data securely. To maintain PCI SAQ-A compliance, we recommend building your payment form with the Highnote Secure Inputs SDK, which uses client tokens for its GraphQL API requests. ## Acquiring sequence flow with tokenization To maintain PCI SAQ-A compliance, you must tokenize customer data. Tokenizing customer data ensures that PCI data does not cross your server. The Highnote Secure Inputs SDK handles the input of customer PCI payment card data and submits it to Highnote’s API directly. This workflow keeps you PCI SAQ-A compliant. The following graphic outlines the acquiring sequence flow _with tokenization_: ## Acquiring sequence flow without tokenization Merchants that are PCI SAQ-D compliant and securely store PCI data already, can choose to bypass tokenization by directly charging payment card data. The following graphic outlines the acquiring sequence flow _without tokenization_: ## Key concepts Highnote acquiring APIs use the following foundational objects to manage your payments: | Concept | Definition | | :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Acquiring Bank | Financial institution that sponsors Bank Identification Numbers (BIN), handles money movement, underwriting, and facilitates communication in electronic payment transactions | | Merchant Settlement Financial Account | Type of Highnote Ledger account that tracks all of your organization’s acquiring transaction funds. | | Merchant Identification Number (MID) | 15-digit numerical value defined by Highnote that uniquely identifies your business for facilitating credit and debit card payments | | Merchant Acceptor | Defines the device and/or method that accepts the details necessary to initiate a payment transaction (e.g., POS or virtual terminal). | | Payment Transaction | Object that captures the intent of a transaction and its details, including the relevant amounts, line items of products/services, and instructions. Transactions are either purchase or credit events. | | Financial Transaction Event | Events corresponding to each step in the payment transaction lifecycle. Events are immutable, meaning they can't be changed. But events can be compensated--e.g., if a occurs, you can cancel the event, resulting in a . | | Financial Instrument | Object that defines the mechanism used for the payment transaction, such as card payments and ACH | | Disbursement | Step in the payment transaction lifecycle where funds due to a merchant account are calculated and paid out, including fees and reserve amounts | | Payout | Step in the payment transaction lifecycle where available funds are moved from Highnote to a Merchant Account. | | Descriptor | Highnote-defined alphanumeric value that identifies your business in each payment transaction. | ## Payment transaction states Highnote's Acquiring product follows a payment transaction lifecycle that provides information about each step. For each step in the payment transaction lifecycle, there are corresponding financial transaction events that take place. The following graphic outlines the payment transaction states in Highnote's acquiring flow: ## Payment schedule Payments on the Highnote platform adhere to the following schedules. ### Network settlement times The settlement cutoff times for each card network: | Network | Time | | :--------------- | :------------------------------ | | Visa | 1 am Pacific Time (PST/PDT) | | Mastercard | 4 am Pacific Time (PST/PDT) | | Discover | 9 pm Pacific Time (PST/PDT) | | American Express | 11:30 pm Pacific Time (PST/PDT) | ### Money movement The time it takes for funds to move from the acquiring bank via Highnote to the cardholder: | Day | Event | | :---- | :--------------------------------------------------------------------------------------------------------- | | Day 0 | Transaction occurs | | Day 1 | Networks deposit funds to the acquiring bank at 6:30 am Pacific Time (PST/PDT). | | | If funds reconcile on Highnote's daily ledger, Highnote triggers the disbursement. | | | If transaction is successful, cardholder has funds by 4-5 pm Pacific Time (PST/PDT) the next business day. | ## Card transaction lifecycle A typical card payment transaction has the following steps. Financial transaction events associated with each step are done synchronously in the Highnote platform: | Payment Transaction Step | Financial Transaction Event | Description | | :------------------------------- | :------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | | CardAuthorizationStep | | Record of a payment transaction authorizing an amount using a | | | CardPaymentAuthorizedEvent | Represents a card payment authorization event within the Highnote platform. | | CardIncrementalAuthorizationStep | | Record of a payment transaction authorizing an additional amount beyond the initial authorized amount using a . | | | CardPaymentIncrementalAuthorizedEvent | Represents a card payment incremental authorized event within the Highnote platform. | | CardReversalStep | | Record of a payment transaction authorization being canceled. | | | CardPaymentReversedEvent | Represents a card payment reversal event within the Highnote platform. | | CardCaptureStep | | Record of a payment transaction capturing an amount with a payment method. | | | CardPaymentIncrementalAuthorizedEvent _(Optional)_ | Represents a card payment incremental authorized event within the Highnote platform. | | | CardPaymentPartialReversedEvent _(Optional)_ | Represents a card payment partial reversal event within the Highnote platform. | | | CardPaymentCapturingEvent | Represents a card payment capturing event within the Highnote platform. | | | CardPaymentCaptureProcessingEvent | Represents a card payment capture processing event within the Highnote platform. | | | CardPaymentClearedEvent | Represents a card payment settled event within the Highnote platform. | | | CardPaymentDisbursedEvent | Represents a card payment disbursement event within the Highnote platform. | | | CardPaymentPayoutEvent | Represents a disbursement payout event for a PaymentTransaction. | | | PayoutTransferCompletedEvent | Represents a completed payout transfer event for a PaymentTransaction. | ## Held authorizations Most card authorizations resolve immediately to an approved or declined outcome. In some cases, an authorization is instead accepted into a non-terminal _held_ state where Highnote has received the request, but the final outcome is still pending. A held authorization resolves to a final approved or reversed state automatically, with no cardholder action required. A reversed authorization releases the hold and is not captured. The transaction remains queryable, recorded as held then reversed. A held authorization surfaces as a [](/docs/api-reference/object#CardPaymentAuthorizationHeldEvent) in the payment transaction's event timeline. Its field ([](/docs/api-reference/enum#PaymentTransactionHoldReason)) tells you why the authorization is held: - : Highnote is waiting for a response from the processor or network. - : Highnote is resolving an issue internally. A held authorization is non-terminal. Query the parent [](/docs/api-reference/interface#PaymentTransaction) to observe the held event in its timeline, then watch for the transaction to resolve to a final approved or reversed outcome. No additional request is required to move it forward. Highnote resolves the hold automatically. A held authorization has already been accepted. Submitting it again creates a duplicate authorization. If you need to retry a request, reuse the original idempotency key so Highnote returns the existing held transaction instead of authorizing a second time. Instant Network Transfers use the same held-then-resolve pattern. The transfer itself reports the hold through two [](/docs/api-reference/enum#InstantNetworkTransferStatus) values rather than a held event of its own, while the internal transfer's linked [](/docs/api-reference/interface#PaymentTransaction) shows the held event. ## GraphQL summary responses To keep Highnote's Acquiring API response time low, we return objects from our mutations. These summary objects contain simplified data about your request. Refer to the Card transaction lifecycle. ### Query for CardAuthorizedStepSummary To get a full version of a summary object, query for and then query for . Use the following query to return a : ### Query for CardCaptureStepSummary Use the following query to return a : ## Amount precision The Amount object represents monetary values using two fields: - — An integer representing the amount (avoids floating-point precision errors) - — Indicates where to place the decimal point To calculate the display amount: ```text displayAmount = value / (10 ^ decimalPlaces) ``` | value | decimalPlaces | Display Amount | | :---- | :------------ | :------------- | | 15000 | 2 | $150.00 | | 165 | 4 | $0.0165 | The API returns based on the precision required for each value. Standard transactions use 2 decimal places (cents), while interchange fees, splits, and percentage-based calculations may use up to 6 decimal places for sub-cent precision. ### Example Acquiring often requires higher precision than issuing. For example, a 1.5% interchange fee on a $1.10 transaction is $0.0165: ```text 1.10 * 0.015 = 0.0165 ``` In the following response, the API returns for the interchange amount, indicating the of should display as : ### GraphQL: CardAuthorizationStepSummary Query: mutation AuthorizePaymentTransaction( $input: AuthorizePaymentTransactionInput! ) { authorizePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardAuthorizationStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentMethodToken": { "id": "" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "authorizePaymentTransaction": { "__typename": "CardAuthorizationStepSummary", "createdAt": "2024-02-22T17:26:20.474Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:26:20.474Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "Q5Z539", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: CardCaptureStepSummary Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentMethodToken": { "id": "" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2024-02-22T17:26:20.474Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:26:20.474Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "978647564526179", "responseCode": { "authorizationCode": "Q5Z539", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: DisbursementEventWithPrecisionAmounts Query: query DisbursementEventWithPrecisionAmounts($id: ID!) { node(id: $id) { ... on DisbursementTransferEvent { eventType createdAt amount { currencyCode value decimalPlaces } } } } Variables: { "id": "indev_1" } Expected Result: { "node": { "__typename": "DisbursementTransferEvent", "eventType": "DISBURSEMENT_INTERCHANGE_FEE", "createdAt": "2024-01-01T00:00:00Z", "amount": { "currency": "USD", "value": "165", "decimalPlaces": "4" } } } --- URL: https://docs.highnote.com/docs/acquiring/disputes/about-disputes Title: About Disputes Section: Acquiring Description: Understand acquiring disputes: how chargebacks begin, the four dispute categories, and the stages from chargeback to arbitration. ## Overview Highnote's Acquiring Disputes solution handles the merchant side of payment disputes. Highnote categorizes each dispute into one of **four categories**: consumer dispute, processing error, fraud, and invalid authorization. A dispute begins when a cardholder contests a payment, and their bank (the issuing bank) sends a chargeback to the card network. The merchant can accept or challenge the dispute by presenting evidence. A dispute can resolve at any one of **five stages** or escalate through representment, pre-arbitration, pre-arbitration response, and arbitration before reaching a final outcome. ## Dispute categories Highnote disputes fall into one of four categories. Contest consumer disputes and processing errors with an evidence questionnaire, supporting documents, or both: - **Consumer dispute**: The cardholder recognizes the transaction but disputes what they received—for example, goods or services not received, defective or not as described, a cancelled recurring charge, or a refund never processed. Contest with the consumer dispute questionnaire, supporting documents, or both. - **Processing error**: The transaction was processed incorrectly—for example, an incorrect amount or currency, duplicate processing, or the cardholder paid by other means. Contest with the processing error questionnaire, supporting documents, or both. Contest fraud and invalid authorizations with supporting documents only—these categories have no questionnaire to answer. - **Fraud**: The cardholder claims they didn't authorize or participate in the transaction—for example, a stolen or counterfeit card, or activity flagged by the network's fraud monitoring program. Contest with supporting documents; there is no structured questionnaire. - **Invalid authorization**: The transaction was processed without a required or valid authorization—for example, authorization was declined or never obtained. Contest with supporting documents; there is no structured questionnaire. Each category maps to a set of network reason codes and, where applicable, a category-specific evidence questionnaire. For network mapping, see Network reason codes. ## Dispute stages Highnote surfaces each dispute as a [](/docs/api-reference/object#CardPaymentDispute) object that progresses through a sequence of stages: 1. **Chargeback**: The cardholder disputes the transaction with their issuing bank. 2. **Representment**: The merchant rebuts the chargeback with a **_second_** presentment of evidence. _The **first** presentment is the acquirer's original transaction to the issuer for settlement._ 3. **Pre-arbitration**: Either party—issuer or merchant—challenges the dispute's current outcome. 4. **Pre-arbitration response**: The party that did not initiate pre-arbitration responds, partially accepting the claim or contesting it. 5. **Arbitration**: The card network reviews the case and makes a binding decision. Highnote notifies you of dispute activity through the family of webhook events. See Monitoring Disputes. For the ways a dispute can resolve at each stage, see How disputes resolve. --- URL: https://docs.highnote.com/docs/acquiring/disputes/api-sequence-diagram Title: API Sequence Diagram Section: Acquiring Description: API sequence diagram of the five acquiring dispute stages, with Visa's allocation and collaboration workflow differences. ## Overview The following API sequence diagram depicts the entire dispute process across all five stages. The diagram shows the issuer initiating pre-arbitration; either party can initiate, and the party that did not initiate responds. ## Network differences Highnote models every dispute as the same sequence of stages regardless of card network. Underneath, the networks run different workflows. **Mastercard** disputes follow the single normalized lifecycle described above. **Visa** routes each dispute into one of two workflows based on its category: - **Fraud and authorization disputes**. Visa rules on the dispute at filing and allocates liability. _There is no representment stage._ The merchant's remedy is pre-arbitration, and arbitration follows if the outcome is still contested. - **Processing-error and consumer disputes**. The issuer and merchant work the dispute between themselves through representment and pre-arbitration. Visa decides the outcome only if the dispute escalates to arbitration. --- URL: https://docs.highnote.com/docs/acquiring/disputes/categories-stages Title: Categories and Stages Section: Acquiring Description: Reference for acquiring dispute categories, dispute and stage statuses, stage response windows, and the category-stage status matrix. ## Overview Highnote disputes fall into four categories and progress through up to five stages. Each dispute carries a status, as does each stage. For example, a consumer dispute in the representment stage is as a whole, while its representment stage is , and its chargeback stage is . For all dispute/stage status possibilities, see the category-stage status matrix below. ## Disputes A dispute's category and status describe it as a whole. The category classifies what the cardholder claims and determines how you contest it; the status tracks the dispute's progress and outcome. ### Dispute categories Every dispute is assigned one of four [](/docs/api-reference/enum#CardPaymentDisputeCategory) values: | Category | Description | | :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | | | Dispute categorized as a consumer dispute. Has an optional questionnaire. | | | Dispute categorized as a processing error. Has an optional questionnaire. | | | Dispute categorized as fraud. | | | Dispute categorized as an authorization issue. | Each category maps to a set of network reason codes and, where applicable, a category-specific evidence questionnaire. See Network Reason Codes for the code tables and Evidence Questionnaires for the questionnaire reference. ### Dispute statuses The overall dispute carries a [](/docs/api-reference/enum#CardPaymentDisputeStatus) that reflects where the dispute stands as a whole: | Status | Meaning | | :------------------ | :-------------------------------------------------------------------------------- | | | Dispute has been initiated. | | | Dispute is in review. | | | Dispute has timed out due to inaction. | | | Dispute has been withdrawn by the party that created it. | | | Dispute is closed. | | | Issuer accepts responsibility for the dispute. Resolved in favor of the merchant. | | | Merchant accepts responsibility for the dispute. Resolved in favor of the issuer. | ## Stages A dispute progresses through one to five stages—either party can accept the loss at any stage, and some network workflows skip stages entirely. Visa fraud and authorization disputes, for example, have no representment stage; see Network differences. Stages are exposed as objects implementing the [](/docs/api-reference/interface#CardPaymentDisputeStage) interface: | Stage | What it represents | | :---------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [](/docs/api-reference/object#CardPaymentDisputeChargebackStage) | The first stage of the dispute where the cardholder, via their issuing bank, disputes a transaction. | | [](/docs/api-reference/object#CardPaymentDisputeRepresentmentStage) | The acquiring merchant challenges the issuer's chargeback by submitting further evidence. | | [](/docs/api-reference/object#CardPaymentDisputePreArbitrationStage) | Either party—issuer or merchant—escalates the dispute after representment. | | Pre-Arbitration Response | The party that did not initiate pre-arbitration responds—a partial acceptance or a denial contesting the claim. The last opportunity to resolve the dispute without network intervention and arbitration. | | [](/docs/api-reference/object#CardPaymentDisputeArbitrationStage) | The final stage, where the card network makes a binding decision. | ### Stage statuses Each stage of the dispute tracks its own [](/docs/api-reference/enum#CardPaymentDisputeStageStatus), independent of the overall dispute status: | Status | Meaning | | :------------ | :------------------------------------- | | | The stage is awaiting action. | | | The stage is actively being worked on. | | | The stage has been completed. | | | The stage has expired without action. | ### Stage response windows Every stage carries a deadline field: | Field | Type | Description | | :-------------- | :---------------- | :--------------------------- | | | String (ISO-8601) | The deadline for a response. | Missing a response deadline typically results in the dispute closing against the merchant. ### How disputes resolve A dispute resolves in one of three ways—a party accepts the loss, a response window lapses, or the card network rules at arbitration. - **Chargeback**: The merchant accepts the chargeback, resolving the dispute in the issuer's favor. - **Representment**: The issuer accepts the merchant's evidence, resolving the dispute in the merchant's favor. - **Pre-arbitration**: The party that did not initiate pre-arbitration accepts the claim in full. - **Pre-arbitration response**: The initiating party accepts the response—in a partial acceptance, a portion of the disputed amount resolves in each party's favor. This is the last opportunity to resolve the dispute without network intervention. - **Arbitration**: The card network's binding decision resolves the dispute—won, lost, or partially won for the merchant. At any stage before arbitration, a dispute can also resolve by timeout—miss a response window and the dispute typically closes against the merchant. When a dispute concludes, its final outcome surfaces on the field as a [](/docs/api-reference/enum#CardPaymentDisputeOutcome): , , or , from the merchant's perspective. ## Category-stage status matrix The dispute and stage statuses move together—a dispute under review has exactly one stage in progress, and every stage in its history is completed: | Stage status →
Dispute status ↓ | | | | | | :----------------------------------- | :-------------------------- | :-------------------- | :---------------------- | :-------- | | | Chargeback stage (creation) | — | — | — | | | — | The active stage | All earlier stages | — | | | — | — | All stages | — | | | — | — | All stages | — | | | — | — | — | — | | | — | — | — | — | | | — | Final stage (timeout) | All stages (acceptance) | — | Read the matrix as follows: - A live dispute is with exactly one stage ; every earlier stage in the dispute's history is . - A resolved dispute is , , or with all stages —with one exception: a dispute that closes because a response window lapsed may keep its final stage . - and are transitional: a new dispute typically advances to as it is created—though a query can catch it earlier, as with a chargeback stage—and a timed-out dispute typically advances to . Both also appear in dispute webhook events along the way. - An em-dash marks a combination without a documented pattern, not one that cannot occur. , for example, is the stage-level counterpart of a lapsed response window, and has a matching webhook event. Handle every defined value in your code rather than treating any status as unreachable. --- URL: https://docs.highnote.com/docs/acquiring/disputes/accepting Title: Accepting Disputes Section: Acquiring Description: Accept an acquiring dispute with acceptAndFinalizeCardPaymentDispute, resolving it in favor of the issuer for the full disputed amount. ## Overview Accepting a dispute resolves it in favor of the issuer: the dispute moves to the terminal [](/docs/acquiring/disputes/categories-stages#dispute-statuses) status, and all of its stages complete. You can accept at any active stage, before the stage's response window () lapses. Acceptance is always for the full disputed amount—the mutation takes only the dispute ID. To contest part of the amount instead, submit evidence with a [](/docs/acquiring/disputes/challenging#submit-evidence). ## Accept a dispute Accept a dispute by passing its ID to : ```graphql mutation AcceptAndFinalizeCardPaymentDispute( $input: AcceptAndFinalizeCardPaymentDisputeInput! ) { acceptAndFinalizeCardPaymentDispute(input: $input) { ... on CardPaymentDispute { id cardPaymentDisputeStatus } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } ``` --- URL: https://docs.highnote.com/docs/acquiring/disputes/challenging Title: Challenging Disputes Section: Acquiring Description: Challenge an acquiring dispute through the API: upload evidence to the active stage, answer the category's questionnaire, and submit your response. ## Overview Challenging a dispute means contesting it with evidence instead of accepting the loss. The flow has two parts: upload each evidence file to the dispute's active stage, then submit the evidence to finalize your response. What you submit depends on the dispute's category. Fraud and authorization disputes take supporting documents only, while processing-error and consumer disputes can also carry an optional category-specific questionnaire. Carry at least one of: a completed document on the active stage, questionnaire answers, or a . ## Upload evidence Uploading evidence starts by opening a session scoped to the dispute's active stage. Then, for each file, create an upload link, the file to the link, and confirm the upload completed. ### Open an evidence upload session Open a session for the dispute's active stage by passing the dispute's ID () to : ```graphql mutation InitiateCardPaymentDisputeEvidenceUpload( $input: InitiateCardPaymentDisputeEvidenceUploadInput! ) { initiateCardPaymentDisputeEvidenceUpload(input: $input) { ... on CardPaymentDisputeEvidenceUploadSession { documentUploadSessionId expiresAt } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } ``` ### Create an upload link Pass the session's and the file's to [](/docs/api-reference/mutation#createDocumentUploadLink) to create a link for each file: ```graphql mutation CreateDocumentUploadLink($input: CreateDocumentUploadLinkInput!) { createDocumentUploadLink(input: $input) { ... on DocumentUploadLink { id uploadUrl } ... on UserError { errors { code description } } } } ``` ### Upload the file the file's raw bytes to the link's , with set to the file's MIME type. The URL is signed—no header is needed. The maximum file size is 10 MB, and each link accepts a single file. ```bash curl -X PUT "UPLOAD_URL" \ -H "Content-Type: image/jpeg" \ --data-binary "@evidence.jpg" ``` Upload links expire 5 minutes after creation. If a link expires before you upload, create a new one. ### Check upload status Uploaded files are scanned before they are stored. Check each [](/docs/api-reference/object#DocumentUploadLink)'s with a query: ```graphql query CheckDocumentUploadLink($id: ID!) { node(id: $id) { ... on DocumentUploadLink { id status documentType updatedAt } } } ``` | Status | Description | | :------------ | :------------------------------------------------------------------------------------ | | | The link is waiting for a file to be uploaded. | | | The upload is being processed. | | | The file uploaded successfully and is securely stored. | | | The file was rejected by the malware scan. Create a new link and upload a clean file. | | | The upload failed due to a server communication error. Retry the upload. | Confirm every file's link reports before submitting the evidence. ## Submit evidence Finalize the uploaded evidence with . This closes the upload session. No further evidence can be added to the stage afterward. A representment with no questionnaire answers, no , and no completed document returns a with code . The error is not retriable. Upload at least one document, or provide questionnaire answers or a , then submit again. To see which questionnaire fields a stage still wants answered, read its . The questionnaire action's is a [](/docs/api-reference/object#CardPaymentDisputeStageQuestionnaireActionDetails), and its lists them as [](/docs/api-reference/enum#DisputeQuestionnaireField) values. Answer what you can in when you submit—the API accepts a partial questionnaire. ```graphql mutation SubmitCardPaymentDisputeEvidence( $input: SubmitCardPaymentDisputeEvidenceInput! ) { submitCardPaymentDisputeEvidence(input: $input) { ... on CardPaymentDispute { id cardPaymentDisputeStatus } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } ``` | Field | Type | Description | | :---------------------- | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | ID! | The whose active stage's uploaded evidence is finalized. | | | DisputeQuestionnaireInput | Optional. Answers for the category's evidence questionnaire. Provide exactly one variant. See Evidence Questionnaires. | | | AmountInput | Optional. The portion of the disputed amount to contest. Omit to contest the full amount. Must be less than the active stage's . | | | String | Optional. A free-text note forwarded to the card network with your response. | --- URL: https://docs.highnote.com/docs/acquiring/disputes/monitoring Title: Monitoring Disputes Section: Acquiring Description: Observe acquiring disputes and their lifecycle stages through the CardPaymentDispute read model and webhook events, and track each dispute's financial impact. ## Overview Subscribers observe acquiring disputes through three mechanisms: - Subscribing to webhook events using the events family. - Looking up [](/docs/api-reference/object#CardPaymentDispute) by ID. - Listing your organization's disputes with the connection. ## Watch for dispute activity Subscribe to events to track a dispute's lifecycle transitions. Each fires when the dispute reaches the matching [](/docs/acquiring/disputes/categories-stages#dispute-statuses). Subscribe to for disputes that need a response from you. The payload's , when set, carries the final result. ## Find a dispute Look up a dispute directly with , using the dispute ID from a webhook payload: On , the field is restricted to the Highnote Dashboard and is not available to a subscriber API key. Every other field, including and each stage's , resolves normally. ## List disputes List your organization's disputes with the connection. Results are paginated: pass , page with , and narrow the results with . ```graphql query ListCardPaymentDisputes { organizations { cardPaymentDisputes(first: 20) { pageInfo { hasNextPage endCursor startCursor } edges { node { id cardPaymentDisputeStatus } } } } } ``` ## Track financial impact Highnote tracks the merchant's financial impact of a dispute on the field on [](/docs/api-reference/object#CardPaymentDispute). Use with your transaction and ledger activity as the authoritative source for a given dispute's financial state. Exact fund movement timing depends on the dispute's network, as well as category and stage. For the full field-by-field breakdown of dispute categories, stages, and status values, see Categories and Stages. For the evidence questionnaire fields returned on each stage, see Evidence Questionnaires. ### GraphQL: Find a Dispute Query: query NodeCardPaymentDispute($id: ID!) { node(id: $id) { __typename ... on CardPaymentDispute { id cardPaymentDisputeStatus category merchantIdentifier initiatedAt closedAt financialImpact { value decimalPlaces currencyCode } networkCaseIdentifier networkReason { code description } transactionEvent { acquirerReferenceNumber createdAt } stages { __typename status amount { value decimalPlaces currencyCode } startedAt responseDueAt completedAt questionnaire { __typename } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "CardPaymentDispute", "id": "", "cardPaymentDisputeStatus": "IN_REVIEW", "category": "CONSUMER_DISPUTE", "merchantIdentifier": "", "initiatedAt": "1970-01-01T00:01:00.000Z", "closedAt": null, "financialImpact": { "value": 5000, "decimalPlaces": 2, "currencyCode": "USD" }, "networkCaseIdentifier": "", "networkReason": { "code": "13.1", "description": "Reason provided by the card network." }, "transactionEvent": { "acquirerReferenceNumber": "24445551234567890123456", "createdAt": "1970-01-01T00:00:30.000Z" }, "stages": [ { "__typename": "CardPaymentDisputeChargebackStage", "status": "COMPLETED", "amount": { "value": 5000, "decimalPlaces": 2, "currencyCode": "USD" }, "startedAt": "1970-01-01T00:01:00.000Z", "responseDueAt": "1970-01-01T00:11:00.000Z", "completedAt": "1970-01-01T00:05:00.000Z", "questionnaire": null }, { "__typename": "CardPaymentDisputeRepresentmentStage", "status": "IN_PROGRESS", "amount": { "value": 5000, "decimalPlaces": 2, "currencyCode": "USD" }, "startedAt": "1970-01-01T00:05:00.000Z", "responseDueAt": "1970-01-01T00:15:00.000Z", "completedAt": null, "questionnaire": { "__typename": "ConsumerDisputeQuestionnaire" } } ] } } } --- URL: https://docs.highnote.com/docs/acquiring/disputes/questionnaires Title: Evidence Questionnaires Section: Acquiring Description: Field-by-field reference for acquiring dispute evidence questionnaires: ProcessingErrorQuestionnaire, ConsumerDisputeQuestionnaire, and their supporting enums. ## Overview The [](/docs/api-reference/interface#CardPaymentDisputeStage) field on a stage returns the [](/docs/api-reference/union#DisputeQuestionnaire) union or for categories with no questionnaire. Every questionnaire field is optional. An unanswered field is , which for boolean fields is distinct from an explicit . A questionnaire action on a stage lists the fields still requested for that stage, identified by the [](/docs/api-reference/enum#DisputeQuestionnaireField) enum. Answering the fields the stage requested makes for a stronger representment. Submitting answers is covered in Challenging Disputes. A representment cannot be empty, and must carry either a questionnaire (answers, a submission note, or both) or at least one document whose upload reached on the active stage. Otherwise, it is rejected with a non-retriable error. The API does not enforce individual requested fields; a partial questionnaire is accepted. | Category | Questionnaire | | :---------------------- | :---------------------------------------------------------------------------------------- | | | [](/docs/api-reference/object#ConsumerDisputeQuestionnaire) | | | [](/docs/api-reference/object#ProcessingErrorQuestionnaire) | | | None. Fraud disputes don't use a structured questionnaire. | | | None. Authorization disputes don't use a structured questionnaire. | ## Consumer dispute questionnaire | Field | Type | Description | | :-------------------------- | :-------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- | | | String | Description of the product or service involved in the disputed transaction. | | | String | Explanation of how the goods or services differed from what was described. | | | String | Description of the goods or services the cardholder actually received. | | | String | The claim or representation the merchant advertised about the goods or services. | | | String | The relevant terms of the contract or agreement governing the transaction. | | | String | Confirmation reference for a cancellation, such as a confirmation number. | | | String | The address the goods were shipped to. | | | Boolean | Whether the cardholder attempted to return the goods. | | | Boolean | Whether the cardholder contacted the merchant before initiating the dispute. | | | Boolean | Whether the cardholder cancelled the order, service, or recurring agreement. | | | Boolean | Whether store credit was offered to the cardholder. | | | [](/docs/api-reference/enum#ProductReturnMethod) | The method by which the goods were returned. | | | [](/docs/api-reference/enum#ProductCancellationMethod) | The method by which the cancellation was requested. | | | String (ISO-8601) | The expected delivery date of the goods or services. | | | String (ISO-8601) | When the merchandise was received. | | | String (ISO-8601) | When the merchandise was returned. | | | String (ISO-8601) | When the cardholder contacted the merchant. | | | String (ISO-8601) | When the order or service was cancelled. | | | String (ISO-8601) | When the cardholder requested a refund. | | | String | The tracking number for the shipment of the goods. | ## Processing error questionnaire | Field | Type | Description | | :----------------------- | :-------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | | | String | The relevant terms of the contract or agreement governing the transaction. | | | Boolean | Whether there is proof the cardholder paid for the transaction by an alternate method. | | | [](/docs/api-reference/enum#AlternatePaymentMethod) | The alternate method by which the cardholder paid. | | | String (ISO-8601) | When the alternate payment was made. | | | String (ISO-8601) | When the cardholder requested a refund. | | | [](/docs/api-reference/object#Amount) | The amount paid via the alternate payment method. | ## Supporting enums - [](/docs/api-reference/enum#AlternatePaymentMethod): the alternate method by which a cardholder paid for a transaction. - - - - - - [](/docs/api-reference/enum#ProductReturnMethod): the method by which goods were returned to the merchant. - - - - [](/docs/api-reference/enum#ProductCancellationMethod): the method by which a cancellation was requested. - - - - - - --- URL: https://docs.highnote.com/docs/acquiring/disputes/reason-codes Title: Network Reason Codes Section: Acquiring Description: How Visa and Mastercard dispute reason codes map to Highnote's four acquiring dispute categories, with full code tables for each network. ## Overview This page covers the network reason code carried on every dispute and how each code maps to a [](/docs/api-reference/enum#CardPaymentDisputeCategory). See Dispute categories for the four category values. ## Network reason codes Every dispute carries a [](/docs/api-reference/object#CardPaymentDisputeNetworkReason) reflecting the reason the card network gave for the dispute: | Field | Type | Description | | :------------ | :----- | :--------------------------------------------- | | | String | The network-specific reason code. | | | String | Human-readable description of the reason code. | is the network's own value; is Highnote's human-readable text for that code. Use to branch your evidence logic, and for display and audit purposes. ### Visa Visa organizes its dispute conditions into four numbered categories—Fraud (10), Authorization (11), Processing Errors (12), and Consumer Disputes (13)—that map one-to-one to Highnote's four categories.
Visa condition codes by Highnote category | Visa code | Visa dispute condition | Highnote category | | :-------- | :------------------------------------------------- | :---------------------- | | 10.1 | EMV Liability Shift Counterfeit Fraud | | | 10.2 | EMV Liability Shift Non-Counterfeit Fraud | | | 10.3 | Other Fraud—Card-Present Environment | | | 10.4 | Other Fraud—Card-Absent Environment | | | 10.5 | Visa Fraud Monitoring Program | | | 11.1 | Card Recovery Bulletin | | | 11.2 | Declined Authorization | | | 11.3 | No Authorization/Late Presentment | | | 12.1 | Late Presentment | | | 12.2 | Incorrect Transaction Code | | | 12.3 | Incorrect Currency | | | 12.4 | Incorrect Account Number | | | 12.5 | Incorrect Amount | | | 12.6.1 | Duplicate Processing | | | 12.6.2 | Paid by Other Means | | | 12.7 | Invalid Data | | | 13.1 | Merchandise/Services Not Received | | | 13.2 | Cancelled Recurring Transaction | | | 13.3 | Not as Described or Defective Merchandise/Services | | | 13.4 | Counterfeit Merchandise | | | 13.5 | Misrepresentation | | | 13.6 | Credit Not Processed | | | 13.7 | Cancelled Merchandise/Services | | | 13.8 | Original Credit Transaction Not Accepted | | | 13.9 | Non-Receipt of Cash or Load Transaction Value | | _For transactions completed on or after 13 April 2024, Visa retired condition 12.1 and folded late presentment into condition 11.3 (No Authorization/Late Presentment)._
### Mastercard Mastercard consolidates its chargeback reasons into a small set of message reason codes rather than numbering them by category—each code maps individually to a Highnote category. One code—4860—maps by reason: a credit not processed is a processing error, while a credit posted as a purchase is a consumer dispute.
Mastercard reason codes by Highnote category | Mastercard code | Mastercard chargeback reason | Highnote category | | :-------------- | :---------------------------------------------------------------- | :---------------------- | | 4837 | No Cardholder Authorization | | | 4849 | Questionable Merchant Activity | | | 4870 | Chip Liability Shift | | | 4871 | Chip Liability Shift—Lost/Stolen/Never Received Issue Fraud | | | 4808 | Authorization-related Chargeback | | | 4831 | Transaction Amount Differs | | | 4834 | Point-of-Interaction Error | — | | 4860 | Credit Not Processed (includes Timeshares) | | | 4841 | Canceled Recurring or Digital Goods Transactions | | | 4853 | Cardholder Dispute | | | 4855 | Goods or Services Not Provided | | | 4860 | Credit Posted as a Purchase | | | 4863 | Cardholder Does Not Recognize—Potential Fraud | |
--- URL: https://docs.highnote.com/docs/acquiring/disputes/sim-disputes Title: Simulating Disputes Section: Acquiring Description: Drive an acquiring dispute through its lifecycle in the Test environment: originate a dispute, respond to it, and simulate the issuer's decision. ## Overview To simulate a dispute: 1. Create a test dispute against a captured payment transaction. 2. Find the dispute to read its status and stages. 3. Respond to the dispute with evidence, or accept it. 4. Simulate the issuer's full acceptance, then confirm the terminal state. The mutations are available in the Test environment only. They simulate the issuer's side of a dispute so you can drive a [](/docs/api-reference/object#CardPaymentDispute) through its lifecycle and exercise your webhook handling and response flow. The acquiring dispute surface is in preview. Access is provisioned by Highnote rather than through self-serve API keys, so contact your Highnote representative to enable it for your Test organization. ## Error handling The mutations below return a payload union of , , and . See API Error Handling for the general error-handling pattern. ## Create a test dispute Originate a dispute against a captured [](/docs/api-reference/interface#PaymentTransaction) with [](/docs/api-reference/mutation#simulateIssuerInitiatesCardPaymentDispute). This gives you a dispute to test without waiting for a network file. ```graphql mutation SimulateIssuerInitiatesCardPaymentDispute( $input: SimulateIssuerInitiatesCardPaymentDisputeInput! ) { simulateIssuerInitiatesCardPaymentDispute(input: $input) { ... on CardPaymentDispute { id cardPaymentDisputeStatus category networkReason { code } stages { __typename status responsibleParty responseDueAt } } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } ``` | Field | Type | Description | | :--------------------- | :------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- | | | ID! | The payment transaction to dispute. The transaction must have been captured. | | | SimulateCardPaymentDisputeNetworkReasonCode! | The network reason for the dispute. Determines the dispute's , and must belong to the transaction's card network. | | | AmountInput! | The amount to dispute, in minor units. Must be positive, no greater than the captured amount, and in the transaction's currency. | An unknown transaction ID and a transaction that has not been captured both return . A that is not positive, exceeds the captured amount, or uses a different currency than the transaction returns . Three things about the dispute you get back are worth noting: - It opens at , not . The dispute is live from the moment you create it. - Its chargeback stage is already with , so the dispute is waiting on you immediately. Read for your window to act in. - Its is derived from the you passed. You do not set it directly. ## Find the dispute Read the dispute back to check its status and stages before you respond. See Monitoring Disputes for the by-ID lookup, and List disputes for the connection and its filters. The connection is backed by a search index, so a dispute you just created or changed can lag briefly in list results. A by-ID lookup with is always current. Prefer it when a dispute you know exists is missing from a list. ## Respond to the dispute Respond as you would to a real dispute: - To contest it, upload evidence to the active stage and submit your response. See Challenging Disputes. - To concede it, accept the dispute for the full amount. See Accepting Disputes. This closes the dispute at , so the simulated issuer actions below no longer apply. To continue this walkthrough, contest the dispute: the issuer needs a representment to accept. ## Simulate issuer acceptance Simulate the issuer accepting the full amount of the latest contested stage by passing the dispute ID to [](/docs/api-reference/mutation#simulateIssuerAcceptsFullCardPaymentDispute). This acts on a dispute that is waiting on the issuer, so submit your evidence first. Simulating acceptance before a representment exists is rejected. ```graphql mutation SimulateIssuerAcceptsFullCardPaymentDispute( $input: SimulateIssuerAcceptsFullCardPaymentDisputeInput! ) { simulateIssuerAcceptsFullCardPaymentDispute(input: $input) { ... on CardPaymentDispute { id cardPaymentDisputeStatus } ... on UserError { errors { code description } } ... on AccessDeniedError { message } } } ``` | Field | Type | Description | | :--------------------- | :--- | :------------------------------------------------------------- | | | ID! | The to drive to a full issuer acceptance. | ## Confirm the terminal state The mutation response reports the dispute's status at the time of the call, which is still with . The outcome applies a few seconds later, so read the dispute back to see its terminal state. On read-back, the dispute is with . This is a real write: the dispute closes and stays closed. populates on resolution. While a dispute is open it reads , so use the active stage's for the contested value and once the dispute reaches a terminal outcome. See Track financial impact. --- URL: https://docs.highnote.com/docs/acquiring/onboarding/business-onboarding Title: Business Onboarding Section: Acquiring Description: Onboard a business to accept card payments or move money using the createBusiness and onboardBusiness mutations. ## Overview Onboarding enrolls a business into your program so it can accept card payments, move money, or affiliate with your other businesses. Onboarding is two mutations, called in order, plus program-level setup that Highnote completes with you before you start: 1. [](#step-1-create-the-business) records the legal business entity. 2. [](#step-2-onboard-the-business) enrolls that business into your program. is one mutation with three types defined by member, of which you choose one: | Type | member | Enrolls the business to ... | | :----------------------------- | :------------------ | :------------------------------------------------------------------------- | | Acquiring | | Accept card payments | | Money movement | | Move money over payment rails | | Independent Sales Organization | | Affiliate with other businesses in your program | and work only with acquiring and money movement products. To onboard account holders for card issuing, see Onboard an Account. ## Program setup Highnote sets up your program with you before you onboard your first business. During setup, Highnote: - **Configures your application steps.** Every onboarding application runs the verification steps configured for your program — identity verification (KYC/KYB), terminated-merchant screening, and underwriting review. Which steps apply depends on the configuration set up for your program. - **Provisions your products.** Highnote sets up the products for your program and provides the values your integration passes. - **Pricing.** requires a , so pricing is in place before you onboard your first business. For the acquiring type, Merchant Pricing covers creating, simulating, and publishing a pricing plan; for money movement, your Highnote implementation team provides the pricing ID. ## How onboarding works Program setup comes first. These three steps are your integration: 1. **Create the business.** records the legal business entity and returns its ID. 2. **Onboard the business.** creates and returns a [](/docs/api-reference/object#ProductApplication), which Highnote shepherds toward approval by running your program's application steps. Once approved, Highnote provisions each capability the business requested — setting up settlement, registering with the card networks, and configuring it in the Highnote system. Provisioning steps and timelines vary by capability. 3. **Track status and start transacting.** Follow the application until the business is ready, then start transacting. ## Step 1. Create the business Use to record the legal business entity. This captures the business profile and the people associated with the business. Select these two fields in the response; each carries an ID needed in Step 2: - : The new business's ID. Pass it to Step 2 as . - : The people on the business. The person whose is is the primary authorized person; pass their to Step 2 as . ```graphql mutation CreateBusiness($input: CreateBusinessInput!) { createBusiness(input: $input) { ... on Business { id businessProfile { name { legalBusinessName doingBusinessAsName } externalId businessPersons { id isPrimary } } } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } ``` ```json { "input": { "businessProfile": { "name": { "legalBusinessName": "", "doingBusinessAsName": "" }, "businessType": "LLC", "industryType": "RETAIL_OUTLET_SERVICES", "addresses": [ { "addressType": "LEGAL", "streetAddress": "", "locality": "", "region": "", "postalCode": "", "countryCodeAlpha3": "USA" } ], "jurisdiction": { "countryOfIncorporation": "USA", "regionOfIncorporation": "US-CA" }, "taxIdentifier": { "taxIdentificationNumberType": "EMPLOYER_IDENTIFICATION_NUMBER", "number": "", "countryCodeAlpha3": "USA" }, "customerSupport": { "phone": { "number": "", "countryCode": "1", "label": "WORK" }, "email": "" } }, "businessPersons": [ { "name": { "givenName": "", "familyName": "" }, "dateOfBirth": "", "email": "", "phoneNumbers": [ { "number": "", "countryCode": "1", "label": "WORK" } ], "homeAddress": { "streetAddress": "", "locality": "", "region": "", "postalCode": "", "countryCodeAlpha3": "USA" }, "identificationDocument": { "socialSecurityNumber": { "taxIdentificationNumberType": "SOCIAL_SECURITY_NUMBER", "number": "", "countryCodeAlpha3": "USA" } }, "isPrimaryApplicant": true, "roles": ["CONTROL_PRONG", "ULTIMATE_BENEFICIAL_OWNER", "GUARANTOR"], "percentageOwnership": 100 } ], "externalId": "" } } ``` ## Step 2. Onboard the business Use to enable capabilities for the business within your program. It returns a [](/docs/api-reference/object#ProductApplication). Set exactly one member of the field — omitting it or supplying more than one throws an error. Each member nests its configuration the same way, for example : - : Onboard for acquiring - : Onboard for money movement - : Contact your Highnote representative. All member types share the same mutation and top-level inputs. All three are required: - : The returned by in Step 1. - : The ID of the pricing plan in place for your program. A business cannot be onboarded without one. See Program setup. - : The primary authorized person's agreement to the terms — their ID from Step 1, a timestamp, and the IP address the consent was given from. ```graphql mutation OnboardBusiness($input: OnboardBusinessInput!) { onboardBusiness(input: $input) { __typename ... on ProductApplication { id applicationState { status } business { id } product { ... on CardProduct { id name } } createdAt updatedAt } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } ``` ### Onboard for acquiring Supply to enroll the business to accept card payments. ##### Required fields {#acq-required-fields} - : The product to onboard the business to, from program setup. - : The networks, payment methods, merchant categories, and transaction types the business may process. Each entry takes exactly one of or . The schema accepts an application without this field, but nothing provisions and you cannot add capabilities afterward. - : The business's reported operating details and processing volumes. These must sum to 100: - + - + + ##### Optional fields {#acq-optional-fields} - : Reserve requirements withheld from the business's transactions. - selects which value applies: or . uses in basis points (so means 2%), and uses . The schema requires both on every reserve, even though only the one matching your collection method applies. - An optional caps the total collected. ```json { "input": { "businessId": "", "pricingPlanId": "", "consent": { "consentTimestamp": "", "consentIpAddress": { "v4": "" }, "primaryAuthorizedPersonId": "" }, "onboarding": { "merchant": { "productId": "", "processingCapabilities": [ { "permittedProcessingNetwork": "VISA", "permittedPaymentMethod": "CARD", "permittedMerchantCategoryCode": "5999", "permittedTransactionTypes": ["GOODS_AND_SERVICES", "RETURNS"], "acquiringProviderType": "CRB", "merchantDescriptor": "" }, { "permittedProcessingNetwork": "MASTERCARD", "permittedPaymentMethod": "CARD", "permittedMerchantCategoryCode": "5999", "permittedTransactionTypes": ["GOODS_AND_SERVICES", "RETURNS"], "acquiringProviderType": "CRB", "merchantDescriptor": "" } ], "financialReserves": [ { "reserveType": "RISK", "reserveCollectionMethod": "PERCENTAGE", "percentagePerTransaction": 200, "amountPerTransaction": { "value": 20, "currencyCode": "USD" }, "thresholdAmount": { "value": 1000000, "currencyCode": "USD" } } ], "businessProcessingAttributes": { "annualVolume": { "value": 50000000, "currencyCode": "USD" }, "averageTicket": { "value": 5000, "currencyCode": "USD" }, "largestTicket": { "value": 100000, "currencyCode": "USD" }, "cardPresentSalesPercentage": 60, "cardNotPresentSalesPercentage": 40, "businessSalesPercentage": 50, "consumerSalesPercentage": 40, "governmentSalesPercentage": 10 } } } } } ``` ### Onboard for money movement Supply to enroll the business for money movement. ##### Required fields {#mvt-required-fields} - : The product to onboard the business to, from program setup. ##### Optional fields {#mvt-optional-fields} - : The rails to enable — , , , , , , or . The card-network rails (, , , ) provision acquiring capabilities for the business. and are currently enabled at the product level, so listing them takes no per-business action. - : The business's money movement operating details and licensing, used during underwriting. If you supply it, its yes/no fields and the three description fields are required. - : Same as for acquiring. ##### Conditional fields {#mvt-conditional-fields} - is required when is . - is required when is . - is required when contains . ```json { "input": { "businessId": "", "pricingPlanId": "", "consent": { "consentTimestamp": "", "consentIpAddress": { "v4": "" }, "primaryAuthorizedPersonId": "" }, "onboarding": { "moneyMovement": { "productId": "", "moneyMovementCapabilities": ["ACH", "US_RTP"], "moneyMovementProcessingAttributes": { "isRegulatedEntity": true, "regulatedEntityDetails": "Licensed as a Money Transmitter in all required states under NMLS ID 123456.", "moneyMovementLicenses": ["MONEY_TRANSMITTER_LICENSE"], "hasAmlPolicy": true, "hasPreviouslyProcessedTransfers": true, "previousMoneyMovementProcessors": [""], "hasBeenTerminatedByPreviousProcessor": false, "hasPreviousBankruptcy": false, "descriptionOfCustomers": "Small and medium-sized businesses in the retail and e-commerce sectors across the United States.", "descriptionOfFunding": "ACH pull from a prefunded operating account held at an FDIC-insured bank.", "descriptionOfReceivingAccounts": "Consumer checking and business operating accounts at US financial institutions.", "annualVolumeEstimates": [ { "year": 1, "estimatedVolume": { "value": 500000000, "currencyCode": "USD" }, "estimatedTransactionCount": 50000 }, { "year": 2, "estimatedVolume": { "value": 1250000000, "currencyCode": "USD" }, "estimatedTransactionCount": 125000 } ] } } } } } ``` ### Results - A valid application returns a . Step 3 shows how to track it. - An invalid application returns a synchronously, e.g., a missing required field. is an array of path segments beginning with the member you supplied, so a bad merchant field reports as . ## Step 3. Track status and start transacting Approval and provisioning happen after the mutation returns, so track the application until the business is ready. ### Listen for application events Highnote publishes a notification event as the application moves between the statuses below, so a webhook subscription can drive your integration rather than a polling loop. The status queries in Track acquiring status remain the source of truth. Reconcile against them if an expected event does not arrive. | Event | Meaning | | :---------------------------------------------- | :----------------------------------------------------------- | | | The application is being processed. | | | The application requires additional review. | | | Document upload sessions were requested for the application. | | | The application is approved; capability provisioning begins. | | | The application is denied. | | | The application is closed. | Provisioning follows approval and reports through each capability's status rather than through events, so after switch to the queries below. ### Track acquiring status The application's reports the application overall, and each requested capability reports its own provisioning status: | Capability status | Meaning | | :---------------- | :----------------------------------------------------------------------- | | | The capability is being provisioned. | | | The capability is provisioned; the business can process on that network. | | | The capability was not approved and will not become active. | | | A previously active capability was turned off; it no longer processes. | Check capability status by querying the applications through the you created in Step 1. The root [](/docs/api-reference/query#productApplications) query takes no filter, so reading through the is how you scope the result to one business. ```graphql query BusinessProductApplications($id: ID!, $first: Int) { node(id: $id) { ... on Business { id businessServices { merchantDetails { productApplications(first: $first) { ... on ProductApplicationConnection { pageInfo { hasNextPage endCursor } edges { node { id applicationState { status } contract { processingCapabilities { ... on CardProcessingCapability { permittedProcessingNetwork permittedTransactionTypes status merchantDescriptor } } } } } } ... on UserError { errors { code description errorPath } } } } } services(first: $first) { edges { node { ... on Merchant { id merchantAcceptors(first: 20) { edges { node { id } } } } } } } } } } ``` ```json { "id": "", "first": 20 } ``` The selection returns the business's . Its is the used below, and its [](/docs/api-reference/object#MerchantAcceptor) IDs (prefix ) are what you reference when you accept payments once capabilities are . If you already have the merchant's ID, you can query the acceptors directly. The merchant's [](/docs/api-reference/enum#MerchantStatus) reports the merchant itself — means it can process transactions: ```graphql query MerchantAcceptors($id: ID!) { node(id: $id) { ... on Merchant { id status merchantAcceptors(first: 20) { pageInfo { hasNextPage endCursor } edges { node { id } } } } } } ``` ```json { "id": "" } ``` ### Track money movement status Money movement does not use merchant acceptors, and how you track readiness depends on the rails you requested: - **Card-network rails** (, , , ) move money to and from cards, so Highnote provisions them as acquiring capabilities for the business. Track them with the acquiring query above — the same capabilities, the same to lifecycle. - **Bank rails** (, ) are currently enabled at the product level rather than per business, so there is no per-business status to query. Highnote confirms with you when the business is ready to transact. --- URL: https://docs.highnote.com/docs/acquiring/payments/incremental-authorization Title: Incremental Authorization Section: Acquiring Description: Increase the authorized amount on an existing payment transaction without creating a new authorization. Covers network constraints for Visa and Mastercard, including zero-dollar authorization for extending expiration dates. ## Overview Incremental authorization enables merchants to **increase the authorized amount on an existing payment without creating a new authorization**. This is commonly used in industries where the final transaction amount isn't known at the time of initial authorization, for example: - Hotels: Guest extends stay or incurs additional charges. - Car Rentals: Rental period extension or additional fees. - Restaurants: Adding tip to the bill. Instead of creating a new authorization, which would hold additional funds on the customer's card, incremental authorization increases the existing hold, providing a better customer experience. ## Prerequisites Before using Incremental Authorization, ensure the following: - Original authorization exists: A valid, approved authorization must exist for the payment. - Authorization not expired: The original authorization must not be expired. - Not the final capture: The payment must not have been final captured. - Currency matches: The incremental amount must be in the same currency as the original authorization. - Visa amounts non-zero: Visa does not support zero-amount incremental authorizations (Mastercard does). - Remaining amount non-zero: The authorized remaining amount must be available and not zero. ## Inputs Incremental authorizations operate on the initial payment transaction using the . | Authorization | Mutation | Input | | :------------ | :------------------------------------------------------------------------------------------------------------ | :--------------------------------------- | | Initial | authorizePaymentCard | Normal auth for $800 | | Incremental | incrementalAuthorizePaymentTransaction | + additional $500 | ```json title="incrementalAuthorizePaymentTransaction input" { "input": { "paymentTransactionId": "acqpt_552b9415686744859fb12585c1fd5b48", "amount": { "value": 100, "currencyCode": "USD" }, "idempotencyKey": "B238076C-FCB4-44EE-9E90-E37ABA711A98" } } ``` | Field | Type | Required | Description | | :--------------------- | :--------- | :------------------------ | :-------------------------------------- | | | String | Yes | ID of the existing payment to increment | | | MoneyInput | Visa: Yes, Mastercard: No | Additional amount to authorize | | | Integer | Yes | Monetary value (e.g., ) | | | String | Yes | ISO 4217 currency code (e.g., ) | | | String | No | | ## Best practices - **Check authorization validity**: Before attempting an incremental authorization, verify the original authorization hasn't expired. - **Handle declines gracefully**: If an incremental authorization is declined, consider creating a new authorization. - **Monitor expiration**: Authorization validity periods vary by card network and merchant category. - **Currency consistency**: Always use the same currency as the original authorization. ## Request incremental authorization Use the incrementalAuthorizePaymentTransaction mutation to increase the authorized amount on an existing payment. ## Request $0 incremental authorization Zero dollar incremental authorization only applies to Mastercard authorizations. Use the following mutation to run an incremental authorization of zero dollars () and extend the expiration date of the original authorization. ### GraphQL: incrementalAuthorizePaymentTransaction Query: mutation IncrementalAuthorizePaymentTransaction( $input: IncrementalAuthorizePaymentTransactionInput! ) { incrementalAuthorizePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardAuthorizationStepSummary { amount { value currencyCode } createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } canceledAmount { value currencyCode } networkTransactionIdentifier settledAmount { value currencyCode } disbursedAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { addressCode postalCode securityCode authorizationCode processorResponseCode } } } } } Variables: { "input": { "paymentTransactionId": "", "amount": { "value": 100, "currencyCode": "USD" }, "idempotencyKey": "UUID v4" } } Expected Result: { "data": { "incrementalAuthorizePaymentTransaction": { "__typename": "CardAuthorizationStepSummary", "amount": { "value": 100, "currencyCode": "USD" }, "createdAt": "2026-01-09T18:36:14.562Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2026-01-09T18:36:14.562Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 218, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 218, "currencyCode": "USD" }, "canceledAmount": null, "networkTransactionIdentifier": "MCSKUV38O", "settledAmount": null, "disbursedAmount": null, "refundedAmount": null, "responseCode": { "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED", "authorizationCode": "58349Z", "processorResponseCode": "APPROVED" } } } }, "extensions": { "requestId": "1c320813-7f6d-492a-8c8d-021bd3f2e3ab", "rateLimit": { "cost": 19, "limit": 60060, "remaining": 60040, "asOf": "2026-01-09T18:36:34.624Z", "complexity": { "limit": 60060, "remaining": 60040, "cost": 19 }, "count": { "limit": 60060, "remaining": 60058, "cost": 1 } } } } ### GraphQL: incrementalAuthorizePaymentTransaction Query: mutation IncrementalAuthorizePaymentTransaction( $input: IncrementalAuthorizePaymentTransactionInput! ) { incrementalAuthorizePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardAuthorizationStepSummary { amount { value currencyCode } createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } canceledAmount { value currencyCode } networkTransactionIdentifier settledAmount { value currencyCode } disbursedAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { addressCode postalCode securityCode authorizationCode processorResponseCode } } } } } Variables: { "input": { "paymentTransactionId": "", "amount": { "value": 0, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "incrementalAuthorizePaymentTransaction": { "__typename": "CardAuthorizationStepSummary", "amount": { "value": 0, "currencyCode": "USD" }, "createdAt": "2026-01-23T23:04:12.339Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2026-01-23T23:04:12.339Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 100000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 75000, "currencyCode": "USD" }, "canceledAmount": null, "networkTransactionIdentifier": "MCCQMP04RLBT", "settledAmount": null, "disbursedAmount": null, "refundedAmount": null, "responseCode": { "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED", "authorizationCode": "BBFROI", "processorResponseCode": "APPROVED" } } } } } --- URL: https://docs.highnote.com/docs/acquiring/payments/merchant-descriptors Title: Merchant Descriptors Section: Acquiring Description: Understand how Highnote builds merchant descriptors for acquiring transactions and how to pass a per-transaction suffix through the API. ## Overview A **merchant descriptor** is the short alphanumeric string that appears on a customer's card statement to identify a transaction. Accurate, recognizable descriptors reduce disputes and chargebacks by helping customers answer "Who charged me, and what is the charge for?" Highnote builds the descriptor sent to the payment networks for each transaction. Across the supported networks (Visa, Mastercard, Discover, American Express), the combined descriptor is capped at **{MERCHANT_DESCRIPTOR_MAX_CHARS} characters** by default, or **{MERCHANT_DESCRIPTOR_MAX_CHARS_VISA} characters** when the transaction routes through a Visa DMS or Visa SMS processor. ## How descriptors are built Highnote constructs the descriptor from three parts: - **Prefix**: A static value Highnote manages for your merchant based on the Public Merchant Name or Doing Business As (DBA) name collected and validated during onboarding. Where payment network rules require it, Highnote automatically prepends indicators such as the payment facilitator marker (). Contact Highnote to change your prefix. - **Suffix**: An optional, per-transaction value you pass through the API on acquiring mutations. Use the suffix to include transaction-specific details (for example, an order number or store identifier) that help the customer recognize the charge. - **Separator**: On push (OCT) transactions, Highnote inserts an asterisk () between the prefix and the suffix. Pull (AFT) and card-acceptance transactions use no separator. The separator counts toward the character cap, so on push it costs one of the characters otherwise available to your suffix. The combined length of prefix + separator + suffix is capped at **{MERCHANT_DESCRIPTOR_MAX_CHARS} characters** ({MERCHANT_DESCRIPTOR_MAX_CHARS_VISA} on a Visa DMS or Visa SMS processor). If the combined value exceeds the cap, Highnote truncates the suffix to fit; if the prefix alone fills the cap, Highnote drops the suffix entirely. The {MERCHANT_DESCRIPTOR_MAX_CHARS_VISA}-character allowance applies to the combined value only. Where a rail also checks your raw suffix up front — as [](/docs/money-movement/payment-rails/transfer-funds-api) (INT) does — that check uses the flat {MERCHANT_DESCRIPTOR_MAX_CHARS}-character limit. The characters left for your suffix are therefore the cap minus your prefix length, minus one more on push (OCT) for the separator. A {MERCHANT_DESCRIPTOR_MAX_CHARS}-character cap with an 8-character prefix leaves 13 characters for the suffix on push, or 14 on pull and on card-acceptance mutations. The Transfer Funds (INT) rail enforces the same combined-length cap. INT also rejects a raw suffix over {MERCHANT_DESCRIPTOR_MAX_CHARS} characters up front, before the combine step runs. See the info box under Supported mutations. ### Descriptor types | Type | What it looks like | When it's used | | :---------- | :------------------------------------------------------------------- | :------------------------------------------------- | | Static | Prefix only — the same value on every transaction | No passed on the mutation | | Combination | Prefix plus a per-transaction suffix, separated by on push (OCT) | passed on the mutation | ## Pass a suffix per transaction Pass a on the mutation input to append a per-transaction suffix to the configured prefix. ### Supported mutations is an optional field on the input types for the following mutations: | Category | Mutation | Input | | :-------- | :---------------------------- | :--------------------------------- | | Verify | | | | Verify | | | | Verify | | | | Authorize | | | | Charge | | | | Transfer | (INT rail) | | The credential-specific mutations (, , , , , ) also continue to accept . To move an existing integration to the consolidated mutations, see the migration guide. Mutations [](/docs/api-reference/mutation#chargePaymentOrder) and [](/docs/api-reference/mutation#chargePaymentOrderFromPaymentMethodToken) do not accept . On , the field only applies to Instant Network Transfers. Highnote checks the raw suffix first: a suffix over {MERCHANT_DESCRIPTOR_MAX_CHARS} characters is rejected with a validation error, before it reaches the network. This input limit is always {MERCHANT_DESCRIPTOR_MAX_CHARS} characters: it is checked before Highnote knows which processor will handle the transfer, so the higher Visa DMS or Visa SMS cap does not apply to it. After that check, Highnote combines the accepted suffix with the configured prefix, the same as the card-acceptance mutations above, and caps the combined value at {MERCHANT_DESCRIPTOR_MAX_CHARS} characters ({MERCHANT_DESCRIPTOR_MAX_CHARS_VISA} on a Visa DMS or Visa SMS processor). If the combined length exceeds the cap, Highnote truncates the suffix. Push (OCT) transfers also spend one character on the separator; pull (AFT) transfers use no separator. So passing a suffix within the {MERCHANT_DESCRIPTOR_MAX_CHARS}-character input limit does not guarantee it survives intact — what reaches the statement is bounded by the combined cap. ### Input shape contains a single field: | Field | Type | Description | | :------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | | Value appended to the configured merchant descriptor prefix. The combined character length of prefix + separator + suffix is capped at {MERCHANT_DESCRIPTOR_MAX_CHARS} characters ({MERCHANT_DESCRIPTOR_MAX_CHARS_VISA} on a Visa DMS or Visa SMS processor) on every mutation, including (INT), and Highnote truncates an over-length suffix to fit. Push (OCT) transactions spend one character on the separator. On (INT), Highnote also rejects a raw suffix over {MERCHANT_DESCRIPTOR_MAX_CHARS} characters up front. See Supported mutations. | ### Example The following snippet shows the field passed to . The same pattern applies to any supported mutation. ```graphql title="chargePaymentTransaction with a suffix" mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { ... on CardCaptureStepSummary { createdAt transaction { id } } } } ``` ```json title="Variables" { "input": { "credential": { "paymentCard": { "...": "..." } }, "amount": { "value": 1999, "currencyCode": "USD" }, "merchantDescriptor": { "suffix": "ORDER-4821" } } } ``` ### Allowed characters The field accepts any string at the API layer, but the payment networks and processors apply character restrictions downstream. To maximize compatibility across networks, limit suffix content to: - Letters: –, – - Digits: – - Special characters: , , , , , , , , and space ## Where the descriptor appears The constructed descriptor (prefix + optional suffix) is sent to the payment networks with each transaction and appears on the customer's card statement. --- URL: https://docs.highnote.com/docs/acquiring/payments/migrate-payment-mutations Title: Migrate to the Consolidated Payment Mutations Section: Acquiring Description: Migrate from the credential-specific acquiring mutations to authorizePaymentTransaction, chargePaymentTransaction, and reversePaymentTransaction. Highnote has released new consolidated payment mutations. Existing mutations are deprecated (but not removed). There is no cutover date. _Update each call the next time you're working in that code._ ## What changed Highnote's acquiring credential-specific payment mutations have been deprecated in favor of three consolidated mutations that add the following improvements: - **One mutation per verb:** authorize and charge accept any credential; reverse needs none. - **One shape:** input and response are the same for every credential; only the credential member changes. - **No new mutations to adopt:** new credential types arrive as a new member on the same call. - **Reversals you can find:** full and partial reversals are both under the network name. ### Mutation mapping table Replace each call in your integration with the consolidated mutation that performs the same action: | Legacy mutation | Replacement | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------- | | [](/docs/api-reference/mutation#authorizePaymentCard)
[](/docs/api-reference/mutation#authorizeNetworkToken)
[](/docs/api-reference/mutation#authorizePaymentMethodToken) | [](/docs/api-reference/mutation#authorizePaymentTransaction) | | [](/docs/api-reference/mutation#chargePaymentCard)
[](/docs/api-reference/mutation#chargeNetworkToken)
[](/docs/api-reference/mutation#chargePaymentMethodToken) | [](/docs/api-reference/mutation#chargePaymentTransaction) | | [](/docs/api-reference/mutation#cancelPaymentTransaction) | [](/docs/api-reference/mutation#reversePaymentTransaction) | ### One verb, any credential Until now, the mutation you called depended on what you were charging: a payment card, a network token, and a payment method token each had their own authorize mutation and their own charge mutation. The credential is now data rather than surface area. It moves into a single [](/docs/api-reference/input#PaymentCredentialInput) input that carries exactly one of , , or . Amount, payment initiator, idempotency key, and merchant details stay at the top level of the input and are the same whichever credential you send. Two things follow. Your integration calls the same mutation and handles the same response no matter which credential it presents. And when Highnote supports a new credential type, it arrives as a new member of rather than as a new mutation for you to adopt. ### Clearer name for reversals The mutation did more than its name suggested. Passing its optional performed a _partial_ reversal, and released part of a hold instead of ending the authorization, which is what you need when a final amount comes in below your original estimate. That behavior was reachable only if you already knew it was there. The mutation [](/docs/api-reference/mutation#reversePaymentTransaction) is the same operation under the name the card networks use. Full and partial reversals both live on it, and keeps its delta semantics. It is the amount to release, not the new authorization total. The migration is mechanical. Move the credential under the input and pick the member that matches its type; and move inside that member, and every other field stays where it is. The sections below map each legacy mutation to its consolidated call, and Field changes gives the complete field-by-field mapping. ## Authorize payment transaction The mutation [](/docs/api-reference/mutation#authorizePaymentTransaction) authorizes a payment for later capture. Place a hold on the cardholder's funds now, then capture with [](/docs/api-reference/mutation#capturePaymentTransaction) or release the hold with [](#reverse-payment-transaction). | Legacy mutation | Consolidated call | | :---------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------ | | [](/docs/api-reference/mutation#authorizePaymentCard) | | | [](/docs/api-reference/mutation#authorizeNetworkToken) | | | [](/docs/api-reference/mutation#authorizePaymentMethodToken) | | The following variables show the same payment card authorization before and after migration. The details move under , and moves inside the credential member. Every other field stays where it was. ```json title="Legacy — authorizePaymentCard variables" { "input": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "31", "expiryMonth": "12", "securityCode": "111" }, "cardHolder": { "billingAddress": { "streetAddress": "1234 Visa Street", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Visa", "region": "California", "postalCode": "12345" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } ``` ```json title="Consolidated — authorizePaymentTransaction variables" { "input": { "credential": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "31", "expiryMonth": "12", "securityCode": "111", "cardHolder": { "billingAddress": { "streetAddress": "1234 Visa Street", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Visa", "region": "California", "postalCode": "12345" } } } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } ``` ## Charge payment transaction The mutation [](/docs/api-reference/mutation#chargePaymentTransaction) authorizes and captures a payment in a single round trip and mirrors [](#authorize-payment-transaction). The input shape is the same, including the same choice of payment card, network token, or payment method token. Apply the same change as for authorize by moving the credential under and leave the rest of the input unchanged. | Legacy mutation | Consolidated call | | :---------------------------------------------------------------------------------- | :--------------------------------------------------------------------------- | | [](/docs/api-reference/mutation#chargePaymentCard) | | | [](/docs/api-reference/mutation#chargeNetworkToken) | | | [](/docs/api-reference/mutation#chargePaymentMethodToken) | | ## Reverse payment transaction The mutation [](/docs/api-reference/mutation#reversePaymentTransaction) has the same input fields, same behavior, same events as [](/docs/api-reference/mutation#cancelPaymentTransaction). No credential is involved, so the input is unchanged. | Legacy mutation | Consolidated call | | :---------------------------------------------------------------------------------- | :--------------------------------- | | [](/docs/api-reference/mutation#cancelPaymentTransaction) | | The field keeps its delta semantics. It is the amount to release back to the cardholder, not the new authorization total. To reverse the full remaining authorization omit . When you supply , it must not exceed the remaining authorized amount. ### Reversal amount Reversal amount cannot exceed the remaining authorization. If the amount to reverse exceeds the outstanding authorized amount, the mutation returns a with code and an locating the offending amount. Nothing is sent to the network. The following variables attempt to reverse 13.00 USD against an authorization with only 10.00 USD outstanding: ```json title="Variables" { "input": { "paymentTransactionId": "", "amount": { "value": 1300, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4" } } ``` ```json title="Response" { "data": { "reversePaymentTransaction": { "__typename": "UserError", "errors": [ { "code": "REVERSAL_AMOUNT_GREATER_REMAINING_AUTHORIZED_AMOUNT", "description": "Requested reversal amount is greater than remaining authorized amount", "errorPath": ["input", "amount"] } ] } } } ``` ## Field changes Most input fields carry over unchanged. The following table shows where each legacy input field lands in the consolidated inputs, starting with the fields that carry over unchanged: | Field | Change | | :--------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ | | , , , , , | Unchanged. Same names, same position at the top level of the input. | | | Relocated. Moves inside or . | | | Relocated. Moves inside every member. | | , | Relocated. Becomes the or member — see the mapping tables above. | | | Relocated. Becomes . | | | Not carried over. Already superseded by . | ## Provide exactly one credential The field must contain exactly one member. If you set zero members or more than one, the request is rejected before any processing occurs, and the failure is returned as a top-level GraphQL validation error rather than in . Business-rule rejections, such as a reversal amount that exceeds the remaining authorization, instead return a in . Populate a single credential member per request. ## Reversing vs. increasing an authorization The mutation only decreases an authorization. It releases held funds back to the cardholder. To increase the authorized amount on an existing payment transaction, use [](/docs/api-reference/mutation#incrementalAuthorizePaymentTransaction), which is unaffected by this consolidation. See Incremental Authorization for details. ## Next steps For runnable, interactive examples of each consolidated mutation, see Online Payments. --- URL: https://docs.highnote.com/docs/acquiring/payments/online-payments Title: Online Payments Section: Acquiring Description: Process online payments across Visa, Mastercard, Discover, American Express, and Maestro networks. Authorize, charge, capture, refund, and reverse payment transactions. Highnote has released new consolidated payment mutations. Existing mutations are deprecated (but not removed). There is no cutover date. **See Migrate to the Consolidated Payment Mutations**. ## Overview Highnote processes online card payments through a standard lifecycle: an authorization places a hold on the cardholder's funds, a capture claims some or all of that hold for settlement, refunds return captured funds to the cardholder, and a reversal releases any remaining un-captured hold. The integration path depends on your PCI compliance level. Choose tokenized integration to keep card data off your servers via the Highnote SDK, or direct integration when you handle raw card data under PCI SAQ-D scope. ## Payment networks Highnote accepts online payments through the following payment networks: | Payment Network | Rail | Payment Instrument | | :--------------- | :------------- | :----------------- | | Visa | Credit/Debit | Card | | Mastercard | Credit/Debit | Card | | Maestro | PIN-less Debit | Card | | Discover | Credit | Card | | American Express | Credit | Card | Brand support depends on merchant type and use case: | Use case | Visa | Mastercard
(& Maestro) | Discover | Amex | | :--------------------------------------------------------------------------------------------- | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | :------------------------------------------------------: | | Acquiring / Card acceptance — SMB / direct merchants | !approved | !approved | !approved | !approved | | Acquiring / Card acceptance — payfacs / ISOs | !approved | !approved | !approved | !denied | | Money Movement / Instant Network Transfers | !approved | !approved | !denied | !denied | ## Integration options How you integrate with the Highnote API depends on your PCI compliance level. Highnote supports two integration paths: - **Tokenized (non-PCI)**: Use a Highnote SDK to collect card details and tokenize them into a . Your servers never handle raw card data, keeping you out of PCI scope. - **Direct (PCI SAQ-D)**: Pass raw card details directly to the Highnote API. This requires PCI SAQ-D compliance because your servers handle cardholder data. Both paths support the same payment operations (verify, authorize, charge, capture, reverse, refund). The only difference is the credential you supply: a tokenized for tokenized integrations, or raw card details for direct integrations. ### Tokenization with Highnote SDKs For merchants who are not PCI SAQ-D compliant, Highnote provides two SDKs that tokenize card details into a : - **Secure Inputs SDK**: Build a custom payment form with your own UI. The SDK renders secure input fields that you style and position. - **Checkout SDK**: Drop in a pre-built payment form. The SDK generates the UI for you. Both SDKs output the same result: a tokenized ID () that you use with the tokenized mutations below. Follow the Secure Inputs SDK setup guide and add the following SDK snippet to your payment form: ```js title="Secure Inputs" const secureInputs = await renderFields({ creditCard: { clientToken: clientTokenFromServer, cardNumber: { selector: "#card-number", }, expiryYear: { selector: "#expiry-year", }, expiryMonth: { selector: "#expiry-month", }, securityCode: { selector: "#security-code", }, cardHolderName: { selector: "#card-holder-name", }, }, onSuccess: (element) => { if (element.name === "card") { const paymentMethodId = element.paymentMethod.id; console.log( "Send this paymentMethodId to your server for payment: ", paymentMethodId, ); } }, onError: (error) => { console.log("Error: " + error.message); }, }); ``` ## Payments process This page shows the consolidated payment mutations: [](/docs/api-reference/mutation#authorizePaymentTransaction), [](/docs/api-reference/mutation#chargePaymentTransaction), and [](/docs/api-reference/mutation#reversePaymentTransaction). The credential-specific mutations (, , , , , ) and continue to work unchanged. To move an existing integration to the consolidated mutations, see the migration guide. The standard payment process uses the following steps: - **Verification** (optional): Confirm the card is valid with a zero-dollar transaction before authorizing. - **Authorization**: The customer's payment details are verified with the issuer, and the funds are held. - **Reverse**: If the payment cannot continue, reverse the authorization to release the held funds. - **Capture**: The held funds are transferred to your merchant settlement financial account after the customer's successful authorization. - **Refund**: The held funds are transferred from your merchant settlement financial account back to the customer's account. - **Disburse**: The funds due to each merchant account is calculated and moved from Highnote's ledger to the merchant settlement account, including fees and reserve amounts. Transactions can be processed in two ways, "Dual message" or "Single message". ### Dual message **Dual message**: Authorize first, then capture later. Use this for transactions where the final amount may change, such as tips or partial shipments. ### Single message **Single message**: Authorize and capture in a single step using the charge mutation. Use this when the final amount is known at the time of payment. ## Tokenized integration (non-PCI) Use the following mutations if you tokenize card details with a Highnote SDK. These mutations accept a tokenized instead of raw card details. ### Verify a payment method token Before authorizing a transaction, you can verify that a payment method token is valid and able to be used for payment. Token verification runs a zero-dollar transaction to confirm the underlying card details without placing a hold on funds. ### Authorize a payment method token Tokenized and direct integrations call the same [](/docs/api-reference/mutation#authorizePaymentTransaction) mutation, differing only in which member you populate — here, . Use the following mutation to authorize a payment method token for later capture: ### Charge a payment method token Tokenized and direct integrations call the same [](/docs/api-reference/mutation#chargePaymentTransaction) mutation, differing only in which member you populate — here, . Use the following mutation to authorize and capture a payment in a single step: ## Direct integration (PCI SAQ-D) The following mutations accept raw card details (PAN, expiry, CVV). Your servers must be PCI SAQ-D compliant to use these mutations. Use the following mutations if you handle raw card details directly. These mutations accept a input with the card number, expiry, and security code. ### Verify a payment card Before authorizing a transaction, you can verify that a payment card is valid and able to be used for payment. Card verification runs a zero-dollar transaction against the card to confirm the card number, expiration date, and security code without placing a hold on funds. The verification response includes response codes for the processor result, address (AVS), postal code, and security code (CVV). Use these response codes to determine whether to proceed with authorization. To verify a payment card, provide the card details in the input. Optionally, include with a billing address to enable address verification (AVS). ### Authorize a payment card Tokenized and direct integrations call the same [](/docs/api-reference/mutation#authorizePaymentTransaction) mutation, differing only in which member you populate — here, . Use the following mutation to authorize a payment card for later capture: ### Charge a payment card Tokenized and direct integrations call the same [](/docs/api-reference/mutation#chargePaymentTransaction) mutation, differing only in which member you populate — here, . Use the following mutation to authorize and capture a payment in a single step: ## Verification response codes Both and return a with the following sub-fields: | Field | Description | | :---------------------- | :------------------------------------------------------------------------------------------------ | | | The outcome of the transaction. See Read the processor response code. | | | Whether the street address matches the issuer's records. | | | Whether the postal code matches the issuer's records. | | | Whether the security code (CVV/CVC) matches the issuer's records. | Each AVS and security code field returns one of the following values: , , , , , or . ### Read the processor response code {#processor-response-code} returns a [](/docs/api-reference/enum#PaymentTransactionResponseCodeProcessorResponseCode) value. The same enum types this field on both [](/docs/api-reference/object#PaymentCardVerificationResponseCode) and [](/docs/api-reference/object#PaymentTransactionResponseCode), so verification, authorization, and charge all return the same set of values. Most values report the issuer's decision, such as or . One value is Highnote's own. means Highnote's risk controls declined the authorization before it was sent to the card network. Neither the network nor the issuer saw the transaction. Highnote publishes as a class of decline only. #### Absent and unrecognized codes and describe different situations: | Value | Meaning | | :-------- | :------------------------------------------------------------------------------- | | | No response code was sent. Highnote received no code for this transaction. | | | A response code was sent, but it matches no value Highnote publishes a name for. | Read as an outcome Highnote cannot name and as missing data. Neither one is an approval. Use the transaction to decide whether the transaction succeeded. is a query-only surface. No notification event carries it, and no webhook payload selects it, so these values do not change what your webhook endpoint receives. Query the payment transaction to read the field. ## Handle SCA soft declines When the issuer requires **strong customer authentication** (SCA) before approving a card-not-present (CNP) authorization, Highnote returns = . This is a **soft decline** — the authorization is recoverable. The merchant initiates a 3D Secure (3DS) step-up flow with the cardholder, then resubmits the authorization with the resulting authentication data. is distinct from a hard decline (such as or ). The cardholder's account, card, and credentials are valid; the issuer is asking for additional proof of identity before approving the transaction. Treat it as a prompt to authenticate, not a final decision. ### When AUTHENTICATION_REQUIRED is returned Highnote returns for a card-not-present Mastercard authorization when the issuer's response indicates strong customer authentication is required. ### Recover the authorization To complete a transaction that was declined with : 1. Initiate a 3DS step-up flow with the cardholder using your 3DS provider (such as Cardinal Commerce / CMPI). Highnote does not perform the merchant-side 3DS challenge — it is your responsibility as the merchant. 2. Once the cardholder completes authentication, your provider returns authentication data (CAVV, ECI, and a transaction identifier). 3. Resubmit the authorization using the [](/docs/api-reference/mutation#authorizePaymentTransaction) mutation, passing the authentication data on , where is , , or . That object takes (ECI), (CAVV), , , and . The retry is a new authorization, not a continuation of the declined one. There is no platform-side correlation between the original decline and the subsequent authenticated retry — your integration is responsible for tracking that relationship. ### Test in the sandbox To exercise the flow in the sandbox, use a Mastercard test card with an authorization amount of . See Authorization response code declines for the full simulator amount table. ## Reverse a payment {#cancel-a-payment} A payment can only be reversed before Highnote captures the payment. When a payment is reversed before capture, no money has moved out of the cardholder's account, resulting in the funds being returned to their account balance. Use the [](/docs/api-reference/mutation#reversePaymentTransaction) mutation to release held funds: is the amount to release back to the cardholder, and it must not exceed the remaining authorized amount. Payments can be reversed by the cardholder, merchant, issuing bank, acquiring bank, or payment network. Payment reversals are common in the following use cases: - Undelivered goods or services - Duplicate transactions - Fraud transactions - The customer asks for a cancellation before goods are shipped Full and partial payment reversals are supported for all card networks except American Express. For an overview of use cases for partial reversals, see Reverse a partial amount. ### Reverse the full amount {#cancel-full-amount} To reverse the full remaining authorization, omit the input variable: ### Reverse a partial amount {#cancel-partial-amount} Partial reversals are not supported for American Express. Partial reversals are common in the following use cases: - A customer returns items from their purchase, but not the entire purchase. - A customer cancels a service and is refunded the unused portion of the service. - An error was made in the initial billing, such as overcharging a service or product. - Only one part of an order was fulfilled or delivered, and the other part is reversed as a refund. To process a partial reversal, use the following mutation and set the input variable to the amount to release: ## Capture a payment Capturing a payment transaction moves funds from the customer's account to your merchant account. Full and partial captures are supported for all card networks except for American Express. ### Capture full amount To capture a full amount of an authorized transaction, set the input field to the full amount of the original authorization. Set to an authorized PaymentTransaction ID (e.g., ). Use the following mutation and input variables to capture the full amount of an authorized payment transaction: ### Capture partial amount Partial captures are not supported for American Express. To capture the partial amount of an authorized transaction, enter a partial amount in the input field. Set to an authorized PaymentTransaction ID (e.g., ). Partial captures are common in the following use cases: - Customer places pre-order or makes deposit, and only a portion of the total authorization is captured. - Customer's order is split into multiple shipments and the merchant captures payments separately for each. - Merchant offers flexible payment terms, with partial captures collected at an agreed-upon schedule. - Item from customer's order is back-ordered and the business captures a payment for only the available items. Use the following mutation and input variables to capture the partial amount of an authorized payment transaction: ### Capture final amount When you make a final capture, the Highnote platform schedules a reversal of any remaining authorized amount. For example, if $100 is authorized, and $80 is final captured, then $20 is reversed. Use the following mutation and input variables to capture the final amount of an authorized payment transaction: ### Force capture Contact your Highnote representative to enable Force Capture in your product. When an authorization is declined, and the cardholder has agreed to the terms, a merchant can, if necessary, submit the transaction by force. The API automatically captures the outstanding declined portion without requiring the user to explicitly specify a capture amount. Chargeback protection is available when the merchant can provide evidence that the cardholder agreed to the capture of funds. Use the following mutation to perform a force capture. See the docs on simulating declines. Clearing may be delayed due to the network's review processes. ## Refund a payment Refunds are issued after a **payment has been captured and funds have been disbursed**. Highnote supports full and partial refunds. Multiple partial refunds can be done if the total of the refunds does not exceed the captured amount. For multi-capture transactions, see Refund one of multiple captures. ### Refund full amount A full refund returns the entire captured amount. If the payment was only partially captured, refunding does not release the remaining authorized hold — use Reverse a payment to release it. Use the following mutation to refund the full captured amount: ### Refund partial amount A partial refund returns a portion of the captured amount. The value cannot exceed the captured amount; the API returns if it does. If the payment was only partially captured, refunding does not release the remaining authorized hold — use Reverse a payment to release it. Use the following mutation to refund a partial amount. In the response payload, note the difference between the and : ### Combining refund and reversal {#combining-refund-and-cancel} When the captured amount is less than the authorized amount, refunds do not release the remaining authorized hold. You must use Reverse a payment to release it. The following examples show when a reversal is needed with a refund: | Authorized | Captured | Refund | Remaining Authorized | Reversal Needed | | :--------- | :------------ | :------------------------ | :------------------- | :------------------------------------- | | $100 | $100 | $40 (partial) | $0 | No — nothing to release | | $100 | $70 (partial) | $20 (partial of captured) | $30 | Yes — a reversal releases the $30 hold | | $100 | $70 (partial) | $70 (full of captured) | $30 | Yes — a reversal releases the $30 hold | The following sequence walks through a $100 authorization that is partially captured ($70), partially refunded ($20), and then reversed to release the remaining $30 hold. | Step | Action | Captured (With Merchant) | Refunded | Un-captured Hold | Net Cardholder Paid | | :--- | :---------- | :----------------------: | :------: | :--------------: | :-----------------: | | 1 | Auth $100 | $0 | $0 | $100 | $0 | | 2 | Capture $70 | $70 | $0 | $30 | $70 | | 3 | Refund $20 | $50 | $20 | $30 | $50 | | 4 | **Reverse** | $50 | $20 | **$0** | **$50** | After the full sequence, the merchant keeps $50 (captured minus refunded), the cardholder paid $50 net, and the $30 hold is released. ## Refund one of multiple captures When a single payment is captured in multiple installments — common in Buy Now, Pay Later (BNPL) or installment scenarios — each capture is a separate [](/docs/api-reference/object#CardCaptureStep). The [](/docs/api-reference/mutation#refundCaptureStep) mutation refunds one specific capture without touching the others. The existing [](/docs/api-reference/mutation#refundPaymentTransaction) mutation remains unchanged for aggregate refunds. **When to use:** - Refund a specific installment in a multi-capture transaction. - Pre-chargeback Request For Information (RFI) targeting — refund the disputed capture and leave others intact. - Multi-capture reconciliation where refunds align with specific orders or shipments. ### Get capture step ID To obtain a , query the parent transaction's field and select on each [](/docs/api-reference/object#CardCaptureStep). A multi-capture transaction returns one [](/docs/api-reference/object#CardCaptureStep) per capture; match the step's or to identify the specific capture, and confirm is before refunding. ### Refund capture step Use the following mutation to refund a specific capture. The field is optional; when omitted, the full remaining amount of the capture is refunded. See [](/docs/api-reference/input#RefundCaptureStepInput) for the full input shape. ### Trace refund capture step To trace a refund back to its source capture, query the field on the [](/docs/api-reference/object#PaymentCreditTransaction): ## Find all payment transactions Querying payment data can take 3-5 minutes to appear after a PaymentTransactionEvent is created, due to synchronization between databases. Use the following query to create a list view of all payment transactions: ## Find a payment transaction Use the following query to find a single payment transaction: ### GraphQL: Verify Payment Method Token Query: mutation VerifyPaymentMethodToken($input: VerifyPaymentMethodTokenInput!) { verifyPaymentMethodToken(input: $input) { ... on PaymentCardVerification { createdAt responseCode { processorResponseCode addressCode postalCode securityCode } } } } Variables: { "input": { "paymentMethodTokenId": "", "merchantAcceptorId": "", "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "verifyPaymentMethodToken": { "createdAt": "2024-02-22T17:26:20.474Z", "responseCode": { "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "MATCHED" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Authorize Payment Transaction - Payment Method Token Query: mutation AuthorizePaymentTransaction( $input: AuthorizePaymentTransactionInput! ) { authorizePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardAuthorizationStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentMethodToken": { "id": "" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "authorizePaymentTransaction": { "__typename": "CardAuthorizationStepSummary", "createdAt": "2024-02-22T17:26:20.474Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:26:20.474Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "Q5Z539", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Charge Payment Transaction - Payment Method Token Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentMethodToken": { "id": "" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2024-02-22T17:26:20.474Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:26:20.474Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "978647564526179", "responseCode": { "authorizationCode": "Q5Z539", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Verify Payment Card Query: mutation VerifyPaymentCard($input: VerifyPaymentCardInput!) { verifyPaymentCard(input: $input) { ... on PaymentCardVerification { createdAt responseCode { processorResponseCode addressCode postalCode securityCode } } } } Variables: { "input": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "31", "expiryMonth": "12", "securityCode": "111" }, "cardHolder": { "billingAddress": { "streetAddress": "1234 Visa Street", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Visa", "region": "California", "postalCode": "12345" } }, "merchantAcceptorId": "", "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "verifyPaymentCard": { "createdAt": "2024-02-22T17:26:20.474Z", "responseCode": { "processorResponseCode": "APPROVED", "addressCode": "MATCHED", "postalCode": "MATCHED", "securityCode": "MATCHED" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Authorize Payment Transaction - Payment Card Query: mutation AuthorizePaymentTransaction( $input: AuthorizePaymentTransactionInput! ) { authorizePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardAuthorizationStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "31", "expiryMonth": "12", "securityCode": "111", "cardHolder": { "billingAddress": { "streetAddress": "1234 Visa Street", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Visa", "region": "California", "postalCode": "12345" } } } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "authorizePaymentTransaction": { "__typename": "CardAuthorizationStepSummary", "createdAt": "2024-02-22T17:26:20.474Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:26:20.474Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "Q5Z539", "processorResponseCode": "APPROVED", "addressCode": "NOT_VERIFIED", "postalCode": "NOT_VERIFIED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Charge Payment Transaction - Payment Card Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentCard": { "cardNumber": "4229989999000012", "expiryYear": "31", "expiryMonth": "12", "securityCode": "871", "cardHolder": { "billingAddress": { "streetAddress": "street-address", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Los Angeles", "region": "California", "postalCode": "90210" } } } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2024-02-21T17:46:00.650Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-21T17:46:00.650Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "978647564526179", "responseCode": { "authorizationCode": "H7JRNX", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Reverse Payment Transaction - Full Query: mutation ReversePaymentTransaction($input: ReversePaymentTransactionInput!) { reversePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardReversalStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "paymentTransactionId": "", "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "reversePaymentTransaction": { "__typename": "CardReversalStepSummary", "createdAt": "2024-02-22T17:26:20.474Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:26:20.474Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": { "value": 1000, "currencyCode": "USD" }, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Reverse Payment Transaction - Partial Query: mutation ReversePaymentTransaction($input: ReversePaymentTransactionInput!) { reversePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardReversalStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "paymentTransactionId": "", "amount": { "value": 500, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "reversePaymentTransaction": { "__typename": "CardReversalStepSummary", "createdAt": "2025-10-29T15:34:39.465Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2025-10-29T15:34:39.465Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 500, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": { "value": 500, "currencyCode": "USD" }, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Capture Payment Transaction - Full Query: mutation CapturePaymentTransaction($input: CapturePaymentTransactionInput!) { capturePaymentTransaction(input: $input) { __typename ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "paymentTransactionId": "", "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "capturePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": null, "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-22T17:32:11.361Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "O4KBDO", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60038 } } } ### GraphQL: Capture Payment Transaction - Partial Query: mutation CapturePaymentTransaction($input: CapturePaymentTransactionInput!) { capturePaymentTransaction(input: $input) { __typename ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "paymentTransactionId": "", "merchantAcceptorId": "", "amount": { "value": 500, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "capturePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2025-10-29T15:51:40.966Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2025-10-29T15:51:40.966Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 500, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "G50650", "processorResponseCode": "APPROVED", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" } } } }, "extensions": { "requestId": "a262d929-d475-982e-ad7f-041b934bd7d2", "rateLimit": { "cost": 18, "limit": 2500, "remaining": 2482, "asOf": "2025-10-29T15:52:03.655Z", "complexity": { "limit": 2500, "remaining": 2482, "cost": 18 }, "count": { "limit": 100, "remaining": 99, "cost": 1 } } } } ### GraphQL: Capture Payment Transaction - Final Query: mutation CapturePaymentTransaction($input: CapturePaymentTransactionInput!) { capturePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { processorResponseCode addressCode postalCode securityCode authorizationCode processorResponseCode } } } } } Variables: { "input": { "paymentTransactionId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "captureType": "FINAL_CAPTURE", "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "capturePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2026-01-15T19:28:03.649Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2026-01-15T19:28:03.649Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED", "authorizationCode": "QBTHBA" } } } }, "extensions": { "requestId": "15b0c624-8b21-995c-a7f2-1c96299d6b67", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60018, "asOf": "2026-01-15T19:28:18.168Z", "complexity": { "limit": 60060, "remaining": 60018, "cost": 18 }, "count": { "limit": 60060, "remaining": 60053, "cost": 1 } } } } ### GraphQL: forceCapturePaymentTransaction Query: mutation ForceCapturePaymentTransaction( $input: ForceCapturePaymentTransactionInput! ) { forceCapturePaymentTransaction(input: $input) { __typename ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } capturedAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { processorResponseCode addressCode postalCode securityCode } } } ... on UserError { __typename errors { description code errorPath } } } } Variables: { "input": { "paymentTransactionId": "", "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "forceCapturePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2026-01-27T18:25:26.897Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2026-01-27T18:25:26.897Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 0, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "capturedAmount": { "value": 333, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" } } } } } ### GraphQL: Refund Payment Transaction - Full Query: mutation RefundPaymentTransaction($input: RefundPaymentTransactionInput!) { refundPaymentTransaction(input: $input) { __typename ... on CardCreditStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } originatedPaymentTransactionId } } } } Variables: { "input": { "paymentTransactionId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "refundReason": "CUSTOMER_REQUESTED" } } Expected Result: { "data": { "refundPaymentTransaction": { "__typename": "CardCreditStepSummary", "createdAt": null, "transaction": { "__typename": "PaymentCreditTransactionSummary", "id": "", "createdAt": "2024-02-22T17:33:52.116Z", "accountingDirection": "CREDIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": { "value": 1000, "currencyCode": "USD" }, "originatedPaymentTransactionId": "" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 17, "limit": 60060, "remaining": 60042 } } } ### GraphQL: Refund Payment Transaction - Partial Query: mutation RefundPaymentTransaction($input: RefundPaymentTransactionInput!) { refundPaymentTransaction(input: $input) { __typename ... on CardCreditStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } originatedPaymentTransactionId } } } } Variables: { "input": { "paymentTransactionId": "", "amount": { "value": 500, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "refundReason": "CUSTOMER_REQUESTED" } } Expected Result: { "data": { "refundPaymentTransaction": { "__typename": "CardCreditStepSummary", "createdAt": null, "transaction": { "__typename": "PaymentCreditTransactionSummary", "id": "", "createdAt": "2024-02-22T17:33:52.116Z", "accountingDirection": "CREDIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": { "value": 500, "currencyCode": "USD" }, "originatedPaymentTransactionId": "" } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 17, "limit": 60060, "remaining": 60042 } } } ### GraphQL: Capture Steps for Transaction Query: query CaptureStepsForTransaction($id: ID!) { node(id: $id) { __typename ... on PaymentTransaction { id steps { __typename ... on CardCaptureStep { id amount { value currencyCode } status createdAt } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "PaymentDebitTransaction", "id": "", "steps": [ { "__typename": "CardAuthorizedStep" }, { "__typename": "CardCaptureStep", "id": "", "amount": { "value": 1000, "currencyCode": "USD" }, "status": "COMPLETED", "createdAt": "2026-04-20T10:00:00Z" }, { "__typename": "CardCaptureStep", "id": "", "amount": { "value": 2500, "currencyCode": "USD" }, "status": "COMPLETED", "createdAt": "2026-05-20T10:00:00Z" }, { "__typename": "CardCaptureStep", "id": "", "amount": { "value": 1500, "currencyCode": "USD" }, "status": "PENDING", "createdAt": "2026-06-20T10:00:00Z" } ] } }, "extensions": { "requestId": "" } } ### GraphQL: Refund Capture Step Query: mutation RefundCaptureStep($input: RefundCaptureStepInput!) { refundCaptureStep(input: $input) { __typename ... on CardCreditStepSummary { amount { value currencyCode } createdAt transaction { __typename id refundedAmount { value currencyCode } originatedPaymentTransactionCaptureStep { id amount { value currencyCode } status createdAt } } } } } Variables: { "input": { "paymentTransactionId": "", "captureStepId": "", "amount": { "value": 2500, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "refundReason": "CUSTOMER_REQUESTED" } } Expected Result: { "data": { "refundCaptureStep": { "__typename": "CardCreditStepSummary", "amount": { "value": 2500, "currencyCode": "USD" }, "createdAt": "2026-04-22T12:00:00Z", "transaction": { "__typename": "PaymentCreditTransactionSummary", "id": "", "refundedAmount": { "value": 2500, "currencyCode": "USD" }, "originatedPaymentTransactionCaptureStep": { "id": "", "amount": { "value": 2500, "currencyCode": "USD" }, "status": "COMPLETED", "createdAt": "2026-04-20T10:00:00Z" } } } }, "extensions": { "requestId": "" } } ### GraphQL: Trace Refund to Capture Step Query: query PaymentCreditTransactionWithCaptureStep($id: ID!) { node(id: $id) { __typename ... on PaymentCreditTransaction { id refundReason originatedPaymentTransaction { id } originatedPaymentTransactionCaptureStep { id amount { value currencyCode } status createdAt events { __typename ... on CardPaymentCaptureProcessingEvent { amount { value currencyCode } createdAt acquirerReferenceNumber } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "PaymentCreditTransaction", "id": "", "refundReason": "CUSTOMER_REQUESTED", "originatedPaymentTransaction": { "id": "" }, "originatedPaymentTransactionCaptureStep": { "id": "", "amount": { "value": 2500, "currencyCode": "USD" }, "status": "COMPLETED", "createdAt": "2026-04-20T10:00:00Z", "events": [ { "__typename": "CardPaymentCaptureProcessingEvent", "amount": { "value": 2500, "currencyCode": "USD" }, "createdAt": "2026-04-20T10:00:00Z", "acquirerReferenceNumber": "123456789012345678901234" } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: ListPaymentTransactions Query: query ListPaymentTransactions($first: Int) { paymentTransactions(first: $first) { __typename pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id createdAt updatedAt steps { __typename createdAt amount { value currencyCode } transaction { id accountingDirection } events { __typename createdAt updatedAt amount { value currencyCode } } } status accountingDirection authorizedAmount { value currencyCode } authorizedAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } totalFeeAmount { value currencyCode } totalPayableAmount { value currencyCode } fees { __typename feeAmount { value currencyCode } accountingDirection } instrument { __typename ... on PaymentCardInstrument { createdAt last4 expiryYear expiryMonth brand } } ... on PaymentCreditTransaction { originatedPaymentTransaction { __typename id createdAt updatedAt } } ... on PaymentDebitTransaction { refunds { __typename id createdAt updatedAt } } } } } } Variables: { "first": 2 } Expected Result: { "data": { "paymentTransactions": { "__typename": "PaymentTransactionsConnection", "pageInfo": { "hasNextPage": true, "hasPreviousPage": false, "startCursor": "dD0yMDI0LTAyLTIyVDE3JTNBMzMlM0E1Mi4xMTYwMDAwMDBaJmk9YWNxcHRfYjZiYWU3NjY4M2UyNDdlOGI0MWQ1ZmRiYmVjNjkwNDQ", "endCursor": "dD0yMDI0LTAyLTIyVDE3JTNBMzIlM0ExMS4zNjEwMDAwMDBaJmk9YWNxcHRfYzY2ZjZlMDgxN2NjNDEzZmI0NTgxMjJhZTIwNTA4Y2Q" }, "edges": [ { "cursor": "dD0yMDI0LTAyLTIyVDE3JTNBMzMlM0E1Mi4xMTYwMDAwMDBaJmk9YWNxcHRfYjZiYWU3NjY4M2UyNDdlOGI0MWQ1ZmRiYmVjNjkwNDQ", "node": { "__typename": "PaymentCreditTransaction", "id": "", "createdAt": "2024-02-22T17:33:52.116Z", "updatedAt": "2024-02-22T17:33:52.118Z", "steps": [ { "__typename": "CardCapturedStep", "createdAt": "2024-02-22T17:33:52.177Z", "amount": { "value": 1000000000, "currencyCode": "USD" }, "transaction": { "id": "", "accountingDirection": "DEBIT" }, "events": [ { "__typename": "CardPaymentCapturingEvent", "createdAt": "2024-02-22T17:33:52.178Z", "updatedAt": "2024-02-22T17:33:52.178Z", "amount": { "value": 1000000000, "currencyCode": "USD" } } ] }, { "__typename": "CardAuthorizedStep", "createdAt": "2024-02-22T17:33:52.116Z", "amount": { "value": 1000000000, "currencyCode": "USD" }, "transaction": { "id": "", "accountingDirection": "DEBIT" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-02-22T17:33:52.177Z", "updatedAt": "2024-02-22T17:33:52.179Z", "amount": { "value": 1000000000, "currencyCode": "USD" } } ] } ], "status": "PENDING", "accountingDirection": "CREDIT", "authorizedAmount": null, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "84QNMZ", "processorResponseCode": "APPROVED", "addressCode": "UNSPECIFIED", "postalCode": "UNSPECIFIED", "securityCode": "UNSPECIFIED" }, "totalFeeAmount": { "value": 0, "currencyCode": "USD" }, "totalPayableAmount": { "value": 0, "currencyCode": "USD" }, "fees": null, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-02-22T17:33:52.116Z", "last4": "", "expiryYear": "31", "expiryMonth": "12", "brand": "VISA" }, "originatedPaymentTransaction": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-02-22T17:32:11.361Z", "updatedAt": "2024-02-22T17:32:11.380Z" } } }, { "cursor": "dD0yMDI0LTAyLTIyVDE3JTNBMzIlM0ExMS4zNjEwMDAwMDBaJmk9YWNxcHRfYzY2ZjZlMDgxN2NjNDEzZmI0NTgxMjJhZTIwNTA4Y2Q", "node": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-02-22T17:32:11.361Z", "updatedAt": "2024-02-22T17:32:11.380Z", "steps": [ { "__typename": "CardCapturedStep", "createdAt": "2024-02-22T17:32:28.122Z", "amount": { "value": 1000000000, "currencyCode": "USD" }, "transaction": { "id": "", "accountingDirection": "DEBIT" }, "events": [ { "__typename": "CardPaymentCapturingEvent", "createdAt": "2024-02-22T17:32:28.122Z", "updatedAt": "2024-02-22T17:32:28.122Z", "amount": { "value": 1000000000, "currencyCode": "USD" } } ] }, { "__typename": "CardAuthorizedStep", "createdAt": "2024-02-22T17:32:11.361Z", "amount": { "value": 1000000000, "currencyCode": "USD" }, "transaction": { "id": "", "accountingDirection": "DEBIT" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-02-22T17:32:11.380Z", "updatedAt": "2024-02-22T17:32:11.380Z", "amount": { "value": 1000000000, "currencyCode": "USD" } } ] } ], "status": "PENDING", "accountingDirection": "DEBIT", "authorizedAmount": null, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "O4KBDO", "authorizationResponseCode": "APPROVED", "addressCode": "UNSPECIFIED", "postalCode": "UNSPECIFIED", "securityCode": "UNSPECIFIED" }, "totalFeeAmount": { "value": 0, "currencyCode": "USD" }, "totalPayableAmount": { "value": 0, "currencyCode": "USD" }, "fees": null, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-02-22T17:32:11.361Z", "last4": "", "expiryYear": "31", "expiryMonth": "12", "brand": "VISA" }, "refunds": [ { "__typename": "PaymentCreditTransaction", "id": "", "createdAt": "2024-02-22T17:33:52.116Z", "updatedAt": "2024-02-22T17:33:52.118Z" } ] } } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 38, "limit": 60060, "remaining": 59659 } } } ### GraphQL: PaymentTransaction Query: fragment PaymentTransactionEvent on PaymentTransactionEvent { __typename createdAt updatedAt amount { value currencyCode } } query PaymentTransaction($id: ID!) { node(id: $id) { __typename ... on PaymentTransaction { id createdAt updatedAt steps { __typename createdAt amount { value currencyCode } events { ...PaymentTransactionEvent } transaction { id accountingDirection } } status events { ...PaymentTransactionEvent } accountingDirection authorizedAmount { value currencyCode } authorizedAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } totalFeeAmount { value currencyCode } totalPayableAmount { value currencyCode } fees { __typename feeAmount { value currencyCode } accountingDirection } instrument { __typename ... on PaymentCardInstrument { createdAt last4 expiryYear expiryMonth brand } } ... on PaymentCreditTransaction { originatedPaymentTransaction { __typename id createdAt updatedAt } } ... on PaymentDebitTransaction { refunds { __typename id createdAt updatedAt } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-02-17T06:26:54.892Z", "updatedAt": "2024-02-17T06:26:56.174Z", "steps": [ { "__typename": "CardAuthorizedStep", "createdAt": "2024-02-17T06:26:54.903Z", "amount": { "value": 1000000000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-02-17T06:26:55.962Z", "updatedAt": "2024-02-17T06:26:55.962Z", "amount": { "value": 1000000000, "currencyCode": "USD" } } ], "transaction": { "id": "", "accountingDirection": "DEBIT" } } ], "status": "PENDING", "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-02-17T06:26:55.962Z", "updatedAt": "2024-02-17T06:26:55.962Z", "amount": { "value": 1000000000, "currencyCode": "USD" } } ], "accountingDirection": "DEBIT", "authorizedAmount": null, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "authorizationCode": "FCV1U6", "addressCode": "UNSPECIFIED", "postalCode": "UNSPECIFIED", "securityCode": "UNSPECIFIED" }, "totalFeeAmount": null, "totalPayableAmount": null, "fees": null, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-02-17T06:26:54.880Z", "last4": "", "expiryYear": "31", "expiryMonth": "12", "brand": "VISA" }, "refunds": null } }, "extensions": { "requestId": "", "rateLimit": { "cost": 21, "limit": 60060, "remaining": 60039 } } } --- URL: https://docs.highnote.com/docs/acquiring/payments/payment-orders Title: Payment Orders Section: Acquiring Description: Create payment orders with catalog items and payment instructions to simplify payment collection and automated disbursement to financial accounts. ## Overview The Payment Orders API simplifies the Highnote acquiring offering by letting you easily define items for a [](/docs/api-reference/object#PaymentOrder) and enabling Highnote to manage the payment flow. ## Create a payment order A payment order can be created using [](/docs/api-reference/mutation#createPaymentOrder). This mutation takes [](/docs/api-reference/input#CreatePaymentOrderInput) which are pre-defined by Highnote for your merchant. These items have pre-defined names, descriptions, and amounts. All pre-defined data can be overwritten when invoking the mutation. [](/docs/api-reference/input#PaymentOrderItemFromCatalogItemInput) can take [](/docs/api-reference/input#PaymentInstructionInput) which define and automate disbursement regarding which accounts get what amounts. Payment Instructions can be defined to disburse a specific amount or a percentage of the item's amount. They also require a disburseToId (i.e., a Highnote ID) to disburse funds to. Currently only a ID can be used.> ## Charge a payment order with a payment method token Once the payment order has been created, a request to charge a (generated from the Checkout SDK) can proceed by using [](/docs/api-reference/mutation#chargePaymentOrderFromPaymentMethodToken). This mutation returns both the payment order charged and a new charging the token for the payment order amount. ## View a payment order A can be queried using the node query, which lists any associated with the . ### GraphQL: CreatePaymentOrderWithPaymentInstructions Query: mutation CreatePaymentOrderWithPaymentInstructions( $input: CreatePaymentOrderInput! ) { createPaymentOrder(input: $input) { ... on PaymentOrder { __typename id totalAmount { __typename value currencyCode decimalPlaces } lineItems { item { __typename ... on PaymentOrderItemFromCatalogItem { catalogItem { id name description } name description amountPerItem { __typename value currencyCode decimalPlaces } } } quantity } } } } Variables: { "input": { "catalogItems": [ { "id": "acqca_1", "name": "Apple", "description": "A delicious red apple", "amountPerItem": { "value": 100, "currencyCode": "USD" }, "paymentInstructions": [ { "disbursementPercent": 100, "disburseToId": "ac_apple_seller" } ], "quantity": 1 }, { "id": "acqca_2", "name": "Orange", "description": "A juicy orange bursting with flavor", "amountPerItem": { "value": 100, "currencyCode": "USD" }, "paymentInstructions": [ { "disbursementPercent": 100, "disburseToId": "ac_orange_seller" } ], "quantity": 1 } ], "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "createPaymentOrder": { "__typename": "PaymentOrder", "id": "acqor_1", "totalAmount": { "__typename": "Amount", "value": 200, "currencyCode": "USD", "decimalPlaces": 2 }, "lineItems": [ { "item": { "__typename": "PaymentOrderItemFromCatalogItem", "catalogItem": { "id": "acqca_1", "name": "Apple", "description": "A delicious red apple" }, "name": "Apple", "description": "A delicious red apple", "amountPerItem": { "__typename": "Amount", "value": 100, "currencyCode": "USD", "decimalPlaces": 2 } }, "quantity": 1 }, { "item": { "__typename": "PaymentOrderItemFromCatalogItem", "catalogItem": { "id": "acqca_2", "name": "Orange", "description": "A juicy orange bursting with flavor" }, "name": "Orange", "description": "A juicy orange bursting with flavor", "amountPerItem": { "__typename": "Amount", "value": 100, "currencyCode": "USD", "decimalPlaces": 2 } }, "quantity": 1 } ] } } } ### GraphQL: ChargePaymentOrderPaymentMethodToken Query: mutation ChargePaymentOrderPaymentMethodToken( $input: ChargePaymentOrderPaymentMethodTokenInput! ) { chargePaymentOrderFromPaymentMethodToken(input: $input) { ... on CardCapturePaymentOrderSummary { transaction { requestedAuthorizationAmount { __typename value currencyCode decimalPlaces } } order { __typename id totalAmount { __typename value currencyCode decimalPlaces } lineItems { item { __typename name description amountPerItem { __typename value currencyCode decimalPlaces } } quantity } } } } } Variables: { "input": { "paymentMethodTokenId": "", "orderId": "", "merchantAcceptorId": "", "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "chargePaymentOrderFromPaymentMethodToken": { "transaction": { "requestedAuthorizationAmount": { "__typename": "Amount", "value": 200, "currencyCode": "USD", "decimalPlaces": 2 } }, "order": { "__typename": "PaymentOrder", "id": "", "totalAmount": { "__typename": "Amount", "value": 200, "currencyCode": "USD", "decimalPlaces": 2 }, "lineItems": [ { "item": { "__typename": "PaymentOrderItemFromCatalogItem", "name": "Apple", "description": "A delicious red apple", "amountPerItem": { "__typename": "Amount", "value": 100, "currencyCode": "USD", "decimalPlaces": 2 } }, "quantity": 1 }, { "item": { "__typename": "PaymentOrderItemFromCatalogItem", "name": "Orange", "description": "A juicy orange bursting with flavor", "amountPerItem": { "__typename": "Amount", "value": 100, "currencyCode": "USD", "decimalPlaces": 2 } }, "quantity": 1 } ] } } } } ### GraphQL: PaymentOrder Query: query PaymentOrder($id: ID!) { node(id: $id) { ... on PaymentOrder { totalAmount { __typename value currencyCode decimalPlaces } transactions { __typename id settledAmount { __typename value currencyCode decimalPlaces } refundedAmount { __typename value currencyCode decimalPlaces } } } } } Variables: { "id": "acqor_1" } Expected Result: { "data": { "node": { "totalAmount": { "__typename": "Amount", "value": 200, "currencyCode": "USD", "decimalPlaces": 2 }, "transactions": [ { "__typename": "PaymentDebitTransaction", "id": "acqpt_1", "settledAmount": { "__typename": "Amount", "value": 200, "currencyCode": "USD", "decimalPlaces": 2 }, "refundedAmount": null }, { "__typename": "PaymentCreditTransaction", "id": "acqpt_2", "settledAmount": null, "refundedAmount": { "__typename": "Amount", "value": 200, "currencyCode": "USD", "decimalPlaces": 2 } } ] } } } --- URL: https://docs.highnote.com/docs/acquiring/payments/credential-on-file/cof-installments Title: Credential on File Installments Section: Acquiring Description: Split a payment into multiple scheduled installments using Credential on File. The first payment is customer-initiated (CIT) and follow-on payments are merchant-initiated (MIT). Includes Mastercard Single Authorization Multiple Capture (SAMC). ## Overview Merchant-managed installment payments enable the splitting of purchases into multiple scheduled payments for cards, payment method tokens, and network tokens. ### CIT / MIT model Installment payments follow the customer-initiated transaction (CIT) and merchant-initiated transaction (MIT) model defined in Credential On File Payments: - The first installment is sent as a CIT with full customer authentication. - Follow-on installments are sent as scheduled MITs referencing the initial CIT. CIT establishes consent and returns a . MIT uses that network ID to prove the charge traces back to valid cardholder consent. #### CIT payment 1 (first installment) - Use as the payment initiator - Set : true in - Provide installment details: , total amount, frequency, etc. - Response returns both a AND a #### MIT payments 2-n (subsequent installments) - Use as the payment initiator - Pass in - Pass in (from CIT response: ) - Increment for each payment ### Installment payment data Querying payment data can take 3-5 minutes to appear after a PaymentTransactionEvent is created, due to synchronization between databases. Both authorization and charge mutations (for supported input types PaymentCard, NetworkToken, and PaymentMethodToken) accept an **installmentPayment** object in the input. When provided, the resulting PaymentDebitTransaction is associated with a MerchantManagedInstallmentPayment. To build a list of PaymentTransactions that includes installment details, query the paymentTransactionsConnection and select the field on the PaymentDebitTransaction type. See Find all payment transactions and Find a payment transaction for the relevant queries. ### Highnote vs network tokens | Aspect | Payment Method Token | Network Token | | :--------- | :------------------------------- | :--------------------------------------------------------------- | | Created by | Highnote (internal tokenization) | Card networks (Visa, Mastercard) or Token Service Provider (TSP) | | Storage | Highnote's secure vault | External vault | | ID format | prefix | Raw token number + cryptogram | | Use case | Internal COF transactions | External COF transactions | ### Supported mutations | Operation | Mutation / Query | | :----------------------------- | :------------------------------------------------------------- | | Authorize card | authorizePaymentCard | | Authorize payment method token | authorizePaymentMethodToken | | Authorize network token | authorizeNetworkToken | | Charge card | chargePaymentCard | | Charge payment method token | chargePaymentMethodToken | | Charge network token | chargeNetworkToken | ## Payment cards Authorizations must be captured with the capturePaymentTransaction mutation. Charges = authorization + capture. Use the following mutations for standard card payments. ### Authorize payment card The authorizePaymentCard mutation creates an authorization on a card for a merchant managed installment payment when installment-specific fields are provided in the input. This associates the resulting PaymentDebitTransaction with a merchant‑managed installment payment. #### Customer-initiated transaction First installment with cardholder present. Sets to establish the credential on file. #### Merchant-initiated transaction = CIT Subsequent installment using stored credentials. References the first payment via and . ### Charge payment card The chargePaymentCard mutation creates a capture on a card for a merchant‑managed installment payment when installment-specific fields are provided in the input. This associates the resulting PaymentDebitTransaction with a merchant‑managed installment payment. #### Customer-initiated transaction First installment with cardholder present. Sets to establish the credential on file. #### Merchant-initiated transaction = CIT Subsequent installment using stored credentials. References the first payment via and . ## Payment method tokens Authorizations must be captured with the capturePaymentTransaction mutation. Charges = authorization + capture. Use the following mutations for payment method token transactions. Payment method tokens are used by Highnote for internal COF transactions. They have the prefix and are stored in Highnote's secure vault. ### Authorize payment method token The authorizePaymentMethodToken mutation creates an authorization on a payment method token for a merchant‑managed installment payment when installment-specific fields are provided in the input. This associates the resulting PaymentDebitTransaction with a merchant‑managed installment payment. #### Customer-initiated transaction First installment with cardholder present. Sets to establish the credential on file. #### Merchant-initiated transaction = CIT Subsequent installment using stored credentials. References the first payment via and . ### Charge payment method token The chargePaymentMethodToken mutation creates a capture on a payment method token for a merchant‑managed installment payment when installment-specific fields are provided in the input. This associates the resulting PaymentDebitTransaction with a merchant‑managed installment payment. #### Customer-initiated transaction First installment with cardholder present. Sets to establish the credential on file. #### Merchant-initiated transaction = CIT Subsequent installment using stored credentials. References the first payment via and . ## Network tokens Authorizations must be captured with the capturePaymentTransaction mutation. Charges = authorization + capture. Use the following mutations for network token transactions. Network tokens are used by the card networks for COF transactions external to Highnote. They are comprised of a raw network token number + cryptogram. ### Authorize network token The authorizeNetworkToken mutation creates an authorization on a network token for a merchant‑managed installment payment when installment-specific fields are provided in the input. This associates the resulting PaymentDebitTransaction with a merchant‑managed installment payment. #### Customer-initiated transaction First installment with cardholder present. Sets to establish the credential on file. #### Merchant-initiated transaction = CIT Subsequent installment using stored credentials. References the first payment via and . ### Charge network token The chargeNetworkToken mutation creates a capture on a network token for a merchant‑managed installment payment when installment-specific fields are provided in the input. This associates the resulting PaymentDebitTransaction with a merchant‑managed installment payment. #### Customer-initiated transaction First installment with cardholder present. Sets to establish the credential on file. #### Merchant-initiated transaction = CIT Subsequent installment using stored credentials. References the first payment via and . ## Mastercard single authorization multiple capture (SAMC) Mastercard single authorization multiple capture (SAMC) supports the ability to authorize the full amount in a single authorization, while capturing each authorization in multiple installments. #### Single authorization multiple capture Assume a $1000 purchase is to be paid back in four installments of $250: 1. Make one CIT authorization for the full installment amount ($1000). 2. Capture each installment amount ($250 each month for 4 months). 3. Monitor the expiration date for the first CIT authorization (valid for 30 days). To extend for another 30 days, see Request $0 incremental authorization in the Incremental Authorization docs. ### Authorize SAMC network token #### Customer-initiated transaction Using Mastercard SAMC, make one customer-initiated transaction network token authorization for the full amount of the payment. ### Capture SAMC partial amount After making a single authorization for the full amount of $1000, use the following mutation multiple times to capture each installment amount of $250. ### Extend SAMC expiration date You can extend the expiration date of the original SAMC authorization by running a zero dollar incremental authorization. ### GraphQL: authorizePaymentCard Query: mutation AuthorizePaymentCard($input: AuthorizePaymentCardInput!) { authorizePaymentCard(input: $input) { ... on CardAuthorizationStepSummary { transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { __typename value currencyCode decimalPlaces } numberOfInstallments paymentAmount { __typename value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { __typename value currencyCode decimalPlaces } } } } } } Variables: { "input": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12", "securityCode": "111" }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_INSTALLMENT_FIRST", "externalCredentialOnFile": { "intendToStore": true }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "value": 0, "currencyCode": "USD" } } } } Expected Result: { "data": { "authorizePaymentCard": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } } } } } ### GraphQL: authorizePaymentCard Query: mutation AuthorizePaymentCard($input: AuthorizePaymentCardInput!) { authorizePaymentCard(input: $input) { ... on CardAuthorizationStepSummary { createdAt transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { value currencyCode decimalPlaces } numberOfInstallments paymentAmount { value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { value currencyCode decimalPlaces } firstInstallmentPaymentTransaction { ... on PaymentDebitTransaction { id } } } } } } } Variables: { "input": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12" }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "NEW_UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_INSTALLMENT", "externalCredentialOnFile": { "networkTransactionIdentifier": "532675987658354" }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD" }, "firstInstallmentPaymentTransactionId": "" } } } Expected Result: { "data": { "authorizePaymentCard": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "firstInstallmentPaymentTransaction": { "id": "" } } } } } } ### GraphQL: chargePaymentCard Query: mutation ChargePaymentCard($input: ChargePaymentCardInput!) { chargePaymentCard(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id networkTransactionIdentifier installmentPayment { ... on MerchantManagedInstallmentPayment { fundedAmount { currencyCode decimalPlaces value } firstInstallmentPaymentTransaction { ... on PaymentDebitTransaction { id } } firstPaymentDate frequency numberOfInstallments paymentAmount { currencyCode decimalPlaces value } paymentNumber totalAmount { currencyCode decimalPlaces value } } } } } } } Variables: { "input": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12", "securityCode": "111" }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_INSTALLMENT_FIRST", "externalCredentialOnFile": { "intendToStore": true }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "value": 0, "currencyCode": "USD" } } } } Expected Result: { "data": { "chargePaymentCard": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } } } } } ### GraphQL: chargePaymentCard Query: mutation ChargePaymentCard($input: ChargePaymentCardInput!) { chargePaymentCard(input: $input) { ... on CardCaptureStepSummary { createdAt transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { value currencyCode decimalPlaces } numberOfInstallments paymentAmount { value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { value currencyCode decimalPlaces } firstInstallmentPaymentTransaction { ... on PaymentDebitTransaction { id } } } } } } } Variables: { "input": { "paymentCard": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12" }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "NEW_UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_INSTALLMENT", "externalCredentialOnFile": { "networkTransactionIdentifier": "532675987658354" }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD" }, "firstInstallmentPaymentTransactionId": "" } } } Expected Result: { "data": { "chargePaymentCard": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "firstInstallmentPaymentTransaction": { "id": "" } } } } } } ### GraphQL: authorizePaymentMethodToken Query: mutation AuthorizePaymentMethodToken( $input: AuthorizePaymentMethodTokenInput! ) { authorizePaymentMethodToken(input: $input) { ... on CardAuthorizationStepSummary { transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { __typename value currencyCode decimalPlaces } numberOfInstallments paymentAmount { __typename value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { __typename value currencyCode decimalPlaces } } } } } } Variables: { "input": { "paymentMethodTokenId": "", "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_INSTALLMENT_FIRST", "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "value": 0, "currencyCode": "USD" } } } } Expected Result: { "data": { "authorizePaymentMethodToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } } } } } ### GraphQL: authorizePaymentMethodToken Query: mutation AuthorizePaymentMethodToken( $input: AuthorizePaymentMethodTokenInput! ) { authorizePaymentMethodToken(input: $input) { ... on CardAuthorizationStepSummary { createdAt transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { value currencyCode decimalPlaces } numberOfInstallments paymentAmount { value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { value currencyCode decimalPlaces } firstInstallmentPaymentTransaction { ... on PaymentDebitTransaction { id } } } } } } } Variables: { "input": { "paymentMethodTokenId": "", "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "NEW_UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_INSTALLMENT", "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD" }, "firstInstallmentPaymentTransactionId": "" } } } Expected Result: { "data": { "authorizePaymentMethodToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "firstInstallmentPaymentTransaction": { "id": "" } } } } } } ### GraphQL: chargePaymentMethodToken Query: mutation ChargePaymentMethodToken($input: ChargePaymentMethodTokenInput!) { chargePaymentMethodToken(input: $input) { ... on CardCaptureStepSummary { transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { __typename value currencyCode decimalPlaces } numberOfInstallments paymentAmount { __typename value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { __typename value currencyCode decimalPlaces } } } } } } Variables: { "input": { "paymentMethodTokenId": "", "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_INSTALLMENT_FIRST", "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "value": 0, "currencyCode": "USD" } } } } Expected Result: { "data": { "chargePaymentMethodToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } } } } } ### GraphQL: chargePaymentMethodToken Query: mutation ChargePaymentMethodToken($input: ChargePaymentMethodTokenInput!) { chargePaymentMethodToken(input: $input) { ... on CardCaptureStepSummary { createdAt transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { value currencyCode decimalPlaces } numberOfInstallments paymentAmount { value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { value currencyCode decimalPlaces } firstInstallmentPaymentTransaction { ... on PaymentDebitTransaction { id } } } } } } } Variables: { "input": { "paymentMethodTokenId": "", "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "NEW_UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_INSTALLMENT", "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD" }, "firstInstallmentPaymentTransactionId": "" } } } Expected Result: { "data": { "chargePaymentMethodToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "firstInstallmentPaymentTransaction": { "id": "" } } } } } } ### GraphQL: authorizeNetworkToken Query: mutation AuthorizeNetworkToken($input: AuthorizeNetworkTokenInput!) { authorizeNetworkToken(input: $input) { ... on CardAuthorizationStepSummary { transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { __typename value currencyCode decimalPlaces } numberOfInstallments paymentAmount { __typename value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { __typename value currencyCode decimalPlaces } } } } } } Variables: { "input": { "networkToken": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12", "networkTokenization": { "cryptogram": "test-cryptogram" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_INSTALLMENT_FIRST", "externalCredentialOnFile": { "intendToStore": true }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "value": 0, "currencyCode": "USD" } } } } Expected Result: { "data": { "authorizeNetworkToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } } } } } ### GraphQL: authorizeNetworkToken Query: mutation AuthorizeNetworkToken($input: AuthorizeNetworkTokenInput!) { authorizeNetworkToken(input: $input) { ... on CardAuthorizationStepSummary { createdAt transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { value currencyCode decimalPlaces } numberOfInstallments paymentAmount { value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { value currencyCode decimalPlaces } firstInstallmentPaymentTransaction { ... on PaymentDebitTransaction { id } } } } } } } Variables: { "input": { "networkToken": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12", "networkTokenization": { "cryptogram": "test-cryptogram" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "NEW_UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_INSTALLMENT", "externalCredentialOnFile": { "networkTransactionIdentifier": "532675987658354" }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD" }, "firstInstallmentPaymentTransactionId": "" } } } Expected Result: { "data": { "authorizeNetworkToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "firstInstallmentPaymentTransaction": { "id": "" } } } } } } ### GraphQL: chargeNetworkToken Query: mutation ChargeNetworkToken($input: ChargeNetworkTokenInput!) { chargeNetworkToken(input: $input) { ... on CardCaptureStepSummary { transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { __typename value currencyCode decimalPlaces } numberOfInstallments paymentAmount { __typename value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { __typename value currencyCode decimalPlaces } } } } } } Variables: { "input": { "networkToken": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12", "networkTokenization": { "cryptogram": "test-cryptogram" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_INSTALLMENT_FIRST", "externalCredentialOnFile": { "intendToStore": true }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "value": 0, "currencyCode": "USD" } } } } Expected Result: { "data": { "chargeNetworkToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 1, "fundedAmount": { "__typename": "Amount", "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } } } } } ### GraphQL: chargeNetworkToken Query: mutation ChargeNetworkToken($input: ChargeNetworkTokenInput!) { chargeNetworkToken(input: $input) { ... on CardCaptureStepSummary { createdAt transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { value currencyCode decimalPlaces } numberOfInstallments paymentAmount { value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { value currencyCode decimalPlaces } firstInstallmentPaymentTransaction { ... on PaymentDebitTransaction { id } } } } } } } Variables: { "input": { "networkToken": { "cardNumber": "4000000000000002", "expiryYear": "29", "expiryMonth": "12", "networkTokenization": { "cryptogram": "test-cryptogram" } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "NEW_UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_INSTALLMENT", "externalCredentialOnFile": { "networkTransactionIdentifier": "532675987658354" }, "installmentPayment": { "totalAmount": { "value": 6000, "currencyCode": "USD" }, "numberOfInstallments": 6, "paymentAmount": { "value": 1000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "value": 1000, "currencyCode": "USD" }, "firstInstallmentPaymentTransactionId": "" } } } Expected Result: { "data": { "chargeNetworkToken": { "transaction": { "id": "", "networkTransactionIdentifier": "532675987658354", "installmentPayment": { "__typename": "MerchantManagedInstallmentPayment", "totalAmount": { "__typename": "Amount", "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 }, "numberOfInstallments": 6, "paymentAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-15", "paymentNumber": 2, "fundedAmount": { "__typename": "Amount", "value": 1000, "currencyCode": "USD", "decimalPlaces": 2 }, "firstInstallmentPaymentTransaction": { "id": "" } } } } } } ### GraphQL: authorizeNetworkToken Query: mutation AuthorizeNetworkToken($input: AuthorizeNetworkTokenInput!) { authorizeNetworkToken(input: $input) { ... on CardAuthorizationStepSummary { transaction { id networkTransactionIdentifier installmentPayment { __typename totalAmount { __typename value currencyCode decimalPlaces } numberOfInstallments paymentAmount { __typename value currencyCode decimalPlaces } frequency firstPaymentDate paymentNumber fundedAmount { __typename value currencyCode decimalPlaces } } responseCode { addressCode postalCode securityCode authorizationCode processorResponseCode } } } } } Variables: { "input": { "networkToken": { "cardNumber": "5555555555554444", "expiryYear": "29", "expiryMonth": "12", "networkTokenization": { "cryptogram": "MKTfCToAAATiAAdDNDaQAAADFAA=" } }, "merchantAcceptorId": "", "amount": { "value": 100000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_INSTALLMENT_FIRST", "externalCredentialOnFile": { "intendToStore": true }, "installmentPayment": { "totalAmount": { "value": 100000, "currencyCode": "USD" }, "numberOfInstallments": 4, "paymentAmount": { "value": 25000, "currencyCode": "USD" }, "frequency": "MONTHLY", "firstPaymentDate": "2025-01-23", "paymentNumber": 1, "fundedAmount": { "value": 100000, "currencyCode": "USD" }, "networkData": { "mastercardData": { "singleAuthorizationMultipleCaptures": true } } } } } Expected Result: { "data": { "authorizeNetworkToken": { "__typename": "CardAuthorizationStepSummary", "createdAt": "2026-01-23T22:43:53.906Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2026-01-23T22:43:53.906Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 100000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 100000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "MCCV42I4WSLL", "responseCode": { "authorizationCode": "QYD9KN", "processorResponseCode": "APPROVED", "addressCode": "MATCHED", "postalCode": "MATCHED", "securityCode": "NOT_PROVIDED" }, "installmentPayment": { "fundedAmount": { "currencyCode": "USD", "decimalPlaces": 2, "value": 0 }, "firstInstallmentPaymentTransaction": null, "firstPaymentDate": "2026-01-23", "frequency": "MONTHLY", "numberOfInstallments": 4, "paymentAmount": { "currencyCode": "USD", "decimalPlaces": 2, "value": 25000 }, "paymentNumber": 1, "totalAmount": { "currencyCode": "USD", "decimalPlaces": 2, "value": 100000 } }, "instrument": { "cardHolder": { "email": "", "fullName": "", "billingAddress": { "postalCode": "21345", "streetAddress": "2134 Mastercard St", "countryCodeAlpha3": "USA" } } } } } } } ### GraphQL: capturePaymentTransaction Query: mutation CapturePaymentTransaction($input: CapturePaymentTransactionInput!) { capturePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { processorResponseCode addressCode postalCode securityCode authorizationCode processorResponseCode } } } } } Variables: { "input": { "paymentTransactionId": "", "amount": { "value": 25000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4" } } Expected Result: { "data": { "capturePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2026-01-23T22:58:25.607Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2026-01-23T22:58:25.607Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 100000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 75000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED", "authorizationCode": "0GJCIX" } } } } } --- URL: https://docs.highnote.com/docs/acquiring/payments/credential-on-file/cof-payments Title: Credential on File Payments Section: Acquiring Description: Reuse stored payment card details for unscheduled and recurring purchases with Credential on File (COF). Supports internal and external COF transactions with network token integration. ## Overview Credential on File (COF) refers to payment card details stored within Highnote’s platform and authorized by the cardholder for making future purchases without re-entering card details. Transactions are categorized as customer-initiated (CIT) or merchant-initiated (MIT), with specific processes for each. COF scenarios include unscheduled, recurring, and installment transactions, each with distinct initiation methods. Credential On File (COF) transactions can be internal or external, with support for both raw card details and network tokens. External COF transactions require a network transaction identifier from a CIT to process further MIT transactions. The examples on this page use the consolidated [](/docs/api-reference/mutation#chargePaymentTransaction) mutation, which accepts raw card details or a network token through its input. To move an existing integration from the credential-specific mutations, see the migration guide. ## Concepts Credential on File (COF) is a saved payment card authorized for use. The Highnote platform uses the stored credentials, including the primary account number (PAN) and expiration date, to process future transactions without requiring the customer to re-enter their information or authorization. ### CIT and MIT COF transactions are either customer-initiated (CIT) or merchant-initiated (MIT). **Customer-initiated (CIT):** The cardholder actively participates in the transaction. - CIT COF transactions can represent the first transaction for a subscription service or a one-time payment using a previously stored method. **Merchant-initiated (MIT):** The merchant is the active participant for the transaction. - MIT COF transactions can be one-time payments (unscheduled) or recurring payments related to subscriptions. - The cardholder must have previously given permission to your system for Highnote to store their payment method for future use. ### Internal and external Highnote’s platform supports internal and external COF transactions, providing the flexibility and security to match your program’s needs. - **Internal COF transactions** use tokenized payment card details stored within the Highnote platform's secure vault. - **External COF transactions** use a third-party token service provider (TSP) with either raw payment card details or a network token. ### Scenarios Highnote’s platform supports the following use cases for COF transactions: - **Unscheduled:** Your system can initiate a COF transaction at any time for situations such as reloading a balance or collecting payment after conditions have been met. - **Recurring:** Your system can set up COF transactions on a schedule to handle scenarios such as subscription payments. - **Installment:** Your system may support paying for purchases over time with repeated partial authorizations through COF transactions. ## Processing Your platform must create COF transactions with an **AcquiringPaymentInitiator** enum set. You must first complete a customer-initiated transaction (CIT) before your system can initiate merchant-initiated (MIT) transactions. | Type | Customer-initiated Value | Merchant-initiated Value | | :---------- | :----------------------------------- | :----------------------------- | | Unscheduled | CUSTOMER_INITIATED_VIA_WEB | MERCHANT_INITIATED_UNSCHEDULED | | Recurring | CUSTOMER_INITIATED_RECURRING_FIRST | MERCHANT_INITIATED_RECURRING | | Installment | CUSTOMER_INITIATED_INSTALLMENT_FIRST | MERCHANT_INITIATED_INSTALLMENT | ### Network transaction identifier Network transaction identifier chaining applies to external COF only. Save the from the CIT response, then set it on each subsequent MIT with the input: ```json title="MIT input (excerpt)" { "paymentInitiator": "MERCHANT_INITIATED_UNSCHEDULED", "externalCredentialOnFile": { "networkTransactionIdentifier": "abc123xyz..." } } ``` ### Unscheduled transactions To initiate unscheduled COF payments, your system uses the enum value . You begin by processing the CIT with ; further transactions use the value . ### Recurring transactions To initiate recurring COF payments, your system uses the enum value . You begin by processing the CIT with to indicate that the customer has agreed to store the payment method for recurring payments; further transactions use the value . ### Installment transactions To initiate recurring COF payments, your system uses the enum value . You begin by processing the CIT with to indicate that the customer has agreed to store the payment method for installment payments; further transactions use the value . ## External COF (raw) External COF transactions use a third-party token service provider (TSP) with either raw payment card details or a network token. This section describes how to use a TSP with raw payment card details. ### Customer-initiated (CIT) {#cit-raw} To begin, your platform must process a transaction with one of the "" AcquiringPaymentInitiator values set on the acquiring mutation and the object set with . #### Operation Define an acquiring mutation, such as with the credential member, requesting the properties you may need for your use case along with the . #### Input - Set the as one of the AcquiringPaymentInitiator values. - Set inside the credential member with the value . Save the resulting to process further transactions. ### Merchant-initiated (MIT) {#mit-raw} To process further transactions, use a "" AcquiringPaymentInitiator values set on the acquiring mutation and the object set with from a customer initiated transaction. #### Operation Define an acquiring mutation, such as with the credential member, requesting the properties you may need for your use case. #### Input - Set the as one of the AcquiringPaymentInitiator values. - Set inside the credential member with the value from a previous customer initiated transaction. ## External COF (token) **Network token** transactions work like external COF transactions with the exception that instead of providing the payment card’s raw details, your system supplies a object that includes a cryptogram and a provided by the card network or a TSP. ### Customer-initiated (CIT) {#cit-token} To begin, your platform must process a transaction with one of the AcquiringPaymentInitiator values set on the acquiring mutation and the object set with . You can also process subsequent CIT unscheduled transactions as + . #### Operation Define an acquiring mutation, such as with the credential member, requesting the properties you may need for your use case along with the . #### Input - Set the paymentInitiator as one of the AcquiringPaymentInitiator values. - Set inside the credential member with the value . Save the resulting to process further transactions. ### Merchant-initiated (MIT) {#mit-token} To process further transactions, use a AcquiringPaymentInitiator values set on the acquiring mutation and the object set with from a customer initiated transaction. #### Operation Define an acquiring mutation, such as with the credential member, requesting the properties you may need for your use case. #### Input - Set paymentInitiator as one of the AcquiringPaymentInitiator values. - Set inside the credential member with the value from a previous customer initiated transaction. ### GraphQL: Charge Payment Transaction - CIT with Payment Card Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentCard": { "cardNumber": "4229989999000012", "expiryYear": "31", "expiryMonth": "12", "securityCode": "871", "cardHolder": { "billingAddress": { "streetAddress": "street-address", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Los Angeles", "region": "California", "postalCode": "90210" } }, "externalCredentialOnFile": { "intendToStore": true } } }, "merchantAcceptorId": "", "amount": { "value": 1000, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_VIA_WEB" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2024-02-21T17:46:00.650Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-21T17:46:00.650Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "978647564526179", "responseCode": { "authorizationCode": "H7JRNX", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_VERIFIED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Charge Payment Transaction - MIT with Payment Card Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "paymentCard": { "cardNumber": "4229989999000012", "expiryYear": "31", "expiryMonth": "12", "externalCredentialOnFile": { "networkTransactionIdentifier": "" } } }, "merchantAcceptorId": "", "amount": { "value": 100, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_UNSCHEDULED" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2024-02-21T17:46:00.650Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2024-02-21T17:46:00.650Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 100, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "942385099517320", "responseCode": { "authorizationCode": "XQIY75", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_PROVIDED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Charge Payment Transaction - CIT with Network Token Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "networkToken": { "cardNumber": "4000000000000002", "expiryYear": "31", "expiryMonth": "12", "networkTokenization": { "cryptogram": "test-cryptogram", "tokenRequestorIdentifier": "01234567891" }, "cardHolder": { "fullName": "First Last", "billingAddress": { "streetAddress": "street-address", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Los Angeles", "region": "California", "postalCode": "90210" } }, "externalCredentialOnFile": { "intendToStore": true } } }, "merchantAcceptorId": "", "amount": { "value": 106, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "CUSTOMER_INITIATED_RECURRING_FIRST" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2025-11-25T19:51:23.178Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2025-11-25T19:51:23.178Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 106, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "978647564526179", "responseCode": { "authorizationCode": "H7JRNX", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_PROVIDED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } ### GraphQL: Charge Payment Transaction - MIT with Network Token Query: mutation ChargePaymentTransaction($input: ChargePaymentTransactionInput!) { chargePaymentTransaction(input: $input) { __typename ... on UserError { errors { errorPath code description } } ... on CardCaptureStepSummary { createdAt transaction { __typename id createdAt accountingDirection authorizedAmount { value currencyCode } authorizedRemainingAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } networkTransactionIdentifier responseCode { authorizationCode processorResponseCode addressCode postalCode securityCode } } } } } Variables: { "input": { "credential": { "networkToken": { "cardNumber": "4000000000000002", "expiryYear": "31", "expiryMonth": "12", "networkTokenization": { "cryptogram": "test-cryptogram" }, "cardHolder": { "fullName": "First Last", "billingAddress": { "streetAddress": "street-address", "countryCodeAlpha3": "USA", "extendedAddress": "extended-address", "locality": "Los Angeles", "region": "California", "postalCode": "90210" } }, "externalCredentialOnFile": { "networkTransactionIdentifier": "" } } }, "merchantAcceptorId": "", "amount": { "value": 101, "currencyCode": "USD" }, "idempotencyKey": "UUID_v4", "paymentInitiator": "MERCHANT_INITIATED_UNSCHEDULED" } } Expected Result: { "data": { "chargePaymentTransaction": { "__typename": "CardCaptureStepSummary", "createdAt": "2025-11-25T19:52:04.528Z", "transaction": { "__typename": "PaymentDebitTransactionSummary", "id": "", "createdAt": "2025-11-25T19:52:04.528Z", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 101, "currencyCode": "USD" }, "authorizedRemainingAmount": { "value": 0, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "networkTransactionIdentifier": "942385099517320", "responseCode": { "authorizationCode": "XQIY75", "processorResponseCode": "APPROVED", "addressCode": "NOT_PROVIDED", "postalCode": "NOT_PROVIDED", "securityCode": "NOT_PROVIDED" } } } }, "extensions": { "requestId": "", "rateLimit": { "cost": 18, "limit": 60060, "remaining": 60041 } } } --- URL: https://docs.highnote.com/docs/acquiring/pricing/merchant-pricing Title: Merchant Pricing Section: Acquiring Description: Define how acquiring processing charges are calculated for a merchant with pricing plans, validate them with simulation, and apply them with pricing configurations. ## Overview Merchant pricing lets you **define** how processing charges are calculated for a merchant and then **apply** those charges over a chosen time period. A [](/docs/api-reference/object#PricingPlan) holds a set of [](/docs/api-reference/object#PricingRule) records. Each rule references a Highnote-managed rule template and supplies the parameter values that template expects. A published plan is applied to a merchant during onboarding through a [](/docs/api-reference/object#PricingConfiguration), which sets the period the plan is in effect. ## Key concepts | Concept | Definition | | :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Named container for the rules that calculate a merchant's charges. Moves through a → → lifecycle. | | | Single charge within a plan. Supplies a rule template ( on input, returned as ) and defines when it is evaluated through its and . | | | Name-value pair that supplies an input the rule template expects (for example, a fixed fee or a percentage). | | | Associates a published plan with a merchant and a validity window ( through an optional ). | | | Lifecycle state of a plan: , , or . A plan's rules are set at creation and cannot be changed afterward. | ## Pricing plan lifecycle A pricing plan is created in with its full set of rules, and cannot be changed after the plan is created. While a plan is in it can be simulated but is not yet applied to transactions. Publishing makes the plan live for transaction processing. A plan that is no longer in use moves to , where it is retained for historical records and no longer applied to transactions. | Step | Action | Plan status | | :--- | :---------------------------------------------------------------------------------------- | :---------- | | 1 | Create a plan with its rules. | | | 2 | Simulate the plan against sample transactions to confirm the charges calculate correctly. | | | 3 | Publish the plan to make it live for transaction processing. | | A plan's rules are fixed when it is created — there is no operation to change a rule afterward. To revise pricing, create a new plan, simulate it, and publish it. ## Rule templates Each rule supplies a that points to a rule template, along with the parameter values that template expects. When you read a rule back, that reference is returned as . Each template defines the calculation logic for a charge and the named parameters a rule must supply. Templates are not created or queried through the pricing API. Contact your Highnote representative for the values available to your program and the parameter names each template expects. ## Create pricing plan Use [](/docs/api-reference/mutation#createPricingPlan) to create a plan together with all of its rules. New plans are created in . A plan's rules are set here and cannot be changed afterward. To revise pricing, create a new plan. Each rule supplies: - : Rule template providing the calculation logic. - : Parameter values the template expects, each a and a . - : Event that evaluates the rule — , , or . - : How often the rule is evaluated — or . ```graphql mutation CreatePricingPlan($input: CreatePricingPlanInput!) { createPricingPlan(input: $input) { ... on PricingPlan { id name status rules(first: 20) { edges { node { id templateId trigger frequency } } } } ... on UserError { errors { code description } } } } ``` ```json { "input": { "name": "Standard Merchant Pricing", "description": "Per-transaction fee plus a monthly service charge", "pricingRules": [ { "ruleTemplateId": "", "trigger": "TRANSACTION", "frequency": "TRANSACTIONAL", "pricingRuleParameters": [ { "name": "fixedFee", "value": { "single": "0.10" } }, { "name": "variableFee", "value": { "single": "0.20" } } ] }, { "ruleTemplateId": "", "trigger": "RECURRING", "frequency": "MONTHLY", "pricingRuleParameters": [ { "name": "monthlyFixedFee", "value": { "single": "100.00" } } ] } ] } } ``` ## Simulate pricing plan Use [](/docs/api-reference/mutation#simulatePricingPlan) to perform a dry run of a plan against sample transactions before you publish it. A plan can be simulated in any status. You provide the sample transactions as a base64-encoded CSV in , and the mutation returns the calculated charges as a base64-encoded CSV in . Decode the result to review the charges. Each row in the template is one sample transaction, keyed by . The remaining columns, prefixed , supply the context the rules evaluate, grouped as: - **Transaction attributes**: Per-transaction fields such as network, amount, card brand, entry mode, interchange, and merchant category code. - **Batch totals**: Batch amount, currency, and transaction count. - **Merchant prior-month counts**: Per-network authorization counts, plus AVS and PIN-debit counts. - **Payfac prior-month volumes**: Settled and authorized transaction counts and payment volumes. ```csv transactionId,pricing.transactionAcquirerNetwork,pricing.transactionAmount,pricing.transactionAmountCurrency,pricing.transactionAmountImpact,pricing.transactionAvs,pricing.transactionCardBrand,pricing.transactionCardPresent,pricing.transactionContactless,pricing.transactionCrossBorder,pricing.transactionChannel,pricing.transactionForeignExchange,pricing.transactionInterchangeAmount,pricing.transactionInterchangeAmountCurrency,pricing.transactionInterchangeAmountImpact,pricing.transactionInterchangePercentage,pricing.transactionKeyedIn,pricing.transactionMerchantCategoryCode,pricing.transactionType,pricing.transactionVirtualTerminal,pricing.transactionAuthTimestamp,pricing.transactionSettlementTimestamp,pricing.transactionFundingSource,pricing.transactionAuthorizationRequestCount,pricing.transactionPosTerminalType,pricing.transactionPanEntryMode,pricing.transactionPinEntryMode,pricing.transactionPinProvidedInd,pricing.transactionIsPinDebit,pricing.transactionAvsPostalCode,pricing.transactionCardBinVertical,pricing.batchTotalAmount,pricing.batchTotalAmountCurrency,pricing.batchTotalTransactionCount,pricing.merchantPreviousMonthVisaAuthCount,pricing.merchantPreviousMonthMastercardAuthCount,pricing.merchantPreviousMonthDiscoverAuthCount,pricing.merchantPreviousMonthAmericanExpressAuthCount,pricing.merchantPreviousMonthUnionPayAuthCount,pricing.merchantPreviousMonthJcbAuthCount,pricing.merchantPreviousMonthAvsCount,pricing.merchantPreviousMonthPinDebitCount,pricing.payfacPreviousMonthTotalSettledTransactionCount,pricing.payfacPreviousMonthTotalSettledTransactionPaymentVolumeAmount,pricing.payfacPreviousMonthTotalSettledTransactionPaymentVolumeAmountCurrency,pricing.payfacPreviousMonthTotalAuthTransactionCount,pricing.payfacPreviousMonthTotalAuthTransactionPaymentVolumeAmount,pricing.payfacPreviousMonthTotalAuthTransactionPaymentVolumeAmountCurrency txn-1,Highnote,100.50,USD,CREDIT,MATCH,VISA,true,false,true,E_COMMERCE,false,1.75,USD,DEBIT,200,false,5411,PURCHASE,false,2026-03-15T14:30:25,2026-03-25T15:09:51,DEBIT,3,POS_TERMINAL,INTEGRATED_CIRCUIT_CARD,TERMINAL_HAS_PIN_ENTRY,true,true,ZIP5_MATCH,CONSUMER,25000.00,USD,100,600,350,50,30,15,8,500,20,5000,1250000.00,USD,5200,1300000.00,USD ``` Simulation accepts a maximum of 100 transactions per request. The template lists every column the simulation expects. Contact Highnote support if you need help populating it. ```graphql mutation SimulatePricingPlan($input: SimulatePricingPlanInput!) { simulatePricingPlan(input: $input) { ... on PricingPlanSimulationResult { resultCsvBase64 } ... on UserError { errors { code description } } } } ``` ```json { "input": { "pricingPlanId": "", "contextDataCsvBase64": "" } } ``` ## Publish pricing plan Use [](/docs/api-reference/mutation#publishPricingPlan) to transition a plan from to . Once published, the plan is live for transaction processing. ```graphql mutation PublishPricingPlan($input: PublishPricingPlanInput!) { publishPricingPlan(input: $input) { ... on PricingPlan { id name status } ... on UserError { errors { code description } } } } ``` ```json { "input": { "pricingPlanId": "" } } ``` ## Apply a plan A published plan is applied to a merchant during onboarding, through the field on the mutation. Applying a plan records a [](/docs/api-reference/object#PricingConfiguration) — the link between the plan and the merchant, with the window it is in effect ( through an optional ). Read a merchant's configurations through its field. ## Find pricing configurations Find the pricing configurations that apply to a merchant through its field. Each [](/docs/api-reference/object#PricingConfiguration) reports the plan that applies, the payer and payee, and the window it is in effect. ```graphql query MerchantPricingConfigurations($id: ID!) { node(id: $id) { ... on Merchant { id payerPricingConfigurations(first: 20) { pageInfo { hasNextPage endCursor } edges { node { id pricingPlan { id name status } payerEntityId payeeEntityId effectiveFrom effectiveThrough } } } } } } ``` ```json { "id": "" } ``` ## Find pricing plans Query an organization's pricing plans through the interface, filtering by status with [](/docs/api-reference/input#PricingPlanFilterInput). ```graphql query OrganizationPricingPlans($id: ID!, $filterBy: PricingPlanFilterInput) { node(id: $id) { ... on Organization { id pricingPlans(first: 10, filterBy: $filterBy) { pageInfo { hasNextPage endCursor } edges { node { id name description status } } } } } } ``` ```json { "id": "", "filterBy": { "status": "PUBLISHED" } } ``` --- URL: https://docs.highnote.com/docs/acquiring/simulations/sim-auths-and-refunds Title: Simulate Authorizations and Refunds Section: Acquiring Description: Test payment authorizations and declines in the Highnote sandbox using test card numbers for Visa and Mastercard. Includes decline codes, retry policies, and test PANs. ## Simulation card data To test your payments integration, you can use test Primary Account Numbers (PANs), addresses, and CVCs to simulate various scenarios, including specific card brands, error code responses, and successful payments. We currently support simulation card data for the following brands: | Card Network | PAN | CVV/CVC | Expiration | Address | | :----------- | :------------------ | :------ | :-------------- | :--------------------------------------- | | Visa | 4000 0000 0000 0002 | 111 | Any future date | 1234 Visa St, Visa, CA 12345 | | Mastercard | 5555 5555 5555 4444 | 222 | Any future date | 2134 Mastercard St, Mastercard, CA 21345 | ## Simulate authorizations {#simulate-successful-authorization} To simulate a successful authorization, use the simulation card data above with any amount that is not in the decline amounts table. ### Authorization approvals A successful authorization returns an with a of , along with verification response codes: | Field | Description | | :----------------------- | :----------------------------------------- | | | for a successful authorization | | | Result of AVS address verification | | | Result of postal code verification | | | Result of CVV (security code) verification | ### Authorization response code declines {#simulate-declines} The simulator emits only **real network response codes**. It never invents one. When a network has no distinct code for a given decline, the simulator emits the closest real code and the platform decodes it to a coarser outcome. Six amounts return a different on Visa than on Mastercard for this reason. Others return the same code from a different raw code. Read the column for the network you are testing before you assert on a response code. For example, returns () on Visa and () on Mastercard. Three values an earlier version of this table published are not returned on either network: (), (), and (). They remain valid values, but no Visa or Mastercard response code decodes to them. Update any test that asserts one of the three. To simulate a decline by **response code**, use one of the following transaction amounts. Set the card network using the simulation card data listed above. The parenthetical is the raw network response code the simulator emits. | Amount | Visa returns | Mastercard returns | Retries Allowed | | :------ | :------------------------------------------ | :------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------: | | $1.11 | () | () | !Allowed | | $2.22 | () | () | !Not Allowed | | $3.33 | () | () | !Allowed | | $4.44 | () | () | !Not Allowed | | $6.67 | () | () | Visa !Not Allowed
Mastercard !Allowed | | $7.77 | () | () | !Allowed | | $8.88 | () | () | !Allowed | | $9.99 | () | () | !Not Allowed | | $11.11 | () | () | !Not Allowed | | $22.22 | () | () | !Allowed | | $33.33 | () | () | !Not Allowed | | $44.44 | () | () | !Allowed | | $55.55 | () | () | !Not Allowed | | $66.66 | () | () | Visa !Allowed
Mastercard !Not Allowed | | $77.77 | () | () | !Allowed | | $88.88 | () | () | !Not Allowed | | $99.99 | () | () | !Allowed | | $111.11 | () | (, card-present only) | !Allowed | | $222.22 | () | () | !Allowed | | $333.33 | () | (, card-not-present only) | !Allowed | Retry guidance follows the response code actually returned, so it can differ by network on the same amount. Card data checks run **before** the amount lookup. If you combine a decline amount with an incorrect CVV, address, or expiration date, the response reflects the card data failure, not the amount. See Authorization card data declines. On Mastercard, the platform resolves by card presence, not by amount: - **Card-present** decodes to . - **Card-not-present** decodes to . A transaction is card-present only when it carries track 1, track 2, or ICC data, or a device-read PAN entry mode (magnetic stripe, chip, contactless, or chip fallback). Keyed and e-commerce transactions are card-not-present, so a typical API call returns for **both** amounts. To reach , send with card-present data. Visa uses two distinct codes ( and ), so both Visa amounts return the code shown regardless of card presence. The Visa and Mastercard simulators produce only the response codes listed above. ### Authorization card data declines AVS declines always return with result codes populated in separate response fields. is not returned for AVS failures. To simulate a decline by **incorrect card data**, send a past-dated expiration date, the wrong CVV, or the wrong address (for AVS declines) with the test PANs above. The platform response depends on the card network and transaction (txn) type. #### Visa | Scenario | Response Code | Details | | :----------------------------------- | :------------- | :------------------------------------------------------------------------------------------------------------- | | Past-dated expiration date | | Returns the 05 response code. Visa does not return for a card whose expiration date has passed. | | Omitted expiration date | | Visa accepts a missing expiration date and moves on to the CVV, address, and amount checks. | | Incorrect CVV | | Returns the N7 response code. | | Incorrect address (non-verification) | | Returns the 05 response code with or set to . | | Incorrect address (verification txn) | | AVS result codes are still returned, but incorrect address data does not trigger a decline. | #### Mastercard | Scenario | Response Code | Details | | :----------------------------------- | :------------- | :---------------------------------------------------------------------------------------------------- | | Past-dated expiration date | | Returns the 54 response code. | | Omitted expiration date | | Returns the 54 response code. Mastercard requires the expiration date and declines when it is absent. | | Incorrect CVV | | Returns the 05 response code with set to . | | Incorrect address (non-verification) | | Returns the 05 response code along with the specific AVS codes. | | Incorrect address (verification txn) | | Same as non-verification. Mastercard does not exempt verification transactions from AVS declines. | Two expiration-date behaviors differ from what the rest of this page would lead you to expect: - **A past-dated card returns on Visa**, not . The decline amount _does_ return on Visa, so the two ways of simulating an expired card produce different response codes on the same network. Mastercard returns for both. - **Omitting the expiration date approves on Visa and declines on Mastercard.** Send the field on both networks. Expiration-date checks run before the CVV and address checks, and all three run before the amount lookup. Visa returns for verification transactions with incorrect address data, while Mastercard returns . Test both networks to ensure your integration handles both responses. ## Simulate refunds Refunds are submitted against the original payment transaction (the first authorization), not against individual captures. The total captured amount is the refund limit, regardless of how many captures were made. Multiple partial refunds are supported as long as the total refunded amount does not exceed the total captured amount. Use the [](/docs/api-reference/mutation#refundPaymentTransaction) mutation with the original to issue a refund. The response returns a with an that references the original payment. There are no dedicated refund event types. Instead, refund outcomes use authorization events: | Refund outcome | Event | | :------------- | :-------------------------------------- | | Approved | | | Declined | | ### Refund approvals To simulate an approved refund, use any amount that is not in the authorization declines table and does not exceed the captured amount of the original transaction. ### Refund declines To simulate a declined refund, use one of the decline amounts from the authorization declines table. For example, a refund amount of $1.11 triggers a decline. To simulate the issuer accepting an acquiring dispute, see Simulate Disputes. --- URL: https://docs.highnote.com/docs/acquiring/transactions/display-transactions Title: Display Transactions Section: Acquiring Description: Query and display payment transaction data, build filtered transaction lists, and show transaction details from the Highnote acquiring API. ## Overview Highnote provides access to all transaction data processed through your Acquiring product. You can use Highnote's API to create filtered lists of transactions and display transaction details. This data is useful for building transaction history views in your website or application. ## Build a transaction feed Use the following query to display a list of transactions: ## Display transaction details Use the following query to display transaction details: ### GraphQL: PaymentTransaction Query: query PaymentTransaction($first: Int) { paymentTransactions(first: $first) { __typename pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename id createdAt updatedAt steps { __typename ... on CardCaptureStep { id } createdAt amount { value currencyCode } events { __typename createdAt updatedAt amount { value currencyCode } } } status accountingDirection authorizedAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { processorResponseCode authorizationCode addressCode postalCode securityCode } instrument { __typename ... on PaymentCardInstrument { createdAt last4 expiryYear expiryMonth brand } } ... on PaymentCreditTransaction { originatedPaymentTransaction { __typename id createdAt updatedAt } } ... on PaymentDebitTransaction { refunds { __typename id createdAt updatedAt } } } } } } Variables: { "first": 20 } Expected Result: { "data": { "paymentTransactions": { "__typename": "PaymentTransactionsConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "", "endCursor": "" }, "edges": [ { "cursor": "", "node": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "steps": [ { "__typename": "CardAuthorizationStep", "createdAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] } ], "status": "PENDING", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "authorizationCode": "067689", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" }, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-01-01T00:00:00.000Z", "last4": "4242", "expiryYear": "2024", "expiryMonth": "12", "brand": "VISA" }, "refunds": null } }, { "cursor": "", "node": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-01-02T00:00:00.000Z", "updatedAt": "2024-01-02T00:00:00.000Z", "steps": [ { "__typename": "CardAuthorizationStep", "createdAt": "2024-01-02T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] }, { "__typename": "CardReversalStep", "createdAt": "2024-01-02T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentReversedEvent", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] } ], "status": "REVERSED", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": { "value": 1000, "currencyCode": "USD" }, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "authorizationCode": "214590", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" }, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-01-01T00:00:00.000Z", "last4": "4242", "expiryYear": "2024", "expiryMonth": "12", "brand": "VISA" }, "refunds": null } }, { "cursor": "", "node": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-01-03T00:00:00.000Z", "updatedAt": "2024-01-03T00:00:00.000Z", "steps": [ { "__typename": "CardAuthorizationStep", "createdAt": "2024-01-03T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] }, { "__typename": "CardCaptureStep", "id": "", "createdAt": "2024-01-03T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentCapturingEvent", "createdAt": "2024-01-03T00:00:00.000Z", "updatedAt": "2024-01-03T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } }, { "__typename": "CardPaymentCaptureProcessingEvent", "createdAt": "2024-01-03T00:00:00.000Z", "updatedAt": "2024-01-03T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } }, { "__typename": "CardPaymentClearedEvent", "createdAt": "2024-01-03T00:00:00.000Z", "updatedAt": "2024-01-03T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } }, { "__typename": "CardPaymentDisbursedEvent", "createdAt": "2024-01-03T00:00:00.000Z", "updatedAt": "2024-01-03T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] } ], "status": "PENDING", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": { "value": 1000, "currencyCode": "USD" }, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "authorizationCode": "883021", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" }, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-01-01T00:00:00.000Z", "last4": "4242", "expiryYear": "2024", "expiryMonth": "12", "brand": "VISA" }, "refunds": null } }, { "cursor": "", "node": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-01-04T00:00:00.000Z", "updatedAt": "2024-01-05T00:00:00.000Z", "steps": [ { "__typename": "CardAuthorizationStep", "createdAt": "2024-01-04T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] }, { "__typename": "CardCaptureStep", "id": "", "createdAt": "2024-01-04T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentCapturingEvent", "createdAt": "2024-01-04T00:00:00.000Z", "updatedAt": "2024-01-04T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } }, { "__typename": "CardPaymentCaptureProcessingEvent", "createdAt": "2024-01-04T00:00:00.000Z", "updatedAt": "2024-01-04T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } }, { "__typename": "CardPaymentClearedEvent", "createdAt": "2024-01-04T00:00:00.000Z", "updatedAt": "2024-01-04T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } }, { "__typename": "CardPaymentDisbursedEvent", "createdAt": "2024-01-04T00:00:00.000Z", "updatedAt": "2024-01-04T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] } ], "status": "COMPLETED", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": { "value": 1000, "currencyCode": "USD" }, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "authorizationCode": "471256", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" }, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-01-01T00:00:00.000Z", "last4": "4242", "expiryYear": "2024", "expiryMonth": "12", "brand": "VISA" }, "refunds": [ { "__typename": "PaymentCreditTransaction", "id": "", "createdAt": "2024-01-05T00:00:00.000Z", "updatedAt": "2024-01-05T00:00:00.000Z" } ] } }, { "cursor": "", "node": { "__typename": "PaymentCreditTransaction", "id": "", "createdAt": "2024-01-05T00:00:00.000Z", "updatedAt": "2024-01-05T00:00:00.000Z", "steps": [ { "__typename": "CardAuthorizationStep", "createdAt": "2024-01-05T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] } ], "status": "PENDING", "accountingDirection": "CREDIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "authorizationCode": "309847", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" }, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-01-01T00:00:00.000Z", "last4": "4242", "expiryYear": "2024", "expiryMonth": "12", "brand": "VISA" }, "originatedPaymentTransaction": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-01-04T00:00:00.000Z", "updatedAt": "2024-01-05T00:00:00.000Z" } } } ] } }, "extensions": { "requestId": "", "rateLimit": { "cost": 282 } } } ### GraphQL: PaymentTransaction Query: query PaymentTransaction($id: ID!) { node(id: $id) { __typename ... on PaymentTransaction { id createdAt updatedAt steps { __typename ... on CardCaptureStep { id } createdAt amount { value currencyCode } events { __typename createdAt updatedAt amount { value currencyCode } } } status accountingDirection authorizedAmount { value currencyCode } settledAmount { value currencyCode } disbursedAmount { value currencyCode } canceledAmount { value currencyCode } refundedAmount { value currencyCode } responseCode { processorResponseCode authorizationCode addressCode postalCode securityCode } instrument { __typename ... on PaymentCardInstrument { createdAt last4 expiryYear expiryMonth brand } } ... on PaymentCreditTransaction { originatedPaymentTransaction { __typename id createdAt updatedAt } } ... on PaymentDebitTransaction { refunds { __typename id createdAt updatedAt } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "PaymentDebitTransaction", "id": "", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "steps": [ { "__typename": "CardAuthorizationStep", "createdAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" }, "events": [ { "__typename": "CardPaymentAuthorizedEvent", "createdAt": "2024-01-01T00:00:00.000Z", "updatedAt": "2024-01-01T00:00:00.000Z", "amount": { "value": 1000, "currencyCode": "USD" } } ] } ], "status": "PENDING", "accountingDirection": "DEBIT", "authorizedAmount": { "value": 1000, "currencyCode": "USD" }, "settledAmount": null, "disbursedAmount": null, "canceledAmount": null, "refundedAmount": null, "responseCode": { "processorResponseCode": "APPROVED", "authorizationCode": "067689", "addressCode": "SKIPPED", "postalCode": "SKIPPED", "securityCode": "SKIPPED" }, "instrument": { "__typename": "PaymentCardInstrument", "createdAt": "2024-01-01T00:00:00.000Z", "last4": "4242", "expiryYear": "2024", "expiryMonth": "12", "brand": "VISA" }, "refunds": null } } } --- URL: https://docs.highnote.com/docs/acquiring/transactions/transaction-batching Title: Transaction Batching Section: Acquiring Description: Batch payment transactions for settlement and payout — list transaction batches, inspect a batch's totals, drill into a batch's transactions, and close a batch on demand. ## Overview A [](/docs/api-reference/object#TransactionBatch) groups [](/docs/api-reference/interface#PaymentTransaction)s together for settlement and payout. An owner has one open batch per batch bucket, which for most owners means a single open batch. New transactions accumulate into it until it closes. Closing a batch on demand opens a replacement immediately; a batch that closes on its own schedule gets no replacement, and the next transaction to arrive opens one. A batch's owner is either a [](/docs/api-reference/object#Merchant) or a [](/docs/api-reference/object#Payfac) ([](/docs/api-reference/union#TransactionBatchOwner)). A sub-merchant is itself a — reachable from its payfac via — so this union already covers merchant, sub-merchant, and payfac batch owners. ## Batch statuses A batch starts and accumulates transactions. Closing it (see Close a batch for payout) moves it to , and it proceeds through settlement, clearing, and disbursement toward . Batches can also land in holding or terminal states. The [](/docs/api-reference/enum#TransactionBatchStatus) values: | Status | Meaning | | :--------------------- | :------------------------------------------------------ | | | The batch is currently open and accepting transactions. | | | A close has been requested for the batch. | | | The batch is processing. | | | The batch is on hold. | | | The batch is closed. | | | The batch is pending clearing. | | | The batch has cleared. | | | The batch is pending disbursement. | | | The batch payout is complete. | | | The batch was rejected. | | | The batch was disbursed. | | | The batch payout is pending. | | | The batch payout failed. | ## How a batch accumulates Highnote adds a transaction's amount and any associated fees to its batch's running totals as the transaction moves through the payment lifecycle — for example, as a purchase is captured and cleared, as funds are disbursed, or if a first chargeback is filed against a transaction in the batch. A batch's [](/docs/api-reference/object#TransactionBatch) and total the transactions that debit or credit the customer. is a breakdown rather than a separate bucket — chargebacks are also counted in or by direction, so summing all three double-counts them. is the signed running total of all transactions before fees, holds, and adjustments; it is for batches created before the field was introduced. is what the owner is actually paid, and it is less fees, holds, and adjustments — so it will not reconcile against alone. ## List transaction batches Use the query to list an owner's batches — the open one, historical ones, or a filtered slice by status or date. Results are scoped to your API key's organization context. If you're a payfac, a query without further scoping returns your own batch plus one for each of your sub-merchants — scope to a single owner with (see the Highnote Query Language (HQL) fields below), or select to tell them apart. If you build that filter from a value supplied by one of your sub-merchants, validate its format before interpolating it — see Build query strings safely. ```graphql transactionBatches( first: Int = 20 after: String filterBy: TransactionBatchFilterInput ): TransactionBatchConnectionPayload ``` is a union of , , and — select on the concrete type with . accepts an HQL query string and cannot be combined with other filters. ### The open batch Most owners have a single open batch, so filtering on returns it (plus one per sub-merchant, for a payfac). An owner routed across several batch buckets has one open batch per bucket, and an owner whose last batch closed on schedule has none until its next transaction arrives: supports five HQL fields: | Field | Type | Operators | Example | | -------------------- | ------------------------ | ------------------------------- | ------------------------------------- | | | ID | , | | | | ID | , | | | | | , | | | | Currency amount | , , , , , | | | | ISO 8601 timestamp | , , , , , | | An HQL money literal carries the amount in the currency's minor units, so matches batches at or above **$3.00**, not $300. The comparison also scopes results to the currency you name. So in addition to , you can filter to a specific status such as , exclude one with (below), scope to a single owner with , or filter by creation date or running total. ### Non-open batches Filter on to list an owner's historical and in-flight batches: ## Inspect a batch A implements [](/docs/api-reference/interface#Node), so once you have a batch's — from a list result above, or from another reference — fetch it directly through the top-level query. The example below inspects a closed batch, because and are produced by the close workflow and are while a batch is still open: ## Drill into a batch's transactions The field on returns the s inside a batch, letting you break it down by type or by amount. Results are always scoped to the batch you're querying — the filter is applied automatically, so you never supply it yourself. Alias the field ( / below) to pull multiple filtered slices in one request. supports five HQL fields: | Field | Type | Operators | Example | | --------------------- | ------------------ | ------------------------------- | ------------------------------------- | | | ID | , | | | | Currency amount | , , , , , | | | | , | , | | | | ISO 8601 timestamp | , , , , , | | | | ISO 8601 timestamp | , , , , , | | Money literals here carry minor units too, so matches entries between $3.00 and $5.00. ## Batch-level fees A batch's field returns [](/docs/api-reference/interface#TransactionBatchFee) entries — a separate interface from the transaction-level [](/docs/api-reference/interface#PaymentTransactionFee) described in Transaction Fees. declares , , and — one field more than , which exposes only and . It currently has one concrete type, [](/docs/api-reference/object#TransactionBatchProcessingFee). Batch fees are calculated when a batch closes, so they are populated on closed batches and on an open one — note that the field is rather than an empty list when a batch has no fees. See the selection in Inspect a batch above for a populated example. ## Close a batch for payout Close an open batch on demand with . The close is processed asynchronously: the batch moves to immediately and doesn't reach until the async processing completes. Closing also opens a new batch in its place, returned as . Whether a batch also closes on a schedule depends on its owner. A batch owned by a closes automatically each day at the globally configured close time, but closing one on demand opts that owner out of the schedule — the replacement batch returned as then stays open until it too is closed on demand. Batches owned by a , including a payfac's sub-merchants, close automatically only when auto-close is configured for the account; otherwise they stay open until closed on demand. The input takes (required), plus optional (a UUIDv4 that dedupes repeated requests) and (an external reference, up to 255 alphanumeric characters). This mutation runs against your active organization's environment. Closing a batch cannot be undone — there is no reopen operation — and closing a -owned batch on demand permanently opts that owner out of the daily close schedule. ### GraphQL: List the open batch Query: query QueryOpenTransactionBatch($filterBy: TransactionBatchFilterInput!) { transactionBatches(filterBy: $filterBy) { __typename ... on AccessDeniedError { message } ... on UserError { errors { errorPath code description } } ... on TransactionBatchConnection { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { id owner { __typename ... on Merchant { id } ... on Payfac { id } } status debitTotal { count totalAmount { value currencyCode decimalPlaces } } creditTotal { count totalAmount { value currencyCode decimalPlaces } } chargebackTotal { count totalAmount { value currencyCode decimalPlaces } } holdsTotalAmount { value currencyCode decimalPlaces } adjustmentsTotalAmount { value currencyCode decimalPlaces } } } } } } Variables: { "filterBy": { "searchQueryLanguage": { "query": "status = 'OPEN'", "version": "VERSION_1" } } } Expected Result: { "data": { "transactionBatches": { "__typename": "TransactionBatchConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "", "endCursor": "" }, "edges": [ { "cursor": "", "node": { "id": "", "owner": { "__typename": "Merchant", "id": "" }, "status": "OPEN", "debitTotal": { "count": 2, "totalAmount": { "value": 10000, "currencyCode": "USD", "decimalPlaces": 2 } }, "creditTotal": { "count": 1, "totalAmount": { "value": 2500, "currencyCode": "USD", "decimalPlaces": 2 } }, "chargebackTotal": { "count": 0, "totalAmount": { "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, "holdsTotalAmount": { "value": -100, "currencyCode": "USD", "decimalPlaces": 2 }, "adjustmentsTotalAmount": { "value": -50, "currencyCode": "USD", "decimalPlaces": 2 } } }, { "cursor": "", "node": { "id": "", "owner": { "__typename": "Payfac", "id": "" }, "status": "OPEN", "debitTotal": { "count": 1, "totalAmount": { "value": 4000, "currencyCode": "USD", "decimalPlaces": 2 } }, "creditTotal": { "count": 0, "totalAmount": { "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, "chargebackTotal": { "count": 0, "totalAmount": { "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, "holdsTotalAmount": { "value": 0, "currencyCode": "USD", "decimalPlaces": 2 }, "adjustmentsTotalAmount": { "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } } } ] } }, "extensions": { "requestId": "" } } ### GraphQL: List non-open batches Query: query QueryNonOpenTransactionBatch($filterBy: TransactionBatchFilterInput!) { transactionBatches(filterBy: $filterBy) { __typename ... on AccessDeniedError { message } ... on UserError { errors { errorPath code description } } ... on TransactionBatchConnection { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { id status } } } } } Variables: { "filterBy": { "searchQueryLanguage": { "query": "status != 'OPEN'", "version": "VERSION_1" } } } Expected Result: { "data": { "transactionBatches": { "__typename": "TransactionBatchConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "", "endCursor": "" }, "edges": [ { "cursor": "", "node": { "id": "", "status": "PROCESSING" } }, { "cursor": "", "node": { "id": "", "status": "CLOSED" } }, { "cursor": "", "node": { "id": "", "status": "ON_HOLD" } } ] } }, "extensions": { "requestId": "" } } ### GraphQL: Inspect a batch Query: query QueryTransactionBatchNode($id: ID!) { node(id: $id) { __typename ... on TransactionBatch { id owner { __typename ... on Merchant { id } ... on Payfac { id } } status createdAt closeRequestedAt currentTotal { count totalAmount { value currencyCode decimalPlaces } } debitTotal { count totalAmount { value currencyCode decimalPlaces } } creditTotal { count totalAmount { value currencyCode decimalPlaces } } chargebackTotal { count totalAmount { value currencyCode decimalPlaces } } holdsTotalAmount { value currencyCode decimalPlaces } adjustmentsTotalAmount { value currencyCode decimalPlaces } disbursedAmount { value currencyCode decimalPlaces } fees { __typename accountingDirection description feeAmount { value currencyCode decimalPlaces } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "TransactionBatch", "id": "", "owner": { "__typename": "Merchant", "id": "" }, "status": "CLOSED", "createdAt": "2026-07-01T00:00:00.000Z", "closeRequestedAt": "2026-07-08T00:00:00.000Z", "currentTotal": { "count": 3, "totalAmount": { "value": 7500, "currencyCode": "USD", "decimalPlaces": 2 } }, "debitTotal": { "count": 2, "totalAmount": { "value": 10000, "currencyCode": "USD", "decimalPlaces": 2 } }, "creditTotal": { "count": 1, "totalAmount": { "value": 2500, "currencyCode": "USD", "decimalPlaces": 2 } }, "chargebackTotal": { "count": 0, "totalAmount": { "value": 0, "currencyCode": "USD", "decimalPlaces": 2 } }, "holdsTotalAmount": { "value": -100, "currencyCode": "USD", "decimalPlaces": 2 }, "adjustmentsTotalAmount": { "value": -50, "currencyCode": "USD", "decimalPlaces": 2 }, "disbursedAmount": { "value": 7200, "currencyCode": "USD", "decimalPlaces": 2 }, "fees": [ { "__typename": "TransactionBatchProcessingFee", "accountingDirection": "DEBIT", "description": "Processing fee", "feeAmount": { "value": 150, "currencyCode": "USD", "decimalPlaces": 2 } } ] } }, "extensions": { "requestId": "" } } ### GraphQL: Drill into a batch Query: query QueryTransactionBatchByTransactionType($id: ID!) { node(id: $id) { __typename ... on TransactionBatch { id status purchases: transactions( filterBy: { searchQueryLanguage: { query: "accountingDirection = 'DEBIT'" version: VERSION_1 } } ) { __typename ... on AccessDeniedError { message } ... on UserError { errors { errorPath code description } } ... on PaymentTransactionsConnection { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename ... on PaymentDebitTransaction { id capturedAmount { value currencyCode decimalPlaces } } } } } } refunds: transactions( filterBy: { searchQueryLanguage: { query: "accountingDirection = 'CREDIT'" version: VERSION_1 } } ) { __typename ... on AccessDeniedError { message } ... on UserError { errors { errorPath code description } } ... on PaymentTransactionsConnection { pageInfo { hasNextPage hasPreviousPage startCursor endCursor } edges { cursor node { __typename ... on PaymentCreditTransaction { id capturedAmount { value currencyCode decimalPlaces } } } } } } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "TransactionBatch", "id": "", "status": "OPEN", "purchases": { "__typename": "PaymentTransactionsConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "", "endCursor": "" }, "edges": [ { "cursor": "", "node": { "__typename": "PaymentDebitTransaction", "id": "", "capturedAmount": { "value": 6000, "currencyCode": "USD", "decimalPlaces": 2 } } }, { "cursor": "", "node": { "__typename": "PaymentDebitTransaction", "id": "", "capturedAmount": { "value": 4000, "currencyCode": "USD", "decimalPlaces": 2 } } } ] }, "refunds": { "__typename": "PaymentTransactionsConnection", "pageInfo": { "hasNextPage": false, "hasPreviousPage": false, "startCursor": "", "endCursor": "" }, "edges": [ { "cursor": "", "node": { "__typename": "PaymentCreditTransaction", "id": "", "capturedAmount": { "value": 2500, "currencyCode": "USD", "decimalPlaces": 2 } } } ] } } }, "extensions": { "requestId": "" } } ### GraphQL: Close a batch for payout Query: mutation CloseTransactionBatch($input: CloseTransactionBatchInput!) { closeTransactionBatch(input: $input) { __typename ... on AccessDeniedError { message } ... on UserError { errors { errorPath code description } } ... on CloseTransactionBatch { closingTransactionBatch { id status fees { __typename accountingDirection description feeAmount { value currencyCode decimalPlaces } } } openedTransactionBatch { id status } } } } Variables: { "input": { "transactionBatchId": "", "idempotencyKey": "", "externalIdentifier": "" } } Expected Result: { "data": { "closeTransactionBatch": { "__typename": "CloseTransactionBatch", "closingTransactionBatch": { "id": "", "status": "CLOSE_REQUESTED", "fees": [ { "__typename": "TransactionBatchProcessingFee", "accountingDirection": "DEBIT", "description": "Processing fee", "feeAmount": { "value": 150, "currencyCode": "USD", "decimalPlaces": 2 } } ] }, "openedTransactionBatch": { "id": "", "status": "OPEN" } } }, "extensions": { "requestId": "" } } --- URL: https://docs.highnote.com/docs/acquiring/transactions/transaction-fees Title: Transaction Fees Section: Acquiring Description: Fee breakdown surfaced on acquiring payment transactions — interchange, merchant, and network fees with accounting direction. ## Overview Acquiring payment transactions surface a fee breakdown via the [](/docs/api-reference/interface#PaymentTransactionFee) field. Each entry describes one fee associated with the transaction, with a sign that tells you whether the fee debits or credits your payable amount. The field is exposed on: - [](/docs/api-reference/object#PaymentDebitTransaction) — payment (charge) transactions. - [](/docs/api-reference/object#PaymentCreditTransaction) — refund transactions. - [](/docs/api-reference/object#PaymentOrderLineItem) — line items within a payment order. Fees are also charged at the batch level, on a separate interface. See Transaction Batching. ## Fee shape [](/docs/api-reference/interface#PaymentTransactionFee) is an interface. All concrete fee types share the same two fields: | Field | Type | Description | | :-------------------- | :-------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | | | [](/docs/api-reference/enum#AccountingDirection) | Direction the fee is moving from the subscriber's perspective. deducts the fee from the total payable amount; credits it. | | | [](/docs/api-reference/object#Amount) | The amount of the fee. | ## Fee categories Discriminate concrete fee types via . Each concrete type currently exposes the same fields as the interface; identification is by only. | Concrete Type | What It Represents | | :------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Merchant-side processing fees (Highnote's discount fee and per-transaction surcharges such as keyed-in, virtual terminal, cross-border, foreign exchange). | | | Interchange fee assessed between the acquirer and the card issuer. | | | Network assessment fee charged by the card network (for example, Visa or Mastercard). | | | Appears when the underlying fee category is , , or any unrecognized value — read and like the other types. | ### Fees by pricing model Whether a fee category is populated depends on the **Pricing Model** configured on the subscriber's contract. can appear on any model when the network or processor has not classified the fee. Production code does not emit fees for [](/docs/api-reference/object#NetworkFeePaymentTransactionFee) today. The schema includes the type so subscribers can parse defensively for forward compatibility as the schema evolves. | Pricing Model | Interchange | Merchant | Network | | :--------------------------- | :---------: | :------: | :-----: | | Blended | — | Yes | — | | Interchange Plus (IC+) | Yes | Yes | — | | Interchange Plus Plus (IC++) | Yes | Yes | Planned | | Tiered | Yes | Yes | Planned | ## Query fee details The following request and response demonstrate the array when populated. ### Request example Query the transaction by ID and select on each fee to discriminate the concrete fee type: ```graphql query PaymentTransactionFees($id: ID!) { node(id: $id) { __typename ... on PaymentTransaction { id fees { __typename accountingDirection feeAmount { currencyCode value decimalPlaces } } } } } ``` ### Response example Interchange fees use four decimal places to support sub-cent precision. The transaction's payable amount is reduced by of interchange and of merchant fees. See Acquiring transaction precision for the convention. ```json { "data": { "node": { "__typename": "PaymentDebitTransaction", "id": "", "fees": [ { "__typename": "InterchangeFeePaymentTransactionFee", "accountingDirection": "DEBIT", "feeAmount": { "currencyCode": "USD", "value": 165, "decimalPlaces": 4 } }, { "__typename": "MerchantFeePaymentTransactionFee", "accountingDirection": "DEBIT", "feeAmount": { "currencyCode": "USD", "value": 30, "decimalPlaces": 2 } } ] } } } ``` --- URL: https://docs.highnote.com/docs/money-movement/about-money-movement Title: About Money Movement Section: Money Movement Description: Move funds across ACH, wire transfers, Real-Time Payments (RTP), and Instant Network Transfers using a single API with intelligent routing based on cost, speed, and destination. Highnote's money movement framework provides a single API for moving funds across multiple payment rails. Instead of integrating separate providers for each transfer type, you use one programmable interface that supports cards, accounts, and emerging rails — domestic and international, inbound and outbound. ## Payment rails Highnote supports multiple payment rails through a unified API. Transactions are routed based on cost, speed, and destination — either configured by you or intelligently routed by the platform. Supported and planned rails include: - **Instant Payments** — Near real-time transfers to and from eligible external debit and prepaid cards via Mastercard Move and Visa Direct. - **ACH** — Standard and same-day ACH transfers for account-to-account movement. - **Wire Transfers** — Domestic wire transfers for high-value, time-sensitive payments. - **Real Time Payments (RTP)** — Near real-time account-to-bank transfers. - **FedNow** — Real-time payment network for instant settlement _(coming soon)_. ## Orchestration Highnote's orchestration layer routes transactions based on real-time variables including ticket size, card type, network eligibility, and merchant category. The platform balances speed, cost-efficiency, and success rates so you can fine-tune routing rules or let the system optimize automatically. Because money movement is built into the same platform as issuing, acquiring, credit, and the general ledger, there is no middleware layer between funding, disbursement, and reconciliation. Funds flow through a single system from first dollar in to last dollar out. ## On-us transfers When disbursing funds to a Highnote-issued card, the transfer executes as an internal ledger move rather than a network transaction. These on-us transfers: - Settle instantly (milliseconds, not minutes or days) - Incur no network fees (no Visa Direct or Mastercard Move costs) - Remain within the Highnote ledger for simplified reconciliation This applies when both the source account and destination card are on the Highnote platform. For payouts to external cards or bank accounts, standard network rails apply. ## Use cases Instant Payments and the broader money movement framework support a range of disbursement scenarios: - Gig worker and contractor payouts - Employee tips and earned wage access - Insurance claim reimbursements - Merchant settlements - Customer refunds See Money Movement Use Cases. ## Next steps - Set up Instant Payments using Mastercard Move or Visa Direct. - Use Real Time Payments for instant account-to-bank transfers. - Configure ACH transfers for account-to-account movement. --- URL: https://docs.highnote.com/docs/money-movement/account-linking/plaid Title: Linking Accounts with Plaid Section: Money Movement Description: Verify and link external bank accounts using Plaid or Finicity. Choose from Hosted URL, Plaid SDK, or direct processor token integration paths. ## Overview External bank accounts must be verified and linked before you can move funds to and from a Highnote financial account. Highnote partners with Plaid and Finicity to verify and connect external bank accounts securely and with NACHA compliance. ## Integration paths Highnote offers three ways to verify and link external bank accounts with Plaid: | Path | Description | Best for | | :--------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------- | :---------------------------------------------------------- | | **Hosted URL** | No-code solution — Highnote manages the Plaid relationship and hosts the Link flow. | Reducing compliance burden and frontend development. | | **Plaid SDK** | Highnote manages Plaid, but you embed the Plaid Link SDK for a native experience. | Full control over the UX while delegating Plaid operations. | | **Direct (processor token)** | You maintain your own Plaid relationship and pass a to Highnote. | Subscribers already integrated with Plaid. | For full setup instructions, prerequisites, and API mutations, see **Link External Accounts with Plaid**. ## Non-verified accounts External accounts that have not been verified through Plaid or Finicity can only be used for fund-out transfers (e.g., returning funds on account closure). They cannot pull funds into Highnote. For details, see Connect a non-verified account. --- URL: https://docs.highnote.com/docs/money-movement/use-cases Title: Money Movement Use Cases Section: Money Movement Description: Explore money movement use cases including payroll, earned wage access (EWA), gig worker payouts, corporate disbursements, and stablecoin wallet onramp and offramp. ## Overview Highnote's money movement capabilities support disbursement scenarios across industries. Each use case below leverages Highnote's unified platform to move funds via Push-to-Card (INT), RTP, and ACH. ## Payroll, EWA and Tips Employers and payroll platforms in hospitality, food service, and other service industries can use Highnote to disburse wages, earned wage access (EWA) advances, and tips to employees. **Supported rails:** | Rail | Use | Speed | | :------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------- | :------- | | INT | Delivers tip payouts and shift-end earnings to a worker's debit card in minutes | Minutes | | RTP | Sends payroll advances and EWA disbursements directly to an employee's bank account in real time | Minutes | | ACH | Handles standard payroll runs and bulk disbursements where same-day or next-day settlement is acceptable | 1-3 days | ## 1099 GIG Worker Gig economy and marketplace platforms that connect SMB merchants with independent contractors can use Highnote to manage contractor payouts. **Supported rails:** | Rail | Use | Speed | | :------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------ | :------- | | INT | Push-to-Card enables instant disbursement upon job completion to a contractor's debit card | Minutes | | RTP | Provides on-demand payouts directly to a contractor's bank account when immediate access to funds is required | Minutes | | ACH | Supports scheduled weekly or monthly settlement cycles for recurring contractor relationships | 1-3 days | ## Corporate Disbursements Corporate platforms managing disbursements across multiple categories — customer rewards, refunds, marketing funds, and promotional payouts — can use Highnote to route each payment through the appropriate rail. **Supported rails:** | Rail | Use | Speed | | :------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------- | :------- | | INT | Push-to-Card enables instant refunds directly to a recipient's card on file | Minutes | | RTP | Handles time-sensitive disbursements like refunds and promotional payouts that require immediate delivery | Minutes | | ACH | Supports high-volume, lower-priority distributions such as bulk reward programs and marketing fund allocations | 1-3 days | ## Stablecoin Wallets Stablecoin platforms serving both direct-to-consumer and B2B markets can use Highnote to provide fiat onramp and offramp capabilities alongside core disbursements. **Supported rails:** | Rail | Use | Speed | | :------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------- | :------- | | INT | Push-to-Card enables instant offramp from a stablecoin wallet to a user's debit card | Minutes | | RTP | Supports offramp to a bank account with real-time settlement | Minutes | | ACH | Handles bulk onramp and offramp operations as well as recurring fiat conversion flows where immediate settlement is not required | 1-3 days | --- URL: https://docs.highnote.com/docs/money-movement/payment-rails/ach-transfers Title: ACH Transfers Section: Money Movement Description: Process routine, high-volume payments between U.S. bank accounts using ACH. Supports originated and non-originated transfers with same-day, next-day, or standard processing. ## Overview ACH Consent is mandatory per ACH transfer. You must define and maintain a Consent Template to use for each ACH transfer. ACH transactions are routine, high-volume, low-cost payments between U.S. bank accounts on the ACH network, an electronic funds-transfer system run by Nacha (National Automated Clearing House Association). Unlike wire transfers, ACH transactions are processed in batches at scheduled intervals throughout the day, making them good for recurring payments, payroll, and situations where low cost matters more than speed. ACH payments may be processed on a same-day or next-day basis, or through standard processing, which can take multiple days. See Add Funds to an Account for ACH API examples. See ACH Transfers in the Events Reference for notifications. ## ACH consent Per NACHA rules, ACH transfers **require documented account holder authorization**. Use a consent template to capture it for each transfer: - In TransferAgreementConsentTemplateInput, and values are defined by your system. - In TransferAgreementConsentInput: is the for Person account holders, and for Business account holders. ## Account status eligibility The following table lists ACH transfer eligibility by their Highnote financial account status. | Financial Account Status | Debit / Prepaid | Credit | ACH Transfer Eligibility | | :----------------------- | :-------------- | :----- | :---------------------------------------------------------- | | | Yes | Yes | All transfer types supported | | | No | Yes | Limited transfer capabilities, case-by-case basis | | | No | Yes | Restricted transfers pending investigation | | | No | Yes | No new scheduled transfers, existing transfers may complete | | | No | No | No transfers permitted | ## ACH core concepts Only Highnote can initiate an originated transfer, and only an external party can initiate a non-originated transfer. But per ACH standard terminology, the bank of the initiator (Highnote or external party) is always the Originating Depository Financial Institution (ODFI), and vice versa, the bank of the non-initiator is always the Receiving Depository Financial Institution (RDFI). A Highnote ACH transfer begins when either Highnote or an external party initiates a transaction (debit or credit) on the ACH network. - **Initiator:** Any party (Highnote or an external party) who initiates a push or pull transaction. - **Originated transfer:** Transfers initiated on the Highnote platform by Highnote. - **Non-originated transfer:** Transfers initiated outside of the Highnote platform by an external party. ## Terminology {#transfer-type-method-effect} Note the following transfer terms: - Transfer **type** is determined by the initiator: Originated ACH Transfers are initiated by Highnote on the Highnote platform, and Non-Originated ACH Transfers are initiated by an external party outside of the Highnote platform. - Transfer **method** is determined by the initiator who either pushes or pulls funds. - Transfer **effect** describes what happens to Highnote's account (which is credited or debited). | Transfer Type | Method | Effect
_Highnote POV_ | Description | | :----------------- | :----- | :------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | | **Originated** | Push | Debit/Fund out | Highnote initiates an ACH instruction to push funds from a Highnote financial account (which is debited) to an external bank account. | | | Pull | Credit/Fund in | Highnote initiates an ACH instruction to pull funds from an external bank account into a Highnote financial account (which is credited). | | **Non-originated** | Push | Credit/Fund in | An external bank initiates an ACH instruction to push funds from their bank account to a Highnote financial account (which is credited). | | | Pull | Debit/Fund out | An external bank initiates an ACH instruction to pull funds from a Highnote financial account (which is debited) into their bank account. | ## Instruction and money flows ## Processing schedule #### Originated Originated ACH (OACH) transfer events transition on this general timeline: - → : This transition occurs almost immediately. Once the ACH transfer is initiated, Highnote moves it to a Pending state within seconds to secure the necessary funds (for example, we temporarily reduce available cash for ACH pushes). - → : Transfers typically move to Processing within the next scheduled batch window. Highnote runs batch processing multiple times per business day, so most transfers progress to this state within a few hours of initiation. - → : Processing and settlement generally complete within 2–3 business days, depending on standard ACH clearing schedules. Transfers initiated late in the day or on weekends begin processing on the next business day. #### Non-originated Non-originated ACH (NOACH) transfer events are processed based on the settlement date marked by the Fed in the transaction itself. We process same-day on receipt and next-day at the start of the next business day. ## Merchant disbursements When you send Instant Network Transfer (INT) push volume, you receive notifications you didn't initiate. They're system-generated. Identify these transfers by , not by a prefix. In general, ID prefixes (such as and ) can change and aren't a stable contract. Highnote emits them on the next business day (T+1) while staging the network settlement of your prior-day INT push volume (see Timeline: funds settlement), and you **take no action on them**. A transfer carries these field values: | Field | Value | Meaning | | :-------------------------- | :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------- | | | | The [](/docs/api-reference/object#OriginatedAchTransfer) ID. | | | | Highnote-generated settlement of network-rail volume, distinct from a transfer you initiated. | | | | Funds move out of the originating financial account. | | | | The originating financial account balance decreases. | | | Your financial account | The originating account whose prior-day INT push volume is being settled. | | | Settlement account | Where the staged funds move. See the note below on its type. | | | | An internal [](/docs/api-reference/object#DisbursementTransferEvent) ID, not a reconciliation key you supplied. | - In the payload, resolves to , which can make the transfer look like money leaving Highnote for an outside bank. - For a , both sides of the movement are held at Highnote's bank partner. It is an internal book transfer that uses ACH as the movement mechanism, with no external destination you need to recognize. ## Example use cases #### Originated Push - Highnote debited, External account credited - Customer refunds - Cash-out from prepaid - Gig worker payouts - Expense reimbursements #### Originated Pull - Highnote credited, External account debited - All credit card payments and autopay - Prepaid card loading - Fleet fuel payments - Charge card full payments #### Non-originated Push - Highnote credited - Direct deposits (payroll, benefits) - Business funding for AP automation - Corporate payments to subsidiaries - Tax refunds and government payments #### Non-originated Pull - Highnote debited - External bill pay services - Third-party payment processors - Corporate treasury management - Bank-initiated transfers --- URL: https://docs.highnote.com/docs/money-movement/payment-rails/failure-reasons Title: Transfer Failure Reasons Section: Money Movement Description: What each Real-Time Payments and Unified Funds Transfer failure reason means, grouped by the action to take. Covers routing to another rail, retry, and request errors. ## Overview When a transfer fails, its tells you why. This page groups the reasons you can receive on a Real-Time Payments transfer by the action to take. Group your handling by action, not by individual value. Highnote adds values to these enums, and can move an existing condition to a more precise value. A handler keyed to one value can stop matching after a change like that, while the transfer outcome stays the same. For Instant Network Transfer failures, see Transfer failure reasons on the Instant Network Transfers page. For the synchronous codes that can preempt some of these failures on RTP transfers submitted through , see RTP Transfer Error Codes. ## Where to read the failure Three fields report a failure, and they do not always carry the same value. | Field | Enum | What it describes | | :------------------------------------------ | :------------------------------------------------------------------------------------------------ | :---------------------------------- | | | [](/docs/api-reference/enum#UnifiedFundsTransferFailureReason) | Why the transfer failed end to end. | | | [](/docs/api-reference/enum#UnifiedFundsTransferFailureReason) | Why the RTP step failed. | | | [](/docs/api-reference/enum#RtpTransferFailureReason) | Why the RTP transfer itself failed. | Read the RTP transfer first when you need the most specific answer. Fall back to the Unified Funds Transfer value when no RTP transfer exists, which happens when validation stops the transfer before Highnote sends it. Three conditions lose detail on the Unified Funds Transfer. , , and all report there as . Separately, and with no loss of meaning, on the RTP transfer is named on the Unified Funds Transfer. The **In which enum** column in the tables below records which enum defines a value. It does not tell you which surface produced your specific failure. Read the you received rather than inferring it from that column. An on a Unified Funds Transfer is therefore not always a Highnote fault. Read the RTP transfer before you retry, and see Duplicate submissions. ## Group 1: RTP cannot deliver this transfer The receiving bank or the rail cannot accept the transfer. Route the payment to another rail, such as ACH or Wire. For the first two values below, retrying the same transfer on RTP fails identically. and are normally rejected synchronously as a , before Highnote creates a transfer. See RTP Transfer Error Codes. They can still appear below as a , most often when the destination becomes ineligible after the pre-flight check passes. | Failure reason | In which enum | Meaning | | :---------------------------- | :------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Both | The receiving bank does not participate in RTP. | | | Both | The receiving bank participates in RTP but is not active to receive. | | | Both | The rail is disabled at the partner bank. No transfer on this network can currently succeed. The state can be cleared, so a later attempt may succeed. Do not wait on it for a time-sensitive payment. | | | Both | The partner bank does not support this rail. | and describe two different bank states. They call for the same routing decision. Match both. The Transfer Funds API does not fall back to same-day ACH. You build that fallback. Match every value in this group, not one value. Highnote can add a value to this group, and a fallback keyed to a single value will stop firing when that happens. ## Group 2: Retry later The condition is temporary. The same request can succeed on a later attempt. | Failure reason | In which enum | Meaning | | :--------------------- | :------------ | :------------------------------------------------------------ | | | Both | The network or the receiving bank did not answer in time. | | | Both | The network rejected the message for a system condition. | | | Both | A daily count or value limit was reached. Retry the next day. | means Highnote did not receive an answer. It does not confirm that the receiving bank rejected the payment. Check the transfer status before you resend, and use a new idempotency key only when you have confirmed the first attempt failed. See Idempotency. ## Group 3: Change the request and resubmit The request is the problem. Correct it and send a new transfer. | Failure reason | In which enum | What to change | | :------------------------------------- | :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Both | The amount is above a per-transaction maximum. Reduce the amount. | | | Both | The amount is below a rail or agreement minimum. Increase the amount. | | | Both | The amount is missing, malformed, or not the agreed value. | | | Both | The currency does not match the account or the rail. | | | Both | The source account does not hold the amount. Fund the account and retry. | | | Unified Funds Transfer only | holds a disallowed character or is too long. See Payment information rules. | | | Unified Funds Transfer only | The source and the destination are the same account. | | | RTP transfer only | The same condition, reported on the RTP transfer. | | | RTP transfer only | A field failed validation at the partner bank. Reports as on the Unified Funds Transfer. | Most problems on RTP transfers submitted through are rejected synchronously as or , before Highnote creates a transfer. See RTP Transfer Error Codes. above covers the same condition reported asynchronously. ## Group 4: Terminal The transfer will not succeed as sent. Do not retry the same request unchanged. One value, , can also mean a configuration problem on your side that you can fix. | Failure reason | In which enum | Meaning | | :----------------------- | :------------ | :----------------------------------------------------------------------------------- | | | Both | The destination account is closed. | | | Both | The destination account does not exist at the receiving bank. | | | Both | The destination account exists but cannot receive. | | | Both | The destination account is blocked. | | | Both | A risk control declined the transfer. | | | Both | Highnote configuration or the receiving bank did not permit the transfer. See below. | can come from Highnote's own risk controls or from the receiving bank. Retrying the same transfer returns the same result. Contact Highnote to review the decline, and do not present it to your customer as a decision by the receiving bank. has two causes that need opposite responses, and the failure reason does not tell you which one you hit. **Highnote did not permit the transfer.** Your product or account configuration does not allow it. The transfer type is not enabled on the product, the funding card is not supported, an account-holder condition is not met, or a required feature is off. Validation returns this before Highnote sends anything, so no bank saw the transfer. Another rail does not help. Check your product configuration, or contact Highnote. **The receiving bank refused the transfer.** Causes include customer instruction, a legal or regulatory restriction, and account eligibility at the receiving bank. This is terminal for that destination. Offer another payout method. If a transfer that used to work starts returning , check your own configuration first. ## Duplicate submissions The receiving bank rejects a transfer it identifies as a duplicate. Highnote reports this as on , and as on . Do not retry on either value. A duplicate rejection usually means the first payment already exists at the receiving bank. Query the earlier transfer and confirm its status before you send anything else. See Idempotency. ## Complete enum reference This page covers the reasons a Real-Time Payments transfer returns. For every value in each enum, including values that apply to other rails, see: - [](/docs/api-reference/enum#UnifiedFundsTransferFailureReason) - [](/docs/api-reference/enum#RtpTransferFailureReason) --- URL: https://docs.highnote.com/docs/money-movement/payment-rails/int-transfers Title: Instant Network Transfers Section: Money Movement Description: Push funds to and pull funds from external debit and prepaid cards using Visa Direct or Mastercard Send. Transfers move between a Highnote financial account and a tokenized external card. Supports single-use and reusable payment method tokens. ## Overview Highnote **Instant Network Transfer** (INT) is a specific payment rail within Highnote's instant payments suite that enables your cardholders to make near real-time domestic money movements to and from eligible external cards, both personal and business. Instant Network Transfers are implemented through Highnote's **Unified Funds Transfer** (UFT) framework, using the UnifiedFundsTransfer API object to handle the technical processing of these transactions. ### Transfer directions The INT payment rail moves funds in **both directions** between a Highnote FinancialAccount and an eligible external debit or prepaid card, operating through **Visa Direct and Mastercard Send** (a Mastercard Move platform). | Direction | Transaction | Source | Destination | | :----------------- | :-------------------------------------------------------------------------------------- | :------------------------ | :------------------------ | | **Push to card** | OCT (credit) | Highnote FinancialAccount | Tokenized external card | | **Pull from card** | AFT (debit) | Tokenized external card | Highnote FinancialAccount | The Highnote side of a transfer is always a FinancialAccount, and the external side is always a tokenized card. That FinancialAccount may be one backing a Highnote-issued payment card — you address it by FinancialAccount ID, not by card ID. Each direction is gated independently by its own capability on the external card, and both directions use the same quote-and-initiate flow described below. For both directions as a single call, see Push to card and Pull from card in the Transfer Funds API. ## Capabilities Before an external card can send or receive funds through an Instant Network Transfer, Highnote verifies that the card is eligible. The result of this verification is expressed as **capabilities** — two independent assessments of what the card can do: - INT Destination Capability — whether the card can **receive** funds (push/OCT). - INT Source Capability — whether the card can **send** funds (pull/AFT). Each capability has a status of , , or . A card must have status on the relevant capability before you can initiate a transfer. The two capabilities are evaluated independently and may have different statuses for the same card. ### How status is determined When you create a reusable payment method token, Highnote submits a verification request to the card's issuer. The issuer's response, combined with card network data, determines each capability's status through a series of checks. The destination and source capabilities have different risk profiles, so some checks apply differently. - Pushing money to a card (destination) requires the card network to support receiving funds, but is more lenient on identity matching. - Pulling money from a card (source) does not require network-level eligibility, but demands stronger identity verification because it authorizes a debit. #### Two gates - **Gate 1** (Issuer approval) If the issuer declines the verification request, both capabilities are immediately . No further checks are performed. - **Gate 2** (OCT eligibility, destination only) If the card is not eligible for OCT transactions, the destination capability is regardless of any other results. Source capability is unaffected by this gate because pulling funds does not use OCT. **If both gates pass**, Highnote scores two verification checks independently (ANI and AVS) then combines them. CVV is also part of the verification request but does not affect capabilities status; it only factors into the issuer's approve or decline decision. #### Account Name Inquiry (ANI) {#account-name-inquiry} **ANI** compares the cardholder name you submit against the name on file with the issuer. Because pulling funds demands stronger identity confidence, ANI applies stricter thresholds to the source capability: | ANI Result | Destination (Push/OCT) | Source (Pull/AFT) | | :----------------------------------------------- | :--------------------- | :---------------- | | Full name match | | | | ANI not performed | | | | Partial match (first, last, or middle name only) | | | | No match | | | Both first **and** last name must fail to match to produce a no-match result. If either first or last name matches, the result is a partial match. #### Address Verification System (AVS) {#address-verification-system} **AVS** compares the billing address you submit against the address on file with the issuer. AVS scores _the same_ for both capabilities: | AVS Result | Status | | :------------------------ | :---------------- | | Full address match | | | AVS not performed | | | Street address match only | | | Postal code match only | | | No address match | | #### Combining ANI and AVS Highnote takes the ANI and AVS statuses for each capability and applies a **worst status wins rule**. If either check produces , the final status is . If either produces , the final status is . The status is only when both checks are . For example, if ANI produces but AVS produces , the final status for that capability is . ### Decision flows The following diagrams show the full decision flow for each capability. #### Destination capability (receive funds / push / OCT) ```text Issuer approved? ├── No ──────────────────────────────── DISABLED └── Yes └── Card OCT-eligible? ├── No ──────────────────────── DISABLED └── Yes ├── ANI score: │ ├── Full match ──────── ENABLED │ ├── Not performed ───── ENABLED │ ├── Partial match ───── ENABLED │ └── No match ────────── REQUIRES_REVIEW │ ├── AVS score: │ ├── Full match ──────── ENABLED │ ├── Not performed ───── ENABLED │ └── Partial/no match ── REQUIRES_REVIEW │ └── Final: worst of ANI + AVS wins ``` #### Source capability (send funds / pull / AFT) ```text Issuer approved? ├── No ──────────────────────────────── DISABLED └── Yes ├── ANI score: │ ├── Full match ──────────────── ENABLED │ ├── Not performed ───────────── ENABLED │ ├── Partial match ───────────── REQUIRES_REVIEW │ └── No match ────────────────── DISABLED │ ├── AVS score: │ ├── Full match ──────────────── ENABLED │ ├── Not performed ───────────── ENABLED │ └── Partial/no match ────────── REQUIRES_REVIEW │ └── Final: worst of ANI + AVS wins ``` ### Decline reasons The field lives on the destination and source capability objects alongside [](#how-status-is-determined), not on the $0 verification transaction. Each capability also carries a field that lists reasons why the capability is not enabled, namely, or . - When a capability is the list is empty. - When a capability is or , the list can be empty or name one or more reasons. The values come from [](/docs/api-reference/enum#InstantNetworkTransferCapabilityDeclineReason): | Decline Reason | Meaning | | :----------------------------- | :------------------------------------------------------------------------ | | | The card's issuing region is not supported for Instant Network Transfers. | | | The card is not a debit or prepaid card. | | | The card does not support money transfer. | | | Highnote Operations decisioned the capability through case management. | These are card-eligibility and operational checks, and do not line up one-to-one with the two gates: - and are card-eligibility checks the two-gate summary does not call out separately. - is the BIN money-transfer check behind the destination capability's OCT-eligibility gate. - reflects a manual Highnote Operations decision rather than an automated check. Issuer declines (Gate 1) are reflected in the field and its status-change events. An issuer decline or an identity-driven produces no value, so fall back to the and the ANI/AVS codes in those cases. ### Simulating capabilities You can simulate capabilities with the following card data. Currently, only Visa cards support simulation. | Card Network | PAN | CVV/CVC | Expiration | Name | Address | | :----------- | :------------------ | :------ | :-------------- | :------- | :--------------------------- | | Visa | 4000 0000 0000 0010 | 111 | Any future date | John Doe | 1234 Visa St, Visa, CA 12345 | ### Query for status changes Payment instrument capabilities are returned synchronously in the response, but can take 3-5 minutes to appear in subsequent queries due to synchronization between databases. Subscribe to the associated notification event topics to receive webhooks when a capability status changes. To detect changes to the capabilities status after initial tokenization (e.g., from → ), query for the Customer object with the list of reusable payment methods (each will have a list of capabilities and their latest status). You can remove the object from the query. ### Retrieve verification results You can query ANI and AVS response codes inline when vaulting a card or on a vaulted card. The capability tells you whether a card can send or receive funds; the underlying ANI and AVS results determine the status value. Both ANI and AVS response codes are available on each capability's $0 verification transaction created when the card was vaulted. ANI/AVS codes only explain the status once the card clears both verification gates. A capability that is from a gate failure (issuer decline or OCT-ineligibility) never reaches ANI/AVS scoring, so its response codes won't explain the status. See How status is determined for the gate logic. You reach that $0 verification transaction through each capability's field, typed as the [](/docs/api-reference/interface#PaymentTransaction) interface. Its [](/docs/api-reference/object#PaymentTransactionResponseCode) is defined on that interface, so you can select it directly. The examples below use an inline fragment to pin the [](/docs/api-reference/object#PaymentDebitTransaction) concrete type the verification transaction resolves to. | Field | Check | Possible values | | :---------------------------------------------------------------- | :---- | :------------------------------------------------------------------------------ | | , , , | ANI | , , , , | | , | AVS | , , , , , | | | CVV | , , , , , | The **destination** and **source** capabilities are backed by the same , so the ANI and AVS response codes are identical for both directions. What can differ is the capability . Each direction scores the same codes against its own thresholds, so the stricter source (pull/AFT) capability can land on while the destination (push/OCT) capability is . See Combining ANI and AVS for the scoring rules. ANI/AVS response codes are normalized across card networks. Visa and Mastercard return verification results through different underlying services, but Highnote maps both into the single set of fields above. So you read the same , , and name-match codes regardless of which network the card runs on, and never branch on network. #### Query inline when vaulting a card When you make the payment method token reusable in Step 2, request the verification fields on the mutation response to receive the results without a follow-up call. #### Query a vaulted card Query the customer's wallet at any time to re-read the latest verification codes for each vaulted (or saved) card. ### Capability status-change events {#notification-events} When a capability transitions, Highnote sends a notification event so your integration can react without polling. The four events that fire on the [](/docs/api-reference/object#PaymentMethodToken) are: | Webhook event name | When it fires | | :------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- | | | A capability moved to (the card can be used in the corresponding direction). | | | A capability moved to (the card cannot be used in the corresponding direction). | | | A capability moved to (the card requires manual review by Highnote Operations before it can be used). | | | A capability previously in was reviewed. Inspect for the outcome ( or ). | Highnote sends one notification per capability status change — the destination and source capabilities fire independently. For payload examples and the destination/source webhook-aliasing pattern, see Capabilities events in the Events reference. ### How capabilities gate transactions A transfer cannot be initiated unless the relevant capability on the external card is : - Pulling funds **from** a card requires the [](/docs/api-reference/object#InstantNetworkTransferSourcePaymentInstrumentCapability) status to be . - Pushing funds **to** a card requires the [](/docs/api-reference/object#InstantNetworkTransferDestinationPaymentInstrumentCapability) status to be . The two capabilities are independent — the same card may be for one direction and or for the other. If you attempt to initiate a transfer against a card whose capability is not in the relevant direction, the transfer fails before the network sees it. ### Null capabilities A capability field can also come back . That is not a status and not a determination — it means no capability record exists yet for that card. It is different from , which is an active decision and always carries a decline reason. Capability records are only written once a $0 verification completes (see How status is determined). The destination and source capabilities are always evaluated and written together, so don't expect one direction's capability to exist without the other. The most common way to encounter is timing, not ineligibility: as noted in Query for status changes, capabilities are returned synchronously in the response but can take 3-5 minutes to appear in later queries. Query again after that window before drawing any conclusion from a result. A transfer against a card with no capability is declined before it reaches the network (see How capabilities gate transactions). If the relevant capability is at transfer time, Highnote declines with a of (destination) or (source) — see Reading a decline reason. Treat the same as any non- status: do not start the transfer. Don't cache it as a permanent negative or mark the card ineligible — a card that previously had capabilities can show again after a re-add, since re-adding a card starts a new verification history. Re-query after the sync window above; if the capability is still , no verification has completed for this card yet, so re-tokenize the card or contact Highnote support with the card's ID (e.g. , as used in Step 2). The same rule applies if a capability object's field itself comes back rather than the object being absent — the service returned an unspecified status, and anything that isn't isn't enabled. ## Event lifecycle The lifecycle of every Instant Network Transfer has the following properties: - There are two phases — (a) a _one-time_ $0 verification (or vaulting), per card, that unlocks capabilities, and (b) the actual transfer itself. - There are three objects created across the lifecycle — two instances of and one . - During the transfer phase, the INT forks along two tracks with unique timelines — (a) funds become available to the cardholder almost instantly (b) the funds settle with the networks in 1-3 days. ### Verification and transfer phases ```text PHASE 1 — Verification / Vaulting (one-time per card) ───────────────────────────────────── Highnote sends a $0 verification to the Issuer. Outcome: capability status (ENABLED / REQUIRES_REVIEW / DISABLED). ENABLED is the prerequisite for any transfer. │ ▼ PHASE 2 — Transfer (two parallel timelines per transfer) ────────────────────────────────────────────────────────── InstantNetworkTransfer is initiated │ ├──► FUNDS AVAILABILITY timeline ──► seconds – 30 min │ (Fast Funds SLA) Funds visible │ INT.status = COMPLETED │ └──► FUNDS SETTLEMENT timeline ──► T+1 business day (network settlement) Associated PaymentTransaction clears and disburses ``` ### Transaction and transfer objects Three objects track the progress of an INT. Two are instances with different roles and parents. 1. **$0 Verification PaymentTransaction** — created once when a card is vaulted; see Capabilities. 2. **InstantNetworkTransfer** — created at initiation. 3. **Associated PaymentTransaction** — created during execution. ```text VAULT TIME (one-time) ───────────────────── Capability (per-card status) │ │ verificationPaymentTransaction ▼ 1. $0 Verification PaymentTransaction (one per vaulted card) TRANSFER TIME (per transfer) ──────────────────────────── 2. InstantNetworkTransfer (the transfer order; status PENDING → COMPLETED) │ │ events[].associatedPaymentTransaction ▼ 3. Associated PaymentTransaction (stays PENDING until T+1 disbursement) ``` ### Parallel transfer timelines The actual transfer forks along two parallel timelines, each with unique milestones: | INT Timeline | Milestone | How you know it happened | | :----------------- | :----------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------ | | Funds availability | Recipient cardholder can see and spend the funds (typically instant; see network rules) | | | Funds settlement | Funds disburse from your financial account (1-3 days) | exits | ### Timeline: funds availability Funds become available to the recipient cardholder when the recipient Issuer posts them—typically within seconds. The outer bound is set by the network's own rules rather than by a single figure: see Payment network funds availability rules for the Visa and Mastercard Send timings, and for the cases where posting can extend well beyond 30 minutes. The Issuer post happens off-event as no fires when the recipient cardholder is credited. Funds-availability speed is governed by the recipient Issuer's adherence to the payment network specifications—not by Highnote, and not by the INT's own . The _destination_ capability is your earliest signal where indicates BIN-level money-transfer support and often signals the opposite. By contrast, transfers can take hours and should not be confused with transfers in the state. Until an on-hold transfer resolves, your ledger holds on the originating account remain in place and the transfer's final outcome is not yet settled. See On-hold states. #### Payment network funds availability rules Fast Funds is the Visa Direct rule for Original Credit Transactions (OCTs). On Visa Direct, the recipient Issuer must post funds within the Fast Funds SLA. A participating Issuer must: - Support the OCT message (a 0100/TC06 dual-message exchange, or a 0200 single-message system) - Make funds available within **30 minutes or less** of approving the OCT (**60 seconds or less** for U.S. domestic) - Submit an updated Customer Information Questionnaire (CIQ) to Visa to enable the Fast Funds indicator on its issuing identifier. For qualifying transactions, a Fast Funds indicator is carried in **TCR3 position 16** for Issuer reconciliation. If the recipient Issuer does not comply with the SLA, Visa permits the **Non/Late Posting Process** to reclaim funds. ##### BIN money-transfer check {#hn-bin-service} Highnote's BIN service checks money-transfer support (including Fast Funds) when evaluating the [](/docs/api-reference/object#InstantNetworkTransferDestinationPaymentInstrumentCapability). A capability returned as because the BIN does not support money transfers is a strong tell that the recipient Issuer is not Fast Funds-enabled. For **Mastercard Send**, the 30-minute funds availability rule runs from the time of authorization approval. It is Mastercard's Fast Posting standard, and it is scoped to **debit and prepaid** destination accounts. Credit destinations follow a different track: funds show as pending within 30 minutes, but posting is permitted up to two business days after clearing. Treat 30 minutes as Mastercard's ceiling for typical processing rather than a guarantee for every transfer. A Receiving Institution can invoke an **Additional Decision Period** of up to six business days, during which the transfer shows as pending rather than posted. ### Timeline: funds settlement Disbursement is when funds actually leave your financial account and the associated transitions out of . Disbursement typically occurs the **next business day** after the INT completes. Next business days are: - Monday–Thursday → next business day - Friday, Saturday, Sunday → batched, disburse Monday (three-day batch) - Immediately before a Monday bank holiday → batched through the holiday, disburse Tuesday (four-day batch) The associated [](/docs/api-reference/interface#PaymentTransaction) stays in throughout this window, and transitions only when disbursement completes, even if the is already . - As part of this next-day settlement, Highnote emits a system-generated notification for the settled volume on each originating account (). - You don't initiate or act on it. See Merchant disbursements. For the network-side schedule that drives these batches, see Network settlement times. #### Ledger movement As the INT progresses, your financial account ledgers update in two steps: | INT status | Ledger movement | Effect on your account | | :---------- | :---------------------------------------- | :-------------------------------------------------------------------------------------------- | | | → | Your spendable balance drops; funds are reserved and cannot be committed to another transfer. | | | → | The ledger entry finalizes for the outgoing transfer. | Your spendable balance reflects the outgoing INT as soon as it enters — not at disbursement. ### Lifecycle events A transfer fires through the following [](/docs/api-reference/enum#InstantNetworkTransferEventType) values, observable via the field. The **Milestone** column flags events that mark cardholder funds availability and your funds settlement progress. | Event type | When it fires | Milestone | | :---------------------------- | :------------------------------------------- | :---------------------------------------------------------------------------- | | | Transfer requested | Your INT is initiated | | | Compliance review event was created | — | | | Pull (debit / AFT) authorized | — | | | Push (credit / OCT) authorized | The recipient cardholder's Fast Funds SLA starts | | | Funds pulled from source card | — | | | Funds pushed to destination card | — | | | Pull cleared | — | | | Push cleared; INT transitions to | The INT is confirmed and the associated enters | | | Pull reversed (failure path) | — | | | Push reversed (failure path) | — | The [](/docs/api-reference/enum#InstantNetworkTransferStatus) transitions from to (or ). A transfer may also pass through an intermediate **on-hold state** before it resolves. On , the event's field is populated with one of the [](/docs/api-reference/enum#InstantNetworkTransferFailureReason) values, for example: - - - ### Transfer status values The [](/docs/api-reference/enum#InstantNetworkTransferStatus) reports where a transfer is in its lifecycle: | Status | Meaning | | :---------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Accepted by Highnote and in flight. | | | Cleared the network; the funds are good and the transfer cannot be reversed through Highnote. | | | Rejected; any ledger holds on the originating account are reversed. | | | Reached the network, but the network's approval is not yet known because of a connectivity failure. Highnote reconciles against the network's settlement records to determine the outcome. | | | The network approved the transfer, but it is awaiting internal resolution after a post-approval processing error on Highnote's side. Resolves without cardholder action. | #### On-hold states Most transfers move from to within seconds. A small subset instead enters one of two **on-hold** states when a transfer reaches the network but its outcome cannot yet be confirmed by Highnote. Both are normal, automatically-resolving states, not system failures, and they differ in what is still unknown: - — the network's **approval itself is unknown**, because a connectivity failure prevented Highnote from receiving the network's response. Highnote reconciles against the network's settlement records to determine whether the transfer succeeded or failed. - — the network approved the transfer, but a **post-approval processing error** on Highnote's side is still being resolved internally. While a transfer is on hold: - **Your ledger hold remains in place**. The hold taken at on the originating account stays reserved until the transfer resolves. Your spendable balance does not return during the on-hold window. This is the -row reservation in Ledger movement. The on-hold transfer holds there rather than advancing. - **No Subscriber action is required**. Highnote resolves the transfer automatically, by reconciling against the network's settlement records (), or by completing internal processing (). The on-hold value is a status of the itself, surfaced on the transfer's network-facing events in the event timeline. When the transfer resolves, the leg's clearing event () marks completion, and its reversal event () marks an unwound transfer. ### Transfer failure reasons When a transfer's is , its tells you why. Failure reasons fall into three groups (setup and validation, Highnote-originated declines, and issuer declines), and the group tells you what you can do about it. The group also tells you how far the transfer got before it stopped. #### Setup and validation failures Setup and validation failures mean the transfer never reached the receiving issuer — your program configuration or the request stopped it first, so you can usually resolve them yourself. Examples include: - - - (source account) - - - #### Highnote-originated declines Highnote-originated declines mean Highnote's own risk controls declined the transfer before it was sent to the card network. The receiving issuer never saw the transfer, so the decline is not the issuer's decision and no network response code explains it. These declines report on both the transfer's and the associated transaction's . That value is Highnote's own, not a code relayed from the network. See Reading a decline reason for the fields to query. Retrying the same transfer right away returns the same result. Contact Highnote to review the decline, and do not present it to your customer as an issuer decline. #### Issuer decline failures Issuer declines mean the transfer reached the receiving cardholder's issuer, and the issuer declined it. These are network response codes relayed back to you, so the outcome is the issuer's decision and you generally cannot change it. Examples include: - [](#invalid-merchant-failures) - - - - For the complete list of Instant Network Transfer failure reasons, see [](/docs/api-reference/enum#InstantNetworkTransferFailureReason). #### Reading a decline reason Two fields report a decline, and neither is enough on its own. Read both and act on whichever one names the cause: | Case | | | | :--------------------------------------------------- | :------------------------------------------ | :---------------------------------------------------------------- | | Issuer requires strong customer authentication (SCA) | (generic) | | | Highnote risk decline | | | In the first case the failure reason is generic and only the response code names the cause. In the second the two agree. Response codes come from [](/docs/api-reference/enum#PaymentTransactionResponseCodeProcessorResponseCode). Both fields sit on the transfer's events: ```text UnifiedFundsTransfer.steps └── ... on UnifiedFundsTransferInstantNetworkTransferStep └── transfer └── ... on InstantNetworkTransfer └── events ├── failureReason └── associatedPaymentTransaction └── responseCode.processorResponseCode ``` returns the [](/docs/api-reference/union#UnifiedFundsTransferStep) union and returns the [](/docs/api-reference/union#UnifiedFundsTransferStepTransfer) union, so pin each concrete type with an inline fragment. is typed as the [](/docs/api-reference/interface#PaymentTransaction) interface, and [](/docs/api-reference/object#PaymentTransactionResponseCode) is defined on that interface, so you can select it directly. See Query existing Unified Funds Transfer for the query shape. #### Invalid merchant failures is a common source of confusion on push payments, because the sender is not a store. It means the receiving cardholder's issuer declined the transfer because the merchant is not authorized for that card. A push carries a merchant category code (MCC), and a common reason is that the issuer restricts that category for the card. The issuer, not Highnote or the sender, makes the decision. Because the decline is the issuer's, you cannot override it, and retrying the same transfer to the same card generally will not succeed unless the issuer's restriction changes. Offer the recipient an alternative payout method or destination card. ### UFT state machine Every Instant Network Transfer is executed through the Unified Funds Transfer framework. The UFT moves through three transaction-level states. The rail step (RTP or INT) runs internally and is not directly observable through webhooks; OFAC screening happens inside it. On , inspect [](/docs/api-reference/enum#UnifiedFundsTransferFailureReason) on the step whose is to determine the cause (rail rejection, sanctions screen, account closed, etc.). When the failed step is the RTP step, see Transfer Failure Reasons for what each value means and what to do about it. ### Webhook notifications For event-driven integrations, Highnote also delivers higher-level UFT and INT lifecycle webhooks: | Webhook event name | When it fires | | :----------------------------------------- | :--------------------------------------------------------------------------------------------- | | | A Unified Funds Transfer was initiated | | | The INT portion of the UFT was initiated | | | The INT portion completed; funds are good and the transfer cannot be reversed through Highnote | | | The INT portion failed; inspect on the associated event | | | The UFT completed end-to-end | | | The UFT failed end-to-end | For payload schemas and full webhook details, see Unified funds transfer and Instant network transfer in the Events reference. ## Creating an instant payment Creating an instant payment with a fee quote requires the following steps: - Step 1. Create a single-use (3-hour) PaymentMethodToken from customer card data (with the Secure Inputs or Checkout SDK). _Return the tokenized payment card to your server​._ - Step 2. Associate the PaymentMethodToken with the customer ID (to make it reusable). _Your server invokes the API call, then Highnote runs checks and vaults the card._ - Step 3. Get a single-use ScopedPaymentMethodToken by querying the Customer object. - Step 4. Create a UnifiedFundsTransferQuote for fees (on cards with capabilities ). - Step 5. Initiate a UnifiedFundsTransfer. _Your server initiates the transfer after creating the quote._ Steps 4 and 5 are the quote flow, which lets you show fees to the customer before committing. To skip them, the Transfer Funds API completes the same transfer in a single call. The card still has to be tokenized first either way. **You cannot reverse or refund a completed Instant Network Transfer through Highnote.** As soon as an INT completes, the funds are considered “good funds.” The [](/docs/api-reference/object#InstantNetworkTransfer) object exposes no cancel, reverse, or refund mutation, and its status has no reversed state. To reverse the money movement of a completed Instant Network Transfer, you must run _another_ follow-on INT. All associated fees are charged to you. On Visa, the network defines narrow exception-processing paths that sit outside Highnote's API: a Good Faith Adjustment raised through Visa Resolve Online (VROL), and a time-boxed Request for Proof of Posting that can lead to a debit adjustment—the same family as the Non/Late Posting Process described above. These are issuer-mediated and deadline-bound, they cover specific error scenarios rather than buyer's remorse, and you cannot initiate them through Highnote. Mastercard Send defines no equivalent general reversal path. ## Step 1. Generate single-use Payment Method Token You can use the Highnote Checkout SDK or Secure Inputs SDK to tokenize a customer's card data as a single-use PaymentMethodToken. Integrate either SDK in your application on the page where the customer enters their card and saves their payment method. ##### Summary of the SDK token flow 1. Fetch client token with generatePaymentMethodTokenizationClientToken: Your server gets a client token from Highnote for authentication. 2. Initialize SDK: You pass the client token to (with other configurations). 3. Customer presses **Submit** button: This triggers an callback whereby the SDK tokenizes the card data and returns a PaymentMethodToken representing the customer's card data. 4. Pass PaymentMethodToken to your server: Your server can securely authenticate with Highnote's API to complete the payment process. ### Checkout SDK Follow the guide on setting up the Checkout SDK. When initializing the SDK, configure the text to be **Submit** instead of "Pay": ```js renderCheckout({ clientToken, additionalFormSections: { cardHolderName: true, billingAddress: true, }, submitButton: { text: "Submit", }, }); ``` ### Secure Inputs SDK Follow the guide on setting up the Secure Inputs SDK. When tokenizing, additional cardholder data is required for OFAC and AVS compliance checks — namely, and . ## Step 2. Make Payment Method Token reusable {#step-2-associate-payment-method-token-with-customer-id} Payment instrument capabilities are returned synchronously in the response, but can take 3-5 minutes to appear in subsequent queries due to synchronization between databases. Subscribe to the associated notification event topics to receive webhooks when a capability status changes. In this step, you associate the single-use PaymentMethodToken from Step 1 with the customer's ID, thereby making it a reusable token. The reusable PaymentMethodToken is only effective if capabilities status returns as . Use the mutation createReusablePaymentMethodToken and set to the single-use PaymentMethodToken (e.g., "tkpmc_single_use_1"). The response returns a (e.g., "tkpmc_1"). The response includes capability statuses that determine whether the card can send or receive funds. See Capabilities for how these statuses are determined and how to simulate them. ## Step 3. Get single-use Scoped Payment Method Token You can get a unique single-use ScopedPaymentMethodToken by querying the Customer object with the reusable payment method token. Set to the reusable PaymentMethodToken (e.g., "tkpmc_1"). ```json { "checkoutToken": { "__typename": "ScopedPaymentMethodToken", "token": "tkpmc_1", "scope": "ECOMMERCE" } } ``` ## Step 4. Create a Unified Funds Transfer Quote In this flow, you must first request a quote before you can initiate a Unified Funds Transfer. The quote is what gives you the fees to present to the user. All fees come out of your financial account. To create a quote for fees on a **push to card** (OCT), set the following inputs: - Set as the ID of a Highnote FinancialAccount owned by user. - Set as the amount to send. - Set as the ScopedPaymentMethodToken. To **pull from a card** (AFT), swap the two sides: set to the ScopedPaymentMethodToken and to the Highnote FinancialAccount. The amount stays on , and the rest of this flow is unchanged. See Transfer directions. Each UnifiedFundsTransferQuote has an value indicating how long the quote is valid. Reference that timestamp to ensure the quote is still valid when offering it to the user. You are now ready to use the following mutation to create a UnifiedFundsTransferQuote in a quote state. You may get back multiple quotes depending on the fee and time estimate. ## Step 5. Initiate a Unified Funds Transfer Once the user has chosen a quote, you can initiate the transfer. Use a that has not expired to start the transfer. ## Query existing Unified Funds Transfer To look up an existing Unified Funds Transfer, use the following query: ### GraphQL: FindCustomerCapabilities Query: query FindCustomerCapabilities($customerIdentifier: String!) { customer(customerIdentifier: $customerIdentifier) { __typename ... on Customer { customerIdentifier cards: wallet( first: 10 filterBy: { paymentMethodType: { equals: PAYMENT_CARD } } ) { __typename ... on PaymentMethodConnection { edges { node { ... on PaymentMethodToken { id usage instrument { __typename ... on PaymentCardInstrument { brand last4 expiryYear expiryMonth capabilities { __typename ... on InstantNetworkTransferDestinationPaymentInstrumentCapability { status createdAt updatedAt } } cardHolder { fullName email billingAddress { streetAddress extendedAddress locality region postalCode countryCodeAlpha3 } } } } checkoutToken: token(scope: ECOMMERCE) { __typename ... on ScopedPaymentMethodToken { token scope } } createdAt updatedAt } } } } } referenceNode { __typename ... on Node { id } ... on USPersonAccountHolder { id name { givenName familyName } email } ... on USBusinessAccountHolder { id businessProfile { id name { legalBusinessName } website } } } } } } Variables: { "customerIdentifier": "" } Expected Result: { "data": { "customer": { "__typename": "Customer", "customerIdentifier": "", "cards": { "__typename": "PaymentMethodConnection", "edges": [ { "node": { "id": "", "usage": "MULTI_USE", "instrument": { "__typename": "PaymentCardInstrument", "brand": "VISA", "last4": "0010", "expiryYear": "2028", "expiryMonth": "12", "capabilities": [ { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "status": "ENABLED", "createdAt": "2026-04-21T12:00:00.000Z", "updatedAt": "2026-04-21T12:00:00.000Z" } ], "cardHolder": { "fullName": "John Doe", "email": "john.doe@example.com", "billingAddress": { "streetAddress": "1234 Visa St", "extendedAddress": null, "locality": "Visa", "region": "CA", "postalCode": "12345", "countryCodeAlpha3": "USA" } } }, "checkoutToken": { "__typename": "ScopedPaymentMethodToken", "token": "", "scope": "ECOMMERCE" }, "createdAt": "2026-04-21T12:00:00.000Z", "updatedAt": "2026-04-21T12:00:00.000Z" } } ] }, "referenceNode": { "__typename": "USPersonAccountHolder", "id": "", "name": { "givenName": "John", "familyName": "Doe" }, "email": "john.doe@example.com" } } } } ### GraphQL: CreateReusablePaymentMethodTokenWithVerification Query: mutation CreateReusablePaymentMethodTokenWithVerification( $input: CreateReusablePaymentMethodTokenInput! ) { createReusablePaymentMethodToken(input: $input) { __typename ... on PaymentMethodToken { instrument { __typename ... on PaymentCardInstrument { brand last4 capabilities { __typename ... on InstantNetworkTransferDestinationPaymentInstrumentCapability { status verificationPaymentTransaction { id ... on PaymentDebitTransaction { responseCode { fullNameCode firstNameCode lastNameCode middleNameCode addressCode postalCode securityCode processorResponseCode } } } } ... on InstantNetworkTransferSourcePaymentInstrumentCapability { aftStatus: status verificationPaymentTransaction { id ... on PaymentDebitTransaction { responseCode { fullNameCode firstNameCode lastNameCode middleNameCode addressCode postalCode securityCode processorResponseCode } } } } } } } checkoutToken: token(scope: ECOMMERCE) { ... on ScopedPaymentMethodToken { token } } } } } Variables: { "input": { "paymentMethodTokenId": "tkpmc_single_use_1", "customerIdentifier": "ps_customerIdentifier", "idempotencyKey": "idempotencyKey" } } Expected Result: { "data": { "createReusablePaymentMethodToken": { "__typename": "PaymentMethodToken", "instrument": { "__typename": "PaymentCardInstrument", "brand": "VISA", "last4": "0010", "capabilities": [ { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "status": "REQUIRES_REVIEW", "verificationPaymentTransaction": { "id": "", "responseCode": { "fullNameCode": "PARTIALLY_MATCHED", "firstNameCode": "MATCHED", "lastNameCode": "NOT_MATCHED", "middleNameCode": "NOT_PROVIDED", "addressCode": "MATCHED", "postalCode": "NOT_MATCHED", "securityCode": "MATCHED", "processorResponseCode": "APPROVED" } } }, { "__typename": "InstantNetworkTransferSourcePaymentInstrumentCapability", "aftStatus": "REQUIRES_REVIEW", "verificationPaymentTransaction": { "id": "", "responseCode": { "fullNameCode": "PARTIALLY_MATCHED", "firstNameCode": "MATCHED", "lastNameCode": "NOT_MATCHED", "middleNameCode": "NOT_PROVIDED", "addressCode": "MATCHED", "postalCode": "NOT_MATCHED", "securityCode": "MATCHED", "processorResponseCode": "APPROVED" } } } ] }, "checkoutToken": { "token": "" } } } } ### GraphQL: FindCardVerificationResults Query: query FindCardVerificationResults($customerIdentifier: String!) { customer(customerIdentifier: $customerIdentifier) { __typename ... on Customer { customerIdentifier cards: wallet( first: 10 filterBy: { paymentMethodType: { equals: PAYMENT_CARD } } ) { __typename ... on PaymentMethodConnection { edges { node { ... on PaymentMethodToken { id instrument { __typename ... on PaymentCardInstrument { brand last4 capabilities { __typename ... on InstantNetworkTransferDestinationPaymentInstrumentCapability { status verificationPaymentTransaction { id ... on PaymentDebitTransaction { responseCode { fullNameCode firstNameCode lastNameCode middleNameCode addressCode postalCode securityCode processorResponseCode } } } } ... on InstantNetworkTransferSourcePaymentInstrumentCapability { aftStatus: status verificationPaymentTransaction { id ... on PaymentDebitTransaction { responseCode { fullNameCode firstNameCode lastNameCode middleNameCode addressCode postalCode securityCode processorResponseCode } } } } } } } } } } } } } } } Variables: { "customerIdentifier": "" } Expected Result: { "data": { "customer": { "__typename": "Customer", "customerIdentifier": "", "cards": { "__typename": "PaymentMethodConnection", "edges": [ { "node": { "id": "", "instrument": { "__typename": "PaymentCardInstrument", "brand": "VISA", "last4": "0010", "capabilities": [ { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "status": "REQUIRES_REVIEW", "verificationPaymentTransaction": { "id": "", "responseCode": { "fullNameCode": "PARTIALLY_MATCHED", "firstNameCode": "MATCHED", "lastNameCode": "NOT_MATCHED", "middleNameCode": "NOT_PROVIDED", "addressCode": "MATCHED", "postalCode": "NOT_MATCHED", "securityCode": "MATCHED", "processorResponseCode": "APPROVED" } } }, { "__typename": "InstantNetworkTransferSourcePaymentInstrumentCapability", "aftStatus": "REQUIRES_REVIEW", "verificationPaymentTransaction": { "id": "", "responseCode": { "fullNameCode": "PARTIALLY_MATCHED", "firstNameCode": "MATCHED", "lastNameCode": "NOT_MATCHED", "middleNameCode": "NOT_PROVIDED", "addressCode": "MATCHED", "postalCode": "NOT_MATCHED", "securityCode": "MATCHED", "processorResponseCode": "APPROVED" } } } ] } } } ] } } } } ### GraphQL: CreateReusablePaymentMethodToken Query: mutation CreateReusablePaymentMethodToken( $input: CreateReusablePaymentMethodTokenInput! ) { createReusablePaymentMethodToken(input: $input) { __typename ... on PaymentMethodToken { instrument { __typename ... on PaymentCardInstrument { brand last4 capabilities { __typename ... on InstantNetworkTransferDestinationPaymentInstrumentCapability { createdAt status updatedAt } } } } checkoutToken: token(scope: ECOMMERCE) { ... on ScopedPaymentMethodToken { token } } } } } Variables: { "input": { "paymentMethodTokenId": "tkpmc_single_use_1", "customerIdentifier": "ps_customerIdentifier", "idempotencyKey": "idempotencyKey" } } Expected Result: { "data": { "createReusablePaymentMethodToken": { "__typename": "PaymentMethodToken", "instrument": { "__typename": "PaymentCardInstrument", "brand": "VISA", "last4": "4242", "capabilities": [ { "__typename": "InstantNetworkTransferDestinationPaymentInstrumentCapability", "createdAt": "2025-07-11T23:28:18.977Z", "status": "ENABLED", "updatedAt": "2025-07-11T23:28:18.977Z" } ] }, "checkoutToken": { "token": "tkpmc_1" } } } } ### GraphQL: CreateTransferQuote Query: mutation CreateTransferQuote($input: CreateUnifiedFundsTransferQuoteInput!) { createUnifiedFundsTransferQuote(input: $input) { __typename ... on CreateUnifiedFundsTransferQuoteResult { quotes { id source { node { ... on Node { id } ... on FinancialAccount { id } } amount { currencyCode value decimalPlaces } } destination { node { ... on Node { id } ... on PaymentMethodToken { id } } amount { currencyCode value decimalPlaces } } transferDetail { timeEstimate feeTotal { value decimalPlaces } } idempotencyKey expiresAt } } } } Variables: { "input": { "source": { "id": "ac_1", "amount": { "currencyCode": "USD", "value": "15000" } }, "destination": { "id": "tkpmc_1" }, "idempotencyKey": "idempotencyKey" } } Expected Result: { "data": { "createUnifiedFundsTransferQuote": { "__typename": "CreateUnifiedFundsTransferQuoteResult", "quotes": [ { "quoteIdentifier": "woquo_1", "source": { "node": { "id": "ac_1" }, "amount": { "currencyCode": "USD", "value": 15000, "decimalPlaces": 2 } }, "destination": { "node": { "id": "tkpmc_1" }, "amount": { "currencyCode": "USD", "value": 14737, "decimalPlaces": 2 } }, "transferDetails": { "timeEstimate": "3 seconds", "feeTotal": { "value": 263, "decimalPlaces": 2 } }, "idempotencyKey": "idempotencyKey", "expiresAt": "2022-01-01T00:00:00Z" }, { "quoteIdentifier": "woquo_2", "source": { "node": { "id": "ac_1" }, "amount": { "currencyCode": "USD", "value": 15000, "decimalPlaces": 2 } }, "destination": { "node": { "id": "tkpmc_1" }, "amount": { "currencyCode": "USD", "value": 15000, "decimalPlaces": 2 } }, "transferDetails": { "timeEstimate": "2-5 days", "feeTotal": { "value": 0, "decimalPlaces": 2 } }, "idempotencyKey": "idempotencyKey", "expiresAt": "2022-01-01T00:00:00Z" } ] } } } ### GraphQL: InitiateUnifiedFundsTransfer Query: mutation InitiateUnifiedFundsTransfer( $input: InitiateUnifiedFundsTransferInput! ) { initiateUnifiedFundsTransfer(input: $input) { __typename ... on UnifiedFundsTransfer { id source { node { ... on Node { id } ... on FinancialAccount { id } } amount { currencyCode value decimalPlaces } } destination { node { ... on Node { id } ... on PaymentMethodToken { id } } amount { currencyCode value decimalPlaces } } externalIdentifier idempotencyKey steps { ... on UnifiedFundsTransferInitiateRequestStep { status createdAt } ... on UnifiedFundsTransferInstantNetworkTransferStep { status createdAt transfer { ... on InstantNetworkTransfer { id createdAt updatedAt status failureReason } } } } } } } Variables: { "input": { "id": "woquo_1" } } Expected Result: { "data": { "initiateUnifiedFundsTransfer": { "__typename": "UnifiedFundsTransfer", "id": "wouft_1", "source": { "node": { "id": "ac_1" } }, "destination": { "node": { "id": "tkpmc_1" } }, "externalIdentifier": "externalIdentifier", "idempotencyKey": "idempotencyKey", "steps": [ { "status": "COMPLETED", "createdAt": "2025-07-11T19:22:37.510Z" }, { "status": "PROCESSING", "createdAt": "2025-07-11T19:22:37.510Z", "transfer": { "id": "eftip_1", "createdAt": "2025-07-11T19:22:37.223Z", "updatedAt": "2025-07-11T19:22:37.229Z", "status": "PENDING", "failureReason": null } } ] } } } ### GraphQL: GetInstantNetworkTransfer Query: query GetInstantNetworkTransfer($id: ID!) { node(id: $id) { __typename id ... on UnifiedFundsTransfer { status steps { __typename ... on UnifiedFundsTransferInstantNetworkTransferStep { __typename transfer { ... on InstantNetworkTransfer { createdAt destination { node { __typename ... on Node { id } ... on PaymentMethodToken { id } } } status events { __typename type } externalIdentifier failureReason id idempotencyKey updatedAt } } } } } } } Variables: { "id": "wouft_1" } Expected Result: { "data": { "node": { "__typename": "UnifiedFundsTransfer", "id": "wouft_1", "status": "PROCESSING", "steps": [ { "__typename": "UnifiedFundsTransferInitiateRequestStep" }, { "__typename": "UnifiedFundsTransferInstantNetworkTransferStep", "transfer": { "createdAt": "2025-07-10T22:30:59.749Z", "destination": { "node": { "__typename": "PaymentMethodToken", "id": "pm_1" } }, "status": "COMPLETED", "events": [ { "__typename": "InstantNetworkTransferEvent", "type": "PUSH_PAYMENT" }, { "__typename": "InstantNetworkTransferEvent", "type": "CLEAR_PUSH_PAYMENT_FUND" }, { "__typename": "InstantNetworkTransferEvent", "type": "AUTHORIZED_PUSH_PAYMENT_FUND" } ], "externalIdentifier": "", "failureReason": null, "id": "eftip_1", "idempotencyKey": "idempotencyKey", "updatedAt": "2025-07-10T22:31:09.876Z" } } ] } } } --- URL: https://docs.highnote.com/docs/money-movement/payment-rails/rtp-error-codes Title: RTP Transfer Error Codes Section: Money Movement Description: Synchronous UserError codes and the sync/async duality for RTP transfers initiated with transferFunds. For the full failureReason reference, see Transfer Failure Reasons. An RTP transfer initiated with can fail in two places: 1. **Synchronously**: the mutation returns a instead of a . Nothing was created; correct the input and retry. 2. **Asynchronously**: the mutation returns a that later moves to . For the complete list of values, what each one means, and how to handle it, see Transfer Failure Reasons. This page covers the synchronous codes, the fee-specific errors, and how the two paths relate. It assumes you have read Transfer Funds API. ## Synchronous UserError codes Each error carries a , a human-readable , and an pointing at the offending input field, including list indices when the field repeats. A single response can contain multiple errors. Handle the list, not just the first entry.
Synchronous UserError codes for RTP transfers | Code | When | Typical | | :---------------------------------- | :------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------ | | | Both or neither of / were provided. Exactly one is required. | or | | | exceeds 140 characters. | | | | contains characters the RTP network does not allow. | | | | The destination bank is not an RTP network participant. | or | | | The destination bank is an RTP participant but is not currently active on the network. | same as above | | | The amount exceeds the RTP transaction limit. | | | | Source and destination are the same account. | | | | The source or destination account does not exist. | or | | | The account's product configuration does not permit this transfer. | or | | | No transfer method supports the given source and destination combination. | — |
and returned this way mean the transfer was rejected up front: no exists, so there is nothing to reconcile. is not confirmed as a synchronous code for RTP transfers. If the destination account exists but cannot receive, expect it as a on a created transfer instead; see Transfer Failure Reasons. ```json title="Sample UserError response" { "data": { "transferFunds": { "__typename": "UserError", "errors": [ { "code": "NETWORK_NOT_SUPPORTED", "errorPath": ["input", "destination", "id"], "description": "Destination routing number is not an RTP network participant" } ] } } } ``` ## Customer fee errors Errors specific to transfers that include . **Synchronous codes** | Code | When | Typical | | :--------------------------- | :---------------------------------------------------------------------------------------------------- | :------------------------------ | | | The fee's names the side whose amount you specified. The fee must charge the other side. | | | | The fee's side is an external bank account, which cannot be charged a fee. | — | **Asynchronous values** | Reason | When | | :---------------------- | :----------------------------------------------------------------------------------------------------------------------------- | | | The fee could not be collected, for example due to insufficient balance on the charged account. The transfer does not proceed. | | | The transfer failed after its fee was collected. The fee was automatically returned. | | | The transfer failed and the collected fee could not be automatically returned. Contact support. | ## Migrating from the async-only behavior Before this rollout, destination-eligibility and problems could only report **asynchronously**, as a on a that reached . Now they report **synchronously**, as a at initiation, and no transfer is created. The underlying problem is the same; only the timing and the code differ. | Problem | Before 2026-08-17 (async) | Now (sync) | | :----------------------------------------- | :--------------------------------------------------- | :----------------------------------------------------- | | Destination not an RTP participant | | on | | Destination bank not active on the network | | on | | Bad | | / on the field | If your integration only handles these conditions as an async , add handling for the synchronous too. A transfer that fails synchronously creates nothing, so any reconciliation logic keyed to a in will not see it. ## Handling guidance - Treat a as an input problem: fix the request and resubmit. - Treat a as terminal for that transfer. Funds, and any collected fees, return or never moved. Submit a new transfer if appropriate. See Transfer Failure Reasons for which reasons allow a retry and which do not. - Always send a unique per attempt. Reuse a key only to safely retry the identical request. ## See also - Transfer Failure Reasons: the complete reference, grouped by the action to take. - Transfer Funds API: request shape, idempotency, and payment-information rules. --- URL: https://docs.highnote.com/docs/money-movement/payment-rails/transfer-funds-api Title: Transfer Funds API Section: Money Movement Description: Move money in a single API call using Real-Time Payments or Instant Network Transfers via Visa Direct OCT/AFT and Mastercard MoneySend Payment/Funding. Supports push-to-card, pull-from-card, and bank transfers. ## Overview The Transfer Funds API moves money in a single-call, eliminating the multi-step quote flow. Real-Time Payment (RTP) and Instant Network Transfer (INT) rails are supported. - For Instant Network Transfers, cards must be tokenized (Step 1) as a reusable payment method (Step 2). - For Real-Time Payments, bank accounts can be verified and tokenized, but don't have to be; they can also be provided directly via account/routing numbers. ### PCI scope You have three options when tokenizing data, each with different PCI burdens: - **Direct API call**: When you tokenize directly with tokenizeCardPaymentMethod, raw card data passes through your servers and puts you in full PCI DSS scope. - **Highnote SDK**: When you use a Highnote SDK, card data never touches your servers and passes from the customer's browser to Highnote. You stay out of PCI scope, or at a much lower level like SAQ A. - **PCI-compliant vendor**: Using a vendor is the middle ground. You can call the API directly but the PCI compliant vendor handles the PCI-sensitive part, keeping you out of full PCI scope. ### Payment strategy Specify the rail in [](/docs/api-reference/input#TransferFundsPaymentStrategyInput): | Strategy | Rail | Description | | :--------------------------- | :----------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | | | Real-Time Payments | Push funds from a Highnote FinancialAccount to an external bank account via with . | | | Instant Network Transfer | Push funds to or pull funds from a tokenized external card via Visa Direct or Mastercard Send. | | or not provided | — | Fails with listing supported strategies. | ### Transfer options Each row below shows the calls required to complete one transfer; an empty cell means the flow ends at the previous step. Rows 1–3 complete the transfer in a single call. Row 4 shows the UnifiedFundsTransfer flow, which separates fetching a fee quote () from initiating the transfer () so you can show the customer fees before committing. | Rail | Step 1 | Step 2 | Step 3 | | :---------------------------------------------------------- | :---------------------------------- | :-------------------------------- | :----------------------------- | | **RTP** | | | | | **RTP** | Tokenize account | | | | **INT** | Tokenize card (as a reusable token) | | | | **INT** | Tokenize card (as a reusable token) | | | ### Consent Requirements - RTP Transfers: Consent is required via . See Consent below for the required fields. - Instant Network Transfers: Consent is not required; card authorization serves as implicit consent. ### Source and destination - The can be a Highnote FinancialAccount ID or a PaymentMethodToken ID. - The can be a Highnote FinancialAccount ID, a PaymentMethodToken ID, or raw US bank account details provided inline. - The amount can be defined under or . ### Network fees Fees Highnote charges you for using the rail. - **RTP**: Fees are invoiced monthly. - **INT**: Fees are charged to the subscriber per transaction. ### Customer fees Use customerFees on to collect a subscriber-defined fee atomically with the transfer — for example, a convenience fee, service fee, or processing fee. Each entry in the array describes one fee. Each TransferFundsCustomerFeeInput accepts: | Field | Type | Description | | :---------------- | :----------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- | | | | Code identifying the fee category — e.g., , , . You define this value. | | | | Optional memo for the fee. | | | | Fixed fee amount. Combined with if both are provided. | | | | Fee as basis points of the transfer amount; = 1%. Cannot exceed (100%). | | | | Floor: if the calculated fee falls below this, the fee is raised to . | | | | Cap: if the calculated fee exceeds this, the fee is capped to . | | | | (added to the source debit) or (subtracted from the destination credit). | | | | The Highnote account that receives the fee, as . | Provide at least one of or . The calculated fee is , then bounded by and if either is provided. Currency on every amount must match the transfer currency. #### Charge from source When , the fee is added to the source debit so the destination receives the full transfer amount. ```json title="customerFees example — 2.5% convenience fee, capped, paid by source" { "customerFees": [ { "customerFeeCode": "CONVENIENCE_FEE", "basisPoints": 250, "minAmount": { "currencyCode": "USD", "value": 100 }, "maxAmount": { "currencyCode": "USD", "value": 1000 }, "chargeFrom": "SOURCE", "destination": { "id": "" }, "description": "2.5% convenience fee" } ] } ``` For a transfer with this fee, the source is debited , the destination receives , and the fee account receives . #### Charge from destination When , the fee is subtracted from the destination credit so the source pays the full transfer amount. ```json title="customerFees example — $1 service fee with a $2.50 floor, paid by destination" { "customerFees": [ { "customerFeeCode": "SERVICE_FEE", "fixedAmount": { "currencyCode": "USD", "value": 100 }, "minAmount": { "currencyCode": "USD", "value": 250 }, "chargeFrom": "DESTINATION", "destination": { "id": "" }, "description": "Service fee (min $2.50)" } ] } ``` For a transfer with this fee, the source is debited , the destination receives (the fixed fee was raised to the floor), and the fee account receives . ## Real-Time Payments Real-Time Payments (RTP) is a push payment; funds are pushed from a Highnote FinancialAccount to an external bank account. There are three ways to pass account information on the RTP rail: - Inline raw details via - Verified ExternalFinancialBankAccount ID via (with Plaid or Finicity) - NonVerifiedExternalUSFinancialBankAccount ID via (stored but unverified) While you can use a verified bank account and create an , you can also provide bank account details inline via . This bypasses third-party bank verification (Plaid/Finicity) entirely. The bank account details (account number, routing number) are provided directly in the request (no Plaid verification required). RTP transfers require on the , which captures payment-related information and the customer's consent. See Consent and Idempotency below. ### Consent RTP requires you to record the customer's consent inside on the . TransferFundsBankTransferDetailsInput has two required fields: | Field | Type | Description | | :-------------------------- | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | | Payment details that may surface to the recipient (e.g., ). Limited to 140 characters and a restricted character set. See Payment information rules. Availability and presentation depend on the receiving institution. | | | | The customer's consent record. | The TransferAgreementConsentInput object captures who authorized the transfer, when, and which consent template they accepted: | Field | Type | Description | | :-------------------------------- | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | | | ID of the individual authorizing the transfer. Use the for Person account holders, or the for Business account holders. | | | | ISO 8601 timestamp marking when consent was given (for example, ). | | | | Identifier of the consent template your customer accepted. You define this value. | | | | Version of the consent template your customer accepted. You define this value. | ```json title="bankTransferDetails (RTP source)" { "bankTransferDetails": { "paymentRelatedInformation": "Invoice 0123456789 Payment 999.99 USD", "consent": { "authorizedPersonId": "", "consentTimestamp": "2026-04-25T14:30:00Z", "template": { "consentTemplateId": "", "consentTemplateVersion": "" } } } } ``` ### Payment information rules When you submit a transfer, Highnote validates and normalizes your . Highnote stores these normalized values and forwards them to the receiving bank, so the recipient may see a cleaned-up version of what you sent. If and how is displayed to recipients is up to the receiving banks. Treat it as a best-effort memo, not a guaranteed delivery channel. #### Character rules On an RTP transfer, can have a maximum of 140 characters. Length is counted on the value you submit, before the whitespace normalization described below — collapsing spaces or trimming line breaks does not bring an over-length value under the limit. - **Supported characters**: Letters (, ), digits (), spaces, and the punctuation and . - **Unsupported characters**: , , , and ` `'&=\paymentRelatedInformation"<>paymentRelatedInformationINVALID_INPUTMAX_LENGTH_REACHEDUserErrorfailureReason: PAYMENT_RELATED_INFORMATION_INVALID\r\n\tidempotencyKeytransferFundsPROCESSINGCOMPLETEDFAILEDaddNonVerifiedExternalUSFinancialBankAccountbankTransferDetailstransferFundsNETWORK_NOT_SUPPORTEDDESTINATION_BANK_NOT_ACTIVEPROVIDER_NETWORK_DISABLEDtransferFundsNETWORK_NOT_SUPPORTEDDESTINATION_BANK_NOT_ACTIVEUserErrorUnifiedFundsTransferfailureReason: "NETWORK_NOT_SUPPORTED"UnifiedFundsTransferUnifiedFundsTransferRtpStepNETWORK_NOT_SUPPORTEDUSBankAccount.institutionNamedestinationFinancialAccounttransferFundsUnifiedFundsTransfernullsourceUSBankAccountUnifiedFundsTransferUnifiedFundsTransferQuotelast4routingNumberaccountTypenullsubmitButtonfullNamebillingAddressmerchantDescriptor.suffixcardTransferDetailsdestinationdestination.cardTransferDetails.merchantDescriptor.suffix*sourcesource.cardTransferDetails.merchantDescriptor.suffix*` separator. With an 8-character prefix under a {MERCHANT_DESCRIPTOR_MAX_CHARS}-character cap, 13 characters remain for the suffix on push and 14 on pull; anything longer is truncated. See Merchant Descriptors for how the prefix and suffix are constructed, the combined-length cap, and the allowed character set. ```json title="INT OCT push with a soft descriptor" { "input": { "source": { "id": "ac_source_financial_account", "amount": { "currencyCode": "USD", "value": "10000" } }, "destination": { "id": "pmt_tokenized_card_123", "cardTransferDetails": { "merchantDescriptor": { "suffix": "ORDER-4821" } } }, "idempotencyKey": "550e8400-e29b-41d4-a716-446655440000", "memo": "Card payout", "strategy": { "preferredPaymentStrategy": ["INSTANT_NETWORK_TRANSFER"] } } } ``` ### Push to card (Visa Direct OCT / Mastercard MoneySend Payment) {#push-to-card} An OCT (Original Credit Transaction) pushes funds from a Highnote Financial Account to a tokenized external card. ### Pull from card (Visa Direct AFT / Mastercard MoneySend Funding) {#pull-from-card} An AFT (Account Funding Transaction) pulls funds from a tokenized external card into a Highnote FinancialAccount. The mutation is the same — swap the source and destination: ```json title="INT AFT Funding" { "input": { "source": { "id": "pmt_tokenized_card_123", "amount": { "currencyCode": "USD", "value": "10000" } }, "destination": { "id": "ac_destination_financial_account" }, "idempotencyKey": "550e8400-e29b-41d4-a716-446655440001", "memo": "Card funding", "strategy": { "preferredPaymentStrategy": ["INSTANT_NETWORK_TRANSFER"] } } } ``` ### GraphQL: transferFunds — RTP (inline bank details) Query: mutation TransferFunds($input: TransferFundsInput!) { transferFunds(input: $input) { __typename ... on UnifiedFundsTransfer { id status failureReason createdAt updatedAt source { node { ... on Node { id } ... on FinancialAccount { id } } amount { currencyCode value decimalPlaces } } destination { node { ... on USBankAccount { last4 routingNumber accountType name { givenName middleName familyName } } } amount { currencyCode value decimalPlaces } } externalIdentifier idempotencyKey memo steps { __typename ... on UnifiedFundsTransferInitiateRequestStep { id status failureReason createdAt } ... on UnifiedFundsTransferRtpStep { id status failureReason createdAt transfer { id status } } } } } } Variables: { "input": { "source": { "id": "ac_merchant_settlement_account", "amount": { "currencyCode": "USD", "value": "50000" } }, "destination": { "usBankAccount": { "accountNumber": "123456789", "routingNumber": "021000021", "accountType": "CHECKING", "firstName": "John", "middleName": "Michael", "lastName": "Doe" }, "bankTransferDetails": { "paymentRelatedInformation": "Invoice #12345 payment", "consent": { "consentTimestamp": "2026-01-20T14:30:00Z", "authorizedPersonId": "per_john_doe_123", "template": { "consentTemplateId": "rtp_authorization_v1", "consentTemplateVersion": "2.0" } } } }, "idempotencyKey": "550e8400-e29b-41d4-a716-446655440001", "memo": "Payout via RTP", "externalIdentifier": "INVOICE-12345", "strategy": { "preferredPaymentStrategy": [ "RTP" ] } } } Expected Result: { "data": { "transferFunds": { "__typename": "UnifiedFundsTransfer", "id": "wouft_1", "status": "PROCESSING", "failureReason": null, "createdAt": "2026-01-20T14:30:01Z", "updatedAt": "2026-01-20T14:30:01Z", "source": { "node": { "id": "ac_merchant_settlement_account" }, "amount": { "currencyCode": "USD", "value": 50000, "decimalPlaces": 2 } }, "destination": { "node": { "last4": "6789", "routingNumber": "021000021", "accountType": "CHECKING", "name": { "givenName": "John", "middleName": "Michael", "familyName": "Doe" } }, "amount": { "currencyCode": "USD", "value": 49500, "decimalPlaces": 2 } }, "externalIdentifier": "INVOICE-12345", "idempotencyKey": "550e8400-e29b-41d4-a716-446655440001", "memo": "Payout via RTP", "steps": [ { "__typename": "UnifiedFundsTransferInitiateRequestStep", "id": "woustep_1", "status": "COMPLETED", "failureReason": null, "createdAt": "2026-01-20T14:30:01Z" }, { "__typename": "UnifiedFundsTransferRtpStep", "id": "woustep_2", "status": "PROCESSING", "failureReason": null, "createdAt": "2026-01-20T14:30:01Z", "transfer": { "id": "rtp_1", "status": "PROCESSING" } } ] } } } ### GraphQL: transferFunds — RTP (non-verified account) Query: mutation TransferFunds($input: TransferFundsInput!) { transferFunds(input: $input) { __typename ... on UnifiedFundsTransfer { id status failureReason createdAt updatedAt source { node { ... on Node { id } ... on FinancialAccount { id } } amount { currencyCode value decimalPlaces } } destination { node { ... on USBankAccount { last4 routingNumber accountType name { givenName familyName } } } amount { currencyCode value decimalPlaces } } externalIdentifier idempotencyKey memo steps { __typename ... on UnifiedFundsTransferInitiateRequestStep { id status failureReason createdAt } ... on UnifiedFundsTransferRtpStep { id status failureReason createdAt transfer { id status } } } } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "source": { "id": "ac_3", "amount": { "currencyCode": "USD", "value": 3501 }, "bankTransferDetails": { "paymentRelatedInformation": "Payment description here", "consent": { "consentTimestamp": "2026-02-20T06:06:51.890Z", "authorizedPersonId": "ps_3", "template": { "consentTemplateId": "consent", "consentTemplateVersion": "0" } } } }, "destination": { "usBankAccount": { "accountNumber": "0123456789", "routingNumber": "074000010", "accountType": "CHECKING", "firstName": "Clemens", "lastName": "McKenzie" } }, "idempotencyKey": "UUID_v4", "strategy": { "preferredPaymentStrategy": [ "RTP" ] }, "externalIdentifier": "UUID_v4", "memo": "Payout via RTP" } } Expected Result: { "data": { "transferFunds": { "__typename": "UnifiedFundsTransfer", "id": "wouft_3", "status": "PROCESSING", "failureReason": null, "createdAt": "2026-02-20T06:06:52Z", "updatedAt": "2026-02-20T06:06:52Z", "source": { "node": { "id": "ac_3" }, "amount": { "currencyCode": "USD", "value": 3501, "decimalPlaces": 2 } }, "destination": { "node": { "last4": "6789", "routingNumber": "074000010", "accountType": "CHECKING", "name": { "givenName": "Clemens", "familyName": "McKenzie" } }, "amount": { "currencyCode": "USD", "value": 3501, "decimalPlaces": 2 } }, "externalIdentifier": "UUID_V4", "idempotencyKey": "UUID_v4", "memo": "Payout via RTP", "steps": [ { "__typename": "UnifiedFundsTransferInitiateRequestStep", "id": "woustep_5", "status": "COMPLETED", "failureReason": null, "createdAt": "2026-02-20T06:06:52Z" }, { "__typename": "UnifiedFundsTransferRtpStep", "id": "woustep_6", "status": "PROCESSING", "failureReason": null, "createdAt": "2026-02-20T06:06:52Z", "transfer": { "id": "rtp_2", "status": "PROCESSING" } } ] } } } ### GraphQL: transferFunds — INT OCT Payment Query: mutation TransferFunds($input: TransferFundsInput!) { transferFunds(input: $input) { __typename ... on UnifiedFundsTransfer { id status failureReason createdAt updatedAt source { node { ... on Node { id } ... on FinancialAccount { id } } amount { currencyCode value decimalPlaces } } destination { node { ... on Node { id } ... on PaymentMethodToken { id } } amount { currencyCode value decimalPlaces } } externalIdentifier idempotencyKey memo steps { __typename ... on UnifiedFundsTransferInitiateRequestStep { id status failureReason createdAt } ... on UnifiedFundsTransferInstantNetworkTransferStep { id status failureReason createdAt transfer { ... on InstantNetworkTransfer { id createdAt updatedAt status failureReason } } } } } ... on UserError { errors { code description errorPath } } ... on AccessDeniedError { message } } } Variables: { "input": { "source": { "id": "ac_2", "amount": { "currencyCode": "USD", "value": "10000" } }, "destination": { "id": "tkpmc_2" }, "idempotencyKey": "UUID_v4", "memo": "Card payout", "strategy": { "preferredPaymentStrategy": [ "INSTANT_NETWORK_TRANSFER" ] } } } Expected Result: { "data": { "transferFunds": { "__typename": "UnifiedFundsTransfer", "id": "wouft_2", "status": "PROCESSING", "failureReason": null, "createdAt": "2026-01-20T15:00:01Z", "updatedAt": "2026-01-20T15:00:01Z", "source": { "node": { "id": "ac_2" }, "amount": { "currencyCode": "USD", "value": 10000, "decimalPlaces": 2 } }, "destination": { "node": { "id": "tkpmc_2" }, "amount": { "currencyCode": "USD", "value": 10000, "decimalPlaces": 2 } }, "externalIdentifier": null, "idempotencyKey": "UUID_v4", "memo": "Card payout", "steps": [ { "__typename": "UnifiedFundsTransferInitiateRequestStep", "id": "woustep_3", "status": "COMPLETED", "failureReason": null, "createdAt": "2026-01-20T15:00:01Z" }, { "__typename": "UnifiedFundsTransferInstantNetworkTransferStep", "id": "woustep_4", "status": "PROCESSING", "failureReason": null, "createdAt": "2026-01-20T15:00:01Z", "transfer": { "id": "int_1", "status": "PROCESSING" } } ] } } } --- URL: https://docs.highnote.com/docs/money-movement/payment-rails/wire-transfers Title: Wire Transfers Section: Money Movement Description: Move funds between Highnote financial accounts and external bank accounts via Fedwire with same-day settlement. Covers incoming and outgoing wire transfers with approval workflows. ## Overview Wire transfers move funds between Highnote financial accounts and external bank accounts via the Fedwire Funds Service. Unlike ACH, wire transfers settle individually in real-time during Fedwire operating hours, making them suitable for high-value, time-sensitive payments. **Key characteristics:** - **Speed:** Same-day settlement (during Fedwire hours) - **Value:** No transaction limit (program limits may apply) - **Finality:** Irrevocable once completed - **Cost:** Higher than ACH ## Transfer directions | Direction | Description | | :----------- | :--------------------------------------------------------------------- | | **Incoming** | Funds received into a Highnote financial account from an external bank | | **Outgoing** | Funds sent from a Highnote financial account to an external bank | ## Transfer statuses Wire transfers progress through the following statuses: | Status | Description | | :----------- | :------------------------------------------------------- | | | Transfer has been scheduled | | | Transfer is being processed | | | Funds have been deposited | | | Transfer failed (see for details) | ## Initiate an incoming wire transfer Use the following mutation to initiate a wire transfer into a Highnote financial account. This creates a review workflow event that must be approved before the transfer is processed. The response returns a with . Once approved, the wire transfer will be processed. ## Find wire transfers After a wire transfer is initiated, use these queries to retrieve transfer details. ### Find incoming wire transfer Use the following query to get an incoming wire transfer by ID: ### Find outgoing wire transfer Use the following query to get an outgoing wire transfer by ID: ## Failure reasons When a wire transfer fails, the provides details: | Reason Code | Description | | :-------------------------------------- | :------------------------------------------------------ | | | Source or receiving account is closed | | | Source or receiving account was not found | | | Receiving account holder is not an organization | | | Source and receiving accounts have different currencies | | | Source account has insufficient funds | ## Simulate wire transfers In the Test environment, you can simulate wire transfers to test your integration. See Simulate a Wire Transfer for details. ### GraphQL: InitiateAddWiredFundsToFinancialAccount Query: mutation InitiateAddWiredFundsToFinancialAccount( $input: InitiateAddWiredFundsToFinancialAccountInput! ) { initiateAddWiredFundsToFinancialAccount(input: $input) { __typename ... on ReviewWorkflowEvent { id reviewState createdAt updatedAt transfer { __typename ... on WireTransfer { id type } } reviewItem { __typename ... on WireTransferReview { toFinancialAccount { __typename id } memo amount { ... on Amount { currencyCode value } } externalIdentifier } } } ... on UserError { errors { code } } ... on AccessDeniedError { message } } } Variables: { "input": { "toFinancialAccountId": "", "memo": "240926-HNS", "idempotencyKey": "00000000-0000-0000-0000-000000000000", "amount": { "value": 500000, "currencyCode": "USD" }, "externalIdentifier": "an additional reference ID" } } Expected Result: { "data": { "initiateAddWiredFundsToFinancialAccount": { "__typename": "ReviewWorkflowEvent", "id": "", "reviewState": "PENDING", "createdAt": "2025-01-23T21:13:41.685Z", "updatedAt": "2025-01-23T21:13:41.707Z", "transfer": null, "reviewItem": { "__typename": "WireTransferReview", "toFinancialAccount": { "__typename": "FinancialAccount", "id": "" }, "memo": "Initiate workflow approval for wire transfer", "amount": { "currencyCode": "USD", "value": 999999 }, "externalIdentifier": "2b43fc97-2541-43fc-8dd6-6ab414ad0a48" } } } } ### GraphQL: NodeWireTransfer (Incoming) Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an incoming wire transfer", "type": "INCOMING_WIRE_TRANSFER", "status": "COMPLETED", "financialAccount": { "id": "" } } } } ### GraphQL: NodeWireTransfer (Outgoing) Query: query NodeWireTransfer($id: ID!) { node(id: $id) { __typename ... on WireTransfer { id amount { value currencyCode } createdAt updatedAt memo type status financialAccount { id } } } } Variables: { "id": "" } Expected Result: { "data": { "node": { "__typename": "WireTransfer", "id": "", "amount": { "value": 2000, "currencyCode": "USD" }, "createdAt": "1970-01-01T00:01:00.000Z", "updatedAt": "1970-01-01T00:02:00.000Z", "memo": "This is an outgoing wire transfer", "type": "OUTGOING_WIRE_TRANSFER", "status": "COMPLETED", "financialAccount": { "id": "" } } } }