broadcast-ruby 0.7.0 → 0.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: 6691d4bb7e0fb74c2f3fe326d1ef2ae6797ec957f730be3d62287c07b13b2b65
4
- data.tar.gz: 6117bc0c528ddb576ec51eafe1c56071b05fc354d06cbe66b067effbe2f8e560
3
+ metadata.gz: 722b6b8aba5a3d87fbdacbab42f757071d0f4b7bc548a803f9b28fb0b4596ec9
4
+ data.tar.gz: 78c247ac8e18e66f3fff0e380b8a0d299047d15994765a0ad6ddb8f13cb766ba
5
5
  SHA512:
6
- metadata.gz: 86f1f4579ff54f8677f1848efa21d097bea66ab5e2102fcc05763021a4f7ff05b34818b93e506631f2cd241bbe87c21d587bc0f6ff60f72adadad4f3acefc009
7
- data.tar.gz: b0a6d3889b396bce312a174f3da12e87a3f20ac729c91c26891a03f1b6f7f1f696f02d1c5681773b1f3fdc649034426d52a637891fe3153b8e0d0e4b044fc6a1
6
+ metadata.gz: a3cd09cc4c96d57ed30c64c8c48fade4f75bb6f5c15136819f7725e9eea1f8811b8e3bd91ec70125d92ad8411fcf60ca04cc0b5461bd50858e5f6c611f2246fe
7
+ data.tar.gz: edf1130a392a68a08fc95c1a29619e1a0399dbe0373c85048b6c45bba12a8dff88fb9ed84b1364c06ba5b5c9fa2c90e5da8fd083bd99b7d832a122cb72d3501e
data/CHANGELOG.md CHANGED
@@ -4,6 +4,33 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.8.0] - 2026-10-10
8
+
9
+ ### Added
10
+
11
+ - `email.send_delayed` and `broadcast.batch_completed` in
12
+ `Broadcast::Webhook::EVENT_TYPES` (and in `EMAIL_EVENTS` /
13
+ `BROADCAST_EVENTS`), matching the server (Broadcast 2.43.0).
14
+ `email.send_delayed` fires when a transactional email waits for room under
15
+ its server's hourly limit.
16
+ - `excluded_segment_ids` on broadcasts, sequences and autopilots (create,
17
+ update, and in the returned record): segments a send never reaches. The
18
+ server refuses a segment that is both sent to and excluded with 422.
19
+ - `subscribers.create(unsubscribed_at: ...)`: creates a subscriber who has
20
+ already unsubscribed, in one request, with any token. Before, the server
21
+ ignored the field and a migration had to create, then unsubscribe.
22
+
23
+ - `Broadcast::Resources::OptInForms::TRIGGER_FREQUENCIES`: the words
24
+ `trigger_settings[:frequency]` accepts (`always`, `every_visit`,
25
+ `once_per_session`, `once_per_day`, `once_per_week`, `once`).
26
+
27
+ ### Changed
28
+
29
+ - Opt-in forms: the server now refuses an unknown `trigger_settings`
30
+ frequency word with 422 (`Broadcast::ValidationError`). Before, it saved
31
+ any word, and an unknown one showed the popup on every visit. The client
32
+ still sends what it is given.
33
+
7
34
  ## [0.7.0] - 2026-10-06
8
35
 
9
36
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- broadcast-ruby (0.7.0)
4
+ broadcast-ruby (0.8.0)
5
5
  base64
6
6
 
7
7
  GEM
@@ -177,7 +177,7 @@ CHECKSUMS
177
177
  ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
178
178
  base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
179
179
  bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
180
- broadcast-ruby (0.7.0)
180
+ broadcast-ruby (0.8.0)
181
181
  builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
182
182
  concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
183
183
  connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
data/README.md CHANGED
@@ -734,6 +734,12 @@ client.topics.delete(topic['id']) # 422 while a broadcast or sequence uses it
734
734
  # Send to a topic
735
735
  client.broadcasts.create(subject: 'Webinar', body: '...', segment_ids: [2], topic_id: topic['id'])
736
736
 
737
+ # Send to everyone except a segment (also on sequences and autopilots)
738
+ client.broadcasts.create(subject: 'Offer', body: '...', excluded_segment_ids: [competitors['id']])
739
+
740
+ # Migrate someone who already unsubscribed, in one request
741
+ client.subscribers.create(email: 'opted-out@example.com', unsubscribed_at: '2025-03-14T09:30:00Z')
742
+
737
743
  # Change only the keys you send (nil deletes a key); the default replaces custom_data
738
744
  client.subscribers.update('jane@example.com', custom_data: { sub_webinars: false }, custom_data_mode: 'merge')
739
745
  ```
@@ -889,6 +895,11 @@ result = client.opt_in_forms.create(
889
895
  # Update (deeply nested settings hashes pass through verbatim)
890
896
  client.opt_in_forms.update(1, enabled: false)
891
897
 
898
+ # How often the same visitor sees a popup. Any word outside
899
+ # Broadcast::Resources::OptInForms::TRIGGER_FREQUENCIES raises
900
+ # Broadcast::ValidationError (422).
901
+ client.opt_in_forms.update(1, trigger_settings: { frequency: 'once_per_day' })
902
+
892
903
  # Delete
893
904
  client.opt_in_forms.delete(1)
894
905
  ```
@@ -1163,7 +1174,7 @@ secret = result['secret']
1163
1174
 
1164
1175
  # Every valid event type is available as a constant. An unknown event type is
1165
1176
  # dropped server-side rather than rejected, so subscribe from these.
1166
- Broadcast::Webhook::EVENT_TYPES # all 35
1177
+ Broadcast::Webhook::EVENT_TYPES # all 37
1167
1178
  Broadcast::Webhook::EMAIL_EVENTS # email.sent, email.delivered, ...
1168
1179
  Broadcast::Webhook::SUBSCRIBER_EVENTS # subscriber.created, ..., subscribers.purged
1169
1180
  Broadcast::Webhook::BROADCAST_EVENTS # broadcast.sending, broadcast.sent, ...
@@ -1194,9 +1205,9 @@ result['data'] # => [{'id' => 1, 'event_type' => 'email.sent', 'response_status
1194
1205
 
1195
1206
  | Category | Events |
1196
1207
  |----------|--------|
1197
- | Email | `email.sent`, `email.delivered`, `email.delivery_delayed`, `email.opened`, `email.clicked`, `email.bounced`, `email.complained`, `email.failed` |
1208
+ | Email | `email.sent`, `email.delivered`, `email.delivery_delayed`, `email.send_delayed`, `email.opened`, `email.clicked`, `email.bounced`, `email.complained`, `email.failed` |
1198
1209
  | Subscriber | `subscriber.created`, `subscriber.updated`, `subscriber.deleted`, `subscriber.subscribed`, `subscriber.unsubscribed`, `subscriber.bounced`, `subscriber.complained`, `subscribers.purged`, `subscribers.purge_failed` |
1199
- | Broadcast | `broadcast.scheduled`, `broadcast.queueing`, `broadcast.sending`, `broadcast.sent`, `broadcast.failed`, `broadcast.partial_failure`, `broadcast.aborted`, `broadcast.paused` |
1210
+ | Broadcast | `broadcast.scheduled`, `broadcast.queueing`, `broadcast.sending`, `broadcast.sent`, `broadcast.failed`, `broadcast.partial_failure`, `broadcast.aborted`, `broadcast.paused`, `broadcast.batch_completed` |
1200
1211
  | Sequence | `sequence.subscriber_added`, `sequence.subscriber_completed`, `sequence.subscriber_moved`, `sequence.subscriber_removed`, `sequence.subscriber_paused`, `sequence.subscriber_resumed`, `sequence.subscriber_error` |
1201
1212
  | System | `message.attempt.exhausted`, `test.webhook` |
1202
1213
 
data/SDK-COVERAGE.md CHANGED
@@ -331,7 +331,7 @@ Inbound webhooks — the app calling you.
331
331
  | HMAC-SHA256 verification (`v1,<base64>`) | ✅ `Webhook.verify` |
332
332
  | 5-minute timestamp tolerance | ✅ Replay protection |
333
333
  | Constant-time comparison | ✅ `OpenSSL.fixed_length_secure_compare` |
334
- | Event type constants | ✅ `Webhook::EVENT_TYPES` — 35 values |
334
+ | Event type constants | ✅ `Webhook::EVENT_TYPES` — 37 values |
335
335
 
336
336
  Categories: `EMAIL_EVENTS` (8), `SUBSCRIBER_EVENTS` (7), `BROADCAST_EVENTS` (8),
337
337
  `SEQUENCE_EVENTS` (7), `SYSTEM_EVENTS` (2).
@@ -30,6 +30,7 @@ module Broadcast
30
30
  # copies_to_generate: how many drafts each run produces
31
31
  # tone_description:, content_instructions:, newsletter_structure:
32
32
  # segment_ids: array — restrict the newsletter's audience
33
+ # excluded_segment_ids: array — segments its drafts never reach
33
34
  def create(**attrs)
34
35
  post('/api/v1/autopilots', { autopilot: attrs })
35
36
  end
@@ -5,6 +5,12 @@ require 'date'
5
5
  module Broadcast
6
6
  module Resources
7
7
  class OptInForms < Base
8
+ # The words trigger_settings[:frequency] accepts: how often the same visitor
9
+ # sees a popup. always and every_visit mean the same. The server refuses any
10
+ # other word with 422 (Broadcast::ValidationError); the client does not
11
+ # check, so an older server is never refused a word it would take.
12
+ TRIGGER_FREQUENCIES = %w[always every_visit once_per_session once_per_day once_per_week once].freeze
13
+
8
14
  # List opt-in forms.
9
15
  #
10
16
  # NOTE: returns up to 250 results per page along with `pagination`
@@ -36,6 +42,10 @@ module Broadcast
36
42
  #
37
43
  # Custom fields declared in opt_in_form_blocks_attributes support a
38
44
  # multi-line variant, which renders as a textarea on the hosted form.
45
+ #
46
+ # trigger_settings: { frequency: } must be one of TRIGGER_FREQUENCIES;
47
+ # any other word raises Broadcast::ValidationError (422). Keys sent in a
48
+ # settings hash are merged into the stored settings.
39
49
  def create(**attrs)
40
50
  post('/api/v1/opt_in_forms', { opt_in_form: attrs })
41
51
  end
@@ -45,7 +45,13 @@ module Broadcast
45
45
  # another provider. Ignored (with a warning) on update,
46
46
  # and ignored entirely for channel-scoped tokens.
47
47
  #
48
- # Note `unsubscribed_at` is never settable here — use `unsubscribe(email)`.
48
+ # Any token, create only:
49
+ # unsubscribed_at: ISO 8601. Stores the subscriber as unsubscribed in the
50
+ # same request (inactive, on the unsubscribe list), for
51
+ # migrating a list with its opt-outs intact. No
52
+ # confirmation email; 422 if it is in the future or sent
53
+ # with is_active: true. To unsubscribe an existing
54
+ # subscriber, use `unsubscribe(email)`.
49
55
  def create(**attrs)
50
56
  double_opt_in = attrs.delete(:double_opt_in)
51
57
  confirmation_template_id = attrs.delete(:confirmation_template_id)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Broadcast
4
- VERSION = '0.7.0'
4
+ VERSION = '0.8.0'
5
5
  end
@@ -10,9 +10,12 @@ module Broadcast
10
10
  # Every event type a webhook endpoint can subscribe to, mirroring
11
11
  # WebhookEndpoint::AVAILABLE_EVENT_TYPES server-side. Use these when
12
12
  # creating an endpoint — an unknown event type is dropped silently.
13
+ # email.send_delayed: a transactional email is waiting for room under its
14
+ # server's hourly limit (not yet sent). email.delivery_delayed: the
15
+ # provider accepted it and the recipient's server is delaying it.
13
16
  EMAIL_EVENTS = %w[
14
- email.sent email.delivered email.delivery_delayed email.complained
15
- email.bounced email.opened email.clicked email.failed
17
+ email.sent email.delivered email.delivery_delayed email.send_delayed
18
+ email.complained email.bounced email.opened email.clicked email.failed
16
19
  ].freeze
17
20
 
18
21
  # subscribers.* are sent once for a whole-list purge, in place of a
@@ -26,7 +29,7 @@ module Broadcast
26
29
  BROADCAST_EVENTS = %w[
27
30
  broadcast.scheduled broadcast.queueing broadcast.sending broadcast.sent
28
31
  broadcast.failed broadcast.partial_failure broadcast.aborted
29
- broadcast.paused
32
+ broadcast.paused broadcast.batch_completed
30
33
  ].freeze
31
34
 
32
35
  SEQUENCE_EVENTS = %w[
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: broadcast-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Chiu