usage_credits

Demo app for the 💳✨ usage_credits gem

The basics: get and spend credits

 

Subscribe to a plan: Buy credit packs: Get arbitrary bonuses: Spend credits:

Ledger status

Date Amount Category Expiration
Jul 05, 5:20 PM +10 credits subscription_credits first_cycle expires in about 1 month

Payment records (pay gem)

The user has paid $0.0 total

Pay::Charge (0) none
Pay::Subscription (1)
# {
                         "id" => 436,
                "customer_id" => 1175,
                       "name" => "default",
               "processor_id" => "Ux9_KF-Bcxi_FLnuJmM34",
             "processor_plan" => "abcdef123456",
                   "quantity" => 1,
                     "status" => "active",
       "current_period_start" => nil,
         "current_period_end" => nil,
              "trial_ends_at" => nil,
                    "ends_at" => nil,
                    "metered" => nil,
             "pause_behavior" => nil,
            "pause_starts_at" => nil,
           "pause_resumes_at" => nil,
    "application_fee_percent" => nil,
                   "metadata" => {
                   "purchase_type" => "credit_subscription",
               "subscription_name" => "test_plan",
              "fulfillment_period" => "1 month",
              "credits_per_period" => 10,
            "signup_bonus_credits" => 0,
                   "trial_credits" => 0,
                "rollover_enabled" => false,
        "expire_credits_on_cancel" => false,
        "credit_expiration_period" => nil,
                        "metadata" => {}
    },
                       "data" => nil,
             "stripe_account" => nil,
          "payment_method_id" => nil,
                 "created_at" => 2025-07-05 17:20:00.182837000 UTC +00:00,
                 "updated_at" => 2025-07-05 17:20:00.182837000 UTC +00:00,
                       "type" => "Pay::FakeProcessor::Subscription",
                    "prorate" => true
}

Model records

UsageCredits::Fulfillment (1)
# {
                          :id => 1350,
                   :wallet_id => 1175,
                 :source_type => "Pay::Subscription",
                   :source_id => 436,
    :credits_last_fulfillment => 10,
            :fulfillment_type => "subscription",
           :last_fulfilled_at => 2025-07-05 17:20:00.191325000 UTC +00:00,
         :next_fulfillment_at => 2025-08-05 17:20:00.182837000 UTC +00:00,
          :fulfillment_period => "1 month",
                    :stops_at => nil,
                    :metadata => {
        "subscription_id" => 436,
                   "plan" => "abcdef123456"
    },
                  :created_at => 2025-07-05 17:20:00.192310000 UTC +00:00,
                  :updated_at => 2025-07-05 17:20:00.192310000 UTC +00:00
}
UsageCredits::Transaction (1)
# {
                :id => 2110,
         :wallet_id => 1175,
            :amount => 10,
          :category => "subscription_credits",
        :expires_at => 2025-08-05 17:25:00.182837000 UTC +00:00,
    :fulfillment_id => 1350,
          :metadata => {
        "subscription_id" => 436,
                 "reason" => "first_cycle",
                   "plan" => "abcdef123456",
           "fulfilled_at" => "2025-07-05T17:20:00.187Z"
    },
        :created_at => 2025-07-05 17:20:00.189509000 UTC +00:00,
        :updated_at => 2025-07-05 17:20:00.189509000 UTC +00:00
}
UsageCredits::Allocation (0) none

Audit trail

Audit trail
[
    [0] [
        [0] "subscription_credits",
        [1] 10,
        [2] {
            "subscription_id" => 436,
                     "reason" => "first_cycle",
                       "plan" => "abcdef123456",
               "fulfilled_at" => "2025-07-05T17:20:00.187Z"
        }
    ]
]

Loaded config

Literal, raw config file
      # frozen_string_literal: true

UsageCredits.configure do |config|

  # Default test operations
  operation :small_operation do
    costs 1.credit
  end

  # operation :test_operation do
  #   costs 10.credits + 1.credits_per(:mb)
  #   validate ->(params) { params[:size].to_i <= 100.megabytes }, "File too large (max: 100 MB)"
  # end

  operation :prohibitive_operation do
    costs 1_000_000.credits
  end

  operation :this_operation_will_always_fail do
    costs 42.credits
  end


  # Define test credit packs
  credit_pack :tiny do
    gives 10.credits
    costs 99.cents
  end

  credit_pack :starter do
    gives 1000.credits
    costs 49.dollars
  end

  credit_pack :pro do
    gives 5000.credits
    bonus 100.credits  # Optional: give bonus credits
    costs 199.dollars
    currency :usd
  end


  # Define subscriptions
  subscription_plan :test_plan do
    processor_plan(:fake_processor, "abcdef123456")
    gives 10.credits.every(:month)
    unused_credits :expire
  end

  # Alert when balance drops below 100 credits
  # Set to nil to disable low balance alerts
  # config.low_balance_threshold = 20.credits

  # # Handle low credit balance alerts
  # config.on_low_balance do |user|
  #   # Send notification to user when their balance drops below the threshold
  #   ApplicationMailer.generic_email(to: user.email, body: "Heads up! You're low on credits.", subject: "Low credits alert").deliver_now
  # end

end

    
Credit-consuming operations
Credit packs
Credit subscription plans
Rest of the config
      {
  "default_currency": "usd",
  "rounding_strategy": "ceil",
  "credit_formatter": {},
  "fulfillment_grace_period": 300,
  "allow_negative_balance": false,
  "low_balance_threshold": null,
  "low_balance_callback": null
}