Accept instant blockchain micropayments in your Rails applications using the x402 payment protocol.
Supports Base, avalanche, and other blockchain networks.
- 1 line of code to accept digital dollars (USDC)
- No fees on supported networks (Base)
- ~1 second response times (optimistic mode)
- $0.001 minimum payment amounts
- Optimistic & non-optimistic settlement modes
- Automatic settlement after successful responses
- Browser paywall and API support
- Rails 7.0+ compatible
x402-rails-video.mp4
Add to your Gemfile:
gem 'x402-rails'Then run:
bundle installCreate config/initializers/x402.rb:
X402.configure do |config|
config.wallet_address = ENV['X402_WALLET_ADDRESS'] # Your recipient wallet
config.facilitator = "https://x402.org/facilitator"
config.chain = "base-sepolia" # or "base" for base mainnet
config.currency = "USDC"
config.optimistic = false # Forces to check for settlement before giving response.
endUse x402_paywall in any controller action:
class ApiController < ApplicationController
def weather
x402_paywall(amount: 0.001) # $0.001 in USD
render json: {
temperature: 72,
paid_by: request.env['x402.payment'][:payer]
}
end
endThat's it! Your endpoint now requires payment.
Call x402_paywall in any action:
def show
x402_paywall(amount: 0.01)
# Action continues after payment verified
render json: @data
endProtect multiple actions:
class PremiumController < ApplicationController
before_action :require_payment, only: [:show, :index]
def show
# Payment already verified
render json: @premium_content
end
private
def require_payment
x402_paywall(amount: 0.001, chain: "base")
end
endDifferent prices for different actions:
def basic_data
x402_paywall(amount: 0.001)
render json: basic_info
end
def premium_data
x402_paywall(amount: 0.01)
render json: premium_info
endSet defaults in config/initializers/x402.rb:
X402.configure do |config|
# Required: Your wallet address where payments will be received
config.wallet_address = ENV['X402_WALLET_ADDRESS']
# Facilitator service URL (default: "https://x402.org/facilitator")
config.facilitator = ENV.fetch("X402_FACILITATOR_URL", "https://x402.org/facilitator")
# Blockchain network (default: "base-sepolia")
# Options: "base-sepolia", "base", "avalanche-fuji", "avalanche"
config.chain = ENV.fetch("X402_CHAIN", "base-sepolia")
# Payment token (default: "USDC")
# Currently only USDC is supported
config.currency = ENV.fetch("X402_CURRENCY","USDC")
# Optimistic mode (default: true)
# true: Fast response, settle payment after response is sent
# false: Wait for blockchain settlement before sending response
config.optimistic = ENV.fetch("X402_OPTIMISTIC",false)
end| Attribute | Required | Default | Description |
|---|---|---|---|
wallet_address |
Yes | - | Your Ethereum wallet address where payments will be received |
facilitator |
No | "https://x402.org/facilitator" |
Facilitator service URL for payment verification and settlement |
chain |
No | "base-sepolia" |
Blockchain network to use (base-sepolia, base, avalanche-fuji, avalanche) |
currency |
No | "USDC" |
Payment token symbol (currently only USDC supported) |
optimistic |
No | true |
Settlement mode (see Optimistic vs Non-Optimistic Mode below) |
rpc_urls |
No | {} |
Custom RPC endpoint URLs per chain (see Custom RPC URLs below) |
By default, x402-rails uses public QuickNode RPC endpoints for each supported chain. For production use or higher reliability, you can configure custom RPC URLs from providers like QuickNode.
Configuration Priority (highest to lowest):
- Programmatic configuration via
config.rpc_urls - Per-chain environment variables
- Built-in default RPC URLs
Configure RPC URLs in your initializer:
X402.configure do |config|
config.wallet_address = ENV['X402_WALLET_ADDRESS']
# Custom RPC URLs per chain
config.rpc_urls["base"] = "https://your-base-rpc.quiknode.pro/your-key"
config.rpc_urls["base-sepolia"] = "https://your-sepolia-rpc.quiknode.pro/your-key"
config.rpc_urls["avalanche"] = "https://your-avalanche-rpc.quiknode.pro/your-key"
endSet per-chain environment variables:
# Per-chain RPC URL overrides
X402_BASE_RPC_URL=https://your-base-rpc.quiknode.pro/your-key
X402_BASE_SEPOLIA_RPC_URL=https://your-sepolia-rpc.quiknode.pro/your-key
X402_AVALANCHE_RPC_URL=https://your-avalanche-rpc.quiknode.pro/your-key
X402_AVALANCHE_FUJI_RPC_URL=https://your-fuji-rpc.quiknode.pro/your-keyIf no custom RPC URL is configured, it will default to the public QuickNode RPC urls.
Configure via environment variables:
# Required
X402_WALLET_ADDRESS=0xYourAddress
# Optional (with defaults)
X402_FACILITATOR_URL=https://x402.org/facilitator
X402_CHAIN=base-sepolia
X402_CURRENCY=USDC
X402_OPTIMISTIC=true # "true" or "false"
# Custom RPC URLs (optional, per-chain overrides)
X402_BASE_RPC_URL=https://your-base-rpc.quiknode.pro/your-key
X402_BASE_SEPOLIA_RPC_URL=https://your-base-speoliarpc.quiknode.pro/your-key
X402_AVALANCHE_RPC_URL=https://your-avalanche.quiknode.pro/your-key
X402_AVALANCHE_FUJI_RPC_URL=https://your-fuji-rpc.quiknode.pro/your-keyclass WeatherController < ApplicationController
def current
x402_paywall(amount: 0.001)
render json: { temp: 72, condition: "sunny" }
end
def forecast
x402_paywall(amount: 0.01)
render json: { forecast: [...] }
end
end┌──────────┐ ┌──────────┐ ┌─────────────┐
│ Client │─────▶│ Rails │─────▶│ Facilitator │
│ │ │ x402 │ │ (x402.org) │
└──────────┘ └──────────┘ └─────────────┘
│ │ │
│ │ ▼
│ │ ┌──────────────┐
│ │ │ Blockchain │
│ │ │ (Base) │
└──────────────────┴─────────────┴──────────────┘
The gem raises these errors:
X402::ConfigurationError- Invalid configurationX402::InvalidPaymentError- Invalid payment payloadX402::FacilitatorError- Facilitator communication issues
- Payments validated via EIP-712 signatures
- Nonce prevents replay attacks
- Time windows limit authorization validity
- Facilitator verifies all parameters
- Settlement happens on-chain (immutable)
- Ruby 3.0+
- Rails 7.0+
MIT License. See LICENSE.txt.