sentdm 0.31.0 → 0.32.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +1 -1
  4. data/lib/sentdm/models/channel_event.rb +78 -0
  5. data/lib/sentdm/models/channel_event_payload.rb +128 -0
  6. data/lib/sentdm/models/contact_event.rb +69 -0
  7. data/lib/sentdm/models/contact_event_payload.rb +111 -0
  8. data/lib/sentdm/models/inbound_message_event.rb +16 -8
  9. data/lib/sentdm/models/message_event.rb +16 -8
  10. data/lib/sentdm/models/message_event_payload.rb +11 -1
  11. data/lib/sentdm/models/template.rb +36 -5
  12. data/lib/sentdm/models/template_body.rb +20 -11
  13. data/lib/sentdm/models/template_body_content.rb +35 -3
  14. data/lib/sentdm/models/template_button.rb +8 -2
  15. data/lib/sentdm/models/template_button_props.rb +12 -1
  16. data/lib/sentdm/models/template_definition.rb +14 -2
  17. data/lib/sentdm/models/template_event.rb +16 -8
  18. data/lib/sentdm/models/template_event_payload.rb +31 -4
  19. data/lib/sentdm/models/template_variable.rb +20 -3
  20. data/lib/sentdm/models/webhook_list_events_response.rb +17 -9
  21. data/lib/sentdm/models.rb +8 -0
  22. data/lib/sentdm/resources/templates.rb +28 -2
  23. data/lib/sentdm/version.rb +1 -1
  24. data/lib/sentdm.rb +4 -0
  25. data/rbi/sentdm/models/channel_event.rbi +128 -0
  26. data/rbi/sentdm/models/channel_event_payload.rbi +189 -0
  27. data/rbi/sentdm/models/contact_event.rbi +110 -0
  28. data/rbi/sentdm/models/contact_event_payload.rbi +164 -0
  29. data/rbi/sentdm/models/inbound_message_event.rbi +18 -10
  30. data/rbi/sentdm/models/message_event.rbi +18 -10
  31. data/rbi/sentdm/models/message_event_payload.rbi +12 -0
  32. data/rbi/sentdm/models/template.rbi +58 -4
  33. data/rbi/sentdm/models/template_body.rbi +22 -13
  34. data/rbi/sentdm/models/template_body_content.rbi +59 -1
  35. data/rbi/sentdm/models/template_button.rbi +14 -2
  36. data/rbi/sentdm/models/template_button_props.rbi +22 -0
  37. data/rbi/sentdm/models/template_definition.rbi +20 -2
  38. data/rbi/sentdm/models/template_event.rbi +18 -10
  39. data/rbi/sentdm/models/template_event_payload.rbi +51 -8
  40. data/rbi/sentdm/models/template_variable.rbi +28 -1
  41. data/rbi/sentdm/models/webhook_list_events_response.rbi +18 -12
  42. data/rbi/sentdm/models.rbi +8 -0
  43. data/rbi/sentdm/resources/templates.rbi +28 -2
  44. data/sig/sentdm/models/channel_event.rbs +44 -0
  45. data/sig/sentdm/models/channel_event_payload.rbs +63 -0
  46. data/sig/sentdm/models/contact_event.rbs +44 -0
  47. data/sig/sentdm/models/contact_event_payload.rbs +63 -0
  48. data/sig/sentdm/models/inbound_message_event.rbs +5 -0
  49. data/sig/sentdm/models/message_event.rbs +5 -0
  50. data/sig/sentdm/models/message_event_payload.rbs +5 -0
  51. data/sig/sentdm/models/template.rbs +5 -0
  52. data/sig/sentdm/models/template_event.rbs +5 -0
  53. data/sig/sentdm/models/template_event_payload.rbs +9 -6
  54. data/sig/sentdm/models/webhook_list_events_response.rbs +2 -0
  55. data/sig/sentdm/models.rbs +8 -0
  56. metadata +14 -2
@@ -4,27 +4,27 @@ module Sentdm
4
4
  module Models
5
5
  class TemplateBody < Sentdm::Internal::Type::BaseModel
6
6
  # @!attribute multi_channel
7
- # Content that will be used for all channels (SMS and WhatsApp) unless
8
- # channel-specific content is provided
7
+ # The shared body, used for every channel. One half of the choice described above.
9
8
  #
10
9
  # @return [Sentdm::Models::TemplateBodyContent, nil]
11
10
  optional :multi_channel, -> { Sentdm::TemplateBodyContent }, api_name: :multiChannel, nil?: true
12
11
 
13
12
  # @!attribute rcs
14
- # RCS-specific content that overrides multi-channel content for RCS messages
13
+ # RCS-specific copy that overrides the chosen strategy for RCS only. The one true
14
+ # override: optional on top of either strategy, but it cannot be the only body
15
+ # present. Its length cap is the higher one described on Template.
15
16
  #
16
17
  # @return [Sentdm::Models::TemplateBodyContent, nil]
17
18
  optional :rcs, -> { Sentdm::TemplateBodyContent }, nil?: true
18
19
 
19
20
  # @!attribute sms
20
- # SMS-specific content that overrides multi-channel content for SMS messages
21
+ # The SMS body. It does not override multiChannel, it replaces it.
21
22
  #
22
23
  # @return [Sentdm::Models::TemplateBodyContent, nil]
23
24
  optional :sms, -> { Sentdm::TemplateBodyContent }, nil?: true
24
25
 
25
26
  # @!attribute whatsapp
26
- # WhatsApp-specific content that overrides multi-channel content for WhatsApp
27
- # messages
27
+ # The WhatsApp body. It does not override multiChannel, it replaces it.
28
28
  #
29
29
  # @return [Sentdm::Models::TemplateBodyContent, nil]
30
30
  optional :whatsapp, -> { Sentdm::TemplateBodyContent }, nil?: true
@@ -33,15 +33,24 @@ module Sentdm
33
33
  # Some parameter documentations has been truncated, see
34
34
  # {Sentdm::Models::TemplateBody} for more details.
35
35
  #
36
- # Body section of a message template with channel-specific content
36
+ # Body section of a message template.
37
37
  #
38
- # @param multi_channel [Sentdm::Models::TemplateBodyContent, nil] Content that will be used for all channels (SMS and WhatsApp) unless channel-spe
38
+ # A body picks one of two authoring strategies, and mixing them is refused
39
+ # (TemplateDefinitionValidator.HaveValidChannelConfiguration): a shared
40
+ # multiChannel body on its own, or an explicit sms + whatsapp pair, both present.
39
41
  #
40
- # @param rcs [Sentdm::Models::TemplateBodyContent, nil] RCS-specific content that overrides multi-channel content for RCS messages
42
+ # multiChannel together with sms or whatsapp is rejected, and so is sms or
43
+ # whatsapp on its own — every template is expected to be deliverable on every
44
+ # channel. rcs is the one true override: it may accompany either strategy to vary
45
+ # the copy, but cannot stand alone.
41
46
  #
42
- # @param sms [Sentdm::Models::TemplateBodyContent, nil] SMS-specific content that overrides multi-channel content for SMS messages
47
+ # @param multi_channel [Sentdm::Models::TemplateBodyContent, nil] The shared body, used for every channel. One half of the choice described above.
43
48
  #
44
- # @param whatsapp [Sentdm::Models::TemplateBodyContent, nil] WhatsApp-specific content that overrides multi-channel content for WhatsApp mess
49
+ # @param rcs [Sentdm::Models::TemplateBodyContent, nil] RCS-specific copy that overrides the chosen strategy for RCS only. The one true
50
+ #
51
+ # @param sms [Sentdm::Models::TemplateBodyContent, nil] The SMS body. It does not override multiChannel, it replaces it.
52
+ #
53
+ # @param whatsapp [Sentdm::Models::TemplateBodyContent, nil] The WhatsApp body. It does not override multiChannel, it replaces it.
45
54
  end
46
55
  end
47
56
  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
@@ -22,6 +22,25 @@ module Sentdm
22
22
  # @return [String, nil]
23
23
  optional :account_id, String
24
24
 
25
+ # @!attribute auto_reply_action
26
+ # Which consent keyword this template answers, when it is one of Sent's
27
+ # auto-replies: OPT_IN, OPT_OUT, HELP, or OTHER for a customer-defined keyword.
28
+ #
29
+ # Omitted for an ordinary template, so its presence is the answer to "is this an
30
+ # auto-reply". Sent creates the three compliance auto-replies at signup and they
31
+ # go through review like any other template, so their events arrive mixed in with
32
+ # the customer's own with nothing else to tell them apart.
33
+ #
34
+ # Named for the reader rather than after Template.OptAction, which it is mapped
35
+ # from. The MCP tool result deliberately keeps OptAction, OptKeywords and IsOpt:
36
+ # it mirrors the internal shape on purpose and publishes the keywords too, so
37
+ # renaming one of the three there would leave a surface half in each vocabulary.
38
+ # Two names for one concept, each consistent within its own surface, chosen over a
39
+ # rename that breaks MCP clients silently.
40
+ #
41
+ # @return [String, nil]
42
+ optional :auto_reply_action, String, nil?: true
43
+
25
44
  # @!attribute category
26
45
  # The template's category, for example UTILITY, MARKETING, or AUTHENTICATION.
27
46
  #
@@ -29,10 +48,16 @@ module Sentdm
29
48
  optional :category, String
30
49
 
31
50
  # @!attribute channel
32
- # The channel the template applies to.
51
+ # The channel leg this decision is about, for example whatsapp, sms, or rcs. A
52
+ # template is reviewed per channel and the legs come back independently, so each
53
+ # one reports separately.
54
+ #
55
+ # Omitted when the decision applies to the template as a whole rather than to one
56
+ # leg. That event is the broader news: a template-wide rejection blocks every
57
+ # channel, whatever the individual legs say.
33
58
  #
34
59
  # @return [String, nil]
35
- optional :channel, String
60
+ optional :channel, String, nil?: true
36
61
 
37
62
  # @!attribute language
38
63
  # The template's language code, for example en_US.
@@ -59,7 +84,7 @@ module Sentdm
59
84
  # @return [String, nil]
60
85
  optional :template_name, String
61
86
 
62
- # @!method initialize(status:, whatsapp_template_id:, account_id: nil, category: nil, channel: nil, language: nil, reason: nil, template_id: nil, template_name: nil)
87
+ # @!method initialize(status:, whatsapp_template_id:, account_id: nil, auto_reply_action: nil, category: nil, channel: nil, language: nil, reason: nil, template_id: nil, template_name: nil)
63
88
  # Some parameter documentations has been truncated, see
64
89
  # {Sentdm::Models::TemplateEventPayload} for more details.
65
90
  #
@@ -72,9 +97,11 @@ module Sentdm
72
97
  #
73
98
  # @param account_id [String] The account the template belongs to.
74
99
  #
100
+ # @param auto_reply_action [String, nil] Which consent keyword this template answers, when it is one of Sent's auto-repli
101
+ #
75
102
  # @param category [String] The template's category, for example UTILITY, MARKETING, or
76
103
  #
77
- # @param channel [String] The channel the template applies to.
104
+ # @param channel [String, nil] The channel leg this decision is about, for example whatsapp, sms, or rcs.
78
105
  #
79
106
  # @param language [String] The template's language code, for example en_US.
80
107
  #
@@ -4,6 +4,9 @@ module Sentdm
4
4
  module Models
5
5
  class TemplateVariable < Sentdm::Internal::Type::BaseModel
6
6
  # @!attribute name
7
+ # The variable's name, and the key callers use for it in a send request's
8
+ # parameters object. Must start with a letter and hold only letters, digits and
9
+ # underscores.
7
10
  #
8
11
  # @return [String]
9
12
  required :name, String
@@ -14,20 +17,34 @@ module Sentdm
14
17
  required :props, -> { Sentdm::TemplateVariable::Props }
15
18
 
16
19
  # @!attribute type
20
+ # One of variable, link or media. Decides which Props fields are required.
17
21
  #
18
22
  # @return [String]
19
23
  required :type, String
20
24
 
21
25
  # @!attribute id
26
+ # The variable's index, and the number its {{index:variable}} placeholder refers
27
+ # to.
28
+ #
29
+ # Omitting it is only safe for a section holding a single variable. The field is a
30
+ # non-nullable int, so every variable that leaves it out defaults to 0, and a
31
+ # section with two such variables is refused by the unique-id rule ("variables
32
+ # must have unique IDs"). Number them from 0 in the order they appear.
22
33
  #
23
34
  # @return [Integer, nil]
24
35
  optional :id, Integer
25
36
 
26
37
  # @!method initialize(name:, props:, type:, id: nil)
27
- # @param name [String]
38
+ # Some parameter documentations has been truncated, see
39
+ # {Sentdm::Models::TemplateVariable} for more details.
40
+ #
41
+ # @param name [String] The variable's name, and the key callers use for it in a send request's paramete
42
+ #
28
43
  # @param props [Sentdm::Models::TemplateVariable::Props]
29
- # @param type [String]
30
- # @param id [Integer]
44
+ #
45
+ # @param type [String] One of variable, link or media. Decides which Props fields
46
+ #
47
+ # @param id [Integer] The variable's index, and the number its {{index:variable}} placeholder refers t
31
48
 
32
49
  # @see Sentdm::Models::TemplateVariable#props
33
50
  class Props < Sentdm::Internal::Type::BaseModel
@@ -31,11 +31,11 @@ module Sentdm
31
31
 
32
32
  # @!attribute event_data
33
33
  # The exact event body that was delivered, or attempted, for this record. One of
34
- # the three webhook envelopes: a message status change, an inbound message, or a
35
- # template status change. Read field and event to tell which, the same way your
36
- # endpoint does.
34
+ # the four webhook envelopes: a message status change, an inbound message, a
35
+ # template status change, or a contact consent signal. Read field and event to
36
+ # tell which, the same way your endpoint does.
37
37
  #
38
- # @return [Sentdm::Models::MessageEvent, Sentdm::Models::InboundMessageEvent, Sentdm::Models::TemplateEvent, nil]
38
+ # @return [Sentdm::Models::MessageEvent, Sentdm::Models::InboundMessageEvent, Sentdm::Models::TemplateEvent, Sentdm::Models::ChannelEvent, Sentdm::Models::ContactEvent, nil]
39
39
  optional :event_data, union: -> { Sentdm::Models::WebhookListEventsResponse::EventData }
40
40
 
41
41
  # @!attribute event_type
@@ -77,7 +77,7 @@ module Sentdm
77
77
  #
78
78
  # @param error_message [String, nil]
79
79
  #
80
- # @param event_data [Sentdm::Models::MessageEvent, Sentdm::Models::InboundMessageEvent, Sentdm::Models::TemplateEvent] The exact event body that was delivered, or attempted, for this record. One of t
80
+ # @param event_data [Sentdm::Models::MessageEvent, Sentdm::Models::InboundMessageEvent, Sentdm::Models::TemplateEvent, Sentdm::Models::ChannelEvent, Sentdm::Models::ContactEvent] The exact event body that was delivered, or attempted, for this record. One of t
81
81
  #
82
82
  # @param event_type [String]
83
83
  #
@@ -90,9 +90,9 @@ module Sentdm
90
90
  # @param response_body [String, nil]
91
91
 
92
92
  # The exact event body that was delivered, or attempted, for this record. One of
93
- # the three webhook envelopes: a message status change, an inbound message, or a
94
- # template status change. Read field and event to tell which, the same way your
95
- # endpoint does.
93
+ # the four webhook envelopes: a message status change, an inbound message, a
94
+ # template status change, or a contact consent signal. Read field and event to
95
+ # tell which, the same way your endpoint does.
96
96
  #
97
97
  # @see Sentdm::Models::WebhookListEventsResponse#event_data
98
98
  module EventData
@@ -110,8 +110,16 @@ module Sentdm
110
110
  # varies only in Payload.
111
111
  variant -> { Sentdm::TemplateEvent }
112
112
 
113
+ # The envelope Sent POSTs to a subscribed webhook endpoint. Every event shares this shape and
114
+ # varies only in Payload.
115
+ variant -> { Sentdm::ChannelEvent }
116
+
117
+ # The envelope Sent POSTs to a subscribed webhook endpoint. Every event shares this shape and
118
+ # varies only in Payload.
119
+ variant -> { Sentdm::ContactEvent }
120
+
113
121
  # @!method self.variants
114
- # @return [Array(Sentdm::Models::MessageEvent, Sentdm::Models::InboundMessageEvent, Sentdm::Models::TemplateEvent)]
122
+ # @return [Array(Sentdm::Models::MessageEvent, Sentdm::Models::InboundMessageEvent, Sentdm::Models::TemplateEvent, Sentdm::Models::ChannelEvent, Sentdm::Models::ContactEvent)]
115
123
  end
116
124
  end
117
125
  end
data/lib/sentdm/models.rb CHANGED
@@ -67,10 +67,18 @@ module Sentdm
67
67
 
68
68
  BrandsBrandData = Sentdm::Models::BrandsBrandData
69
69
 
70
+ ChannelEvent = Sentdm::Models::ChannelEvent
71
+
72
+ ChannelEventPayload = Sentdm::Models::ChannelEventPayload
73
+
70
74
  ContactCreateParams = Sentdm::Models::ContactCreateParams
71
75
 
72
76
  ContactDeleteParams = Sentdm::Models::ContactDeleteParams
73
77
 
78
+ ContactEvent = Sentdm::Models::ContactEvent
79
+
80
+ ContactEventPayload = Sentdm::Models::ContactEventPayload
81
+
74
82
  ContactListParams = Sentdm::Models::ContactListParams
75
83
 
76
84
  ContactMessageSummary = Sentdm::Models::ContactMessageSummary
@@ -15,7 +15,9 @@ module Sentdm
15
15
  #
16
16
  # Creates a new message template with header, body, footer, and buttons. The
17
17
  # template can be submitted for review immediately or saved as draft for later
18
- # submission.
18
+ # submission. There is no `name` field on create — the display name is derived
19
+ # from the template's content and can be changed afterwards with
20
+ # `PUT /v3/templates/{id}`.
19
21
  #
20
22
  # @overload create(category: nil, creation_source: nil, definition: nil, language: nil, sandbox: nil, submit_for_review: nil, idempotency_key: nil, x_profile_id: nil, request_options: {})
21
23
  #
@@ -85,7 +87,31 @@ module Sentdm
85
87
  # {Sentdm::Models::TemplateUpdateParams} for more details.
86
88
  #
87
89
  # Updates an existing template's name, category, language, definition, or submits
88
- # it for review.
90
+ # it for review. While the template is in review (status PENDING, or any channel
91
+ # awaiting a verdict) its definition, category and language are frozen and a
92
+ # resubmission is refused — those requests answer 409 CONFLICT_006. The display
93
+ # name stays editable throughout.
94
+ #
95
+ # `definition`, `category` and `language` are editable only from status DRAFT,
96
+ # REJECTED or APPROVED. An edit to any of them on a template in another state
97
+ # (PAUSED, DISABLED or REVOKED) is refused with 400 VALIDATION_001 and the detail
98
+ # "Template (except display name) cannot be updated unless it is in draft or
99
+ # rejected status"; `name` stays editable in every state. `submit_for_review` on a
100
+ # PAUSED, DISABLED or REVOKED template is accepted and answers 200, but opens no
101
+ # review and does not move the status — only the reviewer can reinstate it.
102
+ #
103
+ # Editing an APPROVED template is a live edit: the new content is stored
104
+ # immediately, and sending `submit_for_review: true` re-opens review, which
105
+ # returns the affected channels to PENDING so they stop sending until they are
106
+ # approved again. The previously approved content is never sent during re-review.
107
+ # Watch the per-channel `templates` webhook events rather than assuming the
108
+ # template-level status.
109
+ #
110
+ # Templates provisioned by Sent (light-onboarding templates, whose names carry the
111
+ # reserved `sent_` prefix) are read-only: every field is refused with 400
112
+ # VALIDATION*001 and the detail "This template is read-only. Only 'submit for
113
+ # review' is allowed.", and only `submit_for_review` is accepted. A `name`
114
+ # starting with `sent*` is refused for the same reason — the prefix is reserved.
89
115
  #
90
116
  # @overload update(id, category: nil, definition: nil, language: nil, name: nil, sandbox: nil, submit_for_review: nil, idempotency_key: nil, x_profile_id: nil, request_options: {})
91
117
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sentdm
4
- VERSION = "0.31.0"
4
+ VERSION = "0.32.0"
5
5
  end
data/lib/sentdm.rb CHANGED
@@ -72,8 +72,12 @@ require_relative "sentdm/models/brand_business_info"
72
72
  require_relative "sentdm/models/brand_compliance_info"
73
73
  require_relative "sentdm/models/brand_contact_info"
74
74
  require_relative "sentdm/models/brands_brand_data"
75
+ require_relative "sentdm/models/channel_event"
76
+ require_relative "sentdm/models/channel_event_payload"
75
77
  require_relative "sentdm/models/contact_create_params"
76
78
  require_relative "sentdm/models/contact_delete_params"
79
+ require_relative "sentdm/models/contact_event"
80
+ require_relative "sentdm/models/contact_event_payload"
77
81
  require_relative "sentdm/models/contact_list_params"
78
82
  require_relative "sentdm/models/contact_message_summary"
79
83
  require_relative "sentdm/models/contact_response"
@@ -0,0 +1,128 @@
1
+ # typed: strong
2
+
3
+ module Sentdm
4
+ module Models
5
+ class ChannelEvent < Sentdm::Internal::Type::BaseModel
6
+ OrHash =
7
+ T.type_alias { T.any(Sentdm::ChannelEvent, Sentdm::Internal::AnyHash) }
8
+
9
+ # The specific event within the family, for example message.delivered,
10
+ # message.received or contact.opt_out. Absent on events that have no subtype, so
11
+ # treat it as optional.
12
+ sig { returns(T.nilable(String)) }
13
+ attr_accessor :event
14
+
15
+ # The event family, for example message, templates or contact. Route on this
16
+ # first, then on event for the specific change.
17
+ sig { returns(T.nilable(String)) }
18
+ attr_reader :field
19
+
20
+ sig { params(field: String).void }
21
+ attr_writer :field
22
+
23
+ # Body of a channel event: where one of the customer's channels stands in
24
+ # provisioning and compliance. Delivered when a milestone moves — a registration
25
+ # filed, a verdict returned, a resubmission asked for, a sender gone live — so a
26
+ # customer's own onboarding UI does not have to poll GET /v3/channels.
27
+ #
28
+ # The subject is one item, never the account. A customer's "SMS channel" has no
29
+ # status; a market does. Country, NumberType and SenderValue name which one, so a
30
+ # customer terminating only to Kosovo never receives an event about US 10DLC.
31
+ #
32
+ # Status is the stable half of the contract. It is the same four-value set GET
33
+ # /v3/channels publishes, computed through the same code, so an event and a read
34
+ # of the same market cannot disagree. A subscriber that reads nothing but the
35
+ # status and the subject fields is a correct subscriber. The sub-type on the
36
+ # envelope names the specific milestone and is additive — that vocabulary comes
37
+ # from registries and carriers, which are parties Sent does not control.
38
+ #
39
+ # Status means provisioning and compliance are complete, not that a send will
40
+ # succeed right now. An account can be suspended, or a destination blocked by a
41
+ # routing rule, without either showing up here. Those are separate surfaces and
42
+ # deliberately not modelled on this payload.
43
+ sig { returns(T.nilable(Sentdm::ChannelEventPayload)) }
44
+ attr_reader :payload
45
+
46
+ sig do
47
+ params(payload: T.nilable(Sentdm::ChannelEventPayload::OrHash)).void
48
+ end
49
+ attr_writer :payload
50
+
51
+ # The event-specific body.
52
+ sig { returns(T.nilable(String)) }
53
+ attr_accessor :request_id
54
+
55
+ # When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
56
+ # time, not the time the underlying change happened. Use the timestamp inside the
57
+ # payload for the latter.
58
+ sig { returns(T.nilable(String)) }
59
+ attr_reader :timestamp
60
+
61
+ sig { params(timestamp: String).void }
62
+ attr_writer :timestamp
63
+
64
+ # The envelope Sent POSTs to a subscribed webhook endpoint. Every event shares
65
+ # this shape and varies only in Payload.
66
+ sig do
67
+ params(
68
+ event: T.nilable(String),
69
+ field: String,
70
+ payload: T.nilable(Sentdm::ChannelEventPayload::OrHash),
71
+ request_id: T.nilable(String),
72
+ timestamp: String
73
+ ).returns(T.attached_class)
74
+ end
75
+ def self.new(
76
+ # The specific event within the family, for example message.delivered,
77
+ # message.received or contact.opt_out. Absent on events that have no subtype, so
78
+ # treat it as optional.
79
+ event: nil,
80
+ # The event family, for example message, templates or contact. Route on this
81
+ # first, then on event for the specific change.
82
+ field: nil,
83
+ # Body of a channel event: where one of the customer's channels stands in
84
+ # provisioning and compliance. Delivered when a milestone moves — a registration
85
+ # filed, a verdict returned, a resubmission asked for, a sender gone live — so a
86
+ # customer's own onboarding UI does not have to poll GET /v3/channels.
87
+ #
88
+ # The subject is one item, never the account. A customer's "SMS channel" has no
89
+ # status; a market does. Country, NumberType and SenderValue name which one, so a
90
+ # customer terminating only to Kosovo never receives an event about US 10DLC.
91
+ #
92
+ # Status is the stable half of the contract. It is the same four-value set GET
93
+ # /v3/channels publishes, computed through the same code, so an event and a read
94
+ # of the same market cannot disagree. A subscriber that reads nothing but the
95
+ # status and the subject fields is a correct subscriber. The sub-type on the
96
+ # envelope names the specific milestone and is additive — that vocabulary comes
97
+ # from registries and carriers, which are parties Sent does not control.
98
+ #
99
+ # Status means provisioning and compliance are complete, not that a send will
100
+ # succeed right now. An account can be suspended, or a destination blocked by a
101
+ # routing rule, without either showing up here. Those are separate surfaces and
102
+ # deliberately not modelled on this payload.
103
+ payload: nil,
104
+ # The event-specific body.
105
+ request_id: nil,
106
+ # When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
107
+ # time, not the time the underlying change happened. Use the timestamp inside the
108
+ # payload for the latter.
109
+ timestamp: nil
110
+ )
111
+ end
112
+
113
+ sig do
114
+ override.returns(
115
+ {
116
+ event: T.nilable(String),
117
+ field: String,
118
+ payload: T.nilable(Sentdm::ChannelEventPayload),
119
+ request_id: T.nilable(String),
120
+ timestamp: String
121
+ }
122
+ )
123
+ end
124
+ def to_hash
125
+ end
126
+ end
127
+ end
128
+ end