Project

polar-ruby

0.0
No release in over 3 years
A comprehensive Ruby SDK for Polar.sh, providing easy integration with their payment infrastructure, subscription management, and merchant services.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 13.0
~> 3.0
~> 1.21
~> 0.21
~> 6.0
~> 3.0
~> 0.9

Runtime

 Project Readme

Polar Ruby SDK

Note: This SDK was generated with the help of AI and is not an official SDK from Polar.sh. It is a community project and not affiliated with or endorsed by Polar.sh. Contributions, suggestions, and improvements are very welcome!

A comprehensive Ruby SDK for Polar.sh, providing easy integration with their payment infrastructure, subscription management, and merchant services.

Gem Version Ruby License: MIT

Features

  • Complete API Coverage: Access all Polar.sh API endpoints
  • Type Safety: Well-structured response objects and error handling
  • Authentication: Support for Organization Access Tokens and Customer Sessions
  • Pagination: Built-in pagination support for list endpoints
  • Retry Logic: Automatic retries with exponential backoff
  • Webhook Verification: Secure webhook signature validation
  • Environment Support: Production and sandbox environments
  • Customer Portal: Dedicated customer-facing API endpoints
  • Ruby Compatibility: Supports Ruby 2.7+

Table of Contents

  • Installation
  • Quick Start
  • Authentication
  • Configuration
  • Core API Resources
  • Customer Portal API
  • Pagination
  • Error Handling
  • Webhook Verification
  • Environment Support
  • Examples
  • Development
  • Contributing

Installation

Add this line to your application's Gemfile:

gem 'polar-ruby'

And then execute:

bundle install

Or install it yourself as:

gem install polar-ruby

Quick Start

require 'polar'

# Initialize client with Organization Access Token
client = Polar.new(access_token: 'polar_oat_your_token_here')

# List organizations
organizations = client.organizations.list.auto_paginate
puts organizations.first

# Create a product
product = client.products.create({
  name: "Premium Plan",
  description: "Access to premium features",
  organization_id: "org_123"
})

# List customers with pagination
client.customers.list.each do |customer|
  puts "Customer: #{customer['name']} (#{customer['email']})"
end

Authentication

Organization Access Tokens (OAT)

Use an OAT to act on behalf of your organization. Create tokens in your organization settings.

# Via initialization
client = Polar.new(access_token: 'polar_oat_your_token_here')

# Via environment variable
ENV['POLAR_ACCESS_TOKEN'] = 'polar_oat_your_token_here'
client = Polar.new

# Via global configuration
Polar.configure do |config|
  config.access_token = 'polar_oat_your_token_here'
end
client = Polar.new

Customer Sessions

For customer-facing operations, use customer session tokens:

# Customer portal operations require customer session
customer_client = Polar.new(customer_session: 'customer_session_token')

# Or pass session token to individual calls
orders = client.customer_portal.orders.list(customer_session: 'customer_session_token')

Configuration

Global Configuration

Polar.configure do |config|
  config.access_token = 'polar_oat_your_token_here'
  config.server = :sandbox  # :production (default) or :sandbox
  config.timeout = 30       # Request timeout in seconds
  config.retries = 3        # Number of retry attempts
  config.logger = Logger.new(STDOUT)
  config.debug = true       # Enable debug logging
end

Per-Client Configuration

client = Polar.new(
  access_token: 'polar_oat_your_token_here',
  server: :sandbox,
  timeout: 60,
  retries: 5,
  debug: true
)

Environment Variables

The SDK respects the following environment variables:

  • POLAR_ACCESS_TOKEN: Default access token
  • POLAR_DEBUG: Enable debug logging (set to 'true')

Core API Resources

Organizations

# List organizations
organizations = client.organizations.list.auto_paginate

# Get organization
org = client.organizations.get('org_123')

# Create organization
new_org = client.organizations.create({
  name: "My Company",
  slug: "my-company"
})

# Update organization
updated_org = client.organizations.update('org_123', { name: "Updated Name" })

Products

# List products
products = client.products.list(organization_id: 'org_123').auto_paginate

# Create product
product = client.products.create({
  name: "Premium Plan",
  description: "Access to premium features",
  organization_id: "org_123",
  prices: [
    {
      type: "recurring",
      amount: 2000,  # $20.00 in cents
      currency: "USD",
      recurring: { interval: "month" }
    }
  ]
})

# Get product
product = client.products.get('prod_123')

# Update product
updated_product = client.products.update('prod_123', { name: "New Name" })

Customers

# List customers
customers = client.customers.list(organization_id: 'org_123')

# Create customer
customer = client.customers.create({
  email: "customer@example.com",
  name: "John Doe",
  organization_id: "org_123"
})

# Get customer
customer = client.customers.get('cust_123')

# Update customer
updated_customer = client.customers.update('cust_123', { name: "Jane Doe" })

# Get customer by external ID
customer = client.customers.get_external('external_123', organization_id: 'org_123')

Orders

# List orders
orders = client.orders.list(organization_id: 'org_123')

# Get order
order = client.orders.get('order_123')

# Update order
updated_order = client.orders.update('order_123', { metadata: { key: "value" } })

# Generate invoice
invoice = client.orders.generate_invoice('order_123')

Payments

# List payments
payments = client.payments.list(organization_id: 'org_123')

# Get payment
payment = client.payments.get('pay_123')

Subscriptions

# List subscriptions
subscriptions = client.subscriptions.list(organization_id: 'org_123')

# Get subscription
subscription = client.subscriptions.get('sub_123')

# Update subscription
updated_sub = client.subscriptions.update('sub_123', { metadata: { key: "value" } })

# Cancel subscription
cancelled_sub = client.subscriptions.revoke('sub_123')

Checkouts

# Create checkout session
checkout = client.checkouts.create({
  product_price_id: "price_123",
  success_url: "https://yoursite.com/success",
  cancel_url: "https://yoursite.com/cancel",
  customer_data: {
    email: "customer@example.com"
  }
})

# Get checkout session
checkout = client.checkouts.get('checkout_123')

# Client-side operations (no auth required)
checkout = client.checkouts.client_get('checkout_123')
updated_checkout = client.checkouts.client_update('checkout_123', { customer_data: { name: "John" } })
confirmed_checkout = client.checkouts.client_confirm('checkout_123')

Customer Portal API

The Customer Portal API provides customer-facing endpoints with proper scoping:

# Initialize with customer session
customer_client = Polar.new(customer_session: 'customer_session_token')

# Or pass session to individual calls
session_token = 'customer_session_token'

# Get customer information
customer = client.customer_portal.customers.get(customer_session: session_token)

# List customer orders
orders = client.customer_portal.orders.list(customer_session: session_token)

# Get specific order
order = client.customer_portal.orders.get('order_123', customer_session: session_token)

# List customer subscriptions
subscriptions = client.customer_portal.subscriptions.list(customer_session: session_token)

# Cancel subscription
client.customer_portal.subscriptions.cancel('sub_123', customer_session: session_token)

# List license keys
license_keys = client.customer_portal.license_keys.list(customer_session: session_token)

# Validate license key (no auth required)
validation = client.customer_portal.license_keys.validate('license_key_123')

# Activate license key
activation = client.customer_portal.license_keys.activate('license_key_123', {
  label: "Development Machine"
})

Pagination

The SDK provides automatic pagination support:

# Auto-paginate (loads all pages into memory)
all_customers = client.customers.list.auto_paginate

# Manual pagination
customers_paginated = client.customers.list(organization_id: 'org_123')

# Iterate through all pages
customers_paginated.each do |customer|
  puts "Customer: #{customer['name']}"
end

# Get specific page
page_2 = customers_paginated.page(2)

# Check pagination info
puts "Total: #{customers_paginated.count}"
puts "Pages: #{customers_paginated.total_pages}"

Error Handling

The SDK provides comprehensive error handling:

begin
  customer = client.customers.get('invalid_id')
rescue Polar::NotFoundError => e
  puts "Customer not found: #{e.message}"
rescue Polar::UnauthorizedError => e
  puts "Authentication failed: #{e.message}"
rescue Polar::ValidationError => e
  puts "Validation error: #{e.message}"
  puts "Status: #{e.status_code}"
  puts "Body: #{e.body}"
rescue Polar::HTTPError => e
  puts "HTTP error: #{e.status_code} - #{e.message}"
rescue Polar::ConnectionError => e
  puts "Connection error: #{e.message}"
rescue Polar::TimeoutError => e
  puts "Request timed out: #{e.message}"
rescue Polar::Error => e
  puts "Polar SDK error: #{e.message}"
end

Error Types

  • Polar::HTTPError - Base HTTP error class
  • Polar::BadRequestError - 400 Bad Request
  • Polar::UnauthorizedError - 401 Unauthorized
  • Polar::ForbiddenError - 403 Forbidden
  • Polar::NotFoundError - 404 Not Found
  • Polar::UnprocessableEntityError - 422 Validation Error
  • Polar::TooManyRequestsError - 429 Rate Limited
  • Polar::InternalServerError - 500 Server Error
  • Polar::ConnectionError - Network connection failed
  • Polar::TimeoutError - Request timeout
  • Polar::WebhookVerificationError - Webhook signature verification failed

Webhook Verification

Verify webhook signatures to ensure requests are from Polar:

# In your webhook endpoint (Rails example)
class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token

  def polar_webhook
    payload = request.body.read
    headers = request.headers
    secret = ENV['POLAR_WEBHOOK_SECRET']

    begin
      event = Polar::Webhooks.validate_event(payload, headers, secret)

      # Process the event
      case event['type']
      when 'order.created'
        handle_order_created(event['data'])
      when 'subscription.cancelled'
        handle_subscription_cancelled(event['data'])
      end

      render json: { status: 'ok' }
    rescue Polar::WebhookVerificationError => e
      render json: { error: 'Invalid signature' }, status: 403
    end
  end

  private

  def handle_order_created(order_data)
    # Process order creation
    puts "New order: #{order_data['id']}"
  end

  def handle_subscription_cancelled(subscription_data)
    # Process subscription cancellation
    puts "Cancelled subscription: #{subscription_data['id']}"
  end
end

Manual Webhook Verification

# Verify signature manually
valid = Polar::Webhooks.verify_signature(
  payload,
  timestamp,
  signature,
  secret
)

# Parse event type
event_type = Polar::Webhooks.parse_event_type(payload)

# Check specific event type
is_order_event = Polar::Webhooks.event_type?(payload, 'order.created')

# Create event wrapper
event = Polar::Webhooks::Event.new(payload)
puts "Event ID: #{event.id}"
puts "Event Type: #{event.type}"
puts "Is subscription event: #{event.subscription_event?}"

Environment Support

Production Environment

# Default environment
client = Polar.new(access_token: 'polar_oat_prod_token')

# Explicit production
client = Polar.new(
  access_token: 'polar_oat_prod_token',
  server: :production
)

Sandbox Environment

# Sandbox environment for testing
client = Polar.new(
  access_token: 'polar_oat_sandbox_token',
  server: :sandbox
)

# Custom base URL
client = Polar.new(
  access_token: 'polar_oat_token',
  base_url: 'https://custom-api.polar.sh/v1'
)

Examples

E-commerce Integration

class PolarService
  def initialize
    @client = Polar.new(access_token: ENV['POLAR_ACCESS_TOKEN'])
  end

  def create_checkout_for_product(product_id, customer_email, success_url, cancel_url)
    @client.checkouts.create({
      product_price_id: product_id,
      success_url: success_url,
      cancel_url: cancel_url,
      customer_data: {
        email: customer_email
      }
    })
  end

  def get_customer_orders(customer_id)
    @client.orders.list(customer_id: customer_id).auto_paginate
  end

  def create_subscription_checkout(price_id, customer_data)
    @client.checkouts.create({
      product_price_id: price_id,
      success_url: "#{ENV['APP_URL']}/subscription/success",
      cancel_url: "#{ENV['APP_URL']}/subscription/cancel",
      customer_data: customer_data
    })
  end
end

License Key Management

class LicenseManager
  def initialize
    @client = Polar.new(access_token: ENV['POLAR_ACCESS_TOKEN'])
  end

  def validate_license(license_key)
    result = @client.customer_portal.license_keys.validate(license_key)
    {
      valid: result['valid'],
      customer: result['customer'],
      product: result['product']
    }
  rescue Polar::Error => e
    { valid: false, error: e.message }
  end

  def activate_license(license_key, machine_info)
    @client.customer_portal.license_keys.activate(license_key, {
      label: machine_info[:name],
      metadata: {
        os: machine_info[:os],
        version: machine_info[:version]
      }
    })
  rescue Polar::Error => e
    { error: e.message }
  end
end

Subscription Management

class SubscriptionManager
  def initialize
    @client = Polar.new(access_token: ENV['POLAR_ACCESS_TOKEN'])
  end

  def get_customer_subscriptions(customer_session)
    @client.customer_portal.subscriptions.list(
      customer_session: customer_session
    ).auto_paginate
  end

  def cancel_subscription(subscription_id, customer_session)
    @client.customer_portal.subscriptions.cancel(
      subscription_id,
      customer_session: customer_session
    )
  end

  def update_subscription(subscription_id, updates, customer_session)
    @client.customer_portal.subscriptions.update(
      subscription_id,
      updates,
      customer_session: customer_session
    )
  end
end

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

Running Tests

# Run all tests
bundle exec rspec

# Run with coverage
bundle exec rspec --format documentation

# Run specific test file
bundle exec rspec spec/polar/client_spec.rb

Documentation

Generate documentation:

bundle exec yard doc

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/polarsource/polar-ruby. This project is intended to be a safe, welcoming space for collaboration.

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

License

The gem is available as open source under the terms of the MIT License.

Support