Skip to main content

The Lightning Charge Workflow Problem

Perform Lightning Network Withdrawals

Perform Lightning Network Withdrawals

The Lightning Network is a push-based system: in order to receive payments, the payee must first create a Charge / Payment Request, which the payer can pay. This is a great workflow when users are making payments for goods and services. Usually this workflow is as follows:

  • User performs action that requires a Payment
  • You create a Lightning Charge for the specified amount and displays it in a QR Code
  • User uses a Lightning Wallet (usually mobile phone wallet apps) to scan that QR Code and decode payment information
  • User confirms Payment details and performs the Payment
  • You receive Payment and unlock content/action for the user

This is a great user experience between User and a Project (e.g. game or application). However, this user workflow is limited to User paying Project. To perform the reverse (Project paying User), as with all Lightning payments, the Project must first ask for a Lightning Network Charge/Invoice from the User, for a specific amount. This provides for subpar UX because the User is now an active participant when receiving funds.


Enter Lightning Withdrawal Request

Withdrawal Requests are the exact opposite of a Charge. Whereas a Charge is a payment from a User to a Project, a Withdrawal Request can be understood as a payment from a Project to a User. In other words, a Charge is a QR code that accepts a Bitcoin payment while a Withdrawal Request is a QR code that allows a User to claim Bitcoin.

ZEBEDEE's Withdrawal Request capability is based on the LNURL open-source specification, which provides a standard for easier communication between Wallets (users) and Projects, through the use of HTTP requests. A developer building upon ZEBEDEE's Withdrawal Requests functionality does not need to understand the underlying methodology and workflow of LNURL - the ZEBEDEE API abstracts away any complexities. Let's see how to do it.

tip

If you've been able to create a ZEBEDEE Charge, then you will be able to create a ZEBEDEE Withdrawal Request easily.


Creating a Withdrawal Request

When creating a Withdrawal Request code to allow Lightning Wallets to withdraw funds from the Project (game or application) you must provide the following attributes to the /withdrawal-requests endpoint:

PropertyStatusDescription
amountStringThe Withdrawal Request amount (in millisatoshis).
descriptionStringThe Withdrawal Request description (also applied as the description to the associated BOLT11 Lightning invoice).
internalIdStringAn optional free-use attribute. Usually used by setting the Player/User ID of your Game/Application in order to link specific Withdrawal Requests to specific Players.
callbackUrlStringThe URL ZEBEDEE services will make a POST HTTP request to with information about the Withdrawal Requests's status updates.
expiresInNumberThe desired expiration time for this Withdrawal Request (in seconds).

To create the Withdrawal Request, use the ZEBEDEE API (or leverage one of our SDKs) by passing the correct attributes:

// Using ZEBEDEE's NodeJS SDK
import { zbd } from '@zbd/node';

// Instantiate the client
const ZBD = new zbd('API_KEY_HERE');

// Set the payload
const payload = {
expiresIn: 300,
amount: '50000',
internalId: '11af01d0924aa6b8304b8',
description: 'My Custom Withdrawal Request',
callbackUrl: 'https://yourapp.com/zbd-callback',
};

// Create Withdrawal Request
try {
const response = await ZBD.createWithdrawalRequest(payload);
} catch(error) {
console.log({ error });
}

If the submitted request suceeds, you can expect a JSON API response that resembles the following:

{
"message": "Successfully created Withdrawal Request.",
"data": {
"id": "c121356b-9671-4fbd-a751-987fb4b3d0b3",
"unit": "msats",
"amount": "50000",
"status": "pending",
"description": "Description of the Withdrawal Request",
"createdAt": "2019-12-23T03:58:17.993Z",
"callbackUrl": "http://your-website.com/zbd-callback",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"invoice": {
"expiresAt": "2019-12-23T04:08:18.038Z",
"request": "lnurl1dp68gurn8ghj7cn9w3sj6ctsdyh85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7um9vdex2apav3skxdfev93rwvm9x43nwcf5vvekgdmpxq6rgvrrxumnxdp3vserqe35v4jr2efs8y6k2epkxf3rxc35vg6nwdrpx9jrqv3kxfjxxwqxmuhcd"
}
}
}

Displaying the Withdrawal Request QR Code

In order to display the Withdrawal Request as a QR code, simple use the data.invoice.request attribute returned from the API response and pass it to your QR code generator of choice. The QR code should look something like this:

Withdrawal Requests QR Code

Withdrawal Requests QR Code

Withdrawal Request Updates

Note that the Withdrawal Request is created in a pending state as it still hasn't been claimed. All Withdrawal Requests will either complete or expire. If no User is able to Withdraw the funds on time before the Withdrawal Request's expiration time, the Request will expire and will therefore no longer be valid. To know the status of your specific Withdrawal Request, check the status attribute returned from the CreateWithdrawalRequest or GetWithdrawalRequestDetails API calls.

{
...
"status": "expired" // pending | completed | expired | error
...
}

To subscribe to updates on a specific Withdrawal Request, the recommended approach is to provide a callbackUrl property when creating that Withdrawal Request. Whenever there are updates to the Withdrawal Request (a payment was made, or it has expired) the ZEBEDEE API will make a POST request to the URL provided in callbackUrl, passing the Withdrawal Request updates as data in the request.