Pay with Tempo
This page shows how to pay an Uno storage quote with a Tempo wallet. It covers an Agent capacity quote and an App block purchase. It is for developers and AI agents that hold a Tempo wallet and an Uno account. The page is self-contained.
You pay a quote once and then read the receipt. Uno never takes payment inside a write. A write that needs storage is refused, and you buy storage in a separate step.
Before you start
- Install the Tempo CLI and sign in to your wallet with the steps in the Tempo docs: Tempo CLI and
tempo wallet. Uno does not repeat them. The Tempo docs saytempo wallet whoamireportsready=truewhen the wallet can pay withtempo request. - Have an Uno account. See Install and accounts.
- Pin the account. Set
UNO_ACCOUNTandUNO_EXPECT_ACCOUNTto the account UUID, or pass--accountand--expect-accounton each command. See Agent mode and exit codes. - Get your user's approval for the exact amount before you pay. A printed command is not approval.
Quote terms
| Term | Value |
|---|---|
| Price | USD 0.50 per GB-month, charged in the token that the quote names |
| Capacity | Total storage including stored history, from 100 MB to 10 TB, in exact 100 MB steps |
| Units | MB, GB and TB are decimal |
| Month | 30 days |
| Quote end | The earlier of 30 minutes after creation and the plan's next expiry or restore cutoff |
| Refunds | No cash refund. A late, stale or duplicate payment becomes storage time |
These numbers can change. uno kit quota and AccountService.GetCapabilities hold the live values. Read the amount and token from the quote. The CLI never computes a price.
Agent purchases can be off
Purchases stay off for a network until its offers open. While they are off, a quote shows no price and pays nothing. The CLI reports this with two exit codes:
| Exit | Meaning | What to do |
|---|---|---|
| 21 | Offers are off, or the quote does not match your request, account or owner. The text says "not offered" or "Do not pay" | Stop. Run uno kit quota later |
| 24 | The backend has no capacity purchases yet | Stop |
Pay an Agent capacity quote
An Agent account buys total capacity for whole months. Do not use --blocks, --renew or --subscribe on an Agent account.
1. Preview
uno kit pay --capacity 1GB --months 1 --dry-run --format jsonThe preview sends nothing.
2. Request the quote
uno kit pay --capacity 1GB --months 1 --operation buy-1 --format jsonThis command never pays. It exits 15 and returns the quote in error.details.payment:
| Field | Meaning |
|---|---|
purchase_id | The purchase |
quote_id | The frozen quote |
amount | Amount in whole tokens |
token | Token contract address |
chain | Chain ID |
capacity_bytes | Total capacity quoted |
months | Months quoted |
usd_per_gb_month | Unit price |
expires_at | Quote end, in Unix seconds |
no_refund | The no-refund statement |
pay_url | The backend payment link |
pay_command | The Tempo command to run |
next_command holds the command to run after payment. Compare amount, token, chain, capacity_bytes and months with what your user approved. Stop if any term differs.
3. Run the printed command
The CLI prints this command. Run it as printed. Do not assemble one.
tempo request --network testnet --payment-intent charge \
--max-spend 0.5 --payment-token 0xPUBLIC_TEST_TOKEN \
-X POST -H 'x-uno-expect-account: <account-uuid>' \
'https://mpp.uno.fun/v1/purchases/PUBLIC_TEST_LINK/pay'The values above are placeholders. The real command uses --network testnet or --network mainnet, the quoted --max-spend, the quoted --payment-token, your account UUID and the exact pay_url. tempo request pays the link and settles in one step.
4. Read the receipt
uno kit purchase <purchase_id> --format jsonThis read sends no payment. data.owner.purchase.status is PURCHASE_STATUS_SETTLED when the purchase settled. Do not report storage as bought before that status. A settled result holds:
| Field | Meaning |
|---|---|
classification | quoted, stale, late or extra |
applied_amount | Amount applied |
capacity_bytes | Capacity |
starts_at, expires_at | Term dates |
payment_tx | The paying transaction |
After settlement, retry the write that needed storage with its original operation and identical inputs.
Exit codes of the quote command
| Exit | State | What to do |
|---|---|---|
| 15 | Unpaid quote | Pay the printed command |
| 14 | Payment in flight | Wait, then run uno kit purchase <purchase_id>. Never pay again |
| 0 | Settled | Read results |
| 9 | Failed, expired or old-network purchase | Read it with uno kit purchase. Start a new operation to buy again |
| 21, 24 | Not offered or unavailable | See Agent purchases can be off |
If the reply is lost, rerun the identical uno kit pay command with the same --operation. It replays the quote on the same server key or reads the purchase. It never pays. For lost payments, see Recover an uncertain payment.
Pay as a separate payer
The owner can send the payer only the pay_url. The link names the beneficiary account and grants payment only. It gives no owner access. The payer sees terms, status and receipts, and never usage or Kit names. The payer needs no Uno account and sends no Bearer token. The owner stays the acting account whoever pays.
Ask the owner for their account UUID with the pay_url. Pin it with the x-uno-expect-account header:
tempo request --network testnet --payment-intent charge \
--max-spend 0.5 --payment-token 0xPUBLIC_TEST_TOKEN \
-X POST -H 'x-uno-expect-account: <owner-account-uuid>' \
'https://mpp.uno.fun/v1/purchases/PUBLIC_TEST_LINK/pay'Account pin and ACCOUNT_MISMATCH
The server checks the pin against the link's beneficiary. A wrong pin is refused with HTTP 400 failed_precondition and reason ACCOUNT_MISMATCH before any charge. Stop and check the link.
Pay with another wallet
tempo request uses the wallet you logged in to. To use a different Tempo wallet on an App purchase, retry the saved purchase with a credential file:
uno kit pay --blocks 1 --renew --yes --payment-file <file> --operation purchase-1The file must have mode 0600. Only the file's own mode counts. It must hold one serialized Authorization: Payment credential value that starts with Payment . Keep the file outside any upload folder. Keep the original --blocks, --renew or --no-renew, and --operation on the retry.
Pay an App block purchase
App accounts buy storage in blocks. Every one-time block purchase needs --renew to start or renew a term, or --no-renew to add blocks to an active term. Omitting both exits 2 before any request.
uno kit pay --blocks 1 --renew --dry-run --format json
uno kit pay --blocks 1 --renew --yes --operation purchase-1The second command exits 15 and saves a private challenge file and a private request file. Both have mode 0600. It prints a runnable tempo request command. The CLI doc shows this form:
tempo request --network testnet --payment-intent charge --max-spend 1 \
-X POST -H 'connect-protocol-version: 1' -H 'content-type: application/json' \
--data '@/absolute/path/kit-payment-challenge.request.json' \
'https://kit.uno.fun/rpc/uno.kit.v1.AccountService/Pay'Replace the request-file path with the exact path that the CLI printed. Run the command as printed. For a quoted token contract, it also pins --payment-token. Moderato uses --network testnet. Tempo mainnet uses --network mainnet. Review the chain, token, amount and spend cap first.
tempo request settles in one step, so no --payment-file retry is needed on this path. Then check uno kit quota and retry the original write with its saved operation. After an uncertain payment, check quota before you pay again.
In error.details.payment, an App quote holds amount, token, chain, blocks and pay_command. uno kit capabilities lists the block limit (payment.blocks) and the price per block.
The memo rule
A Tempo charge can carry a memo in methodDetails.memo. The Tempo charge draft says that when a memo is present, the client must use transferWithMemo instead of transfer (draft-tempo-charge-00). Uno refuses a plain transfer that has no memo. tempo request follows the rule for you. Follow it yourself only when you pay with another tool.
Pay with a raw HTTP retry
Another wallet can send the Payment retry itself. The retry targets the same URL as the quote request. It carries no Bearer token and repeats the same body and Idempotency-Key.
POST /v1/purchases HTTP/1.1
Host: mpp.uno.fun
Authorization: Payment PUBLIC_TEST_PAYMENT_NOT_A_CREDENTIAL
Content-Type: application/json
Idempotency-Key: public-test-buy-1
{"capacity_bytes":"1000000000","months_to_add":"1"}The purchase and quote come from the verified challenge, not from your body. A success is HTTP 200 with a Payment-Receipt header. data.purchase.status is PURCHASE_STATUS_SETTLED, and data.purchase.results holds the outcome. A payer that holds only the pay_url sends the same kind of Payment retry to POST /v1/purchases/{link}/pay. A POST there without a credential returns the 402 challenge and moves no money.
For the quote request, see Buy Agent storage over HTTP.
Pay from an MCP client
The hosted MCP server is at https://mcp.uno.fun/mcp. It requires OAuth sign-in. It answers an unauthenticated request with HTTP 401.
A write or quote that needs payment returns an error result with structuredContent.payment_required. For an Agent plan, call uno_storage_purchase. For an App block purchase, call uno_storage_buy.
- An Agent
payment_requiredholdspurchase_id,quote_expires_at,pay_url,amount,currency,chain_id,token,amount_base_unitsandpay_command. Runpay_command, then calluno_purchase_lookupwithpurchase_id. - An App
payment_requiredholdschallenge,pay_url,amount,memo,chain_idandpay_commands. Runpay_commands[0]. With another wallet, send the transfer with the memo, then calluno_payment_settle. uno_payment_settletakes onlychallengeandtx_hash. It submits proof of a payment and never sends funds.- Do not put a payment credential in
_meta. The server does not support it. - Retry the original write with the same arguments and
idempotency_key.
Subscription (App accounts only)
This path depends on the offer. It is for App accounts only.
uno kit pay --subscribe --dry-run
uno kit pay --subscribe
uno kit pay --cancel-subscription <subscription-id>--subscribe starts a Tempo subscription at USD 9.99 every 30 days. Each paid term adds 50 GB of paid capacity. --dry-run shows the terms. In a script, pass --yes after you review them. --cancel-subscription stops future charges. Paid capacity stays until the current term ends.
Related pages
- How Uno uses MPP
- Pay with Stripe Link
- Recover an uncertain payment
- Agent mode and exit codes
- Command reference
- API reference