Automatic Transfer Confirmation
Learn how to create transfers that are automatically confirmed without user interaction - perfect for background payments, automated payouts, and system-to-system transfers.
Overview​
Automatic confirmation allows you to create and complete transfers programmatically without redirecting users to the Paysera interface. This is ideal when:
- Processing automated payouts (commissions, royalties)
- Running scheduled payments
- Handling system-triggered transfers
- Operating without user presence
Automatic confirmation requires special API permissions. Contact Paysera support to enable this feature for your client.
Prerequisites​
Before you begin:
- ✅ API credentials with automatic confirmation permissions
- ✅ Sufficient balance in your account
- ✅ Understanding of Transfer Statuses
Workflow​
1. Create Transfer (auto_confirm: true)
↓
2. Transfer Status: reserved
↓
3. Automatic Confirmation
↓
4. Transfer Status: done
This workflow is a simplified version of the full 5-step workflow. By setting auto_confirm: true, you are instructing the system to automatically perform the reserve, provide-password (if applicable), sign (if applicable), and register steps.
Step-by-Step Guide​
- Step 1: Create Transfer
- Step 2: Handle Response
- Step 3: Monitor Status
Create a transfer with auto_confirm parameter:
POST /transfer/rest/v1/transfers HTTP/1.1
Host: wallet.paysera.com
Content-Type: application/json
Authorization: MAC id="client_id", ts="...", nonce="...", mac="..."
{
"amount": {
"amount": "50.00",
"currency": "EUR"
},
"beneficiary": {
"type": "bank",
"name": "John Doe",
"bank_account": {
"iban": "LT123456789012345678"
}
},
"payer": {
"account_number": "EVP9876543210"
},
"purpose": {
"details": "Commission payment"
},
"auto_confirm": true
}
Key Parameter:
auto_confirm: true- Enables automatic confirmation
Success Response:
{
"id": "12345",
"status": "reserved",
"amount": {
"amount": "50.00",
"currency": "EUR"
},
"beneficiary": {
"type": "bank",
"name": "John Doe",
"bank_account": {
"iban": "LT123456789012345678"
}
},
"payer": {
"account_number": "EVP9876543210"
},
"purpose": {
"details": "Commission payment"
},
"created_at": 1697193600
}
The transfer is reserved and will be automatically confirmed by the system.
The system automatically confirms the transfer. You'll receive a callback (if configured) when status changes to done.
Callback notification:
POST /your-callback-url
Content-Type: application/x-www-form-urlencoded
transfer_id=12345&status=done&date=1697193650
Complete Code Examples​
- PHP
- Python
- Node.js
<?php
use Paysera\Client\TransferClient;
// Initialize client
$client = TransferClient::create([
'auth' => [
'mac' => [
'mac_id' => getenv('PAYSERA_CLIENT_ID'),
'mac_secret' => getenv('PAYSERA_MAC_KEY'),
],
],
]);
try {
// Create transfer with automatic confirmation
$transfer = $client->createTransfer([
'amount' => [
'amount' => '50.00',
'currency' => 'EUR',
],
'beneficiary' => [
'type' => 'bank',
'name' => 'John Doe',
'bank_account' => [
'iban' => 'LT123456789012345678',
],
],
'payer' => [
'account_number' => 'EVP9876543210',
],
'purpose' => [
'details' => 'Commission payment',
],
'auto_confirm' => true,
]);
echo "Transfer created: " . $transfer->getId() . "\n";
echo "Status: " . $transfer->getStatus() . "\n";
echo "Auto-confirm: " . ($transfer->getAutoConfirm() ? 'Yes' : 'No') . "\n";
// Wait for automatic confirmation (usually happens within seconds)
sleep(5);
// Check updated status
$updated = $client->getTransfer($transfer->getId());
echo "Updated status: " . $updated->getStatus() . "\n";
if ($updated->getStatus() === 'done') {
echo "Transfer completed successfully!\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
import requests
import time
from datetime import datetime
# Configuration
BASE_URL = "https://wallet.paysera.com/transfer/rest/v1"
CLIENT_ID = "your_client_id"
MAC_KEY = "your_mac_key"
def create_auto_confirm_transfer():
# Calculate MAC authentication (simplified - use library in production)
headers = {
"Content-Type": "application/json",
"Authorization": f'MAC id="{CLIENT_ID}", ts="...", nonce="...", mac="..."'
}
data = {
"amount": {
"amount": "50.00",
"currency": "EUR"
},
"beneficiary": {
"type": "bank",
"name": "John Doe",
"bank_account": {
"iban": "LT123456789012345678"
}
},
"payer": {
"account_number": "EVP9876543210"
},
"purpose": {
"details": "Commission payment"
},
"auto_confirm": True
}
response = requests.post(
f"{BASE_URL}/transfers",
json=data,
headers=headers
)
if response.status_code == 200:
transfer = response.json()
print(f"Transfer created: {transfer['id']}")
print(f"Status: {transfer['status']}")
# Wait for automatic confirmation
time.sleep(5)
# Check status
status_response = requests.get(
f"{BASE_URL}/transfers/{transfer['id']}",
headers=headers
)
updated = status_response.json()
print(f"Updated status: {updated['status']}")
if updated['status'] == 'done':
print("Transfer completed!")
return transfer
else:
print(f"Error: {response.status_code}")
print(response.text)
return None
# Execute
transfer = create_auto_confirm_transfer()
const axios = require('axios');
const BASE_URL = 'https://wallet.paysera.com/transfer/rest/v1';
const CLIENT_ID = process.env.PAYSERA_CLIENT_ID;
const MAC_KEY = process.env.PAYSERA_MAC_KEY;
async function createAutoConfirmTransfer() {
try {
// Create transfer with auto-confirmation
const response = await axios.post(`${BASE_URL}/transfers`, {
amount: {
amount: '50.00',
currency: 'EUR'
},
beneficiary: {
type: 'bank',
name: 'John Doe',
bank_account: {
iban: 'LT123456789012345678'
}
},
payer: {
account_number: 'EVP9876543210'
},
purpose: {
details: 'Commission payment'
},
auto_confirm: true
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': `MAC id="${CLIENT_ID}", ts="...", nonce="...", mac="..."`
}
});
const transfer = response.data;
console.log(`Transfer created: ${transfer.id}`);
console.log(`Status: ${transfer.status}`);
// Wait for automatic confirmation
await new Promise(resolve => setTimeout(resolve, 5000));
// Check updated status
const statusResponse = await axios.get(
`${BASE_URL}/transfers/${transfer.id}`,
{
headers: {
'Authorization': `MAC id="${CLIENT_ID}", ts="...", nonce="...", mac="..."`
}
}
);
console.log(`Updated status: ${statusResponse.data.status}`);
if (statusResponse.data.status === 'done') {
console.log('Transfer completed successfully!');
}
return transfer;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
throw error;
}
}
// Execute
createAutoConfirmTransfer();
Use Cases​
- Commission Payouts
- Scheduled Payouts
- Refund Processing
Automatically pay commissions to partners:
function payCommission($partnerId, $amount) {
$partner = getPartner($partnerId);
$transfer = $client->createTransfer([
'amount' => [
'amount' => $amount,
'currency' => 'EUR',
],
'beneficiary' => [
'type' => 'paysera',
'name' => $partner->name,
'paysera_account' => [
'account_number' => $partner->account,
],
],
'payer' => [
'account_number' => 'EVP9876543210',
],
'purpose' => [
'details' => "Commission for period " . date('Y-m'),
],
'auto_confirm' => true,
]);
logPayment($partnerId, $transfer->getId());
return $transfer;
}
Process scheduled payments automatically:
// Cron job: Run daily at 2 AM
function processDailyPayouts() {
$payouts = getPendingPayouts();
foreach ($payouts as $payout) {
try {
$transfer = $client->createTransfer([
'amount' => [
'amount' => $payout->amount,
'currency' => $payout->currency,
],
'beneficiary' => [
'type' => 'paysera',
'name' => $payout->recipient_name,
'paysera_account' => [
'account_number' => $payout->account,
],
],
'payer' => [
'account_number' => 'EVP9876543210',
],
'purpose' => [
'details' => $payout->description,
],
'auto_confirm' => true,
]);
markPayoutProcessed($payout->id, $transfer->getId());
} catch (Exception $e) {
logError($payout->id, $e->getMessage());
}
}
}
Automate refund workflows:
function processRefund($orderId, $amount) {
$order = getOrder($orderId);
if (!$order->canRefund()) {
throw new Exception('Order cannot be refunded');
}
$transfer = $client->createTransfer([
'amount' => [
'amount' => $amount,
'currency' => $order->currency,
],
'beneficiary' => [
'type' => 'paysera',
'name' => $order->customer_name,
'paysera_account' => [
'account_number' => $order->customer_account,
],
],
'payer' => [
'account_number' => 'EVP9876543210',
],
'purpose' => [
'details' => "Refund for order #" . $orderId,
],
'auto_confirm' => true,
]);
updateOrderRefundStatus($orderId, $transfer->getId());
sendRefundNotification($order->customer_email);
return $transfer;
}
Error Handling​
- Common Errors
- Error Handling Pattern
Insufficient Funds:
{
"error": "insufficient_funds",
"error_description": "Account balance insufficient",
"available": "30.00",
"required": "50.00"
}
Permission Denied:
{
"error": "forbidden",
"error_description": "Auto-confirmation not enabled for this client"
}
Invalid Beneficiary:
{
"error": "invalid_beneficiary",
"error_description": "Invalid account number format"
}
try {
$transfer = $client->createTransfer([
'amount' => '50.00',
'auto_confirm' => true,
// ... other fields
]);
} catch (InsufficientFundsException $e) {
// Handle insufficient funds
notifyAdmin('Low balance: ' . $e->getAvailable());
throw $e;
} catch (ForbiddenException $e) {
// Auto-confirm not enabled
logger()->error('Auto-confirm permission missing');
// Fallback to manual confirmation
return createManualTransfer($data);
} catch (ApiException $e) {
// Other API errors
logger()->error('Transfer failed', [
'error' => $e->getErrorCode(),
'message' => $e->getMessage(),
]);
throw $e;
}
Security Considerations​
- 1. Validate Input
- 2. Rate Limiting
- 3. Amount Limits
function validateTransferData($data) {
if (!isset($data['amount']) || $data['amount'] <= 0) {
throw new ValidationException('Invalid amount');
}
if (!isset($data['beneficiary']['account_number'])) {
throw new ValidationException('Beneficiary account required');
}
// Validate IBAN format
if (!isValidIBAN($data['beneficiary']['account_number'])) {
throw new ValidationException('Invalid IBAN');
}
return true;
}
// Implement rate limiting for automated transfers
$key = "transfer_limit:" . $userId;
$count = Redis::incr($key);
if ($count === 1) {
Redis::expire($key, 3600); // 1 hour window
}
if ($count > 100) { // Max 100 transfers per hour
throw new RateLimitException('Transfer limit exceeded');
}
// Set maximum transfer amount for auto-confirmation
const MAX_AUTO_CONFIRM_AMOUNT = 1000.00;
if ($amount > MAX_AUTO_CONFIRM_AMOUNT) {
throw new SecurityException(
"Amount exceeds auto-confirm limit. Use manual confirmation."
);
}
Comparison: Auto vs Manual​
| Feature | Auto Confirmation | Manual Confirmation |
|---|---|---|
| User Interaction | None | Required |
| Speed | Instant | Depends on user |
| Use Case | Background payments | User-initiated |
| Permissions | Special permission needed | Standard |
| Control | Full automation | User verifies |
Additional Resources​
Support​
Need help with complex integrations?
Contact: tech_support@paysera.com