zernio-sdk 0.0.552 → 0.0.553

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/docs/AdCampaignsApi.md +3 -3
  4. data/docs/ConnectApi.md +70 -0
  5. data/docs/ConnectOpenAIAdsCredentials200Response.md +22 -0
  6. data/docs/ConnectOpenAIAdsCredentialsRequest.md +24 -0
  7. data/docs/ConversionEvent.md +1 -1
  8. data/docs/ConversionsApi.md +5 -5
  9. data/docs/CreateStandaloneAdRequest.md +8 -8
  10. data/docs/CreateTrackingTagRequest.md +1 -1
  11. data/docs/GetTrackingTag200Response.md +20 -0
  12. data/docs/ListConversionDestinations200ResponseDestinationsInner.md +1 -1
  13. data/docs/SendConversions200Response.md +1 -1
  14. data/docs/SendConversionsRequest.md +3 -3
  15. data/docs/TrackingTagsApi.md +17 -17
  16. data/docs/UpdateAdRequestBudget.md +1 -1
  17. data/lib/zernio-sdk/api/ad_campaigns_api.rb +10 -10
  18. data/lib/zernio-sdk/api/connect_api.rb +68 -0
  19. data/lib/zernio-sdk/api/conversions_api.rb +8 -8
  20. data/lib/zernio-sdk/api/tracking_tags_api.rb +18 -18
  21. data/lib/zernio-sdk/models/account_with_follower_stats.rb +2 -2
  22. data/lib/zernio-sdk/models/ad.rb +2 -2
  23. data/lib/zernio-sdk/models/ad_campaign.rb +2 -2
  24. data/lib/zernio-sdk/models/ad_tree_campaign.rb +2 -2
  25. data/lib/zernio-sdk/models/bulk_update_ad_campaign_status_request_campaigns_inner.rb +2 -2
  26. data/lib/zernio-sdk/models/connect_open_ai_ads_credentials200_response.rb +165 -0
  27. data/lib/zernio-sdk/models/connect_open_ai_ads_credentials_request.rb +212 -0
  28. data/lib/zernio-sdk/models/conversion_event.rb +1 -1
  29. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +8 -8
  30. data/lib/zernio-sdk/models/create_tracking_tag201_response.rb +2 -2
  31. data/lib/zernio-sdk/models/create_tracking_tag_request.rb +1 -1
  32. data/lib/zernio-sdk/models/get_tracking_tag200_response.rb +190 -0
  33. data/lib/zernio-sdk/models/list_conversion_destinations200_response.rb +2 -2
  34. data/lib/zernio-sdk/models/list_conversion_destinations200_response_destinations_inner.rb +1 -1
  35. data/lib/zernio-sdk/models/list_tracking_tags200_response.rb +2 -2
  36. data/lib/zernio-sdk/models/send_conversions200_response.rb +3 -3
  37. data/lib/zernio-sdk/models/send_conversions_request.rb +3 -3
  38. data/lib/zernio-sdk/models/social_account.rb +2 -2
  39. data/lib/zernio-sdk/models/update_ad_campaign_status_request.rb +2 -2
  40. data/lib/zernio-sdk/models/update_ad_request_budget.rb +1 -0
  41. data/lib/zernio-sdk/models/update_ad_set_request.rb +2 -2
  42. data/lib/zernio-sdk/version.rb +1 -1
  43. data/lib/zernio-sdk.rb +3 -0
  44. data/openapi.yaml +165 -65
  45. data/spec/api/ad_campaigns_api_spec.rb +3 -3
  46. data/spec/api/connect_api_spec.rb +12 -0
  47. data/spec/api/conversions_api_spec.rb +4 -4
  48. data/spec/api/tracking_tags_api_spec.rb +8 -8
  49. data/spec/models/account_with_follower_stats_spec.rb +1 -1
  50. data/spec/models/ad_campaign_spec.rb +1 -1
  51. data/spec/models/ad_spec.rb +1 -1
  52. data/spec/models/ad_tree_campaign_spec.rb +1 -1
  53. data/spec/models/bulk_update_ad_campaign_status_request_campaigns_inner_spec.rb +1 -1
  54. data/spec/models/connect_open_ai_ads_credentials200_response_spec.rb +48 -0
  55. data/spec/models/connect_open_ai_ads_credentials_request_spec.rb +54 -0
  56. data/spec/models/create_tracking_tag201_response_spec.rb +1 -1
  57. data/spec/models/get_tracking_tag200_response_spec.rb +46 -0
  58. data/spec/models/list_conversion_destinations200_response_spec.rb +1 -1
  59. data/spec/models/list_tracking_tags200_response_spec.rb +1 -1
  60. data/spec/models/send_conversions200_response_spec.rb +1 -1
  61. data/spec/models/social_account_spec.rb +1 -1
  62. data/spec/models/update_ad_campaign_status_request_spec.rb +1 -1
  63. data/spec/models/update_ad_set_request_spec.rb +1 -1
  64. metadata +13 -1
@@ -0,0 +1,165 @@
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 ConnectOpenAIAdsCredentials200Response < ApiModelBase
18
+ attr_accessor :account_id
19
+
20
+ attr_accessor :ad_account_name
21
+
22
+ attr_accessor :redirect_url
23
+
24
+ # Attribute mapping from ruby-style variable name to JSON key.
25
+ def self.attribute_map
26
+ {
27
+ :'account_id' => :'accountId',
28
+ :'ad_account_name' => :'adAccountName',
29
+ :'redirect_url' => :'redirectUrl'
30
+ }
31
+ end
32
+
33
+ # Returns attribute mapping this model knows about
34
+ def self.acceptable_attribute_map
35
+ attribute_map
36
+ end
37
+
38
+ # Returns all the JSON keys this model knows about
39
+ def self.acceptable_attributes
40
+ acceptable_attribute_map.values
41
+ end
42
+
43
+ # Attribute type mapping.
44
+ def self.openapi_types
45
+ {
46
+ :'account_id' => :'String',
47
+ :'ad_account_name' => :'String',
48
+ :'redirect_url' => :'String'
49
+ }
50
+ end
51
+
52
+ # List of attributes with nullable: true
53
+ def self.openapi_nullable
54
+ Set.new([
55
+ ])
56
+ end
57
+
58
+ # Initializes the object
59
+ # @param [Hash] attributes Model attributes in the form of hash
60
+ def initialize(attributes = {})
61
+ if (!attributes.is_a?(Hash))
62
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::ConnectOpenAIAdsCredentials200Response` initialize method"
63
+ end
64
+
65
+ # check to see if the attribute exists and convert string to symbol for hash key
66
+ acceptable_attribute_map = self.class.acceptable_attribute_map
67
+ attributes = attributes.each_with_object({}) { |(k, v), h|
68
+ if (!acceptable_attribute_map.key?(k.to_sym))
69
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::ConnectOpenAIAdsCredentials200Response`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
70
+ end
71
+ h[k.to_sym] = v
72
+ }
73
+
74
+ if attributes.key?(:'account_id')
75
+ self.account_id = attributes[:'account_id']
76
+ end
77
+
78
+ if attributes.key?(:'ad_account_name')
79
+ self.ad_account_name = attributes[:'ad_account_name']
80
+ end
81
+
82
+ if attributes.key?(:'redirect_url')
83
+ self.redirect_url = attributes[:'redirect_url']
84
+ end
85
+ end
86
+
87
+ # Show invalid properties with the reasons. Usually used together with valid?
88
+ # @return Array for valid properties with the reasons
89
+ def list_invalid_properties
90
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
91
+ invalid_properties = Array.new
92
+ invalid_properties
93
+ end
94
+
95
+ # Check to see if the all the properties in the model are valid
96
+ # @return true if the model is valid
97
+ def valid?
98
+ warn '[DEPRECATED] the `valid?` method is obsolete'
99
+ true
100
+ end
101
+
102
+ # Checks equality by comparing each attribute.
103
+ # @param [Object] Object to be compared
104
+ def ==(o)
105
+ return true if self.equal?(o)
106
+ self.class == o.class &&
107
+ account_id == o.account_id &&
108
+ ad_account_name == o.ad_account_name &&
109
+ redirect_url == o.redirect_url
110
+ end
111
+
112
+ # @see the `==` method
113
+ # @param [Object] Object to be compared
114
+ def eql?(o)
115
+ self == o
116
+ end
117
+
118
+ # Calculates hash code according to all attributes.
119
+ # @return [Integer] Hash code
120
+ def hash
121
+ [account_id, ad_account_name, redirect_url].hash
122
+ end
123
+
124
+ # Builds the object from hash
125
+ # @param [Hash] attributes Model attributes in the form of hash
126
+ # @return [Object] Returns the model itself
127
+ def self.build_from_hash(attributes)
128
+ return nil unless attributes.is_a?(Hash)
129
+ attributes = attributes.transform_keys(&:to_sym)
130
+ transformed_hash = {}
131
+ openapi_types.each_pair do |key, type|
132
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
133
+ transformed_hash["#{key}"] = nil
134
+ elsif type =~ /\AArray<(.*)>/i
135
+ # check to ensure the input is an array given that the attribute
136
+ # is documented as an array but the input is not
137
+ if attributes[attribute_map[key]].is_a?(Array)
138
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
139
+ end
140
+ elsif !attributes[attribute_map[key]].nil?
141
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
142
+ end
143
+ end
144
+ new(transformed_hash)
145
+ end
146
+
147
+ # Returns the object in the form of hash
148
+ # @return [Hash] Returns the object in the form of hash
149
+ def to_hash
150
+ hash = {}
151
+ self.class.attribute_map.each_pair do |attr, param|
152
+ value = self.send(attr)
153
+ if value.nil?
154
+ is_nullable = self.class.openapi_nullable.include?(attr)
155
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
156
+ end
157
+
158
+ hash[param] = _to_hash(value)
159
+ end
160
+ hash
161
+ end
162
+
163
+ end
164
+
165
+ end
@@ -0,0 +1,212 @@
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 ConnectOpenAIAdsCredentialsRequest < ApiModelBase
18
+ # API key from ChatGPT Ads Manager (Settings). Grants full read/write access on OpenAI's side; Zernio only ever reads with it.
19
+ attr_accessor :api_key
20
+
21
+ # Your Zernio profile ID
22
+ attr_accessor :profile_id
23
+
24
+ # Optional state passthrough for the connect flow.
25
+ attr_accessor :state
26
+
27
+ # Optional URL to redirect to after successful connection
28
+ attr_accessor :redirect_uri
29
+
30
+ # Attribute mapping from ruby-style variable name to JSON key.
31
+ def self.attribute_map
32
+ {
33
+ :'api_key' => :'apiKey',
34
+ :'profile_id' => :'profileId',
35
+ :'state' => :'state',
36
+ :'redirect_uri' => :'redirectUri'
37
+ }
38
+ end
39
+
40
+ # Returns attribute mapping this model knows about
41
+ def self.acceptable_attribute_map
42
+ attribute_map
43
+ end
44
+
45
+ # Returns all the JSON keys this model knows about
46
+ def self.acceptable_attributes
47
+ acceptable_attribute_map.values
48
+ end
49
+
50
+ # Attribute type mapping.
51
+ def self.openapi_types
52
+ {
53
+ :'api_key' => :'String',
54
+ :'profile_id' => :'String',
55
+ :'state' => :'String',
56
+ :'redirect_uri' => :'String'
57
+ }
58
+ end
59
+
60
+ # List of attributes with nullable: true
61
+ def self.openapi_nullable
62
+ Set.new([
63
+ ])
64
+ end
65
+
66
+ # Initializes the object
67
+ # @param [Hash] attributes Model attributes in the form of hash
68
+ def initialize(attributes = {})
69
+ if (!attributes.is_a?(Hash))
70
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::ConnectOpenAIAdsCredentialsRequest` initialize method"
71
+ end
72
+
73
+ # check to see if the attribute exists and convert string to symbol for hash key
74
+ acceptable_attribute_map = self.class.acceptable_attribute_map
75
+ attributes = attributes.each_with_object({}) { |(k, v), h|
76
+ if (!acceptable_attribute_map.key?(k.to_sym))
77
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::ConnectOpenAIAdsCredentialsRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
78
+ end
79
+ h[k.to_sym] = v
80
+ }
81
+
82
+ if attributes.key?(:'api_key')
83
+ self.api_key = attributes[:'api_key']
84
+ else
85
+ self.api_key = nil
86
+ end
87
+
88
+ if attributes.key?(:'profile_id')
89
+ self.profile_id = attributes[:'profile_id']
90
+ else
91
+ self.profile_id = nil
92
+ end
93
+
94
+ if attributes.key?(:'state')
95
+ self.state = attributes[:'state']
96
+ end
97
+
98
+ if attributes.key?(:'redirect_uri')
99
+ self.redirect_uri = attributes[:'redirect_uri']
100
+ end
101
+ end
102
+
103
+ # Show invalid properties with the reasons. Usually used together with valid?
104
+ # @return Array for valid properties with the reasons
105
+ def list_invalid_properties
106
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
107
+ invalid_properties = Array.new
108
+ if @api_key.nil?
109
+ invalid_properties.push('invalid value for "api_key", api_key cannot be nil.')
110
+ end
111
+
112
+ if @profile_id.nil?
113
+ invalid_properties.push('invalid value for "profile_id", profile_id cannot be nil.')
114
+ end
115
+
116
+ invalid_properties
117
+ end
118
+
119
+ # Check to see if the all the properties in the model are valid
120
+ # @return true if the model is valid
121
+ def valid?
122
+ warn '[DEPRECATED] the `valid?` method is obsolete'
123
+ return false if @api_key.nil?
124
+ return false if @profile_id.nil?
125
+ true
126
+ end
127
+
128
+ # Custom attribute writer method with validation
129
+ # @param [Object] api_key Value to be assigned
130
+ def api_key=(api_key)
131
+ if api_key.nil?
132
+ fail ArgumentError, 'api_key cannot be nil'
133
+ end
134
+
135
+ @api_key = api_key
136
+ end
137
+
138
+ # Custom attribute writer method with validation
139
+ # @param [Object] profile_id Value to be assigned
140
+ def profile_id=(profile_id)
141
+ if profile_id.nil?
142
+ fail ArgumentError, 'profile_id cannot be nil'
143
+ end
144
+
145
+ @profile_id = profile_id
146
+ end
147
+
148
+ # Checks equality by comparing each attribute.
149
+ # @param [Object] Object to be compared
150
+ def ==(o)
151
+ return true if self.equal?(o)
152
+ self.class == o.class &&
153
+ api_key == o.api_key &&
154
+ profile_id == o.profile_id &&
155
+ state == o.state &&
156
+ redirect_uri == o.redirect_uri
157
+ end
158
+
159
+ # @see the `==` method
160
+ # @param [Object] Object to be compared
161
+ def eql?(o)
162
+ self == o
163
+ end
164
+
165
+ # Calculates hash code according to all attributes.
166
+ # @return [Integer] Hash code
167
+ def hash
168
+ [api_key, profile_id, state, redirect_uri].hash
169
+ end
170
+
171
+ # Builds the object from hash
172
+ # @param [Hash] attributes Model attributes in the form of hash
173
+ # @return [Object] Returns the model itself
174
+ def self.build_from_hash(attributes)
175
+ return nil unless attributes.is_a?(Hash)
176
+ attributes = attributes.transform_keys(&:to_sym)
177
+ transformed_hash = {}
178
+ openapi_types.each_pair do |key, type|
179
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
180
+ transformed_hash["#{key}"] = nil
181
+ elsif type =~ /\AArray<(.*)>/i
182
+ # check to ensure the input is an array given that the attribute
183
+ # is documented as an array but the input is not
184
+ if attributes[attribute_map[key]].is_a?(Array)
185
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
186
+ end
187
+ elsif !attributes[attribute_map[key]].nil?
188
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
189
+ end
190
+ end
191
+ new(transformed_hash)
192
+ end
193
+
194
+ # Returns the object in the form of hash
195
+ # @return [Hash] Returns the object in the form of hash
196
+ def to_hash
197
+ hash = {}
198
+ self.class.attribute_map.each_pair do |attr, param|
199
+ value = self.send(attr)
200
+ if value.nil?
201
+ is_nullable = self.class.openapi_nullable.include?(attr)
202
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
203
+ end
204
+
205
+ hash[param] = _to_hash(value)
206
+ end
207
+ hash
208
+ end
209
+
210
+ end
211
+
212
+ end
@@ -16,7 +16,7 @@ require 'time'
16
16
  module Zernio
17
17
  # A single conversion event to relay to the ad platform. All PII fields (email, phone, names) are hashed with SHA-256 server-side using each platform's normalization rules before they leave Zernio. Callers send plaintext.
18
18
  class ConversionEvent < ApiModelBase
19
- # Standard event name (Purchase, Lead, CompleteRegistration, AddToCart, InitiateCheckout, AddPaymentInfo, Subscribe, StartTrial, ViewContent, Search, Contact, SubmitApplication, Schedule) or a custom string (only supported on platforms that accept custom events — Meta). Per-platform behavior: - Meta: free-form; standard names match Meta's built-ins. - Google: ignored — the conversion action's category determines the type. - LinkedIn: ignored — the conversion rule's `type` is locked to the destination.
19
+ # Standard event name (Purchase, Lead, CompleteRegistration, AddToCart, InitiateCheckout, AddPaymentInfo, Subscribe, StartTrial, ViewContent, Search, Contact, SubmitApplication, Schedule) or a custom string (only supported on platforms that accept custom events — Meta and OpenAI Ads). Per-platform behavior: - Meta: free-form; standard names match Meta's built-ins. - Google: ignored — the conversion action's category determines the type. - LinkedIn: ignored — the conversion rule's `type` is locked to the destination. - OpenAI Ads: a fixed subset of standard names (Purchase, Lead, AddToCart, ViewContent, InitiateCheckout, CompleteRegistration, Subscribe, StartTrial, Schedule) maps 1:1 onto OpenAI's own event-type enum; anything else is sent as a custom event with the name preserved.
20
20
  attr_accessor :event_name
21
21
 
22
22
  # When the conversion happened, in unix seconds.
@@ -32,7 +32,7 @@ module Zernio
32
32
 
33
33
  attr_accessor :tracking
34
34
 
35
- # Required on legacy and multi-creative shapes; the attach shape inherits it from the ad set. Available goals vary by platform. **Meta** - `conversions`: OUTCOME_SALES. Requires `promotedObject.pixelId` and `promotedObject.customEventType` with a commerce event such as PURCHASE or START_TRIAL. - `lead_conversion`: OUTCOME_LEADS optimizing website pixel leads. Same pixel and event fields, but with a leads-class event such as LEAD, SUBMIT_APPLICATION, SCHEDULE or CONTACT. Meta gates conversion events by objective, so leads-class events are rejected under `conversions`. - `lead_generation`: OUTCOME_LEADS with instant forms. Requires `leadGenFormId`. `promotedObject.pageId` is optional and auto-filled from the connected Page. - `app_promotion`: requires `promotedObject.applicationId` and `promotedObject.objectStoreUrl`. - `catalog_sales`: Advantage+ catalog ads, for example vehicle inventory. Requires `promotedObject.productSetId`, `promotedObject.pixelId` and `promotedObject.customEventType`. Builds a catalog TEMPLATE creative from the copy fields, which may carry template tags like {{product.name}} or {{vehicle.make}}. No imageUrl or video is sent; Meta renders the visuals per catalog item. Discover catalogs via GET /v1/ads/catalogs and product sets via GET /v1/ads/catalogs/{catalogId}/product-sets. Single shape only, no creatives[], adSetId, dynamicCreative or placementAssets. **TikTok** - `conversions`: website-conversion ad group. Requires `promotedObject.pixelId`, your TikTok Pixel ID. Accepts an optional `promotedObject.customEventType` with a TikTok optimization_event code your pixel tracks (newer pixels use e.g. SHOPPING for purchase events; legacy pixels use ON_WEB_ORDER, INITIATE_ORDER, ON_WEB_REGISTER or FORM). To inherit pixel and event from an existing ad group, pass `adSetId` instead. **LinkedIn** - `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`. - `job_applicants` requires a `platformSpecificData.jobs` creative. - For `lead_generation` or `conversions` on LinkedIn, or to promote an existing post, use POST /v1/ads/boost.
35
+ # Required on legacy and multi-creative shapes; the attach shape inherits it from the ad set. Available goals vary by platform. **Meta** - `conversions`: OUTCOME_SALES. Requires `promotedObject.pixelId` and `promotedObject.customEventType` with a commerce event such as PURCHASE or START_TRIAL. - `lead_conversion`: OUTCOME_LEADS optimizing website pixel leads. Same pixel and event fields, but with a leads-class event such as LEAD, SUBMIT_APPLICATION, SCHEDULE or CONTACT. Meta gates conversion events by objective, so leads-class events are rejected under `conversions`. - `lead_generation`: OUTCOME_LEADS with instant forms. Requires `leadGenFormId`. `promotedObject.pageId` is optional and auto-filled from the connected Page. - `app_promotion`: requires `promotedObject.applicationId` and `promotedObject.objectStoreUrl`. - `catalog_sales`: Advantage+ catalog ads, for example vehicle inventory. Requires `promotedObject.productSetId`, `promotedObject.pixelId` and `promotedObject.customEventType`. Builds a catalog TEMPLATE creative from the copy fields, which may carry template tags like {{product.name}} or {{vehicle.make}}. No imageUrl or video is sent; Meta renders the visuals per catalog item. Discover catalogs via GET /v1/ads/catalogs and product sets via GET /v1/ads/catalogs/{catalogId}/product-sets. Single shape only, no creatives[], adSetId, dynamicCreative or placementAssets. **TikTok** - `conversions`: website-conversion ad group. Requires `promotedObject.pixelId`, your TikTok Pixel ID. Accepts an optional `promotedObject.customEventType` with a TikTok optimization_event code your pixel tracks (newer pixels use e.g. SHOPPING for purchase events; legacy pixels use ON_WEB_ORDER, INITIATE_ORDER, ON_WEB_REGISTER or FORM). To inherit pixel and event from an existing ad group, pass `adSetId` instead. **LinkedIn** - `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`. - `job_applicants` requires a `platformSpecificData.jobs` creative. - For `lead_generation` or `conversions` on LinkedIn, or to promote an existing post, use POST /v1/ads/boost. **OpenAI Ads** - Only `traffic`, `awareness`, and `conversions` are supported (other goals return 400). Maps to OpenAI's `bidding_type` (clicks, impressions, conversions respectively). `conversions` requires an active conversion event setting on the account; create a tracking tag with `defaultEventType` via the tracking-tags API (`POST /v1/accounts/{accountId}/tracking-tags`), or configure a conversion event in OpenAI Ads Manager, or the request returns 422.
36
36
  attr_accessor :goal
37
37
 
38
38
  # Meta only. Explicit ad-set `optimization_goal` (e.g. `LANDING_PAGE_VIEWS`, `LINK_CLICKS`, `REACH`, `IMPRESSIONS`, `OFFSITE_CONVERSIONS`, `THRUPLAY`, `LEAD_GENERATION`). Overrides the default derived from `goal` (e.g. `traffic` defaults to `LINK_CLICKS`). Forwarded verbatim to Meta, which validates compatibility with the campaign objective and rejects incompatible combinations.
@@ -53,10 +53,10 @@ module Zernio
53
53
  # Meta only, single standalone shape only (no creatives[], adSetId, or RESERVED). Dry-run: each node runs Meta's execution_options validate_only and NOTHING is created or persisted. Children need real parents, so a fresh tree validates the campaign + creative (the ad set needs its campaign to exist — pass existingCampaignId to validate it too; the ad itself is never validatable pre-create). A Meta validation failure returns the 400 verbatim; success returns 200 with per-node results instead of an ad.
54
54
  attr_accessor :validate_only
55
55
 
56
- # Required on legacy + multi-creative shapes. Inherited on attach.
56
+ # Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType).
57
57
  attr_accessor :budget_amount
58
58
 
59
- # Required on legacy + multi-creative shapes. Inherited on attach.
59
+ # Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads accepts lifetime only (no daily-budget concept on the platform); sending daily returns 422. OpenAI Ads lifetime budgets require `endDate` to give the lifetime cap a spend window.
60
60
  attr_accessor :budget_type
61
61
 
62
62
  # Meta and TikTok. Publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused and skips activation, so you can review before they spend. On TikTok the whole campaign > ad group > ad hierarchy stays paused.
@@ -67,13 +67,13 @@ module Zernio
67
67
 
68
68
  attr_accessor :currency
69
69
 
70
- # Required for Meta, Google, Pinterest, and LinkedIn on legacy + attach shapes (skip for multi-creative — use `creatives[].headline`). Ignored for TikTok and X/Twitter. Max: Meta=255, Google=30, Pinterest=100, LinkedIn=400. On LinkedIn this is the ad's headline (the bold text on the creative); for traffic ads it's the link card title.
70
+ # Required for Meta, Google, Pinterest, LinkedIn, and OpenAI Ads on legacy + attach shapes (skip for multi-creative — use `creatives[].headline`). Ignored for TikTok and X/Twitter. Max: Meta=255, Google=30, Pinterest=100, LinkedIn=400, OpenAI=50 (min 3). On LinkedIn this is the ad's headline (the bold text on the creative); for traffic ads it's the link card title. On OpenAI Ads this is the chat card's title.
71
71
  attr_accessor :headline
72
72
 
73
73
  # Google Display only — defaults to `headline` if omitted. On LinkedIn, reused as the optional secondary description text on traffic (link) ads; omitted if not provided.
74
74
  attr_accessor :long_headline
75
75
 
76
- # Required on legacy + attach shapes. For X/Twitter this is the tweet text (max 280 chars including a ~24-char URL when `linkUrl` is set). On LinkedIn this is the post commentary (the intro text shown above the ad). Max: Google=90, Pinterest=500.
76
+ # Required on legacy + attach shapes. For X/Twitter this is the tweet text (max 280 chars including a ~24-char URL when `linkUrl` is set). On LinkedIn this is the post commentary (the intro text shown above the ad). On OpenAI Ads this is the chat card's body text. Max: Google=90, Pinterest=500, OpenAI=100.
77
77
  attr_accessor :body
78
78
 
79
79
  # Meta only (facebook/instagram). Link description — the secondary text shown below the headline (Meta's link_data.description; on video creatives mapped to video_data.link_description). When omitted, Meta auto-pulls the destination URL's OpenGraph description. Applies on legacy, attach, and placementAssets shapes; for multi-creative use creatives[].description (this field is the shared fallback). For multi-text variations use dynamicCreative.descriptions instead.
@@ -82,13 +82,13 @@ module Zernio
82
82
  # Required on legacy + attach shapes for Meta. Honoured on TikTok (passes through to the Spark Ad creative's `call_to_action`) and on LinkedIn (the CTA button on the ad; defaults to LEARN_MORE when `linkUrl` is set). LinkedIn accepts: LEARN_MORE, SIGN_UP, DOWNLOAD, SUBSCRIBE, REGISTER, JOIN, ATTEND, REQUEST_DEMO, VIEW_QUOTE, APPLY, SEE_MORE, SHOP_NOW, BUY_NOW. Ignored by Google, Pinterest, and X/Twitter.
83
83
  attr_accessor :call_to_action
84
84
 
85
- # Required on legacy + attach shapes (skip for multi-creative). On LinkedIn it's the ad's destination URL; required for `traffic` ads, optional for `engagement` / `awareness`. NOT required when `goal` is `lead_generation` (the ad opens a Lead Gen form instead of a destination). On LinkedIn, `imageUrl` + `linkUrl` publishes an ARTICLE-content creative; this is LinkedIn's article ad format, with the image as thumbnail and `longHeadline` as description.
85
+ # Required on legacy + attach shapes (skip for multi-creative). On LinkedIn it's the ad's destination URL; required for `traffic` ads, optional for `engagement` / `awareness`. NOT required when `goal` is `lead_generation` (the ad opens a Lead Gen form instead of a destination). On LinkedIn, `imageUrl` + `linkUrl` publishes an ARTICLE-content creative; this is LinkedIn's article ad format, with the image as thumbnail and `longHeadline` as description. Required for OpenAI Ads (the chat card's target_url).
86
86
  attr_accessor :link_url
87
87
 
88
88
  # Meta Lead Gen forms only (facebook/instagram). The leadgen_forms ID to attach to the ad's creative — create one via POST /v1/ads/lead-forms. REQUIRED when `goal` is `lead_generation`, and on every ATTACH (`adSetId`) call that targets a lead ad set (the form attaches per-ad; Meta rejects a formless ad in a lead ad set). Ignored otherwise. The ad set's promoted_object.page_id + LEAD_GENERATION optimization + destination_type ON_AD are derived automatically from the goal. Both `placementAssets` (per-placement creative) and `dynamicCreative` (multi-text / multi-asset pool, e.g. multiple headlines and primary texts) ARE supported on instant-form lead ads — the form is attached for you, and for `dynamicCreative` the ad set is created as a Dynamic Creative ad set automatically (Meta requires that for any multi-text feed; there is no non-DCO multi-text path). Send a single `imageUrls` entry plus your text variations to get Meta's \"Multiple Text Options\" behavior on a lead ad.
89
89
  attr_accessor :lead_gen_form_id
90
90
 
91
- # Image creative for Meta/Google/Pinterest/LinkedIn on legacy + attach shapes (mutually exclusive with `video`). Required for LinkedIn ads unless `video` is set. Not required for Google Search campaigns. For TikTok, this field carries the VIDEO URL (the TikTok ads endpoint is video-only; the field retains the `imageUrl` name for cross-platform consistency). Ignored for X/Twitter. For Google Display, treated as the landscape image (alias of `images.landscape`); supply `images.square` alongside or the request is rejected. For LinkedIn the image is uploaded to LinkedIn under the authoring Company Page (see `organizationId`); recommended ratio 1.91:1 (e.g. 1200×627).
91
+ # Image creative for Meta/Google/Pinterest/LinkedIn on legacy + attach shapes (mutually exclusive with `video`). Required for LinkedIn ads unless `video` is set. Not required for Google Search campaigns. For TikTok, this field carries the VIDEO URL (the TikTok ads endpoint is video-only; the field retains the `imageUrl` name for cross-platform consistency). Ignored for X/Twitter. For Google Display, treated as the landscape image (alias of `images.landscape`); supply `images.square` alongside or the request is rejected. For LinkedIn the image is uploaded to LinkedIn under the authoring Company Page (see `organizationId`); recommended ratio 1.91:1 (e.g. 1200×627). Required for OpenAI Ads (uploaded as the chat card's image; OpenAI has no video ad format).
92
92
  attr_accessor :image_url
93
93
 
94
94
  attr_accessor :images
@@ -119,7 +119,7 @@ module Zernio
119
119
  # Nested targeting object — the same TargetingSpec shape as `POST /v1/ads/boost`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. Merged UNDER the flat inline targeting fields below: `savedTargetingId` < `targeting` < flat fields (a flat field present on the body replaces the nested value entirely). Both forms are equivalent; use whichever your integration already builds.
120
120
  attr_accessor :targeting
121
121
 
122
- # ISO 3166-1 alpha-2 country codes (e.g. ['NL']). Defaults to ['US'] when no other geo targeting (flat or nested `targeting`) is provided. (LinkedIn currently honours country-level targeting only.)
122
+ # ISO 3166-1 alpha-2 country codes (e.g. ['NL']). Defaults to ['US'] when no other geo targeting (flat or nested `targeting`) is provided. (LinkedIn and OpenAI Ads currently honour country-level targeting only; any other targeting field returns 400 for OpenAI Ads.)
123
123
  attr_accessor :countries
124
124
 
125
125
  # City-level geo targeting (Meta and TikTok). Each city is targeted by the platform's opaque `key` (the city ID) which can be looked up via `GET /v1/ads/targeting/search?dimension=geo&q=<name>&countryCode=<ISO>`. Optional `radius` + `distance_unit` (Meta only) extend the targeting beyond the city limits (e.g. radius 25 km around the city center). Both must be set together, or both omitted (Meta defaults to ~16 km when omitted). On Meta, cannot overlap with the same country in `countries` (Meta returns a \"locations overlap\" error). Either drop the country or scope it to a different country. On TikTok, keys are numeric location ids and can be sent without `countries`.
@@ -110,7 +110,7 @@ module Zernio
110
110
  # @return true if the model is valid
111
111
  def valid?
112
112
  warn '[DEPRECATED] the `valid?` method is obsolete'
113
- platform_validator = EnumAttributeValidator.new('String', ["metaads"])
113
+ platform_validator = EnumAttributeValidator.new('String', ["metaads", "openaiads"])
114
114
  return false unless platform_validator.valid?(@platform)
115
115
  true
116
116
  end
@@ -118,7 +118,7 @@ module Zernio
118
118
  # Custom attribute writer method checking allowed values (enum).
119
119
  # @param [Object] platform Object to be assigned
120
120
  def platform=(platform)
121
- validator = EnumAttributeValidator.new('String', ["metaads"])
121
+ validator = EnumAttributeValidator.new('String', ["metaads", "openaiads"])
122
122
  unless validator.valid?(platform)
123
123
  fail ArgumentError, "invalid value for \"platform\", must be one of #{validator.allowable_values}."
124
124
  end
@@ -15,7 +15,7 @@ require 'time'
15
15
 
16
16
  module Zernio
17
17
  class CreateTrackingTagRequest < ApiModelBase
18
- # Meta ad account id, e.g. `act_123456789`.
18
+ # Meta ad account id, e.g. `act_123456789`. Required by this endpoint but ignored for OpenAI Ads.
19
19
  attr_accessor :ad_account_id
20
20
 
21
21
  attr_accessor :name
@@ -0,0 +1,190 @@
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 GetTrackingTag200Response < ApiModelBase
18
+ attr_accessor :platform
19
+
20
+ attr_accessor :tag
21
+
22
+ class EnumAttributeValidator
23
+ attr_reader :datatype
24
+ attr_reader :allowable_values
25
+
26
+ def initialize(datatype, allowable_values)
27
+ @allowable_values = allowable_values.map do |value|
28
+ case datatype.to_s
29
+ when /Integer/i
30
+ value.to_i
31
+ when /Float/i
32
+ value.to_f
33
+ else
34
+ value
35
+ end
36
+ end
37
+ end
38
+
39
+ def valid?(value)
40
+ !value || allowable_values.include?(value)
41
+ end
42
+ end
43
+
44
+ # Attribute mapping from ruby-style variable name to JSON key.
45
+ def self.attribute_map
46
+ {
47
+ :'platform' => :'platform',
48
+ :'tag' => :'tag'
49
+ }
50
+ end
51
+
52
+ # Returns attribute mapping this model knows about
53
+ def self.acceptable_attribute_map
54
+ attribute_map
55
+ end
56
+
57
+ # Returns all the JSON keys this model knows about
58
+ def self.acceptable_attributes
59
+ acceptable_attribute_map.values
60
+ end
61
+
62
+ # Attribute type mapping.
63
+ def self.openapi_types
64
+ {
65
+ :'platform' => :'String',
66
+ :'tag' => :'TrackingTag'
67
+ }
68
+ end
69
+
70
+ # List of attributes with nullable: true
71
+ def self.openapi_nullable
72
+ Set.new([
73
+ ])
74
+ end
75
+
76
+ # Initializes the object
77
+ # @param [Hash] attributes Model attributes in the form of hash
78
+ def initialize(attributes = {})
79
+ if (!attributes.is_a?(Hash))
80
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::GetTrackingTag200Response` initialize method"
81
+ end
82
+
83
+ # check to see if the attribute exists and convert string to symbol for hash key
84
+ acceptable_attribute_map = self.class.acceptable_attribute_map
85
+ attributes = attributes.each_with_object({}) { |(k, v), h|
86
+ if (!acceptable_attribute_map.key?(k.to_sym))
87
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::GetTrackingTag200Response`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
88
+ end
89
+ h[k.to_sym] = v
90
+ }
91
+
92
+ if attributes.key?(:'platform')
93
+ self.platform = attributes[:'platform']
94
+ end
95
+
96
+ if attributes.key?(:'tag')
97
+ self.tag = attributes[:'tag']
98
+ end
99
+ end
100
+
101
+ # Show invalid properties with the reasons. Usually used together with valid?
102
+ # @return Array for valid properties with the reasons
103
+ def list_invalid_properties
104
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
105
+ invalid_properties = Array.new
106
+ invalid_properties
107
+ end
108
+
109
+ # Check to see if the all the properties in the model are valid
110
+ # @return true if the model is valid
111
+ def valid?
112
+ warn '[DEPRECATED] the `valid?` method is obsolete'
113
+ platform_validator = EnumAttributeValidator.new('String', ["metaads"])
114
+ return false unless platform_validator.valid?(@platform)
115
+ true
116
+ end
117
+
118
+ # Custom attribute writer method checking allowed values (enum).
119
+ # @param [Object] platform Object to be assigned
120
+ def platform=(platform)
121
+ validator = EnumAttributeValidator.new('String', ["metaads"])
122
+ unless validator.valid?(platform)
123
+ fail ArgumentError, "invalid value for \"platform\", must be one of #{validator.allowable_values}."
124
+ end
125
+ @platform = platform
126
+ end
127
+
128
+ # Checks equality by comparing each attribute.
129
+ # @param [Object] Object to be compared
130
+ def ==(o)
131
+ return true if self.equal?(o)
132
+ self.class == o.class &&
133
+ platform == o.platform &&
134
+ tag == o.tag
135
+ end
136
+
137
+ # @see the `==` method
138
+ # @param [Object] Object to be compared
139
+ def eql?(o)
140
+ self == o
141
+ end
142
+
143
+ # Calculates hash code according to all attributes.
144
+ # @return [Integer] Hash code
145
+ def hash
146
+ [platform, tag].hash
147
+ end
148
+
149
+ # Builds the object from hash
150
+ # @param [Hash] attributes Model attributes in the form of hash
151
+ # @return [Object] Returns the model itself
152
+ def self.build_from_hash(attributes)
153
+ return nil unless attributes.is_a?(Hash)
154
+ attributes = attributes.transform_keys(&:to_sym)
155
+ transformed_hash = {}
156
+ openapi_types.each_pair do |key, type|
157
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
158
+ transformed_hash["#{key}"] = nil
159
+ elsif type =~ /\AArray<(.*)>/i
160
+ # check to ensure the input is an array given that the attribute
161
+ # is documented as an array but the input is not
162
+ if attributes[attribute_map[key]].is_a?(Array)
163
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
164
+ end
165
+ elsif !attributes[attribute_map[key]].nil?
166
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
167
+ end
168
+ end
169
+ new(transformed_hash)
170
+ end
171
+
172
+ # Returns the object in the form of hash
173
+ # @return [Hash] Returns the object in the form of hash
174
+ def to_hash
175
+ hash = {}
176
+ self.class.attribute_map.each_pair do |attr, param|
177
+ value = self.send(attr)
178
+ if value.nil?
179
+ is_nullable = self.class.openapi_nullable.include?(attr)
180
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
181
+ end
182
+
183
+ hash[param] = _to_hash(value)
184
+ end
185
+ hash
186
+ end
187
+
188
+ end
189
+
190
+ end