Create a Wallet

Set up a merchant store wallet on the ledger — with automatic balance management, multi-currency support, and full visibility into every payment your merchant receives.

Audience: Developers, Integration Engineers · Read time: 4 min

To understand the platform, we'll start as a developer at a bank or fintech offering payment services to merchants.

Your client is a coffee chain with locations across the city that wants to accept payments from customers using any method — bank transfers, QR codes, mobile wallets. Traditionally, you'd set up separate merchant accounts in your core banking system for each store, reconcile transactions across multiple processors every night, and build custom code to figure out which store received which payment.

With Minka, you create a wallet for each merchant location on the ledger. The wallet tracks every incoming and outgoing payment automatically, maintains a real-time balance, and works with every payment network connected to the ledger. No reconciliation scripts. No separate integrations per payment rail. One wallet per store, one balance, every network.

This guide uses a bank onboarding a merchant store as the example. The same model applies if you're a payment network offering services to bank participants — each bank becomes a wallet on the ledger, and the network orchestrates settlement between them. The primitives are identical; only the scale changes.

This guide walks you through creating a store wallet for a Great Coffee location — the same wallet you'll use in Collect a Payment to start receiving QR payments and in Send a Payment to send a payout.

What is a wallet?

A wallet is a balance container in the ledger. It represents anything that holds value — a merchant account, a settlement pool, an escrow position, a loan, even an invoice waiting to be paid. Every time money moves through an intent, the ledger debits the source wallet and credits the target wallet atomically. Both balances update at the same instant, or neither does.

As a bank, you could route merchant payments directly to their existing bank accounts. But we recommend creating a dedicated wallet for each merchant on the ledger instead. A wallet gives you a real-time position for every merchant — every sale, refund, and payout reflected instantly — without coupling your core banking system to individual transaction flows. You settle to the merchant's bank account on your own schedule, while the wallet keeps a precise record of what's owed. See About Wallets for a deeper look at how wallets work, how addressing and resolution operate, and why they make the ledger a programmable payment switch.

How wallet addresses work

Every wallet has a handle — its unique address on the ledger. Handles follow a structured format:

identifier@domain

For our coffee shop, the handle will be store1@greatcoffee.co. The identifier is store1 — the specific store location. The domain is greatcoffee.co — the business that owns it.

When a wallet represents a specific account type — like a savings account at a bank — the handle includes a schema prefix: svgs:42424242@mybank.co. The schema tells the ledger what kind of account this address represents. For merchant wallets like ours, the simple form is sufficient.

This addressing scheme is what makes the ledger powerful. When a customer pays store1@greatcoffee.co, the ledger knows exactly where to route the funds — regardless of which payment network the customer used. And because the wallet is a virtual account on the ledger rather than a direct mapping to a bank account, you have full visibility into the merchant's position at all times. See About Wallets for a deeper look at addressing, resolution hierarchies, and schema prefixes like svgs: or chk: for typed accounts.

Wallet handles contain @ and . characters. When these appear in URL paths (like GET /v2/wallets/store1@greatcoffee.co), the @ is technically a reserved character that should be percent-encoded as %40. In practice, curl and browsers handle this transparently — the examples in this guide use the readable form.

Create the wallet

Register the wallet on the ledger

curl -X POST "https://{ledger-host}/v2/wallets" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer {your-token}" \
  -H "x-ledger: {your-ledger}" \
  -d '{
    "data": {
      "handle": "store1@greatcoffee.co",
      "schema": "merchant-wallet",
      "custom": {
        "name": "GREAT COFFEE UNICENTRO",
        "city": "BOGOTA",
        "postal": "110111",
        "type": "store"
      }
    }
  }'
POST /v2/wallets

Two fields beyond the handle deserve attention:

schema references a schema record registered on the ledger — in this case, merchant-wallet. A schema defines which custom fields are required for this type of wallet. When you set schema: "merchant-wallet", the ledger validates the entire wallet payload against the schema's rules before accepting the creation. If a required field is missing or has the wrong type, the request is rejected.

custom carries the store data that the merchant-wallet schema requires. For a store wallet, the minimum fields are:

FieldDescription
nameThe store's trading name — shown to customers when they pay. Maximum 25 characters.
cityThe city where this store operates — used for display and geographic routing. Maximum 15 characters.
postalPostal or ZIP code of the store location.
typeSet to store for a physical location. The parent merchant wallet (with type: merchant) holds the full business profile — tax ID, settlement account, acquirer code — and store wallets inherit those fields automatically.

Store wallets are lean by design. The business-level fields — tax ID, country, tax regime, settlement account — live on the parent merchant wallet (main@greatcoffee.co). When a bridge generates a QR code for this store, it reads the store wallet for the name and city, then walks up to the merchant wallet for everything else. Changing the settlement account means updating one merchant wallet, not every store. See Onboard a Merchant for the full hierarchy setup.

The handle is permanent — choose something meaningful. For merchants, the pattern location@company.domain makes it easy to identify wallets across multiple stores: store1@greatcoffee.co, store2@greatcoffee.co, warehouse@greatcoffee.co.

Verify the wallet was created

Query the wallet to confirm it's live:

curl "https://{ledger-host}/v2/wallets/store1@greatcoffee.co" \
  -H "Authorization: Bearer {your-token}" \
  -H "x-ledger: {your-ledger}"
GET /v2/wallets/store1@greatcoffee.co

The wallet is live. The merchant-wallet schema confirmed all required fields are present, the store identity is stored on the ledger, and the balance starts at zero across every currency. Ready to receive its first payment.

Check the balance

Confirm the wallet's starting balance:

curl "https://{ledger-host}/v2/wallets/store1@greatcoffee.co/balances" \
  -H "Authorization: Bearer {your-token}" \
  -H "x-ledger: {your-ledger}"
GET /v2/wallets/store1@greatcoffee.co/balances

A brand new wallet returns an empty balance list — no money has moved yet. Once payments start flowing, each currency appears with its current balance, updated in real time after every settled intent.

What you just set up

With a single wallet creation, the Great Coffee Unicentro store now has:

A real-time balance. Every payment that arrives at store1@greatcoffee.co updates the balance instantly. No batch processing, no overnight reconciliation.

Multi-currency support. A single wallet holds balances in every currency configured on the ledger. If the merchant starts accepting a second currency tomorrow, the same wallet handles it.

Atomic settlement. When a customer pays, the ledger debits the customer's wallet and credits store1@greatcoffee.co in a single atomic operation. Both balances update together, or neither does.

One address, every network. Whether the customer pays through a bank transfer, a QR code scan, a mobile wallet, or a card — the payment arrives at store1@greatcoffee.co. The ledger handles all the routing, protocol translation, and settlement coordination behind the scenes.

Native and bridge wallets

The wallet you just created is a native wallet — its balance is fully managed by the ledger. This is the simplest kind, perfect for merchant accounts, fee pools, escrow, and any case where the ledger is the source of truth.

When you need to connect a wallet to an external system — like a bank's core banking platform — you assign a bridge. A bridge wallet coordinates every balance change with the external system using a two-phase commit: both the ledger and the bank must agree before any balance moves. Settlement wallets (like svgs:4242@bank.co) are bridge wallets — they represent real bank accounts linked to the ACH bridge.

Wallet typeBalance managed byBest for
NativeLedger onlyMerchant accounts, fee pools, escrow, internal accounts
BridgeLedger + external systemBank accounts, card networks, mobile money platforms

What's next

Now that Store 1 has a wallet, the next two guides complete the picture:

Collect a Payment — Register a QR code anchor for store1@greatcoffee.co so customers can scan and pay. The bridge reads the merchant profile, generates the network-specific payload, and the ledger routes the payment automatically.

Send a Payment — Send funds from the hub treasury to a settlement account. One API call, one format — whether the destination is at the same bank or across the country.

For a deeper look at how addressing, resolution hierarchies, and business rules work, see About Wallets.

On this page