Hi everyone, I’m Sonny.
In my earlier “Chat-and-Pay” and “Charge-as-You-Go” experiments, I focused on one question: can payments happen alongside a service, instead of asking users to top up first, consume later, and wait for a platform to settle everything afterward?
While working with Fiber Network 0.9.0, I noticed another useful part of Invoice payments:
After an Invoice payment succeeds, the payer can retrieve its payment preimage, exposed as payment_preimage.
“Preimage” is a crypto term, but the basic idea is simple: it is a random value generated when the order is created.
Fiber calculates a payment_hash from that value. You can think of the hash as its digital fingerprint:
Random payment value → payment_preimage
Digital fingerprint → payment_hash
The Invoice can safely include the payment_hash without exposing the original payment_preimage.
Only after the payment succeeds does the payer receive the corresponding preimage.
This raises an interesting question:
What if we connect that payment preimage to the service from the moment the order is created?
We built two interactive Testnet tutorials on the Fiber website to explore two versions of this idea:
- Use the payment preimage to unlock encrypted data after payment.
- Commit a payment first, verify the service output, and then settle or cancel it.
One tutorial is about encryption and the other is about conditional settlement, but they share the same connection point: payment_preimage.
An Invoice Can Return More Than a Payment Status
Most applications only check whether an Invoice payment succeeded:
Success / Failed
If the payment succeeds, the application updates the order and asks its backend to unlock the content.
In this common flow, the application usually ignores payment_preimage. It is treated as internal payment data.
With Fiber 0.9.0, the payer can retrieve the preimage after a successful payment.
That means the application receives more than a payment confirmation. It also receives a random value that can continue to participate in the service flow.
This led us to a simple idea:
What if the payment preimage also served as the decryption key for the purchased result?
Experiment One: Unlock Data After Payment
The first tutorial is:
Unlock Encrypted Data with a Fiber Payment
It demonstrates a digital content purchase.
The provider has already produced a research report, an AI-generated result, or the output of a data query. The provider wants to deliver the result before payment without allowing the buyer to read it yet.
When creating the order, the provider generates a random payment preimage. We will call it K.
The same K is then used in two places.
First, the provider uses K to encrypt the service output.
Second, the provider uses K to create a regular Fiber Invoice.
Fiber calculates the corresponding payment_hash and places that hash in the Invoice. The buyer can inspect the Invoice, but cannot recover K from the hash.
The application then packages the following information into one order:
- The encrypted service output
- The Fiber Invoice
- The Invoice’s
payment_hash - The service description and required payment information
The full flow looks like this:
Generate random value K
├── Use K to encrypt the service output
└── Use K to create the Fiber Invoice
Encrypted output + Invoice + service information
↓
One complete order
At this point, the buyer already has the service output, but only in encrypted form.
The order does not expose K, and the Invoice contains only its digital fingerprint. The buyer therefore cannot read the original content before paying.
After the buyer pays the Invoice, Fiber returns the payment’s payment_preimage.
That preimage is the same K generated when the order was created.
The buyer can now use K to decrypt the result locally:
Pay the Invoice
↓
Fiber returns payment_preimage
↓
payment_preimage is K
↓
Use K to decrypt the service output
The important part is not the specific encryption algorithm.
The important part is this:
Payment settlement and delivery of the decryption key become the same process.
The provider does not need to run another backend endpoint that sends the key after payment.
The buyer does not need to log into a platform and wait for it to check a database before unlocking the content.
The encrypted result can be delivered in advance. The decryption key reaches the buyer through the payment result only after settlement succeeds.
Payment completes, and the data becomes readable.
How Is the Service Connected to the Invoice?
This is the most important part of the first experiment.
A traditional application usually connects an order and a payment through a database record:
Order 123 belongs to Invoice 456
After payment, the backend looks up Order 123, marks it as paid, and then sends the file or grants access.
This works, but the relationship between the payment and the service mainly depends on the platform’s database and authorization system.
Our experiment creates a more direct connection.
The same random value K plays two roles:
- It is the payment preimage for the Invoice.
- It is the decryption key for the service output.
The Invoice’s payment_hash is derived from K, while the encrypted content can only be opened with the correct K.
The order, payment, and service output are therefore linked through the same value from the beginning.
The official Fiber discussion Agent / Fiber Integration Solutions Design #1255 also describes this pattern as Hash-Locked Data Exchange.
Its core flow closely matches the tutorial:
- The provider generates a random value.
- The provider encrypts the service output with that value.
- The provider uses the same value as the Invoice payment preimage.
- The buyer receives the encrypted output and the Invoice.
- The buyer pays the Invoice.
- Fiber returns the payment preimage to the buyer.
- The buyer uses the preimage to decrypt the result.
The provider gets paid only when the payment settles, while the buyer receives the decryption key through the same settlement flow.
How Is This Different From a Regular Invoice?
At the Fiber protocol level, the first experiment uses a regular Invoice.
It is not a new type of “encrypted Invoice,” and it does not change how Invoice payments work.
The difference is how the application uses the payment result.
A typical application only asks:
Did the payment succeed?
This experiment also asks:
What is the payment_preimage?
It then uses the returned payment_preimage as the decryption key.
The difference can be summarized like this:
| Usage | How the application handles the payment result |
|---|---|
| Regular Invoice payment | Only checks whether the payment succeeded or failed |
| Pay-to-decrypt | Retrieves the preimage after payment and uses it to decrypt the service output |
A regular Invoice is usually treated as a way to move funds.
This experiment uses the same payment to do two things:
- Pay the provider
- Deliver the decryption key to the payer
The Invoice itself has not changed. The application is simply making use of the payment preimage returned after settlement.
Where Could This Be Used?
The most direct use case is digital content:
- Paid research reports
- AI or agent-generated results
- Pay-per-query data
- Private files and downloads
- Images, video, and audio
- Pay-per-call API responses
- Machine-to-machine data exchange
The provider can complete the work first, then deliver the encrypted result together with the Invoice.
Before payment, the buyer only has encrypted content.
After payment, Fiber returns the payment preimage and the buyer decrypts the result locally.
In our tutorial, encryption, Invoice creation, payment tracking, and decryption all run inside browser-based Fiber nodes.
The demo still relies on public Fiber and CKB Testnet infrastructure, but it does not require a separate application backend dedicated to storing and sending decryption keys.
This approach also has a clear limitation.
It can guarantee:
No completed payment, no decryption key.
But it cannot guarantee:
The decrypted content will meet the buyer’s expectations.
A buyer may pay successfully, decrypt the content, and then discover that the report is low quality or that the service output is not what they expected.
That leads to the second experiment.
Experiment Two: Commit Payment First, Verify Before Settlement
The second tutorial is:
This experiment also starts with a random payment preimage K.
The difference is that the application does not give K to the Fiber node when creating the Invoice. It provides only the corresponding payment_hash.
The node knows which payment_hash the Invoice expects, but it does not have the preimage required to complete the payment.
Because the preimage is unavailable, the payment cannot settle automatically when it arrives.
Instead, it enters a held state.
At this point:
- The buyer has submitted the payment.
- The required channel liquidity is committed.
- The provider can see that the payment is ready.
- The provider has not received the funds yet.
- The application can still settle or cancel the payment.
The application can now verify the service output.
If the result passes the agreed checks, the application provides K to Fiber. Fiber verifies that it matches the Invoice’s payment_hash.
If it matches, the payment settles and the provider receives the funds.
If the result fails verification, the application cancels the Invoice. The held payment is rejected instead of being added to the provider’s balance.
The flow looks like this:
Generate random value K
↓
Put only K’s payment_hash in the Hold Invoice
↓
The buyer submits payment
↓
The payment enters a held state
↓
The application verifies the service output
├── Pass → provide K → settle the payment
└── Fail → cancel the Invoice
Here, “settlement” simply means completing the pending payment so the provider actually receives the funds.
This experiment answers a different question:
How can the buyer prove that payment is ready, while allowing the application to verify the result before the provider receives the funds?
What Is the Difference Between a Regular Invoice and a Hold Invoice?
Both regular Invoices and Hold Invoices use the relationship between payment_hash and payment_preimage.
The main difference is whether the Fiber node already has the payment preimage when the Invoice is created.
| Regular Invoice | Hold Invoice | |
|---|---|---|
| What is provided at creation | The payment preimage | Only the corresponding payment_hash |
| Does the node have the preimage? | Yes | No |
| What happens when payment arrives? | It settles automatically | It enters a held state |
| When is the preimage delivered? | Automatically after successful settlement | After verification and explicit settlement |
| Can the pending payment be cancelled? | Not after it has settled | Yes, while it is held |
| Best suited for | Payment followed by immediate delivery | Verification before final settlement |
The first tutorial uses a regular Invoice.
The provider gives its node K as the payment preimage when creating the Invoice. When the payment arrives, the node can settle it immediately and return the preimage to the payer.
It fits this model:
Successful payment = service delivery
The second tutorial uses a Hold Invoice.
The node has only the payment_hash, so it must wait for the application to provide the matching preimage or cancel the payment.
It fits this model:
Payment is ready
+
The service output passes verification
=
Settle the payment
The two tutorials can be summarized like this:
Regular Invoice: receive the preimage automatically after payment.
Hold Invoice: use the preimage to settle only after verification passes.
Why Does This Matter for Agents and Machine Payments?
Most internet payment systems were designed around people.
A user confirms an order, opens a payment page, completes the payment, and waits for the merchant to deliver the service.
Transactions between agents and machines may work very differently.
One agent might ask another agent to analyze some data and receive the result within seconds. A program might call an API but only want to pay for a correctly formatted response. One device might automatically purchase data from another device.
These flows may have no human approval step and no one manually clicking “Confirm delivery.”
The application needs to determine:
- How does the buyer receive the result after payment?
- How is the service output linked to a specific payment?
- How does the provider know that the buyer has committed funds?
- How does the buyer avoid paying for an obviously invalid result?
- How does payment settle automatically after verification passes?
The payment preimage creates a useful connection point.
It belongs to the payment flow, but the application can continue using it afterward.
An application can use a payment preimage as:
- A data decryption key
- A service access credential
- A content access condition
- A condition for settling a held payment
Payment is no longer just the final checkout step. It can directly participate in service delivery.
These Models Still Have Limits
Pay-to-decrypt can bind payment to delivery of a decryption key, but it cannot prove content quality before payment.
A Hold Invoice can keep payment pending while the result is checked, but only if the application has clear rules for deciding whether that result is valid.
Software is good at checking things such as:
- Whether a response contains the required fields
- Whether the data format is correct
- Whether a file hash matches the expected value
- Whether a computation can be reproduced
- Whether a task completed within the agreed time
Software is not as good at deciding:
- Whether an article is well written
- Whether a design looks good
- Whether business advice is genuinely useful
- Whether a subjective service meets someone’s expectations
If the result requires human judgment, the application may still need manual confirmation, third-party arbitration, or a reputation system.
A Hold Invoice provides a way to hold, settle, or cancel payment. It does not replace every form of dispute resolution.
Final Thoughts
I used to think of an Invoice as an off-chain payment request.
The provider creates an Invoice, the buyer pays it, the application sees Success, and the order continues.
After building these two tutorials, I started to see an Invoice as something else as well: a connection point between payment and service delivery.
When an order is created, the application generates a random payment preimage.
That preimage can participate in several parts of the flow:
Order creation
Data encryption
Invoice payment
Service delivery
Conditional settlement
The first tutorial uses the payment preimage as a decryption key.
The second tutorial uses the payment preimage to control when a held payment settles.
These Testnet experiments are intentionally simple, but they introduce a different way to build with Fiber:
Do not stop at checking whether a payment succeeded. Consider how your application can use the payment preimage returned after settlement.
It can unlock a report, grant access to a data service, or allow software to settle payment automatically after verifying a result.
The most interesting machine-payment applications may not be the ones that simply teach software how to send money.
The bigger opportunity is to make payment, result verification, and service delivery part of the same flow.