trycourier 6.4.3 → 6.5.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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +1 -1
  4. data/lib/courier/models/elemental_channel_node.rb +13 -1
  5. data/lib/courier/models/elemental_node_non_channel.rb +188 -0
  6. data/lib/courier/models/email_footer.rb +114 -7
  7. data/lib/courier/models/notification_template_update_request.rb +6 -3
  8. data/lib/courier/models/users/token_add_single_params.rb +13 -5
  9. data/lib/courier/models/users/token_update_params.rb +30 -4
  10. data/lib/courier/models/users/user_token.rb +13 -5
  11. data/lib/courier/models.rb +2 -0
  12. data/lib/courier/resources/journeys/templates.rb +7 -0
  13. data/lib/courier/resources/notifications.rb +10 -0
  14. data/lib/courier/resources/tenants/templates.rb +10 -0
  15. data/lib/courier/resources/users/tokens.rb +1 -1
  16. data/lib/courier/version.rb +1 -1
  17. data/lib/courier.rb +1 -0
  18. data/rbi/courier/models/elemental_channel_node.rbi +54 -0
  19. data/rbi/courier/models/elemental_node_non_channel.rbi +561 -0
  20. data/rbi/courier/models/email_footer.rbi +229 -7
  21. data/rbi/courier/models/notification_template_update_request.rbi +6 -3
  22. data/rbi/courier/models/users/token_add_single_params.rbi +18 -6
  23. data/rbi/courier/models/users/token_update_params.rbi +59 -7
  24. data/rbi/courier/models/users/user_token.rbi +18 -6
  25. data/rbi/courier/models.rbi +2 -0
  26. data/rbi/courier/resources/journeys/templates.rbi +7 -0
  27. data/rbi/courier/resources/notifications.rbi +10 -0
  28. data/rbi/courier/resources/tenants/templates.rbi +10 -0
  29. data/rbi/courier/resources/users/tokens.rbi +6 -2
  30. data/sig/courier/models/elemental_channel_node.rbs +9 -0
  31. data/sig/courier/models/elemental_node_non_channel.rbs +221 -0
  32. data/sig/courier/models/email_footer.rbs +107 -5
  33. data/sig/courier/models/users/token_update_params.rbs +27 -4
  34. data/sig/courier/models.rbs +2 -0
  35. metadata +5 -2
@@ -6,28 +6,250 @@ module Courier
6
6
  OrHash =
7
7
  T.type_alias { T.any(Courier::EmailFooter, Courier::Internal::AnyHash) }
8
8
 
9
- sig { returns(T.nilable(String)) }
10
- attr_accessor :content
11
-
12
9
  sig { returns(T.nilable(T::Boolean)) }
13
10
  attr_accessor :inherit_default
14
11
 
12
+ # The footer body, as markdown. This is the field the API returns and accepts; it
13
+ # is omitted entirely when no footer body is set. Sending null is accepted and
14
+ # treated as no footer body.
15
+ sig { returns(T.nilable(String)) }
16
+ attr_accessor :markdown
17
+
18
+ # Social links rendered in the email footer.
19
+ sig { returns(T.nilable(Courier::EmailFooter::Social)) }
20
+ attr_reader :social
21
+
22
+ sig do
23
+ params(social: T.nilable(Courier::EmailFooter::Social::OrHash)).void
24
+ end
25
+ attr_writer :social
26
+
15
27
  sig do
16
28
  params(
17
- content: T.nilable(String),
18
- inherit_default: T.nilable(T::Boolean)
29
+ inherit_default: T.nilable(T::Boolean),
30
+ markdown: T.nilable(String),
31
+ social: T.nilable(Courier::EmailFooter::Social::OrHash)
19
32
  ).returns(T.attached_class)
20
33
  end
21
- def self.new(content: nil, inherit_default: nil)
34
+ def self.new(
35
+ inherit_default: nil,
36
+ # The footer body, as markdown. This is the field the API returns and accepts; it
37
+ # is omitted entirely when no footer body is set. Sending null is accepted and
38
+ # treated as no footer body.
39
+ markdown: nil,
40
+ # Social links rendered in the email footer.
41
+ social: nil
42
+ )
22
43
  end
23
44
 
24
45
  sig do
25
46
  override.returns(
26
- { content: T.nilable(String), inherit_default: T.nilable(T::Boolean) }
47
+ {
48
+ inherit_default: T.nilable(T::Boolean),
49
+ markdown: T.nilable(String),
50
+ social: T.nilable(Courier::EmailFooter::Social)
51
+ }
27
52
  )
28
53
  end
29
54
  def to_hash
30
55
  end
56
+
57
+ class Social < Courier::Internal::Type::BaseModel
58
+ OrHash =
59
+ T.type_alias do
60
+ T.any(Courier::EmailFooter::Social, Courier::Internal::AnyHash)
61
+ end
62
+
63
+ sig { returns(T.nilable(Courier::EmailFooter::Social::Facebook)) }
64
+ attr_reader :facebook
65
+
66
+ sig do
67
+ params(
68
+ facebook: T.nilable(Courier::EmailFooter::Social::Facebook::OrHash)
69
+ ).void
70
+ end
71
+ attr_writer :facebook
72
+
73
+ sig { returns(T.nilable(Courier::EmailFooter::Social::Instagram)) }
74
+ attr_reader :instagram
75
+
76
+ sig do
77
+ params(
78
+ instagram:
79
+ T.nilable(Courier::EmailFooter::Social::Instagram::OrHash)
80
+ ).void
81
+ end
82
+ attr_writer :instagram
83
+
84
+ sig { returns(T.nilable(Courier::EmailFooter::Social::Linkedin)) }
85
+ attr_reader :linkedin
86
+
87
+ sig do
88
+ params(
89
+ linkedin: T.nilable(Courier::EmailFooter::Social::Linkedin::OrHash)
90
+ ).void
91
+ end
92
+ attr_writer :linkedin
93
+
94
+ sig { returns(T.nilable(Courier::EmailFooter::Social::Medium)) }
95
+ attr_reader :medium
96
+
97
+ sig do
98
+ params(
99
+ medium: T.nilable(Courier::EmailFooter::Social::Medium::OrHash)
100
+ ).void
101
+ end
102
+ attr_writer :medium
103
+
104
+ sig { returns(T.nilable(Courier::EmailFooter::Social::Twitter)) }
105
+ attr_reader :twitter
106
+
107
+ sig do
108
+ params(
109
+ twitter: T.nilable(Courier::EmailFooter::Social::Twitter::OrHash)
110
+ ).void
111
+ end
112
+ attr_writer :twitter
113
+
114
+ # Social links rendered in the email footer.
115
+ sig do
116
+ params(
117
+ facebook: T.nilable(Courier::EmailFooter::Social::Facebook::OrHash),
118
+ instagram:
119
+ T.nilable(Courier::EmailFooter::Social::Instagram::OrHash),
120
+ linkedin: T.nilable(Courier::EmailFooter::Social::Linkedin::OrHash),
121
+ medium: T.nilable(Courier::EmailFooter::Social::Medium::OrHash),
122
+ twitter: T.nilable(Courier::EmailFooter::Social::Twitter::OrHash)
123
+ ).returns(T.attached_class)
124
+ end
125
+ def self.new(
126
+ facebook: nil,
127
+ instagram: nil,
128
+ linkedin: nil,
129
+ medium: nil,
130
+ twitter: nil
131
+ )
132
+ end
133
+
134
+ sig do
135
+ override.returns(
136
+ {
137
+ facebook: T.nilable(Courier::EmailFooter::Social::Facebook),
138
+ instagram: T.nilable(Courier::EmailFooter::Social::Instagram),
139
+ linkedin: T.nilable(Courier::EmailFooter::Social::Linkedin),
140
+ medium: T.nilable(Courier::EmailFooter::Social::Medium),
141
+ twitter: T.nilable(Courier::EmailFooter::Social::Twitter)
142
+ }
143
+ )
144
+ end
145
+ def to_hash
146
+ end
147
+
148
+ class Facebook < Courier::Internal::Type::BaseModel
149
+ OrHash =
150
+ T.type_alias do
151
+ T.any(
152
+ Courier::EmailFooter::Social::Facebook,
153
+ Courier::Internal::AnyHash
154
+ )
155
+ end
156
+
157
+ sig { returns(T.nilable(String)) }
158
+ attr_accessor :url
159
+
160
+ sig { params(url: T.nilable(String)).returns(T.attached_class) }
161
+ def self.new(url: nil)
162
+ end
163
+
164
+ sig { override.returns({ url: T.nilable(String) }) }
165
+ def to_hash
166
+ end
167
+ end
168
+
169
+ class Instagram < Courier::Internal::Type::BaseModel
170
+ OrHash =
171
+ T.type_alias do
172
+ T.any(
173
+ Courier::EmailFooter::Social::Instagram,
174
+ Courier::Internal::AnyHash
175
+ )
176
+ end
177
+
178
+ sig { returns(T.nilable(String)) }
179
+ attr_accessor :url
180
+
181
+ sig { params(url: T.nilable(String)).returns(T.attached_class) }
182
+ def self.new(url: nil)
183
+ end
184
+
185
+ sig { override.returns({ url: T.nilable(String) }) }
186
+ def to_hash
187
+ end
188
+ end
189
+
190
+ class Linkedin < Courier::Internal::Type::BaseModel
191
+ OrHash =
192
+ T.type_alias do
193
+ T.any(
194
+ Courier::EmailFooter::Social::Linkedin,
195
+ Courier::Internal::AnyHash
196
+ )
197
+ end
198
+
199
+ sig { returns(T.nilable(String)) }
200
+ attr_accessor :url
201
+
202
+ sig { params(url: T.nilable(String)).returns(T.attached_class) }
203
+ def self.new(url: nil)
204
+ end
205
+
206
+ sig { override.returns({ url: T.nilable(String) }) }
207
+ def to_hash
208
+ end
209
+ end
210
+
211
+ class Medium < Courier::Internal::Type::BaseModel
212
+ OrHash =
213
+ T.type_alias do
214
+ T.any(
215
+ Courier::EmailFooter::Social::Medium,
216
+ Courier::Internal::AnyHash
217
+ )
218
+ end
219
+
220
+ sig { returns(T.nilable(String)) }
221
+ attr_accessor :url
222
+
223
+ sig { params(url: T.nilable(String)).returns(T.attached_class) }
224
+ def self.new(url: nil)
225
+ end
226
+
227
+ sig { override.returns({ url: T.nilable(String) }) }
228
+ def to_hash
229
+ end
230
+ end
231
+
232
+ class Twitter < Courier::Internal::Type::BaseModel
233
+ OrHash =
234
+ T.type_alias do
235
+ T.any(
236
+ Courier::EmailFooter::Social::Twitter,
237
+ Courier::Internal::AnyHash
238
+ )
239
+ end
240
+
241
+ sig { returns(T.nilable(String)) }
242
+ attr_accessor :url
243
+
244
+ sig { params(url: T.nilable(String)).returns(T.attached_class) }
245
+ def self.new(url: nil)
246
+ end
247
+
248
+ sig { override.returns({ url: T.nilable(String) }) }
249
+ def to_hash
250
+ end
251
+ end
252
+ end
31
253
  end
32
254
  end
33
255
  end
@@ -39,9 +39,12 @@ module Courier
39
39
  end
40
40
  attr_writer :state
41
41
 
42
- # Request body for replacing a notification template. Same shape as create. All
43
- # fields required (PUT = full replacement), except `alias`, whose omission means
44
- # "leave the existing aliases alone".
42
+ # Request body for replacing a notification template. All fields are required,
43
+ # since `PUT` is a full replacement, except `alias`, whose omission leaves the
44
+ # existing aliases in place. Unlike `NotificationTemplateCreateRequest`,
45
+ # `notification.content` is not required to place its elements inside a channel
46
+ # block: the requirement applies to creation only, so templates already stored
47
+ # without one stay editable.
45
48
  sig do
46
49
  params(
47
50
  notification: Courier::NotificationTemplateWritePayload::OrHash,
@@ -38,8 +38,12 @@ module Courier
38
38
  end
39
39
  attr_writer :device
40
40
 
41
- # ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to
42
- # disable expiration.
41
+ # When the token expires. Accepts a date, or the boolean `false` to disable
42
+ # expiration entirely. ISO 8601 is recommended (for example
43
+ # `2026-10-25T00:00:00.000Z`). A value that cannot be parsed as a date is
44
+ # rejected; it is not treated as "no expiration" and does not fall back to the
45
+ # default. `true` is not a supported value. Omit the field to use the default,
46
+ # which expires a token that has not been re-registered for 60 days.
43
47
  sig do
44
48
  returns(
45
49
  T.nilable(
@@ -94,8 +98,12 @@ module Courier
94
98
  provider_key:,
95
99
  # Information about the device the token came from.
96
100
  device: nil,
97
- # ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to
98
- # disable expiration.
101
+ # When the token expires. Accepts a date, or the boolean `false` to disable
102
+ # expiration entirely. ISO 8601 is recommended (for example
103
+ # `2026-10-25T00:00:00.000Z`). A value that cannot be parsed as a date is
104
+ # rejected; it is not treated as "no expiration" and does not fall back to the
105
+ # default. `true` is not a supported value. Omit the field to use the default,
106
+ # which expires a token that has not been re-registered for 60 days.
99
107
  expiry_date: nil,
100
108
  # Properties about the token.
101
109
  properties: nil,
@@ -244,8 +252,12 @@ module Courier
244
252
  end
245
253
  end
246
254
 
247
- # ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to
248
- # disable expiration.
255
+ # When the token expires. Accepts a date, or the boolean `false` to disable
256
+ # expiration entirely. ISO 8601 is recommended (for example
257
+ # `2026-10-25T00:00:00.000Z`). A value that cannot be parsed as a date is
258
+ # rejected; it is not treated as "no expiration" and does not fall back to the
259
+ # default. `true` is not a supported value. Omit the field to use the default,
260
+ # which expires a token that has not been re-registered for 60 days.
249
261
  module ExpiryDate
250
262
  extend Courier::Internal::Type::Union
251
263
 
@@ -62,32 +62,84 @@ module Courier
62
62
  sig { returns(String) }
63
63
  attr_accessor :path
64
64
 
65
- # The value for the operation.
66
- sig { returns(T.nilable(String)) }
65
+ # The value for the operation. A string for most fields; boolean `false` when
66
+ # disabling token expiration via `expiry_date`, which cannot be expressed as a
67
+ # string.
68
+ sig do
69
+ returns(
70
+ T.nilable(
71
+ Courier::Users::TokenUpdateParams::Patch::Value::Variants
72
+ )
73
+ )
74
+ end
67
75
  attr_accessor :value
68
76
 
69
77
  sig do
70
- params(op: String, path: String, value: T.nilable(String)).returns(
71
- T.attached_class
72
- )
78
+ params(
79
+ op: String,
80
+ path: String,
81
+ value:
82
+ T.nilable(
83
+ Courier::Users::TokenUpdateParams::Patch::Value::Variants
84
+ )
85
+ ).returns(T.attached_class)
73
86
  end
74
87
  def self.new(
75
88
  # The operation to perform.
76
89
  op:,
77
90
  # The JSON path specifying the part of the profile to operate on.
78
91
  path:,
79
- # The value for the operation.
92
+ # The value for the operation. A string for most fields; boolean `false` when
93
+ # disabling token expiration via `expiry_date`, which cannot be expressed as a
94
+ # string.
80
95
  value: nil
81
96
  )
82
97
  end
83
98
 
84
99
  sig do
85
100
  override.returns(
86
- { op: String, path: String, value: T.nilable(String) }
101
+ {
102
+ op: String,
103
+ path: String,
104
+ value:
105
+ T.nilable(
106
+ Courier::Users::TokenUpdateParams::Patch::Value::Variants
107
+ )
108
+ }
87
109
  )
88
110
  end
89
111
  def to_hash
90
112
  end
113
+
114
+ # The value for the operation. A string for most fields; boolean `false` when
115
+ # disabling token expiration via `expiry_date`, which cannot be expressed as a
116
+ # string.
117
+ module Value
118
+ extend Courier::Internal::Type::Union
119
+
120
+ Variants =
121
+ T.type_alias do
122
+ T.any(String, T::Boolean, T::Hash[Symbol, T.anything])
123
+ end
124
+
125
+ sig do
126
+ override.returns(
127
+ T::Array[
128
+ Courier::Users::TokenUpdateParams::Patch::Value::Variants
129
+ ]
130
+ )
131
+ end
132
+ def self.variants
133
+ end
134
+
135
+ UnionMember2Map =
136
+ T.let(
137
+ Courier::Internal::Type::HashOf[
138
+ Courier::Internal::Type::Unknown
139
+ ],
140
+ Courier::Internal::Type::Converter
141
+ )
142
+ end
91
143
  end
92
144
  end
93
145
  end
@@ -29,8 +29,12 @@ module Courier
29
29
  end
30
30
  attr_writer :device
31
31
 
32
- # ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to
33
- # disable expiration.
32
+ # When the token expires. Accepts a date, or the boolean `false` to disable
33
+ # expiration entirely. ISO 8601 is recommended (for example
34
+ # `2026-10-25T00:00:00.000Z`). A value that cannot be parsed as a date is
35
+ # rejected; it is not treated as "no expiration" and does not fall back to the
36
+ # default. `true` is not a supported value. Omit the field to use the default,
37
+ # which expires a token that has not been re-registered for 60 days.
34
38
  sig do
35
39
  returns(T.nilable(Courier::Users::UserToken::ExpiryDate::Variants))
36
40
  end
@@ -71,8 +75,12 @@ module Courier
71
75
  provider_key:,
72
76
  # Information about the device the token came from.
73
77
  device: nil,
74
- # ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to
75
- # disable expiration.
78
+ # When the token expires. Accepts a date, or the boolean `false` to disable
79
+ # expiration entirely. ISO 8601 is recommended (for example
80
+ # `2026-10-25T00:00:00.000Z`). A value that cannot be parsed as a date is
81
+ # rejected; it is not treated as "no expiration" and does not fall back to the
82
+ # default. `true` is not a supported value. Omit the field to use the default,
83
+ # which expires a token that has not been re-registered for 60 days.
76
84
  expiry_date: nil,
77
85
  # Properties about the token.
78
86
  properties: nil,
@@ -207,8 +215,12 @@ module Courier
207
215
  end
208
216
  end
209
217
 
210
- # ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to
211
- # disable expiration.
218
+ # When the token expires. Accepts a date, or the boolean `false` to disable
219
+ # expiration entirely. ISO 8601 is recommended (for example
220
+ # `2026-10-25T00:00:00.000Z`). A value that cannot be parsed as a date is
221
+ # rejected; it is not treated as "no expiration" and does not fall back to the
222
+ # default. `true` is not a supported value. Omit the field to use the default,
223
+ # which expires a token that has not been re-registered for 60 days.
212
224
  module ExpiryDate
213
225
  extend Courier::Internal::Type::Union
214
226
 
@@ -192,6 +192,8 @@ module Courier
192
192
 
193
193
  ElementalNode = Courier::Models::ElementalNode
194
194
 
195
+ ElementalNodeNonChannel = Courier::Models::ElementalNodeNonChannel
196
+
195
197
  ElementalQuoteNode = Courier::Models::ElementalQuoteNode
196
198
 
197
199
  ElementalQuoteNodeWithType = Courier::Models::ElementalQuoteNodeWithType
@@ -8,6 +8,13 @@ module Courier
8
8
  class Templates
9
9
  # Create a notification template scoped to this journey. Defaults to `DRAFT`
10
10
  # state; pass `state: "PUBLISHED"` to publish on create.
11
+ #
12
+ # The content tree must contain exactly one channel block whose `channel` matches
13
+ # the `channel` on the request — a journey-scoped template carries a single
14
+ # channel. Top-level elements, or a block for a different channel, return `400`.
15
+ # The template designer renders only the channel block matching the tab it draws,
16
+ # so content stored without one cannot be opened. An empty `elements` array is
17
+ # accepted.
11
18
  sig do
12
19
  params(
13
20
  template_id: String,
@@ -12,6 +12,16 @@ module Courier
12
12
 
13
13
  # Create a notification template. Requires all fields in the notification object.
14
14
  # Templates are created in draft state by default.
15
+ #
16
+ # Content must place its elements inside a channel block —
17
+ # `{ "type": "channel", "channel": "email", "elements": [...] }` — or the request
18
+ # returns `400`. The template designer renders only the channel block matching the
19
+ # tab it draws, so content stored without one cannot be opened. An empty
20
+ # `elements` array is accepted, and the requirement applies to creation only:
21
+ # `PUT /notifications/{id}` still accepts unwrapped content. Note this endpoint
22
+ # takes versioned content only — the `{ title, body }` shorthand accepted by
23
+ # `/send` is rejected here with an `invalid_request_error` on
24
+ # `notification.content.version`.
15
25
  sig do
16
26
  params(
17
27
  notification: Courier::NotificationTemplateWritePayload::OrHash,
@@ -92,6 +92,16 @@ module Courier
92
92
 
93
93
  # Creates or updates a notification template scoped to one tenant, letting a
94
94
  # tenant override the content the workspace template would send.
95
+ #
96
+ # This is an upsert: it creates when the tenant has no template under
97
+ # `template_id`, and updates when it does. On the create half, content must place
98
+ # its elements inside a channel block —
99
+ # `{ "type": "channel", "channel": "email", "elements": [...] }` — or the request
100
+ # returns `400`. The template designer renders only the channel block matching the
101
+ # tab it draws, so content stored without one cannot be opened. An empty
102
+ # `elements` array is accepted, as is the `{ title, body }` shorthand, which has
103
+ # no elements to wrap. Updates are not checked, so tenant templates already stored
104
+ # without a wrapper stay editable.
95
105
  sig do
96
106
  params(
97
107
  template_id: String,
@@ -122,8 +122,12 @@ module Courier
122
122
  provider_key:,
123
123
  # Body param: Information about the device the token came from.
124
124
  device: nil,
125
- # Body param: ISO 8601 formatted date the token expires. Defaults to 2 months. Set
126
- # to false to disable expiration.
125
+ # Body param: When the token expires. Accepts a date, or the boolean `false` to
126
+ # disable expiration entirely. ISO 8601 is recommended (for example
127
+ # `2026-10-25T00:00:00.000Z`). A value that cannot be parsed as a date is
128
+ # rejected; it is not treated as "no expiration" and does not fall back to the
129
+ # default. `true` is not a supported value. Omit the field to use the default,
130
+ # which expires a token that has not been re-registered for 60 days.
127
131
  expiry_date: nil,
128
132
  # Body param: Properties about the token.
129
133
  properties: nil,
@@ -3,6 +3,7 @@ module Courier
3
3
  type elemental_channel_node =
4
4
  {
5
5
  channel: String,
6
+ elements: ::Array[Courier::Models::elemental_node_non_channel]?,
6
7
  font_size: String?,
7
8
  line_height: String?,
8
9
  padding: String?,
@@ -14,6 +15,12 @@ module Courier
14
15
 
15
16
  def channel=: (String _) -> String
16
17
 
18
+ def elements: -> ::Array[Courier::Models::elemental_node_non_channel]?
19
+
20
+ def elements=: (
21
+ ::Array[Courier::Models::elemental_node_non_channel]? _
22
+ ) -> ::Array[Courier::Models::elemental_node_non_channel]?
23
+
17
24
  def font_size: -> String?
18
25
 
19
26
  def font_size=: (String? _) -> String?
@@ -32,6 +39,7 @@ module Courier
32
39
 
33
40
  def initialize: (
34
41
  ?channel: String,
42
+ ?elements: ::Array[Courier::Models::elemental_node_non_channel]?,
35
43
  ?font_size: String?,
36
44
  ?line_height: String?,
37
45
  ?padding: String?,
@@ -40,6 +48,7 @@ module Courier
40
48
 
41
49
  def to_hash: -> {
42
50
  channel: String,
51
+ elements: ::Array[Courier::Models::elemental_node_non_channel]?,
43
52
  font_size: String?,
44
53
  line_height: String?,
45
54
  padding: String?,