Offers, pricing, and identity
An offer is a signed payment intent. It describes a merchant endpoint and payment constraints, while each invoice remains one-time and is generated only when a payer is ready to continue.
System design
The offer is portable and verifiable. The resolver is responsible for service-side concerns such as invoice creation, lifecycle records, delivery outbox management, and diagnostics.
Offer
A reusable, Ed25519-signed descriptor. It declares recipient identity, accepted assets, price constraints, resolver URL, and optional recurrence metadata.
Resolver
The HTTP service that verifies an offer, checks a request, asks its invoice source for a fresh invoice, and records a resolution.
Resolution
An individual invoice attempt. It stores the requested amount and asset, invoice data, lifecycle history, settlement data, receipts, and webhook events.
Fiber Address
A username@domain lookup that returns the signed offer and its shareable payment link through a well-known URL.
Signed offer format
Encoded offers use bech32m with the fbroffer human-readable prefix and canonical JSON data. The offer ID is deterministic, and the signature covers the canonical offer including its ID.
{
"scheme": "fiberoffer-v1",
"version": 1,
"network": "testnet",
"node_id": "02...",
"public_key": "-----BEGIN PUBLIC KEY-----...",
"resolver_url": "https://resolver.example",
"description": "Coffee checkout",
"assets": [{ "asset_type": "ckb", "symbol": "CKB" }],
"amount_min": "1000",
"amount_max": "1000",
"single_use": false,
"offer_id": "0x...",
"signature": { "scheme": "ed25519", "value": "..." }
}
offer_idis derived from the canonical unsigned offer, so a field change creates a different identity.- Amounts are integer strings. A wallet should never convert them through floating-point arithmetic.
- Supported asset types are
ckb,udt, andrgbpp. UDT and RGB++ assets require a type script hash. - Wallets should decode and verify the signature before trusting resolver-hosted metadata.
Pricing types
The console and demo API make price intent explicit with pricing_type. The signed protocol stores the equivalent amount constraints so existing resolver and wallet integrations remain compatible.
| Pricing type | Fields on the offer | Useful for |
|---|---|---|
| Fixed amount | Demo API: pricing_type: "fixed" with amount. Signed offer: equal bounds. | Checkout, a fixed service, or a subscription cycle. |
| Customer chooses amount | amount_min only | Tips, donations, or open-value payments. |
| Amount range | Both amount_min and amount_max | Metered or variable service with a hard spending limit. |
Scenario: a fixed coffee checkout
A merchant creates pricing_type: "fixed" with amount: "1000". The resolver signs equal bounds internally; wallets show one fixed price and a request for 1200 fails as an exact-price mismatch, with no invoice minted.
Scenario: a bounded API charge
A service publishes a range from 100 to 10000. The wallet can show the chosen amount before resolution; requests outside that range fail cleanly with the offer still reusable for a valid amount.
Discovery and QR payloads
Offer data can be shared in three forms. Each form leads to the same signed offer and resolver contract.
| Form | Example | When to use it |
|---|---|---|
| Payment link | https://resolver.example/pay/0x... | Merchant checkout, browser, or app-to-app handoff. |
| Fiber Address | coffee@example.com | Human-friendly repeat payments and wallet address lookup. |
| Encoded offer | fbroffer1... | Wallet-level sharing and offline transport of the signed descriptor. |
GET /.well-known/fiberoffer/coffee
GET /offers/0x.../qr.svg?payload=link
GET /offers/0x.../qr.svg?payload=offer
The link QR is the default because it is smaller and resolves current metadata through the payment URL. The offer QR embeds the signed offer and is helpful for wallet integration testing.
Reusable and single-use behavior
Most offers are reusable: every valid invoice request receives a newly created invoice. For a one-time authorization, set single_use: true. The resolver serializes invoice creation per offer so simultaneous requests cannot produce multiple invoices from a single-use offer.