ZZanoraDocs

Core concepts

How to write an amount, how prices and fees are calculated, and why a balance is always calculated from the ledger and never stored.

Amounts are strings of minor units

Every amount that crosses the API is a string of integer minor units, meaning cents for USD:

You meanYou send
$1.00"100"
$0.05"5"
$250.00"25000"
JSON
{ "priceMinor": "100", "amountMinor": "5000", "dailyBudgetMinor": "50000" }

A number is an error, not a guess

"priceMinor": 100 (a JSON number) is rejected with 400 VALIDATION_FAILED. Floats can't represent every cent exactly, and a value that's silently rounded is how money goes missing. Keep amounts as strings in your code too. In TypeScript, use bigint when you need to do arithmetic.

Every response uses the same format: {"balanceMinor":"4900","availableMinor":"4900","currency":"USD"}. The ledger's currency is USD.

Prices in seller code

When you declare a price in @zanora/middleware-mcp, you can write it in either of two unambiguous forms:

FieldExampleMeaning
price"$1.00"dollars, with the $ sign. Parsed as a string, never as a float
priceMinor"100"cents

price: "100" is refused, because it could mean $100 or $1.00.

Prices in policies

Spending policies are the one place that uses dollars: price > 5 means more than $5.00. Policies are written by people, and price > 500 to mean $5 would be a trap.

Fees

Zanora takes a platform fee on each paid call, 3% by default. The seller gets the rest:

Buyer paysSeller receivesPlatform fee
"100" ($1.00)"97""3"
"50" ($0.50)"49""1"
"10" ($0.10)"10""0"

The fee is rounded down to the cent, so any rounding goes to the seller. Fee plus net always equals the price exactly. The console's seller screens show the current fee.

The ledger

  • Append-only. Entries are never edited or deleted. A refund is a new credit that offsets the original debit, so your history shows both.
  • Double-entry. Every movement is a set of entries that sum to zero, so money is never created or lost between wallets.
  • Balances are calculated. GET /v1/wallets/:id/balance adds up the ledger every time. availableMinor is the balance minus anything on hold, such as a payment that is being authorized.
  • No personal data. Ledger entries carry opaque ids only. To find out what a charge bought, look at the receipt.

Rails: how money gets in and out

RailDirectionNotes
cardina card top-up. It credits when the card network confirms
achina bank debit
usdc_basein and outUSDC on Base. Deposits are credited 1:1 while USDC is within ±0.5% of $1; outside that band they are held, not credited at a guessed rate
bank_transferoutseller payouts by ACH, wire or SEPA

Which rails exist depends on the deployment. Ask rather than assume: GET /v1/rail/providers lists what the gateway can do. See Funding a wallet and Payouts.