Documentation

Dedicated virtual wallets

A dedicated virtual wallet gives each customer their own on-chain deposit address per chain. When they send a supported stablecoin or token (USDC, USDT, DAI, EURC, and other assets registered on your chain's TokenRegistry), Videpay detects it, sweeps to your merchant balance, and notifies you, ideal for billing portals, memberships, and repeat invoicing. 'Send to this address every month', finally a sentence finance and engineering agree on.

Need machine-readable request/response bodies for your AI or codebase? Download this page as plain Markdown.

When should I use this?

  • Customers pay you repeatedly (subscriptions, utilities, memberships).
  • You want one permanent address per customer instead of per-invoice addresses.
  • Exchange or wallet users who prefer sending to a fixed address.

Why use Videpay?

  • Same address every time: customers can save it in their wallet.
  • Automatic sweep when deposits arrive (autoSweep, default true).
  • Five dedicated-virtual-wallet.* webhook events cover the full deposit lifecycle.
  • Deploy on one chain or all active merchant chains in a single request.

Utility billing portal

Each household gets a virtual wallet address in their billing portal. They send USDC or DAI monthly to the same address. Your system receives customer.dedicated-virtual-wallet.deposit-detected, then customer.dedicated-virtual-wallet.swept when funds reach your balance.

Before you start

  • Active customer record (not archived)
  • Merchant registered on-chain for the target chain(s)
  • Customer sends a TokenRegistry-supported asset for automatic sweep (same registry as checkout and settlement APIs)

Supported assets

Virtual wallets use the same on-chain TokenRegistry as deposit sessions and checkout, not a USDC-only path. When a transfer arrives, Videpay calls `getTokenInfo(tokenAddress)` on the wallet's registry. If `supported` is true, the token is swept to your merchant balance. If false, you receive customer.dedicated-virtual-wallet.unsupported-token-detected and recovery is queued automatically when `autoSweep` is true (default).

Supported vs unsupported

Supported, USDC, USDT, DAI, EURC, BUSD, cNGN, and any other asset your chain's TokenRegistry marks as supported (including native ETH/MATIC when enabled). Swept via `deposit-detected` → `swept` webhooks. Unsupported, random ERC-20s, scam tokens, or assets not in the registry. Moved to Videpay platform custody, not credited to your merchant balance. After `unsupported-token-recovered`, a recovery holding is created; release it to your registered `merchantAddress` via POST `/recovery-holdings/{id}/release`. Listen for `recovery-holding.created` and `recovery-holding.released`.

  1. Check `transfer.token.isSupported` in webhook payloads: false means the token is outside the registry.
  2. Supported deposits credit your merchant balance after sweep (same fee model as deposit sessions).
  3. Unsupported deposits are moved off the customer wallet to the platform recovery wallet: funds are not lost on-chain, but they are not in your settlement balance either.
  4. With `autoSweep: false`, transfers are held on the wallet until you sweep supported tokens or queue recovery for unsupported ones.

How virtual wallets work

  1. POST to deploy a wallet: Videpay queues on-chain deployment via factory contract.
  2. Customer sends a supported token to the returned address.
  3. Videpay detects the on-chain transfer → deposit-detected webhook.
  4. Auto-sweep moves the token to merchant balance → swept webhook.
  5. Unsupported tokens trigger unsupported-token-detected; recovery runs automatically when autoSweep is true.

Dashboard features

Dashboard → Customers → Virtual wallets

From a customer detail page, deploy wallets per chain, toggle autoSweep, and view transfer history. Supported assets sweep like settlement deposits; unsupported assets route to platform custody for release. Every action maps to the API endpoints below.

  1. Deploy wallet: choose chain or deploy on all active chains.
  2. Copy deposit address for the customer.
  3. Transfer history shows detected, swept, and failed transfers.
  4. Toggle autoSweep to pause automatic sweeping.

Create and list virtual wallets

FieldTypeRequiredDescription
businessIduuidNoTarget business. Omit when your API key is scoped to one business.
chainstringNoDeploy on a specific chain (e.g. base). Omit to deploy on all active merchant chains.
autoSweepbooleanNoAutomatically sweep supported-token deposits to merchant balance. Defaults to true. Unsupported tokens are moved to Videpay platform custody (not your merchant wallet).
POST/customers/:cus_3b7e9f1a-2c4d-5e6f-7a8b-9c0d1e2f3a4b/dedicated-virtual-wallets

Deploy a persistent deposit address. Omit chain to deploy on all active merchant chains. Emits customer.dedicated-virtual-wallet.created when deployment completes.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "chain": "base",03  "autoSweep": true04}
GET/customers/:cus_3b7e9f1a-2c4d-5e6f-7a8b-9c0d1e2f3a4b/dedicated-virtual-wallets

List all virtual wallets for a customer.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json
PATCH/customers/:cus_3b7e9f1a-2c4d-5e6f-7a8b-9c0d1e2f3a4b/dedicated-virtual-wallets/dvw_5c8d2e1f-9a3b-4c7d-8e6f-1a2b3c4d5e6f

Update wallet settings (e.g. toggle autoSweep).

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "autoSweep": false03}

List transfers

FieldTypeRequiredDescription
businessIduuidNoTarget business. Omit when your API key is scoped to one business.
offset / limitintegerNoTransfer list pagination. limit 1–100, default 20.
GET/customers/:cus_3b7e9f1a-2c4d-5e6f-7a8b-9c0d1e2f3a4b/dedicated-virtual-wallets/dvw_5c8d2e1f-9a3b-4c7d-8e6f-1a2b3c4d5e6f/transfers?limit=20

List deposits detected on a virtual wallet with pagination.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Virtual wallet object reference

FieldTypeRequiredDescription
id / walletIduuid / bytes32NoVidepay record ID and on-chain wallet identifier.
addressaddressNoDeposit address customers send supported tokens to.
chainobjectNoChain id and name (e.g. base-sepolia).
statusenumNodeploying, deployed, or failed.
autoSweepbooleanNoWhether supported-token deposits are automatically swept to the merchant settlement wallet. Unsupported tokens are automatically recovered when true.
deployTxHash / deployedAtstring / datetimeNoOn-chain deployment transaction details.

Release unsupported tokens from custody

When an unsupported token is recovered from a virtual wallet or deposit session, Videpay creates a recovery holding ledger entry. Release sends the exact recorded amount from platform custody to your registered `merchantAddress` on that chain: destination is fixed; you cannot redirect to an arbitrary wallet. Dashboard sessions require step-up auth (PIN, OTP, or 2FA) on live; secret API key calls skip step-up.

FieldTypeRequiredDescription
sourceenumNovirtual_wallet_transfer or deposit_session: links back to the originating transfer or session via sourceId.
statusenumNoin_custody → release_queued → released (or failed).
amount.rawstringNoExact token amount released: must match custody record.
recoveryTxHash / releaseTxHashstringNoOn-chain custody move and merchant release transactions.
authorizationobjectNoDashboard only. Step-up confirmation (PIN, OTP, or 2FA) when a logged-in owner acts in the browser. Omit entirely for secret API key integrations: the server skips this check when you authenticate with x-api-key. On sandbox, any emailed OTP code is `000000` (six zeroes). It's giving dev mode. Live sends a real code.
authorization.pinstringNoTransaction PIN when enabled.
authorization.otpChallengeIduuidNoOTP challenge from a prior dashboard auth step. On sandbox, enter `000000` when verifying the emailed code.
authorization.twoFactorCodestringNoTOTP code when 2FA is enabled.
GET/recovery-holdings?source=VIRTUAL_WALLET_TRANSFER&sourceId=dvwt_1a2b3c4d&status=in_custody

List recovery holdings for your business. Filter by source, sourceId, status, or chain.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json
GET/recovery-holdings/rh_6d9e2f3a-4b5c-4d7e-8f9a-0b1c2d3e4f5a

Retrieve a single recovery holding.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json
POST/recovery-holdings/rh_6d9e2f3a-4b5c-4d7e-8f9a-0b1c2d3e4f5a/release

Queue release to your merchantAddress. Emits recovery-holding.release-queued, then recovery-holding.released on success.

Headers

headers
01x-api-key: sk_AbCdEfGhIj_XyZ1234567890abcdefghijklmnopqrstuvwxyz01234502Content-Type: application/json

Request body

request.json
01{02  "chain": "base"03}

Transfer object reference

FieldTypeRequiredDescription
statusenumNodetected, held, sweep_queued, swept, recovery_queued, recovered, or failed.
token.isSupportedbooleanNotrue when the token is supported by your chain's TokenRegistry (swept to merchant). false triggers unsupported-token-detected and recovery.
amount.raw / amount.formattedstringNoTransfer amount in raw and human units.
sweepRef / settlementTxHashstringNoPresent after sweep completes.

Webhooks you'll receive

Register a webhook endpoint and verify the X-Protocol-Signature header on every delivery before fulfilling orders or updating your database.

Webhookcustomer.dedicated-virtual-wallet.created

Sent when a dedicated virtual wallet is deployed for a customer.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: customer.dedicated-virtual-wallet.created04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookcustomer.dedicated-virtual-wallet.deposit-detected

Sent when a TokenRegistry-supported token arrives at a customer virtual wallet.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: customer.dedicated-virtual-wallet.deposit-detected04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookcustomer.dedicated-virtual-wallet.swept

Sent when a detected deposit is swept to your merchant balance.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: customer.dedicated-virtual-wallet.swept04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookcustomer.dedicated-virtual-wallet.unsupported-token-detected

Sent when a token outside the chain TokenRegistry arrives at a virtual wallet address. Recovery to Videpay platform custody is queued automatically when autoSweep is true.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: customer.dedicated-virtual-wallet.unsupported-token-detected04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookcustomer.dedicated-virtual-wallet.unsupported-token-recovered

Sent when an unsupported token is moved from a virtual wallet into Videpay platform custody (not the merchant settlement wallet).

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: customer.dedicated-virtual-wallet.unsupported-token-recovered04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookrecovery-holding.created

Sent when an unsupported token is moved into platform custody and a releaseable holding is recorded.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: recovery-holding.created04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...
Webhookrecovery-holding.released

Sent when a recovery holding is released to the merchant registered address.

Delivery headers

webhook-headers
01Content-Type: application/json02User-Agent: Protocol-Webhooks/1.003X-Protocol-Event: recovery-holding.released04X-Protocol-Delivery: wev_1a2b3c4d-5e6f-7890-abcd-ef123456789005X-Protocol-Business-Id: a1b2c3d4-e5f6-7890-abcd-ef123456789006X-Protocol-Attempt: 107X-Protocol-Signature: sha256=abc123def456...