trycourier 6.6.0 → 6.7.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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +1 -1
  4. data/lib/courier/models/create_journey_request.rb +16 -1
  5. data/lib/courier/models/journey_response.rb +14 -1
  6. data/lib/courier/models/topic_digest_request.rb +23 -11
  7. data/lib/courier/models/topic_digest_schedule_request.rb +6 -0
  8. data/lib/courier/models/topic_digest_schedule_response.rb +8 -0
  9. data/lib/courier/models/users/topic_preference.rb +7 -2
  10. data/lib/courier/models/workspace_preference_topic_create_request.rb +87 -5
  11. data/lib/courier/resources/journeys.rb +9 -2
  12. data/lib/courier/resources/workspace_preferences/topics.rb +1 -1
  13. data/lib/courier/version.rb +1 -1
  14. data/rbi/courier/models/create_journey_request.rbi +19 -0
  15. data/rbi/courier/models/journey_response.rbi +12 -0
  16. data/rbi/courier/models/topic_digest_request.rbi +43 -12
  17. data/rbi/courier/models/topic_digest_schedule_request.rbi +6 -0
  18. data/rbi/courier/models/topic_digest_schedule_response.rbi +16 -0
  19. data/rbi/courier/models/users/topic_preference.rbi +14 -4
  20. data/rbi/courier/models/workspace_preference_topic_create_request.rbi +155 -8
  21. data/rbi/courier/resources/journeys.rbi +14 -0
  22. data/rbi/courier/resources/workspace_preferences/topics.rbi +11 -3
  23. data/sig/courier/models/create_journey_request.rbs +7 -0
  24. data/sig/courier/models/journey_response.rbs +5 -0
  25. data/sig/courier/models/topic_digest_request.rbs +9 -5
  26. data/sig/courier/models/workspace_preference_topic_create_request.rbs +49 -4
  27. data/sig/courier/resources/journeys.rbs +2 -0
  28. data/sig/courier/resources/workspace_preferences/topics.rbs +1 -1
  29. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72f51e60173a98ce2cc1e4b6d3c0613e82f18de751e7ea855ed2418808cac4d9
4
- data.tar.gz: 5a10110fea4a9c3b8c5acaf39d169a902c7a8566e4ddfb49933eaed3600c0924
3
+ metadata.gz: c665c6475e9af26f67197651f5599bac614c384d86086dd974ed410005ab407d
4
+ data.tar.gz: 4e037944cf9a6cd6346aa647a5f097e3cd04a5be4676b1b0bc392bed497be990
5
5
  SHA512:
6
- metadata.gz: 7940121c65ecbb1ef483b5f8594cdde2a3b08f1c93d22c04ebbd829b2989030e6d3bc43359b98196fc749a4c21fe8d54cb2a3355f37e057996da472e807751eb
7
- data.tar.gz: 569ff793ab8fa5d18202278cd38630cb6556c391f3097e2931c938afb87e2a6c163c4b061bab684dc4a18d668843d0b36a7ebbb5b11699976483d49e466d5370
6
+ metadata.gz: 244553b3412e7041264a0ceb8e355e89fcf67b8f00098cfab876e00408c39089e4e6bf0031693e7ab49749e43e74ac4fbf6b7ca16f8e91c00f63bc061157725e
7
+ data.tar.gz: 60ce9fc7ae0c32289b97208cad86e4c97c0ca4b44f6d7f0d10967e72ea4922bc19104a95a46c6c7ee146372a57ba9a255b773a26f9d2bad505f3e905c84d66e9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [6.7.0](https://github.com/trycourier/courier-ruby/compare/v6.6.0...v6.7.0) (2026-09-22)
4
+
5
+
6
+ ### Features
7
+
8
+ * **api:** add cancelation_token to journey create, replace, and get ([#158](https://github.com/trycourier/courier-ruby/issues/158)) ([ec47880](https://github.com/trycourier/courier-ruby/commit/ec47880a79aaefde00dedcbdc84527ff234a99f2))
9
+
10
+
11
+ ### Documentation
12
+
13
+ * **api:** correct the digest schedule contract, and make `schedules` optional ([#156](https://github.com/trycourier/courier-ruby/issues/156)) ([8578d77](https://github.com/trycourier/courier-ruby/commit/8578d77848275105865c1b29b799f2cc6621987e))
14
+
3
15
  ## [6.6.0](https://github.com/trycourier/courier-ruby/compare/v6.5.0...v6.6.0) (2026-09-15)
4
16
 
5
17
 
data/README.md CHANGED
@@ -9,7 +9,7 @@ Add the gem to your `Gemfile`:
9
9
  <!-- x-release-please-start-version -->
10
10
 
11
11
  ```ruby
12
- gem "trycourier", "~> 6.6.0"
12
+ gem "trycourier", "~> 6.7.0"
13
13
  ```
14
14
 
15
15
  <!-- x-release-please-end -->
@@ -13,6 +13,16 @@ module Courier
13
13
  # @return [Array<Courier::Models::JourneyAPIInvokeTriggerNode, Courier::Models::JourneySegmentTriggerNode, Courier::Models::JourneyAudienceTriggerNode, Courier::Models::JourneyWebhookTriggerNode, Courier::Models::JourneySendNode, Courier::Models::JourneyDelayDurationNode, Courier::Models::JourneyDelayUntilNode, Courier::Models::JourneyFetchGetDeleteNode, Courier::Models::JourneyFetchPostPutNode, Courier::Models::JourneyAINode, Courier::Models::JourneyThrottleStaticNode, Courier::Models::JourneyThrottleDynamicNode, Courier::Models::JourneyNode::JourneyBatchNode, Courier::Models::JourneyNode::JourneyAddToDigestNode, Courier::Models::JourneyExitNode, Courier::Models::JourneyNode::JourneyBranchNode>]
14
14
  required :nodes, -> { Courier::Internal::Type::ArrayOf[union: Courier::JourneyNode] }
15
15
 
16
+ # @!attribute cancelation_token
17
+ # Cancelation token stored on the journey definition. It tags every run the
18
+ # journey creates so that `POST /journeys/cancel` can later cancel those runs by
19
+ # token. Accepts a templated string such as `order-{{data.order_id}}`, which is
20
+ # resolved per run when the journey is invoked. On a replace, omitting this field
21
+ # preserves any existing token and sending a value replaces it.
22
+ #
23
+ # @return [String, nil]
24
+ optional :cancelation_token, String
25
+
16
26
  # @!attribute enabled
17
27
  #
18
28
  # @return [Boolean, nil]
@@ -24,13 +34,18 @@ module Courier
24
34
  # @return [Symbol, Courier::Models::JourneyState, nil]
25
35
  optional :state, enum: -> { Courier::JourneyState }
26
36
 
27
- # @!method initialize(name:, nodes:, enabled: nil, state: nil)
37
+ # @!method initialize(name:, nodes:, cancelation_token: nil, enabled: nil, state: nil)
38
+ # Some parameter documentations has been truncated, see
39
+ # {Courier::Models::CreateJourneyRequest} for more details.
40
+ #
28
41
  # Request body for creating a journey.
29
42
  #
30
43
  # @param name [String]
31
44
  #
32
45
  # @param nodes [Array<Courier::Models::JourneyAPIInvokeTriggerNode, Courier::Models::JourneySegmentTriggerNode, Courier::Models::JourneyAudienceTriggerNode, Courier::Models::JourneyWebhookTriggerNode, Courier::Models::JourneySendNode, Courier::Models::JourneyDelayDurationNode, Courier::Models::JourneyDelayUntilNode, Courier::Models::JourneyFetchGetDeleteNode, Courier::Models::JourneyFetchPostPutNode, Courier::Models::JourneyAINode, Courier::Models::JourneyThrottleStaticNode, Courier::Models::JourneyThrottleDynamicNode, Courier::Models::JourneyNode::JourneyBatchNode, Courier::Models::JourneyNode::JourneyAddToDigestNode, Courier::Models::JourneyExitNode, Courier::Models::JourneyNode::JourneyBranchNode>]
33
46
  #
47
+ # @param cancelation_token [String] Cancelation token stored on the journey definition. It tags every run the journe
48
+ #
34
49
  # @param enabled [Boolean]
35
50
  #
36
51
  # @param state [Symbol, Courier::Models::JourneyState] Lifecycle state of a journey.
@@ -9,6 +9,14 @@ module Courier
9
9
  # @return [String]
10
10
  required :id, String
11
11
 
12
+ # @!attribute cancelation_token
13
+ # The journey cancelation token, or null when none is set. A token authored in the
14
+ # dashboard is returned in its raw templated form, such as
15
+ # `order-{{data.order_id}}`, so it can be read back and asserted.
16
+ #
17
+ # @return [String, nil]
18
+ required :cancelation_token, String, nil?: true
19
+
12
20
  # @!attribute created
13
21
  #
14
22
  # @return [Integer, nil]
@@ -55,11 +63,16 @@ module Courier
55
63
  # @return [String, nil]
56
64
  required :updater, String, nil?: true
57
65
 
58
- # @!method initialize(id:, created:, creator:, enabled:, name:, nodes:, published:, state:, updated:, updater:)
66
+ # @!method initialize(id:, cancelation_token:, created:, creator:, enabled:, name:, nodes:, published:, state:, updated:, updater:)
67
+ # Some parameter documentations has been truncated, see
68
+ # {Courier::Models::JourneyResponse} for more details.
69
+ #
59
70
  # A journey, with its current draft or published nodes and metadata.
60
71
  #
61
72
  # @param id [String]
62
73
  #
74
+ # @param cancelation_token [String, nil] The journey cancelation token, or null when none is set. A token authored in the
75
+ #
63
76
  # @param created [Integer, nil]
64
77
  #
65
78
  # @param creator [String, nil]
@@ -3,14 +3,6 @@
3
3
  module Courier
4
4
  module Models
5
5
  class TopicDigestRequest < Courier::Internal::Type::BaseModel
6
- # @!attribute schedules
7
- # The cadences this digest delivers on. At least one is required: a digest with no
8
- # schedule collects events into an instance that can never fire. Omitting the key
9
- # on a replace leaves stored schedules untouched; sending `[]` is a `400`.
10
- #
11
- # @return [Array<Courier::Models::TopicDigestScheduleRequest>]
12
- required :schedules, -> { Courier::Internal::Type::ArrayOf[Courier::TopicDigestScheduleRequest] }
13
-
14
6
  # @!attribute template_id
15
7
  # The notification template that renders the digest. A digest with no template
16
8
  # collects nothing, so this is required.
@@ -31,13 +23,33 @@ module Courier
31
23
  # @return [Array<Courier::Models::TopicDigestCategory>, nil]
32
24
  optional :categories, -> { Courier::Internal::Type::ArrayOf[Courier::TopicDigestCategory] }
33
25
 
26
+ # @!attribute schedules
27
+ # The cadences this digest delivers on.
28
+ #
29
+ # The array replaces the stored schedules wholesale, so a schedule you leave out
30
+ # of it is deleted along with its delivery rule. Omit the key entirely to leave
31
+ # the stored schedules untouched — useful for changing `template_id` or
32
+ # `categories` without restating every schedule.
33
+ #
34
+ # A digest must end up with at least one schedule, because one with none collects
35
+ # events into an instance that can never fire. So sending `[]` is always a `400`,
36
+ # and so is omitting the key on a topic that has no schedules stored yet.
37
+ #
38
+ # On **create** the key is required outright: a topic being created has nothing
39
+ # stored to leave alone, and the topic row is written before its digest, so
40
+ # rejecting it any later would leave the topic behind and let a retry duplicate
41
+ # it.
42
+ #
43
+ # @return [Array<Courier::Models::TopicDigestScheduleRequest>, nil]
44
+ optional :schedules, -> { Courier::Internal::Type::ArrayOf[Courier::TopicDigestScheduleRequest] }
45
+
34
46
  # @!attribute trigger_empty
35
47
  # Whether to deliver the digest even when nothing was collected.
36
48
  #
37
49
  # @return [Boolean, nil]
38
50
  optional :trigger_empty, Courier::Internal::Type::Boolean
39
51
 
40
- # @!method initialize(schedules:, template_id:, audience_id: nil, categories: nil, trigger_empty: nil)
52
+ # @!method initialize(template_id:, audience_id: nil, categories: nil, schedules: nil, trigger_empty: nil)
41
53
  # Some parameter documentations has been truncated, see
42
54
  # {Courier::Models::TopicDigestRequest} for more details.
43
55
  #
@@ -49,14 +61,14 @@ module Courier
49
61
  # `schedules: []` is rejected, because both states are un-deliverable rather than
50
62
  # merely off.
51
63
  #
52
- # @param schedules [Array<Courier::Models::TopicDigestScheduleRequest>] The cadences this digest delivers on. At least one is required: a digest with no
53
- #
54
64
  # @param template_id [String] The notification template that renders the digest. A digest with no template col
55
65
  #
56
66
  # @param audience_id [String] Optional audience the digest is scoped to.
57
67
  #
58
68
  # @param categories [Array<Courier::Models::TopicDigestCategory>] Retention rules per category key. Defaults to a single `digest` category retaini
59
69
  #
70
+ # @param schedules [Array<Courier::Models::TopicDigestScheduleRequest>] The cadences this digest delivers on.
71
+ #
60
72
  # @param trigger_empty [Boolean] Whether to deliver the digest even when nothing was collected.
61
73
  end
62
74
  end
@@ -71,6 +71,12 @@ module Courier
71
71
  # `schedules` array is a full replacement, so a stored schedule absent from it is
72
72
  # deleted along with its delivery rule.
73
73
  #
74
+ # Updating by `schedule_id` replaces that schedule rather than merging into it:
75
+ # any field you leave out is cleared. Two of those change delivery silently — an
76
+ # omitted `timezone` reverts the schedule to UTC, and an omitted `is_default` can
77
+ # leave the topic with no default schedule, which is what recipients who have not
78
+ # chosen one fall back to. Restate every field you want to keep.
79
+ #
74
80
  # @param frequency [Symbol, Courier::Models::DigestFrequency] How often a digest is delivered. `instant` delivers immediately without batching
75
81
  #
76
82
  # @param day_of_month [Integer] Required when `frequency` is `monthly`.
@@ -7,6 +7,14 @@ module Courier
7
7
  # The schedule's identifier, assigned by the server. This is the value the
8
8
  # `/digests/schedules/{schedule_id}` endpoints are keyed by.
9
9
  #
10
+ # Two formats are in circulation and only one is safe to drop into a URL.
11
+ # Schedules created through the API are `sch_01m26xfcn3endt3nxy4e2kx2rh` and need
12
+ # no encoding. Schedules created in the Preferences Editor before that format are
13
+ # `sch/{uuid}` and contain a literal `/`, so they must be URL-encoded as
14
+ # `sch%2F{uuid}` — unencoded, the path does not match the route and the response
15
+ # is a bare `404` that reads like a broken endpoint. Existing ids are never
16
+ # migrated.
17
+ #
10
18
  # @return [String]
11
19
  required :schedule_id, String
12
20
 
@@ -44,8 +44,13 @@ module Courier
44
44
  # @!attribute digest_schedule_id
45
45
  # The digest schedule this recipient is on for the topic. Omitted rather than null
46
46
  # when they have not chosen one, in which case the topic's default schedule
47
- # applies. Ids come from the topic's digest configuration or from
48
- # `GET /digests/schedules`.
47
+ # applies. Ids come from the topic's digest configuration, returned on any read of
48
+ # the topic.
49
+ #
50
+ # Also omitted when the schedule they chose has since been deleted or disabled:
51
+ # the recipient is on the topic's default from that point on, which is how a send
52
+ # already resolves it, so the field reports what would actually be used rather
53
+ # than a dead id.
49
54
  #
50
55
  # @return [String, nil]
51
56
  optional :digest_schedule_id, String
@@ -33,16 +33,21 @@ module Courier
33
33
  optional :description, String, nil?: true
34
34
 
35
35
  # @!attribute digest
36
- # A topic's digest configuration: the template that renders it, the cadences it
37
- # delivers on, and how collected events are retained.
36
+ # A topic's digest, as supplied when the topic itself is created: the template
37
+ # that renders it, the cadences it delivers on, and how collected events are
38
+ # retained.
39
+ #
40
+ # Identical to `TopicDigestRequest`, which a replace uses, except that `schedules`
41
+ # is required — a topic being created has no stored schedules for an absent key to
42
+ # leave alone.
38
43
  #
39
44
  # Send `null` for the whole object to turn a digest off, which unlinks the
40
45
  # template and removes its schedules. There is no `enabled` flag, and
41
46
  # `schedules: []` is rejected, because both states are un-deliverable rather than
42
47
  # merely off.
43
48
  #
44
- # @return [Courier::Models::TopicDigestRequest, nil]
45
- optional :digest, -> { Courier::TopicDigestRequest }, nil?: true
49
+ # @return [Courier::Models::WorkspacePreferenceTopicCreateRequest::Digest, nil]
50
+ optional :digest, -> { Courier::WorkspacePreferenceTopicCreateRequest::Digest }, nil?: true
46
51
 
47
52
  # @!attribute include_unsubscribe_header
48
53
  # Whether to include a list-unsubscribe header on emails for this topic.
@@ -78,7 +83,7 @@ module Courier
78
83
  #
79
84
  # @param description [String, nil] Optional description shown under the topic on the hosted preferences page.
80
85
  #
81
- # @param digest [Courier::Models::TopicDigestRequest, nil] A topic's digest configuration: the template that renders it, the cadences it de
86
+ # @param digest [Courier::Models::WorkspacePreferenceTopicCreateRequest::Digest, nil] A topic's digest, as supplied when the topic itself is created: the template tha
82
87
  #
83
88
  # @param include_unsubscribe_header [Boolean, nil] Whether to include a list-unsubscribe header on emails for this topic.
84
89
  #
@@ -110,6 +115,83 @@ module Courier
110
115
  # @!method self.values
111
116
  # @return [Array<Symbol>]
112
117
  end
118
+
119
+ # @see Courier::Models::WorkspacePreferenceTopicCreateRequest#digest
120
+ class Digest < Courier::Internal::Type::BaseModel
121
+ # @!attribute schedules
122
+ # The cadences this digest delivers on.
123
+ #
124
+ # The array replaces the stored schedules wholesale, so a schedule you leave out
125
+ # of it is deleted along with its delivery rule. Omit the key entirely to leave
126
+ # the stored schedules untouched — useful for changing `template_id` or
127
+ # `categories` without restating every schedule.
128
+ #
129
+ # A digest must end up with at least one schedule, because one with none collects
130
+ # events into an instance that can never fire. So sending `[]` is always a `400`,
131
+ # and so is omitting the key on a topic that has no schedules stored yet.
132
+ #
133
+ # On **create** the key is required outright: a topic being created has nothing
134
+ # stored to leave alone, and the topic row is written before its digest, so
135
+ # rejecting it any later would leave the topic behind and let a retry duplicate
136
+ # it.
137
+ #
138
+ # @return [Array<Courier::Models::TopicDigestScheduleRequest>]
139
+ required :schedules, -> { Courier::Internal::Type::ArrayOf[Courier::TopicDigestScheduleRequest] }
140
+
141
+ # @!attribute template_id
142
+ # The notification template that renders the digest. A digest with no template
143
+ # collects nothing, so this is required.
144
+ #
145
+ # @return [String]
146
+ required :template_id, String
147
+
148
+ # @!attribute audience_id
149
+ # Optional audience the digest is scoped to.
150
+ #
151
+ # @return [String, nil]
152
+ optional :audience_id, String
153
+
154
+ # @!attribute categories
155
+ # Retention rules per category key. Defaults to a single `digest` category
156
+ # retaining `FIRST`.
157
+ #
158
+ # @return [Array<Courier::Models::TopicDigestCategory>, nil]
159
+ optional :categories, -> { Courier::Internal::Type::ArrayOf[Courier::TopicDigestCategory] }
160
+
161
+ # @!attribute trigger_empty
162
+ # Whether to deliver the digest even when nothing was collected.
163
+ #
164
+ # @return [Boolean, nil]
165
+ optional :trigger_empty, Courier::Internal::Type::Boolean
166
+
167
+ # @!method initialize(schedules:, template_id:, audience_id: nil, categories: nil, trigger_empty: nil)
168
+ # Some parameter documentations has been truncated, see
169
+ # {Courier::Models::WorkspacePreferenceTopicCreateRequest::Digest} for more
170
+ # details.
171
+ #
172
+ # A topic's digest, as supplied when the topic itself is created: the template
173
+ # that renders it, the cadences it delivers on, and how collected events are
174
+ # retained.
175
+ #
176
+ # Identical to `TopicDigestRequest`, which a replace uses, except that `schedules`
177
+ # is required — a topic being created has no stored schedules for an absent key to
178
+ # leave alone.
179
+ #
180
+ # Send `null` for the whole object to turn a digest off, which unlinks the
181
+ # template and removes its schedules. There is no `enabled` flag, and
182
+ # `schedules: []` is rejected, because both states are un-deliverable rather than
183
+ # merely off.
184
+ #
185
+ # @param schedules [Array<Courier::Models::TopicDigestScheduleRequest>] The cadences this digest delivers on.
186
+ #
187
+ # @param template_id [String] The notification template that renders the digest. A digest with no template col
188
+ #
189
+ # @param audience_id [String] Optional audience the digest is scoped to.
190
+ #
191
+ # @param categories [Array<Courier::Models::TopicDigestCategory>] Retention rules per category key. Defaults to a single `digest` category retaini
192
+ #
193
+ # @param trigger_empty [Boolean] Whether to deliver the digest even when nothing was collected.
194
+ end
113
195
  end
114
196
  end
115
197
  end
@@ -21,12 +21,14 @@ module Courier
21
21
  # Creates a journey from a set of nodes, in draft state unless you pass a
22
22
  # published state. Send nodes cannot be included until their templates exist.
23
23
  #
24
- # @overload create(name:, nodes:, enabled: nil, state: nil, idempotency_key: nil, x_idempotency_expiration: nil, request_options: {})
24
+ # @overload create(name:, nodes:, cancelation_token: nil, enabled: nil, state: nil, idempotency_key: nil, x_idempotency_expiration: nil, request_options: {})
25
25
  #
26
26
  # @param name [String] Body param
27
27
  #
28
28
  # @param nodes [Array<Courier::Models::JourneyAPIInvokeTriggerNode, Courier::Models::JourneySegmentTriggerNode, Courier::Models::JourneyAudienceTriggerNode, Courier::Models::JourneyWebhookTriggerNode, Courier::Models::JourneySendNode, Courier::Models::JourneyDelayDurationNode, Courier::Models::JourneyDelayUntilNode, Courier::Models::JourneyFetchGetDeleteNode, Courier::Models::JourneyFetchPostPutNode, Courier::Models::JourneyAINode, Courier::Models::JourneyThrottleStaticNode, Courier::Models::JourneyThrottleDynamicNode, Courier::Models::JourneyNode::JourneyBatchNode, Courier::Models::JourneyNode::JourneyAddToDigestNode, Courier::Models::JourneyExitNode, Courier::Models::JourneyNode::JourneyBranchNode>] Body param
29
29
  #
30
+ # @param cancelation_token [String] Body param: Cancelation token stored on the journey definition. It tags every ru
31
+ #
30
32
  # @param enabled [Boolean] Body param
31
33
  #
32
34
  # @param state [Symbol, Courier::Models::JourneyState] Body param: Lifecycle state of a journey.
@@ -259,10 +261,13 @@ module Courier
259
261
  )
260
262
  end
261
263
 
264
+ # Some parameter documentations has been truncated, see
265
+ # {Courier::Models::JourneyReplaceParams} for more details.
266
+ #
262
267
  # Replaces a journey's working draft, leaving the published version live until you
263
268
  # publish. Reach for this when editing a journey already running.
264
269
  #
265
- # @overload replace(template_id, name:, nodes:, enabled: nil, state: nil, request_options: {})
270
+ # @overload replace(template_id, name:, nodes:, cancelation_token: nil, enabled: nil, state: nil, request_options: {})
266
271
  #
267
272
  # @param template_id [String] Journey id
268
273
  #
@@ -270,6 +275,8 @@ module Courier
270
275
  #
271
276
  # @param nodes [Array<Courier::Models::JourneyAPIInvokeTriggerNode, Courier::Models::JourneySegmentTriggerNode, Courier::Models::JourneyAudienceTriggerNode, Courier::Models::JourneyWebhookTriggerNode, Courier::Models::JourneySendNode, Courier::Models::JourneyDelayDurationNode, Courier::Models::JourneyDelayUntilNode, Courier::Models::JourneyFetchGetDeleteNode, Courier::Models::JourneyFetchPostPutNode, Courier::Models::JourneyAINode, Courier::Models::JourneyThrottleStaticNode, Courier::Models::JourneyThrottleDynamicNode, Courier::Models::JourneyNode::JourneyBatchNode, Courier::Models::JourneyNode::JourneyAddToDigestNode, Courier::Models::JourneyExitNode, Courier::Models::JourneyNode::JourneyBranchNode>]
272
277
  #
278
+ # @param cancelation_token [String] Cancelation token stored on the journey definition. It tags every run the journe
279
+ #
273
280
  # @param enabled [Boolean]
274
281
  #
275
282
  # @param state [Symbol, Courier::Models::JourneyState] Lifecycle state of a journey.
@@ -22,7 +22,7 @@ module Courier
22
22
  #
23
23
  # @param description [String, nil] Body param: Optional description shown under the topic on the hosted preferences
24
24
  #
25
- # @param digest [Courier::Models::TopicDigestRequest, nil] Body param: A topic's digest configuration: the template that renders it, the ca
25
+ # @param digest [Courier::Models::WorkspacePreferenceTopicCreateRequest::Digest, nil] Body param: A topic's digest, as supplied when the topic itself is created: the
26
26
  #
27
27
  # @param include_unsubscribe_header [Boolean, nil] Body param: Whether to include a list-unsubscribe header on emails for this topi
28
28
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Courier
4
- VERSION = "6.6.0"
4
+ VERSION = "6.7.0"
5
5
  end
@@ -37,6 +37,17 @@ module Courier
37
37
  end
38
38
  attr_accessor :nodes
39
39
 
40
+ # Cancelation token stored on the journey definition. It tags every run the
41
+ # journey creates so that `POST /journeys/cancel` can later cancel those runs by
42
+ # token. Accepts a templated string such as `order-{{data.order_id}}`, which is
43
+ # resolved per run when the journey is invoked. On a replace, omitting this field
44
+ # preserves any existing token and sending a value replaces it.
45
+ sig { returns(T.nilable(String)) }
46
+ attr_reader :cancelation_token
47
+
48
+ sig { params(cancelation_token: String).void }
49
+ attr_writer :cancelation_token
50
+
40
51
  sig { returns(T.nilable(T::Boolean)) }
41
52
  attr_reader :enabled
42
53
 
@@ -75,6 +86,7 @@ module Courier
75
86
  Courier::JourneyNode::JourneyBranchNode::OrHash
76
87
  )
77
88
  ],
89
+ cancelation_token: String,
78
90
  enabled: T::Boolean,
79
91
  state: Courier::JourneyState::OrSymbol
80
92
  ).returns(T.attached_class)
@@ -82,6 +94,12 @@ module Courier
82
94
  def self.new(
83
95
  name:,
84
96
  nodes:,
97
+ # Cancelation token stored on the journey definition. It tags every run the
98
+ # journey creates so that `POST /journeys/cancel` can later cancel those runs by
99
+ # token. Accepts a templated string such as `order-{{data.order_id}}`, which is
100
+ # resolved per run when the journey is invoked. On a replace, omitting this field
101
+ # preserves any existing token and sending a value replaces it.
102
+ cancelation_token: nil,
85
103
  enabled: nil,
86
104
  # Lifecycle state of a journey.
87
105
  state: nil
@@ -113,6 +131,7 @@ module Courier
113
131
  Courier::JourneyNode::JourneyBranchNode
114
132
  )
115
133
  ],
134
+ cancelation_token: String,
116
135
  enabled: T::Boolean,
117
136
  state: Courier::JourneyState::OrSymbol
118
137
  }
@@ -11,6 +11,12 @@ module Courier
11
11
  sig { returns(String) }
12
12
  attr_accessor :id
13
13
 
14
+ # The journey cancelation token, or null when none is set. A token authored in the
15
+ # dashboard is returned in its raw templated form, such as
16
+ # `order-{{data.order_id}}`, so it can be read back and asserted.
17
+ sig { returns(T.nilable(String)) }
18
+ attr_accessor :cancelation_token
19
+
14
20
  sig { returns(T.nilable(Integer)) }
15
21
  attr_accessor :created
16
22
 
@@ -43,6 +49,7 @@ module Courier
43
49
  sig do
44
50
  params(
45
51
  id: String,
52
+ cancelation_token: T.nilable(String),
46
53
  created: T.nilable(Integer),
47
54
  creator: T.nilable(String),
48
55
  enabled: T::Boolean,
@@ -76,6 +83,10 @@ module Courier
76
83
  end
77
84
  def self.new(
78
85
  id:,
86
+ # The journey cancelation token, or null when none is set. A token authored in the
87
+ # dashboard is returned in its raw templated form, such as
88
+ # `order-{{data.order_id}}`, so it can be read back and asserted.
89
+ cancelation_token:,
79
90
  created:,
80
91
  creator:,
81
92
  enabled:,
@@ -93,6 +104,7 @@ module Courier
93
104
  override.returns(
94
105
  {
95
106
  id: String,
107
+ cancelation_token: T.nilable(String),
96
108
  created: T.nilable(Integer),
97
109
  creator: T.nilable(String),
98
110
  enabled: T::Boolean,
@@ -8,12 +8,6 @@ module Courier
8
8
  T.any(Courier::TopicDigestRequest, Courier::Internal::AnyHash)
9
9
  end
10
10
 
11
- # The cadences this digest delivers on. At least one is required: a digest with no
12
- # schedule collects events into an instance that can never fire. Omitting the key
13
- # on a replace leaves stored schedules untouched; sending `[]` is a `400`.
14
- sig { returns(T::Array[Courier::TopicDigestScheduleRequest]) }
15
- attr_accessor :schedules
16
-
17
11
  # The notification template that renders the digest. A digest with no template
18
12
  # collects nothing, so this is required.
19
13
  sig { returns(String) }
@@ -36,6 +30,31 @@ module Courier
36
30
  end
37
31
  attr_writer :categories
38
32
 
33
+ # The cadences this digest delivers on.
34
+ #
35
+ # The array replaces the stored schedules wholesale, so a schedule you leave out
36
+ # of it is deleted along with its delivery rule. Omit the key entirely to leave
37
+ # the stored schedules untouched — useful for changing `template_id` or
38
+ # `categories` without restating every schedule.
39
+ #
40
+ # A digest must end up with at least one schedule, because one with none collects
41
+ # events into an instance that can never fire. So sending `[]` is always a `400`,
42
+ # and so is omitting the key on a topic that has no schedules stored yet.
43
+ #
44
+ # On **create** the key is required outright: a topic being created has nothing
45
+ # stored to leave alone, and the topic row is written before its digest, so
46
+ # rejecting it any later would leave the topic behind and let a retry duplicate
47
+ # it.
48
+ sig { returns(T.nilable(T::Array[Courier::TopicDigestScheduleRequest])) }
49
+ attr_reader :schedules
50
+
51
+ sig do
52
+ params(
53
+ schedules: T::Array[Courier::TopicDigestScheduleRequest::OrHash]
54
+ ).void
55
+ end
56
+ attr_writer :schedules
57
+
39
58
  # Whether to deliver the digest even when nothing was collected.
40
59
  sig { returns(T.nilable(T::Boolean)) }
41
60
  attr_reader :trigger_empty
@@ -52,18 +71,14 @@ module Courier
52
71
  # merely off.
53
72
  sig do
54
73
  params(
55
- schedules: T::Array[Courier::TopicDigestScheduleRequest::OrHash],
56
74
  template_id: String,
57
75
  audience_id: String,
58
76
  categories: T::Array[Courier::TopicDigestCategory::OrHash],
77
+ schedules: T::Array[Courier::TopicDigestScheduleRequest::OrHash],
59
78
  trigger_empty: T::Boolean
60
79
  ).returns(T.attached_class)
61
80
  end
62
81
  def self.new(
63
- # The cadences this digest delivers on. At least one is required: a digest with no
64
- # schedule collects events into an instance that can never fire. Omitting the key
65
- # on a replace leaves stored schedules untouched; sending `[]` is a `400`.
66
- schedules:,
67
82
  # The notification template that renders the digest. A digest with no template
68
83
  # collects nothing, so this is required.
69
84
  template_id:,
@@ -72,6 +87,22 @@ module Courier
72
87
  # Retention rules per category key. Defaults to a single `digest` category
73
88
  # retaining `FIRST`.
74
89
  categories: nil,
90
+ # The cadences this digest delivers on.
91
+ #
92
+ # The array replaces the stored schedules wholesale, so a schedule you leave out
93
+ # of it is deleted along with its delivery rule. Omit the key entirely to leave
94
+ # the stored schedules untouched — useful for changing `template_id` or
95
+ # `categories` without restating every schedule.
96
+ #
97
+ # A digest must end up with at least one schedule, because one with none collects
98
+ # events into an instance that can never fire. So sending `[]` is always a `400`,
99
+ # and so is omitting the key on a topic that has no schedules stored yet.
100
+ #
101
+ # On **create** the key is required outright: a topic being created has nothing
102
+ # stored to leave alone, and the topic row is written before its digest, so
103
+ # rejecting it any later would leave the topic behind and let a retry duplicate
104
+ # it.
105
+ schedules: nil,
75
106
  # Whether to deliver the digest even when nothing was collected.
76
107
  trigger_empty: nil
77
108
  )
@@ -80,10 +111,10 @@ module Courier
80
111
  sig do
81
112
  override.returns(
82
113
  {
83
- schedules: T::Array[Courier::TopicDigestScheduleRequest],
84
114
  template_id: String,
85
115
  audience_id: String,
86
116
  categories: T::Array[Courier::TopicDigestCategory],
117
+ schedules: T::Array[Courier::TopicDigestScheduleRequest],
87
118
  trigger_empty: T::Boolean
88
119
  }
89
120
  )
@@ -79,6 +79,12 @@ module Courier
79
79
  # existing schedule in place; omit it and one is assigned and returned. The
80
80
  # `schedules` array is a full replacement, so a stored schedule absent from it is
81
81
  # deleted along with its delivery rule.
82
+ #
83
+ # Updating by `schedule_id` replaces that schedule rather than merging into it:
84
+ # any field you leave out is cleared. Two of those change delivery silently — an
85
+ # omitted `timezone` reverts the schedule to UTC, and an omitted `is_default` can
86
+ # leave the topic with no default schedule, which is what recipients who have not
87
+ # chosen one fall back to. Restate every field you want to keep.
82
88
  sig do
83
89
  params(
84
90
  frequency: Courier::DigestFrequency::OrSymbol,
@@ -13,6 +13,14 @@ module Courier
13
13
 
14
14
  # The schedule's identifier, assigned by the server. This is the value the
15
15
  # `/digests/schedules/{schedule_id}` endpoints are keyed by.
16
+ #
17
+ # Two formats are in circulation and only one is safe to drop into a URL.
18
+ # Schedules created through the API are `sch_01m26xfcn3endt3nxy4e2kx2rh` and need
19
+ # no encoding. Schedules created in the Preferences Editor before that format are
20
+ # `sch/{uuid}` and contain a literal `/`, so they must be URL-encoded as
21
+ # `sch%2F{uuid}` — unencoded, the path does not match the route and the response
22
+ # is a bare `404` that reads like a broken endpoint. Existing ids are never
23
+ # migrated.
16
24
  sig { returns(String) }
17
25
  attr_accessor :schedule_id
18
26
 
@@ -110,6 +118,14 @@ module Courier
110
118
  def self.new(
111
119
  # The schedule's identifier, assigned by the server. This is the value the
112
120
  # `/digests/schedules/{schedule_id}` endpoints are keyed by.
121
+ #
122
+ # Two formats are in circulation and only one is safe to drop into a URL.
123
+ # Schedules created through the API are `sch_01m26xfcn3endt3nxy4e2kx2rh` and need
124
+ # no encoding. Schedules created in the Preferences Editor before that format are
125
+ # `sch/{uuid}` and contain a literal `/`, so they must be URL-encoded as
126
+ # `sch%2F{uuid}` — unencoded, the path does not match the route and the response
127
+ # is a bare `404` that reads like a broken endpoint. Existing ids are never
128
+ # migrated.
113
129
  schedule_id:,
114
130
  # ISO-8601 timestamp of when the schedule was created.
115
131
  created: nil,
@@ -40,8 +40,13 @@ module Courier
40
40
 
41
41
  # The digest schedule this recipient is on for the topic. Omitted rather than null
42
42
  # when they have not chosen one, in which case the topic's default schedule
43
- # applies. Ids come from the topic's digest configuration or from
44
- # `GET /digests/schedules`.
43
+ # applies. Ids come from the topic's digest configuration, returned on any read of
44
+ # the topic.
45
+ #
46
+ # Also omitted when the schedule they chose has since been deleted or disabled:
47
+ # the recipient is on the topic's default from that point on, which is how a send
48
+ # already resolves it, so the field reports what would actually be used rather
49
+ # than a dead id.
45
50
  sig { returns(T.nilable(String)) }
46
51
  attr_reader :digest_schedule_id
47
52
 
@@ -103,8 +108,13 @@ module Courier
103
108
  custom_routing: nil,
104
109
  # The digest schedule this recipient is on for the topic. Omitted rather than null
105
110
  # when they have not chosen one, in which case the topic's default schedule
106
- # applies. Ids come from the topic's digest configuration or from
107
- # `GET /digests/schedules`.
111
+ # applies. Ids come from the topic's digest configuration, returned on any read of
112
+ # the topic.
113
+ #
114
+ # Also omitted when the schedule they chose has since been deleted or disabled:
115
+ # the recipient is on the topic's default from that point on, which is how a send
116
+ # already resolves it, so the field reports what would actually be used rather
117
+ # than a dead id.
108
118
  digest_schedule_id: nil,
109
119
  # Whether the user has chosen specific delivery channels for this topic (listed in
110
120
  # custom_routing) rather than the topic's default routing.
@@ -40,18 +40,32 @@ module Courier
40
40
  sig { returns(T.nilable(String)) }
41
41
  attr_accessor :description
42
42
 
43
- # A topic's digest configuration: the template that renders it, the cadences it
44
- # delivers on, and how collected events are retained.
43
+ # A topic's digest, as supplied when the topic itself is created: the template
44
+ # that renders it, the cadences it delivers on, and how collected events are
45
+ # retained.
46
+ #
47
+ # Identical to `TopicDigestRequest`, which a replace uses, except that `schedules`
48
+ # is required — a topic being created has no stored schedules for an absent key to
49
+ # leave alone.
45
50
  #
46
51
  # Send `null` for the whole object to turn a digest off, which unlinks the
47
52
  # template and removes its schedules. There is no `enabled` flag, and
48
53
  # `schedules: []` is rejected, because both states are un-deliverable rather than
49
54
  # merely off.
50
- sig { returns(T.nilable(Courier::TopicDigestRequest)) }
55
+ sig do
56
+ returns(
57
+ T.nilable(Courier::WorkspacePreferenceTopicCreateRequest::Digest)
58
+ )
59
+ end
51
60
  attr_reader :digest
52
61
 
53
62
  sig do
54
- params(digest: T.nilable(Courier::TopicDigestRequest::OrHash)).void
63
+ params(
64
+ digest:
65
+ T.nilable(
66
+ Courier::WorkspacePreferenceTopicCreateRequest::Digest::OrHash
67
+ )
68
+ ).void
55
69
  end
56
70
  attr_writer :digest
57
71
 
@@ -82,7 +96,10 @@ module Courier
82
96
  ]
83
97
  ),
84
98
  description: T.nilable(String),
85
- digest: T.nilable(Courier::TopicDigestRequest::OrHash),
99
+ digest:
100
+ T.nilable(
101
+ Courier::WorkspacePreferenceTopicCreateRequest::Digest::OrHash
102
+ ),
86
103
  include_unsubscribe_header: T.nilable(T::Boolean),
87
104
  routing_options:
88
105
  T.nilable(T::Array[Courier::ChannelClassification::OrSymbol]),
@@ -99,8 +116,13 @@ module Courier
99
116
  allowed_preferences: nil,
100
117
  # Optional description shown under the topic on the hosted preferences page.
101
118
  description: nil,
102
- # A topic's digest configuration: the template that renders it, the cadences it
103
- # delivers on, and how collected events are retained.
119
+ # A topic's digest, as supplied when the topic itself is created: the template
120
+ # that renders it, the cadences it delivers on, and how collected events are
121
+ # retained.
122
+ #
123
+ # Identical to `TopicDigestRequest`, which a replace uses, except that `schedules`
124
+ # is required — a topic being created has no stored schedules for an absent key to
125
+ # leave alone.
104
126
  #
105
127
  # Send `null` for the whole object to turn a digest off, which unlinks the
106
128
  # template and removes its schedules. There is no `enabled` flag, and
@@ -129,7 +151,8 @@ module Courier
129
151
  ]
130
152
  ),
131
153
  description: T.nilable(String),
132
- digest: T.nilable(Courier::TopicDigestRequest),
154
+ digest:
155
+ T.nilable(Courier::WorkspacePreferenceTopicCreateRequest::Digest),
133
156
  include_unsubscribe_header: T.nilable(T::Boolean),
134
157
  routing_options:
135
158
  T.nilable(T::Array[Courier::ChannelClassification::OrSymbol]),
@@ -214,6 +237,130 @@ module Courier
214
237
  def self.values
215
238
  end
216
239
  end
240
+
241
+ class Digest < Courier::Internal::Type::BaseModel
242
+ OrHash =
243
+ T.type_alias do
244
+ T.any(
245
+ Courier::WorkspacePreferenceTopicCreateRequest::Digest,
246
+ Courier::Internal::AnyHash
247
+ )
248
+ end
249
+
250
+ # The cadences this digest delivers on.
251
+ #
252
+ # The array replaces the stored schedules wholesale, so a schedule you leave out
253
+ # of it is deleted along with its delivery rule. Omit the key entirely to leave
254
+ # the stored schedules untouched — useful for changing `template_id` or
255
+ # `categories` without restating every schedule.
256
+ #
257
+ # A digest must end up with at least one schedule, because one with none collects
258
+ # events into an instance that can never fire. So sending `[]` is always a `400`,
259
+ # and so is omitting the key on a topic that has no schedules stored yet.
260
+ #
261
+ # On **create** the key is required outright: a topic being created has nothing
262
+ # stored to leave alone, and the topic row is written before its digest, so
263
+ # rejecting it any later would leave the topic behind and let a retry duplicate
264
+ # it.
265
+ sig { returns(T::Array[Courier::TopicDigestScheduleRequest]) }
266
+ attr_accessor :schedules
267
+
268
+ # The notification template that renders the digest. A digest with no template
269
+ # collects nothing, so this is required.
270
+ sig { returns(String) }
271
+ attr_accessor :template_id
272
+
273
+ # Optional audience the digest is scoped to.
274
+ sig { returns(T.nilable(String)) }
275
+ attr_reader :audience_id
276
+
277
+ sig { params(audience_id: String).void }
278
+ attr_writer :audience_id
279
+
280
+ # Retention rules per category key. Defaults to a single `digest` category
281
+ # retaining `FIRST`.
282
+ sig { returns(T.nilable(T::Array[Courier::TopicDigestCategory])) }
283
+ attr_reader :categories
284
+
285
+ sig do
286
+ params(
287
+ categories: T::Array[Courier::TopicDigestCategory::OrHash]
288
+ ).void
289
+ end
290
+ attr_writer :categories
291
+
292
+ # Whether to deliver the digest even when nothing was collected.
293
+ sig { returns(T.nilable(T::Boolean)) }
294
+ attr_reader :trigger_empty
295
+
296
+ sig { params(trigger_empty: T::Boolean).void }
297
+ attr_writer :trigger_empty
298
+
299
+ # A topic's digest, as supplied when the topic itself is created: the template
300
+ # that renders it, the cadences it delivers on, and how collected events are
301
+ # retained.
302
+ #
303
+ # Identical to `TopicDigestRequest`, which a replace uses, except that `schedules`
304
+ # is required — a topic being created has no stored schedules for an absent key to
305
+ # leave alone.
306
+ #
307
+ # Send `null` for the whole object to turn a digest off, which unlinks the
308
+ # template and removes its schedules. There is no `enabled` flag, and
309
+ # `schedules: []` is rejected, because both states are un-deliverable rather than
310
+ # merely off.
311
+ sig do
312
+ params(
313
+ schedules: T::Array[Courier::TopicDigestScheduleRequest::OrHash],
314
+ template_id: String,
315
+ audience_id: String,
316
+ categories: T::Array[Courier::TopicDigestCategory::OrHash],
317
+ trigger_empty: T::Boolean
318
+ ).returns(T.attached_class)
319
+ end
320
+ def self.new(
321
+ # The cadences this digest delivers on.
322
+ #
323
+ # The array replaces the stored schedules wholesale, so a schedule you leave out
324
+ # of it is deleted along with its delivery rule. Omit the key entirely to leave
325
+ # the stored schedules untouched — useful for changing `template_id` or
326
+ # `categories` without restating every schedule.
327
+ #
328
+ # A digest must end up with at least one schedule, because one with none collects
329
+ # events into an instance that can never fire. So sending `[]` is always a `400`,
330
+ # and so is omitting the key on a topic that has no schedules stored yet.
331
+ #
332
+ # On **create** the key is required outright: a topic being created has nothing
333
+ # stored to leave alone, and the topic row is written before its digest, so
334
+ # rejecting it any later would leave the topic behind and let a retry duplicate
335
+ # it.
336
+ schedules:,
337
+ # The notification template that renders the digest. A digest with no template
338
+ # collects nothing, so this is required.
339
+ template_id:,
340
+ # Optional audience the digest is scoped to.
341
+ audience_id: nil,
342
+ # Retention rules per category key. Defaults to a single `digest` category
343
+ # retaining `FIRST`.
344
+ categories: nil,
345
+ # Whether to deliver the digest even when nothing was collected.
346
+ trigger_empty: nil
347
+ )
348
+ end
349
+
350
+ sig do
351
+ override.returns(
352
+ {
353
+ schedules: T::Array[Courier::TopicDigestScheduleRequest],
354
+ template_id: String,
355
+ audience_id: String,
356
+ categories: T::Array[Courier::TopicDigestCategory],
357
+ trigger_empty: T::Boolean
358
+ }
359
+ )
360
+ end
361
+ def to_hash
362
+ end
363
+ end
217
364
  end
218
365
  end
219
366
  end
@@ -41,6 +41,7 @@ module Courier
41
41
  Courier::JourneyNode::JourneyBranchNode::OrHash
42
42
  )
43
43
  ],
44
+ cancelation_token: String,
44
45
  enabled: T::Boolean,
45
46
  state: Courier::JourneyState::OrSymbol,
46
47
  idempotency_key: String,
@@ -53,6 +54,12 @@ module Courier
53
54
  name:,
54
55
  # Body param
55
56
  nodes:,
57
+ # Body param: Cancelation token stored on the journey definition. It tags every
58
+ # run the journey creates so that `POST /journeys/cancel` can later cancel those
59
+ # runs by token. Accepts a templated string such as `order-{{data.order_id}}`,
60
+ # which is resolved per run when the journey is invoked. On a replace, omitting
61
+ # this field preserves any existing token and sending a value replaces it.
62
+ cancelation_token: nil,
56
63
  # Body param
57
64
  enabled: nil,
58
65
  # Body param: Lifecycle state of a journey.
@@ -283,6 +290,7 @@ module Courier
283
290
  Courier::JourneyNode::JourneyBranchNode::OrHash
284
291
  )
285
292
  ],
293
+ cancelation_token: String,
286
294
  enabled: T::Boolean,
287
295
  state: Courier::JourneyState::OrSymbol,
288
296
  request_options: Courier::RequestOptions::OrHash
@@ -293,6 +301,12 @@ module Courier
293
301
  template_id,
294
302
  name:,
295
303
  nodes:,
304
+ # Cancelation token stored on the journey definition. It tags every run the
305
+ # journey creates so that `POST /journeys/cancel` can later cancel those runs by
306
+ # token. Accepts a templated string such as `order-{{data.order_id}}`, which is
307
+ # resolved per run when the journey is invoked. On a replace, omitting this field
308
+ # preserves any existing token and sending a value replaces it.
309
+ cancelation_token: nil,
296
310
  enabled: nil,
297
311
  # Lifecycle state of a journey.
298
312
  state: nil,
@@ -19,7 +19,10 @@ module Courier
19
19
  ]
20
20
  ),
21
21
  description: T.nilable(String),
22
- digest: T.nilable(Courier::TopicDigestRequest::OrHash),
22
+ digest:
23
+ T.nilable(
24
+ Courier::WorkspacePreferenceTopicCreateRequest::Digest::OrHash
25
+ ),
23
26
  include_unsubscribe_header: T.nilable(T::Boolean),
24
27
  routing_options:
25
28
  T.nilable(T::Array[Courier::ChannelClassification::OrSymbol]),
@@ -43,8 +46,13 @@ module Courier
43
46
  # Body param: Optional description shown under the topic on the hosted preferences
44
47
  # page.
45
48
  description: nil,
46
- # Body param: A topic's digest configuration: the template that renders it, the
47
- # cadences it delivers on, and how collected events are retained.
49
+ # Body param: A topic's digest, as supplied when the topic itself is created: the
50
+ # template that renders it, the cadences it delivers on, and how collected events
51
+ # are retained.
52
+ #
53
+ # Identical to `TopicDigestRequest`, which a replace uses, except that `schedules`
54
+ # is required — a topic being created has no stored schedules for an absent key to
55
+ # leave alone.
48
56
  #
49
57
  # Send `null` for the whole object to turn a digest off, which unlinks the
50
58
  # template and removes its schedules. There is no `enabled` flag, and
@@ -4,6 +4,7 @@ module Courier
4
4
  {
5
5
  name: String,
6
6
  nodes: ::Array[Courier::Models::journey_node],
7
+ cancelation_token: String,
7
8
  enabled: bool,
8
9
  state: Courier::Models::journey_state
9
10
  }
@@ -13,6 +14,10 @@ module Courier
13
14
 
14
15
  attr_accessor nodes: ::Array[Courier::Models::journey_node]
15
16
 
17
+ attr_reader cancelation_token: String?
18
+
19
+ def cancelation_token=: (String) -> String
20
+
16
21
  attr_reader enabled: bool?
17
22
 
18
23
  def enabled=: (bool) -> bool
@@ -26,6 +31,7 @@ module Courier
26
31
  def initialize: (
27
32
  name: String,
28
33
  nodes: ::Array[Courier::Models::journey_node],
34
+ ?cancelation_token: String,
29
35
  ?enabled: bool,
30
36
  ?state: Courier::Models::journey_state
31
37
  ) -> void
@@ -33,6 +39,7 @@ module Courier
33
39
  def to_hash: -> {
34
40
  name: String,
35
41
  nodes: ::Array[Courier::Models::journey_node],
42
+ cancelation_token: String,
36
43
  enabled: bool,
37
44
  state: Courier::Models::journey_state
38
45
  }
@@ -3,6 +3,7 @@ module Courier
3
3
  type journey_response =
4
4
  {
5
5
  id: String,
6
+ cancelation_token: String?,
6
7
  created: Integer?,
7
8
  creator: String?,
8
9
  enabled: bool,
@@ -17,6 +18,8 @@ module Courier
17
18
  class JourneyResponse < Courier::Internal::Type::BaseModel
18
19
  attr_accessor id: String
19
20
 
21
+ attr_accessor cancelation_token: String?
22
+
20
23
  attr_accessor created: Integer?
21
24
 
22
25
  attr_accessor creator: String?
@@ -37,6 +40,7 @@ module Courier
37
40
 
38
41
  def initialize: (
39
42
  id: String,
43
+ cancelation_token: String?,
40
44
  created: Integer?,
41
45
  creator: String?,
42
46
  enabled: bool,
@@ -50,6 +54,7 @@ module Courier
50
54
 
51
55
  def to_hash: -> {
52
56
  id: String,
57
+ cancelation_token: String?,
53
58
  created: Integer?,
54
59
  creator: String?,
55
60
  enabled: bool,
@@ -2,16 +2,14 @@ module Courier
2
2
  module Models
3
3
  type topic_digest_request =
4
4
  {
5
- schedules: ::Array[Courier::TopicDigestScheduleRequest],
6
5
  template_id: String,
7
6
  audience_id: String,
8
7
  categories: ::Array[Courier::TopicDigestCategory],
8
+ schedules: ::Array[Courier::TopicDigestScheduleRequest],
9
9
  trigger_empty: bool
10
10
  }
11
11
 
12
12
  class TopicDigestRequest < Courier::Internal::Type::BaseModel
13
- attr_accessor schedules: ::Array[Courier::TopicDigestScheduleRequest]
14
-
15
13
  attr_accessor template_id: String
16
14
 
17
15
  attr_reader audience_id: String?
@@ -24,23 +22,29 @@ module Courier
24
22
  ::Array[Courier::TopicDigestCategory]
25
23
  ) -> ::Array[Courier::TopicDigestCategory]
26
24
 
25
+ attr_reader schedules: ::Array[Courier::TopicDigestScheduleRequest]?
26
+
27
+ def schedules=: (
28
+ ::Array[Courier::TopicDigestScheduleRequest]
29
+ ) -> ::Array[Courier::TopicDigestScheduleRequest]
30
+
27
31
  attr_reader trigger_empty: bool?
28
32
 
29
33
  def trigger_empty=: (bool) -> bool
30
34
 
31
35
  def initialize: (
32
- schedules: ::Array[Courier::TopicDigestScheduleRequest],
33
36
  template_id: String,
34
37
  ?audience_id: String,
35
38
  ?categories: ::Array[Courier::TopicDigestCategory],
39
+ ?schedules: ::Array[Courier::TopicDigestScheduleRequest],
36
40
  ?trigger_empty: bool
37
41
  ) -> void
38
42
 
39
43
  def to_hash: -> {
40
- schedules: ::Array[Courier::TopicDigestScheduleRequest],
41
44
  template_id: String,
42
45
  audience_id: String,
43
46
  categories: ::Array[Courier::TopicDigestCategory],
47
+ schedules: ::Array[Courier::TopicDigestScheduleRequest],
44
48
  trigger_empty: bool
45
49
  }
46
50
  end
@@ -6,7 +6,7 @@ module Courier
6
6
  name: String,
7
7
  allowed_preferences: ::Array[Courier::Models::WorkspacePreferenceTopicCreateRequest::allowed_preference]?,
8
8
  description: String?,
9
- digest: Courier::TopicDigestRequest?,
9
+ digest: Courier::WorkspacePreferenceTopicCreateRequest::Digest?,
10
10
  include_unsubscribe_header: bool?,
11
11
  routing_options: ::Array[Courier::Models::channel_classification]?,
12
12
  topic_data: ::Hash[Symbol, top]?
@@ -21,7 +21,7 @@ module Courier
21
21
 
22
22
  attr_accessor description: String?
23
23
 
24
- attr_accessor digest: Courier::TopicDigestRequest?
24
+ attr_accessor digest: Courier::WorkspacePreferenceTopicCreateRequest::Digest?
25
25
 
26
26
  attr_accessor include_unsubscribe_header: bool?
27
27
 
@@ -34,7 +34,7 @@ module Courier
34
34
  name: String,
35
35
  ?allowed_preferences: ::Array[Courier::Models::WorkspacePreferenceTopicCreateRequest::allowed_preference]?,
36
36
  ?description: String?,
37
- ?digest: Courier::TopicDigestRequest?,
37
+ ?digest: Courier::WorkspacePreferenceTopicCreateRequest::Digest?,
38
38
  ?include_unsubscribe_header: bool?,
39
39
  ?routing_options: ::Array[Courier::Models::channel_classification]?,
40
40
  ?topic_data: ::Hash[Symbol, top]?
@@ -45,7 +45,7 @@ module Courier
45
45
  name: String,
46
46
  allowed_preferences: ::Array[Courier::Models::WorkspacePreferenceTopicCreateRequest::allowed_preference]?,
47
47
  description: String?,
48
- digest: Courier::TopicDigestRequest?,
48
+ digest: Courier::WorkspacePreferenceTopicCreateRequest::Digest?,
49
49
  include_unsubscribe_header: bool?,
50
50
  routing_options: ::Array[Courier::Models::channel_classification]?,
51
51
  topic_data: ::Hash[Symbol, top]?
@@ -73,6 +73,51 @@ module Courier
73
73
 
74
74
  def self?.values: -> ::Array[Courier::Models::WorkspacePreferenceTopicCreateRequest::allowed_preference]
75
75
  end
76
+
77
+ type digest =
78
+ {
79
+ schedules: ::Array[Courier::TopicDigestScheduleRequest],
80
+ template_id: String,
81
+ audience_id: String,
82
+ categories: ::Array[Courier::TopicDigestCategory],
83
+ trigger_empty: bool
84
+ }
85
+
86
+ class Digest < Courier::Internal::Type::BaseModel
87
+ attr_accessor schedules: ::Array[Courier::TopicDigestScheduleRequest]
88
+
89
+ attr_accessor template_id: String
90
+
91
+ attr_reader audience_id: String?
92
+
93
+ def audience_id=: (String) -> String
94
+
95
+ attr_reader categories: ::Array[Courier::TopicDigestCategory]?
96
+
97
+ def categories=: (
98
+ ::Array[Courier::TopicDigestCategory]
99
+ ) -> ::Array[Courier::TopicDigestCategory]
100
+
101
+ attr_reader trigger_empty: bool?
102
+
103
+ def trigger_empty=: (bool) -> bool
104
+
105
+ def initialize: (
106
+ schedules: ::Array[Courier::TopicDigestScheduleRequest],
107
+ template_id: String,
108
+ ?audience_id: String,
109
+ ?categories: ::Array[Courier::TopicDigestCategory],
110
+ ?trigger_empty: bool
111
+ ) -> void
112
+
113
+ def to_hash: -> {
114
+ schedules: ::Array[Courier::TopicDigestScheduleRequest],
115
+ template_id: String,
116
+ audience_id: String,
117
+ categories: ::Array[Courier::TopicDigestCategory],
118
+ trigger_empty: bool
119
+ }
120
+ end
76
121
  end
77
122
  end
78
123
  end
@@ -8,6 +8,7 @@ module Courier
8
8
  def create: (
9
9
  name: String,
10
10
  nodes: ::Array[Courier::Models::journey_node],
11
+ ?cancelation_token: String,
11
12
  ?enabled: bool,
12
13
  ?state: Courier::Models::journey_state,
13
14
  ?idempotency_key: String,
@@ -66,6 +67,7 @@ module Courier
66
67
  String template_id,
67
68
  name: String,
68
69
  nodes: ::Array[Courier::Models::journey_node],
70
+ ?cancelation_token: String,
69
71
  ?enabled: bool,
70
72
  ?state: Courier::Models::journey_state,
71
73
  ?request_options: Courier::request_opts
@@ -8,7 +8,7 @@ module Courier
8
8
  name: String,
9
9
  ?allowed_preferences: ::Array[Courier::Models::WorkspacePreferenceTopicCreateRequest::allowed_preference]?,
10
10
  ?description: String?,
11
- ?digest: Courier::TopicDigestRequest?,
11
+ ?digest: Courier::WorkspacePreferenceTopicCreateRequest::Digest?,
12
12
  ?include_unsubscribe_header: bool?,
13
13
  ?routing_options: ::Array[Courier::Models::channel_classification]?,
14
14
  ?topic_data: ::Hash[Symbol, top]?,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trycourier
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.6.0
4
+ version: 6.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-15 00:00:00.000000000 Z
11
+ date: 2026-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cgi