MetrifoxSDK Ruby Gem

A Ruby SDK for interacting with the Metrifox platform API.

Installation

Add this line to your application's Gemfile:

gem 'metrifox-sdk'

And then execute:

$ bundle install

Or install it yourself as:

$ gem install metrifox-sdk

Usage

Configuration

require 'metrifox-sdk'

# Initialize with configuration
METRIFOX_SDK = MetrifoxSDK.init({ api_key: "your-api-key"})

# Or set environment variable
ENV["METRIFOX_API_KEY"] = "your-api-key"
METRIFOX_SDK = MetrifoxSDK.init

# Override base URLs (e.g. for staging or self-hosted environments)
METRIFOX_SDK = MetrifoxSDK.init({
  api_key: "your-api-key",
  base_url: "https://api.staging.metrifox.com/api/v1/",
  meter_service_base_url: "https://api-meter.staging.metrifox.com/"
})

# The meter service URL can also be set via env var
ENV["METRIFOX_METER_SERVICE_BASE_URL"] = "https://api-meter.staging.metrifox.com/"

Access Control

# Check feature access
response = METRIFOX_SDK.usages.check_access({
  feature_key: "premium_feature",
  customer_key: "customer_123"
})

puts response["data"]["can_access"] # true/false

Access checks are now served by the Metrifox Meter service (https://api-meter.metrifox.com). Example response payload:

{
  "data": {
    "customer_key": "cust-mit7k5v8obzs",
    "feature_key": "feature_seats",
    "requested_quantity": 1,
    "can_access": true,
    "unlimited": false,
    "balance": 4,
    "used_quantity": 0,
    "entitlement_active": true,
    "prepaid": false,
    "wallet_balance": 0,
    "message": "Feature found"
  }
}

Usage Tracking

# Basic usage recording
response = METRIFOX_SDK.usages.record_usage({
  customer_key: "customer_123",
  event_name: "api_call",
  amount: 1,
  event_id: "evt_12345", # required idempotency key
  timestamp: (Time.now.to_f * 1000).to_i # recommended (milliseconds)
})
puts response["message"] # "Event received"
puts response["data"]["quantity"] # 1

The usage event endpoint now returns a simple payload with the recorded data and a message confirming the event reception.

You can send either an event_name or a feature_key when recording usage events.

# Advanced usage recording with additional fields
response = METRIFOX_SDK.usages.record_usage({
  customer_key: "customer_123",
  event_name: "api_call", # Or use feature_key
  amount: 1,
  event_id: "event_uuid_123", # required idempotency key
  credit_used: 5,
  timestamp: (Time.now.to_f * 1000).to_i,
  metadata: {
    source: "web_app",
    feature: "premium_search"
  }
})

# Using structured request object
usage_request = MetrifoxSDK::Types::UsageEventRequest.new(
  customer_key: "customer_123",
  feature_key: "feat_my_feat_234", # OR use event_name
  amount: 1,
  credit_used: 5,
  event_id: "event_uuid_123",
  timestamp: (Time.now.to_f * 1000).to_i,
  metadata: { source: "mobile_app" }
)

response = METRIFOX_SDK.usages.record_usage(usage_request)

Sample response body:

{
  "data": {
    "customer_key": "cust-mit7k5v8obzs",
    "quantity": 1,
    "feature_key": "feature_job_posts"
  },
  "message": "Event received"
}

Customer Management

# Create customer (customer_key is REQUIRED)
customer_data = {
  customer_key: "customer_123",  # Required - unique identifier for the customer
  customer_type: "BUSINESS",
  primary_email: "customer@example.com",
  legal_name: "Acme Corp",
  display_name: "ACME"
}

response = METRIFOX_SDK.customers.create(customer_data)

# Update customer (customer_key cannot be changed and is passed as a parameter)
update_data = {
  display_name: "ACME Corporation",
  website_url: "https://acme.com"
  # Note: customer_key is NOT included here - it's immutable
}

response = METRIFOX_SDK.customers.update("customer_123", update_data)

# Get customer
response = METRIFOX_SDK.customers.get_customer({ customer_key: "customer_123" })

# Get customer details
response = METRIFOX_SDK.customers.get_details({ customer_key: "customer_123" })

# Check for an active subscription
has_active_subscription = MetrifoxSDK.customers.has_active_subscription?(customer_key: "customer_123")
puts has_active_subscription # true or false

# List customers
response = METRIFOX_SDK.customers.list

# List customers with pagination
response = METRIFOX_SDK.customers.list({ page: 2, per_page: 10 })

# List customers with filters
response = METRIFOX_SDK.customers.list({ 
  search_term: "TechStart",
  customer_type: "BUSINESS",
  date_created: "2025-09-01"
})

# List customers with combined pagination and filters
response = METRIFOX_SDK.customers.list({ 
  page: 1,
  per_page: 5,
  search_term: "John",
  customer_type: "INDIVIDUAL"
})

# Delete customer
response = METRIFOX_SDK.customers.delete_customer({ customer_key: "customer_123" })

# Archive customer
response = METRIFOX_SDK.customers.archive("customer_123")

# Unarchive customer
response = METRIFOX_SDK.customers.unarchive("customer_123")

Bulk Create Customers

Create multiple customers in a single API call:

result = METRIFOX_SDK.customers.bulk_create({
  customers: [
    {
      customer_key: "customer_001",
      customer_type: "BUSINESS",
      primary_email: "contact@acme.com",
      legal_name: "Acme Corp",
      display_name: "Acme"
    },
    {
      customer_key: "customer_002",
      customer_type: "INDIVIDUAL",
      primary_email: "jane@example.com",
      first_name: "Jane",
      last_name: "Doe"
    }
  ]
})

puts result["data"]["total"]
puts result["data"]["successful_count"]
puts result["data"]["failed_count"]

CSV Upload

# Upload customers via CSV
response = METRIFOX_SDK.customers.upload_csv("/path/to/customers.csv")

puts response["data"]["total_customers"]
puts response["data"]["successful_upload_count"]

Checkout URL Generation

# Basic checkout URL generation
checkout_url = METRIFOX_SDK.checkout.url({
  offering_key: "your_offering_key"
})

# With optional billing interval
checkout_url = METRIFOX_SDK.checkout.url({
  offering_key: "your_offering_key",
  billing_interval: "monthly"
})

# With customer key for pre-filled checkout
checkout_url = METRIFOX_SDK.checkout.url({
  offering_key: "your_offering_key",
  billing_interval: "monthly",
  customer_key: "customer_123"
})

# Using structured config object
checkout_config = MetrifoxSDK::Types::CheckoutConfig.new(
  offering_key: "your_offering_key",
  billing_interval: "monthly",
  customer_key: "customer_123"
)

checkout_url = METRIFOX_SDK.checkout.url(checkout_config)

Card Collection URL

Generate a hosted URL for collecting a payment method against an existing subscription or order:

# For a subscription
url = METRIFOX_SDK.checkout.card_collection_url(subscription_id: "sub_uuid_123")

# For an order
url = METRIFOX_SDK.checkout.card_collection_url(order_id: "order_uuid_456")

Usage Events

# List usage events with optional filters and pagination
response = METRIFOX_SDK.usages.list_events(
  customer_key: "customer_123",   # optional
  feature_key: "feature_seats",   # optional
  page: 1,                        # optional
  per_page: 25                    # optional
)

response["data"].each do |event|
  puts "#{event['feature_key']}: #{event['quantity']} at #{event['timestamp']}"
end

Compute Quantity Price

Compute the price for a given quantity of a feature for a customer, based on their plan. Useful for previewing upgrade costs or showing the cost of additional usage before a customer commits.

response = METRIFOX_SDK.usages.quantity_price(
  customer_key: "customer_123",
  feature_key: "feature_interview_booking",
  quantity: 500
)

puts "#{response['data']['price']} #{response['data']['unit']}"

# For tiered pricing, inspect the per-tier breakdown
response["data"]["applied_tiers"].each do |tier|
  puts "  Tier #{tier['first_unit']}-#{tier['last_unit']}: #{tier['units_consumed']} units -> #{tier['tier_price']}"
end

Only available to tenants whose plan includes the finance API feature.

Wallets

# List wallets for a customer
response = METRIFOX_SDK.wallets.list("customer_123")
response["data"].each do |wallet|
  puts "#{wallet['name']}: #{wallet['balance']} #{wallet['credit_unit_plural']}"
end

# List credit allocations for a wallet (optionally filtered by status)
response = METRIFOX_SDK.wallets.list_credit_allocations("wallet_uuid_123")
response = METRIFOX_SDK.wallets.list_credit_allocations("wallet_uuid_123", status: "active")

# Get a single credit allocation with its transactions
response = METRIFOX_SDK.wallets.get_credit_allocation("alloc_uuid_123")
puts response["data"]["amount"]
response["data"]["transactions"].each do |txn|
  puts "  #{txn['amount']} at #{txn['created_at']}"
end

Subscriptions

# Get billing history for a subscription
response = METRIFOX_SDK.subscriptions.get_billing_history("subscription_uuid")
puts response["data"]
# Get entitlements summary for a subscription
response = METRIFOX_SDK.subscriptions.get_entitlements_summary("subscription_uuid")
puts response["data"]
# Get entitlements usage for a subscription
response = METRIFOX_SDK.subscriptions.get_entitlements_usage("subscription_uuid")
puts response["data"]

Bulk Assign Plan

Assign a plan to multiple customers at once:

result = METRIFOX_SDK.subscriptions.bulk_assign_plan(
  customer_keys: ["customer_001", "customer_002"],
  plan_key: "pro-plan",
  billing_interval: "monthly",          # optional
  currency_code: "USD",                 # optional
  items: [                              # optional: credit/feature quantities
    { credit_key: "api_credits", quantity: 500 }
  ],
  skip_invoice: false                   # optional
)

puts result["data"]["succeeded"]  # Array of successful assignments
puts result["data"]["failed"]     # Array of failures with error details

Using Client Instance


response = METRIFOX_SDK.usages.check_access({
  feature_key: "premium_feature",
  customer_key: "customer_123"
})

Type Safety with Structs

The SDK exposes lightweight structs for the usage and checkout helpers when you want a bit more structure:

# Usage events (event_id required for idempotency)
usage_request = MetrifoxSDK::Types::UsageEventRequest.new(
  customer_key: "customer_123",
  feature_key: "feature_seats",
  amount: 1,
  event_id: "event_uuid_123",
  timestamp: (Time.now.to_f * 1000).to_i,
  metadata: { source: "mobile_app" }
)

response = METRIFOX_SDK.usages.record_usage(usage_request)

# Checkout configuration
checkout_config = MetrifoxSDK::Types::CheckoutConfig.new(
  offering_key: "premium_plan",
  billing_interval: "monthly",
  customer_key: "customer_123"
)

checkout_url = METRIFOX_SDK.checkout.url(checkout_config)

Error Handling

begin
  response = METRIFOX_SDK.usages.check_access({
    feature_key: "premium_feature",
    customer_key: "customer_123"
  })
rescue MetrifoxSDK::APIError => e
  puts "API Error: #{e.message}"
rescue MetrifoxSDK::ConfigurationError => e
  puts "Configuration Error: #{e.message}"
end

SSL Certificate Handling

The SDK configures a custom OpenSSL::X509::Store with system default certificate paths for all HTTPS requests. This ensures reliable SSL connections across different Ruby and OpenSSL versions, including environments where strict CRL (Certificate Revocation List) checking may cause verification failures.

No additional configuration is needed — SSL is handled automatically when making API calls.

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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/metrifox_ruby_sdk.

License

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