1House Global API Documentation

Merchant & Withdrawals

Process withdrawal requests and manage payment methods

Process withdrawal requests, manage payment methods, and handle external payouts.

Withdrawal Process

  1. User initiates withdrawal via Wallet API (Keys are locked)
  2. Merchant service processes payment through payment processor
  3. Transaction is marked as completed or failed
  4. Wallet service is notified of the result

Overview

The Merchant API provides:

  • Withdrawal request management
  • Payment processing integration
  • Withdrawal status tracking
  • Payment method configuration
  • Admin withdrawal management

Base Path: /v1/withdrawals

Keys are Always Integers

Important: Keys are always whole numbers (integers). The amount field in withdrawal requests represents the number of Keys (e.g., 75, not 75.50). The USD value is calculated on the backend using the exchange rate.

Withdrawal Requests

Create Withdrawal Request

Create a new withdrawal request. This should be called after initiating a withdrawal via the Wallet API.

POST /v1/withdrawals
X-API-Key: your-api-key
Authorization: Bearer your-jwt-token
Content-Type: application/json
{
  "transactionId": "TXN-1697891234-GHI90123",
  "amount": 75,
  "paymentMethod": "bank_transfer",
  "paymentDetails": {
    "accountNumber": "1234567890",
    "routingNumber": "987654321",
    "accountName": "John Doe",
    "bankName": "Example Bank"
  },
  "metadata": {
    "userId": "user_456"
  }
}

Try it out:

# Development
curl -X POST "https://api-gateway.dev.1houseglobalservices.com/v1/withdrawals" \
  -H "X-API-Key: your-development-api-key" \
  -H "Authorization: Bearer your-jwt-token" \
  -H "Content-Type: application/json" \
  -d '{
    "transactionId": "TXN-1697891234-GHI90123",
    "amount": 75,
    "paymentMethod": "bank_transfer",
    "paymentDetails": {
      "accountNumber": "1234567890",
      "routingNumber": "987654321"
    }
  }'

# Production
curl -X POST "https://api-gateway.prod.1houseglobalservices.com/v1/withdrawals" \
  -H "X-API-Key: your-production-api-key" \
  -H "Authorization: Bearer your-jwt-token" \
  -H "Content-Type: application/json" \
  -d '{
    "transactionId": "TXN-1697891234-GHI90123",
    "amount": 75,
    "paymentMethod": "bank_transfer",
    "paymentDetails": {
      "accountNumber": "1234567890",
      "routingNumber": "987654321"
    }
  }'
// Development
const DEV_API_URL = 'https://api-gateway.dev.1houseglobalservices.com';
const DEV_API_KEY = 'your-development-api-key';

// Production
const PROD_API_URL = 'https://api-gateway.prod.1houseglobalservices.com';
const PROD_API_KEY = 'your-production-api-key';

// Use appropriate environment
const apiUrl = process.env.NODE_ENV === 'production' ? PROD_API_URL : DEV_API_URL;
const apiKey = process.env.NODE_ENV === 'production' ? PROD_API_KEY : DEV_API_KEY;

const response = await fetch(`${apiUrl}/v1/withdrawals`, {
  method: 'POST',
  headers: {
    'X-API-Key': apiKey,
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    transactionId: 'TXN-1697891234-GHI90123',
    amount: 75,
    paymentMethod: 'bank_transfer',
    paymentDetails: {
      accountNumber: '1234567890',
      routingNumber: '987654321'
    }
  })
});
const data = await response.json();
import requests
import os

# Development
DEV_API_URL = 'https://api-gateway.dev.1houseglobalservices.com'
DEV_API_KEY = 'your-development-api-key'

# Production
PROD_API_URL = 'https://api-gateway.prod.1houseglobalservices.com'
PROD_API_KEY = 'your-production-api-key'

# Use appropriate environment
api_url = PROD_API_URL if os.getenv('ENVIRONMENT') == 'production' else DEV_API_URL
api_key = PROD_API_KEY if os.getenv('ENVIRONMENT') == 'production' else DEV_API_KEY

response = requests.post(
    f'{api_url}/v1/withdrawals',
    headers={
        'X-API-Key': api_key,
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    },
    json={
        'transactionId': 'TXN-1697891234-GHI90123',
        'amount': 75,
        'paymentMethod': 'bank_transfer',
        'paymentDetails': {
            'accountNumber': '1234567890',
            'routingNumber': '987654321'
        }
    }
)
data = response.json()
{
  "success": true,
  "status": 201,
  "message": "Withdrawal request created successfully",
  "data": {
    "_id": "withdrawal_123",
    "requestId": "WDR-1697891234-ABC12345",
    "userId": "user_456",
    "transactionId": "TXN-1697891234-GHI90123",
    "amount": 75.00,
    "currency": "Keys",
    "status": "pending",
    "paymentMethod": "bank_transfer",
    "paymentDetails": {
      "accountNumber": "1234567890",
      "routingNumber": "987654321"
    },
    "createdAt": "2025-10-21T12:00:00.000Z"
  },
  "meta": {
    "timestamp": "2025-10-21T12:00:00.000Z",
    "version": "v1"
  }
}

Get User's Withdrawals

Retrieve withdrawal requests for the authenticated user.

GET /v1/withdrawals
ParameterTypeDescriptionDefault
pagenumberPage number1
limitnumberResults per page50
statusstringFilter by statusall
startDatestringStart date (ISO 8601)none
endDatestringEnd date (ISO 8601)none
{
  "success": true,
  "status": 200,
  "message": "Withdrawals retrieved successfully",
  "data": [
    {
      "requestId": "WDR-1697891234-ABC12345",
      "amount": 75,
      "status": "completed",
      "paymentMethod": "bank_transfer",
      "merchantTransactionId": "MERCHANT-1697891234-XYZ789",
      "processedAt": "2025-10-21T13:00:00.000Z",
      "createdAt": "2025-10-21T12:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 5,
    "pages": 1
  }
}

Get Withdrawal by ID

Retrieve a specific withdrawal request.

GET /v1/withdrawals/:requestId
{
  "success": true,
  "status": 200,
  "data": {
    "_id": "withdrawal_123",
    "requestId": "WDR-1697891234-ABC12345",
    "userId": {
      "_id": "user_456",
      "email": "user@example.com",
      "firstName": "John",
      "lastName": "Doe"
    },
    "transactionId": "TXN-1697891234-GHI90123",
    "amount": 75,
    "currency": "Keys",
    "status": "completed",
    "paymentMethod": "bank_transfer",
    "paymentDetails": {
      "accountNumber": "1234567890",
      "routingNumber": "987654321",
      "accountName": "John Doe",
      "bankName": "Example Bank"
    },
    "merchantTransactionId": "MERCHANT-1697891234-XYZ789",
    "processedAt": "2025-10-21T13:00:00.000Z",
    "processedBy": "system",
    "createdAt": "2025-10-21T12:00:00.000Z",
    "updatedAt": "2025-10-21T13:00:00.000Z"
  }
}

Process Withdrawal (Admin/System)

Process a pending withdrawal request through the payment processor.

POST /v1/withdrawals/:requestId/process
{
  "success": true,
  "status": 200,
  "message": "Withdrawal processed successfully",
  "data": {
    "requestId": "WDR-1697891234-ABC12345",
    "status": "completed",
    "merchantTransactionId": "MERCHANT-1697891234-XYZ789",
    "processedAt": "2025-10-21T13:00:00.000Z",
    "processedBy": "admin@example.com"
  }
}

Cancel Withdrawal

Cancel a pending withdrawal request (refunds Keys to wallet).

POST /v1/withdrawals/:requestId/cancel
{
  "reason": "User requested cancellation"
}
{
  "success": true,
  "status": 200,
  "message": "Withdrawal cancelled successfully",
  "data": {
    "requestId": "WDR-1697891234-ABC12345",
    "status": "cancelled",
    "errorMessage": "User requested cancellation"
  }
}

Admin Endpoints

Get All Withdrawals (Admin Only)

Retrieve all withdrawal requests in the system.

GET /v1/withdrawals/admin/all
ParameterTypeDescriptionDefault
pagenumberPage number1
limitnumberResults per page100
statusstringFilter by statusall
userIdstringFilter by user IDall
paymentMethodstringFilter by payment methodall
startDatestringStart date (ISO 8601)none
endDatestringEnd date (ISO 8601)none

Get Pending Withdrawals (Admin Only)

Retrieve all pending withdrawal requests.

GET /v1/withdrawals/admin/pending
{
  "success": true,
  "status": 200,
  "data": [
    {
      "requestId": "WDR-1697891234-ABC12345",
      "userId": {
        "email": "user@example.com",
        "firstName": "John",
        "lastName": "Doe"
      },
      "amount": 75,
      "paymentMethod": "bank_transfer",
      "status": "pending",
      "createdAt": "2025-10-21T12:00:00.000Z"
    }
  ]
}

Payment Methods

Withdrawal Status

StatusDescription
pendingWithdrawal request created, awaiting processing
processingPayment is being processed by payment processor
completedPayment successfully processed and sent
failedPayment processing failed
cancelledWithdrawal was cancelled (Keys refunded)

Withdrawal Request Object

FieldTypeDescription
requestIdstringUnique withdrawal request identifier
userIdstring/ObjectUser who requested withdrawal
transactionIdstringAssociated wallet transaction ID
amountintegerWithdrawal amount in Keys (number of Keys, always whole number)
currencystringCurrency code (always "Keys")
statusstringWithdrawal status
paymentMethodstringPayment method type
paymentDetailsobjectPayment method specific details
merchantTransactionIdstringPayment processor transaction ID
processedAtdatetimeWhen payment was processed
processedBystringWho processed the payment
errorMessagestringError message (if failed)
errorCodestringError code (if failed)
metadataobjectAdditional metadata
notesstringAdmin notes
createdAtdatetimeRequest creation date
updatedAtdatetimeLast update date

Withdrawal Flow

1. User initiates withdrawal via Wallet API
   POST /v1/wallets/withdraw
   - Keys are locked (deducted from balance)
   - Transaction created with status "pending"

2. User creates withdrawal request
   POST /v1/withdrawals
   - Withdrawal request created with status "pending"
   - Links to wallet transaction

3. Admin/System processes withdrawal
   POST /v1/withdrawals/:requestId/process
   - Payment processor API called
   - Merchant transaction ID generated
   - Wallet service notified to complete transaction

4. Wallet service completes transaction
   - Transaction status updated to "completed"
   - Keys remain deducted (already sent)

OR

3. Withdrawal fails or is cancelled
   POST /v1/withdrawals/:requestId/cancel
   - Wallet service notified to refund
   - Keys refunded to wallet
   - Transaction status updated to "cancelled"

Best Practices

1. Validate Payment Details

const validateBankDetails = (details) => {
  if (!details.accountNumber || !details.routingNumber) {
    throw new Error('Account number and routing number required');
  }
  // Additional validation...
};

2. Handle Processing Errors

try {
  await processWithdrawal(requestId);
} catch (error) {
  // Log error
  // Notify user
  // Cancel withdrawal if needed
  await cancelWithdrawal(requestId, error.message);
}

3. Monitor Pending Withdrawals

// Admin dashboard should regularly check for pending withdrawals
const pending = await getPendingWithdrawals();
pending.forEach(withdrawal => {
  // Process or alert
});

4. Secure Payment Details

// Never log full payment details
const sanitized = {
  ...paymentDetails,
  accountNumber: `****${accountNumber.slice(-4)}`
};

Error Handling

Insufficient Balance

{
  "success": false,
  "status": 400,
  "message": "Insufficient balance"
}

Invalid Payment Method

{
  "success": false,
  "status": 400,
  "message": "Invalid payment method",
  "errors": [
    {
      "field": "paymentMethod",
      "message": "Payment method must be one of: bank_transfer, paypal, stripe, crypto, other"
    }
  ]
}

Processing Failure

{
  "success": false,
  "status": 500,
  "message": "Payment processing failed",
  "error": "Payment processor timeout"
}