Skip to main content

Create an internal transfer (v.3)

warning

This is a new Internal Transfers flow, which is recommended for all new integrations.

If you already have an existing integration with the previous Transfers API, you can continue using it. For the Transfers v.2 guide, see Create an internal transfer.

Use this guide to facilitate internal transfers between wallets, with optional currency conversion. You can transfer both fiat and crypto funds.

The transfer can be initiated according to the following scenarios:

  • Between you and your customer
  • Between your customers
  • Between wallets with different currencies (conversion transfer)
note

This capability is only available as part of the Virtual Account use cases and cannot be used separately.

Same-asset transfer

For transfers where the originator and beneficiary wallets hold the same currency, omit the conversion object.

Create a transfer by sending the POST /payment/v3/transfers request:

{
"reference": "treasury-789",
"originator": {
"amount": 100.00,
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:1"
},
"beneficiary": {
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:2"
},
"metadata": {
"memberId": "987654321"
}
}

The transfer completes immediately. You receive a response with status COMPLETED:

{
"id": "d4a904e0-b040-4132-a6d3-ed7d03cdfce7",
"reference": "treasury-789",
"type": "payment:transfer",
"status": "COMPLETED",
"metadata": {
"memberId": "987654321"
},
"fees": {
"processingFee": {
"amount": 0,
"currency": "USD"
}
},
"originator": {
"amount": 100.00,
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:1",
"entity": {
"legalName": "Acme Corp",
"type": "COMPANY"
}
},
"beneficiary": {
"amount": 100.00,
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:2",
"entity": {
"legalName": "Globex Trading",
"type": "COMPANY"
}
},
"expiresAt": "2025-07-31T10:00:00Z",
"createdAt": "2025-07-30T10:00:00Z",
"updatedAt": "2025-07-30T10:00:00Z",
"trackingDetails": [],
"method": "BOOK"
}

Conversion transfer with quote

Use conversion type QUOTE when you want to present a firm rate to your customer for acceptance before the transfer settles.

Create the transfer

Send the POST /payment/v3/transfers request with the conversion object:

{
"reference": "treasury-123",
"originator": {
"amount": 10.5,
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:1"
},
"beneficiary": {
"currency": "EUR",
"walletId": "a:25072267284363:kd3mRMO:2"
},
"conversion": {
"type": "QUOTE",
"validityDuration": "PT20S"
},
"metadata": {}
}

The validityDuration field accepts PT20S (20 seconds) or PT60M (60 minutes).

The transfer is created in PENDING_QUOTE_ACCEPTANCE status with the quoted rate:

{
"id": "d4a904e0-b040-4132-a6d3-ed7d03cdfce7",
"reference": "treasury-123",
"type": "payment:transfer",
"status": "PENDING_QUOTE_ACCEPTANCE",
"metadata": {},
"fees": {
"processingFee": {
"amount": 0.1,
"currency": "USD"
}
},
"originator": {
"amount": 10.5,
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:1",
"entity": {
"legalName": "Acme Corp",
"type": "COMPANY"
}
},
"beneficiary": {
"amount": 9.52,
"currency": "EUR",
"walletId": "a:25072267284363:kd3mRMO:2",
"entity": {
"legalName": "Globex Trading",
"type": "COMPANY"
}
},
"conversion": {
"type": "QUOTE",
"spread": {
"percentage": 0.01,
"amount": 0.105,
"currency": "USD"
},
"allInRate": 0.9066,
"baseRate": 0.8976,
"validityDuration": "PT20S",
"expiresAt": "2025-07-30T10:30:20Z",
"digest": "a1b2c3d4e5f6"
},
"expiresAt": "2025-07-31T10:00:00Z",
"createdAt": "2025-07-30T10:00:00Z",
"updatedAt": "2025-07-30T10:00:00Z",
"trackingDetails": [],
"method": "BOOK"
}

Accept the quote

Before the quote expires, accept it by sending the POST /payment/v3/transfers/{transferId}/actions request with the digest value from the response:

{
"type": "ACCEPT_QUOTE",
"digest": "a1b2c3d4e5f6"
}

After acceptance, the transfer moves to PROCESSING and settles the beneficiary amount without trading the originator's funds on a venue first.

Refresh an expired quote

If the quote expires before acceptance, you can refresh it:

{
"type": "REFRESH_QUOTE"
}

This returns the transfer with a new quote, updated expiresAt, and a new digest value.

info

All unaccepted quote transfers expire 24 hours after creation (the transfer's expiresAt field), regardless of individual quote expiration times.

Conversion transfer with auto conversion

Use conversion type AUTO_CONVERSION when you want the transfer to execute automatically at the market rate without requiring quote acceptance.

Send the POST /payment/v3/transfers request:

{
"reference": "treasury-456",
"originator": {
"amount": 10.5,
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:1"
},
"beneficiary": {
"currency": "EUR",
"walletId": "a:25072267284363:kd3mRMO:2"
},
"conversion": {
"type": "AUTO_CONVERSION"
},
"metadata": {}
}

The transfer moves to PROCESSING immediately. The beneficiary amount is settled after the originator's amount is traded on venue:

{
"id": "d4a904e0-b040-4132-a6d3-ed7d03cdfce7",
"reference": "treasury-456",
"type": "payment:transfer",
"status": "PROCESSING",
"metadata": {},
"fees": {
"processingFee": {
"amount": 0.1,
"currency": "USD"
}
},
"originator": {
"amount": 10.5,
"currency": "USD",
"walletId": "a:25072267284363:kd3mRMO:1",
"entity": {
"legalName": "Acme Corp",
"type": "COMPANY"
}
},
"beneficiary": {
"amount": 9.52,
"currency": "EUR",
"walletId": "a:25072267284363:kd3mRMO:2",
"entity": {
"legalName": "Globex Trading",
"type": "COMPANY"
}
},
"conversion": {
"type": "AUTO_CONVERSION",
"spread": {
"percentage": 0.01,
"amount": 0.105,
"currency": "USD"
},
"allInRate": 0.9066,
"baseRate": 0.8976
},
"expiresAt": "2025-07-31T10:00:00Z",
"createdAt": "2025-07-30T10:00:00Z",
"updatedAt": "2025-07-30T10:00:00Z",
"trackingDetails": [],
"method": "BOOK"
}
note

Only fixed debit (amount specified on the originator side) is supported for AUTO_CONVERSION transfers.

Check transfer status

To check the status of a transfer, send the GET /payment/v3/transfers/{transferId} request.

A transfer can have following statuses:

StatusDescription
PROCESSINGTransfer is being processed
PENDING_QUOTE_ACCEPTANCEAwaiting quote acceptance (QUOTE type only)
COMPLETEDTransfer completed successfully
EXPIREDTransfer expired before quote was accepted
FAILEDTransfer failed

Transfer webhook

You can listen to the transfer webhook to get notified when the status of the transfer changes. See the Transfer webhook documentation for more details.

Was this page helpful?