Virtual Accounts
Overview
Virtual Accounts are U.S. bank accounts (US_BANK) that receive USD deposits via ACH or wire transfer. They operate in two modes:
| Mode | How it works | Destination required |
|---|---|---|
| Crypto | Deposits are automatically converted to stablecoins (USDC/USDT) and sent to a blockchain wallet | Yes |
| Fiat | Deposits are held as a USD balance | No |
The mode is determined at creation time based on whether a destination wallet is provided. Once created, the mode cannot be changed.
Both modes support payouts - sending USD to any bank account via WIRE or SWIFT. See the Payouts Guide for details.
How It Works
Crypto Mode
- Create virtual account with a destination wallet
- Share the bank details with payers
- Payer sends USD via ACH or wire
- Funds are automatically converted to stablecoins and sent to the destination wallet
- You receive a webhook notification when the settlement is complete
Fiat Mode
- Create virtual account without a destination
- Share the bank details with payers
- Payer sends USD via ACH or wire
- Funds are added to the VA's USD balance
- You receive a webhook notification when the deposit arrives
Supported Configurations
| Currency | Network |
|---|---|
| USDC | Solana |
| USDC | Polygon |
| USDT | Polygon |
Bank Providers
| Bank | Crypto Mode | Fiat Mode | Notes |
|---|---|---|---|
portage | Yes | Yes | For non-US based users |
austin_capital_trust | Yes | Yes | For US-based users |
slovak_savings_bank | Yes | Yes | Sandbox only |
Deprecated:
lead_bankis no longer supported. Existing accounts remain functional, but new accounts cannot be created with this bank.Sandbox: Only
slovak_savings_bankis available in the sandbox environment.Production: Use
portagefor non-US based users andaustin_capital_trustfor US-based users.
Prerequisites
Before creating virtual accounts, ensure:
- You're authenticated (Getting Started)
- User has been created (User Management)
- User is verified (Verification)
- For Crypto Mode: User has a blockchain wallet (Solana, Polygon, or Tron)
- For Fiat Mode: No wallet required
Use Cases
US_BANK (USD Virtual Accounts)
- Freelancers receiving payments from U.S. clients
- Contractors getting paid for project work
- SMBs accepting payments from U.S. customers
- Remote workers receiving salary in crypto
Fiat Mode (USD Holding)
- Treasury management - hold USD without immediate conversion
- Payment aggregation - collect multiple payments before converting
- Timing flexibility - convert to crypto when rates are favorable
- Fiat-only workflows - maintain USD balance for fiat operations
Guides in This Section
1. Virtual Accounts
Learn how to:
- Create US_BANK virtual accounts
- Select the appropriate bank provider
- Get deposit instructions (bank details)
- Manage account status and lifecycle
- Support multiple blockchains and currencies
Key endpoints:
POST /v1/virtual-accounts- Create virtual accountGET /v1/virtual-accounts/{id}- Get virtual account detailsGET /v1/virtual-accounts/{id}/balance- Get account balance (fiat mode)POST /v1/virtual-accounts/{id}/payout- Initiate payout (fiat mode)
2. Deposits
Learn how to:
- Track incoming deposits
- View deposit history
- Get blockchain transaction hashes
- Calculate total received
Key endpoint:
GET /v1/virtual-accounts/{id}/deposits- Get deposits
3. Payouts (Fiat Mode)
Learn how to:
- Preview fees before initiating a payout
- Send funds from US_BANK fiat mode accounts via WIRE or SWIFT
- Create and use WIRE/SWIFT recipients
- Understand fee structure (base fees, client markup)
- Track payout status and lifecycle
- Handle payout webhooks
Key endpoints:
POST /v1/virtual-accounts/{id}/payout/preview- Preview fees before payoutPOST /v1/virtual-accounts/{id}/payout- Send funds to a WIRE/SWIFT recipient
4. Liquidation Address (Crypto to USD)
Learn how to:
- Create a crypto wallet that automatically converts to USD
- Configure ACH, WIRE, or SWIFT recipients for payouts
- Handle liquidation webhooks
- Track crypto deposits and USD payouts
Key endpoints:
POST /v1/virtual-accounts/{id}/liquidation-address- Create liquidation addressGET /v1/virtual-accounts/{id}/liquidation-address- List all liquidation addressesGET /v1/virtual-accounts/{id}/liquidation-address/{addressId}- Get liquidation address by ID
Quick Start
1. Create US_BANK Virtual Account
curl -X POST https://api.balampay.com/v1/virtual-accounts \
-H "Authorization: Bearer $TOKEN" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-H "idempotency-key: $(uuidgen)" \
-d '{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "US_BANK",
"bank": "portage",
"destination": {
"currency": "USDC",
"network": "solana",
"address": "7tQJvFk8XZoaVRjL..."
}
}'2. Create Fiat Mode Account (No Crypto Conversion)
curl -X POST https://api.balampay.com/v1/virtual-accounts \
-H "Authorization: Bearer $TOKEN" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-H "idempotency-key: $(uuidgen)" \
-d '{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "US_BANK",
"bank": "portage"
}'Note: Fiat mode is only available for
portageandslovak_savings_bank. Omitting thedestinationfield creates a fiat mode account.
3. Response with Deposit Instructions
US_BANK Response (Crypto Mode):
{
"id": "va_789012345",
"status": "activating",
"type": "US_BANK",
"bank": "portage",
"source_deposit_instructions": null,
"destination": {
"currency": "USDC",
"network": "solana",
"address": "7tQJvFk8XZoaVRjL..."
},
"created_at": "2024-01-15T10:30:00Z"
}US_BANK Response (Fiat Mode):
{
"id": "va_789012347",
"status": "activating",
"type": "US_BANK",
"bank": "portage",
"source_deposit_instructions": null,
"destination": null,
"created_at": "2024-01-15T10:30:00Z"
}Note: Fiat mode accounts have
destination: null. Funds are held in USD and can be disbursed viaPOST /v1/virtual-accounts/{id}/payout.
Bank Selection (US_BANK)
For US_BANK accounts, you must specify which bank to use:
| Bank | Description | Fiat Mode | Use For |
|---|---|---|---|
portage | Portage Bank | Yes | Non-US based users |
austin_capital_trust | Austin Capital Trust | Yes | US-based users |
slovak_savings_bank | Slovak Savings Bank | Yes | Sandbox only |
Deprecated:
lead_bankis no longer supported. Existing accounts remain functional, but new accounts cannot be created with this bank.Sandbox: Only
slovak_savings_bankis available in the sandbox environment.Production: Use
portagefor non-US based users andaustin_capital_trustfor US-based users.
Supported Configurations
| Currency | Network |
|---|---|
| USDC | Solana |
| USDC | Polygon |
| USDT | Solana |
| USDT | Polygon |
| USDT | Tron |
Virtual Account Status
| Status | Description |
|---|---|
pending | Account creation initiated |
activating | Account is being provisioned (async) |
active | Account is ready to receive deposits |
failed | Account creation failed |
deactivated | Account has been closed |
Payment Rails
ACH Transfer (US_BANK)
- Speed: 1-3 business days
- Cost: Low/free for sender
- Limits: Typically $25K - $1M per transaction
Wire Transfer (US_BANK)
- Speed: Same day or next day
- Cost: $15-$50 for sender
- Types: Domestic and international
Fiat Mode Operations
For virtual accounts in fiat mode (no destination), use these endpoints to manage funds:
Get Balance
curl -X GET https://api.balampay.com/v1/virtual-accounts/va_789012347/balance \
-H "Authorization: Bearer $TOKEN" \
-H "x-api-key: $API_KEY"Response:
{
"virtual_account_id": "va_789012347",
"available_balance": "5000.00",
"currency": "USD"
}Initiate Payout
Note: Payouts are only available for US_BANK fiat mode accounts. You must first create a WIRE or SWIFT recipient.
curl -X POST https://api.balampay.com/v1/virtual-accounts/va_789012347/payout \
-H "Authorization: Bearer $TOKEN" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-H "idempotency-key: $(uuidgen)" \
-d '{
"amount": "1000.00",
"recipient_id": "550e8400-e29b-41d4-a716-446655440020"
}'Response:
{
"id": "po_123456789",
"virtual_account_id": "va_789012347",
"recipient_id": "550e8400-e29b-41d4-a716-446655440020",
"amount": "1000.00",
"currency": "USD",
"status": "pending",
"fees": {
"base_fees": {
"fixed_fee": 15,
"percentage_fee": 0.5,
"fx_markup": 0
},
"client_markup": {
"fixed_fee": 5,
"percentage_fee": 0,
"fx_markup": 0
},
"total_fees": 25
},
"recipient_amount": "975.00",
"recipient_currency": "USD",
"created_at": "2024-01-15T14:30:00Z"
}Tip: Use
POST /v1/virtual-accounts/{id}/payout/previewfirst to see fees before confirming.
See the Payouts Guide for detailed documentation.
Webhooks
Receive real-time notifications for virtual account events:
Virtual Account Created:
{
"event": "virtual_account.created",
"data": {
"event_id": "uuid",
"virtual_account_id": "va_123",
"status": "active"
}
}Deposit Received:
{
"event": "virtual_account.deposit_funds_received",
"data": {
"virtual_account_id": "va_123",
"amount": "1000.00",
"currency": "usdc",
"source": {
"payment_rail": "ach_push",
"sender_name": "Acme Corporation"
},
"created_at": "2024-01-15T14:30:00Z"
}
}See the Webhooks Guide for setup instructions.
Complete Flow Diagram
sequenceDiagram
participant User
participant Your App
participant Kira API
participant Blockchain
Note over Your App: Prerequisites: User created & verified
Your App->>Kira API: POST /v1/virtual-accounts
Kira API-->>Your App: Virtual Account + Deposit Instructions
Your App->>User: Share Bank Details
Note over User,Kira API: User sends payment
User->>Kira API: USD Transfer
Note over Kira API: Convert to USDC/USDT
Kira API->>Blockchain: Send crypto to Wallet
Blockchain-->>Kira API: Transaction Confirmed
Kira API->>Your App: Webhook: Deposit Notification
Your App->>Kira API: GET /v1/virtual-accounts/{id}/deposits
Kira API-->>Your App: Deposit History
Legacy API (Deprecated)
Deprecation Notice: The endpoint
POST /v1/users/{userId}/virtual-accountsis deprecated and will be removed in a future release. Please migrate toPOST /v1/virtual-accounts.
Migration Guide
Legacy (Deprecated):
POST /v1/users/{userId}/virtual-accounts
{
"type": "US_ACH",
"destination": {...}
}Current:
POST /v1/virtual-accounts
{
"user_id": "{userId}",
"type": "US_BANK",
"bank": "portage",
"destination": {...}
}Key Changes:
- Endpoint changed from
/v1/users/{userId}/virtual-accountsto/v1/virtual-accounts user_idis now in the request body, not the URL- Type changed from
US_ACHtoUS_BANK - New required
bankfield for US_BANK accounts - New status values:
pending,failed
For legacy API documentation, see Legacy Virtual Accounts.
Related Documentation
- Getting Started - Authentication setup
- User Management - Create and verify users
- Webhooks - Configure webhook endpoints
Updated 21 days ago
