3 Developer

3.1 API Reference

3.1.1 Manage Lightning Node Backends With Discovery Service

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.json

3.1.1.1 REST API

The Discovery Service provides a REST API for backend management. All endpoints except /health require bearer token authentication.

3.1.1.1.1 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)
3.1.1.1.2 Register A New Backend
# 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
    }
  }'
3.1.1.1.3 List All Backends
curl -X GET http://localhost:3001/discovery \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.1.1.4 Get A Specific Backend
# By public key
curl -X GET "http://localhost:3001/discovery/0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.1.1.5 Update A Backend
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"}
          }
        }
      }
    }
  }'
3.1.1.1.6 Delete A Backend
curl -X DELETE "http://localhost:3001/discovery/0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.1.1.7 Health Check
# No authentication required
curl http://localhost:3001/health

3.1.1.2 CLI

The swgr discovery command provides the same functionality as the REST interface for remote management of Lightning Node backends.

3.1.1.2.1 Token Management
# 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
3.1.1.2.2 Backend Management
# 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 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

3.1.1.3 Discovery Data Model

Discovery 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.

3.1.2 Manage LNURLs With Offer Service

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.json

3.1.2.1 LNURL

An Offer has two fields that combine to create a unique identifier:

Both fields are used to make the final public LNURL:

https://{host}/offers/{partition}/{id}

3.1.2.2 REST API

The Offer service provides a REST API for offer and metadata management. All endpoints except /health require bearer token authentication.

3.1.2.2.1 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)
3.1.2.2.2 Create A New Offer
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"
  }'
3.1.2.2.3 List All Offers In A Partition
curl -X GET http://localhost:3002/offers/default \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.2.2.4 Get A Specific Offer
curl -X GET "http://localhost:3002/offers/default/6a38ebdd-83ef-4b94-b843-3b18cd90a833" \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.2.2.5 Update An Offer
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"
  }'
3.1.2.2.6 Delete An Offer
curl -X DELETE "http://localhost:3002/offers/default/6a38ebdd-83ef-4b94-b843-3b18cd90a833" \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.2.2.7 Create Metadata
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"
    }
  }'
3.1.2.2.8 List All Metadata In A Partition
curl -X GET http://localhost:3002/metadata/default \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.2.2.9 Get Specific Metadata
curl -X GET "http://localhost:3002/metadata/default/88deff7e-ca45-4144-8fca-286a5a18fb1a" \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.2.2.10 Update Metadata
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"
    }
  }'
3.1.2.2.11 Delete Metadata
curl -X DELETE "http://localhost:3002/metadata/default/88deff7e-ca45-4144-8fca-286a5a18fb1a" \
  -H "Authorization: Bearer $AUTH_TOKEN"
3.1.2.2.12 Health Check
# No authentication required
curl http://localhost:3002/health

3.1.2.3 CLI

The swgr offer command provides the same functionality as the REST interface for remote management of Lightning payment offers and metadata.

3.1.2.3.1 Token Management
# 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
3.1.2.3.2 Offer Management
# 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
3.1.2.3.3 Metadata Management
# 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-286a5a18fb1a

3.1.2.4 Offer Data Model

Offer 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"
  }
}
3.1.2.4.1 Image Support

Metadata can include images in PNG or JPEG format, base64 encoded:

3.1.2.4.2 Identifier Types

Metadata identifiers can be: