Create Withdrawal
POST
/withdrawal/
Create a cryptocurrency withdrawal request to send funds from your merchant balance to an external EVM address.
Authentication
Requires OAuth 2.0 authentication with read and write scopes.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
amount | decimal | Yes | Amount to withdraw in the specified currency |
currency | string | Yes | Currency code (e.g., "USDTERC20", "USDCERC20", "DAIERC20") |
address | string | Yes | Destination EVM address (0x format, 42 characters) |
account_id | uuid | No | Source wallet ID. If not provided, uses default wallet |
custom_id | string | No | Your internal reference ID. Max 64 characters |
callback_url | string | No | URL for webhook notifications about withdrawal status |
Example Request
curl -X POST https://api.cryptofuse.io/withdrawal/ \
-H "Authorization: Bearer your_access_token" \
-H "Content-Type: application/json" \
-d '{
"amount": 100.00,
"currency": "USDTERC20",
"address": "0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE",
"custom_id": "WITHDRAW-12345",
"callback_url": "https://your-site.com/webhook/withdrawal"
}'
Response
Success Response (201 Created)
{
"id": "660e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"amount": "100.00",
"currency": "USDTERC20",
"address": "0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE",
"blockchain": "ETH",
"token": "USDT",
"network_fee": "3.50",
"transaction_fee": "1.00",
"total_fee": "4.50",
"total_deducted": "104.50",
"transaction_hash": null,
"custom_id": "WITHDRAW-12345",
"callback_url": "https://your-site.com/webhook/withdrawal",
"account_id": null,
"created_at": "2025-01-15T12:00:00Z",
"updated_at": "2025-01-15T12:00:00Z"
}
Response Fields
| Field | Type | Description |
|---|---|---|
id | uuid | Unique withdrawal identifier |
status | string | Current withdrawal status |
amount | string | Withdrawal amount (what recipient receives) |
network_fee | string | Blockchain network fee |
transaction_fee | string | Platform processing fee |
total_deducted | string | Total amount deducted from balance |
transaction_hash | string | Blockchain transaction hash (null until processed) |
Error Responses
400 Bad Request - Invalid Address
{
"error": {
"code": "invalid_address",
"message": "Invalid EVM address format",
"details": {
"address": "0xinvalid",
"expected_format": "0x followed by 40 hexadecimal characters"
}
}
}
400 Bad Request - Insufficient Balance
{
"error": {
"code": "insufficient_balance",
"message": "Insufficient balance for withdrawal",
"details": {
"available": "50.00",
"requested": "100.00",
"total_with_fees": "104.50",
"currency": "USDTERC20"
}
}
}
422 Unprocessable Entity - Below Minimum
{
"error": {
"code": "below_minimum",
"message": "Withdrawal amount below minimum",
"details": {
"minimum": "10.00",
"requested": "5.00",
"currency": "USDTERC20"
}
}
}
Withdrawal Status Values
| Status | Description | Next Steps |
|---|---|---|
pending | Withdrawal created, awaiting processing | Will be processed in next batch |
processing | Being processed by the system | Transaction will be broadcast soon |
completed | Successfully sent to blockchain | Check transaction hash for confirmation |
failed | Withdrawal failed | Funds returned to balance, check error |
cancelled | Cancelled by user | Funds returned to balance |
Fee Structure
Withdrawals incur two types of fees:
- Network Fee: Variable blockchain gas fee (changes based on network congestion)
- Transaction Fee: Fixed platform processing fee (1% or minimum amount)
Example Fee Calculation
Withdrawal Amount: 100.00 USDT
Network Fee: 3.50 USDT (current gas price)
Transaction Fee: 1.00 USDT (1%)
Total Fees: 4.50 USDT
Total Deducted: 104.50 USDT
Address Validation
EVM addresses must:
- Start with "0x"
- Be exactly 42 characters long
- Contain only hexadecimal characters (0-9, a-f, A-F)
- Pass checksum validation (mixed case)
Valid Address Examples
0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE ✓ Checksummed
0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce ✓ Lowercase
0x0000000000000000000000000000000000000000 ✓ Null address (warning)
Minimum Withdrawal Amounts
| Currency | Minimum Amount | Network |
|---|---|---|
| USDTERC20 | 10.00 | Ethereum |
| USDCERC20 | 10.00 | Ethereum |
| DAIERC20 | 10.00 | Ethereum |
Processing Times
- Pending → Processing: Usually within 5 minutes
- Processing → Completed: 1-5 minutes after broadcast
- Blockchain Confirmations: Varies by network (Ethereum ~12 confirmations)
Important Notes
- Withdrawals are processed in batches for efficiency
- Network fees are estimated and may vary slightly
- Always verify the destination address - transactions cannot be reversed
- The null address (0x000...000) will trigger a warning
- Contract addresses are supported but use at your own risk
- Implement webhook handlers for real-time status updates
Code Examples
JavaScript
async function createWithdrawal(amount, address) {
const withdrawal = {
amount: amount,
currency: 'USDTERC20',
address: address,
custom_id: `WITHDRAW-${Date.now()}`,
callback_url: 'https://your-site.com/webhook/withdrawal'
};
const response = await fetch('https://api.cryptofuse.io/withdrawal/', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(withdrawal)
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
const result = await response.json();
console.log(`Withdrawal created: ${result.id}`);
console.log(`Total deducted: ${result.total_deducted} ${result.currency}`);
return result;
}
Python
import requests
from decimal import Decimal
def create_withdrawal(amount: Decimal, address: str, currency: str = "USDTERC20"):
"""Create a withdrawal request."""
withdrawal_data = {
"amount": str(amount),
"currency": currency,
"address": address,
"custom_id": f"WITHDRAW-{int(time.time())}",
"callback_url": "https://your-site.com/webhook/withdrawal"
}
response = requests.post(
"https://api.cryptofuse.io/withdrawal/",
json=withdrawal_data,
headers={
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
)
if response.status_code == 201:
result = response.json()
print(f"Withdrawal {result['id']} created")
print(f"Amount: {result['amount']} {result['currency']}")
print(f"Fees: {result['total_fee']} {result['currency']}")
print(f"Total deducted: {result['total_deducted']} {result['currency']}")
return result
else:
error = response.json()
raise Exception(f"Withdrawal failed: {error['error']['message']}")
# Example usage
try:
withdrawal = create_withdrawal(
amount=Decimal("100.00"),
address="0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE"
)
except Exception as e:
print(f"Error: {e}")
Testing
In the staging environment:
- Use small amounts for testing (minimum amounts apply)
- Withdrawals to address
0x0000000000000000000000000000000000000001will auto-complete - Withdrawals to address
0x0000000000000000000000000000000000000002will auto-fail