Developers

Cross-Chain Wallet Infrastructure: What It Means for Your Business and How to Integrate It

·8 min read
Updated
wallet-apidevelopersapibusinessinfrastructureintegration

What this is

Minisend's Wallet API issues a real onchain address for any reference you supply, and you never touch a private key. One POST call with a user ID returns an address. Call it again with the same ID and you get the same address back. Your users get somewhere to receive stablecoins; you get no key custody problem.

Why businesses end up needing this

The moment a product accepts stablecoins from more than one customer, a question appears: where does each customer's money land? There are three usual answers and two of them are bad.

One shared address for everyone. Cheap to build, painful to operate. You reconcile by amount and timing, which breaks the first time two customers send the same amount within the same minute.

Run your own wallet infrastructure. Correct, and expensive. Now you are storing key material, thinking about HSMs, rotation, backup, insider risk, and the regulatory posture of holding customer keys. This is a real engineering org's worth of work, and it is not your product.

Per-user addresses from an API. You get clean attribution without becoming a custodian. Funds arriving at an address are unambiguously that user's, because nothing else can arrive there.

The Wallet API is the third option.

What changes in your architecture

Without per-user addressesWith per-user addresses
Reconcile deposits by amount and timestampDeposit is attributed by the address it arrived at
Ambiguity when two users send the same amountNo ambiguity, ever
You store or broker private keysNo keys, no seed phrases, on your side or your users'
Adding a chain means new key handlingActivate the chain, reuse the same user reference
Onboarding a user requires wallet UXAddress exists the moment the user record does

The practical effect is that "which user paid?" stops being a heuristic and becomes a lookup.

What you can build with it

  • Deposit addresses inside your app. Every user has a funding address on day one, no wallet connect flow required.
  • Per-customer accounts. A B2B product can give each business customer a persistent address for topping up a balance.
  • Per-order addresses. Issue an address per invoice or order and reconciliation becomes exact by construction.
  • Onchain features without being a wallet company. Add stablecoin receiving to an existing product without shipping key management.

How to integrate

Three steps. The whole thing is one endpoint.

1. Activate a chain

In the dashboard, go to Wallets and activate the chain you want to issue addresses on. Each activated chain is backed by a master wallet, which is the container your issued addresses belong to.

Chain availability depends on your plan:

PlanMonthlyAddresses includedBeyond the allowanceChains active at once
Free$0100 per monthBlocked1 (Base)
Growth$1992,000 per month$0.50 per address, billed not blockedAny 3 of 6
EnterpriseContractedUnlimitedn/aAll 6

The six eligible chains are Base, Ethereum, Polygon, Arbitrum, Optimism, and Avalanche. Two details are worth reading twice, because both catch teams out at renewal:

  • The allowance is per calendar month, counted on addresses created in that month. It is not a lifetime total and it does not accumulate. Issuing 2,000 addresses in March leaves you 2,000 again in April.
  • On Growth, "any 3 of 6" is a count, not a fixed list. All six are eligible; you choose which three are active and you can change the selection later.

2. Create an API key

Wallet API keys carry the wsk_live_ prefix and are shown once, so store the value immediately. Keep it in an environment variable, never in client code, and use a separate key per environment so you can rotate one without disturbing the others.

3. Create a wallet

bash
curl -X POST https://merchant.minisend.xyz/api/v1/wallets \
  -H "Authorization: Bearer wsk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"walletRef": "user-9214"}'

walletRef is your own identifier: a user ID, a customer ID, an order number. The response comes back with the wallet ID, your reference, the onchain address, the chain, status, mode, an optional metadata object, and a creation timestamp.

Store the returned address against your user record. That is the integration.

The two properties worth designing around

It is idempotent. Calling the endpoint again with the same walletRef returns the existing wallet rather than creating a second one. This means you do not need to track whether you have already provisioned a user. Call it on first login, call it on every login, call it from a retry after a timeout: same address, no duplicates. It also means a failed request is safe to retry blindly.

One reference spans chains. The same walletRef can hold separate addresses on Base, Arbitrum, and the other activated chains. Your internal identity stays one row while the onchain surface grows.

Custody: what you are and are not taking on

Creating an address through this API does not hand you or your end users a private key or a seed phrase to store. Users never receive keys to manage, which removes the most common support burden in consumer crypto products and keeps you out of the business of protecting key material.

Be deliberate about how you describe this to your users. They have an address that receives funds; they do not have a self-custodial wallet they can export.

One thing to plan for: there is no sandbox

Keys are live-only. Every address you create is a real address on mainnet. There is no test mode that simulates the flow with fake funds.

That shapes how you test:

  • Use a dedicated walletRef namespace for testing, something like test-, so test records are trivially filterable later.
  • Run the real flow with a trivial amount. An off-ramp order clears from 0.50 USDC, so an end-to-end test costs cents.
  • Keep a separate API key for staging and rotate it independently.

Pairing wallets with payouts

Wallet addresses are most useful next to the off-ramp. A user funds their address with USDC or USDT, and you convert that balance to local currency through the off-ramp API, settling to M-Pesa, a Buy Goods till, a Paybill number, mobile money, or a bank account across Kenya, Nigeria, Ghana, and Uganda. The off-ramp is non-custodial: USDC moves from the wallet directly into settlement, and Minisend delivers the local payout.

Together that is a full loop inside your own product: receive stablecoins, hold them, pay out in shillings, naira, cedi, or Ugandan shillings.

If you settle in USDC, read this part

Wallets are one piece. Businesses taking payment through hosted checkout can also choose to settle in USDC rather than local currency, keeping the payment in their Minisend balance where it earns while it waits, and nominating a destination chain: Base, Arbitrum, Avalanche, Ethereum, Optimism, or Polygon. Base is the default and forwards nothing. Any other choice is forwarded automatically after each payment, with the business absorbing that network's protocol fee.

Two behaviours there cannot be inferred from the event names, and both have cost integrators real debugging time:

  • checkout.completed fires before any cross-chain forwarding is attempted. It confirms the payment, not the arrival on your destination chain.
  • A failed forward emits no webhook. Silence is not a signal. Read forward.status on the session. A failed forward means the funds are still sitting on Base, not that they are lost.

Rate limits and onboarding

The default API limit is 60 requests per minute per IP, and support can raise it. Going live with payouts requires KYB: incorporation documents, founder and director details, and proof of address for both the business and the director dated within the last three months. You get an acknowledgement within one business day and most reviews finish within two.

Webhooks are signed with HMAC-SHA256 over the raw request body, retried five times with exponential backoff, and logged in the dashboard with their delivery history. API keys are stored as SHA-256 hashes and compared in constant time, so a key is shown once and cannot be recovered afterwards.

Get started

The full reference lives at docs.minisend.xyz. If you are integrating with a coding agent, point it at the official skill, @minisend/skill, documented at docs.minisend.xyz/ai-agent-skill, rather than letting it infer the contract from prose.

To discuss volume terms or activate off-ramp access, email info@minisend.xyz or see Minisend for business.

Frequently asked questions

What does the Minisend Wallet API do?
It issues a real onchain address for any reference you supply, such as a user ID or an order number, through a single POST to /api/v1/wallets. Your application gets a dedicated deposit address per user without managing wallet infrastructure or private keys.
Do I have to hold private keys or seed phrases?
No. Creating an address through the Wallet API does not hand you or your end users a private key or seed phrase to store. Users never receive keys to manage, so key custody never becomes your problem.
How do I create a wallet address for a user?
Send a POST to https://merchant.minisend.xyz/api/v1/wallets with an Authorization: Bearer header carrying your wsk_live_ key and a JSON body containing walletRef set to your own user identifier. The response returns the wallet ID, reference, onchain address, chain, status, mode, metadata, and creation time.
What happens if I call the wallet endpoint twice for the same user?
Nothing duplicates. The endpoint is idempotent: the same walletRef returns the existing wallet and the same address. That makes retries safe and means you do not need to track whether a user was already provisioned.
Which chains can I issue wallet addresses on?
Six chains are eligible: Base, Ethereum, Polygon, Arbitrum, Optimism, and Avalanche. The Free plan can have one active at a time and it must be Base. Growth can have any three of the six active at once and the selection can be changed. Enterprise has all six. One walletRef can hold a separate address on each activated chain.
Is there a sandbox for testing the Wallet API?
No. Keys are live-only and every address created is a real mainnet address. Test by running the real flow with a trivial amount, using a dedicated walletRef namespace for test records and a separate API key you can rotate independently.
When does the checkout.completed webhook fire for USDC settlement?
Before any cross-chain forwarding is attempted. It confirms that the payment succeeded, not that funds arrived on your nominated destination chain. A failed forward emits no webhook at all, so read forward.status on the session rather than treating silence as success. Funds from a failed forward remain on Base.
Can users cash the balance out to local currency?
Yes. Pair the Wallet API with the off-ramp API to convert a balance to KES, NGN, GHS, or UGX, settling to M-Pesa, a Buy Goods till, a Paybill number, mobile money, or a bank account. The off-ramp is non-custodial: USDC moves from the wallet straight into settlement.

Keep Reading

Minisend: Convert USDC to local currency instantlyLaunch App
Copied to clipboard