keplars 2.1.0 → 2.9.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 +4 -4
- data/README.md +20 -0
- data/lib/keplars/audiences.rb +7 -5
- data/lib/keplars/automations.rb +13 -5
- data/lib/keplars/client.rb +19 -4
- data/lib/keplars/contacts.rb +26 -10
- data/lib/keplars/domains.rb +14 -7
- data/lib/keplars/resources.rb +54 -7
- data/lib/keplars/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c9f27c62fc254b42974354edc4e138d253a05b0367eb1276f9999125810e7e9
|
|
4
|
+
data.tar.gz: 1cc364a65c48a1676b3d0fc82a511cf671efe84aae50127b7017907917ef1bbd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2bb04146d158a84e30a28220d06c6ab4308c37aabc4391cd8e9ad3871198e40ea71a92254ef827b1c466237613eee519884217fbfc6f61b8a412aeb5411ddaa9
|
|
7
|
+
data.tar.gz: 9fd4acb85ed648d3bf8babd7a5f2d345599bcfa9db8091fb1da3e710cd5377e52c7f804d3708468475414de7e45de28e03d440d3fb509b9d08b9d8389518142c
|
data/README.md
CHANGED
|
@@ -46,6 +46,26 @@ puts result[:data][:job_id]
|
|
|
46
46
|
| Regular | `kms_<id>.live_<secret>` | Email sending |
|
|
47
47
|
| Admin | `kms_<id>.adm_<secret>` | Contacts, audiences, automations, domains |
|
|
48
48
|
|
|
49
|
+
### Using Both Send and Admin Operations
|
|
50
|
+
|
|
51
|
+
Pass `admin_key:` alongside a live `api_key:` to use a single client for both:
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
client = Keplars::Client.new(
|
|
55
|
+
api_key: 'kms_<id>.live_<secret>',
|
|
56
|
+
admin_key: 'kms_<id>.adm_<secret>'
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
client.emails.send_instant(...) # uses api_key
|
|
60
|
+
client.audiences.list # uses admin_key
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If you only have an admin key, pass it as `api_key:` directly:
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
client = Keplars::Client.new(api_key: 'kms_<id>.adm_<secret>')
|
|
67
|
+
```
|
|
68
|
+
|
|
49
69
|
## Email Sending
|
|
50
70
|
|
|
51
71
|
### Priority Levels
|
data/lib/keplars/audiences.rb
CHANGED
|
@@ -4,24 +4,26 @@ module Keplars
|
|
|
4
4
|
def create(name:, description: nil)
|
|
5
5
|
body = { name: name }
|
|
6
6
|
body[:description] = description if description
|
|
7
|
-
@client.request('POST', '/api/v1/public/audiences/add-audience', body: body)[:data]
|
|
7
|
+
@client.request('POST', '/api/v1/public/audiences/add-audience', body: body, is_admin: true)[:data]
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def list(page: nil, limit: nil)
|
|
10
|
+
def list(page: nil, limit: nil, sort_by: nil, sort_dir: nil)
|
|
11
11
|
params = {}
|
|
12
12
|
params[:page] = page if page
|
|
13
13
|
params[:limit] = limit if limit
|
|
14
|
+
params[:sortBy] = sort_by if sort_by
|
|
15
|
+
params[:sortDir] = sort_dir if sort_dir
|
|
14
16
|
|
|
15
17
|
query = @client.send(:build_query_string, params)
|
|
16
|
-
@client.request('GET', "/api/v1/public/audiences/get-audiences#{query}")[:data]
|
|
18
|
+
@client.request('GET', "/api/v1/public/audiences/get-audiences#{query}", is_admin: true)[:data]
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def get(id)
|
|
20
|
-
@client.request('GET', "/api/v1/public/audiences/get-audience?id=#{URI.encode_www_form_component(id)}")[:data]
|
|
22
|
+
@client.request('GET', "/api/v1/public/audiences/get-audience?id=#{URI.encode_www_form_component(id)}", is_admin: true)[:data]
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def delete(id)
|
|
24
|
-
@client.request('DELETE', "/api/v1/public/audiences/delete-audience?id=#{URI.encode_www_form_component(id)}")[:data]
|
|
26
|
+
@client.request('DELETE', "/api/v1/public/audiences/delete-audience?id=#{URI.encode_www_form_component(id)}", is_admin: true)[:data]
|
|
25
27
|
end
|
|
26
28
|
end
|
|
27
29
|
end
|
data/lib/keplars/automations.rb
CHANGED
|
@@ -7,19 +7,27 @@ module Keplars
|
|
|
7
7
|
params[:limit] = limit if limit
|
|
8
8
|
|
|
9
9
|
query = @client.send(:build_query_string, params)
|
|
10
|
-
@client.request('GET', "/api/v1/public/automations/get-all#{query}")[:data]
|
|
10
|
+
@client.request('GET', "/api/v1/public/automations/get-all#{query}", is_admin: true)[:data]
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def get(id)
|
|
14
|
-
@client.request('GET', "/api/v1/public/automations/get-automation/#{id}")[:data]
|
|
14
|
+
@client.request('GET', "/api/v1/public/automations/get-automation/#{id}", is_admin: true)[:data]
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def enroll(id, email:)
|
|
18
|
-
|
|
17
|
+
def enroll(id, email:, properties: nil)
|
|
18
|
+
body = { email: email }
|
|
19
|
+
body[:properties] = properties if properties
|
|
20
|
+
@client.request('POST', "/api/v1/public/automations/add-automation/#{id}/enroll", body: body, is_admin: true)[:data]
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
def unenroll(id, email:)
|
|
22
|
-
@client.request('DELETE', "/api/v1/public/automations/delete-automation/#{id}/subscribers", body: { email: email })[:data]
|
|
24
|
+
@client.request('DELETE', "/api/v1/public/automations/delete-automation/#{id}/subscribers", body: { email: email }, is_admin: true)[:data]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def track_event(email, event_name, event_properties: nil)
|
|
28
|
+
body = { email: email, event_name: event_name }
|
|
29
|
+
body[:event_properties] = event_properties if event_properties
|
|
30
|
+
@client.request('POST', '/api/v1/public/automations/events/track', body: body, is_admin: true)[:data]
|
|
23
31
|
end
|
|
24
32
|
end
|
|
25
33
|
end
|
data/lib/keplars/client.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Keplars
|
|
|
11
11
|
|
|
12
12
|
attr_reader :emails, :contacts, :audiences, :automations, :domains
|
|
13
13
|
|
|
14
|
-
def initialize(api_key: nil, base_url: nil, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, retry_delay: DEFAULT_RETRY_DELAY)
|
|
14
|
+
def initialize(api_key: nil, admin_key: nil, base_url: nil, timeout: DEFAULT_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, retry_delay: DEFAULT_RETRY_DELAY)
|
|
15
15
|
@api_key = api_key || ENV['KEPLARS_API_KEY']
|
|
16
16
|
raise ArgumentError, 'API key is required. Set KEPLARS_API_KEY or pass api_key parameter' if @api_key.nil? || @api_key.empty?
|
|
17
17
|
|
|
@@ -19,6 +19,11 @@ module Keplars
|
|
|
19
19
|
raise ArgumentError, 'Invalid API key format. Expected: kms_<id>.live_<secret> or kms_<id>.adm_<secret>'
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
if admin_key
|
|
23
|
+
raise ArgumentError, 'Invalid adminKey format. Expected: kms_<id>.adm_<secret>' unless admin_key.match?(/\Akms_[a-f0-9]+\.adm_[a-f0-9]+\z/)
|
|
24
|
+
@admin_key = admin_key
|
|
25
|
+
end
|
|
26
|
+
|
|
22
27
|
resolved_base_url = base_url || ENV['KEPLARS_BASE_URL'] || DEFAULT_BASE_URL
|
|
23
28
|
@base_url = resolved_base_url.sub(/\/$/, '')
|
|
24
29
|
@timeout = timeout
|
|
@@ -32,7 +37,7 @@ module Keplars
|
|
|
32
37
|
@domains = Resources::Domains.new(self)
|
|
33
38
|
end
|
|
34
39
|
|
|
35
|
-
def request(method, path, body: nil, retry_count: 0)
|
|
40
|
+
def request(method, path, body: nil, retry_count: 0, is_admin: false)
|
|
36
41
|
uri = URI("#{@base_url}#{path}")
|
|
37
42
|
|
|
38
43
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
@@ -50,7 +55,7 @@ module Keplars
|
|
|
50
55
|
end
|
|
51
56
|
|
|
52
57
|
request = request_class.new(uri.request_uri)
|
|
53
|
-
request['Authorization'] = "Bearer #{
|
|
58
|
+
request['Authorization'] = "Bearer #{get_auth_key(is_admin)}"
|
|
54
59
|
request['Content-Type'] = 'application/json'
|
|
55
60
|
request['User-Agent'] = "keplars-ruby/#{VERSION}"
|
|
56
61
|
|
|
@@ -66,11 +71,13 @@ module Keplars
|
|
|
66
71
|
|
|
67
72
|
result = response.body && !response.body.empty? ? JSON.parse(response.body, symbolize_names: true) : nil
|
|
68
73
|
{ data: result, rate_limit_info: rate_limit_info }
|
|
74
|
+
rescue KeplarsError
|
|
75
|
+
raise
|
|
69
76
|
rescue StandardError => e
|
|
70
77
|
if retryable_error?(e) && retry_count < @max_retries
|
|
71
78
|
delay = calculate_backoff(retry_count)
|
|
72
79
|
sleep(delay)
|
|
73
|
-
request(method, path, body: body, retry_count: retry_count + 1)
|
|
80
|
+
request(method, path, body: body, retry_count: retry_count + 1, is_admin: is_admin)
|
|
74
81
|
else
|
|
75
82
|
raise NetworkError.new("Request failed: #{e.message}", original_error: e)
|
|
76
83
|
end
|
|
@@ -79,6 +86,14 @@ module Keplars
|
|
|
79
86
|
|
|
80
87
|
private
|
|
81
88
|
|
|
89
|
+
def get_auth_key(is_admin)
|
|
90
|
+
return @api_key unless is_admin
|
|
91
|
+
return @admin_key if @admin_key
|
|
92
|
+
return @api_key if @api_key.match?(/\Akms_[a-f0-9]+\.adm_[a-f0-9]+\z/)
|
|
93
|
+
|
|
94
|
+
raise AuthorizationError.new('Admin key required for this operation. Provide admin_key in config.', request_id: nil)
|
|
95
|
+
end
|
|
96
|
+
|
|
82
97
|
def extract_rate_limit_info(response)
|
|
83
98
|
limit = response['X-RateLimit-Limit']
|
|
84
99
|
remaining = response['X-RateLimit-Remaining']
|
data/lib/keplars/contacts.rb
CHANGED
|
@@ -2,29 +2,45 @@ module Keplars
|
|
|
2
2
|
module Resources
|
|
3
3
|
class Contacts < Base
|
|
4
4
|
def add(**params)
|
|
5
|
-
@client.request('POST', '/api/v1/public/contacts/add-contact', body: params.compact)[:data]
|
|
5
|
+
@client.request('POST', '/api/v1/public/contacts/add-contact', body: params.compact, is_admin: true)[:data]
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
def get(
|
|
9
|
-
|
|
8
|
+
def get(email_or_id)
|
|
9
|
+
param = email_or_id.include?('@') ? 'email' : 'id'
|
|
10
|
+
@client.request('GET', "/api/v1/public/contacts/get-contact?#{param}=#{URI.encode_www_form_component(email_or_id)}", is_admin: true)[:data]
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
def list(audience_id: nil, page: nil, limit: nil)
|
|
13
|
+
def list(audience_id: nil, page: nil, limit: nil, sort_by: nil, sort_dir: nil, subscribed_only: nil)
|
|
13
14
|
params = {}
|
|
14
|
-
params[:
|
|
15
|
+
params[:audienceId] = audience_id if audience_id
|
|
15
16
|
params[:page] = page if page
|
|
16
17
|
params[:limit] = limit if limit
|
|
18
|
+
params[:sortBy] = sort_by if sort_by
|
|
19
|
+
params[:sortDir] = sort_dir if sort_dir
|
|
20
|
+
params[:subscribedOnly] = subscribed_only.to_s if !subscribed_only.nil?
|
|
17
21
|
|
|
18
22
|
query = @client.send(:build_query_string, params)
|
|
19
|
-
@client.request('GET', "/api/v1/public/contacts/get-contacts#{query}")[:data]
|
|
23
|
+
@client.request('GET', "/api/v1/public/contacts/get-contacts#{query}", is_admin: true)[:data]
|
|
20
24
|
end
|
|
21
25
|
|
|
22
|
-
def update(
|
|
23
|
-
|
|
26
|
+
def update(id_or_email, **params)
|
|
27
|
+
if id_or_email.include?('@')
|
|
28
|
+
warn '[Keplars] Deprecated: passing email to update() is deprecated since v2.7.0. Use contact ID instead.'
|
|
29
|
+
param = 'email'
|
|
30
|
+
else
|
|
31
|
+
param = 'id'
|
|
32
|
+
end
|
|
33
|
+
@client.request('PATCH', "/api/v1/public/contacts/update-contact?#{param}=#{URI.encode_www_form_component(id_or_email)}", body: params.compact, is_admin: true)[:data]
|
|
24
34
|
end
|
|
25
35
|
|
|
26
|
-
def delete(
|
|
27
|
-
|
|
36
|
+
def delete(id_or_email)
|
|
37
|
+
if id_or_email.include?('@')
|
|
38
|
+
warn '[Keplars] Deprecated: passing email to delete() is deprecated since v2.7.0. Use contact ID instead.'
|
|
39
|
+
param = 'email'
|
|
40
|
+
else
|
|
41
|
+
param = 'id'
|
|
42
|
+
end
|
|
43
|
+
@client.request('DELETE', "/api/v1/public/contacts/delete-contact?#{param}=#{URI.encode_www_form_component(id_or_email)}", is_admin: true)[:data]
|
|
28
44
|
end
|
|
29
45
|
end
|
|
30
46
|
end
|
data/lib/keplars/domains.rb
CHANGED
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
module Keplars
|
|
2
2
|
module Resources
|
|
3
3
|
class Domains < Base
|
|
4
|
-
def add(domain)
|
|
5
|
-
|
|
4
|
+
def add(domain, region: nil)
|
|
5
|
+
body = { domain: domain }
|
|
6
|
+
body[:region] = region if region
|
|
7
|
+
@client.request('POST', '/api/v1/public/domains/add-domain', body: body, is_admin: true)[:data]
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
def list
|
|
9
|
-
@client.request('GET', '/api/v1/public/domains/get-domains')[:data]
|
|
11
|
+
@client.request('GET', '/api/v1/public/domains/get-domains', is_admin: true)[:data]
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def get_status(domain_id)
|
|
13
|
-
@client.request('GET', "/api/v1/public/domains/domain-status/#{domain_id}")[:data]
|
|
15
|
+
@client.request('GET', "/api/v1/public/domains/domain-status/#{domain_id}", is_admin: true)[:data]
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
def verify(domain_id)
|
|
17
|
-
@client.request('POST', "/api/v1/public/domains/verify-domain/#{domain_id}")[:data]
|
|
19
|
+
@client.request('POST', "/api/v1/public/domains/verify-domain/#{domain_id}", is_admin: true)[:data]
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def delete(domain_id)
|
|
21
|
-
@client.request('DELETE', "/api/v1/public/domains/delete-domain/#{domain_id}")[:data]
|
|
23
|
+
@client.request('DELETE', "/api/v1/public/domains/delete-domain/#{domain_id}", is_admin: true)[:data]
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def create_api_key(**params)
|
|
25
|
-
|
|
27
|
+
body = params.dup
|
|
28
|
+
if body.key?(:domain_id) && !body.key?(:custom_domain_id)
|
|
29
|
+
warn '[Keplars] Deprecated: :domain_id is deprecated since v2.7.0. Use :custom_domain_id instead.'
|
|
30
|
+
body[:custom_domain_id] = body.delete(:domain_id)
|
|
31
|
+
end
|
|
32
|
+
@client.request('POST', '/api/v1/public/domains/api-keys/create', body: body.compact, is_admin: true)[:data]
|
|
26
33
|
end
|
|
27
34
|
end
|
|
28
35
|
end
|
data/lib/keplars/resources.rb
CHANGED
|
@@ -8,22 +8,22 @@ module Keplars
|
|
|
8
8
|
|
|
9
9
|
class Emails < Base
|
|
10
10
|
def send_instant(**args)
|
|
11
|
-
body = args
|
|
11
|
+
body = normalize_email_args(args)
|
|
12
12
|
@client.request('POST', '/api/v1/send-email/instant', body: body)[:data]
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def send_high(**args)
|
|
16
|
-
body = args
|
|
16
|
+
body = normalize_email_args(args)
|
|
17
17
|
@client.request('POST', '/api/v1/send-email/high', body: body)[:data]
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def send_async(**args)
|
|
21
|
-
body = args
|
|
21
|
+
body = normalize_email_args(args)
|
|
22
22
|
@client.request('POST', '/api/v1/send-email/async', body: body)[:data]
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def send_bulk(**args)
|
|
26
|
-
body = args
|
|
26
|
+
body = normalize_email_args(args)
|
|
27
27
|
@client.request('POST', '/api/v1/send-email/bulk', body: body)[:data]
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -32,9 +32,56 @@ module Keplars
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def schedule(**args)
|
|
35
|
-
body = args.
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
body = args.dup
|
|
36
|
+
|
|
37
|
+
if body.key?(:scheduled_for) && !body.key?(:scheduled_at)
|
|
38
|
+
warn '[Keplars] Deprecated: :scheduled_for is deprecated since v2.7.0. Use :scheduled_at instead.'
|
|
39
|
+
body[:scheduled_at] = body.delete(:scheduled_for)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
scheduled_at = body.delete(:scheduled_at)
|
|
43
|
+
timezone = body.delete(:timezone)
|
|
44
|
+
body.delete(:priority)
|
|
45
|
+
|
|
46
|
+
raise ArgumentError, 'scheduled_at is required for scheduling emails' unless scheduled_at
|
|
47
|
+
|
|
48
|
+
email_body = normalize_email_args(body).compact
|
|
49
|
+
|
|
50
|
+
payload = { scheduled_at: scheduled_at, email: email_body }
|
|
51
|
+
payload[:timezone] = timezone if timezone
|
|
52
|
+
|
|
53
|
+
@client.request('POST', '/api/v1/send-email/schedule', body: payload)[:data]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def normalize_email_args(args)
|
|
59
|
+
body = args.dup
|
|
60
|
+
|
|
61
|
+
if body.key?(:to) && !body[:to].is_a?(Array)
|
|
62
|
+
raise ArgumentError, 'to must be an array of email addresses, e.g. to: ["user@example.com"]'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if body.key?(:html)
|
|
66
|
+
warn '[Keplars] Deprecated: :html is deprecated since v2.7.0. Use :body + is_html: true instead.'
|
|
67
|
+
body[:body] ||= body.delete(:html)
|
|
68
|
+
body[:is_html] = true unless body.key?(:is_html)
|
|
69
|
+
body.delete(:html)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if body.key?(:text)
|
|
73
|
+
warn '[Keplars] Deprecated: :text is deprecated since v2.7.0. Use :body instead.'
|
|
74
|
+
body[:body] ||= body.delete(:text)
|
|
75
|
+
body.delete(:text)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if body.key?(:template_data)
|
|
79
|
+
warn '[Keplars] Deprecated: :template_data is deprecated since v2.7.0. Use :params instead.'
|
|
80
|
+
body[:params] ||= body.delete(:template_data)
|
|
81
|
+
body.delete(:template_data)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
body.compact
|
|
38
85
|
end
|
|
39
86
|
end
|
|
40
87
|
end
|
data/lib/keplars/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: keplars
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Keplars
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-08-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|