Skip to main content
Facilitate split payment services where a single payment is divided among multiple recipients. Perfect for splitting bills, shared expenses, or distributing funds to multiple stakeholders efficiently. 🎯 What you’ll build: A split payment system where users deposit USD into a virtual account, funds convert to USDC, then split payments are distributed to multiple recipients through the use of batch transfers.

Use Case Overview

This recipe demonstrates a split payment flow where:
  • ✅ Users deposit USD into dedicated virtual accounts
  • ✅ USD automatically converts to USDC stablecoin
  • ✅ Payments are split among multiple recipients using batch transfers
  • ✅ Operational overhead is minimized through automation
Common Split Payment Use Cases:
  • Paying multiple recipients at once – Take funds from a single wallet and send payouts to several recipients in one batch instead of issuing individual transfers.
  • Sharing revenue between parties – Distribute a single pool of funds across different stakeholders (for example, a primary recipient plus one or more collaborators).
  • Operational or treasury fan-out – Move balance from a central wallet into multiple wallets (such as teams, regions, or projects) in a single operation.
  • Scheduled payout runs – Periodically aggregate earnings and use a batch transfer to pay out all recipients for a given period in one shot.
  • Distributing rewards or incentives – Send rewards, rebates, or incentive payments to many users at the same time from one funding source.

What you’ll build

Here’s what we’ll accomplish in this recipe:
  1. Add Virtual Account - Set up account for collecting USD payments that convert to USDC
  2. Split Payments - Execute on-demand split payments with batch transfers
Payment Flow
USD → User Bank Account → Virtual Account → USDC → Batch Transfer → Multiple Recipients
All examples in this guide use the sandbox environment. When you’re ready for production, simply replace the sandbox URL with the production endpoint and use your production API keys.

Prerequisites

Before you begin, make sure you have: User A – Individual user created and KYC submitted with status = active For a complete guide on user onboarding, see:

Add Virtual Account

The sender needs a Virtual Account for collecting the payment to be split. This is a bank account number automatically created by HIFI that users can deposit USD into. When fiat arrives, it’s automatically converted to USDC and ready for distribution.
Virtual Account for Split Payments: Each virtual account comes with unique ACH/wire/RTP details you can surface in your app. When deposits arrive, HIFI detects the funds and applies your conversion settings (e.g., USD → USDC). You can then use settlement rules for automatic splitting or batch transfers for on-demand splitting.
Request:
curl --request POST \
  --url https://sandbox.hifibridge.com/v2/users/3b77cec8-1bb9-5ea0-91a1-e8c1411dd429/virtual-accounts \
  --header 'accept: application/json' \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --data '
{
  "sourceCurrency": "usd",
  "destinationCurrency": "usdc",
  "destinationChain": "POLYGON"
}
'
Response:
{
  "id": "c48d1dd1-b5cd-5bc7-b85e-df1b0f17c1c8",
  "status": "activated",
  "provider": "CROSS_RIVER",
  "userId": "3b77cec8-1bb9-5ea0-91a1-e8c1411dd429",
  "source": {
    "paymentRails": ["ach", "wire", "rtp"],
    "currency": "usd"
  },
  "destination": {
    "chain": "POLYGON",
    "currency": "usdc",
    "walletAddress": "0x63dAbB631bcE6d6090A4e6c5c7aB20d3D853C338"
  },
  "depositInstructions": {
    "bankName": "Cross River Bank",
    "bankAddress": "885 Teaneck Road, Teaneck, NJ 07666",
    "beneficiary": {
      "name": "John Doe",
      "address": "123 Park Ave, Kansas City, KS, 10001, US"
    },
    "ach": {
      "routingNumber": "021214891",
      "accountNumber": "372232122120"
    },
    "wire": {
      "routingNumber": "021214891",
      "accountNumber": "372232122120"
    },
    "instruction": "Please deposit USD to the bank account provided. Ensure that the beneficiary name matches the account holder name provided, or the payment may be rejected."
  }
}

Split Payments with Batch Transfers

Batch transfers let you manually initiate split payments with full control over amounts and recipients for each transaction. You decide when to split and can customize the distribution for each payment.
When to Use Batch Transfers: Use batch transfers when you need: - On-demand split payments that vary per transaction - Dynamic recipient lists that change based on the payment - Conditional logic before splitting (e.g., verify amounts, check balances) - Bill payments where amounts differ each time
  • One-time or irregular split payments Perfect for bill payment services, dynamic revenue sharing, or variable expense splits.
Create a batch transfer to split a payment among multiple recipients in a single transaction using the Create Batch Transfer endpoint.In this example, we’ll split a payment to three different recipients with 10 USDC each from the user’s wallet.Request:
curl --request POST \
  --url https://sandbox.hifibridge.com/v2/wallets/transfers/batches \
  --header 'accept: application/json' \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --data '
{
  "requestId": "b91772a6-f9c0-4479-a34c-c8723608d2e8",
  "currency": "usdc",
  "chain": "POLYGON",
  "source": {
    "userId": "3b77cec8-1bb9-5ea0-91a1-e8c1411dd429"
  },
  "destination": {
    "batch": [
      {
        "walletAddress": "0xA4C951a7ca4138220a9D4611e7A058d4673e14c3",
        "amount": "10"
      },
      {
        "walletAddress": "0x0466DCD644Ae2Ee5d88CF0e1976c3ce237A0D760",
        "amount": "10"
      },
      {
        "walletAddress": "0x8356d234077d4b7c71E35c95B075ed4ba5FF7681",
        "amount": "10"
      }
    ]
  },
  "requireApproval": false
}
'
Request Fields:
requestId
string
required
Unique identifier (UUID) for this batch transfer request to ensure idempotency.
currency
string
required
Cryptocurrency to transfer. Use usdc for USD Coin.
chain
string
required
Blockchain network for the transfer. Options: POLYGON, ETHEREUM
source
object
required
Source of the batch transfer (the user making the split payment).
destination
object
required
Destination configuration containing the batch of recipients.
requireApproval
boolean
Whether the batch transfer requires manual approval before execution. Set to false for automatic processing.
Response:
{
  "id": "467e8eed-c6e2-4f78-9404-a82148c49e0e",
  "type": "WALLET.TRANSFER.BATCH",
  "status": "CREATED",
  "chain": "POLYGON",
  "currency": "usdc",
  "contractAddress": "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582",
  "source": {
    "userId": "3b77cec8-1bb9-5ea0-91a1-e8c1411dd429",
    "walletAddress": "0x63dAbB631bcE6d6090A4e6c5c7aB20d3D853C338",
    "walletType": "INDIVIDUAL"
  },
  "destination": {
    "batch": [
      {
        "amount": "10",
        "walletAddress": "0xA4C951a7ca4138220a9D4611e7A058d4673e14c3"
      },
      {
        "amount": "10",
        "walletAddress": "0x0466DCD644Ae2Ee5d88CF0e1976c3ce237A0D760"
      },
      {
        "amount": "10",
        "walletAddress": "0x8356d234077d4b7c71E35c95B075ed4ba5FF7681"
      }
    ]
  },
  "receipt": {
    "transactionHash": null,
    "userOpHash": null
  }
}
Batch transfer created!Response Fields:
id
string
Unique batch transfer ID. Save this to monitor the batch status and retrieve transaction details.
type
string
Transfer type. Always WALLET.TRANSFER.BATCH for batch transfers.
status
string
Current batch status. Starts as CREATED, then progresses through: - CREATED - Batch transfer initiated - PENDING - Being processed on blockchain - COMPLETED - All payments successfully delivered - FAILED - One or more payments failed (check individual statuses)
chain
string
Blockchain network where the transfer is being executed.
currency
string
Cryptocurrency being transferred.
contractAddress
string
Smart contract address handling the USDC transfers on the blockchain.
source
object
Source details showing the user’s wallet information.
destination
object
Destination details showing all recipients in the batch.
receipt
object
Transaction receipt information.
Understanding the Batch Transfer:In this example:
  • Source: User’s wallet (0x63dA...C338) with 30+ USDC available
  • Batch: 3 recipients receiving 10 USDC each
  • Total: 30 USDC distributed in a single blockchain transaction
  • Cost Savings: One transaction fee instead of three separate transactions
Monitoring Batch Transfers: Subscribe to WALLET.TRANSFER.BATCH.UPDATE webhook events to receive real-time notifications as the batch progresses. You can also poll the Retrieve Batch Transfer endpoint to check individual payment statuses within the batch.
For a complete guide on batch transfers including advanced features like approval workflows and error handling, see our Batch Transfers Guide.

🎉 Congratulations!

You’ve successfully built a split payment system! By following this recipe, you can now:
  • ✅ Create virtual accounts for collecting payments with automatic conversion
  • ✅ Execute batch transfers for on-demand split payments
  • ✅ Reduce operational overhead with automated or consolidated transactions

Next Steps

Ready to scale your split payment service? Here’s what to explore next:
  • Batch Transfers Guide - Learn about batch transfers with approval workflows, failure handling, and advanced features
  • Webhooks - Set up real-time notifications for deposit detection, conversion completion, and split payment distribution
  • Virtual Accounts Guide - Learn about monitoring deposits and handling multiple virtual accounts per user
  • API Reference - Explore all available endpoints and parameters for advanced features