late-sdk 0.0.725 → 0.0.727
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.
- checksums.yaml +4 -4
- data/README.md +20 -0
- data/docs/AttachNumberToSipTrunk200Response.md +22 -0
- data/docs/AttachNumberToSipTrunkRequest.md +18 -0
- data/docs/CreateSipTrunk201Response.md +34 -0
- data/docs/CreateSipTrunk201ResponseTermination.md +20 -0
- data/docs/CreateSipTrunkRequest.md +24 -0
- data/docs/DetachNumberFromSipTrunk200Response.md +20 -0
- data/docs/GetPhoneNumber200ResponsePhoneNumber.md +3 -1
- data/docs/GetSipTrunk200Response.md +34 -0
- data/docs/GetSipTrunk200ResponseNumbersInner.md +20 -0
- data/docs/ListPhoneNumbers200ResponseNumbersInner.md +2 -0
- data/docs/ListSipTrunks200Response.md +20 -0
- data/docs/ListSipTrunks200ResponseTrunksInner.md +32 -0
- data/docs/ListSipTrunks200ResponseTrunksInnerTermination.md +20 -0
- data/docs/MessagesApi.md +1 -1
- data/docs/RotateSipTrunkCredentials200Response.md +20 -0
- data/docs/SendInboxMessage200ResponseData.md +4 -6
- data/docs/SendInboxMessage200ResponseDataAttachmentsInner.md +20 -0
- data/docs/VoiceApi.md +485 -0
- data/lib/zernio-sdk/api/messages_api.rb +2 -2
- data/lib/zernio-sdk/api/voice_api.rb +447 -0
- data/lib/zernio-sdk/models/attach_number_to_sip_trunk200_response.rb +165 -0
- data/lib/zernio-sdk/models/attach_number_to_sip_trunk_request.rb +165 -0
- data/lib/zernio-sdk/models/create_sip_trunk201_response.rb +255 -0
- data/lib/zernio-sdk/models/create_sip_trunk201_response_termination.rb +158 -0
- data/lib/zernio-sdk/models/create_sip_trunk_request.rb +283 -0
- data/lib/zernio-sdk/models/detach_number_from_sip_trunk200_response.rb +157 -0
- data/lib/zernio-sdk/models/get_phone_number200_response_phone_number.rb +15 -4
- data/lib/zernio-sdk/models/get_sip_trunk200_response.rb +256 -0
- data/lib/zernio-sdk/models/get_sip_trunk200_response_numbers_inner.rb +157 -0
- data/lib/zernio-sdk/models/list_phone_numbers200_response_numbers_inner.rb +12 -1
- data/lib/zernio-sdk/models/list_sip_trunks200_response.rb +159 -0
- data/lib/zernio-sdk/models/list_sip_trunks200_response_trunks_inner.rb +245 -0
- data/lib/zernio-sdk/models/list_sip_trunks200_response_trunks_inner_termination.rb +156 -0
- data/lib/zernio-sdk/models/rotate_sip_trunk_credentials200_response.rb +156 -0
- data/lib/zernio-sdk/models/send_inbox_message200_response_data.rb +12 -23
- data/lib/zernio-sdk/models/send_inbox_message200_response_data_attachments_inner.rb +156 -0
- data/lib/zernio-sdk/version.rb +1 -1
- data/lib/zernio-sdk.rb +13 -0
- data/openapi.yaml +293 -4
- data/spec/api/messages_api_spec.rb +1 -1
- data/spec/api/voice_api_spec.rb +82 -0
- data/spec/models/attach_number_to_sip_trunk200_response_spec.rb +48 -0
- data/spec/models/attach_number_to_sip_trunk_request_spec.rb +36 -0
- data/spec/models/create_sip_trunk201_response_spec.rb +88 -0
- data/spec/models/create_sip_trunk201_response_termination_spec.rb +42 -0
- data/spec/models/create_sip_trunk_request_spec.rb +58 -0
- data/spec/models/detach_number_from_sip_trunk200_response_spec.rb +42 -0
- data/spec/models/get_phone_number200_response_phone_number_spec.rb +6 -0
- data/spec/models/get_sip_trunk200_response_numbers_inner_spec.rb +42 -0
- data/spec/models/get_sip_trunk200_response_spec.rb +88 -0
- data/spec/models/list_phone_numbers200_response_numbers_inner_spec.rb +6 -0
- data/spec/models/list_sip_trunks200_response_spec.rb +42 -0
- data/spec/models/list_sip_trunks200_response_trunks_inner_spec.rb +82 -0
- data/spec/models/list_sip_trunks200_response_trunks_inner_termination_spec.rb +42 -0
- data/spec/models/rotate_sip_trunk_credentials200_response_spec.rb +42 -0
- data/spec/models/send_inbox_message200_response_data_attachments_inner_spec.rb +42 -0
- data/spec/models/send_inbox_message200_response_data_spec.rb +1 -7
- data/zernio-sdk-0.0.727.gem +0 -0
- metadata +55 -3
- data/zernio-sdk-0.0.725.gem +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
#Zernio API
|
|
3
|
+
|
|
4
|
+
#API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api
|
|
5
|
+
|
|
6
|
+
The version of the OpenAPI document: 1.0.4
|
|
7
|
+
Contact: support@zernio.com
|
|
8
|
+
Generated by: https://openapi-generator.tech
|
|
9
|
+
Generator version: 7.19.0
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
require 'date'
|
|
14
|
+
require 'time'
|
|
15
|
+
|
|
16
|
+
module Zernio
|
|
17
|
+
class SendInboxMessage200ResponseDataAttachmentsInner < ApiModelBase
|
|
18
|
+
attr_accessor :type
|
|
19
|
+
|
|
20
|
+
attr_accessor :url
|
|
21
|
+
|
|
22
|
+
# Attribute mapping from ruby-style variable name to JSON key.
|
|
23
|
+
def self.attribute_map
|
|
24
|
+
{
|
|
25
|
+
:'type' => :'type',
|
|
26
|
+
:'url' => :'url'
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns attribute mapping this model knows about
|
|
31
|
+
def self.acceptable_attribute_map
|
|
32
|
+
attribute_map
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Returns all the JSON keys this model knows about
|
|
36
|
+
def self.acceptable_attributes
|
|
37
|
+
acceptable_attribute_map.values
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Attribute type mapping.
|
|
41
|
+
def self.openapi_types
|
|
42
|
+
{
|
|
43
|
+
:'type' => :'String',
|
|
44
|
+
:'url' => :'String'
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# List of attributes with nullable: true
|
|
49
|
+
def self.openapi_nullable
|
|
50
|
+
Set.new([
|
|
51
|
+
])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Initializes the object
|
|
55
|
+
# @param [Hash] attributes Model attributes in the form of hash
|
|
56
|
+
def initialize(attributes = {})
|
|
57
|
+
if (!attributes.is_a?(Hash))
|
|
58
|
+
fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::SendInboxMessage200ResponseDataAttachmentsInner` initialize method"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# check to see if the attribute exists and convert string to symbol for hash key
|
|
62
|
+
acceptable_attribute_map = self.class.acceptable_attribute_map
|
|
63
|
+
attributes = attributes.each_with_object({}) { |(k, v), h|
|
|
64
|
+
if (!acceptable_attribute_map.key?(k.to_sym))
|
|
65
|
+
fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::SendInboxMessage200ResponseDataAttachmentsInner`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
|
|
66
|
+
end
|
|
67
|
+
h[k.to_sym] = v
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if attributes.key?(:'type')
|
|
71
|
+
self.type = attributes[:'type']
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if attributes.key?(:'url')
|
|
75
|
+
self.url = attributes[:'url']
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Show invalid properties with the reasons. Usually used together with valid?
|
|
80
|
+
# @return Array for valid properties with the reasons
|
|
81
|
+
def list_invalid_properties
|
|
82
|
+
warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
|
|
83
|
+
invalid_properties = Array.new
|
|
84
|
+
invalid_properties
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Check to see if the all the properties in the model are valid
|
|
88
|
+
# @return true if the model is valid
|
|
89
|
+
def valid?
|
|
90
|
+
warn '[DEPRECATED] the `valid?` method is obsolete'
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Checks equality by comparing each attribute.
|
|
95
|
+
# @param [Object] Object to be compared
|
|
96
|
+
def ==(o)
|
|
97
|
+
return true if self.equal?(o)
|
|
98
|
+
self.class == o.class &&
|
|
99
|
+
type == o.type &&
|
|
100
|
+
url == o.url
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @see the `==` method
|
|
104
|
+
# @param [Object] Object to be compared
|
|
105
|
+
def eql?(o)
|
|
106
|
+
self == o
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Calculates hash code according to all attributes.
|
|
110
|
+
# @return [Integer] Hash code
|
|
111
|
+
def hash
|
|
112
|
+
[type, url].hash
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Builds the object from hash
|
|
116
|
+
# @param [Hash] attributes Model attributes in the form of hash
|
|
117
|
+
# @return [Object] Returns the model itself
|
|
118
|
+
def self.build_from_hash(attributes)
|
|
119
|
+
return nil unless attributes.is_a?(Hash)
|
|
120
|
+
attributes = attributes.transform_keys(&:to_sym)
|
|
121
|
+
transformed_hash = {}
|
|
122
|
+
openapi_types.each_pair do |key, type|
|
|
123
|
+
if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
|
|
124
|
+
transformed_hash["#{key}"] = nil
|
|
125
|
+
elsif type =~ /\AArray<(.*)>/i
|
|
126
|
+
# check to ensure the input is an array given that the attribute
|
|
127
|
+
# is documented as an array but the input is not
|
|
128
|
+
if attributes[attribute_map[key]].is_a?(Array)
|
|
129
|
+
transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
|
|
130
|
+
end
|
|
131
|
+
elsif !attributes[attribute_map[key]].nil?
|
|
132
|
+
transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
new(transformed_hash)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Returns the object in the form of hash
|
|
139
|
+
# @return [Hash] Returns the object in the form of hash
|
|
140
|
+
def to_hash
|
|
141
|
+
hash = {}
|
|
142
|
+
self.class.attribute_map.each_pair do |attr, param|
|
|
143
|
+
value = self.send(attr)
|
|
144
|
+
if value.nil?
|
|
145
|
+
is_nullable = self.class.openapi_nullable.include?(attr)
|
|
146
|
+
next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
hash[param] = _to_hash(value)
|
|
150
|
+
end
|
|
151
|
+
hash
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
end
|
data/lib/zernio-sdk/version.rb
CHANGED
data/lib/zernio-sdk.rb
CHANGED
|
@@ -86,6 +86,8 @@ require 'zernio-sdk/models/archive_lead_form200_response'
|
|
|
86
86
|
require 'zernio-sdk/models/assign_google_business_location200_response'
|
|
87
87
|
require 'zernio-sdk/models/assign_google_business_location200_response_account'
|
|
88
88
|
require 'zernio-sdk/models/assign_google_business_location_request'
|
|
89
|
+
require 'zernio-sdk/models/attach_number_to_sip_trunk200_response'
|
|
90
|
+
require 'zernio-sdk/models/attach_number_to_sip_trunk_request'
|
|
89
91
|
require 'zernio-sdk/models/batch_get_google_business_reviews200_response'
|
|
90
92
|
require 'zernio-sdk/models/batch_get_google_business_reviews200_response_location_reviews_inner'
|
|
91
93
|
require 'zernio-sdk/models/batch_get_google_business_reviews_request'
|
|
@@ -287,6 +289,9 @@ require 'zernio-sdk/models/create_sequence_request'
|
|
|
287
289
|
require 'zernio-sdk/models/create_sequence_request_steps_inner'
|
|
288
290
|
require 'zernio-sdk/models/create_sequence_request_steps_inner_template'
|
|
289
291
|
require 'zernio-sdk/models/create_sequence_request_steps_inner_template_variable_mapping_value'
|
|
292
|
+
require 'zernio-sdk/models/create_sip_trunk201_response'
|
|
293
|
+
require 'zernio-sdk/models/create_sip_trunk201_response_termination'
|
|
294
|
+
require 'zernio-sdk/models/create_sip_trunk_request'
|
|
290
295
|
require 'zernio-sdk/models/create_sms_sender_id200_response'
|
|
291
296
|
require 'zernio-sdk/models/create_sms_sender_id_request'
|
|
292
297
|
require 'zernio-sdk/models/create_standalone_ad200_response'
|
|
@@ -374,6 +379,7 @@ require 'zernio-sdk/models/delete_inbox_review_reply_request'
|
|
|
374
379
|
require 'zernio-sdk/models/delete_sms_sender_id200_response'
|
|
375
380
|
require 'zernio-sdk/models/delete_value_rule_set200_response'
|
|
376
381
|
require 'zernio-sdk/models/delete_whatsapp_business_username_request'
|
|
382
|
+
require 'zernio-sdk/models/detach_number_from_sip_trunk200_response'
|
|
377
383
|
require 'zernio-sdk/models/dial_voice_web_call200_response'
|
|
378
384
|
require 'zernio-sdk/models/dial_voice_web_call_request'
|
|
379
385
|
require 'zernio-sdk/models/disable_sms_on_number200_response'
|
|
@@ -697,6 +703,8 @@ require 'zernio-sdk/models/get_sequence200_response'
|
|
|
697
703
|
require 'zernio-sdk/models/get_sequence200_response_sequence'
|
|
698
704
|
require 'zernio-sdk/models/get_sequence200_response_sequence_steps_inner'
|
|
699
705
|
require 'zernio-sdk/models/get_sequence200_response_sequence_steps_inner_template'
|
|
706
|
+
require 'zernio-sdk/models/get_sip_trunk200_response'
|
|
707
|
+
require 'zernio-sdk/models/get_sip_trunk200_response_numbers_inner'
|
|
700
708
|
require 'zernio-sdk/models/get_slack_settings200_response'
|
|
701
709
|
require 'zernio-sdk/models/get_slack_settings200_response_account'
|
|
702
710
|
require 'zernio-sdk/models/get_sms_registration200_response'
|
|
@@ -986,6 +994,9 @@ require 'zernio-sdk/models/list_sequence_enrollments200_response'
|
|
|
986
994
|
require 'zernio-sdk/models/list_sequence_enrollments200_response_enrollments_inner'
|
|
987
995
|
require 'zernio-sdk/models/list_sequences200_response'
|
|
988
996
|
require 'zernio-sdk/models/list_sequences200_response_sequences_inner'
|
|
997
|
+
require 'zernio-sdk/models/list_sip_trunks200_response'
|
|
998
|
+
require 'zernio-sdk/models/list_sip_trunks200_response_trunks_inner'
|
|
999
|
+
require 'zernio-sdk/models/list_sip_trunks200_response_trunks_inner_termination'
|
|
989
1000
|
require 'zernio-sdk/models/list_slack_members200_response'
|
|
990
1001
|
require 'zernio-sdk/models/list_slack_members200_response_members_inner'
|
|
991
1002
|
require 'zernio-sdk/models/list_sms_opt_outs200_response'
|
|
@@ -1174,6 +1185,7 @@ require 'zernio-sdk/models/review_webhook_review_reply'
|
|
|
1174
1185
|
require 'zernio-sdk/models/review_webhook_review_reviewer'
|
|
1175
1186
|
require 'zernio-sdk/models/revoke_connected_app200_response'
|
|
1176
1187
|
require 'zernio-sdk/models/rf_prediction'
|
|
1188
|
+
require 'zernio-sdk/models/rotate_sip_trunk_credentials200_response'
|
|
1177
1189
|
require 'zernio-sdk/models/saved_targeting_audience'
|
|
1178
1190
|
require 'zernio-sdk/models/schedule_broadcast200_response'
|
|
1179
1191
|
require 'zernio-sdk/models/schedule_broadcast200_response_broadcast'
|
|
@@ -1237,6 +1249,7 @@ require 'zernio-sdk/models/send_discord_direct_message_request'
|
|
|
1237
1249
|
require 'zernio-sdk/models/send_discord_direct_message_request_attachments_inner'
|
|
1238
1250
|
require 'zernio-sdk/models/send_inbox_message200_response'
|
|
1239
1251
|
require 'zernio-sdk/models/send_inbox_message200_response_data'
|
|
1252
|
+
require 'zernio-sdk/models/send_inbox_message200_response_data_attachments_inner'
|
|
1240
1253
|
require 'zernio-sdk/models/send_inbox_message400_response'
|
|
1241
1254
|
require 'zernio-sdk/models/send_inbox_message400_response_platform_error'
|
|
1242
1255
|
require 'zernio-sdk/models/send_inbox_message_request'
|
data/openapi.yaml
CHANGED
|
@@ -25894,6 +25894,17 @@ paths:
|
|
|
25894
25894
|
instead of sending the message a second time; same key + different body
|
|
25895
25895
|
returns 422; a key still in flight returns 409. Works for JSON and
|
|
25896
25896
|
multipart (file upload) requests alike. Keys are retained for 24 hours.
|
|
25897
|
+
|
|
25898
|
+
Only successful (2xx) responses are stored for replay: if the request
|
|
25899
|
+
throws or returns a non-2xx status, the key is released so the same key
|
|
25900
|
+
can be retried once the problem is fixed. The header therefore protects
|
|
25901
|
+
the "request succeeded but the response was lost" case. For an ambiguous
|
|
25902
|
+
failure (a 5xx or a network timeout), reconcile before retrying: a
|
|
25903
|
+
failure after the platform already accepted the message also releases
|
|
25904
|
+
the key, and a blind retry could send it twice. List the conversation's
|
|
25905
|
+
messages first, and treat an empty result as inconclusive rather than
|
|
25906
|
+
as proof nothing was sent, since a send that failed while being recorded
|
|
25907
|
+
leaves no trace on our side.
|
|
25897
25908
|
tags: [Messages]
|
|
25898
25909
|
security: [{ bearerAuth: [] }]
|
|
25899
25910
|
parameters:
|
|
@@ -26434,10 +26445,20 @@ paths:
|
|
|
26434
26445
|
data:
|
|
26435
26446
|
type: object
|
|
26436
26447
|
properties:
|
|
26437
|
-
messageId:
|
|
26438
|
-
|
|
26439
|
-
|
|
26440
|
-
|
|
26448
|
+
messageId:
|
|
26449
|
+
type: string
|
|
26450
|
+
description: 'Platform id of the sent message (not returned for Reddit). For WhatsApp this is the raw Meta wamid, the same id delivered as message.platformMessageId on webhooks and delivery-status updates, and the value to pass as replyTo to quote-reply.'
|
|
26451
|
+
conversationId:
|
|
26452
|
+
type: string
|
|
26453
|
+
description: 'Zernio conversation id, echoed so the thread can be read back or replied to. It equals the id the list-conversations endpoint returns for Telegram, WhatsApp, SMS and Slack; for Facebook, Instagram, Bluesky and Reddit that endpoint returns the platform thread id instead, so do not correlate the two by equality. For X (Twitter), when the request addressed the conversation by its Twitter dm_conversation_id, that platform id is echoed back instead. Omitted when the send succeeded but the conversation could not be resolved to a stored record.'
|
|
26454
|
+
attachments:
|
|
26455
|
+
type: array
|
|
26456
|
+
description: 'Echo of the sent attachment with its resolved public URL, when one is available (Facebook, Instagram, Telegram, WhatsApp).'
|
|
26457
|
+
items:
|
|
26458
|
+
type: object
|
|
26459
|
+
properties:
|
|
26460
|
+
type: { type: string }
|
|
26461
|
+
url: { type: string }
|
|
26441
26462
|
'400':
|
|
26442
26463
|
description: 'Bad request (e.g., attachment not supported for platform, validation error, category combined with a template or attachment, category used on a non-WhatsApp account, or the WhatsApp Business Account is not eligible for Direct Send)'
|
|
26443
26464
|
content:
|
|
@@ -31917,6 +31938,7 @@ paths:
|
|
|
31917
31938
|
telnyxOrderId: { type: [string, "null"], description: Present once the number order has been placed (i.e. the requirement group was approved). Absent while still in identity review. }
|
|
31918
31939
|
monthlyCents: { type: integer, description: Per-country monthly price in cents ($2..$25). }
|
|
31919
31940
|
hostedByZernio: { type: boolean, description: "False for numbers you brought yourself (connected via Meta embedded signup) — they live on your own carrier, so SMS/Calls can't be enabled on them." }
|
|
31941
|
+
sipTrunkId: { type: [string, "null"], description: 'SIP trunk the number is attached to; null when not trunked. While attached, enabling Calls or WhatsApp calling, requesting WhatsApp verification, and releasing the number all return 409.' }
|
|
31920
31942
|
profileId: { type: object }
|
|
31921
31943
|
provisionedAt: { type: string, format: date-time }
|
|
31922
31944
|
metaPreverifiedId: { type: string }
|
|
@@ -32007,6 +32029,7 @@ paths:
|
|
|
32007
32029
|
endUserLastName: { type: [string, "null"] }
|
|
32008
32030
|
regulatoryDeclineReason: { type: [string, "null"], description: Reviewer rejection reason when status is regulatory_declined. }
|
|
32009
32031
|
provisionedAt: { type: string, format: date-time }
|
|
32032
|
+
sipTrunkId: { type: [string, "null"], description: 'SIP trunk the number is attached to; null when not trunked. While attached, enabling Calls or WhatsApp calling, requesting WhatsApp verification, and releasing the number all return 409.' }
|
|
32010
32033
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
32011
32034
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
32012
32035
|
delete:
|
|
@@ -32048,6 +32071,7 @@ paths:
|
|
|
32048
32071
|
'400': { description: Phone number is already released or being released }
|
|
32049
32072
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
32050
32073
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
32074
|
+
'409': { description: 'The number is attached to a SIP trunk; detach it first (code invalid_resource_state).' }
|
|
32051
32075
|
|
|
32052
32076
|
/v1/phone-numbers/purchase:
|
|
32053
32077
|
post:
|
|
@@ -32458,6 +32482,7 @@ paths:
|
|
|
32458
32482
|
telnyxOrderId: { type: [string, "null"], description: Present once the number order has been placed (i.e. the requirement group was approved). Absent while still in identity review. }
|
|
32459
32483
|
monthlyCents: { type: integer, description: Per-country monthly price in cents ($2..$25). }
|
|
32460
32484
|
hostedByZernio: { type: boolean, description: "False for numbers you brought yourself (connected via Meta embedded signup) — they live on your own carrier, so SMS/Calls can't be enabled on them." }
|
|
32485
|
+
sipTrunkId: { type: [string, "null"], description: 'SIP trunk the number is attached to; null when not trunked. While attached, enabling Calls or WhatsApp calling, requesting WhatsApp verification, and releasing the number all return 409.' }
|
|
32461
32486
|
profileId: { type: object }
|
|
32462
32487
|
provisionedAt: { type: string, format: date-time }
|
|
32463
32488
|
metaPreverifiedId: { type: string }
|
|
@@ -34355,6 +34380,7 @@ paths:
|
|
|
34355
34380
|
ivrOptions: { type: array, items: { type: object, properties: { digit: { type: string }, forwardTo: { type: string }, label: { type: string } } } }
|
|
34356
34381
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34357
34382
|
'404': { description: Number not found }
|
|
34383
|
+
'409': { description: 'This number is attached to a SIP trunk; detach it first (code invalid_resource_state).' }
|
|
34358
34384
|
'422': { description: "This number is hosted by your own carrier (brought via WhatsApp embedded signup), so calls can't be enabled on it." }
|
|
34359
34385
|
delete:
|
|
34360
34386
|
x-resource-group: "telephony"
|
|
@@ -34381,6 +34407,266 @@ paths:
|
|
|
34381
34407
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34382
34408
|
'404': { description: Number not found }
|
|
34383
34409
|
|
|
34410
|
+
/v1/phone-numbers/sip-trunks:
|
|
34411
|
+
post:
|
|
34412
|
+
x-resource-group: "telephony"
|
|
34413
|
+
operationId: createSipTrunk
|
|
34414
|
+
tags: [Voice]
|
|
34415
|
+
summary: Create a SIP trunk
|
|
34416
|
+
description: |
|
|
34417
|
+
Creates a SIP trunk an external voice platform (Retell, ElevenLabs,
|
|
34418
|
+
Vapi, or any SIP endpoint) can import your Zernio numbers into. The
|
|
34419
|
+
trunk carries both directions: inbound calls on attached numbers are
|
|
34420
|
+
delivered to `sipHost`, and the platform originates outbound calls
|
|
34421
|
+
through `termination.uri` with the digest credentials.
|
|
34422
|
+
|
|
34423
|
+
The `digestPassword` is returned only by this call (and by
|
|
34424
|
+
rotate-credentials); store it immediately. Attach any number of numbers
|
|
34425
|
+
to a trunk. Several trunks may point at the same host — each carries its
|
|
34426
|
+
own credentials and spend cap, so separate destination workspaces (e.g.
|
|
34427
|
+
an agency's clients) stay isolated.
|
|
34428
|
+
|
|
34429
|
+
security:
|
|
34430
|
+
- bearerAuth: []
|
|
34431
|
+
requestBody:
|
|
34432
|
+
required: true
|
|
34433
|
+
content:
|
|
34434
|
+
application/json:
|
|
34435
|
+
schema:
|
|
34436
|
+
type: object
|
|
34437
|
+
required: [label, sipHost]
|
|
34438
|
+
properties:
|
|
34439
|
+
label: { type: string, maxLength: 80, description: Display name for the trunk. }
|
|
34440
|
+
sipHost: { type: string, description: 'Fully-qualified hostname inbound calls are delivered to (e.g. sip.rtc.elevenlabs.io, sip.retellai.com).' }
|
|
34441
|
+
sipPort: { type: integer, minimum: 1, maximum: 65535, description: 'Defaults to 5061 for tls, 5060 otherwise.' }
|
|
34442
|
+
transport: { type: string, enum: [tls, tcp, udp], description: 'Signaling transport toward sipHost. Default tls (with SRTP media).' }
|
|
34443
|
+
responses:
|
|
34444
|
+
'201':
|
|
34445
|
+
description: Trunk created. The digest password is shown only here and on rotate.
|
|
34446
|
+
content:
|
|
34447
|
+
application/json:
|
|
34448
|
+
schema:
|
|
34449
|
+
type: object
|
|
34450
|
+
properties:
|
|
34451
|
+
id: { type: string }
|
|
34452
|
+
label: { type: string }
|
|
34453
|
+
sipHost: { type: string }
|
|
34454
|
+
sipPort: { type: integer }
|
|
34455
|
+
transport: { type: string, enum: [tls, tcp, udp] }
|
|
34456
|
+
termination:
|
|
34457
|
+
type: object
|
|
34458
|
+
properties:
|
|
34459
|
+
uri: { type: string, description: 'Telnyx termination host the platform dials for outbound (sip.telnyx.com).' }
|
|
34460
|
+
username: { type: string, description: SIP digest username. }
|
|
34461
|
+
numbersAttached: { type: integer }
|
|
34462
|
+
createdAt: { type: [string, "null"], format: date-time }
|
|
34463
|
+
digestPassword: { type: string, description: 'SIP digest password, shown only in this response.' }
|
|
34464
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
34465
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34466
|
+
'403': { description: 'SIP trunking is not enabled for this workspace, or the workspace is on legacy (non-usage-based) billing, which cannot invoice trunk call costs (code feature_not_available).' }
|
|
34467
|
+
'409': { description: 'The workspace trunk limit was reached (code invalid_resource_state).' }
|
|
34468
|
+
'422': { description: 'The host cannot be used as a trunk destination (e.g. a Zernio or carrier host).' }
|
|
34469
|
+
get:
|
|
34470
|
+
x-resource-group: "telephony"
|
|
34471
|
+
operationId: listSipTrunks
|
|
34472
|
+
tags: [Voice]
|
|
34473
|
+
summary: List SIP trunks
|
|
34474
|
+
security:
|
|
34475
|
+
- bearerAuth: []
|
|
34476
|
+
responses:
|
|
34477
|
+
'200':
|
|
34478
|
+
description: The workspace's trunks. Passwords are never included.
|
|
34479
|
+
content:
|
|
34480
|
+
application/json:
|
|
34481
|
+
schema:
|
|
34482
|
+
type: object
|
|
34483
|
+
properties:
|
|
34484
|
+
trunks:
|
|
34485
|
+
type: array
|
|
34486
|
+
items:
|
|
34487
|
+
type: object
|
|
34488
|
+
properties:
|
|
34489
|
+
id: { type: string }
|
|
34490
|
+
label: { type: string }
|
|
34491
|
+
sipHost: { type: string }
|
|
34492
|
+
sipPort: { type: integer }
|
|
34493
|
+
transport: { type: string, enum: [tls, tcp, udp] }
|
|
34494
|
+
termination:
|
|
34495
|
+
type: object
|
|
34496
|
+
properties:
|
|
34497
|
+
uri: { type: string }
|
|
34498
|
+
username: { type: string }
|
|
34499
|
+
numbersAttached: { type: integer }
|
|
34500
|
+
createdAt: { type: [string, "null"], format: date-time }
|
|
34501
|
+
enabled: { type: boolean, description: 'Whether this workspace can create SIP trunks. Managing existing trunks always works.' }
|
|
34502
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34503
|
+
|
|
34504
|
+
/v1/phone-numbers/sip-trunks/{id}:
|
|
34505
|
+
get:
|
|
34506
|
+
x-resource-group: "telephony"
|
|
34507
|
+
operationId: getSipTrunk
|
|
34508
|
+
tags: [Voice]
|
|
34509
|
+
summary: Get a SIP trunk
|
|
34510
|
+
security:
|
|
34511
|
+
- bearerAuth: []
|
|
34512
|
+
parameters:
|
|
34513
|
+
- { name: id, in: path, required: true, schema: { type: string } }
|
|
34514
|
+
responses:
|
|
34515
|
+
'200':
|
|
34516
|
+
description: Trunk detail, including the attached numbers.
|
|
34517
|
+
content:
|
|
34518
|
+
application/json:
|
|
34519
|
+
schema:
|
|
34520
|
+
type: object
|
|
34521
|
+
properties:
|
|
34522
|
+
id: { type: string }
|
|
34523
|
+
label: { type: string }
|
|
34524
|
+
sipHost: { type: string }
|
|
34525
|
+
sipPort: { type: integer }
|
|
34526
|
+
transport: { type: string, enum: [tls, tcp, udp] }
|
|
34527
|
+
termination:
|
|
34528
|
+
type: object
|
|
34529
|
+
properties:
|
|
34530
|
+
uri: { type: string }
|
|
34531
|
+
username: { type: string }
|
|
34532
|
+
numbersAttached: { type: integer }
|
|
34533
|
+
createdAt: { type: [string, "null"], format: date-time }
|
|
34534
|
+
numbers:
|
|
34535
|
+
type: array
|
|
34536
|
+
items:
|
|
34537
|
+
type: object
|
|
34538
|
+
properties:
|
|
34539
|
+
id: { type: string, description: 'Phone number record ID.' }
|
|
34540
|
+
phoneNumber: { type: string }
|
|
34541
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
34542
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34543
|
+
'404': { description: SIP trunk not found }
|
|
34544
|
+
delete:
|
|
34545
|
+
x-resource-group: "telephony"
|
|
34546
|
+
operationId: deleteSipTrunk
|
|
34547
|
+
tags: [Voice]
|
|
34548
|
+
summary: Delete a SIP trunk
|
|
34549
|
+
description: |
|
|
34550
|
+
Tears down the trunk and its carrier-side objects. Refused while any
|
|
34551
|
+
number is still attached: detach them first.
|
|
34552
|
+
security:
|
|
34553
|
+
- bearerAuth: []
|
|
34554
|
+
parameters:
|
|
34555
|
+
- { name: id, in: path, required: true, schema: { type: string } }
|
|
34556
|
+
responses:
|
|
34557
|
+
'200':
|
|
34558
|
+
description: Trunk deleted.
|
|
34559
|
+
content:
|
|
34560
|
+
application/json:
|
|
34561
|
+
schema:
|
|
34562
|
+
type: object
|
|
34563
|
+
properties:
|
|
34564
|
+
deleted: { type: boolean }
|
|
34565
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
34566
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34567
|
+
'404': { description: SIP trunk not found }
|
|
34568
|
+
'409': { description: 'Numbers are still attached to this trunk (code invalid_resource_state).' }
|
|
34569
|
+
|
|
34570
|
+
/v1/phone-numbers/sip-trunks/{id}/rotate-credentials:
|
|
34571
|
+
post:
|
|
34572
|
+
x-resource-group: "telephony"
|
|
34573
|
+
operationId: rotateSipTrunkCredentials
|
|
34574
|
+
tags: [Voice]
|
|
34575
|
+
summary: Rotate a SIP trunk's password
|
|
34576
|
+
description: |
|
|
34577
|
+
Mints a new digest password on the trunk. The old password stops
|
|
34578
|
+
working immediately, so update the destination platform right away.
|
|
34579
|
+
security:
|
|
34580
|
+
- bearerAuth: []
|
|
34581
|
+
parameters:
|
|
34582
|
+
- { name: id, in: path, required: true, schema: { type: string } }
|
|
34583
|
+
responses:
|
|
34584
|
+
'200':
|
|
34585
|
+
description: New credentials. The password is shown only here.
|
|
34586
|
+
content:
|
|
34587
|
+
application/json:
|
|
34588
|
+
schema:
|
|
34589
|
+
type: object
|
|
34590
|
+
properties:
|
|
34591
|
+
termination:
|
|
34592
|
+
type: object
|
|
34593
|
+
properties:
|
|
34594
|
+
uri: { type: string, description: 'Telnyx termination host the platform dials for outbound (sip.telnyx.com).' }
|
|
34595
|
+
username: { type: string, description: SIP digest username. }
|
|
34596
|
+
digestPassword: { type: string }
|
|
34597
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
34598
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34599
|
+
'404': { description: SIP trunk not found }
|
|
34600
|
+
|
|
34601
|
+
/v1/phone-numbers/{id}/sip-trunk:
|
|
34602
|
+
post:
|
|
34603
|
+
x-resource-group: "telephony"
|
|
34604
|
+
operationId: attachNumberToSipTrunk
|
|
34605
|
+
tags: [Voice]
|
|
34606
|
+
summary: Attach a number to a SIP trunk
|
|
34607
|
+
description: |
|
|
34608
|
+
Routes the number's calls to the trunk: the external platform receives
|
|
34609
|
+
its inbound directly and can present it as outbound caller ID. While
|
|
34610
|
+
attached, Zernio-side voice features are off for this number (call
|
|
34611
|
+
forwarding, IVR, voicemail, recording, the softphone, and WhatsApp
|
|
34612
|
+
calling), so the number must have Calls and WhatsApp calling disabled
|
|
34613
|
+
before attaching. SMS and WhatsApp messaging are unaffected.
|
|
34614
|
+
security:
|
|
34615
|
+
- bearerAuth: []
|
|
34616
|
+
parameters:
|
|
34617
|
+
- { name: id, in: path, required: true, schema: { type: string }, description: "Phone number record ID (from GET /v1/phone-numbers)." }
|
|
34618
|
+
requestBody:
|
|
34619
|
+
required: true
|
|
34620
|
+
content:
|
|
34621
|
+
application/json:
|
|
34622
|
+
schema:
|
|
34623
|
+
type: object
|
|
34624
|
+
required: [trunkId]
|
|
34625
|
+
properties:
|
|
34626
|
+
trunkId: { type: string, description: 'SIP trunk ID (from POST /v1/phone-numbers/sip-trunks).' }
|
|
34627
|
+
responses:
|
|
34628
|
+
'200':
|
|
34629
|
+
description: Number attached (idempotent for the same trunk).
|
|
34630
|
+
content:
|
|
34631
|
+
application/json:
|
|
34632
|
+
schema:
|
|
34633
|
+
type: object
|
|
34634
|
+
properties:
|
|
34635
|
+
attached: { type: boolean }
|
|
34636
|
+
phoneNumber: { type: string }
|
|
34637
|
+
trunkId: { type: string }
|
|
34638
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
34639
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34640
|
+
'403': { description: 'SIP trunking is not enabled for this workspace, or the workspace is on legacy (non-usage-based) billing, which cannot invoice trunk call costs (code feature_not_available).' }
|
|
34641
|
+
'404': { description: Number or trunk not found }
|
|
34642
|
+
'409': { description: 'The number still has Calls or WhatsApp calling enabled, is mid WhatsApp verification, is not active, or is attached to another trunk (code invalid_resource_state).' }
|
|
34643
|
+
'422': { description: 'This number is hosted by your own carrier (brought via WhatsApp embedded signup), so it cannot be trunked.' }
|
|
34644
|
+
delete:
|
|
34645
|
+
x-resource-group: "telephony"
|
|
34646
|
+
operationId: detachNumberFromSipTrunk
|
|
34647
|
+
tags: [Voice]
|
|
34648
|
+
summary: Detach a number from its SIP trunk
|
|
34649
|
+
description: |
|
|
34650
|
+
Returns the number's calls to Zernio routing. Idempotent when the
|
|
34651
|
+
number is not attached to any trunk.
|
|
34652
|
+
security:
|
|
34653
|
+
- bearerAuth: []
|
|
34654
|
+
parameters:
|
|
34655
|
+
- { name: id, in: path, required: true, schema: { type: string } }
|
|
34656
|
+
responses:
|
|
34657
|
+
'200':
|
|
34658
|
+
description: Number detached.
|
|
34659
|
+
content:
|
|
34660
|
+
application/json:
|
|
34661
|
+
schema:
|
|
34662
|
+
type: object
|
|
34663
|
+
properties:
|
|
34664
|
+
attached: { type: boolean, description: Always false after a successful detach. }
|
|
34665
|
+
phoneNumber: { type: string }
|
|
34666
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
34667
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34668
|
+
'404': { description: Number not found }
|
|
34669
|
+
|
|
34384
34670
|
/v1/phone-numbers/{id}/sms:
|
|
34385
34671
|
post:
|
|
34386
34672
|
x-resource-group: "telephony"
|
|
@@ -34594,6 +34880,7 @@ paths:
|
|
|
34594
34880
|
'400': { description: 'Invalid request (including forwardTo set to the number itself)' }
|
|
34595
34881
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34596
34882
|
'404': { description: Phone number not found }
|
|
34883
|
+
'409': { description: 'This number is attached to a SIP trunk; detach it first (code invalid_resource_state).' }
|
|
34597
34884
|
'422': { description: "Not eligible to enable calling: not on usage-based billing, or the number's messaging limit is below Meta's ~2,000-daily-recipient threshold (TIER_250). Warm the number up to raise the limit." }
|
|
34598
34885
|
patch:
|
|
34599
34886
|
x-resource-group: "telephony"
|
|
@@ -34781,6 +35068,7 @@ paths:
|
|
|
34781
35068
|
endUserLastName: { type: [string, "null"] }
|
|
34782
35069
|
regulatoryDeclineReason: { type: [string, "null"], description: Reviewer rejection reason when status is regulatory_declined. }
|
|
34783
35070
|
provisionedAt: { type: string, format: date-time }
|
|
35071
|
+
sipTrunkId: { type: [string, "null"], description: 'SIP trunk the number is attached to; null when not trunked. While attached, enabling Calls or WhatsApp calling, requesting WhatsApp verification, and releasing the number all return 409.' }
|
|
34784
35072
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34785
35073
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
34786
35074
|
delete:
|
|
@@ -34826,6 +35114,7 @@ paths:
|
|
|
34826
35114
|
'400': { description: Phone number is already released or being released }
|
|
34827
35115
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
34828
35116
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
35117
|
+
'409': { description: 'The number is attached to a SIP trunk; detach it first (code invalid_resource_state).' }
|
|
34829
35118
|
|
|
34830
35119
|
# ─── WhatsApp Sandbox (shared test number) ──────────────────────
|
|
34831
35120
|
#
|
|
@@ -196,7 +196,7 @@ describe 'MessagesApi' do
|
|
|
196
196
|
|
|
197
197
|
# unit tests for send_inbox_message
|
|
198
198
|
# Send message
|
|
199
|
-
# Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ \"elements\": [{ \"name\": ..., \"language\": ..., \"components\": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours.
|
|
199
|
+
# Send a message in a conversation. Supports text, attachments, quick replies, buttons, templates, and message tags. Attachment and interactive message support varies by platform. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the `template` field with a single element carrying the template reference: `{ \"elements\": [{ \"name\": ..., \"language\": ..., \"components\": [...] }] }`. See the `template` field below for the exact shape. To send a template to a phone number you have no conversation with yet, use the create-conversation endpoint (POST /v1/inbox/conversations) instead. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the `interactive` field. Tap events are delivered through the `message.received` webhook with WhatsApp-specific `metadata` fields (`interactiveType`, `interactiveId`, `flowResponseJson`, `flowResponseData`). **Idempotency:** send an `Idempotency-Key` header to make retries safe (e.g. after a client-side timeout where delivery is unknown): same key + same body replays the original response (with `Idempotent-Replayed: true`) instead of sending the message a second time; same key + different body returns 422; a key still in flight returns 409. Works for JSON and multipart (file upload) requests alike. Keys are retained for 24 hours. Only successful (2xx) responses are stored for replay: if the request throws or returns a non-2xx status, the key is released so the same key can be retried once the problem is fixed. The header therefore protects the \"request succeeded but the response was lost\" case. For an ambiguous failure (a 5xx or a network timeout), reconcile before retrying: a failure after the platform already accepted the message also releases the key, and a blind retry could send it twice. List the conversation's messages first, and treat an empty result as inconclusive rather than as proof nothing was sent, since a send that failed while being recorded leaves no trace on our side.
|
|
200
200
|
# @param conversation_id Opaque conversation identifier, accepted verbatim from the list endpoint or from the conversationId on inbox webhooks. Format not to be assumed.
|
|
201
201
|
# @param send_inbox_message_request
|
|
202
202
|
# @param [Hash] opts the optional parameters
|