Product story

How it works
Umbra exists so value can move on Solana without turning every counterparty into a public graph. Here that shows up as a pay link people already know how to use, plus one URL agents can poll the same way they would any other gated API.

Product scope

  • Private payment links: share a URL with an opaque id; your merchant pubkey is not in the path, and value settles through Umbra’s confidential machinery instead of a trivial public transfer row for every payer.
  • X402-style private machine payments: the agent URL speaks HTTP 402 + structured accepts[] until the Umbra flow completes, then 200. Same mental model as emerging x402 clients; settlement is explicitly umbra-receiver-claimable-utxo in JSON so tools don’t mis-implement a raw SPL send.

Payment intent

When you submit the form on the home page, the app stores an intent: label, USDC amount, SPL mint, merchant Solana address, and status (open or settled). The public link only contains an opaque id (not the merchant address in the path), which reduces trivial link-scraping of “who earns here.”

Human payer

The /pay/<id> page loads that intent, connects a Wallet Standard wallet, and runs the Umbra SDK: registration if needed, then getPublicBalanceToReceiverClaimableUtxoCreatorFunctionso USDC moves through Umbra's receiver-claimable UTXO path toward the merchant you configured. That uses the same privacy primitives Umbra documents for builders.

What payers see vs what chain observers see

The checkout UI shows the amount and labelso humans know what they're paying, which keeps checkout honest. On-chain, Umbra separates who paid whom from a trivial public graph: value commits into Umbra's structure toward the merchant's keys; claiming can land in private balances per Umbra's model. This prototype does not replace Umbra with a custodial ledger.

x402 shape vs Umbra settlement

The 402 response follows the familiar x402 pattern: x402Version, accepts[], maxAmountRequired, payTo, and asset so generic agents can parse the bill. Umbra is not “only” a plain SPL transfer to payTo: the extra.settlement field is umbra-receiver-claimable-utxo, and extra includes humanPayUrl, confirmUrl, and SDK docs so implementers route funds through the Umbra proof flow.

Agent client

The same intent id backs GET /api/resources/<id>. While the intent is open, the response is 402 with JSON shaped like common x402 examples, plus an extra block that names Umbra as the settlement mechanism. After the payer (human or script) completes Umbra and the app records settlement signatures via POST /api/intents/<id>/confirm, the same GET returns 200 with machine-readable content (see Agents & APIs).

API tables and scripts: Agents & APIs.

Lifecycle checklist

  1. Create intent → copy human pay URL + agent resource URL.
  2. Human or agent settles via Umbra SDK; client POSTs signatures to confirm.
  3. Resource GET flips from 402 to 200. One id feeds CRM, webhooks, and ledgers.