Zero dependencies. Pure net/http. Works with Rails, Sinatra, or plain Ruby.
gem install satsrail
Or add to your Gemfile:
gem "satsrail"
Then run bundle install
require "satsrail"
SatsRail.api_key = "sk_test_your_key_here"
Create config/initializers/satsrail.rb
SatsRail.configure do |config|
config.api_key = ENV["SATSRAIL_API_KEY"]
config.base_url = "https://satsrail.com" # default
config.timeout = 30 # seconds
end
ENV["SATSRAIL_API_KEY"]
order = SatsRail::Order.create(
amount_usd: 50.00,
description: "Order #1234",
metadata: {
customer_id: "cust_abc",
sku: "premium-plan"
}
)
puts order.id # "ord_..."
puts order.status # "pending"
puts order.lightning_invoice # bolt11 string (if auto-generated)
Pass generate_invoice: true to get a Lightning invoice in the same call:
order = SatsRail::Order.create(
amount_usd: 25.00,
description: "Subscription",
generate_invoice: true,
payment_method: "lightning"
)
puts order.invoice.bolt11 # lnbc...
# List all orders
orders = SatsRail::Order.list
# Filter by status
pending = SatsRail::Order.list(status: "pending")
# Pagination
page2 = SatsRail::Order.list(page: 2, per_page: 25)
orders.data.each do |order|
puts "#{order.id}: #{order.status} — $#{order.amount_usd}"
end
order = SatsRail::Order.retrieve("ord_abc123")
puts order.id
puts order.status
puts order.amount_usd
puts order.created_at
invoice = SatsRail::Invoice.generate(
order_id: "ord_abc123",
payment_method: "lightning"
)
puts invoice.id # "inv_..."
puts invoice.bolt11 # Lightning payment string
puts invoice.amount_sats
status = SatsRail::Invoice.status("inv_abc123")
puts status.paid # true or false
puts status.settled_at # timestamp if paid
puts status.amount_sats
# Poll until paid
def wait_for_payment(invoice_id)
loop do
s = SatsRail::Invoice.status(invoice_id)
return s if s.paid
sleep 2
end
end
Create a hosted checkout page — perfect when you don't want to build your own payment UI.
session = SatsRail::CheckoutSession.create(
amount_usd: 99.00,
description: "Annual Plan",
success_url: "https://yoursite.com/success",
cancel_url: "https://yoursite.com/cancel",
metadata: { plan: "annual" }
)
# Redirect customer to hosted checkout
puts session.url # https://satsrail.com/checkout/...
# In a Rails controller:
redirect_to session.url, allow_other_host: true
Verify webhook signatures to ensure events are genuinely from SatsRail.
class SatsrailWebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def create
signature = request.headers["X-SatsRail-Signature"]
payload = request.body.read
begin
event = SatsRail::Webhook.verify(payload, signature, "whsec_your_secret")
case event.type
when "order.paid"
Rails.logger.info "Order paid: #{event.data.id}"
# Fulfill the order
when "invoice.settled"
Rails.logger.info "Invoice settled: #{event.data.id}"
end
render json: { received: true }
rescue SatsRail::WebhookSignatureError => e
render plain: e.message, status: :bad_request
end
end
end
post "/webhooks/satsrail" do
signature = request.env["HTTP_X_SATSRAIL_SIGNATURE"]
payload = request.body.read
begin
event = SatsRail::Webhook.verify(payload, signature, "whsec_your_secret")
case event.type
when "order.paid"
puts "Order paid: #{event.data.id}"
end
{ received: true }.to_json
rescue SatsRail::WebhookSignatureError
halt 400, "Invalid signature"
end
end
begin
order = SatsRail::Order.create(amount_usd: 50.00)
rescue SatsRail::AuthenticationError
puts "Invalid API key"
rescue SatsRail::RateLimitError => e
puts "Rate limited — retry after #{e.retry_after}"
rescue SatsRail::SatsRailError => e
puts "API error: #{e.message} (#{e.code})"
end
Get your API key and accept Bitcoin payments in minutes.