Skip to main content

Overview

Payouts allow you to transfer funds from a user’s Mangopay wallet to their bank account. Before processing a payout:
  1. The user must have a verified bank account
  2. The wallet must have sufficient funds
  3. The user must pass KYC verification (for amounts above thresholds)

Creating a Bank Wire Payout

1

Ensure Prerequisites

Verify the user has a bank account and sufficient funds:
// Check wallet balance
$wallet = $api->Wallets->Get($walletId);
$availableBalance = $wallet->Balance->Amount;

// Get user's bank account
$bankAccounts = $api->Users->GetBankAccounts($userId);
if (empty($bankAccounts)) {
    throw new Exception('User has no bank account');
}
$bankAccountId = $bankAccounts[0]->Id;
2

Create the Payout

Create a payout object:
$payout = new MangoPay\PayOut();
$payout->AuthorId = $userId;
$payout->DebitedWalletId = $walletId;
$payout->DebitedFunds = new MangoPay\Money();
$payout->DebitedFunds->Currency = 'EUR';
$payout->DebitedFunds->Amount = 5000; // 50.00 EUR
$payout->Fees = new MangoPay\Money();
$payout->Fees->Currency = 'EUR';
$payout->Fees->Amount = 0; // No fees

// Bank wire details
$payout->MeanOfPaymentDetails = new MangoPay\PayOutPaymentDetailsBankWire();
$payout->MeanOfPaymentDetails->BankAccountId = $bankAccountId;
$payout->MeanOfPaymentDetails->BankWireRef = 'Invoice #12345';
3

Submit to API

Process the payout:
try {
    $createdPayout = $api->PayOuts->Create($payout);
    
    if ($createdPayout->Status === 'SUCCEEDED') {
        echo "Payout successful!";
    } elseif ($createdPayout->Status === 'CREATED') {
        echo "Payout is being processed";
    } elseif ($createdPayout->Status === 'FAILED') {
        echo "Payout failed: " . $createdPayout->ResultMessage;
    }
} catch (MangoPay\Libraries\ResponseException $e) {
    echo "Error: " . $e->GetMessage();
}

Complete Payout Example

function processPayout($api, $userId, $walletId, $amount, $currency = 'EUR') {
    try {
        // Get bank account
        $bankAccounts = $api->Users->GetBankAccounts($userId);
        if (empty($bankAccounts)) {
            throw new Exception('No bank account found for user');
        }
        
        // Get first active bank account
        $bankAccount = null;
        foreach ($bankAccounts as $account) {
            if ($account->Active) {
                $bankAccount = $account;
                break;
            }
        }
        
        if (!$bankAccount) {
            throw new Exception('No active bank account found');
        }
        
        // Check wallet balance
        $wallet = $api->Wallets->Get($walletId);
        if ($wallet->Balance->Amount < $amount) {
            throw new Exception('Insufficient funds in wallet');
        }
        
        // Create payout
        $payout = new MangoPay\PayOut();
        $payout->AuthorId = $userId;
        $payout->DebitedWalletId = $walletId;
        $payout->DebitedFunds = new MangoPay\Money();
        $payout->DebitedFunds->Currency = $currency;
        $payout->DebitedFunds->Amount = $amount;
        $payout->Fees = new MangoPay\Money();
        $payout->Fees->Currency = $currency;
        $payout->Fees->Amount = 0;
        
        $payout->MeanOfPaymentDetails = new MangoPay\PayOutPaymentDetailsBankWire();
        $payout->MeanOfPaymentDetails->BankAccountId = $bankAccount->Id;
        
        // Create with idempotency
        $idempotencyKey = 'payout_' . $userId . '_' . time();
        $createdPayout = $api->PayOuts->Create($payout, $idempotencyKey);
        
        return $createdPayout;
    } catch (MangoPay\Libraries\ResponseException $e) {
        error_log("Payout failed: " . $e->GetMessage());
        throw $e;
    }
}

// Usage
try {
    $payout = processPayout($api, $userId, $walletId, 10000); // 100.00 EUR
    echo "Payout ID: " . $payout->Id;
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

Instant Payouts

Check if a bank account is eligible for instant payout:
$eligibilityRequest = new MangoPay\PayOutEligibilityRequest();
$eligibilityRequest->AuthorId = $userId;
$eligibilityRequest->DebitedFunds = new MangoPay\Money();
$eligibilityRequest->DebitedFunds->Currency = 'EUR';
$eligibilityRequest->DebitedFunds->Amount = 10000;
$eligibilityRequest->Fees = new MangoPay\Money();
$eligibilityRequest->Fees->Currency = 'EUR';
$eligibilityRequest->Fees->Amount = 0;
$eligibilityRequest->DebitedWalletId = $walletId;
$eligibilityRequest->PayoutModeRequested = 'INSTANT_PAYMENT';

// Bank wire details
$eligibilityRequest->MeanOfPaymentDetails = new MangoPay\PayOutPaymentDetailsBankWire();
$eligibilityRequest->MeanOfPaymentDetails->BankAccountId = $bankAccountId;

try {
    $eligibility = $api->PayOuts->CheckInstantPayoutEligibility($eligibilityRequest);
    
    if ($eligibility->InstantPayout->IsReachable) {
        echo "Instant payout is available";
        
        // Create instant payout
        $payout = new MangoPay\PayOut();
        $payout->AuthorId = $userId;
        $payout->DebitedWalletId = $walletId;
        $payout->DebitedFunds = new MangoPay\Money();
        $payout->DebitedFunds->Currency = 'EUR';
        $payout->DebitedFunds->Amount = 10000;
        $payout->Fees = new MangoPay\Money();
        $payout->Fees->Currency = 'EUR';
        $payout->Fees->Amount = 0;
        $payout->PayoutModeRequested = 'INSTANT_PAYMENT';
        
        $payout->MeanOfPaymentDetails = new MangoPay\PayOutPaymentDetailsBankWire();
        $payout->MeanOfPaymentDetails->BankAccountId = $bankAccountId;
        
        $instantPayout = $api->PayOuts->Create($payout);
    } else {
        echo "Instant payout not available. Reason: " . 
             $eligibility->InstantPayout->ReasonMessage;
    }
} catch (MangoPay\Libraries\ResponseException $e) {
    echo "Error: " . $e->GetMessage();
}

Retrieving Payouts

Get a Specific Payout

try {
    $payout = $api->PayOuts->Get($payoutId);
    
    echo "Status: " . $payout->Status . "\n";
    echo "Amount: " . ($payout->DebitedFunds->Amount / 100) . "\n";
    echo "Currency: " . $payout->DebitedFunds->Currency . "\n";
    echo "Bank Account: " . $payout->MeanOfPaymentDetails->BankAccountId;
} catch (MangoPay\Libraries\ResponseException $e) {
    echo "Error: " . $e->GetMessage();
}

Get Payout with Bank Wire Details

$payout = $api->PayOuts->GetBankwire($payoutId);

echo "Bank wire reference: " . $payout->MeanOfPaymentDetails->BankWireRef;

Payout Statuses

Payouts can have the following statuses:
  • CREATED: Payout has been created and is pending processing
  • SUCCEEDED: Funds have been successfully transferred
  • FAILED: Payout failed (check ResultMessage for details)
$payout = $api->PayOuts->Get($payoutId);

switch ($payout->Status) {
    case 'CREATED':
        echo "Payout is being processed";
        break;
    case 'SUCCEEDED':
        echo "Payout completed successfully";
        break;
    case 'FAILED':
        echo "Payout failed: " . $payout->ResultMessage;
        echo "\nResult code: " . $payout->ResultCode;
        break;
}

Payout Fees

You can charge fees on payouts:
$payout = new MangoPay\PayOut();
$payout->AuthorId = $userId;
$payout->DebitedWalletId = $walletId;
$payout->DebitedFunds = new MangoPay\Money();
$payout->DebitedFunds->Currency = 'EUR';
$payout->DebitedFunds->Amount = 10000; // 100.00 EUR

// Add a fee (deducted from the payout amount)
$payout->Fees = new MangoPay\Money();
$payout->Fees->Currency = 'EUR';
$payout->Fees->Amount = 200; // 2.00 EUR fee

$payout->MeanOfPaymentDetails = new MangoPay\PayOutPaymentDetailsBankWire();
$payout->MeanOfPaymentDetails->BankAccountId = $bankAccountId;

$createdPayout = $api->PayOuts->Create($payout);

// User receives: 98.00 EUR (100.00 - 2.00 fee)
// Your platform receives: 2.00 EUR fee

Refunding Payouts

Get refunds for a payout:
$pagination = new MangoPay\Pagination(1, 20);

try {
    $refunds = $api->PayOuts->GetRefunds($payoutId, $pagination);
    
    foreach ($refunds as $refund) {
        echo "Refund ID: " . $refund->Id . "\n";
        echo "Amount: " . ($refund->DebitedFunds->Amount / 100) . "\n";
        echo "Status: " . $refund->Status . "\n\n";
    }
} catch (MangoPay\Libraries\ResponseException $e) {
    echo "Error: " . $e->GetMessage();
}

Using Idempotency

Prevent duplicate payouts with idempotency keys:
$idempotencyKey = 'payout_' . $userId . '_' . $orderId;

$payout = new MangoPay\PayOut();
$payout->AuthorId = $userId;
$payout->DebitedWalletId = $walletId;
$payout->DebitedFunds = new MangoPay\Money();
$payout->DebitedFunds->Currency = 'EUR';
$payout->DebitedFunds->Amount = 10000;
$payout->Fees = new MangoPay\Money();
$payout->Fees->Currency = 'EUR';
$payout->Fees->Amount = 0;

$payout->MeanOfPaymentDetails = new MangoPay\PayOutPaymentDetailsBankWire();
$payout->MeanOfPaymentDetails->BankAccountId = $bankAccountId;

try {
    // First call
    $createdPayout = $api->PayOuts->Create($payout, $idempotencyKey);
    
    // Retry with same key returns the same payout
    $samePayout = $api->PayOuts->Create($payout, $idempotencyKey);
    
    assert($createdPayout->Id === $samePayout->Id);
} catch (MangoPay\Libraries\ResponseException $e) {
    echo "Error: " . $e->GetMessage();
}

Batch Payouts

Process multiple payouts:
function processBatchPayouts($api, $payoutRequests) {
    $results = [];
    
    foreach ($payoutRequests as $request) {
        try {
            $payout = new MangoPay\PayOut();
            $payout->AuthorId = $request['userId'];
            $payout->DebitedWalletId = $request['walletId'];
            $payout->DebitedFunds = new MangoPay\Money();
            $payout->DebitedFunds->Currency = $request['currency'];
            $payout->DebitedFunds->Amount = $request['amount'];
            $payout->Fees = new MangoPay\Money();
            $payout->Fees->Currency = $request['currency'];
            $payout->Fees->Amount = 0;
            
            $payout->MeanOfPaymentDetails = new MangoPay\PayOutPaymentDetailsBankWire();
            $payout->MeanOfPaymentDetails->BankAccountId = $request['bankAccountId'];
            
            $idempotencyKey = 'payout_' . $request['userId'] . '_' . time();
            $createdPayout = $api->PayOuts->Create($payout, $idempotencyKey);
            
            $results[] = [
                'success' => true,
                'payoutId' => $createdPayout->Id,
                'userId' => $request['userId']
            ];
        } catch (MangoPay\Libraries\ResponseException $e) {
            $results[] = [
                'success' => false,
                'error' => $e->GetMessage(),
                'userId' => $request['userId']
            ];
        }
    }
    
    return $results;
}

// Usage
$payoutRequests = [
    [
        'userId' => 'user_123',
        'walletId' => 'wallet_456',
        'bankAccountId' => 'bank_789',
        'amount' => 10000,
        'currency' => 'EUR'
    ],
    [
        'userId' => 'user_234',
        'walletId' => 'wallet_567',
        'bankAccountId' => 'bank_890',
        'amount' => 15000,
        'currency' => 'EUR'
    ]
];

$results = processBatchPayouts($api, $payoutRequests);

Common Payout Errors

Handle common errors:
try {
    $payout = $api->PayOuts->Create($newPayout);
} catch (MangoPay\Libraries\ResponseException $e) {
    $errorDetails = $e->GetErrorDetails();
    
    foreach ($errorDetails as $error) {
        switch ($error->Message) {
            case 'Insufficient wallet balance':
                echo "Not enough funds in wallet";
                break;
            case 'The bank account is not active':
                echo "Bank account is not active";
                break;
            case 'Author is not KYC verified':
                echo "User needs KYC verification";
                break;
            default:
                echo "Error: " . $error->Message;
        }
    }
}

Best Practices

Verify Balance First

Always check wallet balance before creating payouts.

Use Idempotency Keys

Prevent duplicate payouts with idempotency keys.

Monitor Status

Use webhooks to track payout status changes.

Handle Failures

Implement retry logic for failed payouts.

Security Considerations

Ensure only authorized users can initiate payouts. Verify:
  • User identity
  • Wallet ownership
  • Bank account ownership
  • KYC compliance
function canUserPayout($api, $userId, $walletId, $bankAccountId) {
    // Check wallet ownership
    $wallet = $api->Wallets->Get($walletId);
    if (!in_array($userId, $wallet->Owners)) {
        return false;
    }
    
    // Check bank account ownership
    $bankAccount = $api->Users->GetBankAccount($userId, $bankAccountId);
    if ($bankAccount->UserId !== $userId) {
        return false;
    }
    
    return true;
}

Next Steps

Bank Accounts

Learn how to add and manage bank accounts

Webhooks

Set up notifications for payout status updates

Build docs developers (and LLMs) love