twilio-ruby 7.11.3 → 7.13.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +277 -0
  3. data/Gemfile.lock +2 -2
  4. data/README.md +2 -2
  5. data/examples/WebhookSignatureValidation.md +61 -0
  6. data/lib/rack/twilio_webhook_authentication.rb +30 -5
  7. data/lib/twilio-ruby/rest/api/v2010/account/call.rb +7 -0
  8. data/lib/twilio-ruby/rest/api/v2010/account/conference.rb +4 -4
  9. data/lib/twilio-ruby/rest/client.rb +5 -0
  10. data/lib/twilio-ruby/rest/content/v1/content/approval_create.rb +108 -1
  11. data/lib/twilio-ruby/rest/content/v1/content.rb +10 -4
  12. data/lib/twilio-ruby/rest/conversations/v2/action.rb +9 -2
  13. data/lib/twilio-ruby/rest/conversations/v2/communication.rb +4 -1
  14. data/lib/twilio-ruby/rest/conversations/v2/configuration.rb +21 -0
  15. data/lib/twilio-ruby/rest/conversations/v2/conversation.rb +226 -7
  16. data/lib/twilio-ruby/rest/insights/v1/call/call_summary.rb +1 -1
  17. data/lib/twilio-ruby/rest/insights/v1/call_summaries.rb +1 -1
  18. data/lib/twilio-ruby/rest/insights/v3/custom_field_mapping.rb +512 -17
  19. data/lib/twilio-ruby/rest/insights/v3/{capacity.rb → custom_field_mappings_capacity.rb} +26 -26
  20. data/lib/twilio-ruby/rest/insights/v3.rb +17 -7
  21. data/lib/twilio-ruby/rest/memory/v1/bulk.rb +22 -1
  22. data/lib/twilio-ruby/rest/memory/v1/conversation_summary.rb +5 -5
  23. data/lib/twilio-ruby/rest/memory/v1/import.rb +21 -7
  24. data/lib/twilio-ruby/rest/memory/v1/observation.rb +9 -9
  25. data/lib/twilio-ruby/rest/memory/v1/revision.rb +1 -1
  26. data/lib/twilio-ruby/rest/memory/v1/store.rb +7 -0
  27. data/lib/twilio-ruby/rest/messaging/v2/channels_sender.rb +30 -2
  28. data/lib/twilio-ruby/rest/numbers/v1/sms_verification.rb +30 -6
  29. data/lib/twilio-ruby/rest/numbers/v1/sms_verification_check.rb +30 -6
  30. data/lib/twilio-ruby/rest/numbers/v1/voice_verification.rb +45 -6
  31. data/lib/twilio-ruby/rest/numbers/v1.rb +0 -6
  32. data/lib/twilio-ruby/rest/preview/hosted_numbers/authorization_document.rb +40 -0
  33. data/lib/twilio-ruby/rest/routes/v3/iso_country_code.rb +402 -0
  34. data/lib/twilio-ruby/rest/routes/v3.rb +43 -0
  35. data/lib/twilio-ruby/rest/trusthub/v1/a2p_brand_registration.rb +5 -5
  36. data/lib/twilio-ruby/rest/trusthub/v1/a2p_campaign_registration.rb +4 -4
  37. data/lib/twilio-ruby/rest/trusthub/v1.rb +2 -2
  38. data/lib/twilio-ruby/rest/webhooks/v1/auth_profile.rb +825 -0
  39. data/lib/twilio-ruby/rest/webhooks/v1/edge_zone.rb +320 -0
  40. data/lib/twilio-ruby/rest/webhooks/v1/operation.rb +513 -0
  41. data/lib/twilio-ruby/rest/webhooks/v1/rule.rb +818 -0
  42. data/lib/twilio-ruby/rest/webhooks/v1/setting.rb +1028 -0
  43. data/lib/twilio-ruby/rest/webhooks/v1/shared_key.rb +722 -0
  44. data/lib/twilio-ruby/rest/webhooks/v1/test.rb +228 -0
  45. data/lib/twilio-ruby/rest/webhooks/v1.rb +126 -0
  46. data/lib/twilio-ruby/rest/webhooks.rb +6 -0
  47. data/lib/twilio-ruby/rest/webhooks_base.rb +38 -0
  48. data/lib/twilio-ruby/security/request_validator.rb +54 -8
  49. data/lib/twilio-ruby/twiml/voice_response.rb +20 -5
  50. data/lib/twilio-ruby/version.rb +1 -1
  51. metadata +15 -5
  52. data/lib/twilio-ruby/rest/numbers/v1/voice_verification_check.rb +0 -165
  53. data/lib/twilio-ruby/rest/oauth/v2/oauth_authorization_server.rb +0 -200
@@ -0,0 +1,228 @@
1
+ ##
2
+ # This code was generated by
3
+ # ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
4
+ # | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
5
+ # | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
6
+ #
7
+ # Twilio - Webhooks Configuration
8
+ # Centralized webhook configuration with OAuth2 support, immutable resources, and zero-downtime credential rotation.
9
+ #
10
+ # NOTE: This class is auto generated by OpenAPI Generator.
11
+ # https://openapi-generator.tech
12
+ # Do not edit the class manually.
13
+ #
14
+
15
+
16
+ module Twilio
17
+ module REST
18
+ class Webhooks < WebhooksBase
19
+ class V1 < Version
20
+ class TestList < ListResource
21
+
22
+ class TestDeliveryResultResponse
23
+ # @param [status_code]: [Integer]
24
+ # @param [headers]: [Hash<String, Array<String>>]
25
+ attr_accessor :status_code, :headers
26
+ def initialize(payload)
27
+ @status_code = payload["status_code"]
28
+ @headers = payload["headers"]
29
+ end
30
+ def to_json(options = {})
31
+ {
32
+ "statusCode": @status_code,
33
+ "headers": @headers,
34
+ }.to_json(options)
35
+ end
36
+ end
37
+
38
+ class TestDeliveryResultTiming
39
+ # @param [total_ms]: [Integer] Total time taken for the webhook delivery in milliseconds
40
+ attr_accessor :total_ms
41
+ def initialize(payload)
42
+ @total_ms = payload["total_ms"]
43
+ end
44
+ def to_json(options = {})
45
+ {
46
+ "totalMs": @total_ms,
47
+ }.to_json(options)
48
+ end
49
+ end
50
+
51
+ class TestRequest
52
+ # @param [url]: [String] Target webhook URL to test
53
+ # @param [setting_id]: [String] Setting to use for test configuration
54
+ # @param [method]: [String] HTTP method to use when sending the test webhook request
55
+ attr_accessor :url, :setting_id, :method
56
+ def initialize(payload)
57
+ @url = payload["url"]
58
+ @setting_id = payload["setting_id"]
59
+ @method = payload["method"]
60
+ end
61
+ def to_json(options = {})
62
+ {
63
+ "url": @url,
64
+ "settingId": @setting_id,
65
+ "method": @method,
66
+ }.to_json(options)
67
+ end
68
+ end
69
+
70
+
71
+ ##
72
+ # Initialize the TestList
73
+ # @param [Version] version Version that contains the resource
74
+ # @return [TestList] TestList
75
+ def initialize(version)
76
+
77
+ apiV1Version = ApiV1Version.new version.domain, version
78
+ super(apiV1Version)
79
+ # Path Solution
80
+ @solution = { }
81
+ @uri = "/Webhooks/Tests"
82
+
83
+ end
84
+ ##
85
+ # Create the TestInstance
86
+ # @param [TestRequest] test_request
87
+ # @return [TestInstance] Created TestInstance
88
+ def create(test_request: nil
89
+ )
90
+
91
+ headers = Twilio::Values.of({'Content-Type' => 'application/x-www-form-urlencoded', })
92
+ headers['Content-Type'] = 'application/json'
93
+
94
+
95
+
96
+ headers['Accept'] = '*/*'
97
+ payload = @version.create('POST', @uri, headers: headers, data: test_request.to_json)
98
+ TestInstance.new(
99
+ @version,
100
+ payload,
101
+ )
102
+ end
103
+
104
+ ##
105
+ # Create the TestInstanceMetadata
106
+ # @param [TestRequest] test_request
107
+ # @return [TestInstance] Created TestInstance
108
+ def create_with_metadata(test_request: nil
109
+ )
110
+
111
+ headers = Twilio::Values.of({'Content-Type' => 'application/x-www-form-urlencoded', })
112
+ headers['Content-Type'] = 'application/json'
113
+
114
+
115
+
116
+ headers['Accept'] = '*/*'
117
+ response = @version.create_with_metadata('POST', @uri, headers: headers, data: test_request.to_json)
118
+ test_instance = TestInstance.new(
119
+ @version,
120
+ response.body,
121
+ )
122
+ TestInstanceMetadata.new(
123
+ @version,
124
+ test_instance,
125
+ response.headers,
126
+ response.status_code
127
+ )
128
+ end
129
+
130
+
131
+
132
+
133
+ # Provide a user friendly representation
134
+ def to_s
135
+ '#<Twilio.Webhooks.V1.TestList>'
136
+ end
137
+ end
138
+
139
+ class TestPage < TokenPage
140
+ ##
141
+ # Initialize the TestPage
142
+ # @param [Version] version Version that contains the resource
143
+ # @param [Response] response Response from the API
144
+ # @param [Hash] solution Path solution for the resource
145
+ # @return [TestPage] TestPage
146
+ def initialize(version, response, solution)
147
+
148
+ apiV1Version = ApiV1Version.new version.domain, version
149
+ super(apiV1Version, response)
150
+
151
+ # Path Solution
152
+ @solution = solution
153
+ end
154
+
155
+ ##
156
+ # Build an instance of TestInstance
157
+ # @param [Hash] payload Payload response from the API
158
+ # @return [TestInstance] TestInstance
159
+ def get_instance(payload)
160
+ TestInstance.new(@version, payload)
161
+ end
162
+
163
+ ##
164
+ # Provide a user friendly representation
165
+ def to_s
166
+ '<Twilio.Webhooks.V1.TestPage>'
167
+ end
168
+ end
169
+
170
+ class TestInstance < InstanceResource
171
+ ##
172
+ # Initialize the TestInstance
173
+ # @param [Version] version Version that contains the resource
174
+ # @param [Hash] payload payload that contains response from Twilio
175
+ # @param [String] account_sid The SID of the
176
+ # {Account}[https://www.twilio.com/docs/iam/api/account] that created this Test
177
+ # resource.
178
+ # @param [String] sid The SID of the Call resource to fetch.
179
+ # @return [TestInstance] TestInstance
180
+ def initialize(version, payload )
181
+
182
+ apiV1Version = ApiV1Version.new version.domain, version
183
+ super(apiV1Version)
184
+
185
+ # Marshaled Properties
186
+ @properties = {
187
+ 'url' => payload['url'],
188
+ 'result' => payload['result'],
189
+ 'created_at' => Twilio.deserialize_iso8601_datetime(payload['created_at']),
190
+ }
191
+ end
192
+
193
+
194
+ ##
195
+ # @return [String]
196
+ def url
197
+ @properties['url']
198
+ end
199
+
200
+ ##
201
+ # @return [TestDeliveryResult]
202
+ def result
203
+ @properties['result']
204
+ end
205
+
206
+ ##
207
+ # @return [Time]
208
+ def created_at
209
+ @properties['created_at']
210
+ end
211
+
212
+ ##
213
+ # Provide a user friendly representation
214
+ def to_s
215
+ "<Twilio.Webhooks.V1.TestInstance>"
216
+ end
217
+
218
+ ##
219
+ # Provide a detailed, user friendly representation
220
+ def inspect
221
+ "<Twilio.Webhooks.V1.TestInstance>"
222
+ end
223
+ end
224
+
225
+ end
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,126 @@
1
+ ##
2
+ # This code was generated by
3
+ # ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
4
+ # | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
5
+ # | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
6
+ #
7
+ # Twilio - Webhooks Configuration
8
+ # Centralized webhook configuration with OAuth2 support, immutable resources, and zero-downtime credential rotation.
9
+ #
10
+ # NOTE: This class is auto generated by OpenAPI Generator.
11
+ # https://openapi-generator.tech
12
+ # Do not edit the class manually.
13
+ #
14
+
15
+ module Twilio
16
+ module REST
17
+ class Webhooks
18
+ class V1 < Version
19
+ ##
20
+ # Initialize the V1 version of Webhooks
21
+ def initialize(domain)
22
+ super
23
+ @version = 'v1'
24
+ @auth_profiles = nil
25
+ @edge_zones = nil
26
+ @operations = nil
27
+ @rules = nil
28
+ @settings = nil
29
+ @shared_keys = nil
30
+ @tests = nil
31
+ end
32
+
33
+ ##
34
+ # @param [String] auth_profile_id
35
+ # @return [Twilio::REST::Webhooks::V1::AuthProfileContext] if authProfileId was passed.
36
+ # @return [Twilio::REST::Webhooks::V1::AuthProfileList]
37
+ def auth_profiles(auth_profile_id=:unset)
38
+ if auth_profile_id.nil?
39
+ raise ArgumentError, 'auth_profile_id cannot be nil'
40
+ end
41
+
42
+ if auth_profile_id == :unset
43
+ @auth_profiles ||= AuthProfileList.new self
44
+ else
45
+ AuthProfileContext.new(self, auth_profile_id)
46
+ end
47
+ end
48
+ ##
49
+ # @return [Twilio::REST::Webhooks::V1::EdgeZoneList]
50
+ def edge_zones
51
+ @edge_zones ||= EdgeZoneList.new self
52
+ end
53
+ ##
54
+ # @param [String] operation_id
55
+ # @return [Twilio::REST::Webhooks::V1::OperationContext] if operationId was passed.
56
+ # @return [Twilio::REST::Webhooks::V1::OperationList]
57
+ def operations(operation_id=:unset)
58
+ if operation_id.nil?
59
+ raise ArgumentError, 'operation_id cannot be nil'
60
+ end
61
+
62
+ if operation_id == :unset
63
+ @operations ||= OperationList.new self
64
+ else
65
+ OperationContext.new(self, operation_id)
66
+ end
67
+ end
68
+ ##
69
+ # @param [String] rule_id
70
+ # @return [Twilio::REST::Webhooks::V1::RuleContext] if ruleId was passed.
71
+ # @return [Twilio::REST::Webhooks::V1::RuleList]
72
+ def rules(rule_id=:unset)
73
+ if rule_id.nil?
74
+ raise ArgumentError, 'rule_id cannot be nil'
75
+ end
76
+
77
+ if rule_id == :unset
78
+ @rules ||= RuleList.new self
79
+ else
80
+ RuleContext.new(self, rule_id)
81
+ end
82
+ end
83
+ ##
84
+ # @param [String] setting_id
85
+ # @return [Twilio::REST::Webhooks::V1::SettingContext] if settingId was passed.
86
+ # @return [Twilio::REST::Webhooks::V1::SettingList]
87
+ def settings(setting_id=:unset)
88
+ if setting_id.nil?
89
+ raise ArgumentError, 'setting_id cannot be nil'
90
+ end
91
+
92
+ if setting_id == :unset
93
+ @settings ||= SettingList.new self
94
+ else
95
+ SettingContext.new(self, setting_id)
96
+ end
97
+ end
98
+ ##
99
+ # @param [String] shared_key_id
100
+ # @return [Twilio::REST::Webhooks::V1::SharedKeyContext] if sharedKeyId was passed.
101
+ # @return [Twilio::REST::Webhooks::V1::SharedKeyList]
102
+ def shared_keys(shared_key_id=:unset)
103
+ if shared_key_id.nil?
104
+ raise ArgumentError, 'shared_key_id cannot be nil'
105
+ end
106
+
107
+ if shared_key_id == :unset
108
+ @shared_keys ||= SharedKeyList.new self
109
+ else
110
+ SharedKeyContext.new(self, shared_key_id)
111
+ end
112
+ end
113
+ ##
114
+ # @return [Twilio::REST::Webhooks::V1::TestList]
115
+ def tests
116
+ @tests ||= TestList.new self
117
+ end
118
+ ##
119
+ # Provide a user friendly representation
120
+ def to_s
121
+ '<Twilio::REST::Webhooks::V1>';
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,6 @@
1
+ module Twilio
2
+ module REST
3
+ class Webhooks < WebhooksBase;
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,38 @@
1
+ ##
2
+ # This code was generated by
3
+ # ___ _ _ _ _ _ _ ____ ____ ____ _ ____ ____ _ _ ____ ____ ____ ___ __ __
4
+ # | | | | | | | | | __ | | |__| | __ | __ |___ |\ | |___ |__/ |__| | | | |__/
5
+ # | |_|_| | |___ | |__| |__| | | | |__] |___ | \| |___ | \ | | | |__| | \
6
+ #
7
+ # NOTE: This class is auto generated by OpenAPI Generator.
8
+ # https://openapi-generator.tech
9
+ # Do not edit the class manually.
10
+ # frozen_string_literal: true
11
+ module Twilio
12
+ module REST
13
+ class WebhooksBase < Domain
14
+ ##
15
+ # Initialize webhooks domain
16
+ #
17
+ # @param twilio - The twilio client
18
+ #
19
+ def initialize(twilio)
20
+ super(twilio)
21
+ @base_url = "https://webhooks.twilio.com"
22
+ @host = "webhooks.twilio.com"
23
+ @port = 443
24
+ @v1 = nil
25
+ end
26
+
27
+ def v1
28
+ @v1 ||= Webhooks::V1.new self
29
+ end
30
+
31
+ ##
32
+ # Provide a user friendly representation
33
+ def to_s
34
+ '<Twilio::REST::Webhooks::V1>';
35
+ end
36
+ end
37
+ end
38
+ end
@@ -3,11 +3,35 @@
3
3
  module Twilio
4
4
  module Security
5
5
  class RequestValidator
6
+ # Header that carries the webhook signature
7
+ SIGNATURE_HEADER = 'X-Twilio-Signature'
8
+ # Header Twilio adds to webhooks signed with a SharedKey: key=<sharedKeyId>,algorithm=<algorithm>
9
+ SIGNATURE_SETTINGS_HEADER = 'X-Twilio-Webhooks-Signature-Settings'
10
+ HMAC_SHA1 = 'HMAC_SHA1'
11
+ HMAC_SHA256 = 'HMAC_SHA256'
12
+ DIGESTS = { HMAC_SHA1 => 'sha1', HMAC_SHA256 => 'sha256' }.freeze
13
+
14
+ ##
15
+ # Returns the signing algorithm named in the X-Twilio-Webhooks-Signature-Settings header. A missing or
16
+ # empty header (or one without +algorithm=+) means the legacy Auth Token signature, HMAC_SHA1.
17
+ #
18
+ # @param [String] signature_settings_header e.g. "key=webhooks_sharedkey_...,algorithm=HMAC_SHA256"
19
+ #
20
+ # @return [String] the algorithm name
21
+ def self.signature_algorithm(signature_settings_header)
22
+ signature_settings_header.to_s.split(',').each do |part|
23
+ name, value = part.split('=', 2).map(&:strip)
24
+ return value if name == 'algorithm' && !value.to_s.empty?
25
+ end
26
+ HMAC_SHA1
27
+ end
28
+
6
29
  ##
7
30
  # Initialize a Request Validator. auth_token will either be grabbed from the global Twilio object or you can
8
31
  # pass it in here.
9
32
  #
10
- # @param [String] auth_token Your account auth token, used to sign requests
33
+ # @param [String] auth_token The secret the webhook was signed with: your account auth token, or the
34
+ # SharedKey secret when the request carries the X-Twilio-Webhooks-Signature-Settings header
11
35
  def initialize(auth_token = nil)
12
36
  @auth_token = auth_token || Twilio.auth_token
13
37
  raise ArgumentError, 'Auth token is required' if @auth_token.nil?
@@ -22,9 +46,17 @@ module Twilio
22
46
  # a bodySHA256 parameter in the query string, this parameter can instead be the POST body as a string to
23
47
  # validate JSON or other text-based payloads that aren't x-www-form-urlencoded.
24
48
  # @param [String] signature The expected signature, from the X-Twilio-Signature header of the request
49
+ # @param [String] algorithm HMAC_SHA1 (default) or HMAC_SHA256, see {.signature_algorithm}. An unsupported
50
+ # algorithm fails validation and logs a warning.
25
51
  #
26
52
  # @return [Boolean] whether or not the computed signature matches the signature parameter
27
- def validate(url, params, signature)
53
+ def validate(url, params, signature, algorithm = nil)
54
+ unless digest_name_for(algorithm)
55
+ warn "[Twilio] Unsupported webhook signature algorithm '#{algorithm}'. " \
56
+ "Supported: #{HMAC_SHA1}, #{HMAC_SHA256}. Upgrade twilio-ruby if Twilio added a new one."
57
+ return false
58
+ end
59
+
28
60
  parsed_url = URI(url)
29
61
  url_with_port = add_port(parsed_url)
30
62
  url_without_port = remove_port(parsed_url)
@@ -40,8 +72,10 @@ module Twilio
40
72
 
41
73
  # Check signature of the url with and without port numbers
42
74
  # since signature generation on the back end is inconsistent
43
- valid_signature_with_port = secure_compare(build_signature_for(url_with_port, params_hash), signature)
44
- valid_signature_without_port = secure_compare(build_signature_for(url_without_port, params_hash), signature)
75
+ valid_signature_with_port = secure_compare(build_signature_for(url_with_port, params_hash, algorithm),
76
+ signature)
77
+ valid_signature_without_port = secure_compare(build_signature_for(url_without_port, params_hash, algorithm),
78
+ signature)
45
79
 
46
80
  valid_body && (valid_signature_with_port || valid_signature_without_port)
47
81
  end
@@ -58,20 +92,32 @@ module Twilio
58
92
  end
59
93
 
60
94
  ##
61
- # Build a SHA1-HMAC signature for a url and parameter hash
95
+ # Build an HMAC signature for a url and parameter hash
62
96
  #
63
97
  # @param [String] url The request url, including any query parameters
64
98
  # @param [#join] params The POST parameters
99
+ # @param [String] algorithm HMAC_SHA1 (default) or HMAC_SHA256
65
100
  #
66
- # @return [String] A base64 encoded SHA1-HMAC
67
- def build_signature_for(url, params)
101
+ # @return [String] A base64 encoded HMAC
102
+ # @raise [ArgumentError] if the algorithm is not supported
103
+ def build_signature_for(url, params, algorithm = nil)
104
+ digest_name = digest_name_for(algorithm)
105
+ raise ArgumentError, "Unsupported webhook signature algorithm: #{algorithm}" unless digest_name
106
+
68
107
  data = url + params.sort.join
69
- digest = OpenSSL::Digest.new('sha1')
108
+ digest = OpenSSL::Digest.new(digest_name)
70
109
  Base64.strict_encode64(OpenSSL::HMAC.digest(digest, @auth_token, data))
71
110
  end
72
111
 
73
112
  private
74
113
 
114
+ # Maps an algorithm name to an OpenSSL digest name, or nil when unsupported. nil or empty means HMAC_SHA1.
115
+ def digest_name_for(algorithm)
116
+ return DIGESTS[HMAC_SHA1] if algorithm.nil? || algorithm.to_s.empty?
117
+
118
+ DIGESTS[algorithm.to_s.upcase]
119
+ end
120
+
75
121
  # Compares two strings in constant time to avoid timing attacks.
76
122
  # Borrowed from ActiveSupport::MessageVerifier.
77
123
  # https://github.com/rails/rails/blob/master/activesupport/lib/active_support/message_verifier.rb
@@ -2118,9 +2118,20 @@ module Twilio
2118
2118
  # deepgramSmartFormat:: This parameter enables Deepgram's smart formatting feature, which automatically applies punctuation, capitalization, and formatting (e.g. numbers, dates, currency) to transcripts
2119
2119
  # ignoreBackchannel:: This parameter brief caller acknowledgments (e.g. "yeah", "uh-huh") are ignored and will not interrupt the agent while it is speaking.
2120
2120
  # events:: This parameter allows you to enable event subscriptions
2121
- # keyword_args:: additional attributes
2122
- def conversation_relay(url: nil, language: nil, tts_language: nil, transcription_language: nil, tts_provider: nil, voice: nil, transcription_provider: nil, speech_model: nil, profanity_filter: nil, dtmf_detection: nil, welcome_greeting: nil, partial_prompts: nil, welcome_greeting_interruptible: nil, interruptible: nil, preemptible: nil, hints: nil, intelligence_service: nil, report_input_during_agent_speech: nil, elevenlabs_text_normalization: nil, interrupt_sensitivity: nil, debug: nil, backgroundNoiseReduction: nil, speechTimeout: nil, deepgramSmartFormat: nil, ignoreBackchannel: nil, events: nil, **keyword_args)
2123
- conversation_relay = ConversationRelay.new(url: url, language: language, tts_language: tts_language, transcription_language: transcription_language, tts_provider: tts_provider, voice: voice, transcription_provider: transcription_provider, speech_model: speech_model, profanity_filter: profanity_filter, dtmf_detection: dtmf_detection, welcome_greeting: welcome_greeting, partial_prompts: partial_prompts, welcome_greeting_interruptible: welcome_greeting_interruptible, interruptible: interruptible, preemptible: preemptible, hints: hints, intelligence_service: intelligence_service, report_input_during_agent_speech: report_input_during_agent_speech, elevenlabs_text_normalization: elevenlabs_text_normalization, interrupt_sensitivity: interrupt_sensitivity, debug: debug, backgroundNoiseReduction: backgroundNoiseReduction, speechTimeout: speechTimeout, deepgramSmartFormat: deepgramSmartFormat, ignoreBackchannel: ignoreBackchannel, events: events, **keyword_args)
2121
+ # partial_prompt_on_hangup:: Whether the in-progress partial transcript should be reported as a prompt when the call hangs up
2122
+ # eager_eot_threshold:: Eager end-of-turn confidence threshold, which fires before the end-of-turn threshold. The value can be between 0.3 and 0.9
2123
+ # asr_smart_format:: Whether smart formatting should be applied to transcripts. Takes precedence over deepgramSmartFormat
2124
+ # tts_text_normalization:: Text normalization for text-to-speech. The value can be auto, on, or off. Takes precedence over elevenlabsTextNormalization
2125
+ # tts_language_text_normalization:: Whether language-specific text normalization should be applied for text-to-speech
2126
+ # elevenlabs_language_text_normalization:: Legacy alias of ttsLanguageTextNormalization
2127
+ # include_in_prompt:: Extra fields to be included in prompt messages. The value can be turn-state or prompt-segments
2128
+ # customer_name:: Customer name sent to Conversations and Conversational Intelligence. Defaults to the caller ID
2129
+ # application_reconnect:: Whether the WebSocket connection to the application should be reconnected if it drops during the call. Defaults to false
2130
+ # echo_prompt_filtering:: Whether transcripts that echo the agent's own text-to-speech should be dropped. Defaults to false
2131
+ # turn_detection:: Whether turn detection should be used to decide when the caller has finished speaking. Defaults to false
2132
+ # keyword_args:: additional attributes
2133
+ def conversation_relay(url: nil, language: nil, tts_language: nil, transcription_language: nil, tts_provider: nil, voice: nil, transcription_provider: nil, speech_model: nil, profanity_filter: nil, dtmf_detection: nil, welcome_greeting: nil, partial_prompts: nil, welcome_greeting_interruptible: nil, interruptible: nil, preemptible: nil, hints: nil, intelligence_service: nil, report_input_during_agent_speech: nil, elevenlabs_text_normalization: nil, interrupt_sensitivity: nil, debug: nil, backgroundNoiseReduction: nil, speechTimeout: nil, deepgramSmartFormat: nil, ignoreBackchannel: nil, events: nil, partial_prompt_on_hangup: nil, eager_eot_threshold: nil, asr_smart_format: nil, tts_text_normalization: nil, tts_language_text_normalization: nil, elevenlabs_language_text_normalization: nil, include_in_prompt: nil, customer_name: nil, application_reconnect: nil, echo_prompt_filtering: nil, turn_detection: nil, **keyword_args)
2134
+ conversation_relay = ConversationRelay.new(url: url, language: language, tts_language: tts_language, transcription_language: transcription_language, tts_provider: tts_provider, voice: voice, transcription_provider: transcription_provider, speech_model: speech_model, profanity_filter: profanity_filter, dtmf_detection: dtmf_detection, welcome_greeting: welcome_greeting, partial_prompts: partial_prompts, welcome_greeting_interruptible: welcome_greeting_interruptible, interruptible: interruptible, preemptible: preemptible, hints: hints, intelligence_service: intelligence_service, report_input_during_agent_speech: report_input_during_agent_speech, elevenlabs_text_normalization: elevenlabs_text_normalization, interrupt_sensitivity: interrupt_sensitivity, debug: debug, backgroundNoiseReduction: backgroundNoiseReduction, speechTimeout: speechTimeout, deepgramSmartFormat: deepgramSmartFormat, ignoreBackchannel: ignoreBackchannel, events: events, partial_prompt_on_hangup: partial_prompt_on_hangup, eager_eot_threshold: eager_eot_threshold, asr_smart_format: asr_smart_format, tts_text_normalization: tts_text_normalization, tts_language_text_normalization: tts_language_text_normalization, elevenlabs_language_text_normalization: elevenlabs_language_text_normalization, include_in_prompt: include_in_prompt, customer_name: customer_name, application_reconnect: application_reconnect, echo_prompt_filtering: echo_prompt_filtering, turn_detection: turn_detection, **keyword_args)
2124
2135
 
2125
2136
  yield(conversation_relay) if block_given?
2126
2137
  append(conversation_relay)
@@ -2184,9 +2195,13 @@ module Twilio
2184
2195
  # voice:: Voice to be used for text-to-speech of this language
2185
2196
  # transcription_provider:: Provider to be used for transcription of this language
2186
2197
  # speech_model:: Speech model to be used for transcription of this language
2198
+ # hints:: Phrases to help better accuracy in speech recognition of this language
2199
+ # asr_smart_format:: Whether smart formatting should be applied to transcripts of this language
2200
+ # tts_text_normalization:: Text normalization for text-to-speech of this language. The value can be auto, on, or off
2201
+ # tts_language_text_normalization:: Whether language-specific text normalization should be applied for text-to-speech of this language
2187
2202
  # keyword_args:: additional attributes
2188
- def language(code: nil, tts_provider: nil, voice: nil, transcription_provider: nil, speech_model: nil, **keyword_args)
2189
- append(Language.new(code: code, tts_provider: tts_provider, voice: voice, transcription_provider: transcription_provider, speech_model: speech_model, **keyword_args))
2203
+ def language(code: nil, tts_provider: nil, voice: nil, transcription_provider: nil, speech_model: nil, hints: nil, asr_smart_format: nil, tts_text_normalization: nil, tts_language_text_normalization: nil, **keyword_args)
2204
+ append(Language.new(code: code, tts_provider: tts_provider, voice: voice, transcription_provider: transcription_provider, speech_model: speech_model, hints: hints, asr_smart_format: asr_smart_format, tts_text_normalization: tts_text_normalization, tts_language_text_normalization: tts_language_text_normalization, **keyword_args))
2190
2205
  end
2191
2206
 
2192
2207
  ##
@@ -1,3 +1,3 @@
1
1
  module Twilio
2
- VERSION = '7.11.3'
2
+ VERSION = '7.13.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twilio-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.11.3
4
+ version: 7.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Twilio API Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-28 00:00:00.000000000 Z
11
+ date: 2026-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
@@ -223,6 +223,7 @@ files:
223
223
  - cluster/cluster_oauth_spec.rb
224
224
  - cluster/cluster_orgs_spec.rb
225
225
  - cluster/cluster_spec.rb
226
+ - examples/WebhookSignatureValidation.md
226
227
  - examples/examples.rb
227
228
  - examples/print_call_log.rb
228
229
  - examples/public_oauth.rb
@@ -519,8 +520,8 @@ files:
519
520
  - lib/twilio-ruby/rest/insights/v2/outbound_report.rb
520
521
  - lib/twilio-ruby/rest/insights/v2/report.rb
521
522
  - lib/twilio-ruby/rest/insights/v3.rb
522
- - lib/twilio-ruby/rest/insights/v3/capacity.rb
523
523
  - lib/twilio-ruby/rest/insights/v3/custom_field_mapping.rb
524
+ - lib/twilio-ruby/rest/insights/v3/custom_field_mappings_capacity.rb
524
525
  - lib/twilio-ruby/rest/insights/v3/metadata.rb
525
526
  - lib/twilio-ruby/rest/insights/v3/query.rb
526
527
  - lib/twilio-ruby/rest/insights/v3/query_job.rb
@@ -684,7 +685,6 @@ files:
684
685
  - lib/twilio-ruby/rest/numbers/v1/sms_verification.rb
685
686
  - lib/twilio-ruby/rest/numbers/v1/sms_verification_check.rb
686
687
  - lib/twilio-ruby/rest/numbers/v1/voice_verification.rb
687
- - lib/twilio-ruby/rest/numbers/v1/voice_verification_check.rb
688
688
  - lib/twilio-ruby/rest/numbers/v1/webhook.rb
689
689
  - lib/twilio-ruby/rest/numbers/v2.rb
690
690
  - lib/twilio-ruby/rest/numbers/v2/application.rb
@@ -713,7 +713,6 @@ files:
713
713
  - lib/twilio-ruby/rest/oauth/v1/token.rb
714
714
  - lib/twilio-ruby/rest/oauth/v2.rb
715
715
  - lib/twilio-ruby/rest/oauth/v2/authorize.rb
716
- - lib/twilio-ruby/rest/oauth/v2/oauth_authorization_server.rb
717
716
  - lib/twilio-ruby/rest/oauth/v2/token.rb
718
717
  - lib/twilio-ruby/rest/oauth_base.rb
719
718
  - lib/twilio-ruby/rest/preview.rb
@@ -773,6 +772,7 @@ files:
773
772
  - lib/twilio-ruby/rest/routes/v2/sip_domain.rb
774
773
  - lib/twilio-ruby/rest/routes/v2/trunk.rb
775
774
  - lib/twilio-ruby/rest/routes/v3.rb
775
+ - lib/twilio-ruby/rest/routes/v3/iso_country_code.rb
776
776
  - lib/twilio-ruby/rest/routes/v3/phone_number.rb
777
777
  - lib/twilio-ruby/rest/routes_base.rb
778
778
  - lib/twilio-ruby/rest/serverless.rb
@@ -969,6 +969,16 @@ files:
969
969
  - lib/twilio-ruby/rest/voice/v3.rb
970
970
  - lib/twilio-ruby/rest/voice/v3/transcription.rb
971
971
  - lib/twilio-ruby/rest/voice_base.rb
972
+ - lib/twilio-ruby/rest/webhooks.rb
973
+ - lib/twilio-ruby/rest/webhooks/v1.rb
974
+ - lib/twilio-ruby/rest/webhooks/v1/auth_profile.rb
975
+ - lib/twilio-ruby/rest/webhooks/v1/edge_zone.rb
976
+ - lib/twilio-ruby/rest/webhooks/v1/operation.rb
977
+ - lib/twilio-ruby/rest/webhooks/v1/rule.rb
978
+ - lib/twilio-ruby/rest/webhooks/v1/setting.rb
979
+ - lib/twilio-ruby/rest/webhooks/v1/shared_key.rb
980
+ - lib/twilio-ruby/rest/webhooks/v1/test.rb
981
+ - lib/twilio-ruby/rest/webhooks_base.rb
972
982
  - lib/twilio-ruby/rest/wireless.rb
973
983
  - lib/twilio-ruby/rest/wireless/v1.rb
974
984
  - lib/twilio-ruby/rest/wireless/v1/command.rb