Receiving payments using LNURL-Pay and Lightning addresses
What is a Lightning address?
A Lightning address is a human-readable identifier formatted like an email address (e.g., user@domain.com) that can be used to receive Bitcoin payments over the Lightning Network. Behind the scenes, it uses the LNURL-Pay protocol to dynamically generate invoices when someone wants to send a payment to this address.
Configuring a custom domain
To use Lightning addresses with the Breez SDK, you first need to supply a domain. There are two options:
- Use a hosted LNURL server: You can have your custom domain configured to an LNURL server run by Breez.
- Self-hosted LNURL server: You can run your own LNURL server in a self-hosted environment.
In case you choose to point your domain to a hosted LNURL server, you will need to add a CNAME record in your domain's DNS settings.
Option 1: Using your domain without any subdomain
This points yourdomain.com directly to the LNURL server. Some DNS providers do not support this method. If yours doesn't support CNAME or ALIAS records for the root domain, you will need to configure your domain at the registrar level to use an external DNS provider (like Google Cloud DNS).
- Host/Name: @
- Type: CNAME (or ALIAS if available)
- Value/Target: breez.tips
Option 2: Using a subdomain This points a subdomain like pay.yourdomain.com to the LNURL server.
- Host/Name: pay (or your chosen prefix like payment, tip, donate)
- Type: CNAME
- Value/Target: breez.tips
Send us your domain name (e.g., yourdomain.com or pay.yourdomain.com).
We will verify and add it to our list of allowed domains.
Configuring Lightning addresses for users
Configure your domain in the SDK by passing the lnurl_domain parameter in the SDK configuration:
let mut config = default_config(Network::Mainnet);
config.api_key = Some("your-api-key".to_string());
config.lnurl_domain = Some("yourdomain.com".to_string());
var config = defaultConfig(network: Network.mainnet)
config.apiKey = "your-api-key"
config.lnurlDomain = "yourdomain.com"
val config = defaultConfig(Network.MAINNET)
config.apiKey = "your-api-key"
config.lnurlDomain = "yourdomain.com"
var config = BreezSdkSparkMethods.DefaultConfig(Network.Mainnet) with
{
apiKey = "your-api-key",
lnurlDomain = "yourdomain.com"
};
const config = defaultConfig('mainnet')
config.apiKey = 'your-api-key'
config.lnurlDomain = 'yourdomain.com'
const config = defaultConfig(Network.Mainnet)
config.apiKey = 'your-api-key'
config.lnurlDomain = 'yourdomain.com'
final config = defaultConfig(network: Network.mainnet)
.copyWith(
apiKey: 'your-api-key',
lnurlDomain: 'yourdomain.com'
);
config = default_config(network=Network.MAINNET)
config.api_key = "your-api-key"
config.lnurl_domain = "yourdomain.com"
lnurlDomain := "yourdomain.com"
apiKey := "your-api-key"
config := breez_sdk_spark.DefaultConfig(breez_sdk_spark.NetworkMainnet)
config.ApiKey = &apiKey
config.LnurlDomain = &lnurlDomain
Managing Lightning addresses API docs
The SDK provides several functions to manage Lightning addresses:
Checking address availability
Before registering a Lightning address, you can check if the username is available. In your UI you can use a quick check mark to show the address is available before registering.
let request = CheckLightningAddressRequest {
username,
};
let is_available = sdk.check_lightning_address_available(request).await?;
let request = CheckLightningAddressRequest(
username: username
)
let available = try await sdk.checkLightningAddressAvailable(req: request)
val request = CheckLightningAddressRequest(
username = username
)
val available = sdk.checkLightningAddressAvailable(request)
var request = new CheckLightningAddressRequest(username: username);
var isAvailable = await sdk.CheckLightningAddressAvailable(request);
const request = {
username
}
const available = await sdk.checkLightningAddressAvailable(request)
const request = {
username
}
const available = await sdk.checkLightningAddressAvailable(request)
final request = CheckLightningAddressRequest(
username: username,
);
final available = await sdk.checkLightningAddressAvailable(request: request);
request = CheckLightningAddressRequest(username=username)
is_available = await sdk.check_lightning_address_available(request)
request := breez_sdk_spark.CheckLightningAddressRequest{
Username: username,
}
isAvailable, err := sdk.CheckLightningAddressAvailable(request)
if err != nil {
return false, err
}
Registering a Lightning address
Once you've confirmed a username is available, you can register it by passing a username and a description. The username will be used in username@domain.com. The description will be included in lnurl metadata and as the invoice description, so this is what the sender will see. The description is optional, and will default to Pay to username@domain.com.
let request = RegisterLightningAddressRequest {
username,
description,
};
let address_info = sdk.register_lightning_address(request).await?;
let lightning_address = address_info.lightning_address;
let lnurl = address_info.lnurl;
let request = RegisterLightningAddressRequest(
username: username,
description: description
)
let addressInfo = try await sdk.registerLightningAddress(request: request)
let lightningAddress = addressInfo.lightningAddress
let lnurl = addressInfo.lnurl
val request = RegisterLightningAddressRequest(
username = username,
description = description
)
val addressInfo = sdk.registerLightningAddress(request)
val lightningAddress = addressInfo.lightningAddress
val lnurl = addressInfo.lnurl
var request = new RegisterLightningAddressRequest(
username: username,
description: description
);
var addressInfo = await sdk.RegisterLightningAddress(request);
var lightningAddress = addressInfo.lightningAddress;
var lnurl = addressInfo.lnurl;
const request = {
username,
description
}
const addressInfo = await sdk.registerLightningAddress(request)
const lightningAddress = addressInfo.lightningAddress
const lnurl = addressInfo.lnurl
const request = {
username,
description
}
const addressInfo = await sdk.registerLightningAddress(request)
const lightningAddress = addressInfo.lightningAddress
const lnurl = addressInfo.lnurl
final request = RegisterLightningAddressRequest(
username: username,
description: description,
);
final addressInfo = await sdk.registerLightningAddress(request: request);
final lightningAddress = addressInfo.lightningAddress;
final lnurl = addressInfo.lnurl;
request = RegisterLightningAddressRequest(
username=username,
description=description
)
address_info = await sdk.register_lightning_address(request)
lightning_address = address_info.lightning_address
lnurl = address_info.lnurl
request := breez_sdk_spark.RegisterLightningAddressRequest{
Username: username,
Description: &description,
}
addressInfo, err := sdk.RegisterLightningAddress(request)
if err != nil {
return nil, err
}
_ = addressInfo.LightningAddress
_ = addressInfo.Lnurl
Retrieving Lightning address information
You can retrieve information about the currently registered Lightning address.
let address_info_opt = sdk.get_lightning_address().await?;
if let Some(info) = address_info_opt {
let lightning_address = &info.lightning_address;
let username = &info.username;
let description = &info.description;
let lnurl = &info.lnurl;
}
if let addressInfo = try await sdk.getLightningAddress() {
let lightningAddress = addressInfo.lightningAddress
let username = addressInfo.username
let description = addressInfo.description
let lnurl = addressInfo.lnurl
}
val addressInfoOpt = sdk.getLightningAddress()
if (addressInfoOpt != null) {
val lightningAddress = addressInfoOpt.lightningAddress
val username = addressInfoOpt.username
val description = addressInfoOpt.description
val lnurl = addressInfoOpt.lnurl
}
var addressInfoOpt = await sdk.GetLightningAddress();
if (addressInfoOpt != null)
{
var lightningAddress = addressInfoOpt.lightningAddress;
var username = addressInfoOpt.username;
var description = addressInfoOpt.description;
var lnurl = addressInfoOpt.lnurl;
}
const addressInfoOpt = await sdk.getLightningAddress()
if (addressInfoOpt != null) {
const lightningAddress = addressInfoOpt.lightningAddress
const username = addressInfoOpt.username
const description = addressInfoOpt.description
const lnurl = addressInfoOpt.lnurl
}
const addressInfoOpt = await sdk.getLightningAddress()
if (addressInfoOpt != null) {
const lightningAddress = addressInfoOpt.lightningAddress
const username = addressInfoOpt.username
const description = addressInfoOpt.description
const lnurl = addressInfoOpt.lnurl
}
final addressInfoOpt = await sdk.getLightningAddress();
if (addressInfoOpt == null) {
throw Exception("No Lightning Address registered for this user.");
}
final lightningAddress = addressInfoOpt.lightningAddress;
final username = addressInfoOpt.username;
final description = addressInfoOpt.description;
final lnurl = addressInfoOpt.lnurl;
address_info_opt = await sdk.get_lightning_address()
if address_info_opt is not None:
lightning_address = address_info_opt.lightning_address
username = address_info_opt.username
description = address_info_opt.description
lnurl = address_info_opt.lnurl
addressInfoOpt, err := sdk.GetLightningAddress()
if err != nil {
return nil, err
}
if addressInfoOpt != nil {
_ = addressInfoOpt.LightningAddress
_ = addressInfoOpt.Username
_ = addressInfoOpt.Description
_ = addressInfoOpt.Lnurl
}
Deleting a Lightning address
When a user no longer wants to use the Lightning address, you can delete it.
sdk.delete_lightning_address().await?;
try await sdk.deleteLightningAddress()
sdk.deleteLightningAddress()
await sdk.DeleteLightningAddress();
await sdk.deleteLightningAddress()
await sdk.deleteLightningAddress()
await sdk.deleteLightningAddress();
await sdk.delete_lightning_address()
err := sdk.DeleteLightningAddress()
if err != nil {
return err
}