Skip to main content

Transfer Funds API

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.

See PCI scope to fully understand your PCI burden when tokenizing data.

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 preferredPaymentStrategy:

StrategyRailDescription
[RTP]Real-Time PaymentsPush funds from a Highnote FinancialAccount to an external bank account via destination.usBankAccount with bankTransferDetails.
[INSTANT_NETWORK_TRANSFER]Instant Network TransferPush funds to or pull funds from a tokenized external card via Visa Direct or Mastercard Send.
[] or not providedFails with USER_ERROR listing supported strategies.

Transfer options

RailStep 1Step 2Step 3
RTPtransferFunds
RTPtokenize accounttransferFunds
INTtokenize cardtransferFunds
INTtokenize cardcreateUnifiedFundsTransferQuoteinitiateUnifiedFundsTransfer
  • RTP Transfers: Consent is required via bankTransferDetails.consent. Must capture: consent timestamp, authorizing person ID, and consent template with version.
  • INT Card Transfers: Consent is not required - card authorization serves as implicit consent.

Source and destination

  • The source can be a Highnote FinancialAccount ID or a PaymentMethodToken ID.
  • The destination can be a Highnote FinancialAccount ID, a PaymentMethodToken ID, or raw US bank account details provided inline.
  • The amount can be defined under source.amount or destination.amount.

Fees

  • RTP: Fees are invoiced monthly.
  • INT: Fees are charged to the subscriber per transaction.

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 destination.usBankAccount
  • Verified ExternalFinancialBankAccount ID via destination.id (with Plaid or Finicity)
  • NonVerifiedExternalUSFinancialBankAccount ID via destination.id (stored but unverified)

While you can use a verified bank account and create an ExternalFinancialBankAccount, you can also provide bank account details inline via destination.usBankAccount. 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 bankTransferDetails on the destination, which includes payment-related information and consent from the authorized person.

Consent is captured directly in the request via bankTransferDetails.

Push to verified bank account

Highnote Financial Account to an External Bank Account

RTP transfers are asynchronous. The initial response status is typically PROCESSING. The final COMPLETED or FAILED status arrives via notification events.

transferFunds — RTP (inline bank details)
Query
mutation TransferFunds($input: TransferFundsInput!) {
transferFunds(input: $input) {
__typename
... on UnifiedFundsTransfer {
id
status
failureReason
createdAt
updatedAt
source {
node {
... 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"
      ]
    }
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
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"
}
}
]
}
}
}

Push to non-verified bank account

Highnote Financial Account to a Non-Verified External Bank Account

If the bank account was previously created via addNonVerifiedExternalUSFinancialBankAccount, you can pass its ID directly instead of providing inline bank details. Consent via bankTransferDetails is still required.

transferFunds — RTP (non-verified account)
Query
mutation TransferFunds($input: TransferFundsInput!) {
transferFunds(input: $input) {
__typename
... on UnifiedFundsTransfer {
id
status
failureReason
createdAt
updatedAt
source {
node {
... 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"
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
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"
}
}
]
}
}
}

Instant Network Transfer

Card transfers do not require consent; card authorization serves as implicit consent.

Instant Network Transfers move funds between a Highnote FinancialAccount and a tokenized external card (with a PaymentMethodToken) through Visa Direct or Mastercard Send. Both push to card and Pull from card are supported.

The external card must be tokenized before initiating the transfer using the Secure Inputs SDK or Checkout SDK.

Tokenize with Checkout SDK

Follow the guide on setting up the Checkout SDK. When initializing the SDK, configure the submitButton text to be Submit instead of "Pay":

renderCheckout({
clientToken,
additionalFormSections: {
cardHolderName: true,
billingAddress: true,
},
submitButton: {
text: "Submit",
},
});

Tokenize with 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, fullName and billingAddress.

Push to card (Visa Direct OCT / Mastercard MoneySend Payment)

Highnote Financial Account to tokenized external card

An OCT (Original Credit Transaction) pushes funds from a Highnote Financial Account to a tokenized external card.

transferFunds — INT OCT Payment
Query
mutation TransferFunds($input: TransferFundsInput!) {
transferFunds(input: $input) {
__typename
... on UnifiedFundsTransfer {
id
status
failureReason
createdAt
updatedAt
source {
node {
... on FinancialAccount {
id
}
}
amount {
currencyCode
value
decimalPlaces
}
}
destination {
node {
... 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"
      ]
    }
  }
}
⚠️ Please login to execute queries. Visit the dashboard to authenticate.
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"
}
}
]
}
}
}

Pull from card (Visa Direct AFT / Mastercard MoneySend Funding)

tokenized external card to Highnote Financial Account

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:

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"]
}
}
}