Debit Balance API
Overview
The Debit Balance API deducts funds from a user's wallet. This endpoint creates a debit transaction and updates the wallet balance atomically. Use this endpoint to process withdrawals, deduct bet amounts, or charge fees to user accounts.
Endpoint
| Method | Endpoint | Authentication |
|---|---|---|
| POST | /api/v1/debit-balance | Signature Required |
Authentication
This endpoint requires Signature-based Authentication. You must include the following headers:
| Header | Description |
|---|---|
x-signature | HMAC-SHA256 signature of the request |
x-timestamp | Unix timestamp (seconds) when the request was generated |
Note: See Overview for detailed information on how signature authentication works and how to generate signatures.
Request Body
| Field | Type | Required | Default | Validation |
|---|---|---|---|---|
clientId | string | Yes | - | Min 1 character |
amount | number | Yes | - | Min: 0.01 |
description | string | No | - | Max 500 characters |
reference | string | No | - | Max 255 characters, external reference ID |
Request Example
{
"clientId": "CLIENT_001",
"amount": 50.00,
"description": "Withdrawal request",
"reference": "WITHDRAWAL_789"
}
Response
Success Response (200 OK)
{
"status": "success",
"message": "Balance debited successfully",
"data": {
"userId": 123,
"clientId": "CLIENT_001",
"amount": 50.00,
"type": "debit",
"transactionId": 457,
"balance": 1550.50
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
status | string | Always "success" for successful requests |
message | string | Human-readable success message |
data.userId | integer | Internal user ID |
data.clientId | string | Client identifier |
data.amount | number | Amount that was debited |
data.type | string | Transaction type: "debit" |
data.transactionId | integer | Unique transaction ID for this debit operation |
data.balance | number | null | New wallet balance after debit, or null if unavailable |
Error Responses
Validation Error (400 Bad Request)
{
"status": "failed",
"message": "Validation failed",
"data": {
"errors": {
"clientId": ["The clientId field is required."],
"amount": ["The amount field is required.", "The amount must be at least 0.01."]
}
}
}
User Not Found (404 Not Found)
{
"status": "failed",
"message": "User not found",
"data": null
}
Insufficient Balance (400 Bad Request)
{
"status": "failed",
"message": "Insufficient balance",
"data": {
"error": "Insufficient balance for debit operation"
}
}
Authentication Error (401 Unauthorized)
{
"status": "error",
"message": "Invalid signature",
"data": null
}
Server Error (500 Internal Server Error)
{
"status": "failed",
"message": "Failed to debit balance",
"data": {
"error": "Database connection failed"
}
}
Usage Example
cURL
curl -X POST https://wdcf.xerve.online/api/v1/debit-balance \
-H "Content-Type: application/json" \
-H "x-signature: YOUR_SIGNATURE" \
-H "x-timestamp: 1706802000" \
-d '{
"clientId": "CLIENT_001",
"amount": 50.00,
"description": "Withdrawal request",
"reference": "WITHDRAWAL_789"
}'
Note: To generate the signature, refer to the Overview documentation.
JavaScript/TypeScript (with Axios)
import axios from 'axios';
// Import your signature generation function (see Overview)
import { generateSignature } from './signature-utils';
const API_BASE_URL = 'https://wdcf.xerve.online';
const CLIENT_SECRET = 'your-secret-key';
interface DebitBalanceData {
clientId: string;
amount: number;
description?: string;
reference?: string;
}
async function debitBalance(data: DebitBalanceData) {
const timestamp = Math.floor(Date.now() / 1000);
// Generate signature (see Overview for implementation)
const signature = generateSignature({
method: 'POST',
path: '/api/v1/debit-balance',
payload: data,
secret: CLIENT_SECRET,
timestamp
});
try {
const response = await axios.post(
`${API_BASE_URL}/api/v1/debit-balance`,
data,
{
headers: {
'Content-Type': 'application/json',
'x-signature': signature,
'x-timestamp': timestamp.toString()
}
}
);
console.log('Debited amount:', response.data.data.amount);
console.log('New balance:', response.data.data.balance);
console.log('Transaction ID:', response.data.data.transactionId);
return response.data;
} catch (error: any) {
console.error('Error:', error.response?.data || error.message);
throw error;
}
}
// Usage
debitBalance({
clientId: 'CLIENT_001',
amount: 50.00,
description: 'Withdrawal request',
reference: 'WITHDRAWAL_789'
});
Python
import requests
# Import your signature generation function (see Overview)
from signature_utils import generate_signature
import time
API_BASE_URL = 'https://wdcf.xerve.online'
CLIENT_SECRET = 'your-secret-key'
def debit_balance(client_id: str, amount: float, description: str = None, reference: str = None):
timestamp = int(time.time())
payload = {
"clientId": client_id,
"amount": amount
}
if description:
payload["description"] = description
if reference:
payload["reference"] = reference
# Generate signature (see Overview for implementation)
signature = generate_signature(
method="POST",
path="/api/v1/debit-balance",
payload=payload,
secret=CLIENT_SECRET,
timestamp=timestamp
)
headers = {
"Content-Type": "application/json",
"x-signature": signature,
"x-timestamp": str(timestamp)
}
response = requests.post(
f"{API_BASE_URL}/api/v1/debit-balance",
json=payload,
headers=headers
)
response.raise_for_status()
data = response.json()
print(f"Debited amount: {data['data']['amount']}")
print(f"New balance: {data['data']['balance']}")
print(f"Transaction ID: {data['data']['transactionId']}")
return data
# Usage
if __name__ == "__main__":
debit_balance(
client_id="CLIENT_001",
amount=50.00,
description="Withdrawal request",
reference="WITHDRAWAL_789"
)
Important Notes
- Atomic Operation: The debit operation is atomic - either both the transaction record and balance update succeed, or both fail. This ensures data consistency.
- Insufficient Balance: The system will reject debit requests if the user doesn't have sufficient balance. Always check the balance first using the Get Balance API if you need to verify available funds.
- Minimum Amount: The minimum debit amount is 0.01. Requests with smaller amounts will be rejected.
- Currency: All amounts are in the default currency (USD). Currency conversion is not handled by this endpoint.
- Transaction Record: Each debit operation creates a transaction record that can be retrieved using the Get Transactions API.
- Positive Amounts Only: Send only positive amounts. The system will handle the subtraction internally. Do not send negative amounts.
Common Use Cases
- Withdrawal Processing: Deduct funds when processing withdrawal requests
- Bet Placement: Debit user wallet when placing bets
- Fee Deduction: Charge service fees or commissions
- Purchase Payments: Deduct amounts for in-app purchases or services
Related Endpoints
- Overview - Authentication and signature generation guide
- V1 Generate Auth Token API - Authenticate users
- V1 Get Balance API - Check balance before debiting
- V1 Credit Balance API - Add funds to user wallet
- V1 Get Transactions API - View transaction history
Error Handling
| Error Code | Possible Causes | Resolution |
|---|---|---|
| 400 | Missing/invalid fields, amount < 0.01, insufficient balance | Check validation errors, verify user has sufficient balance |
| 401 | Invalid signature or expired timestamp | Verify signature generation and ensure timestamp is current |
| 404 | User not found | Verify clientId exists; may need to create user first |
| 500 | Database or transaction service failure | Check server logs and retry; transaction may have failed |
Pre-Debit Balance Check
It's recommended to check the user's balance before attempting a debit, especially for large amounts:
async function safeDebit(clientId: string, amount: number) {
// First, check current balance
const balanceResponse = await getBalance(clientId);
const currentBalance = balanceResponse.data.balance;
if (currentBalance < amount) {
throw new Error(`Insufficient balance. Available: ${currentBalance}, Required: ${amount}`);
}
// Proceed with debit
return await debitBalance({ clientId, amount });
}
