Go implementation of the x402 payment standard for paywalled HTTP endpoints.
x402-go makes it simple to add crypto payments to HTTP APIs. This library provides:
- USDC helpers for easy payment setup across 8+ chains (Base, Polygon, Avalanche, Solana)
- Middleware for standard
net/http, Chi, Gin, and PocketBase frameworks - HTTP client with automatic payment handling
- Multi-chain support with automatic wallet selection
Use the USDC helpers to create payment requirements in just a few lines:
import (
"net/http"
"github.com/mark3labs/x402-go"
x402http "github.com/mark3labs/x402-go/http"
)
func main() {
// Create payment requirement using USDC helper
requirement, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.BaseMainnet,
Amount: "0.01", // Human-readable USDC amount
RecipientAddress: "0xYourAddress",
})
// Configure middleware
config := &x402http.Config{
FacilitatorURL: "https://facilitator.x402.rs",
PaymentRequirements: []x402.PaymentRequirement{requirement},
}
// Protect your endpoint
middleware := x402http.NewX402Middleware(config)
http.Handle("/data", middleware(yourHandler))
http.ListenAndServe(":8080", nil)
}That's it! The helper automatically:
- Converts "0.01" to atomic units (10000)
- Sets the correct USDC contract address
- Configures EIP-3009 domain parameters
- Applies sensible defaults
import (
"github.com/mark3labs/x402-go/evm"
x402http "github.com/mark3labs/x402-go/http"
)
// Create USDC token config using helper
token := x402.NewUSDCTokenConfig(x402.BaseMainnet, 1)
// Create signer with your wallet
signer, _ := evm.NewSigner(
evm.WithPrivateKey("0xYourKey"),
evm.WithNetwork("base"),
evm.WithToken(token.Address, token.Symbol, token.Decimals),
)
// Create client - payments happen automatically
client, _ := x402http.NewClient(x402http.WithSigner(signer))
resp, _ := client.Get("https://api.example.com/data")The library includes pre-configured USDC constants for these chains:
| Chain | Mainnet Constant | Testnet Constant |
|---|---|---|
| Base | BaseMainnet |
BaseSepolia |
| Polygon | PolygonMainnet |
PolygonAmoy |
| Avalanche | AvalancheMainnet |
AvalancheFuji |
| Solana | SolanaMainnet |
SolanaDevnet |
All USDC addresses are verified and include EIP-3009 parameters for EVM chains.
Let clients pay with USDC on any supported chain:
requirements := []x402.PaymentRequirement{}
// Accept Base USDC
baseReq, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.BaseMainnet,
Amount: "0.50",
RecipientAddress: "0xYourAddress",
})
requirements = append(requirements, baseReq)
// Or Polygon USDC
polygonReq, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.PolygonMainnet,
Amount: "0.50",
RecipientAddress: "0xYourAddress",
})
requirements = append(requirements, polygonReq)
// Or Solana USDC
solanaReq, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.SolanaMainnet,
Amount: "0.50",
RecipientAddress: "YourSolanaAddress",
})
requirements = append(requirements, solanaReq)
config := &x402http.Config{
FacilitatorURL: "https://facilitator.x402.rs",
PaymentRequirements: requirements,
}import (
"github.com/gin-gonic/gin"
"github.com/mark3labs/x402-go"
ginx402 "github.com/mark3labs/x402-go/http/gin"
)
func main() {
// Create payment requirement
requirement, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.BaseSepolia,
Amount: "0.01",
RecipientAddress: "0xYourAddress",
})
config := &x402http.Config{
FacilitatorURL: "https://facilitator.x402.rs",
PaymentRequirements: []x402.PaymentRequirement{requirement},
}
// Setup Gin with x402 middleware
r := gin.Default()
r.Use(ginx402.NewGinX402Middleware(config))
r.GET("/data", func(c *gin.Context) {
// Access payment details from context
if payment, exists := c.Get("x402_payment"); exists {
verifyResp := payment.(*x402http.VerifyResponse)
c.JSON(200, gin.H{
"data": "your response",
"payer": verifyResp.Payer,
})
return
}
c.JSON(402, gin.H{"error": "payment required"})
})
r.Run(":8080")
}See examples/gin/ for complete examples.
Chi uses the standard http.Handler middleware interface, so you can use the base middleware directly:
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/mark3labs/x402-go"
x402http "github.com/mark3labs/x402-go/http"
)
func main() {
// Create payment requirement
requirement, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.BaseSepolia,
Amount: "0.01",
RecipientAddress: "0xYourAddress",
})
config := &x402http.Config{
FacilitatorURL: "https://facilitator.x402.rs",
PaymentRequirements: []x402.PaymentRequirement{requirement},
}
// Setup Chi with x402 middleware (uses standard http.Handler interface)
r := chi.NewRouter()
r.Use(x402http.NewX402Middleware(config))
r.Get("/data", func(w http.ResponseWriter, r *http.Request) {
// Access payment details from context
if payment := r.Context().Value(x402http.PaymentContextKey); payment != nil {
verifyResp := payment.(*x402http.VerifyResponse)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"data": "your response", "payer": "` + verifyResp.Payer + `"}`))
return
}
w.WriteHeader(http.StatusPaymentRequired)
w.Write([]byte(`{"error": "payment required"}`))
})
http.ListenAndServe(":8080", r)
}See examples/chi/ for complete examples.
import (
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
"github.com/mark3labs/x402-go"
x402http "github.com/mark3labs/x402-go/http"
pbx402 "github.com/mark3labs/x402-go/http/pocketbase"
)
func main() {
app := pocketbase.New()
// Create payment requirement
requirement, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.BaseSepolia,
Amount: "0.01",
RecipientAddress: "0xYourAddress",
})
config := &x402http.Config{
FacilitatorURL: "https://facilitator.x402.rs",
PaymentRequirements: []x402.PaymentRequirement{requirement},
}
// Apply middleware to specific routes
app.OnRecordBeforeCreateRequest("protected_collection").BindFunc(func(e *core.RequestEvent) error {
middleware := pbx402.NewPocketBaseX402Middleware(config)
return middleware(e)
})
app.Start()
}See examples/pocketbase/ for complete examples.
Override defaults for specific use cases:
requirement, _ := x402.NewUSDCPaymentRequirement(x402.USDCRequirementConfig{
Chain: x402.BaseMainnet,
Amount: "2.50",
RecipientAddress: "0xYourAddress",
Scheme: "estimate", // Default: "exact"
MaxTimeoutSeconds: 600, // Default: 300
MimeType: "application/xml", // Default: "application/json"
})import (
"github.com/mark3labs/x402-go"
"github.com/mark3labs/x402-go/evm"
x402http "github.com/mark3labs/x402-go/http"
)
// Use USDC helper for token config
token := x402.NewUSDCTokenConfig(x402.BaseMainnet, 1)
signer, _ := evm.NewSigner(
evm.WithPrivateKey("0xYourPrivateKey"),
evm.WithNetwork("base"),
evm.WithToken(token.Address, token.Symbol, token.Decimals),
)
client, _ := x402http.NewClient(x402http.WithSigner(signer))
resp, _ := client.Get("https://api.example.com/data")Configure multiple wallets and the client will automatically choose the best one:
// Setup Base wallet
baseToken := x402.NewUSDCTokenConfig(x402.BaseMainnet, 1) // Priority 1 (highest)
baseSigner, _ := evm.NewSigner(
evm.WithPrivateKey("0xYourKey"),
evm.WithNetwork("base"),
evm.WithToken(baseToken.Address, baseToken.Symbol, baseToken.Decimals),
)
// Setup Solana wallet
solanaToken := x402.NewUSDCTokenConfig(x402.SolanaMainnet, 2) // Priority 2
solanaSigner, _ := svm.NewSigner(
svm.WithPrivateKey("YourSolanaKey"),
svm.WithNetwork("solana"),
svm.WithToken(solanaToken.Address, solanaToken.Symbol, solanaToken.Decimals),
)
// Client automatically selects appropriate wallet
client, _ := x402http.NewClient(
x402http.WithSigner(baseSigner),
x402http.WithSigner(solanaSigner),
)
// Works with any paywalled endpoint
resp, _ := client.Get("https://api.example.com/data")import (
"github.com/mark3labs/x402-go"
"github.com/mark3labs/x402-go/svm"
x402http "github.com/mark3labs/x402-go/http"
)
// Use USDC helper for token config
token := x402.NewUSDCTokenConfig(x402.SolanaMainnet, 1)
signer, _ := svm.NewSigner(
svm.WithPrivateKey("Base58PrivateKey"),
// Or load from file: svm.WithKeygenFile("~/.config/solana/id.json")
svm.WithNetwork("solana"),
svm.WithToken(token.Address, token.Symbol, token.Decimals),
)
client, _ := x402http.NewClient(x402http.WithSigner(signer))
resp, _ := client.Get("https://api.example.com/data")