--- title: "Initiate on-demand internal funds transfers" description: "Send funds or initiate an internal direct debit between balance accounts within your platform." url: "https://docs.adyen.com/platforms/internal-fund-transfers/on-demand-fund-transfers" source_url: "https://docs.adyen.com/platforms/internal-fund-transfers/on-demand-fund-transfers.md" canonical: "https://docs.adyen.com/platforms/internal-fund-transfers/on-demand-fund-transfers" last_modified: "2020-09-11T17:20:00+02:00" language: "en" --- # Initiate on-demand internal funds transfers Send funds or initiate an internal direct debit between balance accounts within your platform. [View source](/platforms/internal-fund-transfers/on-demand-fund-transfers.md) In your platform, you can set up a [schedule](/platforms/internal-fund-transfers/scheduled-fund-transfers) to automatically transfer funds between balance accounts. In addition to or instead of that, you can transfer funds between balance accounts on-demand. ## Requirements Before you begin, take into account the following requirements and preparations: | Requirement | Description | | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Integration type** | You need an [Adyen for Platforms](/adyen-for-platforms-model) integration. | | **[API credentials](/platforms/manage-access/api-credentials-web-service)** | Your API credential for the [Transfers API](https://docs.adyen.com/api-explorer/transfers/latest/overview) must have the following [role](/platforms/manage-access/webservice-roles?tab=transfers_2): - **TransferService Webservice Initiate role** | | **[Customer Area roles](/account/user-roles)** | You need the following roles: - **Initiate internal transfers** - **Balance platform base role** | | **[Webhooks](/development-resources/webhooks/configure-and-manage)** | 1. Make sure that your server receives and accepts webhooks. 2. In your Customer Area, subscribe to [Transfer webhooks](/platforms/webhook-types#transfer-webhooks). | | **[Capabilities](/platforms/verification-overview/capabilities)** | If the balance accounts involved in the transfer *do not belong to the same account holder*, check the [capabilities](/platforms/verification-overview/capabilities#capabilities) of the account holders:- The account holder of the balance account that sends the the transfer request must have the **sendToBalanceAccount** capability. - The account holder of the balance account that receives the transfer request must have the **receiveFromBalanceAccount** capability. | | **Setup steps** | Before you begin your integration, contact our [Support Team](https://ca-test.adyen.com/ca/ca/contactUs/support.shtml?form=other) to enable transfers for the source balance account. | ## How it works To make an on-demand transfer, you must [initiate a transfer request](#initiate-on-demand-payout). The following diagram shows the stages of a transfer request, from initiation to sending the funds. ![](/user/pages/reuse/pfs-transfers/payouts/on-demand/how-it-works/transfer-flow.svg?decoding=auto\&fetchpriority=auto) As shown in the previous diagram, transfer requests go through the following stages: 1. **Transfer request sent**: You send a transfer request using the POST [/transfers](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers) endpoint or your [Customer Area](https://ca-test.adyen.com/). 2. **Capability check**: Adyen verifies that your user has the required capabilities. * If the capabilities are verified, Adyen receives and accepts your transfer request. * If any capabilities are missing, the transfer request fails. 3. **Approval process**: Before approving a transfer, Adyen reviews the transfer and performs internal checks. Additionally, you can trigger additional reviews for the transfer request, to make sure that the transfer is also approved by a member of your team. * If all the required reviews are completed successfully, the transfer request is approved. * If any of the required reviews fails, the transfer request also fails. 4. **Transfer request authorized**: The transfer request is instantly authorized.\ If you specified an execution date in the future, the transfer request remains pending until the execution date, and is authorized on that date. 5. **Transfer request booked**: The funds are deducted from the user's balance account and sent to the user's transfer instrument. Adyen informs you about the status of a transfer through [webhooks](#get-updates). ## Initiate an internal transfer Select the following tabs to learn how to initiate transfers between balance accounts using your Customer Area, or using an API call. ### Tab: Customer Area In your Customer Area, initiate the transfer as follows: 1. Go to **Transactions** > **Transfers**. 2. In the **Balance platform** dropdown, select the balance platform. You can view transfers from one balance platform at a time. 3. Select **Transfer funds**. 4. In the **Source balance account** field, enter the ID of the [balance account](/platforms/account-structure-resources) where the funds will be debited. 5. In the **Counterparty Type** field, select **balanceAccount**. 6. Select the **Counterparty balance account ID**. This is where the funds will be credited. 7. Select the currency and enter the amount to be transferred. 8. Optional. Enter the following information: * **Reference**: your reference for the transfer, used internally within your platform. If you do not provide this, Adyen generates a unique reference. Maximum 80 characters. * **Description**: a description of the transfer that is sent to the recipient of the transfer request. Supported characters: `[a-z][A-Z][0-9]/ - ? : ( ) . , ' + Space`. We recommend a maximum of 140 characters. * **Reference for beneficiary**: a reference that is sent to the recipient of the transfer request. It is also sent in all the webhooks related to the transfer. Supported characters: `[a-z][A-Z][0-9]`. Maximum 80 characters. 9. Select **Transfer funds** > **Yes, Transfer**. The transfer request is now created. On the **Transactions** > **Transfers** tab you can confirm if the transfer has been booked. ** ### Example fund transfer between balance accounts You want to send EUR 150 from your liable balance account to the balance account of your user. The following table shows the details you need to enter to initiate the transfer: | Field | Details | | ---------------------------------------- | ----------------------------------------------------------- | | **Source balance account** | **BA00000000000000000000001** (your liable balance account) | | **Counterparty Type** | **balanceAccount** | | **Counterparty balance account ID** | **BA00000000000000000000002** (your user's balance account) | | **Amount** | **EUR** **150** | | **Reference (optional)** | Your internal reference for the transfer | | **Description (optional)** | Your description of the transfer | | **Reference for beneficiary (optional)** | Your reference for the recipient of the transfer request | ### Tab: API 1. To move funds between balance accounts, make a POST [/transfers](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers) request. In the body of the request, specify the following fields: | Parameter | Required | Description | | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | [amount](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-amount) | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | An object containing the currency and value of the transfer. | | [balanceAccountId](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-balanceAccountId) | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The unique identifier of the source balance account: the balance account that initiates the transfer request. | | [counterparty.balanceAccountId](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-counterparty-balanceAccountId) | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The unique identifier of the target balance account: the balance account that receives the transfer. The funds are credited to this balance account. | | [category](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-category) | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | Set to **internal**. | | [description](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-description) | | Your description of the transfer. You can use this to identify the transfer in the webhooks that you receive. | | [reference](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-reference) | | Your unique reference for the transfer. You can use this to identify the transfer in the webhooks that you receive. | | [referenceForBeneficiary](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-referenceForBeneficiary) | | Text to inform the recipient about the push or pull transfer. This reference is also included in all webhooks. Supported characters: a-z, A-Z, 0-9. | The following example shows how to push **EUR 100.00** from your liable balance account to your user's balance account. **Push funds to another balance account** #### curl ```bash curl https://balanceplatform-api-test.adyen.com/btl/v4/transfers \ -H 'x-api-key: ADYEN_BALANCE_PLATFORM_API_KEY' \ -H 'content-type: application/json' \ -X POST \ -d '{ "amount": { "currency": "EUR", "value": 10000 }, "balanceAccountId": "BA00000000000000000000001", "counterparty": { "balanceAccountId": "BA00000000000000000000002" }, "category" : "internal", "referenceForBeneficiary": "Your-reference-sent-to-the-counterparty", "description": "YOUR_DESCRIPTION_OF_THE_TRANSFER", "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER" }' ``` #### Java ```java // Adyen Java API Library v33.0.0 import com.adyen.Client; import com.adyen.enums.Environment; import com.adyen.model.transfers.*; import java.time.OffsetDateTime; import java.util.*; import com.adyen.model.RequestOptions; import com.adyen.service.transfers.*; Client client = new Client("ADYEN_BALANCE_PLATFORM_API_KEY", Environment.TEST); // Create the request object(s) Amount amount = new Amount() .currency("EUR") .value(10000L); CounterpartyInfoV3 counterpartyInfoV3 = new CounterpartyInfoV3() .balanceAccountId("BA00000000000000000000002"); TransferInfo transferInfo = new TransferInfo() .balanceAccountId("BA00000000000000000000001") .reference("YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER") .amount(amount) .referenceForBeneficiary("Your-reference-sent-to-the-counterparty") .counterparty(counterpartyInfoV3) .description("YOUR_DESCRIPTION_OF_THE_TRANSFER") .category(TransferInfo.CategoryEnum.INTERNAL); // Send the request TransfersApi service = new TransfersApi(client); Transfer response = service.transferFunds(transferInfo, new RequestOptions().idempotencyKey("UUID")); ``` #### PHP ```php setXApiKey("ADYEN_BALANCE_PLATFORM_API_KEY"); $client->setEnvironment(Environment::TEST); // Create the request object(s) $amount = new Amount(); $amount ->setCurrency("EUR") ->setValue(10000); $counterpartyInfoV3 = new CounterpartyInfoV3(); $counterpartyInfoV3 ->setBalanceAccountId("BA00000000000000000000002"); $transferInfo = new TransferInfo(); $transferInfo ->setBalanceAccountId("BA00000000000000000000001") ->setReference("YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER") ->setAmount($amount) ->setReferenceForBeneficiary("Your-reference-sent-to-the-counterparty") ->setCounterparty($counterpartyInfoV3) ->setDescription("YOUR_DESCRIPTION_OF_THE_TRANSFER") ->setCategory("internal"); $requestOptions['idempotencyKey'] = 'UUID'; // Send the request $service = new TransfersApi($client); $response = $service->transferFunds($transferInfo, $requestOptions); ``` #### C\# ```cs // Adyen .net API Library v28.0.0 using Adyen; using Environment = Adyen.Model.Environment; using Adyen.Model; using Adyen.Model.Transfers; using Adyen.Service.Transfers; var config = new Config() { XApiKey = "ADYEN_BALANCE_PLATFORM_API_KEY", Environment = Environment.Test }; var client = new Client(config); // Create the request object(s) Amount amount = new Amount { Currency = "EUR", Value = 10000 }; CounterpartyInfoV3 counterpartyInfoV3 = new CounterpartyInfoV3 { BalanceAccountId = "BA00000000000000000000002" }; TransferInfo transferInfo = new TransferInfo { BalanceAccountId = "BA00000000000000000000001", Reference = "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER", Amount = amount, ReferenceForBeneficiary = "Your-reference-sent-to-the-counterparty", Counterparty = counterpartyInfoV3, Description = "YOUR_DESCRIPTION_OF_THE_TRANSFER", Category = TransferInfo.CategoryEnum.Internal }; // Send the request var service = new TransfersService(client); var response = service.TransferFunds(transferInfo, requestOptions: new RequestOptions { IdempotencyKey = "UUID"}); ``` #### NodeJS (JavaScript) ```js // Adyen Node API Library v23.3.0 const { Client, TransfersAPI } = require('@adyen/api-library'); const client = new Client({ apiKey: "ADYEN_BALANCE_PLATFORM_API_KEY", environment: "TEST" }); // Create the request object(s) const transferInfo = { amount: { currency: "EUR", value: 10000 }, balanceAccountId: "BA00000000000000000000001", counterparty: { balanceAccountId: "BA00000000000000000000002" }, category: "internal", referenceForBeneficiary: "Your-reference-sent-to-the-counterparty", description: "YOUR_DESCRIPTION_OF_THE_TRANSFER", reference: "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER" } // Send the request const transfersAPI = new TransfersAPI(client); const response = transfersAPI.TransfersApi.transferFunds(transferInfo, { idempotencyKey: "UUID" }); ``` #### Go ```go // Adyen Go API Library v17.0.0 import ( "context" "github.com/adyen/adyen-go-api-library/v17/src/common" "github.com/adyen/adyen-go-api-library/v17/src/adyen" "github.com/adyen/adyen-go-api-library/v17/src/transfers" ) client := adyen.NewClient(&common.Config{ ApiKey: "ADYEN_BALANCE_PLATFORM_API_KEY", Environment: common.TestEnv, }) // Create the request object(s) amount := transfers.Amount{ Currency: "EUR", Value: 10000, } counterpartyInfoV3 := transfers.CounterpartyInfoV3{ BalanceAccountId: common.PtrString("BA00000000000000000000002"), } transferInfo := transfers.TransferInfo{ BalanceAccountId: common.PtrString("BA00000000000000000000001"), Reference: common.PtrString("YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER"), Amount: amount, ReferenceForBeneficiary: common.PtrString("Your-reference-sent-to-the-counterparty"), Counterparty: counterpartyInfoV3, Description: common.PtrString("YOUR_DESCRIPTION_OF_THE_TRANSFER"), Category: "internal", } // Send the request service := client.Transfers() req := service.TransfersApi.TransferFundsInput().IdempotencyKey("UUID").TransferInfo(transferInfo) res, httpRes, err := service.TransfersApi.TransferFunds(context.Background(), req) ``` #### Python ```py # Adyen Python API Library v13.3.0 import Adyen adyen = Adyen.Adyen() adyen.client.xapikey = "ADYEN_BALANCE_PLATFORM_API_KEY" adyen.client.platform = "test" # The environment to use library in. # Create the request object(s) json_request = { "amount": { "currency": "EUR", "value": 10000 }, "balanceAccountId": "BA00000000000000000000001", "counterparty": { "balanceAccountId": "BA00000000000000000000002" }, "category": "internal", "referenceForBeneficiary": "Your-reference-sent-to-the-counterparty", "description": "YOUR_DESCRIPTION_OF_THE_TRANSFER", "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER" } # Send the request result = adyen.transfers.transfers_api.transfer_funds(request=json_request, idempotency_key="UUID") ``` #### Ruby ```rb # Adyen Ruby API Library v10.1.1 require "adyen-ruby-api-library" adyen = Adyen::Client.new adyen.api_key = 'ADYEN_BALANCE_PLATFORM_API_KEY' adyen.env = :test # Set to "live" for live environment # Create the request object(s) request_body = { :amount => { :currency => 'EUR', :value => 10000 }, :balanceAccountId => 'BA00000000000000000000001', :counterparty => { :balanceAccountId => 'BA00000000000000000000002' }, :category => 'internal', :referenceForBeneficiary => 'Your-reference-sent-to-the-counterparty', :description => 'YOUR_DESCRIPTION_OF_THE_TRANSFER', :reference => 'YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER' } # Send the request result = adyen.transfers.transfers_api.transfer_funds(request_body, headers: { 'Idempotency-Key' => 'UUID' }) ``` #### NodeJS (TypeScript) ```ts // Adyen Node API Library v23.3.0 import { Client, TransfersAPI, Types } from "@adyen/api-library"; const client = new Client({ apiKey: "ADYEN_BALANCE_PLATFORM_API_KEY", environment: "TEST" }); // Create the request object(s) const amount: Types.transfers.Amount = { currency: "EUR", value: 10000 }; const counterpartyInfoV3: Types.transfers.CounterpartyInfoV3 = { balanceAccountId: "BA00000000000000000000002" }; const transferInfo: Types.transfers.TransferInfo = { balanceAccountId: "BA00000000000000000000001", reference: "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER", amount: amount, referenceForBeneficiary: "Your-reference-sent-to-the-counterparty", counterparty: counterpartyInfoV3, description: "YOUR_DESCRIPTION_OF_THE_TRANSFER", category: Types.transfers.TransferInfo.CategoryEnum.Internal }; // Send the request const transfersAPI = new TransfersAPI(client); const response = transfersAPI.TransfersApi.transferFunds(transferInfo, { idempotencyKey: "UUID" }); ``` 2. In the response, note the following: * `id`: the unique ID of the transfer. * `status`: the result of the transfer. * `reason`: an explanation of the status.\ For example, the reason for a **refused** status can be **notEnoughBalance**. **Response** ```json { "creationDate": "2023-08-08T13:52:08+02:00", "id": "48NJIB9TWQJ6L7U7", "accountHolder": { "description": "Your account holder description", "id": "AH00000000000000000000001", "reference": "Your account holder reference" }, "amount": { "currency": "EUR", "value": 10000 }, "balanceAccount": { "description": "Your balance account description", "id": "BA00000000000000000000001", "reference": "Your balance account reference" }, "category" : "internal", "categoryData": { "type": "internal" }, "counterparty": { "balanceAccountId": "BA00000000000000000000002" }, "description": "YOUR_DESCRIPTION_OF_THE_TRANSFER", "direction": "outgoing", "reason": "pending", "reference": "YOUR_UNIQUE_REFERENCE_FOR_THE_TRANSFER", "referenceForBeneficiary": "Your-reference-sent-to-the-counterparty", "status": "received", "type": "internalTransfer" } ``` ** ### Trigger additional reviews To better control money movement in your platform, you can trigger additional reviews for transfers. Additional reviews require a member of your team to verify a transfer before Adyen processes it. 1. You can trigger an additional review by including the [review](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-review) object in the POST [/transfers](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers) request. In the object, specify the following parameter: | Parameter name | Required | Description | | | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | | [review.numberOfApprovalsRequired](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-review-numberOfApprovalsRequired) | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | Specifies the number of approvals required to process the transfer. Possible values: **1**. Currently, it is possible to request only one additional review per transfer. | | The following code sample shows how to include the `review` object. **Trigger an additional review** #### curl ```bash curl https://balanceplatform-api-test.adyen.com/btl/v4/transfers \ -H 'x-api-key: YOUR_BALANCE_PLATFORM_API_KEY' \ -H 'content-type: application/json' \ -X POST \ -d '{ "amount": { "value": 60000, "currency": "EUR" }, "balanceAccountId": "BA00000000000000000000001", "category": "internal", "counterparty": { "balanceAccountId": "BA00000000000000000000002" }, "description": "Your-description-for-the-transfer", "reference": "YOUR_INTERNAL_REFERENCE", "referenceForBeneficiary": "Your-reference-for-the-beneficiary", "review": { "numberOfApprovalsRequired": 1 } }' ``` #### Java ```java // Adyen Java API Library v33.0.0 import com.adyen.Client; import com.adyen.enums.Environment; import com.adyen.model.transfers.*; import java.time.OffsetDateTime; import java.util.*; import com.adyen.model.RequestOptions; import com.adyen.service.transfers.*; Client client = new Client("YOUR_BALANCE_PLATFORM_API_KEY", Environment.TEST); // Create the request object(s) Amount amount = new Amount() .currency("EUR") .value(60000L); TransferRequestReview transferRequestReview = new TransferRequestReview() .numberOfApprovalsRequired(1); CounterpartyInfoV3 counterpartyInfoV3 = new CounterpartyInfoV3() .balanceAccountId("BA00000000000000000000002"); TransferInfo transferInfo = new TransferInfo() .balanceAccountId("BA00000000000000000000001") .reference("YOUR_INTERNAL_REFERENCE") .amount(amount) .referenceForBeneficiary("Your-reference-for-the-beneficiary") .review(transferRequestReview) .counterparty(counterpartyInfoV3) .description("Your-description-for-the-transfer") .category(TransferInfo.CategoryEnum.INTERNAL); // Send the request TransfersApi service = new TransfersApi(client); Transfer response = service.transferFunds(transferInfo, new RequestOptions().idempotencyKey("UUID")); ``` #### PHP ```php setXApiKey("YOUR_BALANCE_PLATFORM_API_KEY"); $client->setEnvironment(Environment::TEST); // Create the request object(s) $amount = new Amount(); $amount ->setCurrency("EUR") ->setValue(60000); $transferRequestReview = new TransferRequestReview(); $transferRequestReview ->setNumberOfApprovalsRequired(1); $counterpartyInfoV3 = new CounterpartyInfoV3(); $counterpartyInfoV3 ->setBalanceAccountId("BA00000000000000000000002"); $transferInfo = new TransferInfo(); $transferInfo ->setBalanceAccountId("BA00000000000000000000001") ->setReference("YOUR_INTERNAL_REFERENCE") ->setAmount($amount) ->setReferenceForBeneficiary("Your-reference-for-the-beneficiary") ->setReview($transferRequestReview) ->setCounterparty($counterpartyInfoV3) ->setDescription("Your-description-for-the-transfer") ->setCategory("internal"); $requestOptions['idempotencyKey'] = 'UUID'; // Send the request $service = new TransfersApi($client); $response = $service->transferFunds($transferInfo, $requestOptions); ``` #### C\# ```cs // Adyen .net API Library v28.0.0 using Adyen; using Environment = Adyen.Model.Environment; using Adyen.Model; using Adyen.Model.Transfers; using Adyen.Service.Transfers; var config = new Config() { XApiKey = "YOUR_BALANCE_PLATFORM_API_KEY", Environment = Environment.Test }; var client = new Client(config); // Create the request object(s) Amount amount = new Amount { Currency = "EUR", Value = 60000 }; TransferRequestReview transferRequestReview = new TransferRequestReview { NumberOfApprovalsRequired = 1 }; CounterpartyInfoV3 counterpartyInfoV3 = new CounterpartyInfoV3 { BalanceAccountId = "BA00000000000000000000002" }; TransferInfo transferInfo = new TransferInfo { BalanceAccountId = "BA00000000000000000000001", Reference = "YOUR_INTERNAL_REFERENCE", Amount = amount, ReferenceForBeneficiary = "Your-reference-for-the-beneficiary", Review = transferRequestReview, Counterparty = counterpartyInfoV3, Description = "Your-description-for-the-transfer", Category = TransferInfo.CategoryEnum.Internal }; // Send the request var service = new TransfersService(client); var response = service.TransferFunds(transferInfo, requestOptions: new RequestOptions { IdempotencyKey = "UUID"}); ``` #### NodeJS (JavaScript) ```js // Adyen Node API Library v23.3.0 const { Client, TransfersAPI } = require('@adyen/api-library'); const client = new Client({ apiKey: "YOUR_BALANCE_PLATFORM_API_KEY", environment: "TEST" }); // Create the request object(s) const transferInfo = { amount: { value: 60000, currency: "EUR" }, balanceAccountId: "BA00000000000000000000001", category: "internal", counterparty: { balanceAccountId: "BA00000000000000000000002" }, description: "Your-description-for-the-transfer", reference: "YOUR_INTERNAL_REFERENCE", referenceForBeneficiary: "Your-reference-for-the-beneficiary", review: { numberOfApprovalsRequired: 1 } } // Send the request const transfersAPI = new TransfersAPI(client); const response = transfersAPI.TransfersApi.transferFunds(transferInfo, { idempotencyKey: "UUID" }); ``` #### Go ```go // Adyen Go API Library v17.0.0 import ( "context" "github.com/adyen/adyen-go-api-library/v17/src/common" "github.com/adyen/adyen-go-api-library/v17/src/adyen" "github.com/adyen/adyen-go-api-library/v17/src/transfers" ) client := adyen.NewClient(&common.Config{ ApiKey: "YOUR_BALANCE_PLATFORM_API_KEY", Environment: common.TestEnv, }) // Create the request object(s) amount := transfers.Amount{ Currency: "EUR", Value: 60000, } transferRequestReview := transfers.TransferRequestReview{ NumberOfApprovalsRequired: common.PtrInt32(1), } counterpartyInfoV3 := transfers.CounterpartyInfoV3{ BalanceAccountId: common.PtrString("BA00000000000000000000002"), } transferInfo := transfers.TransferInfo{ BalanceAccountId: common.PtrString("BA00000000000000000000001"), Reference: common.PtrString("YOUR_INTERNAL_REFERENCE"), Amount: amount, ReferenceForBeneficiary: common.PtrString("Your-reference-for-the-beneficiary"), Review: &transferRequestReview, Counterparty: counterpartyInfoV3, Description: common.PtrString("Your-description-for-the-transfer"), Category: "internal", } // Send the request service := client.Transfers() req := service.TransfersApi.TransferFundsInput().IdempotencyKey("UUID").TransferInfo(transferInfo) res, httpRes, err := service.TransfersApi.TransferFunds(context.Background(), req) ``` #### Python ```py # Adyen Python API Library v13.3.0 import Adyen adyen = Adyen.Adyen() adyen.client.xapikey = "YOUR_BALANCE_PLATFORM_API_KEY" adyen.client.platform = "test" # The environment to use library in. # Create the request object(s) json_request = { "amount": { "value": 60000, "currency": "EUR" }, "balanceAccountId": "BA00000000000000000000001", "category": "internal", "counterparty": { "balanceAccountId": "BA00000000000000000000002" }, "description": "Your-description-for-the-transfer", "reference": "YOUR_INTERNAL_REFERENCE", "referenceForBeneficiary": "Your-reference-for-the-beneficiary", "review": { "numberOfApprovalsRequired": 1 } } # Send the request result = adyen.transfers.transfers_api.transfer_funds(request=json_request, idempotency_key="UUID") ``` #### Ruby ```rb # Adyen Ruby API Library v10.1.1 require "adyen-ruby-api-library" adyen = Adyen::Client.new adyen.api_key = 'YOUR_BALANCE_PLATFORM_API_KEY' adyen.env = :test # Set to "live" for live environment # Create the request object(s) request_body = { :amount => { :value => 60000, :currency => 'EUR' }, :balanceAccountId => 'BA00000000000000000000001', :category => 'internal', :counterparty => { :balanceAccountId => 'BA00000000000000000000002' }, :description => 'Your-description-for-the-transfer', :reference => 'YOUR_INTERNAL_REFERENCE', :referenceForBeneficiary => 'Your-reference-for-the-beneficiary', :review => { :numberOfApprovalsRequired => 1 } } # Send the request result = adyen.transfers.transfers_api.transfer_funds(request_body, headers: { 'Idempotency-Key' => 'UUID' }) ``` #### NodeJS (TypeScript) ```ts // Adyen Node API Library v23.3.0 import { Client, TransfersAPI, Types } from "@adyen/api-library"; const client = new Client({ apiKey: "YOUR_BALANCE_PLATFORM_API_KEY", environment: "TEST" }); // Create the request object(s) const amount: Types.transfers.Amount = { currency: "EUR", value: 60000 }; const transferRequestReview: Types.transfers.TransferRequestReview = { numberOfApprovalsRequired: 1 }; const counterpartyInfoV3: Types.transfers.CounterpartyInfoV3 = { balanceAccountId: "BA00000000000000000000002" }; const transferInfo: Types.transfers.TransferInfo = { balanceAccountId: "BA00000000000000000000001", reference: "YOUR_INTERNAL_REFERENCE", amount: amount, referenceForBeneficiary: "Your-reference-for-the-beneficiary", review: transferRequestReview, counterparty: counterpartyInfoV3, description: "Your-description-for-the-transfer", category: Types.transfers.TransferInfo.CategoryEnum.Internal }; // Send the request const transfersAPI = new TransfersAPI(client); const response = transfersAPI.TransfersApi.transferFunds(transferInfo, { idempotencyKey: "UUID" }); ``` 2. If the transfer request is successful, you receive an **HTTP 2XX** response containing transfer details, including the following parameters: | Parameter name | Description | | ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | | [review.numberOfApprovalsRequired](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#responses-202-review-numberOfApprovalsRequired) | Shows the number of approvals required to process the transfer. | After triggering the review, a member of your team must [approve](/platforms/internal-fund-transfers/approve-cancel-transfers) the transfer before Adyen continues processing it. ** ### Process a transfer in a future date 1. When you make a transfer request, you can specify a future date when you want Adyen to process the transfer. You can do this by including the [executionDate](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-executionDate) object in the POST [/transfers](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers) request. If your transfer request is successful, the transfer remains in `status` **received** with `reason` **pending** until the execution date. On the execution date, between 00:00 and 03:00 - based on the time zone configured on the Balance Platform by default - Adyen verifies that: * The source balance account has enough funds. * The transfer was approved by a member of your team, if you triggered an additional review. If all previous conditions are satisfied, Adyen processes the transfer request. Adyen attempts to process the transfer only one time. In case of any errors, such as having insufficient funds in the balance account, the transfer request ends with `status` **failed**. If this happens, Adyen sends a [webhook](#get-status-updates) with details about the failure. To specify a future execution date, specify the following parameters: | Parameter name | Required | Description | | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [executionDate.date](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-executionDate-date) | ![-white\_check\_mark-](/user/data/smileys/emoji/white_check_mark.png "-white_check_mark-") | The date when the transfer will be processed. This date must:- Be within 30 days of the current date. - Be in the [ISO 8601 format](https://www.iso.org/iso-8601-date-and-time-format.html) **YYYY-MM-DD**. For example: 2025-01-31. | | [executionDate.timezone](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-executionDate-timezone) | | The timezone that applies to the execution date. Use a timezone identifier from the [tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). For example: **America/Los\_Angeles**. Default value: **Europe/Amsterdam**. | The following code sample shows how to include the [executionDate](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#request-executionDate) object in a transfer request. **Specify an execution date in the future** ```bash curl https://balanceplatform-api-test.adyen.com/btl/v4/transfers \ -H 'x-api-key: YOUR_BALANCE_PLATFORM_API_KEY' \ -H 'content-type: application/json' \ -X POST \ -d '{ "amount": { "value": 80000, "currency": "EUR" }, "balanceAccountId": "BA00000000000000000000001", "category": "internal", "counterparty": { "balanceAccountId": "BA00000000000000000000002" }, "executionDate": { "date": "2025-04-18", "timezone": "America/Los_Angeles" }, "referenceForBeneficiary": "Your-reference-sent-to-the-beneficiary", "reference": "Your internal reference for the transfer", "description": "Your description for the transfer" }' ``` 2. If the transfer request is successful, you receive an **HTTP 2XX** response with the transfer details and the [executionDate](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers#responses-200-executionDate) object. 3. Before the execution date, you can [cancel the transfer](/platforms/internal-fund-transfers/approve-cancel-transfers) by making a POST [/transfers/cancel](https://docs.adyen.com/api-explorer/transfers/latest/post/transfers/cancel) request. ## Troubleshooting If an internal fund transfer fails, verify if there are enough funds in the source balance account: 1. Make a GET [/balanceAccounts/{id}](https://docs.adyen.com/api-explorer/balanceplatform/latest/get/balanceAccounts/\(id\)) request, specifying the source balance account's ID in the path. 2. Check the [available](https://docs.adyen.com/api-explorer/balanceplatform/latest/get/balanceAccounts/\(id\)#responses-200-balances-available) balance. 3. If the amount is lower than the transfer amount, you can: * Ask your user to [top up](/platforms/top-up-balance-account) their balance account. * Make an internal transfer from your liable balance account to your user's balance account. If there are enough funds in the balance account, but the transfer still fails, contact our [Support Team](https://ca-test.adyen.com/ca/ca/contactUs/support.shtml?form=other). ## Get status updates For every internal transfer request, Adyen sends multiple [webhooks](/platforms/internal-fund-transfers/internal-transfer-webhooks) to your server: a series of webhooks for the balance account where the transfer is an outgoing request, and a series of webhooks for the balance account where the transfer is an incoming request. Using these webhooks, you can track the status of the transfer: **received**, then **authorised**, and finally **booked**. The webhooks also inform you if the transfer failed. You can also [view the transfer details in your Customer Area](/platforms/view-transfers-details). Each transfer of funds between balance accounts appears in the Customer Area as two transfer entries: one for the balance account that is credited, and one for the balance account that is debited. ## See also * [Internal funds transfer webhooks](/platforms/internal-fund-transfers/internal-transfer-webhooks/) * [View transfer details](/platforms/view-transfers-details) * [Schedule automatic internal funds transfers](/platforms/internal-fund-transfers/scheduled-fund-transfers)