postproxy-sdk 1.6.0 → 1.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e62e2ba2b3d951aed31a2d60d74a7ee4a46672b03131676f28d81f6dc5cade69
4
- data.tar.gz: 83bf66f3dae825b04195d1ec9e809849352f4c290dbf2d1458879a1838688e93
3
+ metadata.gz: 1d2f9ae8cbbc2ca3cd324b5dc522226c9d7a77cd93430abb309b31efc210a293
4
+ data.tar.gz: 26c58e5f9b7ea1af4eccb3935ef8c71bf202bf5bff93898d0b30a5450114bb1a
5
5
  SHA512:
6
- metadata.gz: 2b38044c1990d12a5d937b261df5b01e80d3cec44caaebd0eeb4eb9038859bb2428c35c6f557421ba8a5cc494347e4e08de7963d98d8ff1ad552960cbcd02dae
7
- data.tar.gz: 5f3393e61377f4de158148d7c4de2982df376410cc377bdd356d478729bf129a86b5659ea0abc412a4809a55a343dde7b59e4e8ee11ff6957630f7475957286d
6
+ metadata.gz: 906800719560c2e37351c958fa72449d1411b351c1cad4deb0d312e9b6fcaa3af3be3dcb504eeef045a3d24737815afb4e7f772edae4687e102e2f9d4bd605cc
7
+ data.tar.gz: b6ee51b608b91a9d31ed2891b7bba87df996006be1795504f540e275dd54c8ff3b7ef7e5f1994a7aa495a02f67ec8f3921e9017baadb3e1e8d3c5550d6959b06
data/README.md CHANGED
@@ -105,6 +105,18 @@ post.thread.each { |child| puts "#{child.id}: #{child.body}" }
105
105
 
106
106
  # Delete a post
107
107
  client.posts.delete("post-id")
108
+
109
+ # Delete a post and also remove it from social platforms
110
+ client.posts.delete("post-id", delete_on_platform: true)
111
+
112
+ # Delete from platforms only (keeps DB record). Defaults to all platforms.
113
+ client.posts.delete_on_platform("post-id")
114
+ # Target a single network
115
+ client.posts.delete_on_platform("post-id", network: "twitter")
116
+ # Target a specific profile
117
+ client.posts.delete_on_platform("post-id", profile_id: "prof-abc")
118
+ # Target a specific post profile (covers entire thread for that profile)
119
+ client.posts.delete_on_platform("post-id", post_profile_id: "pp-abc")
108
120
  ```
109
121
 
110
122
  ## Post Stats
@@ -248,6 +260,26 @@ PostProxy::WebhookSignature.verify(
248
260
  )
249
261
  ```
250
262
 
263
+ ### Event types and typed payloads
264
+
265
+ Subscribe to any of these events (or pass `["*"]` for all):
266
+
267
+ `post.processed`, `post.imported`, `platform_post.published`, `platform_post.failed`, `platform_post.failed_waiting_for_retry`, `platform_post.insights`, `profile.connected`, `profile.disconnected`, `profile.stats`, `media.failed`, `comment.created`.
268
+
269
+ `PostProxy::WebhookEvents.parse` validates the envelope and returns a typed `Event` — `event.data` is the right model for the event:
270
+
271
+ ```ruby
272
+ event = PostProxy::WebhookEvents.parse(request.body.read)
273
+ case event.type
274
+ when "profile.stats"
275
+ puts "#{event.data.profile_id}: #{event.data.stats}"
276
+ when "platform_post.published"
277
+ puts "Published: #{event.data.platform_id}"
278
+ when "comment.created"
279
+ puts "#{event.data.author_username}: #{event.data.body}"
280
+ end
281
+ ```
282
+
251
283
  ## Comments
252
284
 
253
285
  ```ruby
@@ -299,6 +331,19 @@ placements = client.profiles.placements("prof-id").data
299
331
 
300
332
  # Delete a profile
301
333
  client.profiles.delete("prof-id")
334
+
335
+ # Profile stats timeseries — placement_id required for facebook, linkedin, telegram
336
+ stats = client.profiles.get_profile_stats("prof_li_001",
337
+ placement_id: "108520199",
338
+ from: "2026-04-01T00:00:00Z"
339
+ )
340
+ stats.data.records.each do |r|
341
+ puts "#{r.recorded_at}: #{r.stats[:followerCount]}"
342
+ end
343
+
344
+ # Bluesky — no placements
345
+ bsky = client.profiles.get_profile_stats("prof_bsky_001")
346
+ puts bsky.data.records.last.stats[:followersCount]
302
347
  ```
303
348
 
304
349
  ## Profile Groups
@@ -323,6 +368,28 @@ connection = client.profile_groups.initialize_connection(
323
368
  redirect_url: "https://myapp.com/callback"
324
369
  )
325
370
  # Redirect user to connection.url
371
+
372
+ # BlueSky — app password (synchronous, no OAuth)
373
+ bsky = client.profile_groups.connect_bluesky("pg-id",
374
+ identifier: "yourname.bsky.social",
375
+ app_password: "xxxx-xxxx-xxxx-xxxx"
376
+ )
377
+ puts bsky.profile.id
378
+
379
+ # Telegram — bring-your-own-bot. Channels populate asynchronously; poll
380
+ # placements until non-empty.
381
+ tg = client.profile_groups.connect_telegram("pg-id",
382
+ bot_token: "123456789:ABCdef-GhIJklMnOpQrStUvWxYz"
383
+ )
384
+ puts tg.next_step
385
+
386
+ placements = []
387
+ loop do
388
+ placements = client.profiles.placements(tg.profile.id).data
389
+ break unless placements.empty?
390
+ sleep 3
391
+ end
392
+ puts "Channels: #{placements.map { |p| [p.id, p.name] }}"
326
393
  ```
327
394
 
328
395
  ## Platform Parameters
@@ -352,7 +419,13 @@ platforms = PostProxy::PlatformParams.new(
352
419
  board_id: "board-123"
353
420
  ),
354
421
  threads: PostProxy::ThreadsParams.new(format: "post"),
355
- twitter: PostProxy::TwitterParams.new(format: "post")
422
+ twitter: PostProxy::TwitterParams.new(format: "post"),
423
+ bluesky: PostProxy::BlueskyParams.new(format: "post"),
424
+ telegram: PostProxy::TelegramParams.new(
425
+ chat_id: "-1001234567890",
426
+ parse_mode: "HTML",
427
+ disable_link_preview: true
428
+ )
356
429
  )
357
430
 
358
431
  post = client.posts.create(
@@ -362,6 +435,8 @@ post = client.posts.create(
362
435
  )
363
436
  ```
364
437
 
438
+ Supported platforms: `facebook`, `instagram`, `tiktok`, `linkedin`, `youtube`, `twitter`, `threads`, `pinterest`, `bluesky`, `telegram`. Telegram requires a `chat_id` per post — list channels with `client.profiles.placements(profile_id)`.
439
+
365
440
  ## Error Handling
366
441
 
367
442
  ```ruby
@@ -99,11 +99,16 @@ module PostProxy
99
99
 
100
100
  private
101
101
 
102
+ def user_agent
103
+ @user_agent ||= "postproxy-ruby/#{PostProxy::VERSION} (ruby/#{RUBY_VERSION})"
104
+ end
105
+
102
106
  def json_connection
103
107
  @faraday_client || Faraday.new(url: @base_url) do |f|
104
108
  f.request :url_encoded
105
109
  f.headers["Authorization"] = "Bearer #{@api_key}"
106
110
  f.headers["Content-Type"] = "application/json"
111
+ f.headers["User-Agent"] = user_agent
107
112
  f.adapter Faraday.default_adapter
108
113
  end
109
114
  end
@@ -112,6 +117,7 @@ module PostProxy
112
117
  @faraday_client || Faraday.new(url: @base_url) do |f|
113
118
  f.request :multipart
114
119
  f.headers["Authorization"] = "Bearer #{@api_key}"
120
+ f.headers["User-Agent"] = user_agent
115
121
  f.adapter Faraday.default_adapter
116
122
  end
117
123
  end
@@ -2,7 +2,7 @@ module PostProxy
2
2
  DEFAULT_BASE_URL = "https://api.postproxy.dev"
3
3
 
4
4
  PLATFORMS = %w[
5
- facebook instagram tiktok linkedin youtube twitter threads pinterest
5
+ facebook instagram tiktok linkedin youtube twitter threads pinterest bluesky telegram
6
6
  ].freeze
7
7
 
8
8
  PROFILE_STATUSES = %w[active expired inactive].freeze
@@ -21,10 +21,28 @@ module PostProxy
21
21
  PINTEREST_FORMATS = %w[pin].freeze
22
22
  THREADS_FORMATS = %w[post].freeze
23
23
  TWITTER_FORMATS = %w[post].freeze
24
+ BLUESKY_FORMATS = %w[post].freeze
25
+ TELEGRAM_FORMATS = %w[post].freeze
24
26
 
25
27
  TIKTOK_PRIVACIES = %w[
26
28
  PUBLIC_TO_EVERYONE MUTUAL_FOLLOW_FRIENDS FOLLOWER_OF_CREATOR SELF_ONLY
27
29
  ].freeze
28
30
 
29
31
  YOUTUBE_PRIVACIES = %w[public unlisted private].freeze
32
+
33
+ TELEGRAM_PARSE_MODES = %w[HTML MarkdownV2].freeze
34
+
35
+ WEBHOOK_EVENT_TYPES = %w[
36
+ post.processed
37
+ post.imported
38
+ platform_post.published
39
+ platform_post.failed
40
+ platform_post.failed_waiting_for_retry
41
+ platform_post.insights
42
+ profile.connected
43
+ profile.disconnected
44
+ profile.stats
45
+ media.failed
46
+ comment.created
47
+ ].freeze
30
48
  end
@@ -38,6 +38,8 @@ module PostProxy
38
38
  form_data = { "post[body]" => body }
39
39
  form_data["post[scheduled_at]"] = format_time(scheduled_at) if scheduled_at
40
40
  form_data["post[draft]"] = draft.to_s if !draft.nil?
41
+ form_data["queue_id"] = queue_id if queue_id
42
+ form_data["queue_priority"] = queue_priority if queue_priority
41
43
 
42
44
  files = []
43
45
 
@@ -116,6 +118,8 @@ module PostProxy
116
118
  form_data["post[body]"] = body if body
117
119
  form_data["post[scheduled_at]"] = format_time(scheduled_at) if scheduled_at
118
120
  form_data["post[draft]"] = draft.to_s if !draft.nil?
121
+ form_data["queue_id"] = queue_id if queue_id
122
+ form_data["queue_priority"] = queue_priority if queue_priority
119
123
 
120
124
  files = []
121
125
 
@@ -205,11 +209,28 @@ module PostProxy
205
209
  StatsResponse.new(data: posts)
206
210
  end
207
211
 
208
- def delete(id, profile_group_id: nil)
209
- result = @client.request(:delete, "/posts/#{id}", profile_group_id: profile_group_id)
212
+ def delete(id, delete_on_platform: nil, profile_group_id: nil)
213
+ params = {}
214
+ params[:delete_on_platform] = delete_on_platform unless delete_on_platform.nil?
215
+ result = @client.request(:delete, "/posts/#{id}",
216
+ params: params.empty? ? nil : params,
217
+ profile_group_id: profile_group_id
218
+ )
210
219
  DeleteResponse.new(**result)
211
220
  end
212
221
 
222
+ def delete_on_platform(id, post_profile_id: nil, profile_id: nil, network: nil, profile_group_id: nil)
223
+ json_body = {}
224
+ json_body[:post_profile_id] = post_profile_id if post_profile_id
225
+ json_body[:profile_id] = profile_id if profile_id
226
+ json_body[:network] = network if network
227
+ result = @client.request(:post, "/posts/#{id}/delete_on_platform",
228
+ json: json_body.empty? ? nil : json_body,
229
+ profile_group_id: profile_group_id
230
+ )
231
+ DeleteOnPlatformResponse.new(**result)
232
+ end
233
+
213
234
  private
214
235
 
215
236
  def format_time(value)
@@ -26,11 +26,28 @@ module PostProxy
26
26
  DeleteResponse.new(**result)
27
27
  end
28
28
 
29
- def initialize_connection(id, platform:, redirect_url:)
29
+ # OAuth flow. BlueSky and Telegram use their dedicated helpers below.
30
+ def initialize_connection(id, platform:, redirect_url: nil)
31
+ body = { platform: platform }
32
+ body[:redirect_url] = redirect_url if redirect_url
33
+ result = @client.request(:post, "/profile_groups/#{id}/initialize_connection", json: body)
34
+ ConnectionResponse.new(**result)
35
+ end
36
+
37
+ def connect_bluesky(id, identifier:, app_password:)
30
38
  result = @client.request(:post, "/profile_groups/#{id}/initialize_connection",
31
- json: { platform: platform, redirect_url: redirect_url }
39
+ json: { platform: "bluesky", identifier: identifier, app_password: app_password }
32
40
  )
33
- ConnectionResponse.new(**result)
41
+ BlueskyConnectionResponse.new(**result)
42
+ end
43
+
44
+ # After this call, poll `client.profiles.placements(profile.id)` until non-empty —
45
+ # the bot must be added as administrator to a channel in Telegram first.
46
+ def connect_telegram(id, bot_token:)
47
+ result = @client.request(:post, "/profile_groups/#{id}/initialize_connection",
48
+ json: { platform: "telegram", bot_token: bot_token }
49
+ )
50
+ TelegramConnectionResponse.new(**result)
34
51
  end
35
52
  end
36
53
  end
@@ -22,6 +22,20 @@ module PostProxy
22
22
  ListResponse.new(data: items)
23
23
  end
24
24
 
25
+ # `placement_id` is required for facebook, linkedin, and telegram profiles.
26
+ def get_profile_stats(id, placement_id: nil, from: nil, to: nil, profile_group_id: nil)
27
+ params = {}
28
+ params[:placement_id] = placement_id if placement_id
29
+ params[:from] = from if from
30
+ params[:to] = to if to
31
+
32
+ result = @client.request(:get, "/profiles/#{id}/stats",
33
+ params: params.empty? ? nil : params,
34
+ profile_group_id: profile_group_id
35
+ )
36
+ ProfileStatsResponse.new(data: result[:data])
37
+ end
38
+
25
39
  def delete(id, profile_group_id: nil)
26
40
  result = @client.request(:delete, "/profiles/#{id}", profile_group_id: profile_group_id)
27
41
  SuccessResponse.new(**result)
@@ -63,17 +63,31 @@ module PostProxy
63
63
  end
64
64
  end
65
65
 
66
+ class ErrorDetails < Model
67
+ attr_accessor :platform_error_code, :platform_error_subcode, :platform_error_message, :postproxy_note
68
+
69
+ def initialize(**attrs)
70
+ @platform_error_code = nil
71
+ @platform_error_subcode = nil
72
+ @platform_error_message = nil
73
+ @postproxy_note = nil
74
+ super
75
+ end
76
+ end
77
+
66
78
  class PlatformResult < Model
67
- attr_accessor :platform, :status, :params, :error, :attempted_at, :insights
79
+ attr_accessor :platform, :status, :params, :error, :error_details, :attempted_at, :insights
68
80
 
69
81
  def initialize(**attrs)
70
82
  @params = nil
71
83
  @error = nil
84
+ @error_details = nil
72
85
  @attempted_at = nil
73
86
  @insights = nil
74
87
  super
75
88
  @attempted_at = parse_time(@attempted_at)
76
89
  @insights = Insights.new(**@insights) if @insights.is_a?(Hash)
90
+ @error_details = ErrorDetails.new(**@error_details.transform_keys(&:to_sym)) if @error_details.is_a?(Hash)
77
91
  end
78
92
 
79
93
  private
@@ -316,14 +330,80 @@ module PostProxy
316
330
  attr_accessor :deleted
317
331
  end
318
332
 
333
+ class DeletingPlatform < Model
334
+ attr_accessor :post_profile_id, :platform
335
+ end
336
+
337
+ class DeleteOnPlatformResponse < Model
338
+ attr_accessor :success, :deleting
339
+
340
+ def initialize(**attrs)
341
+ @deleting = []
342
+ super
343
+ @deleting = (@deleting || []).map do |entry|
344
+ entry.is_a?(DeletingPlatform) ? entry : DeletingPlatform.new(**entry)
345
+ end
346
+ end
347
+ end
348
+
319
349
  class SuccessResponse < Model
320
350
  attr_accessor :success
321
351
  end
322
352
 
353
+ # OAuth-style connection response (facebook, instagram, twitter, etc.).
323
354
  class ConnectionResponse < Model
324
355
  attr_accessor :url, :success
325
356
  end
326
357
 
358
+ # Alias for clarity at call sites; same shape as ConnectionResponse.
359
+ OAuthConnectionResponse = ConnectionResponse
360
+
361
+ class SyncProfile < Model
362
+ attr_accessor :id, :network, :name, :external_username
363
+ end
364
+
365
+ class BlueskyConnectionResponse < Model
366
+ attr_accessor :success, :profile
367
+
368
+ def initialize(**attrs)
369
+ @profile = nil
370
+ super
371
+ @profile = SyncProfile.new(**@profile.transform_keys(&:to_sym)) if @profile.is_a?(Hash)
372
+ end
373
+ end
374
+
375
+ class TelegramConnectionResponse < Model
376
+ attr_accessor :success, :profile, :next_step
377
+
378
+ def initialize(**attrs)
379
+ @profile = nil
380
+ @next_step = nil
381
+ super
382
+ @profile = SyncProfile.new(**@profile.transform_keys(&:to_sym)) if @profile.is_a?(Hash)
383
+ end
384
+ end
385
+
386
+ class ProfileStats < Model
387
+ attr_accessor :profile_id, :platform, :placement_id, :records
388
+
389
+ def initialize(**attrs)
390
+ @placement_id = nil
391
+ @records = []
392
+ super
393
+ @records = (@records || []).map do |r|
394
+ r.is_a?(StatsRecord) ? r : StatsRecord.new(**r.transform_keys(&:to_sym))
395
+ end
396
+ end
397
+ end
398
+
399
+ class ProfileStatsResponse
400
+ attr_reader :data
401
+
402
+ def initialize(data:)
403
+ @data = data.is_a?(ProfileStats) ? data : ProfileStats.new(**data.transform_keys(&:to_sym))
404
+ end
405
+ end
406
+
327
407
  # Platform-specific parameter structs
328
408
 
329
409
  class FacebookParams < Model
@@ -346,7 +426,8 @@ module PostProxy
346
426
  end
347
427
 
348
428
  class YouTubeParams < Model
349
- attr_accessor :format, :title, :privacy_status, :cover_url, :made_for_kids
429
+ attr_accessor :format, :title, :privacy_status, :cover_url, :made_for_kids,
430
+ :tags, :category_id, :contains_synthetic_media
350
431
  end
351
432
 
352
433
  class PinterestParams < Model
@@ -361,13 +442,21 @@ module PostProxy
361
442
  attr_accessor :format
362
443
  end
363
444
 
445
+ class BlueskyParams < Model
446
+ attr_accessor :format
447
+ end
448
+
449
+ class TelegramParams < Model
450
+ attr_accessor :format, :chat_id, :parse_mode, :disable_link_preview, :disable_notification
451
+ end
452
+
364
453
  class PlatformParams < Model
365
454
  attr_accessor :facebook, :instagram, :tiktok, :linkedin, :youtube,
366
- :pinterest, :threads, :twitter
455
+ :pinterest, :threads, :twitter, :bluesky, :telegram
367
456
 
368
457
  def to_h
369
458
  result = {}
370
- %i[facebook instagram tiktok linkedin youtube pinterest threads twitter].each do |platform|
459
+ %i[facebook instagram tiktok linkedin youtube pinterest threads twitter bluesky telegram].each do |platform|
371
460
  value = send(platform)
372
461
  next if value.nil?
373
462
 
@@ -1,3 +1,3 @@
1
1
  module PostProxy
2
- VERSION = "1.6.0"
2
+ VERSION = "1.8.0"
3
3
  end
@@ -0,0 +1,113 @@
1
+ require "json"
2
+
3
+ module PostProxy
4
+ class WebhookParseError < StandardError; end
5
+
6
+ module WebhookEvents
7
+ class Event < Model
8
+ attr_accessor :id, :type, :created_at, :data
9
+ end
10
+
11
+ class PostProcessedPlatform < Model
12
+ attr_accessor :id, :platform, :name
13
+ end
14
+
15
+ class PostProcessedData < Model
16
+ attr_accessor :id, :body, :status, :scheduled_at, :created_at, :platforms
17
+
18
+ def initialize(**attrs)
19
+ @platforms = []
20
+ super
21
+ @platforms = (@platforms || []).map do |p|
22
+ p.is_a?(PostProcessedPlatform) ? p : PostProcessedPlatform.new(**p.transform_keys(&:to_sym))
23
+ end
24
+ end
25
+ end
26
+
27
+ class ImportedProfile < Model
28
+ attr_accessor :id, :name, :platform
29
+ end
30
+
31
+ class PostImportedData < Model
32
+ attr_accessor :id, :body, :source, :posted_at, :created_at,
33
+ :platform, :profile, :platform_post_id, :public_id
34
+
35
+ def initialize(**attrs)
36
+ @profile = nil
37
+ super
38
+ @profile = ImportedProfile.new(**@profile.transform_keys(&:to_sym)) if @profile.is_a?(Hash)
39
+ end
40
+ end
41
+
42
+ class PlatformPostData < Model
43
+ attr_accessor :id, :post_id, :platform, :profile_id, :profile_name,
44
+ :status, :error, :error_details, :platform_id, :insights
45
+
46
+ def initialize(**attrs)
47
+ @error_details = nil
48
+ @insights = nil
49
+ super
50
+ @error_details = ErrorDetails.new(**@error_details.transform_keys(&:to_sym)) if @error_details.is_a?(Hash)
51
+ end
52
+ end
53
+
54
+ class ProfileEventData < Model
55
+ attr_accessor :id, :name, :platform, :profile_group_id, :status, :uid, :username
56
+ end
57
+
58
+ class ProfileStatsData < Model
59
+ attr_accessor :profile_id, :platform, :placement_id, :stats, :recorded_at
60
+ end
61
+
62
+ class MediaFailedData < Model
63
+ attr_accessor :id, :post_id, :content_type, :status, :error_message
64
+ end
65
+
66
+ class CommentCreatedData < Model
67
+ attr_accessor :id, :post_id, :platform_post_id, :platform, :external_id,
68
+ :parent_external_id, :body, :status, :author_external_id,
69
+ :author_name, :author_username, :author_avatar_url,
70
+ :like_count, :reply_count, :is_hidden, :permalink,
71
+ :platform_data, :posted_at, :created_at
72
+ end
73
+
74
+ DATA_CLASSES = {
75
+ "post.processed" => PostProcessedData,
76
+ "post.imported" => PostImportedData,
77
+ "platform_post.published" => PlatformPostData,
78
+ "platform_post.failed" => PlatformPostData,
79
+ "platform_post.failed_waiting_for_retry" => PlatformPostData,
80
+ "platform_post.insights" => PlatformPostData,
81
+ "profile.connected" => ProfileEventData,
82
+ "profile.disconnected" => ProfileEventData,
83
+ "profile.stats" => ProfileStatsData,
84
+ "media.failed" => MediaFailedData,
85
+ "comment.created" => CommentCreatedData
86
+ }.freeze
87
+
88
+ # Parse a webhook body and return a typed Event. `data` is parsed into the
89
+ # appropriate model based on `type`. Raises WebhookParseError on bad input.
90
+ def self.parse(body)
91
+ parsed =
92
+ case body
93
+ when String then JSON.parse(body, symbolize_names: true)
94
+ when Hash then body.transform_keys(&:to_sym)
95
+ else raise WebhookParseError, "Webhook body must be a String or Hash"
96
+ end
97
+ rescue JSON::ParserError => e
98
+ raise WebhookParseError, "Invalid JSON: #{e.message}"
99
+ else
100
+ type = parsed[:type].to_s
101
+ raise WebhookParseError, "Unknown webhook event type: #{type.inspect}" unless DATA_CLASSES.key?(type)
102
+
103
+ data_class = DATA_CLASSES[type]
104
+ data_hash = (parsed[:data] || {}).transform_keys(&:to_sym)
105
+ Event.new(
106
+ id: parsed[:id],
107
+ type: type,
108
+ created_at: parsed[:created_at],
109
+ data: data_class.new(**data_hash)
110
+ )
111
+ end
112
+ end
113
+ end
data/lib/postproxy.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "postproxy/errors"
4
4
  require_relative "postproxy/types"
5
5
  require_relative "postproxy/client"
6
6
  require_relative "postproxy/webhook_signature"
7
+ require_relative "postproxy/webhook_events"
7
8
 
8
9
  module PostProxy
9
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postproxy-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - PostProxy
@@ -86,6 +86,7 @@ files:
86
86
  - lib/postproxy/resources/webhooks.rb
87
87
  - lib/postproxy/types.rb
88
88
  - lib/postproxy/version.rb
89
+ - lib/postproxy/webhook_events.rb
89
90
  - lib/postproxy/webhook_signature.rb
90
91
  homepage: https://postproxy.dev
91
92
  licenses: