sentdm 0.31.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/README.md +1 -1
  4. data/lib/sentdm/client.rb +6 -0
  5. data/lib/sentdm/models/channel_event.rb +78 -0
  6. data/lib/sentdm/models/channel_event_payload.rb +265 -0
  7. data/lib/sentdm/models/contact_event.rb +77 -0
  8. data/lib/sentdm/models/contact_event_payload.rb +172 -0
  9. data/lib/sentdm/models/conversation_messages_list.rb +125 -4
  10. data/lib/sentdm/models/inbound_message_event.rb +16 -8
  11. data/lib/sentdm/models/message_event.rb +16 -8
  12. data/lib/sentdm/models/message_event_payload.rb +30 -1
  13. data/lib/sentdm/models/message_retrieve_activities_response.rb +20 -5
  14. data/lib/sentdm/models/message_retrieve_status_response.rb +133 -6
  15. data/lib/sentdm/models/message_send_params.rb +67 -3
  16. data/lib/sentdm/models/message_send_response.rb +13 -4
  17. data/lib/sentdm/models/template.rb +36 -5
  18. data/lib/sentdm/models/template_body.rb +102 -12
  19. data/lib/sentdm/models/template_body_content.rb +35 -3
  20. data/lib/sentdm/models/template_button.rb +8 -2
  21. data/lib/sentdm/models/template_button_props.rb +12 -1
  22. data/lib/sentdm/models/template_definition.rb +14 -2
  23. data/lib/sentdm/models/template_event.rb +16 -8
  24. data/lib/sentdm/models/template_event_payload.rb +31 -4
  25. data/lib/sentdm/models/template_header.rb +91 -3
  26. data/lib/sentdm/models/template_variable.rb +35 -4
  27. data/lib/sentdm/models/webhook_list_events_response.rb +332 -9
  28. data/lib/sentdm/models.rb +8 -0
  29. data/lib/sentdm/resources/messages.rb +33 -5
  30. data/lib/sentdm/resources/templates.rb +28 -2
  31. data/lib/sentdm/version.rb +1 -1
  32. data/lib/sentdm.rb +5 -1
  33. data/rbi/sentdm/client.rbi +6 -0
  34. data/rbi/sentdm/models/channel_event.rbi +128 -0
  35. data/rbi/sentdm/models/channel_event_payload.rbi +440 -0
  36. data/rbi/sentdm/models/contact_event.rbi +126 -0
  37. data/rbi/sentdm/models/contact_event_payload.rbi +254 -0
  38. data/rbi/sentdm/models/conversation_messages_list.rbi +202 -7
  39. data/rbi/sentdm/models/inbound_message_event.rbi +18 -10
  40. data/rbi/sentdm/models/message_event.rbi +18 -10
  41. data/rbi/sentdm/models/message_event_payload.rbi +34 -0
  42. data/rbi/sentdm/models/message_retrieve_activities_response.rbi +23 -5
  43. data/rbi/sentdm/models/message_retrieve_status_response.rbi +214 -9
  44. data/rbi/sentdm/models/message_send_params.rbi +100 -2
  45. data/rbi/sentdm/models/message_send_response.rbi +15 -5
  46. data/rbi/sentdm/models/template.rbi +58 -4
  47. data/rbi/sentdm/models/template_body.rbi +155 -13
  48. data/rbi/sentdm/models/template_body_content.rbi +59 -1
  49. data/rbi/sentdm/models/template_button.rbi +14 -2
  50. data/rbi/sentdm/models/template_button_props.rbi +22 -0
  51. data/rbi/sentdm/models/template_definition.rbi +20 -2
  52. data/rbi/sentdm/models/template_event.rbi +18 -10
  53. data/rbi/sentdm/models/template_event_payload.rbi +51 -8
  54. data/rbi/sentdm/models/template_header.rbi +143 -2
  55. data/rbi/sentdm/models/template_variable.rbi +38 -1
  56. data/rbi/sentdm/models/webhook_list_events_response.rbi +484 -12
  57. data/rbi/sentdm/models.rbi +8 -0
  58. data/rbi/sentdm/resources/messages.rbi +58 -3
  59. data/rbi/sentdm/resources/templates.rbi +28 -2
  60. data/sig/sentdm/models/channel_event.rbs +44 -0
  61. data/sig/sentdm/models/channel_event_payload.rbs +120 -0
  62. data/sig/sentdm/models/contact_event.rbs +44 -0
  63. data/sig/sentdm/models/contact_event_payload.rbs +78 -0
  64. data/sig/sentdm/models/conversation_messages_list.rbs +48 -3
  65. data/sig/sentdm/models/inbound_message_event.rbs +5 -0
  66. data/sig/sentdm/models/message_event.rbs +5 -0
  67. data/sig/sentdm/models/message_event_payload.rbs +15 -0
  68. data/sig/sentdm/models/message_retrieve_activities_response.rbs +5 -0
  69. data/sig/sentdm/models/message_retrieve_status_response.rbs +48 -3
  70. data/sig/sentdm/models/message_send_params.rbs +15 -0
  71. data/sig/sentdm/models/template.rbs +5 -0
  72. data/sig/sentdm/models/template_body.rbs +44 -0
  73. data/sig/sentdm/models/template_event.rbs +5 -0
  74. data/sig/sentdm/models/template_event_payload.rbs +9 -6
  75. data/sig/sentdm/models/template_header.rbs +44 -0
  76. data/sig/sentdm/models/webhook_list_events_response.rbs +147 -0
  77. data/sig/sentdm/models.rbs +8 -0
  78. data/sig/sentdm/resources/messages.rbs +3 -0
  79. metadata +14 -2
@@ -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
  #
@@ -17,6 +17,23 @@ module Sentdm
17
17
  # @return [String, nil]
18
18
  optional :id, String
19
19
 
20
+ # @!attribute auto_reply_action
21
+ # Which consent keyword this template answers, when it is one of Sent's
22
+ # auto-replies: OPT_IN, OPT_OUT, HELP, or OTHER for a customer-defined keyword.
23
+ # Null for an ordinary template, and omitted from the response, so its presence is
24
+ # the answer to "is this an auto-reply".
25
+ #
26
+ # Deliberately not required, unlike CustomerId, even though the same "no single
27
+ # mapper" argument applies: NJsonSchema publishes a C# required member in the
28
+ # schema's required array, so the contract would have advertised a field this
29
+ # response omits for every ordinary template, and a generated client could refuse
30
+ # the common case. A compile-time guard is not worth a wrong published contract.
31
+ # Every mapping site sets it explicitly, and TemplateResponseSchemaTests pins the
32
+ # field as optional so it cannot be reintroduced.
33
+ #
34
+ # @return [String, nil]
35
+ optional :auto_reply_action, String, nil?: true
36
+
20
37
  # @!attribute category
21
38
  # Template category: MARKETING, UTILITY, AUTHENTICATION
22
39
  #
@@ -24,7 +41,18 @@ module Sentdm
24
41
  optional :category, String
25
42
 
26
43
  # @!attribute channels
27
- # Supported channels: sms, whatsapp
44
+ # The channels this template's definition can render on, in canonical order: sms,
45
+ # whatsapp, rcs.
46
+ #
47
+ # Derived from the definition's body, mirroring each channel's send-time fallback
48
+ # chain, so a channel is listed only when a real body would be produced for it:
49
+ # SMS reads sms ?? multiChannel, WhatsApp reads whatsapp ?? multiChannel, and RCS
50
+ # reads rcs ?? multiChannel ?? sms. A multiChannel body therefore reports all
51
+ # three, and the extra SMS fallback on RCS is why an sms/whatsapp pair reports RCS
52
+ # too.
53
+ #
54
+ # This says what the content can render on, not what may be sent: sending also
55
+ # needs the template approved for that channel.
28
56
  #
29
57
  # @return [Array<String>, nil]
30
58
  optional :channels, Sentdm::Internal::Type::ArrayOf[String], nil?: true
@@ -54,7 +82,8 @@ module Sentdm
54
82
  optional :name, String
55
83
 
56
84
  # @!attribute status
57
- # Template status: APPROVED, PENDING, REJECTED
85
+ # Template status: DRAFT, PENDING, APPROVED, REJECTED. A template created with
86
+ # submit_for_review: false starts as DRAFT and stays there until it is submitted.
58
87
  #
59
88
  # @return [String, nil]
60
89
  optional :status, String
@@ -71,7 +100,7 @@ module Sentdm
71
100
  # @return [Array<String>, nil]
72
101
  optional :variables, Sentdm::Internal::Type::ArrayOf[String], nil?: true
73
102
 
74
- # @!method initialize(customer_id:, id: nil, category: nil, channels: nil, created_at: nil, is_published: nil, language: nil, name: nil, status: nil, updated_at: nil, variables: nil)
103
+ # @!method initialize(customer_id:, id: nil, auto_reply_action: nil, category: nil, channels: nil, created_at: nil, is_published: nil, language: nil, name: nil, status: nil, updated_at: nil, variables: nil)
75
104
  # Some parameter documentations has been truncated, see {Sentdm::Models::Template}
76
105
  # for more details.
77
106
  #
@@ -81,9 +110,11 @@ module Sentdm
81
110
  #
82
111
  # @param id [String] Unique template identifier
83
112
  #
113
+ # @param auto_reply_action [String, nil] Which consent keyword this template answers, when it is one of Sent's auto-repli
114
+ #
84
115
  # @param category [String] Template category: MARKETING, UTILITY, AUTHENTICATION
85
116
  #
86
- # @param channels [Array<String>, nil] Supported channels: sms, whatsapp
117
+ # @param channels [Array<String>, nil] The channels this template's definition can render on, in canonical order: sms,
87
118
  #
88
119
  # @param created_at [Time] When the template was created
89
120
  #
@@ -93,7 +124,7 @@ module Sentdm
93
124
  #
94
125
  # @param name [String] Template display name
95
126
  #
96
- # @param status [String] Template status: APPROVED, PENDING, REJECTED
127
+ # @param status [String] Template status: DRAFT, PENDING, APPROVED, REJECTED. A template created with
97
128
  #
98
129
  # @param updated_at [Time, nil] When the template was last updated
99
130
  #
@@ -3,45 +3,135 @@
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
- # Content that will be used for all channels (SMS and WhatsApp) unless
8
- # channel-specific content is provided
19
+ # The shared body, used for every channel. One half of the choice described above.
9
20
  #
10
21
  # @return [Sentdm::Models::TemplateBodyContent, nil]
11
22
  optional :multi_channel, -> { Sentdm::TemplateBodyContent }, api_name: :multiChannel, nil?: true
12
23
 
13
24
  # @!attribute rcs
14
- # RCS-specific content that overrides multi-channel content for RCS messages
25
+ # RCS-specific copy that overrides the chosen strategy for RCS only. The one true
26
+ # override: optional on top of either strategy, but it cannot be the only body
27
+ # present. Its length cap is the higher one described on Template.
15
28
  #
16
29
  # @return [Sentdm::Models::TemplateBodyContent, nil]
17
30
  optional :rcs, -> { Sentdm::TemplateBodyContent }, nil?: true
18
31
 
19
32
  # @!attribute sms
20
- # SMS-specific content that overrides multi-channel content for SMS messages
33
+ # The SMS body. It does not override multiChannel, it replaces it.
21
34
  #
22
35
  # @return [Sentdm::Models::TemplateBodyContent, nil]
23
36
  optional :sms, -> { Sentdm::TemplateBodyContent }, nil?: true
24
37
 
25
38
  # @!attribute whatsapp
26
- # WhatsApp-specific content that overrides multi-channel content for WhatsApp
27
- # messages
39
+ # The WhatsApp body. It does not override multiChannel, it replaces it.
28
40
  #
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
  #
36
- # Body section of a message template with channel-specific content
48
+ # Body section of a message template.
49
+ #
50
+ # A body picks one of two authoring strategies, and mixing them is refused
51
+ # (TemplateDefinitionValidator.HaveValidChannelConfiguration): a shared
52
+ # multiChannel body on its own, or an explicit sms + whatsapp pair, both present.
53
+ #
54
+ # multiChannel together with sms or whatsapp is rejected, and so is sms or
55
+ # whatsapp on its own — every template is expected to be deliverable on every
56
+ # channel. rcs is the one true override: it may accompany either strategy to vary
57
+ # the copy, but cannot stand alone.
58
+ #
59
+ # @param mms [Sentdm::Models::TemplateBody::Mms, nil] MMS-specific content — subject, text and attachments.
37
60
  #
38
- # @param multi_channel [Sentdm::Models::TemplateBodyContent, nil] Content that will be used for all channels (SMS and WhatsApp) unless channel-spe
61
+ # @param multi_channel [Sentdm::Models::TemplateBodyContent, nil] The shared body, used for every channel. One half of the choice described above.
39
62
  #
40
- # @param rcs [Sentdm::Models::TemplateBodyContent, nil] RCS-specific content that overrides multi-channel content for RCS messages
63
+ # @param rcs [Sentdm::Models::TemplateBodyContent, nil] RCS-specific copy that overrides the chosen strategy for RCS only. The one true
41
64
  #
42
- # @param sms [Sentdm::Models::TemplateBodyContent, nil] SMS-specific content that overrides multi-channel content for SMS messages
65
+ # @param sms [Sentdm::Models::TemplateBodyContent, nil] The SMS body. It does not override multiChannel, it replaces it.
43
66
  #
44
- # @param whatsapp [Sentdm::Models::TemplateBodyContent, nil] WhatsApp-specific content that overrides multi-channel content for WhatsApp mess
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
45
135
  end
46
136
  end
47
137
  end
@@ -4,24 +4,56 @@ module Sentdm
4
4
  module Models
5
5
  class TemplateBodyContent < Sentdm::Internal::Type::BaseModel
6
6
  # @!attribute template
7
+ # The body copy, with variables written as {{index:variable}}.
8
+ #
9
+ # Length cap depends on which channel this body belongs to:
10
+ # TemplateContentLimits.MaxBodyLength (1024) for multiChannel, sms and whatsapp —
11
+ # Meta's BODY limit, which a multiChannel body may be delivered under — and
12
+ # TemplateContentLimits.MaxRcsBodyLength (3072) for an rcs body, which never
13
+ # reaches Meta. The maxLength advertised on this schema is the 1024 one, because
14
+ # all four channel bodies share this single schema — an rcs body between the two
15
+ # is accepted.
16
+ #
17
+ # Meta requires every variable to carry surrounding context, so a body is refused
18
+ # unless it also satisfies all of the following (enforced by
19
+ # TemplateDefinitionValidator): At least one letter before the first variable and
20
+ # after the last — trailing punctuation such as "... {{1:variable}}." does not
21
+ # count. At least (2 × variable count) + 1 words once the placeholders are
22
+ # removed. No two variables adjacent with only whitespace between them. No leading
23
+ # or trailing newline, no more than two consecutive line breaks, and no more than
24
+ # four consecutive spaces.
25
+ #
26
+ # Example: "Hello {{0:variable}}! Welcome to {{1:variable}}. We are glad to have
27
+ # you on board." — two variables, so at least five words are required, and the
28
+ # copy after the final variable contains letters.
7
29
  #
8
30
  # @return [String]
9
31
  required :template, String
10
32
 
11
33
  # @!attribute type
34
+ # The type of body content — send "text". It is dropped from the stored definition
35
+ # when null, so a body posted without it is saved with no type key at all and the
36
+ # template editor has nothing to render the block from.
12
37
  #
13
38
  # @return [String, nil]
14
39
  optional :type, String, nil?: true
15
40
 
16
41
  # @!attribute variables
42
+ # The variables referenced by the body copy, one entry per {{index:variable}}
43
+ # placeholder.
17
44
  #
18
45
  # @return [Array<Sentdm::Models::TemplateVariable>, nil]
19
46
  optional :variables, -> { Sentdm::Internal::Type::ArrayOf[Sentdm::TemplateVariable] }, nil?: true
20
47
 
21
48
  # @!method initialize(template:, type: nil, variables: nil)
22
- # @param template [String]
23
- # @param type [String, nil]
24
- # @param variables [Array<Sentdm::Models::TemplateVariable>, nil]
49
+ # Some parameter documentations has been truncated, see
50
+ # {Sentdm::Models::TemplateBodyContent} for more details.
51
+ #
52
+ # @param template [String] The body copy, with variables written as {{index:variable}}.
53
+ #
54
+ # @param type [String, nil] The type of body content — send "text". It is dropped from the stored definition
55
+ #
56
+ # @param variables [Array<Sentdm::Models::TemplateVariable>, nil] The variables referenced by the body copy, one entry per {{index:variable}} plac
25
57
  end
26
58
  end
27
59
  end
@@ -16,7 +16,13 @@ module Sentdm
16
16
  required :type, String
17
17
 
18
18
  # @!attribute id
19
- # The unique identifier of the button (1-based index)
19
+ # The button's identifier (1-based index), unique within the template.
20
+ #
21
+ # Omitting it is only safe for a template holding a single button. The field is a
22
+ # non-nullable int, so every button that leaves it out defaults to 0, and two such
23
+ # buttons are refused by the unique-id rule ("Button IDs must be unique"). Number
24
+ # them from 1 in the order they should appear — order matters on RCS, where only
25
+ # the first four buttons render.
20
26
  #
21
27
  # @return [Integer, nil]
22
28
  optional :id, Integer
@@ -31,7 +37,7 @@ module Sentdm
31
37
  #
32
38
  # @param type [String] The type of button (e.g., QUICK_REPLY, URL, PHONE_NUMBER, VOICE_CALL, COPY_CODE)
33
39
  #
34
- # @param id [Integer] The unique identifier of the button (1-based index)
40
+ # @param id [Integer] The button's identifier (1-based index), unique within the template.
35
41
  end
36
42
  end
37
43
  end
@@ -29,6 +29,17 @@ module Sentdm
29
29
  required :quick_reply_type, String, api_name: :quickReplyType
30
30
 
31
31
  # @!attribute text
32
+ # The button's label. Required for every button type, and capped at
33
+ # TemplateContentLimits.MaxButtonTextLength (25) characters.
34
+ #
35
+ # Meta accepts only static text here, so a label is refused when it contains a
36
+ # {{...}} variable placeholder, a newline, an emoji, or WhatsApp formatting markup
37
+ # (\*, \_, ~) — enforced by ApplyButtonLabelContentRules in
38
+ # TemplateButtonValidator. Meta reports all four as one error: "Buttons can't have
39
+ # any variables, newlines, emojis, or formatting characters."
40
+ #
41
+ # AUTHENTICATION OTP buttons are the exception: Meta auto-localizes their label
42
+ # from the template language, and the converter drops whatever text was sent.
32
43
  #
33
44
  # @return [String]
34
45
  required :text, String
@@ -85,7 +96,7 @@ module Sentdm
85
96
  #
86
97
  # @param quick_reply_type [String]
87
98
  #
88
- # @param text [String]
99
+ # @param text [String] The button's label. Required for every button type, and capped at
89
100
  #
90
101
  # @param url [String]
91
102
  #
@@ -4,7 +4,16 @@ module Sentdm
4
4
  module Models
5
5
  class TemplateDefinition < Sentdm::Internal::Type::BaseModel
6
6
  # @!attribute body
7
- # Body section of a message template with channel-specific content
7
+ # Body section of a message template.
8
+ #
9
+ # A body picks one of two authoring strategies, and mixing them is refused
10
+ # (TemplateDefinitionValidator.HaveValidChannelConfiguration): a shared
11
+ # multiChannel body on its own, or an explicit sms + whatsapp pair, both present.
12
+ #
13
+ # multiChannel together with sms or whatsapp is rejected, and so is sms or
14
+ # whatsapp on its own — every template is expected to be deliverable on every
15
+ # channel. rcs is the one true override: it may accompany either strategy to vary
16
+ # the copy, but cannot stand alone.
8
17
  #
9
18
  # @return [Sentdm::Models::TemplateBody]
10
19
  required :body, -> { Sentdm::TemplateBody }
@@ -43,10 +52,13 @@ module Sentdm
43
52
  optional :header, -> { Sentdm::TemplateHeader }, nil?: true
44
53
 
45
54
  # @!method initialize(body:, authentication_config: nil, buttons: nil, definition_version: nil, footer: nil, header: nil)
55
+ # Some parameter documentations has been truncated, see
56
+ # {Sentdm::Models::TemplateDefinition} for more details.
57
+ #
46
58
  # Complete definition of a message template including header, body, footer, and
47
59
  # buttons
48
60
  #
49
- # @param body [Sentdm::Models::TemplateBody] Body section of a message template with channel-specific content
61
+ # @param body [Sentdm::Models::TemplateBody] Body section of a message template.
50
62
  #
51
63
  # @param authentication_config [Sentdm::Models::AuthenticationConfig, nil] Configuration for AUTHENTICATION category templates
52
64
  #
@@ -4,16 +4,16 @@ module Sentdm
4
4
  module Models
5
5
  class TemplateEvent < Sentdm::Internal::Type::BaseModel
6
6
  # @!attribute event
7
- # The specific event within the family, for example message.delivered or
8
- # message.received. Absent on events that have no subtype, so treat it as
9
- # optional.
7
+ # The specific event within the family, for example message.delivered,
8
+ # message.received or contact.opt_out. Absent on events that have no subtype, so
9
+ # treat it as optional.
10
10
  #
11
11
  # @return [String, nil]
12
12
  optional :event, String, nil?: true
13
13
 
14
14
  # @!attribute field
15
- # The event family, for example message or templates. Route on this first, then on
16
- # event for the specific change.
15
+ # The event family, for example message, templates or contact. Route on this
16
+ # first, then on event for the specific change.
17
17
  #
18
18
  # @return [String, nil]
19
19
  optional :field, String
@@ -25,6 +25,12 @@ module Sentdm
25
25
  # @return [Sentdm::Models::TemplateEventPayload, nil]
26
26
  optional :payload, -> { Sentdm::TemplateEventPayload }, nil?: true
27
27
 
28
+ # @!attribute request_id
29
+ # The event-specific body.
30
+ #
31
+ # @return [String, nil]
32
+ optional :request_id, String, nil?: true
33
+
28
34
  # @!attribute timestamp
29
35
  # When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
30
36
  # time, not the time the underlying change happened. Use the timestamp inside the
@@ -33,19 +39,21 @@ module Sentdm
33
39
  # @return [String, nil]
34
40
  optional :timestamp, String
35
41
 
36
- # @!method initialize(event: nil, field: nil, payload: nil, timestamp: nil)
42
+ # @!method initialize(event: nil, field: nil, payload: nil, request_id: nil, timestamp: nil)
37
43
  # Some parameter documentations has been truncated, see
38
44
  # {Sentdm::Models::TemplateEvent} for more details.
39
45
  #
40
46
  # The envelope Sent POSTs to a subscribed webhook endpoint. Every event shares
41
47
  # this shape and varies only in Payload.
42
48
  #
43
- # @param event [String, nil] The specific event within the family, for example message.delivered or
49
+ # @param event [String, nil] The specific event within the family, for example message.delivered,
44
50
  #
45
- # @param field [String] The event family, for example message or templates. Route on this first, then
51
+ # @param field [String] The event family, for example message, templates or contact. Route on
46
52
  #
47
53
  # @param payload [Sentdm::Models::TemplateEventPayload, nil] Body of a template status event. Delivered when a template's review outcome chan
48
54
  #
55
+ # @param request_id [String, nil] The event-specific body.
56
+ #
49
57
  # @param timestamp [String] When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
50
58
  end
51
59
  end