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.
- For Instant Network Transfers, cards must be tokenized.
- 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 preferredPaymentStrategy:
| Strategy | Rail | Description |
|---|---|---|
[RTP] | Real-Time Payments | Push funds from a Highnote FinancialAccount to an external bank account via destination.usBankAccount with bankTransferDetails. |
[INSTANT_NETWORK_TRANSFER] | 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 USER_ERROR listing supported strategies. |
Transfer options
| Rail | Step 1 | Step 2 | Step 3 |
|---|---|---|---|
| RTP | transferFunds | ||
| RTP | tokenize account | transferFunds | |
| INT | tokenize card | transferFunds | |
| INT | tokenize card | createUnifiedFundsTransferQuote | initiateUnifiedFundsTransfer |
Consent Requirements
- 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
sourcecan be a Highnote FinancialAccount ID or a PaymentMethodToken ID. - The
destinationcan be a Highnote FinancialAccount ID, a PaymentMethodToken ID, or raw US bank account details provided inline. - The amount can be defined under
source.amountordestination.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
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" ] } } }
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
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" } }
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
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)
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" ] } } }
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)
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:
{
"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"]
}
}
}