FFiber Offers
Documentation / Foundations

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.

Fiber Offers system design showing wallet, merchant, resolver, Fiber node, webhook and storage interactions
Fiber Offers separates stable payment discovery from the short-lived invoice used to execute an individual Fiber payment.

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_id is 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, and rgbpp. 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 typeFields on the offerUseful for
Fixed amountDemo API: pricing_type: "fixed" with amount. Signed offer: equal bounds.Checkout, a fixed service, or a subscription cycle.
Customer chooses amountamount_min onlyTips, donations, or open-value payments.
Amount rangeBoth amount_min and amount_maxMetered 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.

FormExampleWhen to use it
Payment linkhttps://resolver.example/pay/0x...Merchant checkout, browser, or app-to-app handoff.
Fiber Addresscoffee@example.comHuman-friendly repeat payments and wallet address lookup.
Encoded offerfbroffer1...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.

Recurring offers When recurrence metadata is used, the protocol requires either a cycle cap or a total spending cap. This prevents an unbounded authorization from being represented as a recurring offer.