Skip to content
Uno Docs

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 say tempo wallet whoami reports ready=true when the wallet can pay with tempo request.
  • Have an Uno account. See Install and accounts.
  • Pin the account. Set UNO_ACCOUNT and UNO_EXPECT_ACCOUNT to the account UUID, or pass --account and --expect-account on 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

TermValue
PriceUSD 0.50 per GB-month, charged in the token that the quote names
CapacityTotal storage including stored history, from 100 MB to 10 TB, in exact 100 MB steps
UnitsMB, GB and TB are decimal
Month30 days
Quote endThe earlier of 30 minutes after creation and the plan's next expiry or restore cutoff
RefundsNo 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:

ExitMeaningWhat to do
21Offers 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
24The backend has no capacity purchases yetStop

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 json

The preview sends nothing.

2. Request the quote

uno kit pay --capacity 1GB --months 1 --operation buy-1 --format json

This command never pays. It exits 15 and returns the quote in error.details.payment:

FieldMeaning
purchase_idThe purchase
quote_idThe frozen quote
amountAmount in whole tokens
tokenToken contract address
chainChain ID
capacity_bytesTotal capacity quoted
monthsMonths quoted
usd_per_gb_monthUnit price
expires_atQuote end, in Unix seconds
no_refundThe no-refund statement
pay_urlThe backend payment link
pay_commandThe 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 json

This 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:

FieldMeaning
classificationquoted, stale, late or extra
applied_amountAmount applied
capacity_bytesCapacity
starts_at, expires_atTerm dates
payment_txThe paying transaction

After settlement, retry the write that needed storage with its original operation and identical inputs.

Exit codes of the quote command

ExitStateWhat to do
15Unpaid quotePay the printed command
14Payment in flightWait, then run uno kit purchase <purchase_id>. Never pay again
0SettledRead results
9Failed, expired or old-network purchaseRead it with uno kit purchase. Start a new operation to buy again
21, 24Not offered or unavailableSee 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-1

The 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-1

The 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_required holds purchase_id, quote_expires_at, pay_url, amount, currency, chain_id, token, amount_base_units and pay_command. Run pay_command, then call uno_purchase_lookup with purchase_id.
  • An App payment_required holds challenge, pay_url, amount, memo, chain_id and pay_commands. Run pay_commands[0]. With another wallet, send the transfer with the memo, then call uno_payment_settle.
  • uno_payment_settle takes only challenge and tx_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.