Skip to content

Wallet-as-a-Service (WaaS) Integration Guide

This guide details how to integrate with the Rach Finance Wallet-as-a-Service (WaaS) API. This API allows businesses to generate non-custodial HD wallets for their customers, derive addresses on multiple blockchains, and execute transfers.

Base URL: https://payments-api-dev-966260606560.europe-west2.run.app/api/v1

Authentication

All requests require a valid API Key in the header:

  • X-API-Key: <your_business_api_key>
  • Restriction: This API is available for Business Accounts only.

1. Create Customer Wallet

Creates a new HD Wallet (BIP-44) for a specific customer ID.

  • Endpoint: POST /wallet/customers
  • Description: Generates a master seed for the customer. One wallet covers all 9 supported networks.

Request

json
{
  "customer_id": "cust_12345",
  "word_count": 12
}

word_count is optional: 12 or 24 (default: 12).

Response

json
{
  "customer_id": "cust_12345",
  "wallet_id": 1,
  "mnemonic": ["word1", "word2", "...", "word12"],
  "created_at": "2024-01-01T12:00:00Z"
}

Critical: mnemonic is returned once only. Store it encrypted immediately — it cannot be retrieved again.


2. Derive Address

Derives a new blockchain address for a customer wallet at a specific index.

  • Endpoint: POST /wallet/:customerID/derive
  • Description: Generates a deposit address for a supported network.

Request

json
{
  "network": "ETH",
  "index": 0,
  "is_testnet": false,
  "enable_monitoring": true
}

Networks: BTC, BCH, LTC, ETH, BSC, POL, TRX, SOL, XRP

Response

json
{
  "customer_id": "cust_12345",
  "network": "ETH",
  "address": "0x71C...",
  "index": 0,
  "derivation_path": "m/44'/60'/0'/0/0",
  "is_testnet": false,
  "monitored": true
}

3. List Addresses

Lists all derived addresses for a customer.

  • Endpoint: GET /wallet/:customerID/addresses

Response

json
{
  "customer_id": "cust_12345",
  "addresses": [
    {
      "network": "ETH",
      "address": "0x71C...",
      "index": 0,
      "monitored": true
    }
  ],
  "total": 1
}

4. Get Seed Phrase

Retrieve the mnemonic seed phrase for a customer (sensitive — requires strong access controls).

  • Endpoint: GET /wallet/:customerID/seed

Response

json
{
  "customer_id": "cust_12345",
  "mnemonic": ["word1", "word2", "..."],
  "word_count": 12
}

5. Estimate Gas (EVM only — no auth required)

Estimate the gas fee for an EVM transaction. Supports ETH, BSC, POL only.

  • Endpoint: POST /wallet/estimate-gas
  • Authentication: None — public endpoint, safe for client-side use.

Request

json
{
  "network": "ETH",
  "currency": "USDT",
  "from_address": "0x...",
  "to_address": "0x...",
  "amount": "50000000"
}

Amount is in base units (see the Transfer section for the decimal reference table).

Response

json
{
  "gas_limit": "65000",
  "gas_price": "20000000000",
  "estimated_fee": "0.0013",
  "estimated_fee_usd": "3.90",
  "currency": "ETH"
}

6. Execute Transfer

Send crypto from a customer's derived wallet.

  • Endpoint: POST /wallet/:customerID/transfer

Amount Units

The API accepts both human-readable decimals ("2.5") and pre-converted base-unit integers ("2500000000000000000"). The server converts decimal input automatically using the correct precision for each network and currency.

NetworkCurrencyDecimalsExample: 50 units (decimal)Example: 50 units (base unit)
ETHETH18"50""50000000000000000000"
ETHUSDT, USDC6"50""50000000"
BSCBNB18"50""50000000000000000000"
BSCUSDT, USDC18"50""50000000000000000000"
POLPOL18"50""50000000000000000000"
POLUSDT, USDC6"50""50000000"
TRXTRX6"50""50000000"
TRXUSDT6"50""50000000"
SOLSOL9"50""50000000000"
SOLUSDC6"50""50000000"
BTC, LTC, BCHBTC/LTC/BCH8"50""5000000000"
XRPXRP6"50""50000000"

BSC USDT/USDC use 18 decimals (Binance-pegged tokens). POL USDT/USDC use 6 decimals (Polygon PoS bridged tokens — same as ETH).

Request

json
{
  "network": "ETH",
  "currency": "USDT",
  "to_address": "0xRecipient...",
  "amount": "50000000",
  "index": 0
}

Response

json
{
  "tx_hash": "0x...",
  "from_address": "0xSenderWallet...",
  "to_address": "0xRecipient...",
  "amount": "50000000",
  "currency": "USDT",
  "network": "ETH",
  "gas_fee": "1050000000000000",
  "status": "pending",
  "timestamp": "2024-01-01T12:05:00Z"
}

All amounts in response are in base units. status: "pending" means broadcast — track confirmation via webhooks.


7. Handle Deposit Webhooks

Rach fires two events per deposit. Configure your webhook URL in the dashboard (Settings → Webhooks).

Event Flow

customer sends crypto

wallet.deposit.detected   →  safe_to_credit: false  →  show "pending" to customer
        ↓  (seconds to minutes depending on network)
wallet.deposit.confirmed  →  safe_to_credit: true   →  credit customer account

Handler

javascript
app.post('/webhooks/rach', express.raw({ type: '*/*' }), async (req, res) => {
  // Always verify signature first
  const sig = req.headers['x-webhook-signature'];
  const expected = crypto
    .createHmac('sha256', process.env.RACH_WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(401).end();
  }

  const { event, data } = JSON.parse(req.body);

  if (event === 'wallet.deposit.detected') {
    // Mark deposit as pending — do not credit yet
    await db.deposits.upsert({
      customerId: data.customer_id,
      network: data.network,
      amount: data.amount,
      currency: data.currency,
      status: 'pending',
    });
  }

  // safe_to_credit is the definitive signal — check it explicitly
  if (event === 'wallet.deposit.confirmed' && data.safe_to_credit === true) {
    await db.deposits.update(
      { customerId: data.customer_id, network: data.network, status: 'pending' },
      { txHash: data.tx_hash, status: 'confirmed' }
    );
    await wallet.credit(data.customer_id, data.amount, data.currency);
  }

  res.sendStatus(200); // must respond 200 within 10s
});

Never credit on wallet.deposit.detected — it fires before the network confirmation threshold is met and safe_to_credit will be false.


8. Configure Fee Collection (optional)

Enable Rach to collect a percentage fee from customer transfers and send it directly on-chain to your own addresses. Configure this once during onboarding using your API key.

  • Endpoint: POST /wallet/fees

Request

json
{
  "fee_percent": "0.01",
  "is_enabled": true,
  "fee_addresses": {
    "ETH": "0xYourEthAddress...",
    "BSC": "0xYourBscAddress...",
    "POL": "0xYourPolAddress...",
    "TRX": "TYourTronAddress...",
    "SOL": "YourSolanaAddress...",
    "BTC": "bc1YourBtcAddress...",
    "XRP": "rYourXrpAddress..."
  }
}

fee_percent is a decimal string: "0.01" = 1%, "0.005" = 0.5%. Maximum is "0.5" (50%).

Fees are only collected for networks where you provide an address. You can update addresses at any time via PUT /wallet/fees/addresses.

Response

json
{
  "fee_percent": "0.01",
  "is_enabled": true,
  "fee_addresses": { "ETH": "0x...", "POL": "0x..." }
}

9. Get Transaction History

Retrieve transaction history for a customer wallet.

  • Endpoint: GET /wallet/:customerID/transactions?page=1&limit=20&network=ETH

Response

json
{
  "customer_id": "cust_12345",
  "transactions": [
    {
      "tx_hash": "0x...",
      "amount": "50000000",
      "currency": "USDT",
      "type": "transfer",
      "status": "confirmed",
      "created_at": "2024-01-01T12:05:00Z"
    }
  ],
  "total": 10
}

Rach Payments API