Vortex Ruby SDK

A Ruby SDK for the Vortex invitation system, providing seamless integration with the same functionality and API compatibility as other Vortex SDKs (Node.js, Python, Java, Go).

Features

  • JWT Generation: Identical algorithm to other SDKs for complete compatibility
  • Simplified JWT Format: New streamlined payload with userEmail and adminScopes
  • Backward Compatible: Legacy JWT format still supported
  • Complete API Coverage: All invitation management operations
  • Framework Integration: Built-in Rails and Sinatra helpers
  • Same Route Structure: Ensures React provider compatibility
  • Comprehensive Testing: Full test coverage with RSpec
  • Type Safety: Clear method signatures and documentation
  • Multiple Delivery Types: Support for email, phone, share, and internal invitation delivery
    • internal invitations allow for customer-managed, in-app invitation flows with no external communication

Installation

Add this line to your application's Gemfile:

gem 'vortex-ruby-sdk'

And then execute:

bundle install

Or install it yourself as:

gem install vortex-ruby-sdk

Basic Usage

require 'vortex'

# Initialize the client
client = Vortex::Client.new(ENV['VORTEX_API_KEY'])

# Create a user object
user = {
  id: 'user-123',
  email: '[email protected]',
  user_name: 'Jane Doe',                                    # Optional: user's display name
  user_avatar_url: 'https://example.com/avatars/jane.jpg',  # Optional: user's avatar URL
  admin_scopes: ['autojoin']                                # Optional: grants autojoin admin privileges
}

# Generate JWT
jwt = client.generate_jwt(user: user)

# Get invitations by target
invitations = client.get_invitations_by_target('email', '[email protected]')

# Accept an invitation
client.accept_invitation('inv-123', { email: '[email protected]' })

# Get invitations by group
group_invitations = client.get_invitations_by_group('team', 'team1')

Rails Integration

Create a controller with Vortex routes:

# app/controllers/vortex_controller.rb
class VortexController < ApplicationController
  include Vortex::Rails::Controller

  private

  def authenticate_vortex_user
    # Return user data hash or nil
    admin_scopes = []
    admin_scopes << 'autojoin' if current_user.admin?

    {
      id: current_user.id,
      email: current_user.email,
      admin_scopes: admin_scopes
    }
  end

  def authorize_vortex_operation(operation, user)
    # Implement your authorization logic
    case operation
    when 'JWT', 'GET_INVITATIONS'
      true
    when 'REVOKE_INVITATION'
      user[:admin_scopes]&.include?('autojoin')
    else
      false
    end
  end

  def vortex_client
    @vortex_client ||= Vortex::Client.new(Rails.application.credentials.vortex_api_key)
  end
end

Add routes to config/routes.rb:

Rails.application.routes.draw do
  scope '/api/vortex', controller: 'vortex' do
    post 'jwt', action: 'generate_jwt'
    get 'invitations', action: 'get_invitations_by_target'
    get 'invitations/:invitation_id', action: 'get_invitation'
    delete 'invitations/:invitation_id', action: 'revoke_invitation'
    post 'invitations/accept', action: 'accept_invitations'
    get 'invitations/by-group/:group_type/:group_id', action: 'get_invitations_by_group'
    delete 'invitations/by-group/:group_type/:group_id', action: 'delete_invitations_by_group'
    post 'invitations/:invitation_id/reinvite', action: 'reinvite'
  end
end

Sinatra Integration

require 'sinatra/base'
require 'vortex/sinatra'

class MyApp < Sinatra::Base
  register Vortex::Sinatra

  configure do
    set :vortex_api_key, ENV['VORTEX_API_KEY']
  end

  def authenticate_vortex_user
    # Implement authentication logic
    user_id = request.env['HTTP_X_USER_ID']
    return nil unless user_id

    {
      id: user_id,
      email: '[email protected]',
      admin_scopes: []  # Optional
    }
  end

  def authorize_vortex_operation(operation, user)
    # Implement authorization logic
    user != nil
  end
end

API Methods

All methods match the functionality of other Vortex SDKs:

JWT Generation

  • generate_jwt(user:, extra: nil) - Generate JWT token
    • user: Hash with :id, :email, and optional :admin_scopes array
    • extra: Optional hash with additional properties to include in JWT payload

Invitation Management

  • get_invitations_by_target(target_type, target_value) - Get invitations by target
  • get_invitation(invitation_id) - Get specific invitation
  • revoke_invitation(invitation_id) - Revoke invitation
  • accept_invitation(invitation_id, user) - Accept an invitation
  • get_invitations_by_group(group_type, group_id) - Get group invitations
  • delete_invitations_by_group(group_type, group_id) - Delete group invitations
  • reinvite(invitation_id) - Reinvite user
  • sync_internal_invitation(creator_id, target_value, action, component_id) - Sync internal invitation action

Route Structure

The SDK provides these routes (same as other SDKs for React provider compatibility):

  • POST /api/vortex/jwt
  • GET /api/vortex/invitations?targetType=email&[email protected]
  • GET /api/vortex/invitations/:id
  • DELETE /api/vortex/invitations/:id
  • POST /api/vortex/invitations/accept
  • GET /api/vortex/invitations/by-group/:type/:id
  • DELETE /api/vortex/invitations/by-group/:type/:id
  • POST /api/vortex/invitations/:id/reinvite
  • POST /api/vortex/invitations/sync-internal-invitation

Sync Internal Invitation

If you're using internal delivery type invitations and managing the invitation flow within your own application, you can sync invitation decisions back to Vortex when users accept or decline invitations in your system.

# Sync an internal invitation action
result = client.sync_internal_invitation(
  'user-123',           # creator_id - The inviter's user ID in your system
  'user-456',           # target_value - The invitee's user ID in your system
  'accepted',           # action - "accepted" or "declined"
  'component-uuid'      # component_id - The widget component UUID
)

puts "Processed: #{result['processed']}"
puts "Invitation IDs: #{result['invitationIds']}"

Parameters:

  • creator_id (String) — The inviter's user ID in your system
  • target_value (String) — The invitee's user ID in your system
  • action ("accepted" | "declined") — The invitation decision
  • component_id (String) — The widget component UUID

Response:

  • processed (Integer) — Count of invitations processed
  • invitationIds (Array) — IDs of processed invitations

Use cases:

  • You handle invitation delivery through your own in-app notifications or UI
  • Users accept/decline invitations within your application
  • You need to keep Vortex updated with the invitation status

JWT Payload Structure

The SDK generates JWTs with the following payload structure:

{
  userId: 'user-123',
  userEmail: '[email protected]',
  adminScopes: ['autojoin'],  # Full array included if admin_scopes provided
  expires: 1234567890
}

Additional properties from the extra parameter are merged into the payload.

Error Handling

All methods raise Vortex::VortexError on failures:

begin
  jwt = client.generate_jwt(
    user: {
      id: 'user-123',
      email: '[email protected]'
    }
  )
rescue Vortex::VortexError => e
  logger.error "Vortex error: #{e.message}"
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.

To install this gem onto your local machine, run bundle exec rake install.

Contributing

Webhooks

The SDK provides built-in support for verifying and parsing incoming webhook events from Vortex.

require 'vortex'

webhooks = Vortex::Webhooks.new(secret: ENV['VORTEX_WEBHOOK_SECRET'])

# In your HTTP handler (Rails example):
class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token

  def create
    payload = request.body.read
    signature = request.headers['X-Vortex-Signature']

    begin
      event = webhooks.construct_event(payload, signature)
    rescue Vortex::WebhookSignatureError
      head :bad_request
      return
    end

    case event
    when Vortex::WebhookEvent
      Rails.logger.info "Webhook event: #{event.type}"
    when Vortex::AnalyticsEvent
      Rails.logger.info "Analytics event: #{event.name}"
    end

    head :ok
  end
end

Event Type Constants

if event.type == Vortex::WebhookEventTypes::INVITATION_ACCEPTED
  # Handle invitation accepted
end

Bug reports and pull requests are welcome on GitHub at https://github.com/vortexsoftware/vortex-ruby-sdk.

License

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