<!--
Sitemap:
- [Welcome to Kakushi 隠し](/index): Kakushi is a private execution layer for institutions building on stablecoin rails.
- [What is Kakushi](/introduction/what-is-kakushi): Money is private.
- [Using Kakushi with AI](/introduction/using-kakushi-with-ai): Every page in these docs is available as plain markdown for use with language models.
- [Quickstart](/quickstart): This is the ten minute path.
- [Zones and the trust model](/concepts/zones-and-trust): A zone is a private blockchain only you can see inside, with a public chain's proofs underneath.
- [The portal](/concepts/the-portal): Money walks in as public USDC and becomes private the moment it crosses.
- [Accounts and custody](/concepts/accounts-and-custody): Your existing wallet address is already a Kakushi account. Nothing to deploy, nothing to enroll.
- [Bring your own address](/concepts/bring-your-own-address): A zone account is just an address, the one an auth key recovers to, with nothing deployed.
- [Virtual addresses](/concepts/virtual-addresses): Hand every customer their own address, the way a bank hands out virtual account numbers.
- [Private transfers](/concepts/private-transfers): Pay fifty thousand people and publish zero salaries.
- [Settlement and composability](/concepts/settlement-and-composability): Two institutions settle in real time without sharing a ledger or seeing each other's books.
- [Private deposits and withdrawals](/concepts/private-deposits-and-withdrawals): Soon, even the edges go dark.
- [Proofs and the verifier](/concepts/proofs-and-the-verifier): You cannot fake a balance, and you can prove you are solvent without showing a single customer.
- [Fees and gas](/concepts/fees-and-gas): Your users never hold ETH and never see gas. They pay in the dollars they are already sending.
- [Privacy and disclosure](/concepts/privacy-and-disclosure): The public sees nothing, you see everything, the regulator sees what the law entitles them to.
- [Zone policies](/concepts/zone-policies): Compliance is built into the zone. You configure your program; the substrate enforces it on every transfer.
- [Onboard a customer](/guides/onboard-a-customer): Two calls and a webhook, and your customer has a private on-chain account.
- [Accept deposits](/guides/accept-deposits): Anyone with funds on the host chain can pay into your zone, and it lands as a private balance for your user.
- [Make private transfers](/guides/private-transfers): One call moves money privately. One call pays a whole payroll.
- [Process withdrawals](/guides/withdrawals): Burn inside, release canonical USDC outside, in one call.
- [Settle between zones](/guides/settle-between-zones): Send money to another institution's zone like it is a withdrawal. It is interbank settlement.
- [Handle webhooks](/guides/webhooks): React to money moving. Do not poll for it.
- [Reconcile](/guides/reconcile): Two numbers that must always match. Assert it on a schedule.
- [Non-custodial integration](/guides/non-custodial-integration): The user signs on their device. You never hold the key, and you still cannot move their money.
- [Compliance and disclosure](/guides/compliance): You hold the whole record. Disclosure is an export, not a negotiation with the protocol.
- [SDK reference](/sdk-reference): The look-it-up layer.
- [Connect and EVM reference](/connect-and-evm-reference): The chain-level integration detail.
- [Run a zone](/run-a-zone): Most operators never run any infrastructure.
- [Protocol spec](/protocol-spec): The deep technical layer, for auditors and engineers integrating below the SDK.
- [Resources](/resources): See Key concepts for the working vocabulary, expanded throughout Core concepts.
-->

# Virtual addresses

If you have ever used a bank's virtual account numbers, you already understand this. A bank gives a business one real account and lets it generate a different account number for every customer or invoice, all funneling into the same place, so the business always knows who paid without asking. A virtual address is that, on-chain.

![Many virtual addresses funneling into one zone account](/images/concepts/virtual-addresses.svg)

You generate a fresh virtual address per payer, per invoice, per intent. Two things fall out of that for free. You get attribution: when money lands on `invoice_4471`'s address, you know exactly which invoice it was, with no reconciliation guesswork. And you get privacy: because each address is distinct, someone watching the host chain cannot tie all of a customer's deposits back to one identity, the same way virtual account numbers stop a counterparty from seeing your whole banking relationship.

```ts
import { privateKeyToAccount } from "viem/accounts";

// acme's account; the key lives in your secret store, the SDK never sees it
const acmeAccount = privateKeyToAccount(process.env.ACME_PRIVATE_KEY as `0x${string}`);

const { virtualAddress } = await kakushi.accounts.createVirtualAddress({
  account: acmeAccount,
  metadata: { reference: "invoice_4471", campaign: "march" },
});
// hand this address to the payer; the deposit that lands on it is self-attributing
```

Every deposit and every deposit webhook carries the `virtualAddress` and the `metadata` you attached when you claimed it, so matching a payment to its invoice needs no lookup table.

:::tip
Each virtual address is backed by a virtual forwarder, a tiny contract deployed lazily on the host chain the first time the address is funded. You can mint as many as you want without paying for them up front.
:::
