risenexa-leads 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bf34b5b98cf6c49a1cba41db3e85d60e10967e51315c3fcbc0a69f172039c65b
4
+ data.tar.gz: 581d96bc497842f48c752e56cc472727f9d2c39fe60bad605a1ecdec6abda261
5
+ SHA512:
6
+ metadata.gz: a0ec6e59a6c61ce13587b19bd95d49054b7d42ea3a39bb3229219dcdd5c6164ca7deec18c25b43fd5354312b330897e8bf02d8e078dbb5379615da760aae1771
7
+ data.tar.gz: bce5295272ceb7d35257a043eb5bb57f464625d57022a54ac0991ee395c390e23544dfa9eefa2a5dff058a4cde1255a25346701f5f5cbd85afcbabbeb0498ab8
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-04-28
11
+
12
+ ### Added
13
+
14
+ - Initial release of the `risenexa-leads` gem
15
+ - Global configuration via `RisenexaLeads.configure` block (`api_key`, `startup_id`,
16
+ `base_url`, `timeout`)
17
+ - `RisenexaLeads.track` for capturing a single lead with email, name, plan tier,
18
+ source, language, external ID, UTM parameters, and custom properties
19
+ - `RisenexaLeads.batch` for sending up to 100 leads in a single request, with
20
+ partial-success handling
21
+ - `Result` object with `success?`, `partial_success?`, `created`, `errors`, and
22
+ `error` accessors for ergonomic response handling
23
+ - Faraday-based HTTP client with `faraday-retry` for transient failure recovery
24
+ - Argument validation for required fields and batch size limits
25
+ - RSpec test suite covering the public API (25 examples)
26
+ - MIT License
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Patrick Espake
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,245 @@
1
+ # Risenexa Leads
2
+
3
+ Ruby SDK for capturing leads and sending them to [Risenexa](https://app.risenexa.com) for AI-powered customer discovery.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'risenexa-leads'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ gem install risenexa-leads
23
+ ```
24
+
25
+ ## Configuration
26
+
27
+ Configure the gem with your API credentials. In a Rails app, create an initializer:
28
+
29
+ ```ruby
30
+ # config/initializers/risenexa_leads.rb
31
+
32
+ RisenexaLeads.configure do |config|
33
+ config.api_key = ENV['RISENEXA_API_KEY']
34
+ config.startup_id = ENV['RISENEXA_STARTUP_ID']
35
+
36
+ # Optional settings
37
+ config.base_url = 'https://app.risenexa.com' # Default
38
+ config.timeout = 30 # Default: 30 seconds
39
+ end
40
+ ```
41
+
42
+ ### Getting Your Credentials
43
+
44
+ 1. Log in to your Risenexa account
45
+ 2. Navigate to your Startup settings
46
+ 3. Copy your API key and Startup ID from the SDK Integration section
47
+
48
+ ## Usage
49
+
50
+ ### Track a Single Lead
51
+
52
+ ```ruby
53
+ result = RisenexaLeads.track(
54
+ email: 'john@example.com',
55
+ name: 'John Doe',
56
+ plan_tier: 'pro', # optional
57
+ source: 'signup_form', # optional
58
+ language: 'en', # optional, defaults to 'en'
59
+ external_id: 'user_12345', # optional, for idempotent upserts
60
+ utm_params: { # optional
61
+ source: 'google',
62
+ medium: 'cpc',
63
+ campaign: 'launch'
64
+ },
65
+ properties: { # optional, custom attributes
66
+ signup_reason: 'productivity',
67
+ team_size: 10
68
+ }
69
+ )
70
+
71
+ if result.success?
72
+ puts "Lead created: #{result.lead['id']}"
73
+ else
74
+ puts "Error: #{result.error}"
75
+ end
76
+ ```
77
+
78
+ ### Track Multiple Leads (Batch)
79
+
80
+ ```ruby
81
+ leads = [
82
+ { email: 'john@example.com', name: 'John Doe', plan_tier: 'pro' },
83
+ { email: 'jane@example.com', name: 'Jane Smith', plan_tier: 'starter' }
84
+ ]
85
+
86
+ result = RisenexaLeads.batch(leads)
87
+
88
+ if result.success?
89
+ puts "Created #{result.created.length} leads"
90
+ elsif result.partial_success?
91
+ puts "Created #{result.created.length} leads"
92
+ puts "Failed: #{result.errors.length}"
93
+ result.errors.each do |error|
94
+ puts " - #{error['email']}: #{error['errors'].join(', ')}"
95
+ end
96
+ else
97
+ puts "Error: #{result.error}"
98
+ end
99
+ ```
100
+
101
+ **Note:** Batch requests are limited to 100 leads per request.
102
+
103
+ ### Rails Integration Example
104
+
105
+ Track leads when users sign up:
106
+
107
+ ```ruby
108
+ # app/controllers/registrations_controller.rb
109
+ class RegistrationsController < ApplicationController
110
+ def create
111
+ @user = User.new(user_params)
112
+
113
+ if @user.save
114
+ # Track the lead asynchronously
115
+ TrackLeadJob.perform_later(@user.id)
116
+ redirect_to dashboard_path
117
+ else
118
+ render :new
119
+ end
120
+ end
121
+ end
122
+
123
+ # app/jobs/track_lead_job.rb
124
+ class TrackLeadJob < ApplicationJob
125
+ queue_as :default
126
+
127
+ def perform(user_id)
128
+ user = User.find(user_id)
129
+
130
+ RisenexaLeads.track(
131
+ email: user.email,
132
+ name: user.name,
133
+ external_id: "user_#{user.id}",
134
+ plan_tier: user.plan,
135
+ source: user.signup_source,
136
+ utm_params: user.utm_params,
137
+ properties: {
138
+ company: user.company_name,
139
+ role: user.job_title
140
+ }
141
+ )
142
+ end
143
+ end
144
+ ```
145
+
146
+ ## Response Objects
147
+
148
+ ### Result (for single leads)
149
+
150
+ ```ruby
151
+ result = RisenexaLeads.track(...)
152
+
153
+ result.success? # true if lead was created
154
+ result.failure? # true if there was an error
155
+ result.lead # Hash with lead data on success
156
+ result.error # Error message string on failure
157
+ result.errors # Array of validation errors (for 422 responses)
158
+ ```
159
+
160
+ ### BatchResult (for batch operations)
161
+
162
+ ```ruby
163
+ result = RisenexaLeads.batch(...)
164
+
165
+ result.success? # true if all leads were created
166
+ result.partial_success? # true if some leads were created
167
+ result.failure? # true if no leads were created
168
+ result.created # Array of created lead hashes
169
+ result.errors # Array of error hashes with index, email, and errors
170
+ result.error # General error message (for auth/rate limit errors)
171
+ ```
172
+
173
+ ## Error Handling
174
+
175
+ The SDK handles various error scenarios gracefully:
176
+
177
+ ```ruby
178
+ result = RisenexaLeads.track(email: 'test@example.com', name: 'Test')
179
+
180
+ case
181
+ when result.success?
182
+ # Lead created successfully
183
+ when result.errors.any?
184
+ # Validation errors (e.g., invalid email, duplicate)
185
+ result.errors.each { |e| puts e }
186
+ when result.error.include?('Rate limit')
187
+ # Too many requests, implement backoff
188
+ when result.error.include?('Invalid API token')
189
+ # Check your API key configuration
190
+ else
191
+ # Other error
192
+ puts result.error
193
+ end
194
+ ```
195
+
196
+ ### Configuration Errors
197
+
198
+ Missing configuration will raise `RisenexaLeads::ConfigurationError`:
199
+
200
+ ```ruby
201
+ RisenexaLeads.reset_configuration!
202
+ RisenexaLeads.track(email: 'test@example.com', name: 'Test')
203
+ # => raises RisenexaLeads::ConfigurationError: api_key is required
204
+ ```
205
+
206
+ ## Idempotency
207
+
208
+ Use `external_id` to make lead creation idempotent:
209
+
210
+ ```ruby
211
+ # First call creates the lead
212
+ RisenexaLeads.track(
213
+ email: 'john@example.com',
214
+ name: 'John Doe',
215
+ external_id: 'user_123'
216
+ )
217
+
218
+ # Second call with same external_id updates the existing lead
219
+ RisenexaLeads.track(
220
+ email: 'john.updated@example.com',
221
+ name: 'John Doe Updated',
222
+ external_id: 'user_123'
223
+ )
224
+ ```
225
+
226
+ ## Rate Limiting
227
+
228
+ The Risenexa API is rate limited to 100 requests per minute per API token. The SDK will return a failure result with a rate limit error message when exceeded.
229
+
230
+ ## Development
231
+
232
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
233
+
234
+ ```bash
235
+ bundle install
236
+ bundle exec rspec
237
+ ```
238
+
239
+ ## Contributing
240
+
241
+ Bug reports and pull requests are welcome on GitHub at https://github.com/patrickespake/risenexa-leads-gem.
242
+
243
+ ## License
244
+
245
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Risenexa
4
+ module Leads
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,262 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "faraday/retry"
5
+ require "json"
6
+
7
+ require_relative "leads/version"
8
+
9
+ module Risenexa
10
+ module Leads
11
+ class Error < StandardError; end
12
+ end
13
+ end
14
+
15
+ # Top-level module for convenient SDK access
16
+ module RisenexaLeads
17
+ class ConfigurationError < StandardError; end
18
+
19
+ class << self
20
+ attr_accessor :configuration
21
+
22
+ def configure
23
+ self.configuration ||= Configuration.new
24
+ yield(configuration)
25
+ end
26
+
27
+ def reset_configuration!
28
+ self.configuration = nil
29
+ @client = nil
30
+ end
31
+
32
+ def track(attributes)
33
+ validate_configuration!
34
+ client.track(attributes)
35
+ end
36
+
37
+ def batch(leads)
38
+ raise ArgumentError, "Batch requires at least one lead" if leads.empty?
39
+ raise ArgumentError, "Batch maximum is 100 leads" if leads.length > 100
40
+
41
+ validate_configuration!
42
+ client.batch(leads)
43
+ end
44
+
45
+ private
46
+
47
+ def validate_configuration!
48
+ raise ConfigurationError, "api_key is required" unless configuration&.api_key
49
+ raise ConfigurationError, "startup_id is required" unless configuration&.startup_id
50
+ end
51
+
52
+ def client
53
+ @client ||= Client.new(configuration)
54
+ end
55
+ end
56
+
57
+ class Configuration
58
+ attr_accessor :api_key, :startup_id, :base_url, :timeout
59
+
60
+ def initialize
61
+ @base_url = "https://app.risenexa.com"
62
+ @timeout = 30
63
+ end
64
+ end
65
+
66
+ class Client
67
+ def initialize(configuration)
68
+ @configuration = configuration
69
+ end
70
+
71
+ def track(attributes)
72
+ response = connection.post("/api/v1/leads") do |req|
73
+ req.body = build_lead_payload(attributes).to_json
74
+ end
75
+
76
+ handle_response(response)
77
+ rescue Faraday::TimeoutError
78
+ Result.failure("Connection timeout")
79
+ rescue Faraday::ConnectionFailed => e
80
+ Result.failure("Connection failed: #{e.message}")
81
+ end
82
+
83
+ def batch(leads)
84
+ response = connection.post("/api/v1/leads/batch") do |req|
85
+ req.body = build_batch_payload(leads).to_json
86
+ end
87
+
88
+ handle_batch_response(response)
89
+ rescue Faraday::TimeoutError
90
+ BatchResult.failure("Connection timeout")
91
+ rescue Faraday::ConnectionFailed => e
92
+ BatchResult.failure("Connection failed: #{e.message}")
93
+ end
94
+
95
+ private
96
+
97
+ attr_reader :configuration
98
+
99
+ def connection
100
+ @connection ||= Faraday.new(url: configuration.base_url) do |conn|
101
+ conn.request :retry, max: 2, interval: 0.5, backoff_factor: 2
102
+ conn.headers["Authorization"] = "Bearer #{configuration.api_key}"
103
+ conn.headers["Content-Type"] = "application/json"
104
+ conn.headers["Accept"] = "application/json"
105
+ conn.options.timeout = configuration.timeout
106
+ conn.adapter Faraday.default_adapter
107
+ end
108
+ end
109
+
110
+ def build_lead_payload(attributes)
111
+ lead = {
112
+ startup_id: configuration.startup_id,
113
+ email: attributes[:email],
114
+ name: attributes[:name]
115
+ }
116
+
117
+ # Optional attributes
118
+ lead[:plan_tier] = attributes[:plan_tier] if attributes[:plan_tier]
119
+ lead[:source] = attributes[:source] if attributes[:source]
120
+ lead[:language] = attributes[:language] if attributes[:language]
121
+ lead[:external_id] = attributes[:external_id] if attributes[:external_id]
122
+ lead[:utm_params] = attributes[:utm_params] if attributes[:utm_params]
123
+ lead[:properties] = attributes[:properties] if attributes[:properties]
124
+
125
+ { lead: lead }
126
+ end
127
+
128
+ def build_batch_payload(leads)
129
+ {
130
+ startup_id: configuration.startup_id,
131
+ leads: leads.map { |lead| normalize_lead(lead) }
132
+ }
133
+ end
134
+
135
+ def normalize_lead(lead)
136
+ normalized = {
137
+ email: lead[:email],
138
+ name: lead[:name]
139
+ }
140
+
141
+ %i[plan_tier source language external_id utm_params properties].each do |key|
142
+ normalized[key] = lead[key] if lead[key]
143
+ end
144
+
145
+ normalized
146
+ end
147
+
148
+ def handle_response(response)
149
+ case response.status
150
+ when 200, 201
151
+ data = parse_json(response.body)
152
+ Result.success(data["data"] || data)
153
+ when 401
154
+ data = parse_json(response.body)
155
+ Result.failure(data["error"] || "Unauthorized")
156
+ when 422
157
+ data = parse_json(response.body)
158
+ Result.validation_failure(data["errors"] || [])
159
+ when 429
160
+ data = parse_json(response.body)
161
+ Result.failure(data["error"] || "Rate limit exceeded")
162
+ when 500..599
163
+ Result.failure("Server error (#{response.status})")
164
+ else
165
+ Result.failure("Unexpected response: #{response.status}")
166
+ end
167
+ end
168
+
169
+ def handle_batch_response(response)
170
+ case response.status
171
+ when 200, 201
172
+ data = parse_json(response.body)
173
+ result_data = data["data"] || data
174
+ BatchResult.new(
175
+ created: result_data["created"] || 0,
176
+ failed: result_data["failed"] || 0,
177
+ errors: result_data["errors"] || []
178
+ )
179
+ when 401
180
+ data = parse_json(response.body)
181
+ BatchResult.failure(data["error"] || "Unauthorized")
182
+ when 422
183
+ data = parse_json(response.body)
184
+ BatchResult.failure(data["errors"]&.join(", ") || "Validation failed")
185
+ when 429
186
+ data = parse_json(response.body)
187
+ BatchResult.failure(data["error"] || "Rate limit exceeded")
188
+ when 500..599
189
+ BatchResult.failure("Server error (#{response.status})")
190
+ else
191
+ BatchResult.failure("Unexpected response: #{response.status}")
192
+ end
193
+ end
194
+
195
+ def parse_json(body)
196
+ JSON.parse(body)
197
+ rescue JSON::ParserError
198
+ {}
199
+ end
200
+ end
201
+
202
+ class Result
203
+ attr_reader :lead, :error, :errors
204
+
205
+ def initialize(lead: nil, error: nil, errors: nil)
206
+ @lead = lead
207
+ @error = error
208
+ @errors = errors || []
209
+ end
210
+
211
+ def success?
212
+ @lead && @error.nil?
213
+ end
214
+
215
+ def failure?
216
+ !success?
217
+ end
218
+
219
+ class << self
220
+ def success(lead_data)
221
+ new(lead: lead_data)
222
+ end
223
+
224
+ def failure(error_message)
225
+ new(error: error_message)
226
+ end
227
+
228
+ def validation_failure(errors)
229
+ new(error: errors.first, errors: errors)
230
+ end
231
+ end
232
+ end
233
+
234
+ class BatchResult
235
+ attr_reader :created, :failed, :errors, :error
236
+
237
+ def initialize(created: 0, failed: 0, errors: [], error: nil)
238
+ @created = created
239
+ @failed = failed
240
+ @errors = errors
241
+ @error = error
242
+ end
243
+
244
+ def success?
245
+ @error.nil? && @errors.empty?
246
+ end
247
+
248
+ def partial_success?
249
+ @error.nil? && @created.positive? && @errors.any?
250
+ end
251
+
252
+ def failure?
253
+ @error.present? || (@created.zero? && @errors.any?)
254
+ end
255
+
256
+ class << self
257
+ def failure(error_message)
258
+ new(error: error_message)
259
+ end
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,6 @@
1
+ module Risenexa
2
+ module Leads
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: risenexa-leads
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Patrick Espake
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: faraday
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '1.0'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '3.0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: faraday-retry
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: '2.0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "~>"
44
+ - !ruby/object:Gem::Version
45
+ version: '2.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '3.0'
53
+ type: :development
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.0'
60
+ - !ruby/object:Gem::Dependency
61
+ name: webmock
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '3.0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '3.0'
74
+ - !ruby/object:Gem::Dependency
75
+ name: rake
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '13.0'
81
+ type: :development
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '13.0'
88
+ description: A Ruby gem to track user signups and send lead data to Risenexa for AI-powered
89
+ customer discovery.
90
+ email:
91
+ - patrickespake@gmail.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - ".rspec"
97
+ - CHANGELOG.md
98
+ - LICENSE.txt
99
+ - README.md
100
+ - Rakefile
101
+ - lib/risenexa/leads.rb
102
+ - lib/risenexa/leads/version.rb
103
+ - sig/risenexa/leads.rbs
104
+ homepage: https://github.com/envixo/risenexa-leads-gem
105
+ licenses:
106
+ - MIT
107
+ metadata:
108
+ allowed_push_host: https://rubygems.org
109
+ homepage_uri: https://github.com/envixo/risenexa-leads-gem
110
+ source_code_uri: https://github.com/envixo/risenexa-leads-gem
111
+ changelog_uri: https://github.com/envixo/risenexa-leads-gem/blob/main/CHANGELOG.md
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: 3.1.0
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubygems_version: 3.6.9
127
+ specification_version: 4
128
+ summary: Ruby SDK for capturing leads and sending them to Risenexa
129
+ test_files: []