late-sdk 0.0.770 → 0.0.772

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -0
  3. data/docs/AdCampaignsApi.md +72 -0
  4. data/docs/AnalyticsApi.md +2 -2
  5. data/docs/AttachCampaignAssets201Response.md +24 -0
  6. data/docs/AttachCampaignAssetsRequest.md +24 -0
  7. data/docs/AttachCampaignAssetsRequestSitelinksInner.md +24 -0
  8. data/docs/AttachCampaignAssetsRequestStructuredSnippetsInner.md +20 -0
  9. data/docs/CreateInboxConversationRequest.md +3 -1
  10. data/docs/CreateInboxConversationRequestTemplateButtonParamsInner.md +22 -0
  11. data/docs/CreateStandaloneAdRequest.md +4 -0
  12. data/docs/CreateStandaloneAdRequestStructuredSnippetsInner.md +20 -0
  13. data/docs/MessagesApi.md +1 -1
  14. data/docs/PostAnalytics.md +4 -0
  15. data/docs/TargetingSpec.md +2 -2
  16. data/lib/zernio-sdk/api/ad_campaigns_api.rb +74 -0
  17. data/lib/zernio-sdk/api/analytics_api.rb +3 -3
  18. data/lib/zernio-sdk/api/messages_api.rb +2 -2
  19. data/lib/zernio-sdk/models/ad_tree_campaign_optimization_goal.rb +1 -0
  20. data/lib/zernio-sdk/models/attach_campaign_assets201_response.rb +180 -0
  21. data/lib/zernio-sdk/models/attach_campaign_assets_request.rb +283 -0
  22. data/lib/zernio-sdk/models/attach_campaign_assets_request_sitelinks_inner.rb +282 -0
  23. data/lib/zernio-sdk/models/attach_campaign_assets_request_structured_snippets_inner.rb +234 -0
  24. data/lib/zernio-sdk/models/create_inbox_conversation_request.rb +33 -2
  25. data/lib/zernio-sdk/models/create_inbox_conversation_request_template_button_params_inner.rb +270 -0
  26. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +81 -1
  27. data/lib/zernio-sdk/models/create_standalone_ad_request_structured_snippets_inner.rb +235 -0
  28. data/lib/zernio-sdk/models/post_analytics.rb +21 -1
  29. data/lib/zernio-sdk/models/targeting_spec.rb +2 -0
  30. data/lib/zernio-sdk/version.rb +1 -1
  31. data/lib/zernio-sdk.rb +6 -0
  32. data/openapi.yaml +167 -10
  33. data/spec/api/ad_campaigns_api_spec.rb +13 -0
  34. data/spec/api/analytics_api_spec.rb +1 -1
  35. data/spec/api/messages_api_spec.rb +1 -1
  36. data/spec/models/attach_campaign_assets201_response_spec.rb +54 -0
  37. data/spec/models/attach_campaign_assets_request_sitelinks_inner_spec.rb +54 -0
  38. data/spec/models/attach_campaign_assets_request_spec.rb +54 -0
  39. data/spec/models/attach_campaign_assets_request_structured_snippets_inner_spec.rb +46 -0
  40. data/spec/models/create_inbox_conversation_request_spec.rb +6 -0
  41. data/spec/models/create_inbox_conversation_request_template_button_params_inner_spec.rb +52 -0
  42. data/spec/models/create_standalone_ad_request_spec.rb +12 -0
  43. data/spec/models/create_standalone_ad_request_structured_snippets_inner_spec.rb +46 -0
  44. data/spec/models/post_analytics_spec.rb +12 -0
  45. data/zernio-sdk-0.0.772.gem +0 -0
  46. metadata +26 -2
  47. data/zernio-sdk-0.0.770.gem +0 -0
@@ -41,6 +41,12 @@ module Zernio
41
41
  # Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.
42
42
  attr_accessor :ig_reels_video_view_total_time
43
43
 
44
+ # Instagram Reels only: the rate of initial views that skipped the reel within its first 3 seconds, as reported by Meta. Passed through exactly as Meta reports it, with no rescaling, so do not assume a 0-1 share. Meta labels the metric estimated and in development, so it can move between syncs. 0 for non-Reels media and other platforms. When a post is published to several accounts, the aggregate is weighted by views.
45
+ attr_accessor :reels_skip_rate
46
+
47
+ # Instagram only: reposts of the media by other users, minus deleted reposts. Available on feed posts, reels and stories. 0 for other platforms, including Threads, where reposts are counted in shares instead.
48
+ attr_accessor :reposts
49
+
44
50
  # Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).
45
51
  attr_accessor :video_duration_seconds
46
52
 
@@ -63,6 +69,8 @@ module Zernio
63
69
  :'follows' => :'follows',
64
70
  :'ig_reels_avg_watch_time' => :'igReelsAvgWatchTime',
65
71
  :'ig_reels_video_view_total_time' => :'igReelsVideoViewTotalTime',
72
+ :'reels_skip_rate' => :'reelsSkipRate',
73
+ :'reposts' => :'reposts',
66
74
  :'video_duration_seconds' => :'videoDurationSeconds',
67
75
  :'engagement_rate' => :'engagementRate',
68
76
  :'last_updated' => :'lastUpdated'
@@ -93,6 +101,8 @@ module Zernio
93
101
  :'follows' => :'Integer',
94
102
  :'ig_reels_avg_watch_time' => :'Integer',
95
103
  :'ig_reels_video_view_total_time' => :'Integer',
104
+ :'reels_skip_rate' => :'Float',
105
+ :'reposts' => :'Integer',
96
106
  :'video_duration_seconds' => :'Integer',
97
107
  :'engagement_rate' => :'Float',
98
108
  :'last_updated' => :'Time'
@@ -166,6 +176,14 @@ module Zernio
166
176
  self.ig_reels_video_view_total_time = attributes[:'ig_reels_video_view_total_time']
167
177
  end
168
178
 
179
+ if attributes.key?(:'reels_skip_rate')
180
+ self.reels_skip_rate = attributes[:'reels_skip_rate']
181
+ end
182
+
183
+ if attributes.key?(:'reposts')
184
+ self.reposts = attributes[:'reposts']
185
+ end
186
+
169
187
  if attributes.key?(:'video_duration_seconds')
170
188
  self.video_duration_seconds = attributes[:'video_duration_seconds']
171
189
  end
@@ -210,6 +228,8 @@ module Zernio
210
228
  follows == o.follows &&
211
229
  ig_reels_avg_watch_time == o.ig_reels_avg_watch_time &&
212
230
  ig_reels_video_view_total_time == o.ig_reels_video_view_total_time &&
231
+ reels_skip_rate == o.reels_skip_rate &&
232
+ reposts == o.reposts &&
213
233
  video_duration_seconds == o.video_duration_seconds &&
214
234
  engagement_rate == o.engagement_rate &&
215
235
  last_updated == o.last_updated
@@ -224,7 +244,7 @@ module Zernio
224
244
  # Calculates hash code according to all attributes.
225
245
  # @return [Integer] Hash code
226
246
  def hash
227
- [impressions, reach, likes, comments, shares, saves, clicks, views, follows, ig_reels_avg_watch_time, ig_reels_video_view_total_time, video_duration_seconds, engagement_rate, last_updated].hash
247
+ [impressions, reach, likes, comments, shares, saves, clicks, views, follows, ig_reels_avg_watch_time, ig_reels_video_view_total_time, reels_skip_rate, reposts, video_duration_seconds, engagement_rate, last_updated].hash
228
248
  end
229
249
 
230
250
  # Builds the object from hash
@@ -36,8 +36,10 @@ module Zernio
36
36
 
37
37
  attr_accessor :excluded_locations
38
38
 
39
+ # Minimum age. Applied on Meta, TikTok and Pinterest; ignored on Google, LinkedIn and X. Each platform clamps to its own range: Meta and Pinterest effectively cap at 65 (65 = 65+), TikTok maps up to 100. Pinterest has no under-18 bucket, so an ageMin below 18 starts at 18 there.
39
40
  attr_accessor :age_min
40
41
 
42
+ # Maximum age. Same per-platform application and clamping as ageMin.
41
43
  attr_accessor :age_max
42
44
 
43
45
  # Restrict by gender. 'all' (default) targets everyone. Applied on Meta, TikTok and Pinterest. Ignored on Google, LinkedIn and X.
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.770'
14
+ VERSION = '0.0.772'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -88,6 +88,10 @@ require 'zernio-sdk/models/archive_lead_form200_response'
88
88
  require 'zernio-sdk/models/assign_google_business_location200_response'
89
89
  require 'zernio-sdk/models/assign_google_business_location200_response_account'
90
90
  require 'zernio-sdk/models/assign_google_business_location_request'
91
+ require 'zernio-sdk/models/attach_campaign_assets201_response'
92
+ require 'zernio-sdk/models/attach_campaign_assets_request'
93
+ require 'zernio-sdk/models/attach_campaign_assets_request_sitelinks_inner'
94
+ require 'zernio-sdk/models/attach_campaign_assets_request_structured_snippets_inner'
91
95
  require 'zernio-sdk/models/attach_number_to_sip_trunk200_response'
92
96
  require 'zernio-sdk/models/attach_number_to_sip_trunk_request'
93
97
  require 'zernio-sdk/models/batch_get_google_business_reviews200_response'
@@ -258,6 +262,7 @@ require 'zernio-sdk/models/create_inbox_conversation422_response'
258
262
  require 'zernio-sdk/models/create_inbox_conversation429_response'
259
263
  require 'zernio-sdk/models/create_inbox_conversation_request'
260
264
  require 'zernio-sdk/models/create_inbox_conversation_request_header_media'
265
+ require 'zernio-sdk/models/create_inbox_conversation_request_template_button_params_inner'
261
266
  require 'zernio-sdk/models/create_invite_token201_response'
262
267
  require 'zernio-sdk/models/create_invite_token_request'
263
268
  require 'zernio-sdk/models/create_lead_form200_response'
@@ -323,6 +328,7 @@ require 'zernio-sdk/models/create_standalone_ad_request_platform_specific_data'
323
328
  require 'zernio-sdk/models/create_standalone_ad_request_promoted_object'
324
329
  require 'zernio-sdk/models/create_standalone_ad_request_regions_inner'
325
330
  require 'zernio-sdk/models/create_standalone_ad_request_sitelinks_inner'
331
+ require 'zernio-sdk/models/create_standalone_ad_request_structured_snippets_inner'
326
332
  require 'zernio-sdk/models/create_standalone_ad_request_tracking'
327
333
  require 'zernio-sdk/models/create_standalone_ad_request_translations_inner'
328
334
  require 'zernio-sdk/models/create_standalone_ad_request_video'
data/openapi.yaml CHANGED
@@ -7159,6 +7159,8 @@ components:
7159
7159
  follows: { type: integer, example: 0, description: 'Instagram feed posts and stories only: organic accounts that started following from this post. 0 for reels and other platforms.' }
7160
7160
  igReelsAvgWatchTime: { type: integer, example: 0, description: 'Instagram Reels only: average watch time per play, in milliseconds. 0 for non-Reels media and other platforms.' }
7161
7161
  igReelsVideoViewTotalTime: { type: integer, example: 0, description: 'Instagram Reels only: total watch time including replays, in milliseconds. 0 for non-Reels media and other platforms.' }
7162
+ reelsSkipRate: { type: number, example: 0, description: 'Instagram Reels only: the rate of initial views that skipped the reel within its first 3 seconds, as reported by Meta. Passed through exactly as Meta reports it, with no rescaling, so do not assume a 0-1 share. Meta labels the metric estimated and in development, so it can move between syncs. 0 for non-Reels media and other platforms. When a post is published to several accounts, the aggregate is weighted by views.' }
7163
+ reposts: { type: integer, example: 0, description: 'Instagram only: reposts of the media by other users, minus deleted reposts. Available on feed posts, reels and stories. 0 for other platforms, including Threads, where reposts are counted in shares instead.' }
7162
7164
  videoDurationSeconds: { type: [integer, "null"], example: 30, description: 'Video length in seconds. Currently Instagram Reels only; combine with igReelsAvgWatchTime (ms) to estimate retention. Null when unknown (other platforms, non-video media, or when Instagram does not expose the media URL, e.g. reels with copyrighted audio).' }
7163
7165
  engagementRate: { type: number, example: 6.59, description: 'Percentage, rounded to 2 decimals: (likes + comments + shares + saves) / (impressions or reach or views) * 100. Clicks and follows are never counted. The denominator is the FIRST of impressions, reach, views that is non-zero, so it is not the same basis on every post: a post with impressions divides by impressions, one without falls back to reach, then to views. If you need a single consistent basis (e.g. interactions / reach), compute it from the raw fields above. The engagementRate on the LinkedIn account endpoints is a different formula.' }
7164
7166
  lastUpdated: { type: string, format: date-time }
@@ -8186,8 +8188,8 @@ components:
8186
8188
  distanceUnit: { type: string, enum: [mile, kilometer] }
8187
8189
  name: { type: string }
8188
8190
  address: { type: string, description: "Optional label, sent to Meta as `address_string`. latitude/longitude take precedence for the pin location." }
8189
- ageMin: { type: integer, minimum: 13, maximum: 100 }
8190
- ageMax: { type: integer, minimum: 13, maximum: 100 }
8191
+ ageMin: { type: integer, minimum: 13, maximum: 100, description: "Minimum age. Applied on Meta, TikTok and Pinterest; ignored on Google, LinkedIn and X. Each platform clamps to its own range: Meta and Pinterest effectively cap at 65 (65 = 65+), TikTok maps up to 100. Pinterest has no under-18 bucket, so an ageMin below 18 starts at 18 there." }
8192
+ ageMax: { type: integer, minimum: 13, maximum: 100, description: "Maximum age. Same per-platform application and clamping as ageMin." }
8191
8193
  gender: { type: string, enum: [all, male, female], description: "Restrict by gender. 'all' (default) targets everyone. Applied on Meta, TikTok and Pinterest. Ignored on Google, LinkedIn and X." }
8192
8194
  incomeTier:
8193
8195
  type: string
@@ -8552,8 +8554,12 @@ components:
8552
8554
  description: "Google-only. Raw campaign.advertising_channel_type (SEARCH, PERFORMANCE_MAX, LOCAL_SERVICES, VIDEO, DEMAND_GEN, DISPLAY, SHOPPING, ...). Serving surface, distinct from platformObjective (advertiser intent). Null/absent for non-Google platforms."
8553
8555
  platformObjective: { type: [string, "null"], description: "Raw Meta campaign objective (e.g. OUTCOME_SALES, OUTCOME_LEADS, OUTCOME_TRAFFIC)" }
8554
8556
  optimizationGoal:
8555
- type: [string, array]
8556
- items: { type: string }
8557
+ # anyOf, not type: [string, array]: hey-api resolves a type-array carrying items
8558
+ # through the array branch and drops the string one (@zernio/node 0.2.640).
8559
+ anyOf:
8560
+ - type: string
8561
+ - type: array
8562
+ items: { type: string }
8557
8563
  description: 'A single string when every ad set shares one optimization goal; a JSON array of the distinct goals when ad sets differ (never a comma-joined string); array element order is not guaranteed, treat it as an unordered set; the key is absent when no ad set carries a goal. Meta: e.g. OFFSITE_CONVERSIONS, VALUE, LEAD_GENERATION. LinkedIn: the campaign optimizationTargetType (e.g. MAX_CLICK, MAX_IMPRESSION, NONE); `NONE` with a manual costType is a campaign LinkedIn will not deliver.'
8558
8564
  bidStrategy:
8559
8565
  anyOf:
@@ -8630,8 +8636,12 @@ components:
8630
8636
  description: "Google-only. Raw campaign.advertising_channel_type. See AdTreeCampaign.advertisingChannelType."
8631
8637
  platformObjective: { type: [string, "null"], description: "Raw Meta campaign objective (e.g. OUTCOME_SALES, OUTCOME_LEADS, OUTCOME_TRAFFIC)" }
8632
8638
  optimizationGoal:
8633
- type: [string, array]
8634
- items: { type: string }
8639
+ # anyOf, not type: [string, array]: hey-api resolves a type-array carrying items
8640
+ # through the array branch and drops the string one (@zernio/node 0.2.640).
8641
+ anyOf:
8642
+ - type: string
8643
+ - type: array
8644
+ items: { type: string }
8635
8645
  description: 'A single string when every ad set shares one optimization goal; a JSON array of the distinct goals when ad sets differ (never a comma-joined string); array element order is not guaranteed, treat it as an unordered set; the key is absent when no ad set carries a goal. Meta: e.g. OFFSITE_CONVERSIONS, VALUE, LEAD_GENERATION. LinkedIn: the campaign optimizationTargetType (e.g. MAX_CLICK, MAX_IMPRESSION, NONE); `NONE` with a manual costType is a campaign LinkedIn will not deliver.'
8636
8646
  bidStrategy:
8637
8647
  anyOf:
@@ -10443,8 +10453,8 @@ paths:
10443
10453
  description: Page number (default 1)
10444
10454
  - name: sortBy
10445
10455
  in: query
10446
- schema: { type: string, enum: [date, engagement, impressions, reach, likes, comments, shares, saves, clicks, views, follows], default: date }
10447
- description: Sort by date, engagement, or a specific metric
10456
+ schema: { type: string, enum: [date, engagement, impressions, reach, likes, comments, shares, saves, clicks, views, follows, ig_reels_avg_watch_time, ig_reels_video_view_total_time, reposts, reels_skip_rate], default: date }
10457
+ description: 'Sort by date, engagement, or a specific metric. Instagram-only metrics (follows, reposts, reels_skip_rate, ig_reels_*) sort posts with no value as 0.'
10448
10458
  - name: order
10449
10459
  in: query
10450
10460
  schema: { type: string, enum: [asc, desc], default: desc }
@@ -25576,7 +25586,7 @@ paths:
25576
25586
 
25577
25587
  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.
25578
25588
 
25579
- 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'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. Calling this for a number you already have a thread with simply 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). Template fields are accepted on the JSON body only, not on multipart requests. 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: 'utility' together with message (and no templateName). See the category field below.
25589
+ 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'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 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. Calling this for a number you already have a thread with simply 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). Template fields are accepted on the JSON body only, not on multipart requests. 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: 'utility' together with message (and no templateName). See the category field below.
25580
25590
 
25581
25591
  DM eligibility (X/Twitter): 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.
25582
25592
 
@@ -25651,7 +25661,42 @@ paths:
25651
25661
  {{1}}, {{2}} plus a URL button https://example.com/{{1}} takes three values:
25652
25662
  [body1, body2, buttonSuffix]. Media headers (image, video, document) are filled
25653
25663
  automatically from the approved template and take no value here (use headerMedia
25654
- to override the header asset per send).
25664
+ to override the header asset per send). Buttons that are not dynamic-URL buttons
25665
+ (copy-code, flow) take no value here either; use templateButtonParams.
25666
+ templateButtonParams:
25667
+ type: array
25668
+ maxItems: 10
25669
+ description: >-
25670
+ WhatsApp only. Values for template buttons that carry one at send time, each
25671
+ addressed by the button's position in the approved template. This is the only
25672
+ way to send a copy-code button's payload (a Pix payment code, a coupon) or a
25673
+ flow token, because templateParams is a flat array of text variables and covers
25674
+ dynamic URL buttons only. Supplying a button here overrides whatever
25675
+ templateParams would have derived for that same index, so the send never
25676
+ carries one button twice; repeating an index within this array is rejected
25677
+ with 400. Each index must name a button of the matching kind on the approved
25678
+ template, which is also checked before the send and returns 400
25679
+ (INVALID_TEMPLATE_BUTTON_PARAM) rather than a Meta rejection.
25680
+ items:
25681
+ type: object
25682
+ required: [index, subType, value]
25683
+ properties:
25684
+ index:
25685
+ type: integer
25686
+ minimum: 0
25687
+ maximum: 9
25688
+ description: 'Zero-based position of the button in the approved template''s buttons.'
25689
+ subType:
25690
+ type: string
25691
+ enum: [url, copy_code, flow]
25692
+ description: >-
25693
+ The button kind, which decides how the value is sent: copy_code sends it
25694
+ as the coupon_code payload, flow as the flow token, url as the dynamic
25695
+ suffix appended to the button's base URL.
25696
+ value:
25697
+ type: string
25698
+ minLength: 1
25699
+ description: 'The value to send (e.g. the Pix copy-and-paste code for a copy_code button).'
25655
25700
  headerMedia:
25656
25701
  type: object
25657
25702
  description: >-
@@ -40508,6 +40553,85 @@ paths:
40508
40553
  '401': { $ref: '#/components/responses/Unauthorized' }
40509
40554
  '404': { description: Ad not found }
40510
40555
 
40556
+ /v1/ads/campaigns/{campaignId}/assets:
40557
+ post:
40558
+ x-resource-group: "ads"
40559
+ operationId: attachCampaignAssets
40560
+ tags: ["Ad Campaigns"]
40561
+ x-platforms: ["google"]
40562
+ summary: Attach extension assets to a Google Search campaign
40563
+ description: |-
40564
+ Attach sitelinks, callouts and/or structured snippets to an already-existing Google
40565
+ Search campaign — the same builders POST /v1/ads/create uses, but without rebuilding
40566
+ the hierarchy. At least one of sitelinks, callouts or structuredSnippets is required.
40567
+
40568
+ Google-only. Other platforms have no equivalent extension surface and return 501.
40569
+
40570
+ Approval status is Google-async; poll `asset.policy_summary` after review. Assets
40571
+ stay in the account library even if the campaign is later deleted.
40572
+ security:
40573
+ - bearerAuth: []
40574
+ parameters:
40575
+ - { name: campaignId, in: path, required: true, schema: { type: string }, description: "Numeric Google platform campaign id." }
40576
+ requestBody:
40577
+ required: true
40578
+ content:
40579
+ application/json:
40580
+ schema:
40581
+ type: object
40582
+ required: [accountId]
40583
+ properties:
40584
+ accountId: { type: string, description: "Zernio Google Ads SocialAccount id — resolves the customer id + refresh token." }
40585
+ sitelinks:
40586
+ type: array
40587
+ minItems: 2
40588
+ maxItems: 20
40589
+ description: "See POST /v1/ads/create sitelinks — same shape."
40590
+ items:
40591
+ type: object
40592
+ required: [text, linkUrl]
40593
+ properties:
40594
+ text: { type: string, minLength: 1, maxLength: 25 }
40595
+ linkUrl: { type: string, format: uri }
40596
+ description1: { type: string, minLength: 1, maxLength: 35 }
40597
+ description2: { type: string, minLength: 1, maxLength: 35 }
40598
+ callouts:
40599
+ type: array
40600
+ minItems: 1
40601
+ maxItems: 20
40602
+ items: { type: string, minLength: 1, maxLength: 25 }
40603
+ structuredSnippets:
40604
+ type: array
40605
+ minItems: 1
40606
+ maxItems: 20
40607
+ items:
40608
+ type: object
40609
+ required: [header, values]
40610
+ properties:
40611
+ header:
40612
+ type: string
40613
+ enum: [Amenities, Brands, Courses, Degree programs, Destinations, Featured hotels, Insurance coverage, Models, Neighborhoods, Service catalog, Shows, Styles, Types]
40614
+ values:
40615
+ type: array
40616
+ minItems: 3
40617
+ maxItems: 10
40618
+ items: { type: string, minLength: 1, maxLength: 25 }
40619
+ responses:
40620
+ '201':
40621
+ description: Assets attached
40622
+ content:
40623
+ application/json:
40624
+ schema:
40625
+ type: object
40626
+ properties:
40627
+ campaignId: { type: string }
40628
+ sitelinkAssetResourceNames: { type: array, items: { type: string } }
40629
+ calloutAssetResourceNames: { type: array, items: { type: string } }
40630
+ structuredSnippetAssetResourceNames: { type: array, items: { type: string } }
40631
+ '400': { description: "Invalid input, or Google rejected the assets" }
40632
+ '401': { $ref: '#/components/responses/Unauthorized' }
40633
+ '501': { description: Only supported on Google Ads }
40634
+
40511
40635
  /v1/ads/campaigns/{campaignId}/analytics:
40512
40636
  get:
40513
40637
  x-resource-group: "ads"
@@ -43349,6 +43473,39 @@ paths:
43349
43473
  linkUrl: { type: string, format: uri, description: "Final URL the sitelink navigates to." }
43350
43474
  description1: { type: string, minLength: 1, maxLength: 35, description: "First description line under the link text (optional). 35-char cap." }
43351
43475
  description2: { type: string, minLength: 1, maxLength: 35, description: "Second description line (optional; usually paired with description1)." }
43476
+ callouts:
43477
+ type: array
43478
+ minItems: 1
43479
+ maxItems: 20
43480
+ items: { type: string, minLength: 1, maxLength: 25 }
43481
+ description: |
43482
+ Google Search only. Short callout texts (max 25 chars each) that appear as
43483
+ non-clickable annotations under the ad, e.g. "Free shipping", "24/7 support".
43484
+ Each becomes one Asset (`callout_asset`) plus a CampaignAsset link with
43485
+ field_type CALLOUT. Response's creative.callouts[] echoes each input plus
43486
+ its Google resourceName.
43487
+ structuredSnippets:
43488
+ type: array
43489
+ minItems: 1
43490
+ maxItems: 20
43491
+ description: |
43492
+ Google Search only. Structured snippets — one header from Google's
43493
+ predefined list plus 3-10 values (max 25 chars each). Each becomes one
43494
+ Asset (`structured_snippet_asset`) plus a CampaignAsset link with
43495
+ field_type STRUCTURED_SNIPPET.
43496
+ items:
43497
+ type: object
43498
+ required: [header, values]
43499
+ properties:
43500
+ header:
43501
+ type: string
43502
+ enum: [Amenities, Brands, Courses, Degree programs, Destinations, Featured hotels, Insurance coverage, Models, Neighborhoods, Service catalog, Shows, Styles, Types]
43503
+ description: "One of Google's 13 predefined snippet headers."
43504
+ values:
43505
+ type: array
43506
+ minItems: 3
43507
+ maxItems: 10
43508
+ items: { type: string, minLength: 1, maxLength: 25 }
43352
43509
  advantageAudience: { type: integer, enum: [0, 1], description: "Meta only. Controls the Advantage audience feature (targeting_automation). 0 = disabled (default), 1 = enabled. Meta Marketing API requires this field on all ad set creation requests." }
43353
43510
  attributionSpec:
43354
43511
  type: array
@@ -32,6 +32,19 @@ describe 'AdCampaignsApi' do
32
32
  end
33
33
  end
34
34
 
35
+ # unit tests for attach_campaign_assets
36
+ # Attach extension assets to a Google Search campaign
37
+ # Attach sitelinks, callouts and/or structured snippets to an already-existing Google Search campaign — the same builders POST /v1/ads/create uses, but without rebuilding the hierarchy. At least one of sitelinks, callouts or structuredSnippets is required. Google-only. Other platforms have no equivalent extension surface and return 501. Approval status is Google-async; poll `asset.policy_summary` after review. Assets stay in the account library even if the campaign is later deleted.
38
+ # @param campaign_id Numeric Google platform campaign id.
39
+ # @param attach_campaign_assets_request
40
+ # @param [Hash] opts the optional parameters
41
+ # @return [AttachCampaignAssets201Response]
42
+ describe 'attach_campaign_assets test' do
43
+ it 'should work' do
44
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
45
+ end
46
+ end
47
+
35
48
  # unit tests for boost_post
36
49
  # Boost post as ad
37
50
  # Creates a paid ad from an existing published post, keeping the post's engagement. By default it provisions the whole hierarchy (campaign, ad set, ad). **Attach shape (Meta).** Send `adSetId` to put the ad under an EXISTING ad set instead, so that ad set keeps its learning phase. It then owns `budget`, `schedule` and `targeting`, and sending any of those alongside `adSetId` is a 400 rather than a silent drop. `budget` is required only without `adSetId`. `instagramAccountId`, `destinationType` and `adSetId` are Meta-only and return 400 on other platforms. **Retries.** Boosts are NOT idempotent and can take minutes when Meta requires re-hosting an Instagram video, so do not retry on client timeout. Send an Idempotency-Key header to make retries safe: same key and body replays the original 201, and distinct keys always create distinct ads. Without the header, an identical request is treated as a retry: while one is in flight it returns 409, and within 10 minutes of a completed boost it returns the already-created ad instead of creating another. To intentionally duplicate an ad, send distinct Idempotency-Keys (or vary the body, e.g. the name).
@@ -45,7 +45,7 @@ describe 'AnalyticsApi' do
45
45
  # @option opts [Date] :to_date Inclusive upper bound (YYYY-MM-DD). Defaults to today if omitted.
46
46
  # @option opts [Integer] :limit Page size (default 50)
47
47
  # @option opts [Integer] :page Page number (default 1)
48
- # @option opts [String] :sort_by Sort by date, engagement, or a specific metric
48
+ # @option opts [String] :sort_by Sort by date, engagement, or a specific metric. Instagram-only metrics (follows, reposts, reels_skip_rate, ig_reels_*) sort posts with no value as 0.
49
49
  # @option opts [String] :order Sort order
50
50
  # @return [GetAnalytics200Response]
51
51
  describe 'get_analytics test' do
@@ -48,7 +48,7 @@ describe 'MessagesApi' do
48
48
 
49
49
  # unit tests for create_inbox_conversation
50
50
  # Create conversation
51
- # Initiate a new direct message conversation with a specified user. If a conversation already exists with the recipient, the message is added to the existing thread. Supported platforms: X/Twitter, 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'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. Calling this for a number you already have a thread with simply 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). Template fields are accepted on the JSON body only, not on multipart requests. 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: 'utility' together with message (and no templateName). See the category field below. DM eligibility (X/Twitter): 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/Twitter only): X'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's per-number messaging tiers (unique business-initiated conversations per 24 hours) and per-number throughput instead.
51
+ # Initiate a new direct message conversation with a specified user. If a conversation already exists with the recipient, the message is added to the existing thread. Supported platforms: X/Twitter, 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'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 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. Calling this for a number you already have a thread with simply 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). Template fields are accepted on the JSON body only, not on multipart requests. 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: 'utility' together with message (and no templateName). See the category field below. DM eligibility (X/Twitter): 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/Twitter only): X'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'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]
@@ -0,0 +1,54 @@
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::AttachCampaignAssets201Response
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::AttachCampaignAssets201Response do
21
+ #let(:instance) { Zernio::AttachCampaignAssets201Response.new }
22
+
23
+ describe 'test an instance of AttachCampaignAssets201Response' do
24
+ it 'should create an instance of AttachCampaignAssets201Response' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::AttachCampaignAssets201Response)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "campaign_id"' 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 "sitelink_asset_resource_names"' do
37
+ it 'should work' do
38
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
+ end
40
+ end
41
+
42
+ describe 'test attribute "callout_asset_resource_names"' do
43
+ it 'should work' do
44
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
45
+ end
46
+ end
47
+
48
+ describe 'test attribute "structured_snippet_asset_resource_names"' do
49
+ it 'should work' do
50
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,54 @@
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::AttachCampaignAssetsRequestSitelinksInner
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::AttachCampaignAssetsRequestSitelinksInner do
21
+ #let(:instance) { Zernio::AttachCampaignAssetsRequestSitelinksInner.new }
22
+
23
+ describe 'test an instance of AttachCampaignAssetsRequestSitelinksInner' do
24
+ it 'should create an instance of AttachCampaignAssetsRequestSitelinksInner' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::AttachCampaignAssetsRequestSitelinksInner)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "text"' 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 "link_url"' do
37
+ it 'should work' do
38
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
+ end
40
+ end
41
+
42
+ describe 'test attribute "description1"' do
43
+ it 'should work' do
44
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
45
+ end
46
+ end
47
+
48
+ describe 'test attribute "description2"' do
49
+ it 'should work' do
50
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,54 @@
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::AttachCampaignAssetsRequest
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::AttachCampaignAssetsRequest do
21
+ #let(:instance) { Zernio::AttachCampaignAssetsRequest.new }
22
+
23
+ describe 'test an instance of AttachCampaignAssetsRequest' do
24
+ it 'should create an instance of AttachCampaignAssetsRequest' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::AttachCampaignAssetsRequest)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "account_id"' 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 "sitelinks"' do
37
+ it 'should work' do
38
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
+ end
40
+ end
41
+
42
+ describe 'test attribute "callouts"' do
43
+ it 'should work' do
44
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
45
+ end
46
+ end
47
+
48
+ describe 'test attribute "structured_snippets"' do
49
+ it 'should work' do
50
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
51
+ end
52
+ end
53
+
54
+ end
@@ -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::AttachCampaignAssetsRequestStructuredSnippetsInner
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::AttachCampaignAssetsRequestStructuredSnippetsInner do
21
+ #let(:instance) { Zernio::AttachCampaignAssetsRequestStructuredSnippetsInner.new }
22
+
23
+ describe 'test an instance of AttachCampaignAssetsRequestStructuredSnippetsInner' do
24
+ it 'should create an instance of AttachCampaignAssetsRequestStructuredSnippetsInner' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::AttachCampaignAssetsRequestStructuredSnippetsInner)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "header"' do
31
+ it 'should work' do
32
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["Amenities", "Brands", "Courses", "Degree programs", "Destinations", "Featured hotels", "Insurance coverage", "Models", "Neighborhoods", "Service catalog", "Shows", "Styles", "Types"])
34
+ # validator.allowable_values.each do |value|
35
+ # expect { instance.header = value }.not_to raise_error
36
+ # end
37
+ end
38
+ end
39
+
40
+ describe 'test attribute "values"' do
41
+ it 'should work' do
42
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
43
+ end
44
+ end
45
+
46
+ end
@@ -91,6 +91,12 @@ describe Zernio::CreateInboxConversationRequest do
91
91
  end
92
92
  end
93
93
 
94
+ describe 'test attribute "template_button_params"' do
95
+ it 'should work' do
96
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
97
+ end
98
+ end
99
+
94
100
  describe 'test attribute "header_media"' do
95
101
  it 'should work' do
96
102
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/