late-sdk 0.0.948 → 0.0.949

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -0
  3. data/docs/CreateInboxConversation400Response.md +11 -3
  4. data/docs/CreateInboxConversation400ResponseAnyOf.md +20 -0
  5. data/docs/CreateInboxConversation404Response.md +11 -3
  6. data/docs/CreateInboxConversation404ResponseAnyOf.md +20 -0
  7. data/docs/CreateInboxConversation422Response.md +11 -3
  8. data/docs/CreateInboxConversation422ResponseAnyOf.md +20 -0
  9. data/docs/CreateInboxConversation429Response.md +11 -3
  10. data/docs/CreateInboxConversation429ResponseAnyOf.md +20 -0
  11. data/docs/MessagesApi.md +2 -2
  12. data/docs/SendInboxMessage400Response.md +1 -1
  13. data/docs/SendInboxMessage502Response.md +30 -0
  14. data/docs/WhatsAppTemplateLookupError.md +28 -0
  15. data/docs/WhatsAppTemplateLookupErrorDetails.md +24 -0
  16. data/docs/WhatsAppTemplateLookupErrorDetailsProviderHeaders.md +22 -0
  17. data/docs/WhatsAppTemplateLookupErrorPlatformError.md +22 -0
  18. data/docs/WhatsAppTemplateLookupErrorPlatformErrorErrorData.md +18 -0
  19. data/lib/zernio-sdk/api/messages_api.rb +4 -4
  20. data/lib/zernio-sdk/models/create_inbox_conversation400_response.rb +73 -160
  21. data/lib/zernio-sdk/models/create_inbox_conversation400_response_any_of.rb +190 -0
  22. data/lib/zernio-sdk/models/create_inbox_conversation404_response.rb +73 -160
  23. data/lib/zernio-sdk/models/create_inbox_conversation404_response_any_of.rb +190 -0
  24. data/lib/zernio-sdk/models/create_inbox_conversation422_response.rb +73 -160
  25. data/lib/zernio-sdk/models/create_inbox_conversation422_response_any_of.rb +190 -0
  26. data/lib/zernio-sdk/models/create_inbox_conversation429_response.rb +73 -160
  27. data/lib/zernio-sdk/models/create_inbox_conversation429_response_any_of.rb +190 -0
  28. data/lib/zernio-sdk/models/send_inbox_message400_response.rb +3 -3
  29. data/lib/zernio-sdk/models/send_inbox_message400_response_platform_error.rb +1 -1
  30. data/lib/zernio-sdk/models/send_inbox_message502_response.rb +103 -0
  31. data/lib/zernio-sdk/models/whats_app_template_lookup_error.rb +305 -0
  32. data/lib/zernio-sdk/models/whats_app_template_lookup_error_details.rb +233 -0
  33. data/lib/zernio-sdk/models/whats_app_template_lookup_error_details_provider_headers.rb +166 -0
  34. data/lib/zernio-sdk/models/whats_app_template_lookup_error_platform_error.rb +166 -0
  35. data/lib/zernio-sdk/models/whats_app_template_lookup_error_platform_error_error_data.rb +147 -0
  36. data/lib/zernio-sdk/version.rb +1 -1
  37. data/lib/zernio-sdk.rb +10 -0
  38. data/openapi.yaml +100 -22
  39. data/spec/api/messages_api_spec.rb +2 -2
  40. data/spec/models/create_inbox_conversation400_response_any_of_spec.rb +46 -0
  41. data/spec/models/create_inbox_conversation400_response_spec.rb +0 -25
  42. data/spec/models/create_inbox_conversation404_response_any_of_spec.rb +46 -0
  43. data/spec/models/create_inbox_conversation404_response_spec.rb +0 -25
  44. data/spec/models/create_inbox_conversation422_response_any_of_spec.rb +46 -0
  45. data/spec/models/create_inbox_conversation422_response_spec.rb +0 -25
  46. data/spec/models/create_inbox_conversation429_response_any_of_spec.rb +46 -0
  47. data/spec/models/create_inbox_conversation429_response_spec.rb +0 -25
  48. data/spec/models/send_inbox_message400_response_spec.rb +1 -1
  49. data/spec/models/send_inbox_message502_response_spec.rb +21 -0
  50. data/spec/models/whats_app_template_lookup_error_details_provider_headers_spec.rb +48 -0
  51. data/spec/models/whats_app_template_lookup_error_details_spec.rb +58 -0
  52. data/spec/models/whats_app_template_lookup_error_platform_error_error_data_spec.rb +36 -0
  53. data/spec/models/whats_app_template_lookup_error_platform_error_spec.rb +48 -0
  54. data/spec/models/whats_app_template_lookup_error_spec.rb +78 -0
  55. data/zernio-sdk-0.0.949.gem +0 -0
  56. metadata +42 -2
  57. data/zernio-sdk-0.0.948.gem +0 -0
@@ -0,0 +1,166 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
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
+ # Sanitized Meta lookup error fields, present when Meta returned them.
18
+ class WhatsAppTemplateLookupErrorPlatformError < ApiModelBase
19
+ attr_accessor :code
20
+
21
+ attr_accessor :message
22
+
23
+ attr_accessor :error_data
24
+
25
+ # Attribute mapping from ruby-style variable name to JSON key.
26
+ def self.attribute_map
27
+ {
28
+ :'code' => :'code',
29
+ :'message' => :'message',
30
+ :'error_data' => :'error_data'
31
+ }
32
+ end
33
+
34
+ # Returns attribute mapping this model knows about
35
+ def self.acceptable_attribute_map
36
+ attribute_map
37
+ end
38
+
39
+ # Returns all the JSON keys this model knows about
40
+ def self.acceptable_attributes
41
+ acceptable_attribute_map.values
42
+ end
43
+
44
+ # Attribute type mapping.
45
+ def self.openapi_types
46
+ {
47
+ :'code' => :'Integer',
48
+ :'message' => :'String',
49
+ :'error_data' => :'WhatsAppTemplateLookupErrorPlatformErrorErrorData'
50
+ }
51
+ end
52
+
53
+ # List of attributes with nullable: true
54
+ def self.openapi_nullable
55
+ Set.new([
56
+ ])
57
+ end
58
+
59
+ # Initializes the object
60
+ # @param [Hash] attributes Model attributes in the form of hash
61
+ def initialize(attributes = {})
62
+ if (!attributes.is_a?(Hash))
63
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::WhatsAppTemplateLookupErrorPlatformError` initialize method"
64
+ end
65
+
66
+ # check to see if the attribute exists and convert string to symbol for hash key
67
+ acceptable_attribute_map = self.class.acceptable_attribute_map
68
+ attributes = attributes.each_with_object({}) { |(k, v), h|
69
+ if (!acceptable_attribute_map.key?(k.to_sym))
70
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::WhatsAppTemplateLookupErrorPlatformError`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
71
+ end
72
+ h[k.to_sym] = v
73
+ }
74
+
75
+ if attributes.key?(:'code')
76
+ self.code = attributes[:'code']
77
+ end
78
+
79
+ if attributes.key?(:'message')
80
+ self.message = attributes[:'message']
81
+ end
82
+
83
+ if attributes.key?(:'error_data')
84
+ self.error_data = attributes[:'error_data']
85
+ end
86
+ end
87
+
88
+ # Show invalid properties with the reasons. Usually used together with valid?
89
+ # @return Array for valid properties with the reasons
90
+ def list_invalid_properties
91
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
92
+ invalid_properties = Array.new
93
+ invalid_properties
94
+ end
95
+
96
+ # Check to see if the all the properties in the model are valid
97
+ # @return true if the model is valid
98
+ def valid?
99
+ warn '[DEPRECATED] the `valid?` method is obsolete'
100
+ true
101
+ end
102
+
103
+ # Checks equality by comparing each attribute.
104
+ # @param [Object] Object to be compared
105
+ def ==(o)
106
+ return true if self.equal?(o)
107
+ self.class == o.class &&
108
+ code == o.code &&
109
+ message == o.message &&
110
+ error_data == o.error_data
111
+ end
112
+
113
+ # @see the `==` method
114
+ # @param [Object] Object to be compared
115
+ def eql?(o)
116
+ self == o
117
+ end
118
+
119
+ # Calculates hash code according to all attributes.
120
+ # @return [Integer] Hash code
121
+ def hash
122
+ [code, message, error_data].hash
123
+ end
124
+
125
+ # Builds the object from hash
126
+ # @param [Hash] attributes Model attributes in the form of hash
127
+ # @return [Object] Returns the model itself
128
+ def self.build_from_hash(attributes)
129
+ return nil unless attributes.is_a?(Hash)
130
+ attributes = attributes.transform_keys(&:to_sym)
131
+ transformed_hash = {}
132
+ openapi_types.each_pair do |key, type|
133
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
134
+ transformed_hash["#{key}"] = nil
135
+ elsif type =~ /\AArray<(.*)>/i
136
+ # check to ensure the input is an array given that the attribute
137
+ # is documented as an array but the input is not
138
+ if attributes[attribute_map[key]].is_a?(Array)
139
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
140
+ end
141
+ elsif !attributes[attribute_map[key]].nil?
142
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
143
+ end
144
+ end
145
+ new(transformed_hash)
146
+ end
147
+
148
+ # Returns the object in the form of hash
149
+ # @return [Hash] Returns the object in the form of hash
150
+ def to_hash
151
+ hash = {}
152
+ self.class.attribute_map.each_pair do |attr, param|
153
+ value = self.send(attr)
154
+ if value.nil?
155
+ is_nullable = self.class.openapi_nullable.include?(attr)
156
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
157
+ end
158
+
159
+ hash[param] = _to_hash(value)
160
+ end
161
+ hash
162
+ end
163
+
164
+ end
165
+
166
+ end
@@ -0,0 +1,147 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
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 WhatsAppTemplateLookupErrorPlatformErrorErrorData < ApiModelBase
18
+ attr_accessor :details
19
+
20
+ # Attribute mapping from ruby-style variable name to JSON key.
21
+ def self.attribute_map
22
+ {
23
+ :'details' => :'details'
24
+ }
25
+ end
26
+
27
+ # Returns attribute mapping this model knows about
28
+ def self.acceptable_attribute_map
29
+ attribute_map
30
+ end
31
+
32
+ # Returns all the JSON keys this model knows about
33
+ def self.acceptable_attributes
34
+ acceptable_attribute_map.values
35
+ end
36
+
37
+ # Attribute type mapping.
38
+ def self.openapi_types
39
+ {
40
+ :'details' => :'String'
41
+ }
42
+ end
43
+
44
+ # List of attributes with nullable: true
45
+ def self.openapi_nullable
46
+ Set.new([
47
+ ])
48
+ end
49
+
50
+ # Initializes the object
51
+ # @param [Hash] attributes Model attributes in the form of hash
52
+ def initialize(attributes = {})
53
+ if (!attributes.is_a?(Hash))
54
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::WhatsAppTemplateLookupErrorPlatformErrorErrorData` initialize method"
55
+ end
56
+
57
+ # check to see if the attribute exists and convert string to symbol for hash key
58
+ acceptable_attribute_map = self.class.acceptable_attribute_map
59
+ attributes = attributes.each_with_object({}) { |(k, v), h|
60
+ if (!acceptable_attribute_map.key?(k.to_sym))
61
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::WhatsAppTemplateLookupErrorPlatformErrorErrorData`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
62
+ end
63
+ h[k.to_sym] = v
64
+ }
65
+
66
+ if attributes.key?(:'details')
67
+ self.details = attributes[:'details']
68
+ end
69
+ end
70
+
71
+ # Show invalid properties with the reasons. Usually used together with valid?
72
+ # @return Array for valid properties with the reasons
73
+ def list_invalid_properties
74
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
75
+ invalid_properties = Array.new
76
+ invalid_properties
77
+ end
78
+
79
+ # Check to see if the all the properties in the model are valid
80
+ # @return true if the model is valid
81
+ def valid?
82
+ warn '[DEPRECATED] the `valid?` method is obsolete'
83
+ true
84
+ end
85
+
86
+ # Checks equality by comparing each attribute.
87
+ # @param [Object] Object to be compared
88
+ def ==(o)
89
+ return true if self.equal?(o)
90
+ self.class == o.class &&
91
+ details == o.details
92
+ end
93
+
94
+ # @see the `==` method
95
+ # @param [Object] Object to be compared
96
+ def eql?(o)
97
+ self == o
98
+ end
99
+
100
+ # Calculates hash code according to all attributes.
101
+ # @return [Integer] Hash code
102
+ def hash
103
+ [details].hash
104
+ end
105
+
106
+ # Builds the object from hash
107
+ # @param [Hash] attributes Model attributes in the form of hash
108
+ # @return [Object] Returns the model itself
109
+ def self.build_from_hash(attributes)
110
+ return nil unless attributes.is_a?(Hash)
111
+ attributes = attributes.transform_keys(&:to_sym)
112
+ transformed_hash = {}
113
+ openapi_types.each_pair do |key, type|
114
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
115
+ transformed_hash["#{key}"] = nil
116
+ elsif type =~ /\AArray<(.*)>/i
117
+ # check to ensure the input is an array given that the attribute
118
+ # is documented as an array but the input is not
119
+ if attributes[attribute_map[key]].is_a?(Array)
120
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
121
+ end
122
+ elsif !attributes[attribute_map[key]].nil?
123
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
124
+ end
125
+ end
126
+ new(transformed_hash)
127
+ end
128
+
129
+ # Returns the object in the form of hash
130
+ # @return [Hash] Returns the object in the form of hash
131
+ def to_hash
132
+ hash = {}
133
+ self.class.attribute_map.each_pair do |attr, param|
134
+ value = self.send(attr)
135
+ if value.nil?
136
+ is_nullable = self.class.openapi_nullable.include?(attr)
137
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
138
+ end
139
+
140
+ hash[param] = _to_hash(value)
141
+ end
142
+ hash
143
+ end
144
+
145
+ end
146
+
147
+ end
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.948'
14
+ VERSION = '0.0.949'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -332,9 +332,13 @@ require 'zernio-sdk/models/create_high_demand_period_request'
332
332
  require 'zernio-sdk/models/create_inbox_conversation201_response'
333
333
  require 'zernio-sdk/models/create_inbox_conversation201_response_data'
334
334
  require 'zernio-sdk/models/create_inbox_conversation400_response'
335
+ require 'zernio-sdk/models/create_inbox_conversation400_response_any_of'
335
336
  require 'zernio-sdk/models/create_inbox_conversation404_response'
337
+ require 'zernio-sdk/models/create_inbox_conversation404_response_any_of'
336
338
  require 'zernio-sdk/models/create_inbox_conversation422_response'
339
+ require 'zernio-sdk/models/create_inbox_conversation422_response_any_of'
337
340
  require 'zernio-sdk/models/create_inbox_conversation429_response'
341
+ require 'zernio-sdk/models/create_inbox_conversation429_response_any_of'
338
342
  require 'zernio-sdk/models/create_inbox_conversation_request'
339
343
  require 'zernio-sdk/models/create_inbox_conversation_request_header_location'
340
344
  require 'zernio-sdk/models/create_inbox_conversation_request_header_media'
@@ -1505,6 +1509,7 @@ require 'zernio-sdk/models/send_inbox_message200_response_data_partial_failure_p
1505
1509
  require 'zernio-sdk/models/send_inbox_message200_response_warnings_inner'
1506
1510
  require 'zernio-sdk/models/send_inbox_message400_response'
1507
1511
  require 'zernio-sdk/models/send_inbox_message400_response_platform_error'
1512
+ require 'zernio-sdk/models/send_inbox_message502_response'
1508
1513
  require 'zernio-sdk/models/send_inbox_message_request'
1509
1514
  require 'zernio-sdk/models/send_inbox_message_request_buttons_inner'
1510
1515
  require 'zernio-sdk/models/send_inbox_message_request_contacts_inner'
@@ -2015,6 +2020,11 @@ require 'zernio-sdk/models/whats_app_named_param_example'
2015
2020
  require 'zernio-sdk/models/whats_app_sandbox_session'
2016
2021
  require 'zernio-sdk/models/whats_app_template_button'
2017
2022
  require 'zernio-sdk/models/whats_app_template_component'
2023
+ require 'zernio-sdk/models/whats_app_template_lookup_error'
2024
+ require 'zernio-sdk/models/whats_app_template_lookup_error_details'
2025
+ require 'zernio-sdk/models/whats_app_template_lookup_error_details_provider_headers'
2026
+ require 'zernio-sdk/models/whats_app_template_lookup_error_platform_error'
2027
+ require 'zernio-sdk/models/whats_app_template_lookup_error_platform_error_error_data'
2018
2028
  require 'zernio-sdk/models/workflow_edge'
2019
2029
  require 'zernio-sdk/models/workflow_execution_event'
2020
2030
  require 'zernio-sdk/models/workflow_node'
data/openapi.yaml CHANGED
@@ -852,6 +852,39 @@ components:
852
852
  effective_account_limit: 2000
853
853
  current_account_count: 2000
854
854
  schemas:
855
+ WhatsAppTemplateLookupError:
856
+ type: object
857
+ required: [error, type, code, platform, details]
858
+ properties:
859
+ error: { type: string }
860
+ type: { type: string, enum: [platform_error] }
861
+ code: { type: string, enum: [platform_api_error] }
862
+ platform: { type: string, enum: [whatsapp] }
863
+ platformError:
864
+ type: object
865
+ description: Sanitized Meta lookup error fields, present when Meta returned them.
866
+ properties:
867
+ code: { type: integer }
868
+ message: { type: string }
869
+ error_data:
870
+ type: object
871
+ properties:
872
+ details: { type: string }
873
+ details:
874
+ type: object
875
+ required: [phase, endpoint]
876
+ properties:
877
+ phase: { type: string, enum: [template_lookup] }
878
+ endpoint: { type: string, description: Meta endpoint path without query parameters or access tokens }
879
+ upstreamStatus: { type: integer }
880
+ providerHeaders:
881
+ type: object
882
+ description: Safe provider headers retained from the lookup response.
883
+ properties:
884
+ retry-after: { type: string }
885
+ x-app-usage: { type: string }
886
+ x-business-use-case-usage: { type: string }
887
+ additionalProperties: false
855
888
  AdTracking:
856
889
  type: object
857
890
  description: "Meta only. Attaches pixel measurement to the ad regardless of the optimization goal (the \"Website events\" tracking row in Ads Manager). `pixelId` becomes the ad's `tracking_specs` (offsite_conversion + fb_pixel); `urlTags` is stored on the new creative as `url_tags` and retained on the ad for compatibility. Applied on the legacy single-creative shape, every ad of the multi-creative shape, and the attach shape. NOTE: tracking lives on the AD object and is not inherited from the ad set, so pass it on EVERY attach call that should carry the pixel."
@@ -29051,6 +29084,8 @@ paths:
29051
29084
 
29052
29085
  **WhatsApp.** This is the endpoint for sending an approved template message to a phone number. Provide templateName, templateLanguage, and templateParams (variable values for the text header, body and dynamic URL buttons, in that order), with the recipient phone in participantId. A template is required because WhatsApp does not permit freeform messages to open a conversation; a missing template returns TEMPLATE_REQUIRED.
29053
29086
 
29087
+ Before sending, Zernio must resolve an exact APPROVED template definition matching both templateName and templateLanguage. If Meta rejects that lookup, or the exact approved definition is absent, Zernio sends no message and returns the canonical platform error instead. Lookup errors use code `platform_api_error`, type `platform_error`, and platform `whatsapp`. Sanitized Meta code, message, and `error_data.details` are returned in `platformError`; `details` identifies `phase: template_lookup`, the query-free endpoint, upstream status, and only safe provider usage or retry headers.
29088
+
29054
29089
  - Templates with media headers (image, video, document) are handled automatically: Zernio reads the approved template definition and fills the header at send time with the template's approved sample asset. To send a DIFFERENT asset per message (e.g. a distinct invoice PDF for each recipient), pass the headerMedia field with a public link (or a Meta media id); it overrides the sample for that send.
29055
29090
  - A template whose approved header format is LOCATION has no header asset to reconstruct at all: Meta only accepts the location at send time, so pass headerLocation (latitude and longitude required) whenever such a template is sent; headerMedia and headerLocation cannot both be supplied.
29056
29091
  - A button that carries its own value at send time (a copy-code button holding a Pix payment code or a coupon, a flow token) is sent with templateButtonParams, addressed by the button's index; templateParams covers text variables and dynamic URL buttons only.
@@ -29332,14 +29367,16 @@ paths:
29332
29367
  type: [string, "null"]
29333
29368
  description: X username of the recipient
29334
29369
  '400':
29335
- description: 'Validation error, platform not supported, an attachment the platform does not accept (PLATFORM_LIMITATION), template required to start a WhatsApp conversation (TEMPLATE_REQUIRED), template variables that do not match the approved definition (INVALID_TEMPLATE_PARAMS, INVALID_TEMPLATE_BUTTON_PARAM), templateCards that do not match the approved carousel definition (INVALID_TEMPLATE_CARD_PARAM), category combined with templateName or used on a non-WhatsApp account, or the WhatsApp Business Account is not eligible for Direct Send: DIRECT_SEND_NOT_ELIGIBLE and DIRECT_SEND_BLOCKED require Meta to grant or restore Direct Send access, while DIRECT_SEND_LIMITED is temporary and lifts on its own'
29370
+ description: 'Validation error, platform not supported, an attachment the platform does not accept (PLATFORM_LIMITATION), template required to start a WhatsApp conversation (TEMPLATE_REQUIRED), template variables that do not match the approved definition (INVALID_TEMPLATE_PARAMS, INVALID_TEMPLATE_BUTTON_PARAM), a missing or incompatible required template header (INVALID_TEMPLATE_HEADER), templateCards that do not match the approved carousel definition (INVALID_TEMPLATE_CARD_PARAM), category combined with templateName or used on a non-WhatsApp account, or the WhatsApp Business Account is not eligible for Direct Send: DIRECT_SEND_NOT_ELIGIBLE and DIRECT_SEND_BLOCKED require Meta to grant or restore Direct Send access, while DIRECT_SEND_LIMITED is temporary and lifts on its own'
29336
29371
  content:
29337
29372
  application/json:
29338
29373
  schema:
29339
- type: object
29340
- properties:
29341
- error: { type: string }
29342
- code: { type: string, enum: [PLATFORM_NOT_SUPPORTED, PLATFORM_LIMITATION, TEMPLATE_REQUIRED, INVALID_TEMPLATE_PARAMS, INVALID_TEMPLATE_BUTTON_PARAM, INVALID_TEMPLATE_CARD_PARAM, DIRECT_SEND_NOT_ELIGIBLE, DIRECT_SEND_LIMITED, DIRECT_SEND_BLOCKED] }
29374
+ anyOf:
29375
+ - type: object
29376
+ properties:
29377
+ error: { type: string }
29378
+ code: { type: string, enum: [PLATFORM_NOT_SUPPORTED, PLATFORM_LIMITATION, TEMPLATE_REQUIRED, INVALID_TEMPLATE_PARAMS, INVALID_TEMPLATE_BUTTON_PARAM, INVALID_TEMPLATE_HEADER, INVALID_TEMPLATE_CARD_PARAM, DIRECT_SEND_NOT_ELIGIBLE, DIRECT_SEND_LIMITED, DIRECT_SEND_BLOCKED] }
29379
+ - { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
29343
29380
  '401': { $ref: '#/components/responses/Unauthorized' }
29344
29381
  '403':
29345
29382
  description: Inbox addon required or profile limit reached
@@ -29348,28 +29385,44 @@ paths:
29348
29385
  content:
29349
29386
  application/json:
29350
29387
  schema:
29351
- type: object
29352
- properties:
29353
- error: { type: string }
29354
- code: { type: string, enum: [account_not_found, PARTICIPANT_NOT_FOUND] }
29388
+ anyOf:
29389
+ - type: object
29390
+ properties:
29391
+ error: { type: string }
29392
+ code: { type: string, enum: [account_not_found, PARTICIPANT_NOT_FOUND] }
29393
+ - { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
29355
29394
  '422':
29356
29395
  description: 'Recipient does not accept DMs from this account (X), or does not accept direct messages from you (Reddit)'
29357
29396
  content:
29358
29397
  application/json:
29359
29398
  schema:
29360
- type: object
29361
- properties:
29362
- error: { type: string }
29363
- code: { type: string, enum: [DM_NOT_ALLOWED] }
29399
+ anyOf:
29400
+ - type: object
29401
+ properties:
29402
+ error: { type: string }
29403
+ code: { type: string, enum: [DM_NOT_ALLOWED] }
29404
+ - { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
29364
29405
  '429':
29365
- description: 'X API rate limit exceeded, or Reddit rate limit reached for this account'
29406
+ description: 'X API rate limit exceeded, Reddit rate limit reached, or Meta rejected the WhatsApp template-definition lookup. A lookup failure sends no message.'
29366
29407
  content:
29367
29408
  application/json:
29368
29409
  schema:
29369
- type: object
29370
- properties:
29371
- error: { type: string }
29372
- code: { type: string, enum: [rate_limited] }
29410
+ anyOf:
29411
+ - type: object
29412
+ properties:
29413
+ error: { type: string }
29414
+ code: { type: string, enum: [rate_limited] }
29415
+ - { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
29416
+ '502':
29417
+ description: The exact approved WhatsApp template definition is unavailable. No message was sent.
29418
+ content:
29419
+ application/json:
29420
+ schema: { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
29421
+ default:
29422
+ description: Meta rejected the WhatsApp template-definition lookup with another upstream status. No message was sent.
29423
+ content:
29424
+ application/json:
29425
+ schema: { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
29373
29426
  /v1/inbox/conversations/search:
29374
29427
  get:
29375
29428
  x-resource-group: "messages"
@@ -29941,6 +29994,14 @@ paths:
29941
29994
  to a phone number you have no conversation with yet, use the
29942
29995
  create-conversation endpoint (POST /v1/inbox/conversations) instead.
29943
29996
 
29997
+ Zernio resolves the exact APPROVED template name and language before any
29998
+ WhatsApp template send. A failed lookup or missing exact definition sends
29999
+ no message and returns code `platform_api_error`, type `platform_error`,
30000
+ and platform `whatsapp`. Sanitized Meta code, message, and
30001
+ `error_data.details` are returned in `platformError`; `details` identifies
30002
+ `phase: template_lookup`, the query-free endpoint, upstream status, and
30003
+ only safe provider usage or retry headers.
30004
+
29944
30005
  WhatsApp rich interactive messages (list, CTA URL, Flow, location request)
29945
30006
  are available via the `interactive` field. Tap events are delivered through
29946
30007
  the `message.received` webhook with WhatsApp-specific `metadata` fields
@@ -30592,13 +30653,13 @@ paths:
30592
30653
  code:
30593
30654
  type: string
30594
30655
  description: "Stable machine-readable reason. PLATFORM_LIMITATION covers a capability the platform does not offer (e.g. Bluesky and Reddit DMs reject media); MISSING_PARTICIPANT means the stored conversation has no recipient to send to; DIRECT_SEND_NOT_ELIGIBLE and DIRECT_SEND_BLOCKED mean the WhatsApp Business Account needs Meta to grant or restore Direct Send access; DIRECT_SEND_LIMITED is temporary, Meta lifts it on its own; platform_api_error means Meta itself rejected the send (see platformError)."
30595
- enum: [PLATFORM_LIMITATION, MISSING_PARTICIPANT, DIRECT_SEND_NOT_ELIGIBLE, DIRECT_SEND_LIMITED, DIRECT_SEND_BLOCKED, platform_api_error]
30656
+ enum: [PLATFORM_LIMITATION, MISSING_PARTICIPANT, INVALID_TEMPLATE_HEADER, DIRECT_SEND_NOT_ELIGIBLE, DIRECT_SEND_LIMITED, DIRECT_SEND_BLOCKED, platform_api_error]
30596
30657
  platform:
30597
30658
  type: string
30598
- description: "Present alongside code platform_api_error. The platform that rejected the send (e.g. instagram, facebook)."
30659
+ description: "Present alongside code platform_api_error. The platform that rejected the send (e.g. instagram, facebook, whatsapp)."
30599
30660
  platformError:
30600
30661
  type: object
30601
- description: "Instagram/Facebook only. Meta's own diagnostic fields for the rejected send, passed through verbatim so you can tell failure classes apart and quote them to Meta. Absent when the failure did not come from Meta."
30662
+ description: "Instagram, Facebook, or WhatsApp. Meta's diagnostic fields for the rejected send or template lookup. WhatsApp lookup errors retain only code, message, and error_data.details. Absent when the failure did not come from Meta."
30602
30663
  properties:
30603
30664
  code: { type: integer, description: "Meta error code" }
30604
30665
  subcode: { type: integer, description: "Meta error_subcode" }
@@ -30621,8 +30682,25 @@ paths:
30621
30682
  schema: { $ref: '#/components/schemas/ErrorResponse' }
30622
30683
  '409': { $ref: '#/components/responses/IdempotencyKeyInFlight' }
30623
30684
  '422': { $ref: '#/components/responses/IdempotencyKeyReused' }
30685
+ '429':
30686
+ description: Meta rejected the WhatsApp template-definition lookup. No message was sent.
30687
+ content:
30688
+ application/json:
30689
+ schema: { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
30624
30690
  '503': { $ref: '#/components/responses/TemporarilyUnavailable' }
30625
- '502': { $ref: '#/components/responses/UpstreamFailure' }
30691
+ '502':
30692
+ description: The exact approved WhatsApp template definition is unavailable, or the platform returned an upstream failure. No WhatsApp template message is sent when definition lookup fails.
30693
+ content:
30694
+ application/json:
30695
+ schema:
30696
+ anyOf:
30697
+ - { $ref: '#/components/schemas/ErrorResponse' }
30698
+ - { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
30699
+ default:
30700
+ description: Meta rejected the WhatsApp template-definition lookup with another upstream status. No message was sent.
30701
+ content:
30702
+ application/json:
30703
+ schema: { $ref: '#/components/schemas/WhatsAppTemplateLookupError' }
30626
30704
 
30627
30705
  /v1/whatsapp/media/{mediaId}:
30628
30706
  get:
@@ -48,7 +48,7 @@ describe 'MessagesApi' do
48
48
 
49
49
  # unit tests for create_inbox_conversation
50
50
  # Create conversation
51
- # Start a direct message conversation with a user. If a conversation with that recipient already exists, the message is added to the existing thread. Supported platforms: X, Bluesky, Reddit, WhatsApp, SMS, and Slack. Other platforms return PLATFORM_NOT_SUPPORTED. **Slack.** Pass a workspace member id as participantId (list them with GET /v1/accounts/{accountId}/slack-members). Zernio opens the DM channel with that member and sends the message; the thread then behaves like any other Slack conversation in the inbox. The member must belong to the connected workspace. **WhatsApp.** This is the endpoint for sending an approved template message to a phone number. Provide templateName, templateLanguage, and templateParams (variable values for the text header, body and dynamic URL buttons, in that order), with the recipient phone in participantId. A template is required because WhatsApp does not permit freeform messages to open a conversation; a missing template returns TEMPLATE_REQUIRED. - Templates with media headers (image, video, document) are handled automatically: Zernio reads the approved template definition and fills the header at send time with the template&#39;s approved sample asset. To send a DIFFERENT asset per message (e.g. a distinct invoice PDF for each recipient), pass the headerMedia field with a public link (or a Meta media id); it overrides the sample for that send. - A template whose approved header format is LOCATION has no header asset to reconstruct at all: Meta only accepts the location at send time, so pass headerLocation (latitude and longitude required) whenever such a template is sent; headerMedia and headerLocation cannot both be supplied. - A button that carries its own value at send time (a copy-code button holding a Pix payment code or a coupon, a flow token) is sent with templateButtonParams, addressed by the button&#39;s index; templateParams covers text variables and dynamic URL buttons only. - CAROUSEL templates take per-card overrides via templateCards, each addressed by the card&#39;s card_index, because card body variables restart at {{1}} per card and cannot be expressed in the flat templateParams order. - Template fields are accepted on the JSON body only, not on multipart requests. For a number you already have a thread with, this sends the template into that thread, which also makes it the way to re-engage a contact after the 24-hour customer-service window has closed. Once the recipient replies (opening the 24h window), send freeform messages with the send-message endpoint (POST /v1/inbox/conversations/{conversationId}/messages). Alternatively, WhatsApp Business Accounts eligible for Meta Direct Send can open a conversation with a business-initiated utility text message and no template: pass category: &#39;utility&#39; together with message (and no templateName). See the category field below. **DM eligibility (X).** Before sending, the endpoint checks if the recipient accepts DMs from your account (via the receives_your_dm field). If not, a 422 error with code DM_NOT_ALLOWED is returned. You can skip this check with skipDmCheck: true if you have already verified eligibility. **X API tier requirement.** DM write endpoints require X API Pro tier ($5,000/month) or Enterprise access. This applies to BYOK (Bring Your Own Key) users who provide their own X API credentials. **Rate limits (X only).** X&#39;s DM API enforces 200 requests per 15 minutes, 1,000 per 24 hours per connected X account, and 15,000 per 24 hours per X developer app (shared across all DM endpoints). These limits do NOT apply to other platforms. WhatsApp sends are governed by Meta&#39;s per-number messaging tiers (unique business-initiated conversations per 24 hours) and per-number throughput instead.
51
+ # Start a direct message conversation with a user. If a conversation with that recipient already exists, the message is added to the existing thread. Supported platforms: X, Bluesky, Reddit, WhatsApp, SMS, and Slack. Other platforms return PLATFORM_NOT_SUPPORTED. **Slack.** Pass a workspace member id as participantId (list them with GET /v1/accounts/{accountId}/slack-members). Zernio opens the DM channel with that member and sends the message; the thread then behaves like any other Slack conversation in the inbox. The member must belong to the connected workspace. **WhatsApp.** This is the endpoint for sending an approved template message to a phone number. Provide templateName, templateLanguage, and templateParams (variable values for the text header, body and dynamic URL buttons, in that order), with the recipient phone in participantId. A template is required because WhatsApp does not permit freeform messages to open a conversation; a missing template returns TEMPLATE_REQUIRED. Before sending, Zernio must resolve an exact APPROVED template definition matching both templateName and templateLanguage. If Meta rejects that lookup, or the exact approved definition is absent, Zernio sends no message and returns the canonical platform error instead. Lookup errors use code &#x60;platform_api_error&#x60;, type &#x60;platform_error&#x60;, and platform &#x60;whatsapp&#x60;. Sanitized Meta code, message, and &#x60;error_data.details&#x60; are returned in &#x60;platformError&#x60;; &#x60;details&#x60; identifies &#x60;phase: template_lookup&#x60;, the query-free endpoint, upstream status, and only safe provider usage or retry headers. - Templates with media headers (image, video, document) are handled automatically: Zernio reads the approved template definition and fills the header at send time with the template&#39;s approved sample asset. To send a DIFFERENT asset per message (e.g. a distinct invoice PDF for each recipient), pass the headerMedia field with a public link (or a Meta media id); it overrides the sample for that send. - A template whose approved header format is LOCATION has no header asset to reconstruct at all: Meta only accepts the location at send time, so pass headerLocation (latitude and longitude required) whenever such a template is sent; headerMedia and headerLocation cannot both be supplied. - A button that carries its own value at send time (a copy-code button holding a Pix payment code or a coupon, a flow token) is sent with templateButtonParams, addressed by the button&#39;s index; templateParams covers text variables and dynamic URL buttons only. - CAROUSEL templates take per-card overrides via templateCards, each addressed by the card&#39;s card_index, because card body variables restart at {{1}} per card and cannot be expressed in the flat templateParams order. - Template fields are accepted on the JSON body only, not on multipart requests. For a number you already have a thread with, this sends the template into that thread, which also makes it the way to re-engage a contact after the 24-hour customer-service window has closed. Once the recipient replies (opening the 24h window), send freeform messages with the send-message endpoint (POST /v1/inbox/conversations/{conversationId}/messages). Alternatively, WhatsApp Business Accounts eligible for Meta Direct Send can open a conversation with a business-initiated utility text message and no template: pass category: &#39;utility&#39; together with message (and no templateName). See the category field below. **DM eligibility (X).** Before sending, the endpoint checks if the recipient accepts DMs from your account (via the receives_your_dm field). If not, a 422 error with code DM_NOT_ALLOWED is returned. You can skip this check with skipDmCheck: true if you have already verified eligibility. **X API tier requirement.** DM write endpoints require X API Pro tier ($5,000/month) or Enterprise access. This applies to BYOK (Bring Your Own Key) users who provide their own X API credentials. **Rate limits (X only).** X&#39;s DM API enforces 200 requests per 15 minutes, 1,000 per 24 hours per connected X account, and 15,000 per 24 hours per X developer app (shared across all DM endpoints). These limits do NOT apply to other platforms. WhatsApp sends are governed by Meta&#39;s per-number messaging tiers (unique business-initiated conversations per 24 hours) and per-number throughput instead.
52
52
  # @param create_inbox_conversation_request
53
53
  # @param [Hash] opts the optional parameters
54
54
  # @return [CreateInboxConversation201Response]
@@ -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 per-recipient rate limit: WhatsApp caps how many messages you may send to the same recipient in a short window and rejects the excess with error code &#x60;131056&#x60; (\&quot;Too many messages sent to this recipient\&quot;). Pace sends to a single recipient at roughly 10 per minute; bursts above that return a &#x60;400&#x60; with code &#x60;131056&#x60;. Sends to other recipients are unaffected, so parallelise across recipients rather than flooding one. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the &#x60;template&#x60; field with a single element carrying the template reference: &#x60;{ \&quot;elements\&quot;: [{ \&quot;name\&quot;: ..., \&quot;language\&quot;: ..., \&quot;components\&quot;: [...] }] }&#x60;. See the &#x60;template&#x60; 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 &#x60;interactive&#x60; field. Tap events are delivered through the &#x60;message.received&#x60; webhook with WhatsApp-specific &#x60;metadata&#x60; fields (&#x60;interactiveType&#x60;, &#x60;interactiveId&#x60;, &#x60;flowResponseJson&#x60;, &#x60;flowResponseData&#x60;). **Idempotency:** send an &#x60;Idempotency-Key&#x60; 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 &#x60;Idempotent-Replayed: true&#x60;) 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 \&quot;request succeeded but the response was lost\&quot; 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&#39;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.
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 per-recipient rate limit: WhatsApp caps how many messages you may send to the same recipient in a short window and rejects the excess with error code &#x60;131056&#x60; (\&quot;Too many messages sent to this recipient\&quot;). Pace sends to a single recipient at roughly 10 per minute; bursts above that return a &#x60;400&#x60; with code &#x60;131056&#x60;. Sends to other recipients are unaffected, so parallelise across recipients rather than flooding one. WhatsApp template messages: to send an approved template into this conversation (required when the 24-hour customer-service window is closed), use the &#x60;template&#x60; field with a single element carrying the template reference: &#x60;{ \&quot;elements\&quot;: [{ \&quot;name\&quot;: ..., \&quot;language\&quot;: ..., \&quot;components\&quot;: [...] }] }&#x60;. See the &#x60;template&#x60; 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. Zernio resolves the exact APPROVED template name and language before any WhatsApp template send. A failed lookup or missing exact definition sends no message and returns code &#x60;platform_api_error&#x60;, type &#x60;platform_error&#x60;, and platform &#x60;whatsapp&#x60;. Sanitized Meta code, message, and &#x60;error_data.details&#x60; are returned in &#x60;platformError&#x60;; &#x60;details&#x60; identifies &#x60;phase: template_lookup&#x60;, the query-free endpoint, upstream status, and only safe provider usage or retry headers. WhatsApp rich interactive messages (list, CTA URL, Flow, location request) are available via the &#x60;interactive&#x60; field. Tap events are delivered through the &#x60;message.received&#x60; webhook with WhatsApp-specific &#x60;metadata&#x60; fields (&#x60;interactiveType&#x60;, &#x60;interactiveId&#x60;, &#x60;flowResponseJson&#x60;, &#x60;flowResponseData&#x60;). **Idempotency:** send an &#x60;Idempotency-Key&#x60; 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 &#x60;Idempotent-Replayed: true&#x60;) 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 \&quot;request succeeded but the response was lost\&quot; 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&#39;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
@@ -0,0 +1,46 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
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 'spec_helper'
14
+ require 'json'
15
+ require 'date'
16
+
17
+ # Unit tests for Zernio::CreateInboxConversation400ResponseAnyOf
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::CreateInboxConversation400ResponseAnyOf do
21
+ #let(:instance) { Zernio::CreateInboxConversation400ResponseAnyOf.new }
22
+
23
+ describe 'test an instance of CreateInboxConversation400ResponseAnyOf' do
24
+ it 'should create an instance of CreateInboxConversation400ResponseAnyOf' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::CreateInboxConversation400ResponseAnyOf)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "error"' do
31
+ it 'should work' do
32
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
+ end
34
+ end
35
+
36
+ describe 'test attribute "code"' do
37
+ it 'should work' do
38
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["PLATFORM_NOT_SUPPORTED", "PLATFORM_LIMITATION", "TEMPLATE_REQUIRED", "INVALID_TEMPLATE_PARAMS", "INVALID_TEMPLATE_BUTTON_PARAM", "INVALID_TEMPLATE_HEADER", "INVALID_TEMPLATE_CARD_PARAM", "DIRECT_SEND_NOT_ELIGIBLE", "DIRECT_SEND_LIMITED", "DIRECT_SEND_BLOCKED"])
40
+ # validator.allowable_values.each do |value|
41
+ # expect { instance.code = value }.not_to raise_error
42
+ # end
43
+ end
44
+ end
45
+
46
+ end