Change Fee Target Account
This endpoint allows the transfer of a Cashout fee (Payout/Cashout fee) to another account within the same customer domain. This functionality is useful when fee charges need to be reallocated between internal accounts belonging to the same customer (e.g., between segregated wallets or cost centers).
Business Rules
Important Restrictions :
The target account must belong to the same customer domain as the original account
After the transfer, the fee becomes exclusively associated with the new account, but it remains linked to the originating entity of the fee
Fees related to Payin/Cashin transactions are not affected by this functionality — they will continue to be charged to the originating account (i.e., the account where the Cashin occurred)
Note : This setting only defines which wallet will be charged the merchant fee, but it does not change the operational model (prepaid or postpaid) of the merchant itself.
Prepaid Model
The destination wallet must have sufficient balance at the time of the fee charge.
Postpaid Model
The destination wallet does not need to have sufficient balance, but all fees will be consolidated and invoiced monthly by the WEpayments finance team.
About Removing This Setting
Update as of 2023-06-11 : Currently, this removal cannot be performed via API. If you need to remove this configuration, please contact our CA team to request the change. In the coming weeks, new account management endpoints will be made available to support this functionality, eliminating the need to open a support ticket with our CA team.
Path Parameters
Request Body
Provide the ID of the account that should receive the fees from the account you are updating (the account specified in the endpoint path). Important : Your “Free fee” to be charged to the destination account should be posted to the fee wallet.
Indicate “true” if the fee to be charged to the destination account should be posted to the fee wallet.
Response
Account fee configuration
Whether fee billing is enabled
Request Example
curl --request POST \
--url https://api.sandbox.wepayout.com.br/v2/account/{merchantId}/fee-target \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {token}' \
--header 'Content-Type: application/json' \
--data '{
"merchant_fee": 1234,
"fee_wallet": true
}'
200 OK
401 Unauthorized
500 Internal Server Error
{
"id" : 0 ,
"merchant_id" : 0 ,
"recipient_id" : 0 ,
"currency_id" : 0 ,
"account_fee" : {
"id" : 0 ,
"merchant_id" : 0 ,
"currency_id" : 0 ,
"use_fee_billing" : true
}
}
Use Cases
Centralize Fee Management
Route all fees to a dedicated fee management account: async function centralizeFees ( merchantId , feeAccountId ) {
const response = await fetch (
`https://api.wepayments.com/v2/account/ ${ merchantId } /fee-target` ,
{
method: 'POST' ,
headers: {
'Authorization' : 'Bearer YOUR_TOKEN' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
merchant_fee: feeAccountId ,
fee_wallet: true
})
}
);
return await response . json ();
}
// Route all fees from account 456 to central fee account 789
await centralizeFees ( 456 , 789 );
Allocate fees to specific cost centers: async function allocateFeesToCostCenter ( accounts , costCenterId ) {
const results = [];
for ( const accountId of accounts ) {
const result = await fetch (
`https://api.wepayments.com/v2/account/ ${ accountId } /fee-target` ,
{
method: 'POST' ,
headers: {
'Authorization' : 'Bearer YOUR_TOKEN' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
merchant_fee: costCenterId ,
fee_wallet: true
})
}
);
results . push ({
accountId ,
status: result . status ,
data: await result . json ()
});
}
return results ;
}
// Allocate fees from multiple accounts to cost center
const accounts = [ 101 , 102 , 103 ];
await allocateFeesToCostCenter ( accounts , 999 );
Segregated Wallet Management
Manage fees across segregated wallets: async function setupSegregatedWalletFees ( mainWalletId , feeWalletId ) {
// Configure main wallet to send fees to fee wallet
const response = await fetch (
`https://api.wepayments.com/v2/account/ ${ mainWalletId } /fee-target` ,
{
method: 'POST' ,
headers: {
'Authorization' : 'Bearer YOUR_TOKEN' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
merchant_fee: feeWalletId ,
fee_wallet: true
})
}
);
const result = await response . json ();
return {
mainWallet: mainWalletId ,
feeWallet: feeWalletId ,
configuration: result
};
}
Multi-Account Fee Routing
Set up fee routing for multiple accounts: async function setupMultiAccountFeeRouting ( feeRoutingConfig ) {
const results = [];
for ( const config of feeRoutingConfig ) {
try {
const response = await fetch (
`https://api.wepayments.com/v2/account/ ${ config . sourceAccount } /fee-target` ,
{
method: 'POST' ,
headers: {
'Authorization' : 'Bearer YOUR_TOKEN' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
merchant_fee: config . targetAccount ,
fee_wallet: config . useFeeWallet
})
}
);
results . push ({
source: config . sourceAccount ,
target: config . targetAccount ,
success: response . ok ,
data: await response . json ()
});
} catch ( error ) {
results . push ({
source: config . sourceAccount ,
target: config . targetAccount ,
success: false ,
error: error . message
});
}
}
return results ;
}
// Usage
const config = [
{ sourceAccount: 101 , targetAccount: 201 , useFeeWallet: true },
{ sourceAccount: 102 , targetAccount: 201 , useFeeWallet: true },
{ sourceAccount: 103 , targetAccount: 202 , useFeeWallet: false }
];
const results = await setupMultiAccountFeeRouting ( config );
console . log ( 'Fee routing setup:' , results );
Important Considerations
Fee Types Affected
Affected Cashout/Payout Fees
Withdrawal fees
Transfer fees
Payout processing fees
Not Affected Cashin/Payin Fees
Deposit fees
Payment processing fees
Remain on original account
Payment Models
Prepaid Model Requirements :
Destination account must have sufficient balance
Fees are deducted immediately
Transaction fails if insufficient funds
// Check balance before setting fee target
const balance = await getBalance ( targetAccountId );
if ( balance . available_balance >= expectedFees ) {
await changeFeeTarget ( sourceAccountId , targetAccountId );
}
Best Practices
Same Customer Domain : Ensure both source and target accounts belong to the same customer domain before attempting the transfer.
Fee Wallet Configuration : When using fee_wallet: true, ensure the destination account is properly configured as a fee wallet.
Audit Trail : Keep a log of all fee target changes for accounting and reconciliation purposes.
Integration Example
class FeeManagementService {
constructor ( apiKey ) {
this . apiKey = apiKey ;
this . baseUrl = 'https://api.wepayments.com/v2' ;
}
async changeFeeTarget ( merchantId , targetMerchantId , useFeeWallet = true ) {
const url = ` ${ this . baseUrl } /account/ ${ merchantId } /fee-target` ;
const response = await fetch ( url , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ this . apiKey } ` ,
'Content-Type' : 'application/json' ,
'Accept' : 'application/json'
},
body: JSON . stringify ({
merchant_fee: targetMerchantId ,
fee_wallet: useFeeWallet
})
});
if ( ! response . ok ) {
throw new Error ( `Failed to change fee target: ${ response . statusText } ` );
}
return await response . json ();
}
async setupFeeHierarchy ( accounts , centralFeeAccountId ) {
const results = [];
for ( const accountId of accounts ) {
try {
const result = await this . changeFeeTarget (
accountId ,
centralFeeAccountId ,
true
);
results . push ({
accountId ,
success: true ,
configuration: result
});
} catch ( error ) {
results . push ({
accountId ,
success: false ,
error: error . message
});
}
// Add delay to avoid rate limiting
await this . delay ( 100 );
}
return results ;
}
async validateFeeTargetSetup ( sourceAccountId , targetAccountId ) {
// Validate that both accounts exist and belong to same customer
// This is a placeholder - implement actual validation logic
return {
valid: true ,
sourceAccount: sourceAccountId ,
targetAccount: targetAccountId ,
sameDomain: true
};
}
delay ( ms ) {
return new Promise ( resolve => setTimeout ( resolve , ms ));
}
}
// Usage
const feeService = new FeeManagementService ( 'YOUR_API_KEY' );
// Change fee target for a single account
const result = await feeService . changeFeeTarget ( 123 , 456 , true );
console . log ( 'Fee target changed:' , result );
// Setup fee hierarchy for multiple accounts
const accounts = [ 101 , 102 , 103 , 104 ];
const centralFeeAccount = 999 ;
const hierarchyResults = await feeService . setupFeeHierarchy ( accounts , centralFeeAccount );
console . log ( 'Fee hierarchy setup:' , hierarchyResults );
// Validate before changing
const validation = await feeService . validateFeeTargetSetup ( 123 , 456 );
if ( validation . valid ) {
await feeService . changeFeeTarget ( 123 , 456 );
}
Error Handling
Common Errors
async function changeFeeTargetWithErrorHandling ( merchantId , targetId ) {
try {
const response = await fetch (
`https://api.wepayments.com/v2/account/ ${ merchantId } /fee-target` ,
{
method: 'POST' ,
headers: {
'Authorization' : 'Bearer YOUR_TOKEN' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
merchant_fee: targetId ,
fee_wallet: true
})
}
);
if ( response . status === 401 ) {
throw new Error ( 'Authentication failed - check your API key' );
}
if ( response . status === 403 ) {
throw new Error ( 'Accounts do not belong to the same customer domain' );
}
if ( response . status === 404 ) {
throw new Error ( 'Source or target account not found' );
}
if ( ! response . ok ) {
throw new Error ( `Request failed with status ${ response . status } ` );
}
return await response . json ();
} catch ( error ) {
console . error ( 'Error changing fee target:' , error );
throw error ;
}
}