The Discovery Service manages Lightning Node backends that connect to Switchgear for invoice requests. The service supports dynamic registration, updates, enablement and removal of CLN and LND nodes.
The Discovery Service can be administered with both REST and the CLI.
To get started quickly, use the CLI to write a new JSON data model template to a file:
# Generate a template backend configuration
swgr discovery new cln-grpc --output cln-backend.json
swgr discovery new lnd-grpc --output lnd-backend.jsonThe Discovery Service provides a REST API for backend management. All endpoints except /health require bearer token authentication.
First, generate a token:
# Create a token (expires in 3600 seconds)
# Note: Requires private key from Authentication Setup (see Discovery Service Configuration)
swgr discovery token mint --key discovery-private.pem --expires 3600 --output discovery.token
# Set authorization header for curl commands
export AUTH_TOKEN=$(cat discovery.token)# Register a CLN node
curl -X POST http://localhost:3001/discovery \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"publicKey": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"name": "CLN Node 1",
"partitions": ["default"],
"weight": 100,
"enabled": true,
"implementation": {
"type": "clnGrpc",
"url": "https://192.168.1.100:9736",
"domain": "cln-node.local",
"auth": {
"caCertPath": "/path/to/ca.pem",
"clientCertSecret": "CLIENT_CERT",
"clientKeySecret": "CLIENT_KEY",
"secrets": {
"ttl": 300.0,
"secrets": {
"CLIENT_CERT": {"path": "/path/to/client.pem"},
"CLIENT_KEY": {"path": "/path/to/client-key.pem"}
}
}
}
}
}'
# Register an LND node
curl -X POST http://localhost:3001/discovery \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"publicKey": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
"name": "LND Node 1",
"partitions": ["default", "us", "eu"],
"weight": 50,
"enabled": true,
"implementation": {
"type": "lndGrpc",
"url": "https://192.168.1.101:10009",
"domain": "lnd-node.local",
"auth": {
"tlsCertPath": "/path/to/tls.cert",
"macaroonSecret": "MACAROON",
"secrets": {
"ttl": 300.0,
"secrets": {
"MACAROON": {"path": "/path/to/admin.macaroon"}
}
}
},
"ampInvoice": false
}
}'curl -X GET http://localhost:3001/discovery \
-H "Authorization: Bearer $AUTH_TOKEN"# By public key
curl -X GET "http://localhost:3001/discovery/0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" \
-H "Authorization: Bearer $AUTH_TOKEN"curl -X PUT "http://localhost:3001/discovery/0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "CLN Node 1 Updated",
"partitions": ["default", "us"],
"weight": 200,
"enabled": false,
"implementation": {
"type": "clnGrpc",
"url": "https://192.168.1.100:9736",
"domain": "cln-node.local",
"auth": {
"caCertPath": "/path/to/ca.pem",
"clientCertSecret": "CLIENT_CERT",
"clientKeySecret": "CLIENT_KEY",
"secrets": {
"ttl": 300.0,
"secrets": {
"CLIENT_CERT": {"path": "/path/to/client.pem"},
"CLIENT_KEY": {"path": "/path/to/client-key.pem"}
}
}
}
}
}'curl -X DELETE "http://localhost:3001/discovery/0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" \
-H "Authorization: Bearer $AUTH_TOKEN"# No authentication required
curl http://localhost:3001/healthThe swgr discovery command provides the same functionality as the REST interface for remote management of Lightning Node backends.
# Create a token (default 3600 seconds)
# Note: Requires a private key generated during Authentication Setup (see Discovery Service Configuration)
swgr discovery token mint --key discovery-private.pem --output discovery.token
# Create a token with custom expiration (86400 seconds = 24 hours)
swgr discovery token mint --key discovery-private.pem --expires 86400 --output discovery-24h.token
# Verify a token
swgr discovery token verify --public discovery-public.pem --token discovery.token# Generate a template backend configuration
swgr discovery new cln-grpc --output cln-backend.json
swgr discovery new lnd-grpc --output lnd-backend.json
# Set connection parameters (via environment or flags)
export DISCOVERY_STORE_HTTP_BASE_URL="https://discovery.example.com"
export DISCOVERY_STORE_HTTP_AUTHORIZATION="/path/to/discovery.token"
export DISCOVERY_STORE_HTTP_TRUSTED_ROOTS="/path/to/ca.pem"
# List all backends (simple table format)
swgr discovery ls
# Get backend details (JSON output)
swgr discovery get 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 --output backend-details.json
# Get all backends (JSON output)
swgr discovery get
# Register a new backend from JSON file
swgr discovery post --input cln-backend.json
# Update an existing backend
swgr discovery put 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 --input updated-backend.json
# Patch an existing backend
swgr discovery patch 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 --input backend-patch.json
# Enable an existing backend
swgr discovery enable 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
# Disable an existing backend
swgr discovery disable 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
# Delete a backend
swgr discovery delete 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798Discovery OpenAPI schema: doc/discovery-service-openapi.yaml.
Example CLN backend configuration:
{
"publicKey": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"name": "CLN Node 1",
"partitions": [
"default"
],
"weight": 1,
"enabled": true,
"implementation": {
"type": "clnGrpc",
"url": "https://127.0.0.1:9736",
"domain": "localhost",
"auth": {
"caCertPath": "/path/to/ca.pem",
"clientCertSecret": "CLIENT_CERT",
"clientKeySecret": "CLIENT_KEY",
"secrets": {
"ttl": 300.0,
"secrets": {
"CLIENT_CERT": {
"path": "/path/to/client.pem"
},
"CLIENT_KEY": {
"path": "/path/to/client-key.pem"
}
}
}
}
}
}caCertPath is optional; omit it to use the platform trust store. clientCertSecret and clientKeySecret name entries in the sibling secrets.secrets map. path must resolve on every host that runs an lnurl service against this backend.
Example LND backend configuration:
{
"publicKey": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
"name": "LND Node 1",
"partitions": [
"default",
"us",
"eu"
],
"weight": 1,
"enabled": true,
"implementation": {
"type": "lndGrpc",
"url": "https://127.0.0.1:10009",
"domain": "localhost",
"auth": {
"tlsCertPath": "/path/to/tls.cert",
"macaroonSecret": "MACAROON",
"secrets": {
"ttl": 300.0,
"secrets": {
"MACAROON": {
"path": "/path/to/admin.macaroon"
}
}
}
},
"ampInvoice": false
}
}tlsCertPath is optional; omit it to use the platform trust store. macaroonSecret names an entry in the sibling secrets.secrets map. path must resolve on every host that runs an lnurl service against this backend.
The Offer service manages Lightning payment offers and their metadata. It provides storage and retrieval of LNURL Pay offers with configurable payment limits and display information.
The Offer Service can be administered with both REST and the CLI.
To get started quickly, use the CLI to write a new JSON data model template to a file:
# Generate a template offer configuration
swgr offer new --output offer-template.json
# Generate a template metadata configuration
swgr offer metadata new --output metadata-template.jsonAn Offer has two fields that combine to create a unique identifier:
partitionid (Uuid)Both fields are used to make the final public LNURL:
https://{host}/offers/{partition}/{id}The Offer service provides a REST API for offer and metadata management. All endpoints except /health require bearer token authentication.
First, generate a token:
# Create a bearer token (expires in 3600 seconds)
# Note: Requires private key from Authentication Setup (see Offer Service Configuration)
swgr offer token mint --key offer-private.pem --expires 3600 --output offer.token
# Set authorization header for curl commands
export AUTH_TOKEN=$(cat offer.token)curl -X POST http://localhost:3002/offers \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"partition": "default",
"id": "6a38ebdd-83ef-4b94-b843-3b18cd90a833",
"maxSendable": 1000000,
"minSendable": 1000,
"metadataId": "88deff7e-ca45-4144-8fca-286a5a18fb1a",
"timestamp": "2024-01-01T00:00:00Z",
"expires": "2024-12-31T23:59:59Z"
}'curl -X GET http://localhost:3002/offers/default \
-H "Authorization: Bearer $AUTH_TOKEN"curl -X GET "http://localhost:3002/offers/default/6a38ebdd-83ef-4b94-b843-3b18cd90a833" \
-H "Authorization: Bearer $AUTH_TOKEN"curl -X PUT "http://localhost:3002/offers/default/6a38ebdd-83ef-4b94-b843-3b18cd90a833" \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"maxSendable": 2000000,
"minSendable": 1000,
"metadataId": "88deff7e-ca45-4144-8fca-286a5a18fb1a",
"timestamp": "2024-01-01T00:00:00Z",
"expires": "2024-12-31T23:59:59Z"
}'curl -X DELETE "http://localhost:3002/offers/default/6a38ebdd-83ef-4b94-b843-3b18cd90a833" \
-H "Authorization: Bearer $AUTH_TOKEN"curl -X POST http://localhost:3002/metadata \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "88deff7e-ca45-4144-8fca-286a5a18fb1a",
"partition": "default",
"text": "Lightning Payment",
"longText": "Pay for premium services with Lightning Network",
"image": {
"png": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
},
"identifier": {
"email": "payments@example.com"
}
}'curl -X GET http://localhost:3002/metadata/default \
-H "Authorization: Bearer $AUTH_TOKEN"curl -X GET "http://localhost:3002/metadata/default/88deff7e-ca45-4144-8fca-286a5a18fb1a" \
-H "Authorization: Bearer $AUTH_TOKEN"curl -X PUT "http://localhost:3002/metadata/default/88deff7e-ca45-4144-8fca-286a5a18fb1a" \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"text": "Updated Lightning Payment",
"longText": "Pay for premium services with Lightning Network - Updated",
"identifier": {
"email": "billing@example.com"
}
}'curl -X DELETE "http://localhost:3002/metadata/default/88deff7e-ca45-4144-8fca-286a5a18fb1a" \
-H "Authorization: Bearer $AUTH_TOKEN"# No authentication required
curl http://localhost:3002/healthThe swgr offer command provides the same functionality as the REST interface for remote management of Lightning payment offers and metadata.
# Create a token (default 3600 seconds)
# Note: Requires a private key generated during Authentication Setup (see Offer Service Configuration)
swgr offer token mint --key offer-private.pem --output offer.token
# Create a token with custom expiration (86400 seconds = 24 hours)
swgr offer token mint --key offer-private.pem --expires 86400 --output offer-24h.token
# Verify a token
swgr offer token verify --public offer-public.pem --token offer.token# Generate a template offer configuration
swgr offer new --output offer-template.json
# Set connection parameters (via environment or flags)
export OFFER_STORE_HTTP_BASE_URL="https://offer.example.com"
export OFFER_STORE_HTTP_AUTHORIZATION="/path/to/offer.token"
export OFFER_STORE_HTTP_TRUSTED_ROOTS="/path/to/ca.pem"
# Get offer details (JSON output)
swgr offer get default 6a38ebdd-83ef-4b94-b843-3b18cd90a833 --output offer-details.json
# Get all offers in partition (JSON output)
swgr offer get default
# Create a new offer from JSON file
swgr offer post --input offer.json
# Update an existing offer
swgr offer put default 6a38ebdd-83ef-4b94-b843-3b18cd90a833 --input updated-offer.json
# Delete an offer
swgr offer delete default 6a38ebdd-83ef-4b94-b843-3b18cd90a833# Generate a template metadata configuration
swgr offer metadata new --output metadata-template.json
# Get metadata details (JSON output)
swgr offer metadata get default 88deff7e-ca45-4144-8fca-286a5a18fb1a --output metadata-details.json
# Get all metadata in partition (JSON output)
swgr offer metadata get default
# Create new metadata from JSON file
swgr offer metadata post --input metadata.json
# Update existing metadata
swgr offer metadata put default 88deff7e-ca45-4144-8fca-286a5a18fb1a --input updated-metadata.json
# Delete metadata
swgr offer metadata delete default 88deff7e-ca45-4144-8fca-286a5a18fb1aOffer OpenAPI schema: doc/offer-service-openapi.yaml.
Example offer configuration:
{
"partition": "default",
"id": "6a38ebdd-83ef-4b94-b843-3b18cd90a833",
"maxSendable": 1000000,
"minSendable": 1000000,
"metadataId": "88deff7e-ca45-4144-8fca-286a5a18fb1a",
"timestamp": "1970-01-01T00:00:00Z",
"expires": null
}Example metadata configuration:
{
"id": "88deff7e-ca45-4144-8fca-286a5a18fb1a",
"partition": "default",
"text": "mandatory offer text",
"longText": "optional long offer text",
"image": {
"png": "base64_encoded_png_data"
},
"identifier": {
"email": "optional@email.com"
}
}Metadata can include images in PNG or JPEG format, base64 encoded:
{"png": "base64_encoded_data"}{"jpeg": "base64_encoded_data"}Metadata identifiers can be:
{"email": "contact@example.com"}{"text": "contact@example.com"}