zernio-sdk 0.0.550 → 0.0.552

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +73 -75
  3. data/docs/AdAccountsApi.md +915 -0
  4. data/docs/AdCampaignsApi.md +615 -15
  5. data/docs/AdCreativesApi.md +815 -0
  6. data/docs/AdInsightsApi.md +415 -0
  7. data/docs/AdTargetingApi.md +371 -0
  8. data/docs/AnalyticsApi.md +7 -7
  9. data/docs/BoostPostRequestTracking.md +1 -1
  10. data/docs/{CreateLeadFormRequestQuestionsInnerOptionsInner.md → BoostPostRequestTrackingUrlTagsInner.md} +2 -2
  11. data/docs/ConversionsApi.md +890 -0
  12. data/docs/CreateLeadFormRequestQuestionsInner.md +1 -1
  13. data/docs/LeadGenApi.md +527 -0
  14. data/docs/MessagingAdsApi.md +215 -0
  15. data/docs/ReachAndFrequencyApi.md +294 -0
  16. data/docs/TrackingTagsApi.md +141 -0
  17. data/docs/YouTubeDailyViewsResponse.md +2 -0
  18. data/docs/YouTubeDemographicsResponse.md +2 -0
  19. data/docs/YouTubeVideoRetentionResponse.md +2 -0
  20. data/lib/zernio-sdk/api/ad_accounts_api.rb +958 -0
  21. data/lib/zernio-sdk/api/ad_campaigns_api.rb +618 -12
  22. data/lib/zernio-sdk/api/ad_creatives_api.rb +826 -0
  23. data/lib/zernio-sdk/api/ad_insights_api.rb +446 -0
  24. data/lib/zernio-sdk/api/ad_targeting_api.rb +404 -0
  25. data/lib/zernio-sdk/api/analytics_api.rb +8 -8
  26. data/lib/zernio-sdk/api/conversions_api.rb +936 -0
  27. data/lib/zernio-sdk/api/lead_gen_api.rb +547 -0
  28. data/lib/zernio-sdk/api/messaging_ads_api.rb +226 -0
  29. data/lib/zernio-sdk/api/reach_and_frequency_api.rb +316 -0
  30. data/lib/zernio-sdk/api/tracking_tags_api.rb +137 -0
  31. data/lib/zernio-sdk/models/boost_post_request_tracking.rb +5 -2
  32. data/lib/zernio-sdk/models/{create_lead_form_request_questions_inner_options_inner.rb → boost_post_request_tracking_url_tags_inner.rb} +3 -3
  33. data/lib/zernio-sdk/models/create_lead_form_request_questions_inner.rb +1 -1
  34. data/lib/zernio-sdk/models/you_tube_daily_views_response.rb +11 -1
  35. data/lib/zernio-sdk/models/you_tube_demographics_response.rb +11 -1
  36. data/lib/zernio-sdk/models/you_tube_video_retention_response.rb +11 -1
  37. data/lib/zernio-sdk/version.rb +1 -1
  38. data/lib/zernio-sdk.rb +9 -2
  39. data/openapi.yaml +329 -163
  40. data/spec/api/ad_accounts_api_spec.rb +206 -0
  41. data/spec/api/ad_campaigns_api_spec.rb +119 -6
  42. data/spec/api/ad_creatives_api_spec.rb +182 -0
  43. data/spec/api/ad_insights_api_spec.rb +120 -0
  44. data/spec/api/ad_targeting_api_spec.rb +101 -0
  45. data/spec/api/analytics_api_spec.rb +4 -4
  46. data/spec/api/conversions_api_spec.rb +199 -0
  47. data/spec/api/lead_gen_api_spec.rb +131 -0
  48. data/spec/api/messaging_ads_api_spec.rb +71 -0
  49. data/spec/api/reach_and_frequency_api_spec.rb +87 -0
  50. data/spec/api/tracking_tags_api_spec.rb +25 -0
  51. data/spec/models/{create_lead_form_request_questions_inner_options_inner_spec.rb → boost_post_request_tracking_url_tags_inner_spec.rb} +6 -6
  52. data/spec/models/you_tube_daily_views_response_spec.rb +6 -0
  53. data/spec/models/you_tube_demographics_response_spec.rb +6 -0
  54. data/spec/models/you_tube_video_retention_response_spec.rb +6 -0
  55. metadata +38 -10
  56. data/docs/AdsApi.md +0 -5278
  57. data/lib/zernio-sdk/api/ads_api.rb +0 -5391
  58. data/spec/api/ads_api_spec.rb +0 -1015
@@ -19,6 +19,74 @@ module Zernio
19
19
  def initialize(api_client = ApiClient.default)
20
20
  @api_client = api_client
21
21
  end
22
+ # Boost post as ad
23
+ # Creates a paid ad campaign from an existing published post. Creates the full platform campaign hierarchy (campaign, ad set, ad).
24
+ # @param boost_post_request [BoostPostRequest]
25
+ # @param [Hash] opts the optional parameters
26
+ # @return [UpdateAd200Response]
27
+ def boost_post(boost_post_request, opts = {})
28
+ data, _status_code, _headers = boost_post_with_http_info(boost_post_request, opts)
29
+ data
30
+ end
31
+
32
+ # Boost post as ad
33
+ # Creates a paid ad campaign from an existing published post. Creates the full platform campaign hierarchy (campaign, ad set, ad).
34
+ # @param boost_post_request [BoostPostRequest]
35
+ # @param [Hash] opts the optional parameters
36
+ # @return [Array<(UpdateAd200Response, Integer, Hash)>] UpdateAd200Response data, response status code and response headers
37
+ def boost_post_with_http_info(boost_post_request, opts = {})
38
+ if @api_client.config.debugging
39
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.boost_post ...'
40
+ end
41
+ # verify the required parameter 'boost_post_request' is set
42
+ if @api_client.config.client_side_validation && boost_post_request.nil?
43
+ fail ArgumentError, "Missing the required parameter 'boost_post_request' when calling AdCampaignsApi.boost_post"
44
+ end
45
+ # resource path
46
+ local_var_path = '/v1/ads/boost'
47
+
48
+ # query parameters
49
+ query_params = opts[:query_params] || {}
50
+
51
+ # header parameters
52
+ header_params = opts[:header_params] || {}
53
+ # HTTP header 'Accept' (if needed)
54
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
55
+ # HTTP header 'Content-Type'
56
+ content_type = @api_client.select_header_content_type(['application/json'])
57
+ if !content_type.nil?
58
+ header_params['Content-Type'] = content_type
59
+ end
60
+
61
+ # form parameters
62
+ form_params = opts[:form_params] || {}
63
+
64
+ # http body (model)
65
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(boost_post_request)
66
+
67
+ # return_type
68
+ return_type = opts[:debug_return_type] || 'UpdateAd200Response'
69
+
70
+ # auth_names
71
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
72
+
73
+ new_options = opts.merge(
74
+ :operation => :"AdCampaignsApi.boost_post",
75
+ :header_params => header_params,
76
+ :query_params => query_params,
77
+ :form_params => form_params,
78
+ :body => post_body,
79
+ :auth_names => auth_names,
80
+ :return_type => return_type
81
+ )
82
+
83
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
84
+ if @api_client.config.debugging
85
+ @api_client.config.logger.debug "API called: AdCampaignsApi#boost_post\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
86
+ end
87
+ return data, status_code, headers
88
+ end
89
+
22
90
  # Pause or resume many campaigns
23
91
  # Process up to 50 campaigns in one call. Each campaign is updated concurrently and the response contains a per-campaign result so a single bad row does not fail the whole batch.
24
92
  # @param bulk_update_ad_campaign_status_request [BulkUpdateAdCampaignStatusRequest]
@@ -87,8 +155,8 @@ module Zernio
87
155
  return data, status_code, headers
88
156
  end
89
157
 
90
- # Create a standalone campaign (Meta)
91
- # Creates a campaign WITHOUT its first ad set / ad (the ODAX shell only). Ad sets join it later via `existingCampaignId` on the create endpoints. A budget here is campaign-level (CBO) by definition; omit it for ABO (each ad set carries its own budget). Created `PAUSED` unless `status: ACTIVE`. The campaign materializes in `/v1/ads/tree` via the next sync discovery pass. Meta only.
158
+ # Create a standalone campaign
159
+ # Creates a campaign WITHOUT its first ad set / ad (the ODAX shell only). Ad sets join it later via `existingCampaignId` on the create endpoints. A budget here is campaign-level (CBO) by definition; omit it for ABO (each ad set carries its own budget). Created `PAUSED` unless `status: ACTIVE`. The campaign materializes in `/v1/ads/tree` via the next sync discovery pass.
92
160
  # @param create_ad_campaign_request [CreateAdCampaignRequest]
93
161
  # @param [Hash] opts the optional parameters
94
162
  # @return [CreateAdCampaign201Response]
@@ -97,8 +165,8 @@ module Zernio
97
165
  data
98
166
  end
99
167
 
100
- # Create a standalone campaign (Meta)
101
- # Creates a campaign WITHOUT its first ad set / ad (the ODAX shell only). Ad sets join it later via &#x60;existingCampaignId&#x60; on the create endpoints. A budget here is campaign-level (CBO) by definition; omit it for ABO (each ad set carries its own budget). Created &#x60;PAUSED&#x60; unless &#x60;status: ACTIVE&#x60;. The campaign materializes in &#x60;/v1/ads/tree&#x60; via the next sync discovery pass. Meta only.
168
+ # Create a standalone campaign
169
+ # Creates a campaign WITHOUT its first ad set / ad (the ODAX shell only). Ad sets join it later via &#x60;existingCampaignId&#x60; on the create endpoints. A budget here is campaign-level (CBO) by definition; omit it for ABO (each ad set carries its own budget). Created &#x60;PAUSED&#x60; unless &#x60;status: ACTIVE&#x60;. The campaign materializes in &#x60;/v1/ads/tree&#x60; via the next sync discovery pass.
102
170
  # @param create_ad_campaign_request [CreateAdCampaignRequest]
103
171
  # @param [Hash] opts the optional parameters
104
172
  # @return [Array<(CreateAdCampaign201Response, Integer, Hash)>] CreateAdCampaign201Response data, response status code and response headers
@@ -155,6 +223,144 @@ module Zernio
155
223
  return data, status_code, headers
156
224
  end
157
225
 
226
+ # Create standalone ad
227
+ # Creates a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X/Twitter, and LinkedIn. Supports three mutually-exclusive request shapes selected by the body, a legacy single-creative shape (all platforms, default), a Meta-only multi-creative shape via the creatives array (one ad set with N ads sharing budget and targeting), and a Meta-only attach shape via adSetId (adds one new ad to an existing ad set). Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`); supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
228
+ # @param create_standalone_ad_request [CreateStandaloneAdRequest]
229
+ # @param [Hash] opts the optional parameters
230
+ # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes create retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
231
+ # @return [CreateStandaloneAd200Response]
232
+ def create_standalone_ad(create_standalone_ad_request, opts = {})
233
+ data, _status_code, _headers = create_standalone_ad_with_http_info(create_standalone_ad_request, opts)
234
+ data
235
+ end
236
+
237
+ # Create standalone ad
238
+ # Creates a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X/Twitter, and LinkedIn. Supports three mutually-exclusive request shapes selected by the body, a legacy single-creative shape (all platforms, default), a Meta-only multi-creative shape via the creatives array (one ad set with N ads sharing budget and targeting), and a Meta-only attach shape via adSetId (adds one new ad to an existing ad set). Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \&quot;dark post\&quot; authored by a Company Page (see &#x60;organizationId&#x60;); supported goals are engagement, traffic, awareness, and video_views (video ads use the &#x60;video&#x60; field; video_views requires a video), and traffic ads require &#x60;linkUrl&#x60;. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an &#x60;Idempotency-Key&#x60; header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with &#x60;Idempotent-Replayed: true&#x60;) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
239
+ # @param create_standalone_ad_request [CreateStandaloneAdRequest]
240
+ # @param [Hash] opts the optional parameters
241
+ # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes create retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
242
+ # @return [Array<(CreateStandaloneAd200Response, Integer, Hash)>] CreateStandaloneAd200Response data, response status code and response headers
243
+ def create_standalone_ad_with_http_info(create_standalone_ad_request, opts = {})
244
+ if @api_client.config.debugging
245
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.create_standalone_ad ...'
246
+ end
247
+ # verify the required parameter 'create_standalone_ad_request' is set
248
+ if @api_client.config.client_side_validation && create_standalone_ad_request.nil?
249
+ fail ArgumentError, "Missing the required parameter 'create_standalone_ad_request' when calling AdCampaignsApi.create_standalone_ad"
250
+ end
251
+ if @api_client.config.client_side_validation && !opts[:'idempotency_key'].nil? && opts[:'idempotency_key'].to_s.length > 255
252
+ fail ArgumentError, 'invalid value for "opts[:"idempotency_key"]" when calling AdCampaignsApi.create_standalone_ad, the character length must be smaller than or equal to 255.'
253
+ end
254
+
255
+ # resource path
256
+ local_var_path = '/v1/ads/create'
257
+
258
+ # query parameters
259
+ query_params = opts[:query_params] || {}
260
+
261
+ # header parameters
262
+ header_params = opts[:header_params] || {}
263
+ # HTTP header 'Accept' (if needed)
264
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
265
+ # HTTP header 'Content-Type'
266
+ content_type = @api_client.select_header_content_type(['application/json'])
267
+ if !content_type.nil?
268
+ header_params['Content-Type'] = content_type
269
+ end
270
+ header_params[:'Idempotency-Key'] = opts[:'idempotency_key'] if !opts[:'idempotency_key'].nil?
271
+
272
+ # form parameters
273
+ form_params = opts[:form_params] || {}
274
+
275
+ # http body (model)
276
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(create_standalone_ad_request)
277
+
278
+ # return_type
279
+ return_type = opts[:debug_return_type] || 'CreateStandaloneAd200Response'
280
+
281
+ # auth_names
282
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
283
+
284
+ new_options = opts.merge(
285
+ :operation => :"AdCampaignsApi.create_standalone_ad",
286
+ :header_params => header_params,
287
+ :query_params => query_params,
288
+ :form_params => form_params,
289
+ :body => post_body,
290
+ :auth_names => auth_names,
291
+ :return_type => return_type
292
+ )
293
+
294
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
295
+ if @api_client.config.debugging
296
+ @api_client.config.logger.debug "API called: AdCampaignsApi#create_standalone_ad\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
297
+ end
298
+ return data, status_code, headers
299
+ end
300
+
301
+ # Cancel an ad
302
+ # Cancels the ad on the platform and marks it as cancelled in the database. The ad is preserved for history.
303
+ # @param ad_id [String]
304
+ # @param [Hash] opts the optional parameters
305
+ # @return [DeleteAccountGroup200Response]
306
+ def delete_ad(ad_id, opts = {})
307
+ data, _status_code, _headers = delete_ad_with_http_info(ad_id, opts)
308
+ data
309
+ end
310
+
311
+ # Cancel an ad
312
+ # Cancels the ad on the platform and marks it as cancelled in the database. The ad is preserved for history.
313
+ # @param ad_id [String]
314
+ # @param [Hash] opts the optional parameters
315
+ # @return [Array<(DeleteAccountGroup200Response, Integer, Hash)>] DeleteAccountGroup200Response data, response status code and response headers
316
+ def delete_ad_with_http_info(ad_id, opts = {})
317
+ if @api_client.config.debugging
318
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.delete_ad ...'
319
+ end
320
+ # verify the required parameter 'ad_id' is set
321
+ if @api_client.config.client_side_validation && ad_id.nil?
322
+ fail ArgumentError, "Missing the required parameter 'ad_id' when calling AdCampaignsApi.delete_ad"
323
+ end
324
+ # resource path
325
+ local_var_path = '/v1/ads/{adId}'.sub('{' + 'adId' + '}', CGI.escape(ad_id.to_s))
326
+
327
+ # query parameters
328
+ query_params = opts[:query_params] || {}
329
+
330
+ # header parameters
331
+ header_params = opts[:header_params] || {}
332
+ # HTTP header 'Accept' (if needed)
333
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
334
+
335
+ # form parameters
336
+ form_params = opts[:form_params] || {}
337
+
338
+ # http body (model)
339
+ post_body = opts[:debug_body]
340
+
341
+ # return_type
342
+ return_type = opts[:debug_return_type] || 'DeleteAccountGroup200Response'
343
+
344
+ # auth_names
345
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
346
+
347
+ new_options = opts.merge(
348
+ :operation => :"AdCampaignsApi.delete_ad",
349
+ :header_params => header_params,
350
+ :query_params => query_params,
351
+ :form_params => form_params,
352
+ :body => post_body,
353
+ :auth_names => auth_names,
354
+ :return_type => return_type
355
+ )
356
+
357
+ data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options)
358
+ if @api_client.config.debugging
359
+ @api_client.config.logger.debug "API called: AdCampaignsApi#delete_ad\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
360
+ end
361
+ return data, status_code, headers
362
+ end
363
+
158
364
  # Delete a campaign
159
365
  # Deletes the whole campaign on the platform, cascading to its ad sets and ads. Locally, all Ad documents for this campaign are marked `status: cancelled`. Meta-only for now. Other platforms return 501 Not Implemented — fall back to DELETE /v1/ads/{adId} per ad in the meantime.
160
366
  # @param campaign_id [String] Platform campaign ID
@@ -229,6 +435,76 @@ module Zernio
229
435
  return data, status_code, headers
230
436
  end
231
437
 
438
+ # Duplicate an ad
439
+ # Duplicates a single ad via Meta's native `POST /{ad-id}/copies`. The copy is created paused. `adSetId` retargets the copy into another ad set; omitted = the source's own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (`syncAfter: false` to skip).
440
+ # @param ad_id [String] Zernio ad ID or platform ad ID
441
+ # @param [Hash] opts the optional parameters
442
+ # @option opts [DuplicateAdRequest] :duplicate_ad_request
443
+ # @return [DuplicateAd200Response]
444
+ def duplicate_ad(ad_id, opts = {})
445
+ data, _status_code, _headers = duplicate_ad_with_http_info(ad_id, opts)
446
+ data
447
+ end
448
+
449
+ # Duplicate an ad
450
+ # Duplicates a single ad via Meta&#39;s native &#x60;POST /{ad-id}/copies&#x60;. The copy is created paused. &#x60;adSetId&#x60; retargets the copy into another ad set; omitted &#x3D; the source&#39;s own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (&#x60;syncAfter: false&#x60; to skip).
451
+ # @param ad_id [String] Zernio ad ID or platform ad ID
452
+ # @param [Hash] opts the optional parameters
453
+ # @option opts [DuplicateAdRequest] :duplicate_ad_request
454
+ # @return [Array<(DuplicateAd200Response, Integer, Hash)>] DuplicateAd200Response data, response status code and response headers
455
+ def duplicate_ad_with_http_info(ad_id, opts = {})
456
+ if @api_client.config.debugging
457
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.duplicate_ad ...'
458
+ end
459
+ # verify the required parameter 'ad_id' is set
460
+ if @api_client.config.client_side_validation && ad_id.nil?
461
+ fail ArgumentError, "Missing the required parameter 'ad_id' when calling AdCampaignsApi.duplicate_ad"
462
+ end
463
+ # resource path
464
+ local_var_path = '/v1/ads/{adId}/duplicate'.sub('{' + 'adId' + '}', CGI.escape(ad_id.to_s))
465
+
466
+ # query parameters
467
+ query_params = opts[:query_params] || {}
468
+
469
+ # header parameters
470
+ header_params = opts[:header_params] || {}
471
+ # HTTP header 'Accept' (if needed)
472
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
473
+ # HTTP header 'Content-Type'
474
+ content_type = @api_client.select_header_content_type(['application/json'])
475
+ if !content_type.nil?
476
+ header_params['Content-Type'] = content_type
477
+ end
478
+
479
+ # form parameters
480
+ form_params = opts[:form_params] || {}
481
+
482
+ # http body (model)
483
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(opts[:'duplicate_ad_request'])
484
+
485
+ # return_type
486
+ return_type = opts[:debug_return_type] || 'DuplicateAd200Response'
487
+
488
+ # auth_names
489
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
490
+
491
+ new_options = opts.merge(
492
+ :operation => :"AdCampaignsApi.duplicate_ad",
493
+ :header_params => header_params,
494
+ :query_params => query_params,
495
+ :form_params => form_params,
496
+ :body => post_body,
497
+ :auth_names => auth_names,
498
+ :return_type => return_type
499
+ )
500
+
501
+ data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
502
+ if @api_client.config.debugging
503
+ @api_client.config.logger.debug "API called: AdCampaignsApi#duplicate_ad\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
504
+ end
505
+ return data, status_code, headers
506
+ end
507
+
232
508
  # Duplicate a campaign
233
509
  # Duplicates a campaign, including its ad sets, ads, creatives, and targeting by default (`deepCopy: true`). The copy is created paused so callers can review before launching. Per-platform implementation: - **Meta** uses the native `POST /{campaign-id}/copies` endpoint. - **TikTok** has no native copy primitive; Zernio walks the source graph (`/v2/campaign/get/`, `/v2/adgroup/get/`, `/v2/ad/get/`) and recreates each entity via the corresponding `/create/` endpoints, carrying over budget / targeting / bid_type / bid_price / deep_bid_type / creative fields. Spark Ad linkage (`tiktok_item_id`) is preserved. - **LinkedIn** has no native copy primitive; Zernio walks the source CampaignGroup → Campaigns → Creatives and recreates each entity, carrying over `type` / `costType` / `unitCost` / `optimizationTargetType` / `creativeSelection` / `objectiveType` / `format` / `dailyBudget` / `totalBudget` / `targetingCriteria` / `runSchedule` and every Creative's `content` object verbatim. `statusOption: INHERITED_FROM_SOURCE` is evaluated **per entity**: any Group / Campaign / Creative whose source is `ACTIVE` gets its clone activated too. Duplicating an ACTIVE campaign with `INHERITED_FROM_SOURCE` starts a second front of spend the moment the clone activates — the safe default is `PAUSED`. The new hierarchy is asynchronous to materialize in our DB — we trigger sync discovery automatically. Set `syncAfter: false` to skip and poll `/v1/ads/tree` on your own cadence. Other platforms return 501 Not Implemented.
234
510
  # @param campaign_id [String] Source platform campaign ID
@@ -303,8 +579,8 @@ module Zernio
303
579
  return data, status_code, headers
304
580
  end
305
581
 
306
- # Duplicate an ad set (Meta)
307
- # Duplicates an ad set, including its ads and creatives by default (`deepCopy: true`), via Meta's native `POST /{adset-id}/copies`. The copy is created paused so callers can review before launching. `campaignId` retargets the copy into another campaign; omitted = the source's own campaign. The new hierarchy materializes asynchronously — sync discovery is triggered automatically (`syncAfter: false` to skip). Meta only.
582
+ # Duplicate an ad set
583
+ # Duplicates an ad set, including its ads and creatives by default (`deepCopy: true`), via Meta's native `POST /{adset-id}/copies`. The copy is created paused so callers can review before launching. `campaignId` retargets the copy into another campaign; omitted = the source's own campaign. The new hierarchy materializes asynchronously — sync discovery is triggered automatically (`syncAfter: false` to skip).
308
584
  # @param ad_set_id [String] Source platform ad set ID
309
585
  # @param duplicate_ad_set_request [DuplicateAdSetRequest]
310
586
  # @param [Hash] opts the optional parameters
@@ -314,8 +590,8 @@ module Zernio
314
590
  data
315
591
  end
316
592
 
317
- # Duplicate an ad set (Meta)
318
- # Duplicates an ad set, including its ads and creatives by default (&#x60;deepCopy: true&#x60;), via Meta&#39;s native &#x60;POST /{adset-id}/copies&#x60;. The copy is created paused so callers can review before launching. &#x60;campaignId&#x60; retargets the copy into another campaign; omitted &#x3D; the source&#39;s own campaign. The new hierarchy materializes asynchronously — sync discovery is triggered automatically (&#x60;syncAfter: false&#x60; to skip). Meta only.
593
+ # Duplicate an ad set
594
+ # Duplicates an ad set, including its ads and creatives by default (&#x60;deepCopy: true&#x60;), via Meta&#39;s native &#x60;POST /{adset-id}/copies&#x60;. The copy is created paused so callers can review before launching. &#x60;campaignId&#x60; retargets the copy into another campaign; omitted &#x3D; the source&#39;s own campaign. The new hierarchy materializes asynchronously — sync discovery is triggered automatically (&#x60;syncAfter: false&#x60; to skip).
319
595
  # @param ad_set_id [String] Source platform ad set ID
320
596
  # @param duplicate_ad_set_request [DuplicateAdSetRequest]
321
597
  # @param [Hash] opts the optional parameters
@@ -377,8 +653,71 @@ module Zernio
377
653
  return data, status_code, headers
378
654
  end
379
655
 
380
- # Live ad-set details incl. learning phase (Meta)
381
- # Reads the ad set live from Meta, returned verbatim. The default projection includes `learning_stage_info` (learning-phase status: LEARNING / SUCCESS / FAIL / WAIVING Meta omits its `status` key on paused ad sets), delivery settings, budgets, schedule and targeting. `fields` is a raw-passthrough override; unknown fields return Meta's 400 verbatim. Meta only.
656
+ # Get ad details
657
+ # Returns an ad with its creative, targeting, status, and performance metrics. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step.
658
+ # @param ad_id [String] Zernio &#x60;_id&#x60; (hex), Meta &#x60;platformAdId&#x60; (numeric), or one of the creative&#39;s effective story/media IDs. See description for details.
659
+ # @param [Hash] opts the optional parameters
660
+ # @return [GetAd200Response]
661
+ def get_ad(ad_id, opts = {})
662
+ data, _status_code, _headers = get_ad_with_http_info(ad_id, opts)
663
+ data
664
+ end
665
+
666
+ # Get ad details
667
+ # Returns an ad with its creative, targeting, status, and performance metrics. The &#x60;{adId}&#x60; path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal &#x60;_id&#x60; (24-char hex) - Meta&#39;s numeric &#x60;platformAdId&#x60; (the value shipped in &#x60;comment.received&#x60; webhooks as &#x60;comment.ad.id&#x60;) - the creative&#39;s &#x60;effective_object_story_id&#x60; (&#x60;{pageId}_{postId}&#x60; shape, Facebook side) - the creative&#39;s &#x60;effective_instagram_media_id&#x60; (Instagram side) Any of the four resolve to the same ad. Caller doesn&#39;t need a translation step.
668
+ # @param ad_id [String] Zernio &#x60;_id&#x60; (hex), Meta &#x60;platformAdId&#x60; (numeric), or one of the creative&#39;s effective story/media IDs. See description for details.
669
+ # @param [Hash] opts the optional parameters
670
+ # @return [Array<(GetAd200Response, Integer, Hash)>] GetAd200Response data, response status code and response headers
671
+ def get_ad_with_http_info(ad_id, opts = {})
672
+ if @api_client.config.debugging
673
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.get_ad ...'
674
+ end
675
+ # verify the required parameter 'ad_id' is set
676
+ if @api_client.config.client_side_validation && ad_id.nil?
677
+ fail ArgumentError, "Missing the required parameter 'ad_id' when calling AdCampaignsApi.get_ad"
678
+ end
679
+ # resource path
680
+ local_var_path = '/v1/ads/{adId}'.sub('{' + 'adId' + '}', CGI.escape(ad_id.to_s))
681
+
682
+ # query parameters
683
+ query_params = opts[:query_params] || {}
684
+
685
+ # header parameters
686
+ header_params = opts[:header_params] || {}
687
+ # HTTP header 'Accept' (if needed)
688
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
689
+
690
+ # form parameters
691
+ form_params = opts[:form_params] || {}
692
+
693
+ # http body (model)
694
+ post_body = opts[:debug_body]
695
+
696
+ # return_type
697
+ return_type = opts[:debug_return_type] || 'GetAd200Response'
698
+
699
+ # auth_names
700
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
701
+
702
+ new_options = opts.merge(
703
+ :operation => :"AdCampaignsApi.get_ad",
704
+ :header_params => header_params,
705
+ :query_params => query_params,
706
+ :form_params => form_params,
707
+ :body => post_body,
708
+ :auth_names => auth_names,
709
+ :return_type => return_type
710
+ )
711
+
712
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
713
+ if @api_client.config.debugging
714
+ @api_client.config.logger.debug "API called: AdCampaignsApi#get_ad\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
715
+ end
716
+ return data, status_code, headers
717
+ end
718
+
719
+ # Live ad-set details incl. learning phase
720
+ # Reads the ad set live from Meta, returned verbatim. The default projection includes `learning_stage_info` (learning-phase status: LEARNING / SUCCESS / FAIL / WAIVING — Meta omits its `status` key on paused ad sets), delivery settings, budgets, schedule and targeting. `fields` is a raw-passthrough override; unknown fields return Meta's 400 verbatim.
382
721
  # @param ad_set_id [String] Meta ad set id (platformAdSetId).
383
722
  # @param account_id [String] Zernio SocialAccount id (posting or ads variant) used to resolve the Meta token.
384
723
  # @param [Hash] opts the optional parameters
@@ -389,8 +728,8 @@ module Zernio
389
728
  data
390
729
  end
391
730
 
392
- # Live ad-set details incl. learning phase (Meta)
393
- # Reads the ad set live from Meta, returned verbatim. The default projection includes &#x60;learning_stage_info&#x60; (learning-phase status: LEARNING / SUCCESS / FAIL / WAIVING — Meta omits its &#x60;status&#x60; key on paused ad sets), delivery settings, budgets, schedule and targeting. &#x60;fields&#x60; is a raw-passthrough override; unknown fields return Meta&#39;s 400 verbatim. Meta only.
731
+ # Live ad-set details incl. learning phase
732
+ # Reads the ad set live from Meta, returned verbatim. The default projection includes &#x60;learning_stage_info&#x60; (learning-phase status: LEARNING / SUCCESS / FAIL / WAIVING — Meta omits its &#x60;status&#x60; key on paused ad sets), delivery settings, budgets, schedule and targeting. &#x60;fields&#x60; is a raw-passthrough override; unknown fields return Meta&#39;s 400 verbatim.
394
733
  # @param ad_set_id [String] Meta ad set id (platformAdSetId).
395
734
  # @param account_id [String] Zernio SocialAccount id (posting or ads variant) used to resolve the Meta token.
396
735
  # @param [Hash] opts the optional parameters
@@ -768,6 +1107,199 @@ module Zernio
768
1107
  return data, status_code, headers
769
1108
  end
770
1109
 
1110
+ # List ads
1111
+ # Returns a paginated list of ads with metrics computed over an optional date range. Use source=all to include externally-synced ads from platform ad managers. If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max. To find the Zernio ad behind a comment you see in Meta Business Manager, filter by platformAdId (the Meta ad ID), effectiveObjectStoryId (Facebook), or effectiveInstagramMediaId (Instagram) — those are the post/media the ad's engagement lives on, and are also returned on each ad's `creative` object. Then call GET /v1/ads/{adId}/comments with the returned ad id.
1112
+ # @param [Hash] opts the optional parameters
1113
+ # @option opts [Integer] :page Page number (1-based) (default to 1)
1114
+ # @option opts [Integer] :limit (default to 50)
1115
+ # @option opts [String] :source all (default) &#x3D; Zernio-created + platform-discovered ads. zernio &#x3D; restrict to Zernio-created only. (default to 'all')
1116
+ # @option opts [AdStatus] :status
1117
+ # @option opts [String] :platform
1118
+ # @option opts [String] :account_id Social account ID
1119
+ # @option opts [String] :ad_account_id Platform ad account ID (e.g. act_123 for Meta). Mirrors the same filter on /v1/ads/campaigns and /v1/ads/tree.
1120
+ # @option opts [String] :profile_id Profile ID
1121
+ # @option opts [String] :campaign_id Platform campaign ID (filter ads within a campaign)
1122
+ # @option opts [String] :platform_ad_id Meta ad ID. Returns the ad with this platform-side ad ID.
1123
+ # @option opts [String] :effective_object_story_id Facebook &#x60;{pageId}_{postId}&#x60; of the post the ad&#39;s engagement lives on (Meta &#x60;effective_object_story_id&#x60;). Use to map a Business-Manager-visible post back to the Zernio ad.
1124
+ # @option opts [String] :effective_instagram_media_id Instagram media ID of the boosted post (Meta &#x60;effective_instagram_media_id&#x60;). Use to map a Business-Manager-visible IG post back to the Zernio ad.
1125
+ # @option opts [Date] :from_date Start of metrics date range (YYYY-MM-DD). Defaults to 90 days ago.
1126
+ # @option opts [Date] :to_date End of metrics date range (YYYY-MM-DD). Defaults to today. Max 730-day range.
1127
+ # @return [ListAds200Response]
1128
+ def list_ads(opts = {})
1129
+ data, _status_code, _headers = list_ads_with_http_info(opts)
1130
+ data
1131
+ end
1132
+
1133
+ # List ads
1134
+ # Returns a paginated list of ads with metrics computed over an optional date range. Use source&#x3D;all to include externally-synced ads from platform ad managers. If no date range is provided, defaults to the last 90 days. Date range is capped at 730 days max. To find the Zernio ad behind a comment you see in Meta Business Manager, filter by platformAdId (the Meta ad ID), effectiveObjectStoryId (Facebook), or effectiveInstagramMediaId (Instagram) — those are the post/media the ad&#39;s engagement lives on, and are also returned on each ad&#39;s &#x60;creative&#x60; object. Then call GET /v1/ads/{adId}/comments with the returned ad id.
1135
+ # @param [Hash] opts the optional parameters
1136
+ # @option opts [Integer] :page Page number (1-based) (default to 1)
1137
+ # @option opts [Integer] :limit (default to 50)
1138
+ # @option opts [String] :source all (default) &#x3D; Zernio-created + platform-discovered ads. zernio &#x3D; restrict to Zernio-created only. (default to 'all')
1139
+ # @option opts [AdStatus] :status
1140
+ # @option opts [String] :platform
1141
+ # @option opts [String] :account_id Social account ID
1142
+ # @option opts [String] :ad_account_id Platform ad account ID (e.g. act_123 for Meta). Mirrors the same filter on /v1/ads/campaigns and /v1/ads/tree.
1143
+ # @option opts [String] :profile_id Profile ID
1144
+ # @option opts [String] :campaign_id Platform campaign ID (filter ads within a campaign)
1145
+ # @option opts [String] :platform_ad_id Meta ad ID. Returns the ad with this platform-side ad ID.
1146
+ # @option opts [String] :effective_object_story_id Facebook &#x60;{pageId}_{postId}&#x60; of the post the ad&#39;s engagement lives on (Meta &#x60;effective_object_story_id&#x60;). Use to map a Business-Manager-visible post back to the Zernio ad.
1147
+ # @option opts [String] :effective_instagram_media_id Instagram media ID of the boosted post (Meta &#x60;effective_instagram_media_id&#x60;). Use to map a Business-Manager-visible IG post back to the Zernio ad.
1148
+ # @option opts [Date] :from_date Start of metrics date range (YYYY-MM-DD). Defaults to 90 days ago.
1149
+ # @option opts [Date] :to_date End of metrics date range (YYYY-MM-DD). Defaults to today. Max 730-day range.
1150
+ # @return [Array<(ListAds200Response, Integer, Hash)>] ListAds200Response data, response status code and response headers
1151
+ def list_ads_with_http_info(opts = {})
1152
+ if @api_client.config.debugging
1153
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.list_ads ...'
1154
+ end
1155
+ if @api_client.config.client_side_validation && !opts[:'page'].nil? && opts[:'page'] < 1
1156
+ fail ArgumentError, 'invalid value for "opts[:"page"]" when calling AdCampaignsApi.list_ads, must be greater than or equal to 1.'
1157
+ end
1158
+
1159
+ if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] > 500
1160
+ fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling AdCampaignsApi.list_ads, must be smaller than or equal to 500.'
1161
+ end
1162
+
1163
+ if @api_client.config.client_side_validation && !opts[:'limit'].nil? && opts[:'limit'] < 1
1164
+ fail ArgumentError, 'invalid value for "opts[:"limit"]" when calling AdCampaignsApi.list_ads, must be greater than or equal to 1.'
1165
+ end
1166
+
1167
+ allowable_values = ["zernio", "all"]
1168
+ if @api_client.config.client_side_validation && opts[:'source'] && !allowable_values.include?(opts[:'source'])
1169
+ fail ArgumentError, "invalid value for \"source\", must be one of #{allowable_values}"
1170
+ end
1171
+ allowable_values = ["facebook", "instagram", "tiktok", "linkedin", "pinterest", "google", "twitter"]
1172
+ if @api_client.config.client_side_validation && opts[:'platform'] && !allowable_values.include?(opts[:'platform'])
1173
+ fail ArgumentError, "invalid value for \"platform\", must be one of #{allowable_values}"
1174
+ end
1175
+ # resource path
1176
+ local_var_path = '/v1/ads'
1177
+
1178
+ # query parameters
1179
+ query_params = opts[:query_params] || {}
1180
+ query_params[:'page'] = opts[:'page'] if !opts[:'page'].nil?
1181
+ query_params[:'limit'] = opts[:'limit'] if !opts[:'limit'].nil?
1182
+ query_params[:'source'] = opts[:'source'] if !opts[:'source'].nil?
1183
+ query_params[:'status'] = opts[:'status'] if !opts[:'status'].nil?
1184
+ query_params[:'platform'] = opts[:'platform'] if !opts[:'platform'].nil?
1185
+ query_params[:'accountId'] = opts[:'account_id'] if !opts[:'account_id'].nil?
1186
+ query_params[:'adAccountId'] = opts[:'ad_account_id'] if !opts[:'ad_account_id'].nil?
1187
+ query_params[:'profileId'] = opts[:'profile_id'] if !opts[:'profile_id'].nil?
1188
+ query_params[:'campaignId'] = opts[:'campaign_id'] if !opts[:'campaign_id'].nil?
1189
+ query_params[:'platformAdId'] = opts[:'platform_ad_id'] if !opts[:'platform_ad_id'].nil?
1190
+ query_params[:'effectiveObjectStoryId'] = opts[:'effective_object_story_id'] if !opts[:'effective_object_story_id'].nil?
1191
+ query_params[:'effectiveInstagramMediaId'] = opts[:'effective_instagram_media_id'] if !opts[:'effective_instagram_media_id'].nil?
1192
+ query_params[:'fromDate'] = opts[:'from_date'] if !opts[:'from_date'].nil?
1193
+ query_params[:'toDate'] = opts[:'to_date'] if !opts[:'to_date'].nil?
1194
+
1195
+ # header parameters
1196
+ header_params = opts[:header_params] || {}
1197
+ # HTTP header 'Accept' (if needed)
1198
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
1199
+
1200
+ # form parameters
1201
+ form_params = opts[:form_params] || {}
1202
+
1203
+ # http body (model)
1204
+ post_body = opts[:debug_body]
1205
+
1206
+ # return_type
1207
+ return_type = opts[:debug_return_type] || 'ListAds200Response'
1208
+
1209
+ # auth_names
1210
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
1211
+
1212
+ new_options = opts.merge(
1213
+ :operation => :"AdCampaignsApi.list_ads",
1214
+ :header_params => header_params,
1215
+ :query_params => query_params,
1216
+ :form_params => form_params,
1217
+ :body => post_body,
1218
+ :auth_names => auth_names,
1219
+ :return_type => return_type
1220
+ )
1221
+
1222
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options)
1223
+ if @api_client.config.debugging
1224
+ @api_client.config.logger.debug "API called: AdCampaignsApi#list_ads\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
1225
+ end
1226
+ return data, status_code, headers
1227
+ end
1228
+
1229
+ # Update ad
1230
+ # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style — `headline` is ignored, `body` becomes `ad_text`). - **Pinterest / X / LinkedIn / Google**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`.
1231
+ # @param ad_id [String]
1232
+ # @param update_ad_request [UpdateAdRequest]
1233
+ # @param [Hash] opts the optional parameters
1234
+ # @return [UpdateAd200Response]
1235
+ def update_ad(ad_id, update_ad_request, opts = {})
1236
+ data, _status_code, _headers = update_ad_with_http_info(ad_id, update_ad_request, opts)
1237
+ data
1238
+ end
1239
+
1240
+ # Update ad
1241
+ # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via &#x60;/v2/adgroup/update/&#x60;), and creative (via &#x60;/v2/ad/update/&#x60; patch-style — &#x60;headline&#x60; is ignored, &#x60;body&#x60; becomes &#x60;ad_text&#x60;). - **Pinterest / X / LinkedIn / Google**: status + budget only. Sending &#x60;targeting&#x60; or &#x60;creative&#x60; returns 501 with code &#x60;unsupported_platform_operation&#x60;.
1242
+ # @param ad_id [String]
1243
+ # @param update_ad_request [UpdateAdRequest]
1244
+ # @param [Hash] opts the optional parameters
1245
+ # @return [Array<(UpdateAd200Response, Integer, Hash)>] UpdateAd200Response data, response status code and response headers
1246
+ def update_ad_with_http_info(ad_id, update_ad_request, opts = {})
1247
+ if @api_client.config.debugging
1248
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.update_ad ...'
1249
+ end
1250
+ # verify the required parameter 'ad_id' is set
1251
+ if @api_client.config.client_side_validation && ad_id.nil?
1252
+ fail ArgumentError, "Missing the required parameter 'ad_id' when calling AdCampaignsApi.update_ad"
1253
+ end
1254
+ # verify the required parameter 'update_ad_request' is set
1255
+ if @api_client.config.client_side_validation && update_ad_request.nil?
1256
+ fail ArgumentError, "Missing the required parameter 'update_ad_request' when calling AdCampaignsApi.update_ad"
1257
+ end
1258
+ # resource path
1259
+ local_var_path = '/v1/ads/{adId}'.sub('{' + 'adId' + '}', CGI.escape(ad_id.to_s))
1260
+
1261
+ # query parameters
1262
+ query_params = opts[:query_params] || {}
1263
+
1264
+ # header parameters
1265
+ header_params = opts[:header_params] || {}
1266
+ # HTTP header 'Accept' (if needed)
1267
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
1268
+ # HTTP header 'Content-Type'
1269
+ content_type = @api_client.select_header_content_type(['application/json'])
1270
+ if !content_type.nil?
1271
+ header_params['Content-Type'] = content_type
1272
+ end
1273
+
1274
+ # form parameters
1275
+ form_params = opts[:form_params] || {}
1276
+
1277
+ # http body (model)
1278
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(update_ad_request)
1279
+
1280
+ # return_type
1281
+ return_type = opts[:debug_return_type] || 'UpdateAd200Response'
1282
+
1283
+ # auth_names
1284
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
1285
+
1286
+ new_options = opts.merge(
1287
+ :operation => :"AdCampaignsApi.update_ad",
1288
+ :header_params => header_params,
1289
+ :query_params => query_params,
1290
+ :form_params => form_params,
1291
+ :body => post_body,
1292
+ :auth_names => auth_names,
1293
+ :return_type => return_type
1294
+ )
1295
+
1296
+ data, status_code, headers = @api_client.call_api(:PUT, local_var_path, new_options)
1297
+ if @api_client.config.debugging
1298
+ @api_client.config.logger.debug "API called: AdCampaignsApi#update_ad\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
1299
+ end
1300
+ return data, status_code, headers
1301
+ end
1302
+
771
1303
  # Update a campaign
772
1304
  # Campaign-level edits. At least one of `budget`, `bidStrategy`, `name` or `platformSpecificData` is required. - `budget` updates the CBO (Campaign Budget Optimization) budget. For ABO campaigns (where the budget lives on the ad set), use PUT /v1/ads/ad-sets/{adSetId} instead — this endpoint will return 409 with code BUDGET_LEVEL_MISMATCH. - `bidStrategy` sets the campaign-level default bid strategy. Per Meta's spec, `bid_amount` and `bid_constraints` do NOT exist at the campaign level — pass them via PUT /v1/ads/ad-sets/{adSetId}. - `platformSpecificData.spendCap` (Meta only) sets the campaign's lifetime spend cap, in the ad account's currency. Meta-only for now. Other platforms return 501 Not Implemented.
773
1305
  # @param campaign_id [String] Platform campaign ID
@@ -1063,5 +1595,79 @@ module Zernio
1063
1595
  end
1064
1596
  return data, status_code, headers
1065
1597
  end
1598
+
1599
+ # Pause or resume a single ad
1600
+ # Ad-scoped pause/resume — touches ONLY this ad, never its parent ad set or campaign (so sibling ads keep running). Thin wrapper over the `status` field of PUT /v1/ads/{adId}, for callers that want a URL symmetric to /v1/ads/campaigns/{campaignId}/status and /v1/ads/ad-sets/{adSetId}/status. `{adId}` accepts the same identifier dialects as GET/PUT /v1/ads/{adId} (Zernio hex `_id`, Meta numeric `platformAdId`, or the creative's effective story/media IDs). `platform` is inferred from the ad, so it's not required in the body. Ads in terminal statuses (rejected, completed, cancelled) and no-op flips (already in the target state) are skipped.
1601
+ # @param ad_id [String] Zernio &#x60;_id&#x60; (hex), Meta &#x60;platformAdId&#x60; (numeric), or one of the creative&#39;s effective story/media IDs.
1602
+ # @param update_ad_status_request [UpdateAdStatusRequest]
1603
+ # @param [Hash] opts the optional parameters
1604
+ # @return [UpdateAdStatus200Response]
1605
+ def update_ad_status(ad_id, update_ad_status_request, opts = {})
1606
+ data, _status_code, _headers = update_ad_status_with_http_info(ad_id, update_ad_status_request, opts)
1607
+ data
1608
+ end
1609
+
1610
+ # Pause or resume a single ad
1611
+ # Ad-scoped pause/resume — touches ONLY this ad, never its parent ad set or campaign (so sibling ads keep running). Thin wrapper over the &#x60;status&#x60; field of PUT /v1/ads/{adId}, for callers that want a URL symmetric to /v1/ads/campaigns/{campaignId}/status and /v1/ads/ad-sets/{adSetId}/status. &#x60;{adId}&#x60; accepts the same identifier dialects as GET/PUT /v1/ads/{adId} (Zernio hex &#x60;_id&#x60;, Meta numeric &#x60;platformAdId&#x60;, or the creative&#39;s effective story/media IDs). &#x60;platform&#x60; is inferred from the ad, so it&#39;s not required in the body. Ads in terminal statuses (rejected, completed, cancelled) and no-op flips (already in the target state) are skipped.
1612
+ # @param ad_id [String] Zernio &#x60;_id&#x60; (hex), Meta &#x60;platformAdId&#x60; (numeric), or one of the creative&#39;s effective story/media IDs.
1613
+ # @param update_ad_status_request [UpdateAdStatusRequest]
1614
+ # @param [Hash] opts the optional parameters
1615
+ # @return [Array<(UpdateAdStatus200Response, Integer, Hash)>] UpdateAdStatus200Response data, response status code and response headers
1616
+ def update_ad_status_with_http_info(ad_id, update_ad_status_request, opts = {})
1617
+ if @api_client.config.debugging
1618
+ @api_client.config.logger.debug 'Calling API: AdCampaignsApi.update_ad_status ...'
1619
+ end
1620
+ # verify the required parameter 'ad_id' is set
1621
+ if @api_client.config.client_side_validation && ad_id.nil?
1622
+ fail ArgumentError, "Missing the required parameter 'ad_id' when calling AdCampaignsApi.update_ad_status"
1623
+ end
1624
+ # verify the required parameter 'update_ad_status_request' is set
1625
+ if @api_client.config.client_side_validation && update_ad_status_request.nil?
1626
+ fail ArgumentError, "Missing the required parameter 'update_ad_status_request' when calling AdCampaignsApi.update_ad_status"
1627
+ end
1628
+ # resource path
1629
+ local_var_path = '/v1/ads/{adId}/status'.sub('{' + 'adId' + '}', CGI.escape(ad_id.to_s))
1630
+
1631
+ # query parameters
1632
+ query_params = opts[:query_params] || {}
1633
+
1634
+ # header parameters
1635
+ header_params = opts[:header_params] || {}
1636
+ # HTTP header 'Accept' (if needed)
1637
+ header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
1638
+ # HTTP header 'Content-Type'
1639
+ content_type = @api_client.select_header_content_type(['application/json'])
1640
+ if !content_type.nil?
1641
+ header_params['Content-Type'] = content_type
1642
+ end
1643
+
1644
+ # form parameters
1645
+ form_params = opts[:form_params] || {}
1646
+
1647
+ # http body (model)
1648
+ post_body = opts[:debug_body] || @api_client.object_to_http_body(update_ad_status_request)
1649
+
1650
+ # return_type
1651
+ return_type = opts[:debug_return_type] || 'UpdateAdStatus200Response'
1652
+
1653
+ # auth_names
1654
+ auth_names = opts[:debug_auth_names] || ['bearerAuth']
1655
+
1656
+ new_options = opts.merge(
1657
+ :operation => :"AdCampaignsApi.update_ad_status",
1658
+ :header_params => header_params,
1659
+ :query_params => query_params,
1660
+ :form_params => form_params,
1661
+ :body => post_body,
1662
+ :auth_names => auth_names,
1663
+ :return_type => return_type
1664
+ )
1665
+
1666
+ data, status_code, headers = @api_client.call_api(:PUT, local_var_path, new_options)
1667
+ if @api_client.config.debugging
1668
+ @api_client.config.logger.debug "API called: AdCampaignsApi#update_ad_status\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
1669
+ end
1670
+ return data, status_code, headers
1671
+ end
1066
1672
  end
1067
1673
  end