Skip to main content

Environment Variables

Lightning Enable is a hosted SaaS. The API at api.lightningenable.com is deployed and operated by Lightning Enable — as a merchant you never run the server or set its server-side configuration. Your setup happens in the dashboard and via the merchant API.

This page covers two audiences:

  • For merchants — environment variables for the open-source MCP server that you run on your own machine so AI agents can pay over Lightning.
  • Platform operator reference — server-side settings used by Lightning Enable staff to operate the hosted platform. Documented for transparency; merchants never set these.

For merchants: MCP server configuration

The MCP (Model Context Protocol) server enables AI agents to use Lightning Enable tools. It runs locally (or wherever your agent runs) and is configured entirely through environment variables and a local config file — none of this touches the hosted platform.

Wallet Configuration

The MCP server is open-source (MIT) and free to install. 15 tools work out of the box with just a wallet configured below. 8 additional tools (2 producer + 6 Agent Service Agreement) unlock when you also set LIGHTNING_ENABLE_API_KEY.

Choose one wallet provider (listed in default priority order):

LND (Best for L402):

LND_REST_HOST=https://your-lnd-node:8080
LND_MACAROON_HEX=your-admin-macaroon-hex

Nostr Wallet Connect (NWC):

NWC_CONNECTION_STRING=nostr+walletconnect://pubkey?relay=wss://relay.example.com&secret=xxx

Strike (Recommended for USD users):

STRIKE_API_KEY=your-strike-api-key

OpenNode:

OPENNODE_API_KEY=your-opennode-api-key
OPENNODE_ENVIRONMENT=production # or "dev" for testnet
Wallet Priority

If multiple wallet credentials are configured, they are used in this order:

  1. LND (if LND_REST_HOST and LND_MACAROON_HEX are set)
  2. NWC (if NWC_CONNECTION_STRING is set)
  3. Strike (if STRIKE_API_KEY is set)
  4. OpenNode (if OPENNODE_API_KEY is set)

This order prioritizes wallets that return a preimage, which is required for L402. OpenNode does not return preimages, so L402 will not work with it. You can override the priority with the WALLET_PRIORITY environment variable (values: lnd, nwc, strike, opennode).

Only the first configured wallet is used.

Spending Limits Configuration

Budget limits are configured via ~/.lightning-enable/config.json:

{
"currency": "USD",
"tiers": {
"autoApprove": 0.10,
"logAndApprove": 1.00,
"formConfirm": 10.00,
"urlConfirm": 100.00
},
"limits": {
"maxPerPayment": 500.00,
"maxPerSession": 100.00
}
}

This file is created automatically on first run. AI agents cannot modify this file. At runtime, an agent can tighten its own caps via the configure_budget tool, but it can never raise them above the limits in this file.

See AI Spending Security for detailed configuration.

MCP Configuration Summary

VariableRequiredDefaultDescription
LND_REST_HOSTIf using LND-LND REST API host
LND_MACAROON_HEXIf using LND-LND admin macaroon in hex
NWC_CONNECTION_STRINGIf using NWC-Nostr Wallet Connect URI
STRIKE_API_KEYIf using Strike-Strike API key (preferred for USD)
OPENNODE_API_KEYIf using OpenNode-OpenNode API key with withdrawal permissions
OPENNODE_ENVIRONMENTNoproductionproduction or dev
WALLET_PRIORITYNo-Override default wallet priority (lnd, nwc, strike, or opennode)
LIGHTNING_ENABLE_API_KEYNo-Merchant API key; unlocks the 8 producer + ASA tools
Open-Source MCP Server

The MCP server is open-source (MIT) and free to install. 15 of the 23 tools work out of the box with just a wallet — no account or API key required. The remaining 8 tools (2 producer + 6 ASA) require LIGHTNING_ENABLE_API_KEY.

Merchant payment provider keys are NOT environment variables

Your Strike or OpenNode API key for accepting payments through Lightning Enable is configured in the dashboard (Settings → Payment Provider) or via the merchant API (PUT /api/merchant/strike-key / PUT /api/merchant/opennode-key) — never through environment variables. The STRIKE_API_KEY / OPENNODE_API_KEY variables above configure the MCP server's outgoing wallet only.

Platform operator reference (Lightning Enable staff)

Merchants never set these

Lightning Enable is hosted SaaS — everything below configures the platform itself and is managed by Lightning Enable staff on the production deployment. It is documented here for transparency and for internal operations. If you are a merchant, nothing in this section applies to you.

Required Configuration

Database Encryption Key

DB_ENCRYPTION_KEY=your-base64-encoded-32-byte-key

Purpose: Encrypts sensitive fields (API keys, provider keys) at rest using AES-256-GCM.

Generate a secure key:

# Linux/Mac
openssl rand -base64 32

# PowerShell
[Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))
Critical
  • BACKUP THIS KEY - If lost, all encrypted merchant data is permanently unrecoverable
  • NEVER CHANGE after deployment - existing encrypted data becomes unreadable

Admin API Key

ADMIN_API_KEY=your-secure-admin-key

Purpose: Authenticates internal admin API requests and Hangfire dashboard access for platform operators. Not used by merchants.

Recommended: Generate using the same method as DB_ENCRYPTION_KEY.

Database Connection

ConnectionStrings__DefaultConnection="Server=your-server;Database=LightningEnable;..."

Purpose: SQL Server connection string for the application database.

For Azure SQL with Entra ID authentication:

Server=your-server.database.windows.net;Database=LightningEnable;Authentication=Active Directory Managed Identity;

Stripe Configuration

All Stripe settings are required for subscription management.

Secret Key

Stripe__SecretKey=sk_live_xxxxxxxxxxxxx

Purpose: Server-side Stripe API authentication.

  • Production: Use sk_live_... keys
  • Development: Use sk_test_... keys

Publishable Key

Stripe__PublishableKey=pk_live_xxxxxxxxxxxxx

Purpose: Client-side Stripe Checkout initialization.

Webhook Secret

Stripe__WebhookSecret=whsec_xxxxxxxxxxxxx

Purpose: Verifies webhook signatures from Stripe.

Get this from: Stripe Dashboard → Webhooks → Select endpoint → Signing secret

Base URL

Stripe__BaseUrl=https://api.lightningenable.com

Purpose: Base URL for success/cancel redirect URLs after checkout.

Pricing Plans

{
"Stripe": {
"PricingPlans": {
"individual": {
"Name": "Agentic Commerce — Individual",
"Description": "Full L402 access for individual developers",
"PriceId": "price_xxxxxxxxxxxxx",
"PriceCents": 9900,
"TrialEligible": true,
"Features": [
"Full REST API access",
"L402 protocol support",
"Pay-per-request billing"
]
},
"standaloneapi": {
"Name": "Standalone API (Legacy)",
"Description": "Full L402 access for individual developers",
"PriceId": "price_xxxxxxxxxxxxx",
"PriceCents": 9900,
"Features": ["Full REST API access", "L402 protocol support"]
},
"kenticocommerce": {
"Name": "Kentico Commerce",
"Description": "Native Xperience by Kentico integration",
"PriceId": "price_xxxxxxxxxxxxx",
"PriceCents": 24900,
"TrialEligible": false,
"Features": ["Everything in Individual plan", "Xperience by Kentico integration"]
},
"l402": {
"Name": "Agentic Commerce — Business",
"Description": "Pay-per-request API monetization",
"PriceId": "price_xxxxxxxxxxxxx",
"PriceCents": 29900,
"TrialEligible": true,
"Features": ["Everything in Individual plan", "L402 protocol support", "Pay-per-request billing"]
}
}
}
}

Purpose: Maps product tiers to Stripe pricing. Each key (individual, standaloneapi, kenticocommerce, l402) maps to an object — not a bare price-ID string — with Name, Description, PriceId, PriceCents, an optional TrialEligible (a bool that defaults to false when omitted — e.g. standaloneapi above omits it), and a Features array.

Note — these keys are checkout-selection identifiers, not the stored Merchant.PlanTier value. The checkout flow looks up a PriceId by this key (StripeSettings.GetPriceId), and the Stripe webhook then derives the tier that's persisted to Merchant.PlanTier from the PriceId via PlanTierService.GetTierFromStripePriceIdnot from this key. That's why a couple of keys differ from their resulting tier ID: standaloneapi → tier standalone, kenticocommerce → tier standard. So the keys above are correct as written; they don't need to match the PlanTierService tier IDs.

Payment Provider Configuration

Lightning Enable supports multiple payment providers. These settings control the platform-wide defaults; each merchant supplies their own provider API key via the dashboard or merchant API.

Default Provider

PaymentProvider__Default=Strike

Values: Strike (default) or OpenNode

This sets the default provider for merchants that don't have an explicit provider configured. Per-merchant provider selection is available via the merchant settings API.

Strike Configuration

PaymentProvider__Strike__BaseUrl=https://api.strike.me/v1
SettingDefaultDescription
PaymentProvider:Strike:BaseUrlhttps://api.strike.me/v1Strike API base URL. Use https://api.dev.strike.me/v1 for sandbox. Platform-wide — not selectable per merchant.

Merchants configure their Strike API key via the merchant settings API. The key is encrypted at rest using AES-256-GCM.

Strike vs OpenNode
FeatureStrikeOpenNode
Invoice creation2-step (create + quote)Single step
Preimage supportDirect from APIParsed from BOLT11
Native refundsNo (uses payment-quotes)Yes
Webhook formatThin (entityId only)Full payload
CurrenciesBTC, USD, EUR, GBPBTC, USD
Best forL402, general paymentsRefund-heavy workflows

OpenNode Environment

OpenNode__Environment=production

Values:

Platform-wide — the hosted platform runs against OpenNode production, so merchants use production OpenNode API keys.

Webhook URL (Optional)

PaymentProvider__WebhookUrl=https://api.lightningenable.com/api/webhooks/opennode

Purpose: Override auto-detected webhook URL. Used as the callback URL for all payment providers (OpenNode and Strike).

Auto-detection order:

  1. PaymentProvider:WebhookUrl from config (if set)
  2. WEBSITE_HOSTNAME environment variable (Azure App Service)
  3. APP_URL environment variable (custom deployment)
  4. localhost:5096 (local development fallback)

L402 Configuration

Root Key

L402_ROOT_KEY=your-secret-l402-root-key

Purpose: Secret key for macaroon signing. Required in production.

caution

In development, a default key is used. Always set this in production.

L402 Options (appsettings.json)

{
"L402": {
"Enabled": true,
"ServiceName": "lightning-enable",
"Location": "https://api.lightningenable.com",
"DefaultPriceSats": 100,
"InvoiceExpirySeconds": 600,
"DefaultTokenValiditySeconds": 3600,
"CacheVerifiedTokens": true,
"TokenCacheSeconds": 300,
"AllowLegacyLsatScheme": true,
"MaxProxyRequestBodyBytes": 1048576,
"MaxProxyResponseBodyBytes": 10485760,
"ProtectedPaths": ["/api/l402/*"],
"ExcludedPaths": ["/api/l402/pricing", "/api/l402/status"],
"EndpointPricing": [
{
"PathPattern": "/api/l402/demo",
"PriceSats": 1,
"ServiceName": "demo",
"TokenValiditySeconds": 3600
}
]
}
}
SettingDefaultDescription
EnabledtrueEnable L402 authentication middleware
ServiceNamelightning-enableService identifier in macaroons
Location-Base URL for the service
DefaultPriceSats100Default price in satoshis for unpriced endpoints
InvoiceExpirySeconds600Lightning invoice expiry (10 min)
DefaultTokenValiditySeconds3600Token validity period (1 hour)
CacheVerifiedTokenstrueCache verified tokens for performance
TokenCacheSeconds300Token cache duration (5 min)
AllowLegacyLsatSchemetrueAccept the legacy "LSAT" auth scheme in addition to "L402"
MaxProxyRequestBodyBytes1048576Max request body size through L402 proxy (1 MB). Set to 0 to disable
MaxProxyResponseBodyBytes10485760Max response body size through L402 proxy (10 MB). Set to 0 to disable
ProtectedPaths[]Glob patterns for protected endpoints
ExcludedPaths[]Glob patterns to exclude from L402
EndpointPricing[]Per-endpoint pricing rules (array of PathPattern, PriceSats, ServiceName, TokenValiditySeconds)

CORS Configuration

{
"AllowedOrigins": [
"https://yourapp.com",
"https://admin.yourapp.com"
]
}

Purpose: Restrict browser-based API access to specific domains.

  • Production: List all legitimate client domains
  • Development: Automatically allows common localhost ports
  • Empty array: API not accessible from browsers

Merchant-specific origins (e.g., Shopify storefronts) are additionally covered by the dynamic per-merchant origin registry — merchants don't need entries here.

Logging Configuration

{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "logs/lightning-enable-.txt",
"rollingInterval": "Day"
}
}
]
}
}

Development Configuration

For local development, use appsettings.Development.json:

{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=LightningEnable;Trusted_Connection=True;"
},
"AdminApiKey": "DEV-ADMIN-KEY-FOR-LOCAL-TESTING",
"OpenNode": {
"Environment": "dev"
},
"Stripe": {
"SecretKey": "sk_test_xxxxx",
"PublishableKey": "pk_test_xxxxx",
"WebhookSecret": "whsec_xxxxx",
"BaseUrl": "http://localhost:5096"
}
}

Default encryption key in development:

DEV-ENCRYPTION-KEY-DO-NOT-USE-IN-PRODUCTION-12345678

Production Checklist

Before deploying to production, ensure:

  • DB_ENCRYPTION_KEY is set and backed up securely
  • ADMIN_API_KEY is set to a secure value
  • ASPNETCORE_ENVIRONMENT=Production
  • Database connection string configured for production SQL Server
  • PaymentProvider__Default set (Strike recommended)
  • OpenNode:Environment=production for mainnet (if any merchants use OpenNode)
  • Stripe live keys configured (sk_live_..., pk_live_...)
  • Stripe webhook endpoint created in Stripe Dashboard
  • AllowedOrigins restricted to legitimate domains
  • L402_ROOT_KEY set (if using L402)
  • SSL/TLS certificate configured
  • Database migrations applied

Azure App Service Configuration

When deploying to Azure App Service, set these application settings:

Setting NameValue
ASPNETCORE_ENVIRONMENTProduction
DB_ENCRYPTION_KEY(from Key Vault)
ADMIN_API_KEY(from Key Vault)
L402_ROOT_KEY(from Key Vault)
ConnectionStrings__DefaultConnection(Azure SQL connection)
Stripe__SecretKey(from Key Vault)
Stripe__PublishableKeypk_live_...
Stripe__WebhookSecret(from Key Vault)
Stripe__BaseUrlhttps://api.lightningenable.com
PaymentProvider__DefaultStrike
OpenNode__Environmentproduction (if any merchants use OpenNode)
Use Key Vault References

For sensitive values, use Azure Key Vault references:

@Microsoft.KeyVault(SecretUri=https://your-vault.vault.azure.net/secrets/DB-ENCRYPTION-KEY/)

Next Steps