L402Requests 0.3.0
dotnet add package L402Requests --version 0.3.0
NuGet\Install-Package L402Requests -Version 0.3.0
<PackageReference Include="L402Requests" Version="0.3.0" />
<PackageVersion Include="L402Requests" Version="0.3.0" />
<PackageReference Include="L402Requests" />
paket add L402Requests --version 0.3.0
#r "nuget: L402Requests, 0.3.0"
#:package L402Requests@0.3.0
#addin nuget:?package=L402Requests&version=0.3.0
#tool nuget:?package=L402Requests&version=0.3.0
L402-Requests (.NET)
Auto-paying L402 HTTP client for .NET. APIs behind Lightning paywalls just work.
L402Requests wraps HttpClient and automatically handles HTTP 402 responses by paying Lightning invoices and retrying with L402 credentials. It's a drop-in HTTP client where any API behind an L402 paywall "just works."
Install
dotnet add package L402Requests
Quick Start
using L402Requests;
using var client = new L402HttpClient();
var response = await client.GetAsync("https://api.example.com/paid-resource");
Console.WriteLine(await response.Content.ReadAsStringAsync());
That's it. The library detects your wallet from environment variables, pays the Lightning invoice when it gets a 402 response, and retries with L402 credentials.
Wallet Configuration
Set environment variables for your preferred wallet. The library auto-detects in this order:
| Priority | Wallet | Environment Variables | Preimage Support |
|---|---|---|---|
| 1 | LND | LND_REST_HOST, LND_MACAROON_HEX |
Yes |
| 2 | NWC | NWC_CONNECTION_STRING |
Yes (CoinOS, CLINK) |
| 3 | Strike | STRIKE_API_KEY |
Yes |
| 4 | OpenNode | OPENNODE_API_KEY |
Limited |
Recommended: Strike (full preimage support, no infrastructure required).
Strike (Recommended)
export STRIKE_API_KEY="your-strike-api-key"
LND
export LND_REST_HOST="https://localhost:8080"
export LND_MACAROON_HEX="your-admin-macaroon-hex"
export LND_TLS_CERT_PATH="/path/to/tls.cert" # optional
NWC (Nostr Wallet Connect)
export NWC_CONNECTION_STRING="nostr+walletconnect://pubkey?relay=wss://relay&secret=hex"
OpenNode
export OPENNODE_API_KEY="your-opennode-key"
Note: OpenNode does not return payment preimages, which limits L402 functionality. For full L402 support, use Strike, LND, or a compatible NWC wallet.
Budget Controls
Safety first — budgets are enabled by default to prevent accidental overspending:
using var client = new L402HttpClient(new L402Options
{
MaxSatsPerRequest = 500, // Max per single payment (default: 1000)
MaxSatsPerHour = 5000, // Hourly rolling limit (default: 10000)
MaxSatsPerDay = 25000, // Daily rolling limit (default: 50000)
AllowedDomains = ["api.example.com"], // Optional domain allowlist
});
If a payment would exceed any limit, BudgetExceededException is raised before the payment is attempted.
To disable budgets entirely:
using var client = new L402HttpClient(new L402Options { BudgetEnabled = false });
Explicit Wallet
using L402Requests;
using L402Requests.Wallets;
using var client = new L402HttpClient(new StrikeWallet("your-api-key"));
var response = await client.GetAsync("https://api.example.com/paid-resource");
DI / HttpClientFactory
// In Program.cs
builder.Services.AddL402HttpClient("myapi", options =>
{
options.MaxSatsPerRequest = 500;
options.MaxSatsPerHour = 5000;
options.AllowedDomains = ["api.example.com"];
});
// In consuming class
public class MyService(IHttpClientFactory factory)
{
public async Task<string> GetPaidData()
{
var client = factory.CreateClient("myapi");
var response = await client.GetAsync("https://api.example.com/paid-resource");
return await response.Content.ReadAsStringAsync();
}
}
Spending Introspection
Track every payment made during a session:
using var client = new L402HttpClient();
await client.GetAsync("https://api.example.com/data");
await client.GetAsync("https://api.example.com/more-data");
Console.WriteLine($"Total: {client.SpendingLog.TotalSpent()} sats");
Console.WriteLine($"Last hour: {client.SpendingLog.SpentLastHour()} sats");
Console.WriteLine($"By domain: {string.Join(", ", client.SpendingLog.ByDomain())}");
Console.WriteLine(client.SpendingLog.ToJson());
How It Works
- Your code makes an HTTP request via
L402HttpClient - If the server returns 200, the response is returned as-is
- If the server returns 402 with an L402 challenge:
- The
WWW-Authenticate: L402 macaroon="...", invoice="..."header is parsed - The BOLT11 invoice amount is checked against your budget
- The invoice is paid via your configured Lightning wallet
- The request is retried with
Authorization: L402 {macaroon}:{preimage}
- The
- Credentials are cached so subsequent requests to the same endpoint don't require re-payment
Error Handling
using L402Requests;
using var client = new L402HttpClient();
try
{
var response = await client.GetAsync("https://api.example.com/paid-resource");
}
catch (BudgetExceededException e)
{
Console.WriteLine($"Over budget: {e.LimitType} limit is {e.LimitSats} sats");
}
catch (PaymentFailedException e)
{
Console.WriteLine($"Payment failed: {e.Reason}");
}
catch (NoWalletException)
{
Console.WriteLine("No wallet configured");
}
| Exception | When |
|---|---|
BudgetExceededException |
Payment would exceed a budget limit |
PaymentFailedException |
Lightning payment failed |
InvoiceExpiredException |
Invoice expired before payment |
NoWalletException |
No wallet env vars detected |
DomainNotAllowedException |
Domain not in AllowedDomains |
ChallengeParseException |
Malformed L402 challenge header |
Usage with AI Agents
L402Requests is the consumer-side complement to the Lightning Enable MCP Server. While the MCP server gives AI agents wallet tools, L402Requests lets your .NET code access paid APIs without any agent framework.
Part of Lightning Enable — infrastructure for agent commerce over Lightning. See the full ecosystem.
Semantic Kernel Tool
using L402Requests;
using Microsoft.SemanticKernel;
public class PaidApiPlugin
{
private readonly L402HttpClient _client = new(new L402Options { MaxSatsPerRequest = 100 });
[KernelFunction("fetch_paid_api")]
[Description("Fetch data from an L402-protected API. Payment is handled automatically.")]
public async Task<string> FetchPaidApiAsync(string url)
{
var response = await _client.GetAsync(url);
return await response.Content.ReadAsStringAsync();
}
}
Standalone
using var client = new L402HttpClient();
var response = await client.GetAsync("https://api.example.com/premium-data");
What is L402?
L402 (formerly LSAT) is a protocol for monetizing APIs with Lightning Network micropayments. Instead of API keys or subscriptions, servers return HTTP 402 ("Payment Required") with a Lightning invoice. Once paid, the client receives a credential (macaroon + payment preimage) that grants access.
Learn more: docs.lightningenable.com
Example: MaximumSats API
MaximumSats provides paid Lightning Network APIs including AI DVM, WoT reports, Nostr analysis, and more. Use L402Requests to automatically pay for these endpoints:
using L402Requests;
using var client = new L402HttpClient();
var response = await client.GetAsync("https://maximumsats.com/api/dvm");
var data = await response.Content.ReadAsStringAsync();
Set your wallet via environment variable:
export STRIKE_API_KEY="your-strike-api-key"
The library automatically handles the L402 payment protocol — you just get the data.
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Http (>= 8.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.