Withdrawing through Lightning

The Invoice Workflow Problem

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

  • Player/User performs action in Game/Application that requires a Payment
  • Game/Application creates a Lightning invoice for the specified amount and displays it in a QR Code
  • Player/User uses a Lightning Wallet (usually mobile phone wallets) to scan that QR Code and decode payment information
  • Player/User performs Payment
  • Game/Application receives Payment and allows action to be performed/continued

This is a great user experience between Player/User and Game/Application. However, this user workflow is limited to User paying Service. To perform the reverse (Service paying User), as with all Lightning payments, the Service must first ask for an Invoice from the User, for a specific amount. This is a

Therefore ZEBEDEE's Withdrawal Request Entity is based on the LNURL open source specification, which provides a standard for easier communication between Lightning Wallets and Lightning Services, 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 -- ZEBEDEE has effectively abstracted any complexities from the API. Let's see how to do it.


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

Creating a Withdrawal Request

When creating a Withdrawal Request code to allow Lightning Wallets to withdraw funds from the Game/Application you must provide the following attributes:

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 API (or leverage one of our SDKs) by passing the correct attributes:

// Using ZEBEDEE's NodeJS SDK
import { createWithdrawalRequest, initAPI } from 'zebedee-nodejs';
// Instantiate the API
const apiOptions = { apiKey: 'API_KEY_HERE' };
// Set the payload
const payload = {
expiresIn: 300,
amount: '50000',
description: 'My Custom Withdrawal Request Description',
callbackUrl: 'https://yourapp.com/callback',
internalId: '11af01d092444a317cb33faa6b8304b8',
// Create Withdrawal Request
try {
const response = await 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 Charge",
"createdAt": "2019-12-23T03:58:17.993Z",
"callbackUrl": "http://your-website.com/callback",
"internalId": "11af01d092444a317cb33faa6b8304b8",
"invoice": {
"expiresAt": "2019-12-23T04:08:18.038Z",
"request": "lnurl1dp68gurn8ghj7cn9w3sj6ctsdyh85etzv4jx2efwd9hj7a3s9acxz7tvdaskgtthd96xserjv9mkzmpdwfjhzat9wd6r7um9vdex2apav3skxdfev93rwvm9x43nwcf5vvekgdmpxq6rgvrrxumnxdp3vserqe35v4jr2efs8y6k2epkxf3rxc35vg6nwdrpx9jrqv3kxfjxxwqxmuhcd"

Withdrawal Request Updates

All Withdrawal Request will either complete or expire. If no User/Player 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

Please refer to the Entity Status portion of the wiki to learn more about the Withdrawal Request status property.

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 services will make a POST request to the URL provided in callbackUrl, passing the Withdrawal Request updates as data in the request.