sentdm 0.32.0 → 0.33.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +1 -1
  4. data/lib/sentdm/client.rb +6 -0
  5. data/lib/sentdm/models/channel_event_payload.rb +139 -2
  6. data/lib/sentdm/models/contact_event.rb +15 -7
  7. data/lib/sentdm/models/contact_event_payload.rb +77 -16
  8. data/lib/sentdm/models/conversation_messages_list.rb +125 -4
  9. data/lib/sentdm/models/message_event_payload.rb +20 -1
  10. data/lib/sentdm/models/message_retrieve_activities_response.rb +20 -5
  11. data/lib/sentdm/models/message_retrieve_status_response.rb +133 -6
  12. data/lib/sentdm/models/message_send_params.rb +67 -3
  13. data/lib/sentdm/models/message_send_response.rb +13 -4
  14. data/lib/sentdm/models/template_body.rb +82 -1
  15. data/lib/sentdm/models/template_header.rb +91 -3
  16. data/lib/sentdm/models/template_variable.rb +15 -1
  17. data/lib/sentdm/models/webhook_list_events_response.rb +324 -9
  18. data/lib/sentdm/resources/messages.rb +33 -5
  19. data/lib/sentdm/version.rb +1 -1
  20. data/lib/sentdm.rb +1 -1
  21. data/rbi/sentdm/client.rbi +6 -0
  22. data/rbi/sentdm/models/channel_event_payload.rbi +253 -2
  23. data/rbi/sentdm/models/contact_event.rbi +28 -12
  24. data/rbi/sentdm/models/contact_event_payload.rbi +118 -28
  25. data/rbi/sentdm/models/conversation_messages_list.rbi +202 -7
  26. data/rbi/sentdm/models/message_event_payload.rbi +22 -0
  27. data/rbi/sentdm/models/message_retrieve_activities_response.rbi +23 -5
  28. data/rbi/sentdm/models/message_retrieve_status_response.rbi +214 -9
  29. data/rbi/sentdm/models/message_send_params.rbi +100 -2
  30. data/rbi/sentdm/models/message_send_response.rbi +15 -5
  31. data/rbi/sentdm/models/template_body.rbi +133 -0
  32. data/rbi/sentdm/models/template_header.rbi +143 -2
  33. data/rbi/sentdm/models/template_variable.rbi +10 -0
  34. data/rbi/sentdm/models/webhook_list_events_response.rbi +478 -12
  35. data/rbi/sentdm/resources/messages.rbi +58 -3
  36. data/sig/sentdm/models/channel_event_payload.rbs +57 -0
  37. data/sig/sentdm/models/contact_event_payload.rbs +24 -9
  38. data/sig/sentdm/models/conversation_messages_list.rbs +48 -3
  39. data/sig/sentdm/models/message_event_payload.rbs +10 -0
  40. data/sig/sentdm/models/message_retrieve_activities_response.rbs +5 -0
  41. data/sig/sentdm/models/message_retrieve_status_response.rbs +48 -3
  42. data/sig/sentdm/models/message_send_params.rbs +15 -0
  43. data/sig/sentdm/models/template_body.rbs +44 -0
  44. data/sig/sentdm/models/template_header.rbs +44 -0
  45. data/sig/sentdm/models/webhook_list_events_response.rbs +145 -0
  46. data/sig/sentdm/resources/messages.rbs +3 -0
  47. metadata +2 -2
@@ -98,9 +98,18 @@ module Sentdm
98
98
  # @return [String, nil]
99
99
  optional :price, String, nil?: true
100
100
 
101
+ # @!attribute scheduled_at
102
+ # SCHEDULED activities only: when the held message will be released for delivery,
103
+ # in UTC. Same wire name as on the send response, the message and the webhook.
104
+ # Omitted on every other activity. A message that quiet hours moved at release has
105
+ # two SCHEDULED entries, each carrying the instant as it stood at that moment.
106
+ #
107
+ # @return [Time, nil]
108
+ optional :scheduled_at, Time, nil?: true
109
+
101
110
  # @!attribute status
102
- # Activity status. Outbound: QUEUED, PROCESSED, ROUTED, SENT, DELIVERED, READ,
103
- # FAILED. Inbound (from contact): RECEIVED (terminal).
111
+ # Activity status. Outbound: QUEUED, PROCESSED, ROUTED, SCHEDULED, SENT,
112
+ # DELIVERED, READ, FAILED. Inbound (from contact): RECEIVED (terminal).
104
113
  #
105
114
  # @return [String, nil]
106
115
  optional :status, String
@@ -111,12 +120,16 @@ module Sentdm
111
120
  # @return [Time, nil]
112
121
  optional :timestamp, Time
113
122
 
114
- # @!method initialize(active_contact_price: nil, description: nil, from: nil, price: nil, status: nil, timestamp: nil)
123
+ # @!method initialize(active_contact_price: nil, description: nil, from: nil, price: nil, scheduled_at: nil, status: nil, timestamp: nil)
115
124
  # Some parameter documentations has been truncated, see
116
125
  # {Sentdm::Models::MessageRetrieveActivitiesResponse::Data::Activity} for more
117
126
  # details.
118
127
  #
119
- # A single message activity event for v3 API
128
+ # A single message activity event for v3 API.
129
+ #
130
+ # The activity list mixes statuses, so unlike a message it is one shape rather
131
+ # than two: a SCHEDULED entry carries scheduled_at, and every other entry has no
132
+ # such key.
120
133
  #
121
134
  # @param active_contact_price [String, nil] Active contact markup applied on top of the channel cost, formatted to 4 decimal
122
135
  #
@@ -126,7 +139,9 @@ module Sentdm
126
139
  #
127
140
  # @param price [String, nil] Channel cost for this activity (e.g., SMS/WhatsApp provider cost), formatted to
128
141
  #
129
- # @param status [String] Activity status. Outbound: QUEUED, PROCESSED, ROUTED, SENT, DELIVERED, READ, FAI
142
+ # @param scheduled_at [Time, nil] SCHEDULED activities only: when the held message will be released for delivery,
143
+ #
144
+ # @param status [String] Activity status. Outbound: QUEUED, PROCESSED, ROUTED, SCHEDULED, SENT, DELIVERED
130
145
  #
131
146
  # @param timestamp [Time] When this activity occurred
132
147
  end
@@ -5,7 +5,12 @@ module Sentdm
5
5
  # @see Sentdm::Resources::Messages#retrieve_status
6
6
  class MessageRetrieveStatusResponse < Sentdm::Internal::Type::BaseModel
7
7
  # @!attribute data
8
- # Message response for v3 API — same shape as v2 with snake_case JSON conventions
8
+ # Message response for v3 API — same shape as v2 with snake_case JSON conventions.
9
+ #
10
+ # The shape of a message that was sent immediately: it never has a scheduled_at
11
+ # key. A message that is or was held for a later instant is a
12
+ # ScheduledMessageResponse, and the endpoint decides which of the two to answer
13
+ # with. From always returns this type.
9
14
  #
10
15
  # @return [Sentdm::Models::MessageRetrieveStatusResponse::Data, nil]
11
16
  optional :data, -> { Sentdm::Models::MessageRetrieveStatusResponse::Data }, nil?: true
@@ -29,9 +34,12 @@ module Sentdm
29
34
  optional :success, Sentdm::Internal::Type::Boolean
30
35
 
31
36
  # @!method initialize(data: nil, error: nil, meta: nil, success: nil)
37
+ # Some parameter documentations has been truncated, see
38
+ # {Sentdm::Models::MessageRetrieveStatusResponse} for more details.
39
+ #
32
40
  # Standard API response envelope for all v3 endpoints
33
41
  #
34
- # @param data [Sentdm::Models::MessageRetrieveStatusResponse::Data, nil] Message response for v3 API — same shape as v2 with snake_case JSON conventions
42
+ # @param data [Sentdm::Models::MessageRetrieveStatusResponse::Data, nil] Message response for v3 API — same shape as v2 with snake_case JSON conventions.
35
43
  #
36
44
  # @param error [Sentdm::Models::ErrorDetail, nil] Error information
37
45
  #
@@ -85,7 +93,14 @@ module Sentdm
85
93
 
86
94
  # @!attribute message_body
87
95
  # Structured message body format for database storage. Preserves channel-specific
88
- # components (header, body, footer, buttons).
96
+ # components (header, header media, body, footer, buttons, MMS subject and media).
97
+ #
98
+ # Persisted as the messageBody jsonb column on Messages. Every write path goes
99
+ # through MessageUtils.MessageBodyJsonOptions, which writes nulls, so the envelope
100
+ # shape is stable regardless of channel or status. Anything that rebuilds this
101
+ # object field by field — the four IMessageBodyStrategy implementations and
102
+ # MessageUtils.BuildSegmentBody — has to carry every member, or that member is
103
+ # silently dropped on whichever path forgot it.
89
104
  #
90
105
  # @return [Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody, nil]
91
106
  optional :message_body,
@@ -136,7 +151,12 @@ module Sentdm
136
151
  # Some parameter documentations has been truncated, see
137
152
  # {Sentdm::Models::MessageRetrieveStatusResponse::Data} for more details.
138
153
  #
139
- # Message response for v3 API — same shape as v2 with snake_case JSON conventions
154
+ # Message response for v3 API — same shape as v2 with snake_case JSON conventions.
155
+ #
156
+ # The shape of a message that was sent immediately: it never has a scheduled_at
157
+ # key. A message that is or was held for a later instant is a
158
+ # ScheduledMessageResponse, and the endpoint decides which of the two to answer
159
+ # with. From always returns this type.
140
160
  #
141
161
  # @param id [String]
142
162
  #
@@ -220,14 +240,63 @@ module Sentdm
220
240
  # @return [String, nil]
221
241
  optional :header, String, nil?: true
222
242
 
223
- # @!method initialize(buttons: nil, content: nil, footer: nil, header: nil)
243
+ # @!attribute header_media
244
+ # The media asset that rode a message's header, recorded as sent.
245
+ #
246
+ # @return [Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::HeaderMedia, nil]
247
+ optional :header_media,
248
+ -> { Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::HeaderMedia },
249
+ api_name: :headerMedia,
250
+ nil?: true
251
+
252
+ # @!attribute media
253
+ # MMS attachments, as the publicly fetchable URLs handed to the carrier. Null on
254
+ # every other channel.
255
+ #
256
+ # Persisted rather than derived because a resend and a curfew release rebuild the
257
+ # send from the stored row — MessageReplayCommandBuilder reads templateId and
258
+ # templateVariables and nothing else — so media that lives only on the original
259
+ # request would silently turn a replayed MMS into a text message.
260
+ #
261
+ # @return [Array<Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::Media>, nil]
262
+ optional :media,
263
+ -> { Sentdm::Internal::Type::ArrayOf[Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::Media] },
264
+ nil?: true
265
+
266
+ # @!attribute subject
267
+ # MMS subject line. Null on every other channel.
268
+ #
269
+ # @return [String, nil]
270
+ optional :subject, String, nil?: true
271
+
272
+ # @!method initialize(buttons: nil, content: nil, footer: nil, header: nil, header_media: nil, media: nil, subject: nil)
273
+ # Some parameter documentations has been truncated, see
274
+ # {Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody} for more
275
+ # details.
276
+ #
224
277
  # Structured message body format for database storage. Preserves channel-specific
225
- # components (header, body, footer, buttons).
278
+ # components (header, header media, body, footer, buttons, MMS subject and media).
279
+ #
280
+ # Persisted as the messageBody jsonb column on Messages. Every write path goes
281
+ # through MessageUtils.MessageBodyJsonOptions, which writes nulls, so the envelope
282
+ # shape is stable regardless of channel or status. Anything that rebuilds this
283
+ # object field by field — the four IMessageBodyStrategy implementations and
284
+ # MessageUtils.BuildSegmentBody — has to carry every member, or that member is
285
+ # silently dropped on whichever path forgot it.
226
286
  #
227
287
  # @param buttons [Array<Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::Button>, nil]
288
+ #
228
289
  # @param content [String]
290
+ #
229
291
  # @param footer [String, nil]
292
+ #
230
293
  # @param header [String, nil]
294
+ #
295
+ # @param header_media [Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::HeaderMedia, nil] The media asset that rode a message's header, recorded as sent.
296
+ #
297
+ # @param media [Array<Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::Media>, nil] MMS attachments, as the publicly fetchable URLs handed to the carrier. Null on e
298
+ #
299
+ # @param subject [String, nil] MMS subject line. Null on every other channel.
231
300
 
232
301
  class Button < Sentdm::Internal::Type::BaseModel
233
302
  # @!attribute postback_data
@@ -256,6 +325,64 @@ module Sentdm
256
325
  # @param type [String]
257
326
  # @param value [String]
258
327
  end
328
+
329
+ # @see Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody#header_media
330
+ class HeaderMedia < Sentdm::Internal::Type::BaseModel
331
+ # @!attribute type
332
+ # "image", "video" or "document" — taken from the header's media variable.
333
+ #
334
+ # @return [String, nil]
335
+ optional :type, String
336
+
337
+ # @!attribute url
338
+ # The https URL the caller supplied for this send. Never the template's stored
339
+ # props.sample, which is Meta's expiring header_handle rather than what was
340
+ # delivered.
341
+ #
342
+ # @return [String, nil]
343
+ optional :url, String
344
+
345
+ # @!method initialize(type: nil, url: nil)
346
+ # Some parameter documentations has been truncated, see
347
+ # {Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::HeaderMedia}
348
+ # for more details.
349
+ #
350
+ # The media asset that rode a message's header, recorded as sent.
351
+ #
352
+ # @param type [String] "image", "video" or "document" — taken from the header's media variable.
353
+ #
354
+ # @param url [String] The https URL the caller supplied for this send. Never the template's stored
355
+ end
356
+
357
+ class Media < Sentdm::Internal::Type::BaseModel
358
+ # @!attribute media_type
359
+ # One of Constants.MmsMediaTypes when known. Advisory — the carrier reads the
360
+ # fetched object's Content-Type, not this.
361
+ #
362
+ # @return [String, nil]
363
+ optional :media_type, String, api_name: :mediaType, nil?: true
364
+
365
+ # @!attribute url
366
+ #
367
+ # @return [String, nil]
368
+ optional :url, String
369
+
370
+ # @!method initialize(media_type: nil, url: nil)
371
+ # Some parameter documentations has been truncated, see
372
+ # {Sentdm::Models::MessageRetrieveStatusResponse::Data::MessageBody::Media} for
373
+ # more details.
374
+ #
375
+ # One attachment on a message: a customer-supplied public URL handed to the
376
+ # carrier as-is.
377
+ #
378
+ # A URL and nothing else. sent.dm never takes custody of MMS media — the customer hosts it and we
379
+ # pass the link through at send time — so there is no storage key, size or expiry to record. If we ever
380
+ # do host attachments, that belongs with the change that introduces the hosting, not here.
381
+ #
382
+ # @param media_type [String, nil] One of Constants.MmsMediaTypes when known. Advisory — the carrier reads the
383
+ #
384
+ # @param url [String]
385
+ end
259
386
  end
260
387
  end
261
388
  end
@@ -15,6 +15,25 @@ module Sentdm
15
15
  # @return [Array<String>, nil]
16
16
  optional :channel, Sentdm::Internal::Type::ArrayOf[String], nil?: true
17
17
 
18
+ # @!attribute media_urls
19
+ # Attachments for this send, as publicly fetchable https URLs. Used by the MMS
20
+ # channel and ignored by every other one.
21
+ #
22
+ # Supplying these replaces the media on the template's mms body rather than adding
23
+ # to it, so a template can hold a default creative while a caller still sends
24
+ # something recipient-specific.
25
+ #
26
+ # Their presence is also what makes a message eligible for MMS on an auto-detect
27
+ # send: a message with nothing attached is delivered as SMS, because an MMS with
28
+ # no media is a more expensive text message.
29
+ #
30
+ # The recipient's carrier fetches each URL after the send is accepted, so it must
31
+ # stay publicly reachable — a link that expires, or one behind auth, arrives as a
32
+ # failed message.
33
+ #
34
+ # @return [Array<String>, nil]
35
+ optional :media_urls, Sentdm::Internal::Type::ArrayOf[String], nil?: true
36
+
18
37
  # @!attribute sandbox
19
38
  # Sandbox flag - when true, the operation is simulated without side effects Useful
20
39
  # for testing integrations without actual execution
@@ -22,6 +41,29 @@ module Sentdm
22
41
  # @return [Boolean, nil]
23
42
  optional :sandbox, Sentdm::Internal::Type::Boolean
24
43
 
44
+ # @!attribute scheduled_at
45
+ # Optional future send time as an ISO-8601 timestamp with an explicit UTC offset,
46
+ # e.g. 2026-10-01T09:00:00+02:00 or 2026-10-01T07:00:00Z. A value without an
47
+ # offset is rejected (400) rather than read in the server's zone. The offset only
48
+ # fixes the instant: it is stored and echoed in UTC as scheduled_at. Omit to send
49
+ # now. Must be at least one minute ahead and at most 30 days ahead. Accepted
50
+ # messages report SCHEDULED and are released for delivery at this time. Quiet
51
+ # hours, balance and template approval are evaluated at release, not at
52
+ # acceptance: a message whose time falls inside a recipient's protected
53
+ # quiet-hours window is moved to the next allowed time and a second
54
+ # message.scheduled webhook reports the new scheduled_at.
55
+ #
56
+ # @return [Time, nil]
57
+ optional :scheduled_at, Time, nil?: true
58
+
59
+ # @!attribute subject
60
+ # Subject line for this send, overriding the template's. MMS only; ignored on
61
+ # every other channel. Most handsets render it above the body, some ignore it
62
+ # entirely.
63
+ #
64
+ # @return [String, nil]
65
+ optional :subject, String, nil?: true
66
+
25
67
  # @!attribute template
26
68
  # SDK-style template reference: resolve by ID or by name, with optional
27
69
  # parameters.
@@ -51,14 +93,20 @@ module Sentdm
51
93
  # @return [String, nil]
52
94
  optional :x_profile_id, String
53
95
 
54
- # @!method initialize(channel: nil, sandbox: nil, template: nil, text: nil, to: nil, idempotency_key: nil, x_profile_id: nil, request_options: {})
96
+ # @!method initialize(channel: nil, media_urls: nil, sandbox: nil, scheduled_at: nil, subject: nil, template: nil, text: nil, to: nil, idempotency_key: nil, x_profile_id: nil, request_options: {})
55
97
  # Some parameter documentations has been truncated, see
56
98
  # {Sentdm::Models::MessageSendParams} for more details.
57
99
  #
58
100
  # @param channel [Array<String>, nil] Channels to broadcast on, e.g. ["whatsapp", "sms"].
59
101
  #
102
+ # @param media_urls [Array<String>, nil] Attachments for this send, as publicly fetchable https URLs. Used by the MMS cha
103
+ #
60
104
  # @param sandbox [Boolean] Sandbox flag - when true, the operation is simulated without side effects
61
105
  #
106
+ # @param scheduled_at [Time, nil] Optional future send time as an ISO-8601 timestamp with an explicit UTC offset,
107
+ #
108
+ # @param subject [String, nil] Subject line for this send, overriding the template's. MMS only; ignored on ever
109
+ #
62
110
  # @param template [Sentdm::Models::MessageSendParams::Template, nil] SDK-style template reference: resolve by ID or by name, with optional parameters
63
111
  #
64
112
  # @param text [String, nil] Plain-text (free-form) message body. Provide either Template or this.
@@ -85,12 +133,28 @@ module Sentdm
85
133
  optional :name, String, nil?: true
86
134
 
87
135
  # @!attribute parameters
88
- # Template variable parameters for personalization
136
+ # Template variable parameters for personalization, keyed by variable name.
137
+ #
138
+ # Every variable the template declares is required; GET /v3/templates/{id} lists
139
+ # them. Supplying a key the template does not declare is ignored.
140
+ #
141
+ # Media headers. A template whose header is an image (designed in WhatsApp Manager
142
+ # and imported into Sent) declares a reserved header_image key. Its value is a
143
+ # publicly reachable https URL that Meta fetches at send time — Sent does not host
144
+ # the asset, and the sample approved with the template is not reused. The key is
145
+ # derived from the header's media type, so header_video and header_document follow
146
+ # the same shape when those formats ship.
147
+ #
148
+ # "parameters": { "header_image": "https://cdn.example.com/banner.jpg", "name":
149
+ # "John Doe" }
89
150
  #
90
151
  # @return [Hash{Symbol=>String}, nil]
91
152
  optional :parameters, Sentdm::Internal::Type::HashOf[String], nil?: true
92
153
 
93
154
  # @!method initialize(id: nil, name: nil, parameters: nil)
155
+ # Some parameter documentations has been truncated, see
156
+ # {Sentdm::Models::MessageSendParams::Template} for more details.
157
+ #
94
158
  # SDK-style template reference: resolve by ID or by name, with optional
95
159
  # parameters.
96
160
  #
@@ -98,7 +162,7 @@ module Sentdm
98
162
  #
99
163
  # @param name [String, nil] Template name (mutually exclusive with id)
100
164
  #
101
- # @param parameters [Hash{Symbol=>String}, nil] Template variable parameters for personalization
165
+ # @param parameters [Hash{Symbol=>String}, nil] Template variable parameters for personalization, keyed by variable name.
102
166
  end
103
167
  end
104
168
  end
@@ -14,7 +14,9 @@ module Sentdm
14
14
  # its result; this is what a caller sees, and the mapping between them is a
15
15
  # decision the endpoint makes.
16
16
  #
17
- # The wire is unchanged by the move: same names, same values.
17
+ # The shape of an immediate send: it never has a scheduled_at key. A send that
18
+ # carried scheduled_at is a ScheduledSendMessageResponse, and the endpoint decides
19
+ # which of the two to answer with. From always returns this type.
18
20
  #
19
21
  # @return [Sentdm::Models::MessageSendResponse::Data, nil]
20
22
  optional :data, -> { Sentdm::Models::MessageSendResponse::Data }, nil?: true
@@ -60,7 +62,9 @@ module Sentdm
60
62
  -> { Sentdm::Internal::Type::ArrayOf[Sentdm::Models::MessageSendResponse::Data::Recipient] }
61
63
 
62
64
  # @!attribute status
63
- # Overall status — QUEUED once the batch is accepted for delivery.
65
+ # QUEUED: the batch is accepted. A request that carried scheduled_at is QUEUED
66
+ # here too; each message moves to SCHEDULED once it is held, as GET
67
+ # /v3/messages/{id} and the message.scheduled webhook report.
64
68
  #
65
69
  # @return [String, nil]
66
70
  optional :status, String
@@ -76,6 +80,9 @@ module Sentdm
76
80
  optional :template_name, String
77
81
 
78
82
  # @!method initialize(recipients: nil, status: nil, template_id: nil, template_name: nil)
83
+ # Some parameter documentations has been truncated, see
84
+ # {Sentdm::Models::MessageSendResponse::Data} for more details.
85
+ #
79
86
  # The result of a multi-recipient send.
80
87
  #
81
88
  # Declared here rather than in the service layer. POST /v3/messages used to
@@ -85,11 +92,13 @@ module Sentdm
85
92
  # its result; this is what a caller sees, and the mapping between them is a
86
93
  # decision the endpoint makes.
87
94
  #
88
- # The wire is unchanged by the move: same names, same values.
95
+ # The shape of an immediate send: it never has a scheduled_at key. A send that
96
+ # carried scheduled_at is a ScheduledSendMessageResponse, and the endpoint decides
97
+ # which of the two to answer with. From always returns this type.
89
98
  #
90
99
  # @param recipients [Array<Sentdm::Models::MessageSendResponse::Data::Recipient>]
91
100
  #
92
- # @param status [String] Overall status — QUEUED once the batch is accepted for delivery.
101
+ # @param status [String] QUEUED: the batch is accepted. A request that carried scheduled_at is QUEUED
93
102
  #
94
103
  # @param template_id [String]
95
104
  #
@@ -3,6 +3,18 @@
3
3
  module Sentdm
4
4
  module Models
5
5
  class TemplateBody < Sentdm::Internal::Type::BaseModel
6
+ # @!attribute mms
7
+ # MMS-specific content — subject, text and attachments.
8
+ #
9
+ # Like Rcs, an override that cannot stand on its own: a template still needs a
10
+ # MultiChannel body or the Sms + Whatsapp pair to be deliverable at all. Unlike
11
+ # Rcs, it has no fallback at send time — MMS with no media is a more expensive
12
+ # SMS, so a template without this slot is deliberately not MMS-capable and never
13
+ # produces an MMS route candidate.
14
+ #
15
+ # @return [Sentdm::Models::TemplateBody::Mms, nil]
16
+ optional :mms, -> { Sentdm::TemplateBody::Mms }, nil?: true
17
+
6
18
  # @!attribute multi_channel
7
19
  # The shared body, used for every channel. One half of the choice described above.
8
20
  #
@@ -29,7 +41,7 @@ module Sentdm
29
41
  # @return [Sentdm::Models::TemplateBodyContent, nil]
30
42
  optional :whatsapp, -> { Sentdm::TemplateBodyContent }, nil?: true
31
43
 
32
- # @!method initialize(multi_channel: nil, rcs: nil, sms: nil, whatsapp: nil)
44
+ # @!method initialize(mms: nil, multi_channel: nil, rcs: nil, sms: nil, whatsapp: nil)
33
45
  # Some parameter documentations has been truncated, see
34
46
  # {Sentdm::Models::TemplateBody} for more details.
35
47
  #
@@ -44,6 +56,8 @@ module Sentdm
44
56
  # channel. rcs is the one true override: it may accompany either strategy to vary
45
57
  # the copy, but cannot stand alone.
46
58
  #
59
+ # @param mms [Sentdm::Models::TemplateBody::Mms, nil] MMS-specific content — subject, text and attachments.
60
+ #
47
61
  # @param multi_channel [Sentdm::Models::TemplateBodyContent, nil] The shared body, used for every channel. One half of the choice described above.
48
62
  #
49
63
  # @param rcs [Sentdm::Models::TemplateBodyContent, nil] RCS-specific copy that overrides the chosen strategy for RCS only. The one true
@@ -51,6 +65,73 @@ module Sentdm
51
65
  # @param sms [Sentdm::Models::TemplateBodyContent, nil] The SMS body. It does not override multiChannel, it replaces it.
52
66
  #
53
67
  # @param whatsapp [Sentdm::Models::TemplateBodyContent, nil] The WhatsApp body. It does not override multiChannel, it replaces it.
68
+
69
+ # @see Sentdm::Models::TemplateBody#mms
70
+ class Mms < Sentdm::Models::TemplateBodyContent
71
+ # @!attribute media
72
+ # Attachments carried by every send on this template, in order. A per-send
73
+ # media_urls on the request replaces this list rather than adding to it, so a
74
+ # template can hold a default creative and a caller can still send something
75
+ # recipient-specific.
76
+ #
77
+ # @return [Array<Sentdm::Models::TemplateBody::Mms::Media>, nil]
78
+ optional :media, -> { Sentdm::Internal::Type::ArrayOf[Sentdm::TemplateBody::Mms::Media] }, nil?: true
79
+
80
+ # @!attribute subject
81
+ # MMS subject line. Optional — most handsets render it above the body, some ignore
82
+ # it entirely. Deliberately its own field rather than riding TemplateHeader: the
83
+ # header is authored once and shared across every channel, and carries Meta's
84
+ # 60-character cap plus its no-newline, no-emoji text rules, none of which
85
+ # describe an MMS subject.
86
+ #
87
+ # @return [String, nil]
88
+ optional :subject, String, nil?: true
89
+
90
+ # @!method initialize(media: nil, subject: nil)
91
+ # Some parameter documentations has been truncated, see
92
+ # {Sentdm::Models::TemplateBody::Mms} for more details.
93
+ #
94
+ # MMS-specific content — subject, text and attachments.
95
+ #
96
+ # Like Rcs, an override that cannot stand on its own: a template still needs a
97
+ # MultiChannel body or the Sms + Whatsapp pair to be deliverable at all. Unlike
98
+ # Rcs, it has no fallback at send time — MMS with no media is a more expensive
99
+ # SMS, so a template without this slot is deliberately not MMS-capable and never
100
+ # produces an MMS route candidate.
101
+ #
102
+ # @param media [Array<Sentdm::Models::TemplateBody::Mms::Media>, nil] Attachments carried by every send on this template, in order. A per-send media_u
103
+ #
104
+ # @param subject [String, nil] MMS subject line. Optional — most handsets render it above the body, some ignore
105
+
106
+ class Media < Sentdm::Internal::Type::BaseModel
107
+ # @!attribute media_type
108
+ # One of MmsMediaTypes. Advisory: the carrier reads the Content-Type off the
109
+ # fetched object, not this field. It exists so an authoring UI can render the
110
+ # right preview and so a reviewer can see what was intended.
111
+ #
112
+ # @return [String, nil]
113
+ optional :media_type, String, api_name: :mediaType, nil?: true
114
+
115
+ # @!attribute url
116
+ # Publicly fetchable https URL. The carrier's MMSC fetches this at send time, so
117
+ # it has to stay reachable and unauthenticated for the life of the send —
118
+ # including retries and a DLQ replay — which is why a presigned URL is not a valid
119
+ # value here.
120
+ #
121
+ # @return [String, nil]
122
+ optional :url, String
123
+
124
+ # @!method initialize(media_type: nil, url: nil)
125
+ # Some parameter documentations has been truncated, see
126
+ # {Sentdm::Models::TemplateBody::Mms::Media} for more details.
127
+ #
128
+ # One attachment on an MMS template body.
129
+ #
130
+ # @param media_type [String, nil] One of MmsMediaTypes. Advisory: the carrier reads the Content-Type off the
131
+ #
132
+ # @param url [String] Publicly fetchable https URL. The carrier's MMSC fetches this at send time, so i
133
+ end
134
+ end
54
135
  end
55
136
  end
56
137
  end
@@ -10,8 +10,56 @@ module Sentdm
10
10
  # @return [String]
11
11
  required :template, String
12
12
 
13
+ # @!attribute example_url
14
+ # Request-only. The s.dm URL of the asset Meta's reviewers see —
15
+ # https://s.dm/s/{ID}, eight uppercase characters, uploaded to s.dm out of band.
16
+ # NormalizeRichHeader folds it into the synthesized media variable's Props.Sample
17
+ # and clears it, so it never persists and a stored definition is indistinguishable
18
+ # from an imported one.
19
+ #
20
+ # Stricter than the send path on purpose:
21
+ # TemplateUtils.ValidateMediaVariableValues accepts any absolute https URL for the
22
+ # per-send asset, because that one is the customer's and may live behind a signed
23
+ # CDN link. This one is the review sample, has to outlive every resubmission, and
24
+ # so must be ours. Do not "fix" one to match the other.
25
+ #
26
+ # @return [String, nil]
27
+ optional :example_url, String, nil?: true
28
+
29
+ # @!attribute location
30
+ # The map pin a location header drops. Meta wants none of this at creation — the
31
+ # component is just {"type":"header","format":"location"} — so these values exist
32
+ # for Sent: a preview, and the default a StaticResource header falls back to at
33
+ # send.
34
+ #
35
+ # @return [Sentdm::Models::TemplateHeader::Location, nil]
36
+ optional :location, -> { Sentdm::TemplateHeader::Location }, nil?: true
37
+
38
+ # @!attribute static_resource
39
+ # Whether the asset registered at creation is reused when a caller omits the
40
+ # header's variable at send time. Default false — the caller must supply it per
41
+ # message, which is the behaviour every existing template has. Written only when
42
+ # true, so a default-valued header serializes byte-identically to one imported
43
+ # from Meta.
44
+ #
45
+ # Stored and validated but not yet honoured at send: that lands with the Resumable
46
+ # Upload work, alongside the code that lets such a template be approved in the
47
+ # first place.
48
+ #
49
+ # @return [Boolean, nil]
50
+ optional :static_resource, Sentdm::Internal::Type::Boolean
51
+
13
52
  # @!attribute type
14
- # The type of header (e.g., "text", "image", "video", "document")
53
+ # The kind of header. One of:
54
+ #
55
+ # text — up to 60 characters, at most one variable. image — png, jpg or jpeg.
56
+ # Needs ExampleUrl. video — mp4. Needs ExampleUrl. gif — mp4, max 3.5MB. WhatsApp
57
+ # renders larger files as an ordinary video. Needs ExampleUrl. document — pdf or
58
+ # docx; only the first page is shown as a thumbnail, so pdf is the practical
59
+ # choice. Needs ExampleUrl. location — a map pin, supplied through Location.
60
+ #
61
+ # Kept lowercase because MetaToTemplateConverter writes Meta's format through
62
+ # ToLowerInvariant() into this field on import, and the two are compared directly.
15
63
  #
16
64
  # @return [String, nil]
17
65
  optional :type, String, nil?: true
@@ -22,7 +70,7 @@ module Sentdm
22
70
  # @return [Array<Sentdm::Models::TemplateVariable>, nil]
23
71
  optional :variables, -> { Sentdm::Internal::Type::ArrayOf[Sentdm::TemplateVariable] }, nil?: true
24
72
 
25
- # @!method initialize(template:, type: nil, variables: nil)
73
+ # @!method initialize(template:, example_url: nil, location: nil, static_resource: nil, type: nil, variables: nil)
26
74
  # Some parameter documentations has been truncated, see
27
75
  # {Sentdm::Models::TemplateHeader} for more details.
28
76
  #
@@ -30,9 +78,49 @@ module Sentdm
30
78
  #
31
79
  # @param template [String] The header template text with optional variable placeholders (e.g., "Welcome to
32
80
  #
33
- # @param type [String, nil] The type of header (e.g., "text", "image", "video", "document")
81
+ # @param example_url [String, nil] Request-only. The s.dm URL of the asset Meta's reviewers see — https://s.dm/s/{I
82
+ #
83
+ # @param location [Sentdm::Models::TemplateHeader::Location, nil] The map pin a location header drops. Meta wants none of this at creation — the c
84
+ #
85
+ # @param static_resource [Boolean] Whether the asset registered at creation is reused when a caller omits the heade
86
+ #
87
+ # @param type [String, nil] The kind of header. One of:
34
88
  #
35
89
  # @param variables [Array<Sentdm::Models::TemplateVariable>, nil] List of variables used in the header template
90
+
91
+ # @see Sentdm::Models::TemplateHeader#location
92
+ class Location < Sentdm::Internal::Type::BaseModel
93
+ # @!attribute address
94
+ #
95
+ # @return [String]
96
+ required :address, String
97
+
98
+ # @!attribute latitude
99
+ #
100
+ # @return [String]
101
+ required :latitude, String
102
+
103
+ # @!attribute longitude
104
+ #
105
+ # @return [String]
106
+ required :longitude, String
107
+
108
+ # @!attribute name
109
+ #
110
+ # @return [String]
111
+ required :name, String
112
+
113
+ # @!method initialize(address:, latitude:, longitude:, name:)
114
+ # The map pin a location header drops. Meta wants none of this at creation — the
115
+ # component is just {"type":"header","format":"location"} — so these values exist
116
+ # for Sent: a preview, and the default a StaticResource header falls back to at
117
+ # send.
118
+ #
119
+ # @param address [String]
120
+ # @param latitude [String]
121
+ # @param longitude [String]
122
+ # @param name [String]
123
+ end
36
124
  end
37
125
  end
38
126
  end
@@ -54,6 +54,11 @@ module Sentdm
54
54
  required :media_type, String, api_name: :mediaType
55
55
 
56
56
  # @!attribute sample
57
+ # Example value substituted into the template when previewing it and when
58
+ # submitting it to Meta for review. Free text by nature, so the converter accepts
59
+ # a JSON number or boolean here and normalizes it — see
60
+ # JsonScalarToStringConverter for why — and guarantees it is always serialized
61
+ # back out as a JSON string.
57
62
  #
58
63
  # @return [String]
59
64
  required :sample, String
@@ -84,12 +89,21 @@ module Sentdm
84
89
  optional :short_url, String, api_name: :shortUrl, nil?: true
85
90
 
86
91
  # @!method initialize(media_type:, sample:, url:, variable_type:, alt: nil, regex: nil, short_url: nil)
92
+ # Some parameter documentations has been truncated, see
93
+ # {Sentdm::Models::TemplateVariable::Props} for more details.
94
+ #
87
95
  # @param media_type [String]
88
- # @param sample [String]
96
+ #
97
+ # @param sample [String] Example value substituted into the template when previewing it and when submitti
98
+ #
89
99
  # @param url [String]
100
+ #
90
101
  # @param variable_type [String]
102
+ #
91
103
  # @param alt [String, nil]
104
+ #
92
105
  # @param regex [String, nil]
106
+ #
93
107
  # @param short_url [String, nil]
94
108
  end
95
109
  end