late-sdk 0.0.905 → 0.0.906

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -0
  3. data/docs/AdCampaignsApi.md +71 -1
  4. data/docs/AdCreative.md +4 -0
  5. data/docs/CreateStandaloneAdRequest.md +8 -6
  6. data/docs/GooglePmaxAssetGroup.md +28 -0
  7. data/docs/GooglePmaxAssetGroupAssetsInner.md +28 -0
  8. data/docs/GooglePmaxAssetGroupInput.md +32 -0
  9. data/docs/GooglePmaxAssetGroupInputImages.md +22 -0
  10. data/docs/ListGoogleAssetGroups200Response.md +22 -0
  11. data/lib/zernio-sdk/api/ad_campaigns_api.rb +70 -2
  12. data/lib/zernio-sdk/models/ad_creative.rb +21 -1
  13. data/lib/zernio-sdk/models/create_standalone_ad200_response_results_inner.rb +2 -2
  14. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +18 -9
  15. data/lib/zernio-sdk/models/google_pmax_asset_group.rb +299 -0
  16. data/lib/zernio-sdk/models/google_pmax_asset_group_assets_inner.rb +244 -0
  17. data/lib/zernio-sdk/models/google_pmax_asset_group_input.rb +453 -0
  18. data/lib/zernio-sdk/models/google_pmax_asset_group_input_images.rb +280 -0
  19. data/lib/zernio-sdk/models/list_google_asset_groups200_response.rb +204 -0
  20. data/lib/zernio-sdk/version.rb +1 -1
  21. data/lib/zernio-sdk.rb +5 -0
  22. data/openapi.yaml +184 -8
  23. data/spec/api/ad_campaigns_api_spec.rb +13 -1
  24. data/spec/models/ad_creative_spec.rb +12 -0
  25. data/spec/models/create_standalone_ad200_response_results_inner_spec.rb +1 -1
  26. data/spec/models/create_standalone_ad_request_spec.rb +7 -1
  27. data/spec/models/google_pmax_asset_group_assets_inner_spec.rb +66 -0
  28. data/spec/models/google_pmax_asset_group_input_images_spec.rb +48 -0
  29. data/spec/models/google_pmax_asset_group_input_spec.rb +78 -0
  30. data/spec/models/google_pmax_asset_group_spec.rb +66 -0
  31. data/spec/models/list_google_asset_groups200_response_spec.rb +48 -0
  32. data/zernio-sdk-0.0.906.gem +0 -0
  33. metadata +22 -2
  34. data/zernio-sdk-0.0.905.gem +0 -0
data/openapi.yaml CHANGED
@@ -9312,6 +9312,88 @@ components:
9312
9312
  $ref: '#/components/schemas/GoogleStructuredSnippet'
9313
9313
  description: "Supply fields for exactly one asset type per update. finalUrls may accompany sitelinkAsset. Shared asset edits affect every attachment using the asset."
9314
9314
 
9315
+ GooglePmaxAssetGroupInput:
9316
+ type: object
9317
+ additionalProperties: false
9318
+ required: [finalUrl, headlines, longHeadline, descriptions, businessName, images]
9319
+ description: "Google Performance Max creative assets. At least one description must be 60 characters or fewer. Texts within each list must be distinct."
9320
+ properties:
9321
+ name: { type: string, minLength: 1, maxLength: 128, description: "Defaults to the request name." }
9322
+ finalUrl: { type: string, format: uri, pattern: '^https?://', description: "Required destination URL." }
9323
+ headlines:
9324
+ type: array
9325
+ minItems: 3
9326
+ maxItems: 15
9327
+ uniqueItems: true
9328
+ items: { type: string, minLength: 1, maxLength: 30 }
9329
+ longHeadline: { type: string, minLength: 1, maxLength: 90 }
9330
+ descriptions:
9331
+ type: array
9332
+ minItems: 2
9333
+ maxItems: 5
9334
+ uniqueItems: true
9335
+ description: "At least one description must be 60 characters or fewer."
9336
+ items: { type: string, minLength: 1, maxLength: 90 }
9337
+ businessName: { type: string, minLength: 1, maxLength: 25 }
9338
+ images:
9339
+ type: object
9340
+ additionalProperties: false
9341
+ required: [landscape, square, logo]
9342
+ description: "Public HTTP(S) image URLs. GIF, JPEG or PNG, at most 5120 KB per image. Google validates dimensions and aspect ratios."
9343
+ properties:
9344
+ landscape:
9345
+ type: array
9346
+ minItems: 1
9347
+ maxItems: 20
9348
+ description: "Landscape marketing images. Aspect ratio 1.91:1, minimum 600 x 314 pixels."
9349
+ items: { type: string, format: uri, pattern: '^https?://' }
9350
+ square:
9351
+ type: array
9352
+ minItems: 1
9353
+ maxItems: 20
9354
+ description: "Square marketing images. Aspect ratio 1:1, minimum 300 x 300 pixels."
9355
+ items: { type: string, format: uri, pattern: '^https?://' }
9356
+ logo:
9357
+ type: array
9358
+ minItems: 1
9359
+ maxItems: 5
9360
+ description: "Required square logos. Aspect ratio 1:1, minimum 128 x 128 pixels."
9361
+ items: { type: string, format: uri, pattern: '^https?://' }
9362
+ youtubeVideoId:
9363
+ type: string
9364
+ pattern: '^[A-Za-z0-9_-]{11}$'
9365
+ description: "Optional existing YouTube video id. Google can generate video when omitted. Video uploads and arbitrary video URLs are not supported."
9366
+ example:
9367
+ finalUrl: 'https://zernio.com'
9368
+ headlines: ['Schedule posts', 'One social API', 'Build with Zernio']
9369
+ longHeadline: 'Schedule social content from your app with Zernio'
9370
+ descriptions: ['Connect your social accounts.', 'Publish and manage social content through one API.']
9371
+ businessName: Zernio
9372
+ images:
9373
+ landscape: ['https://example.com/landscape.png']
9374
+ square: ['https://example.com/square.png']
9375
+ logo: ['https://example.com/logo.png']
9376
+ GooglePmaxAssetGroup:
9377
+ type: object
9378
+ required: [id, resourceName, name, status, finalUrls, assets]
9379
+ properties:
9380
+ id: { type: string }
9381
+ resourceName: { type: string }
9382
+ name: { type: string }
9383
+ status: { type: string, description: "Asset-group status on Google. Campaign status independently controls delivery." }
9384
+ finalUrls: { type: array, items: { type: string, format: uri } }
9385
+ assets:
9386
+ type: array
9387
+ items:
9388
+ type: object
9389
+ required: [resourceName, fieldType, status]
9390
+ properties:
9391
+ resourceName: { type: string }
9392
+ fieldType: { type: string, description: "Google asset role, such as HEADLINE or LOGO." }
9393
+ status: { type: string }
9394
+ text: { type: string }
9395
+ imageUrl: { type: string, format: uri }
9396
+ youtubeVideoId: { type: string }
9315
9397
  GoogleRsaHeadline:
9316
9398
  type: object
9317
9399
  required:
@@ -9500,6 +9582,13 @@ components:
9500
9582
  type: [object, "null"]
9501
9583
  description: Platform-specific creative data. Fields vary by platform.
9502
9584
  properties:
9585
+ assetGroup:
9586
+ $ref: '#/components/schemas/GooglePmaxAssetGroupInput'
9587
+ description: "Initial Performance Max asset group input. Use the asset-groups endpoint for current Google assets."
9588
+ assetGroupResourceName:
9589
+ type: string
9590
+ description: "Google resource name of the created Performance Max asset group."
9591
+ example: "customers/9122445560/assetGroups/123456789"
9503
9592
  headlines:
9504
9593
  type: array
9505
9594
  minItems: 3
@@ -50258,6 +50347,55 @@ paths:
50258
50347
  Also returned as `idempotency_key_reused` when an Idempotency-Key
50259
50348
  is reused with a different request body.
50260
50349
 
50350
+ /v1/ads/campaigns/{campaignId}/asset-groups:
50351
+ get:
50352
+ operationId: listGoogleAssetGroups
50353
+ summary: List Performance Max asset groups
50354
+ tags: ["Ad Campaigns"]
50355
+ x-platforms: ["google"]
50356
+ x-resource-group: "ads"
50357
+ description: "Read Performance Max asset groups and their linked text, image and YouTube assets. campaignId is the platform campaign id returned by creation or the campaign list. The campaign must be visible to the caller. Uses a 10-minute cache, with the last successful response served as stale when Google quota is exhausted. Removed groups and asset links are excluded. Campaign-level brand assets on campaigns with brand guidelines enabled are not included."
50358
+ security:
50359
+ - bearerAuth: []
50360
+ parameters:
50361
+ - name: campaignId
50362
+ in: path
50363
+ required: true
50364
+ schema: { type: string, pattern: '^\d+$' }
50365
+ description: "Google Ads campaign id."
50366
+ responses:
50367
+ '200':
50368
+ description: "Asset groups and linked assets."
50369
+ content:
50370
+ application/json:
50371
+ schema:
50372
+ type: object
50373
+ required: [assetGroups, cachedAt, stale]
50374
+ properties:
50375
+ assetGroups: { type: array, items: { $ref: '#/components/schemas/GooglePmaxAssetGroup' } }
50376
+ cachedAt: { type: [string, "null"], format: date-time }
50377
+ stale: { type: boolean }
50378
+ example:
50379
+ assetGroups:
50380
+ - id: '123456789'
50381
+ resourceName: 'customers/9122445560/assetGroups/123456789'
50382
+ name: 'Social publishing'
50383
+ status: ENABLED
50384
+ finalUrls: ['https://zernio.com']
50385
+ assets:
50386
+ - resourceName: 'customers/9122445560/assets/987654321'
50387
+ fieldType: HEADLINE
50388
+ status: ENABLED
50389
+ text: 'Schedule posts'
50390
+ cachedAt: '2026-09-10T09:00:00Z'
50391
+ stale: false
50392
+ '400': { $ref: '#/components/responses/BadRequest' }
50393
+ '401': { $ref: '#/components/responses/Unauthorized' }
50394
+ '404': { $ref: '#/components/responses/NotFound' }
50395
+ '429':
50396
+ description: "Google quota or operation budget exhausted with no cached response."
50397
+ '501':
50398
+ description: "Campaign is not on Google Ads."
50261
50399
  /v1/ads/create:
50262
50400
  post:
50263
50401
  x-resource-group: "ads"
@@ -50268,7 +50406,20 @@ paths:
50268
50406
  description: |
50269
50407
  Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads).
50270
50408
 
50271
- Three mutually-exclusive request shapes are selected by the body:
50409
+ Google Performance Max: set `campaignType: "pmax"` and supply `assetGroup` with
50410
+ text, images by role, business name and finalUrl. Creates a daily budget, PAUSED
50411
+ campaign and asset group atomically. `validateOnly: true` validates the complete
50412
+ request with Google without creating or persisting resources. Read assets with
50413
+ `GET /v1/ads/campaigns/{campaignId}/asset-groups`. The logo is required; video is
50414
+ optional via `assetGroup.youtubeVideoId`. Brand guidelines are disabled at creation.
50415
+ PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields
50416
+ and attach shapes. Geo and language targeting are supported; omitted geo targets
50417
+ all locations. PMax does not require top-level goal, headline, body or linkUrl.
50418
+ Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions,
50419
+ COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus
50420
+ roasAverageFloor for Maximize Conversion Value with target ROAS.
50421
+
50422
+ Other mutually-exclusive request shapes are selected by the body:
50272
50423
 
50273
50424
  - Legacy single-creative shape (all platforms, the default).
50274
50425
  - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting.
@@ -50347,13 +50498,13 @@ paths:
50347
50498
  description: "Meta only. Multi-advertiser ads: whether Meta may show this ad alongside other advertisers' in one unit. Meta auto-enrols since Aug 2024, so send OPT_OUT to leave. It is a top-level creative field, NOT a `creativeFeatures` key, and Meta rejects it there."
50348
50499
  validateOnly:
50349
50500
  type: boolean
50350
- description: 'Meta only. Validates the complete inline campaign, ad set, creative and ad with execution_options validate_only. Nothing is uploaded or created, and validation bypasses Idempotency-Key storage. Supports a single image, existing video.id or existingCreativeId; media pools, new video uploads, creatives[], adSetId and RESERVED buying return 400. Existing campaign or creative nodes are marked skipped. Success returns 200 with per-node results; Meta rejection returns an error.'
50351
- budgetAmount: { type: number, description: "Budget in WHOLE currency units (USD: 50 = $50.00), NOT cents. Meta's own Marketing API takes this same number in minor units, so it is an easy and expensive mix-up. Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType)." }
50352
- budgetType: { type: string, enum: [daily, lifetime], description: "Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads accepts lifetime only (no daily-budget concept on the platform); sending daily returns 422. OpenAI Ads lifetime budgets require `endDate` to give the lifetime cap a spend window." }
50501
+ description: 'Google Performance Max validates the complete atomic campaign and asset group with no resource creation or local persistence. Google validation still downloads image URLs and consumes quota. On Meta, validates the complete inline campaign, ad set, creative and ad with execution_options validate_only. Nothing is uploaded or created, and validation bypasses Idempotency-Key storage. Supports a single image, existing video.id or existingCreativeId; media pools, new video uploads, creatives[], adSetId and RESERVED buying return 400. Existing campaign or creative nodes are marked skipped. Success returns 200 with per-node results; Meta rejection returns an error.'
50502
+ budgetAmount: { type: number, description: "Budget in WHOLE currency units (USD: 50 = $50.00), NOT cents. Meta's own Marketing API takes this same number in minor units, so it is an easy and expensive mix-up. Required on legacy, multi-creative and Performance Max shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType)." }
50503
+ budgetType: { type: string, enum: [daily, lifetime], description: "Required on legacy, multi-creative and Performance Max shapes. Inherited on attach. OpenAI Ads accepts lifetime only (no daily-budget concept on the platform); sending daily returns 422. OpenAI Ads lifetime budgets require `endDate` to give the lifetime cap a spend window." }
50353
50504
  status:
50354
50505
  type: string
50355
50506
  enum: [ACTIVE, PAUSED]
50356
- description: "Meta, TikTok, and LinkedIn. Publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each)."
50507
+ description: "Google Performance Max accepts PAUSED only and always creates a paused campaign. Meta, TikTok, and LinkedIn: publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each)."
50357
50508
  campaignStatus:
50358
50509
  type: string
50359
50510
  enum: [ACTIVE, PAUSED]
@@ -50984,7 +51135,9 @@ paths:
50984
51135
  type: array
50985
51136
  items: { type: string, enum: [mobile, desktop] }
50986
51137
  audienceId: { type: string, description: Custom audience ID for targeting }
50987
- campaignType: { type: string, enum: [display, search], default: display, description: Google only }
51138
+ campaignType: { type: string, enum: [display, search, pmax], default: display, description: "Google only. Performance Max requires assetGroup and is always created PAUSED." }
51139
+ assetGroup:
51140
+ $ref: '#/components/schemas/GooglePmaxAssetGroupInput'
50988
51141
  keywords: { type: array, maxItems: 1000, items: { $ref: '#/components/schemas/KeywordEntry' }, description: "Google Search only. Keywords on the new ad group; entries are strings (BROAD) or { text, matchType }. Editable later via PUT /v1/ads/{adId} targeting.keywords." }
50989
51142
  negativeKeywords: { type: array, maxItems: 1000, items: { $ref: '#/components/schemas/KeywordEntry' }, description: "Google Search only; other platforms return 400. Ad-group-level negative keywords on the new ad group. Editable later via PUT /v1/ads/{adId} targeting.negativeKeywords." }
50990
51143
  campaignNegativeKeywords: { type: array, maxItems: 1000, items: { $ref: '#/components/schemas/KeywordEntry' }, description: "Google Search only; other platforms return 400. Campaign-level negative keywords (campaign_criterion.negative), created alongside the ad group. Editable later via PUT /v1/ads/campaigns/{campaignId}/negative-keywords." }
@@ -51126,7 +51279,7 @@ paths:
51126
51279
  portfolioBidStrategyId:
51127
51280
  type: string
51128
51281
  pattern: '^\d+$'
51129
- description: "Google only. Attach an existing portfolio bid strategy (numeric id from GET /v1/ads/bid-strategies) to the new campaign instead of a standard one. Exclusive with bidStrategy."
51282
+ description: "Google Search and Display only. Performance Max rejects portfolio bidding. Attach an existing portfolio bid strategy (numeric id from GET /v1/ads/bid-strategies) to the new campaign instead of a standard one. Exclusive with bidStrategy."
51130
51283
  valueRuleSetId:
51131
51284
  type: string
51132
51285
  pattern: '^\d+$'
@@ -51264,6 +51417,29 @@ paths:
51264
51417
  promotedObject:
51265
51418
  $ref: '#/components/schemas/AdPromotedObject'
51266
51419
  examples:
51420
+ performanceMax:
51421
+ summary: "Paused Performance Max campaign."
51422
+ value:
51423
+ accountId: '69ce75d483e990e1c01ccfe4'
51424
+ adAccountId: '9122445560'
51425
+ name: 'Social publishing'
51426
+ campaignType: pmax
51427
+ budgetAmount: 1
51428
+ budgetType: daily
51429
+ status: PAUSED
51430
+ validateOnly: true
51431
+ countries: [US]
51432
+ languages: [en]
51433
+ assetGroup:
51434
+ finalUrl: 'https://zernio.com'
51435
+ headlines: ['Schedule posts', 'One social API', 'Build with Zernio']
51436
+ longHeadline: 'Schedule social content from your app with Zernio'
51437
+ descriptions: ['Connect your social accounts.', 'Publish and manage social content through one API.']
51438
+ businessName: Zernio
51439
+ images:
51440
+ landscape: ['https://example.com/landscape.png']
51441
+ square: ['https://example.com/square.png']
51442
+ logo: ['https://example.com/logo.png']
51267
51443
  appPromotion:
51268
51444
  value:
51269
51445
  accountId: '69fc524892b3d8e85f893e73'
@@ -51322,7 +51498,7 @@ paths:
51322
51498
  items:
51323
51499
  type: object
51324
51500
  properties:
51325
- node: { type: string, enum: [campaign, adSet, creative, ad] }
51501
+ node: { type: string, enum: [campaign, adSet, creative, ad, performanceMaxCampaign] }
51326
51502
  status: { type: string, enum: [validated, skipped] }
51327
51503
  reason: { type: string, description: "Why the node could not be validated (only on skipped)." }
51328
51504
  message: { type: string }
@@ -135,7 +135,7 @@ describe 'AdCampaignsApi' do
135
135
 
136
136
  # unit tests for create_standalone_ad
137
137
  # Create standalone ad
138
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `promotion` and `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`. An item replaces the whole feature map; its `promotion` replaces the default offer, and `promotion: null` disables that default for the item. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Only ads supplied a `promotion` receive live readback; multi-create batches those reads in groups of up to 50 IDs without per-ad fallback. Inspect `ad.creative.promotionStatus` (or `ads[].creative.promotionStatus`). `not_returned` means Meta omitted the metadata; successful creation does not by itself prove the offer was applied or will display. 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.
138
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Google Performance Max: set `campaignType: \"pmax\"` and supply `assetGroup` with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. `validateOnly: true` validates the complete request with Google without creating or persisting resources. Read assets with `GET /v1/ads/campaigns/{campaignId}/asset-groups`. The logo is required; video is optional via `assetGroup.youtubeVideoId`. Brand guidelines are disabled at creation. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS. Other mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `promotion` and `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`. An item replaces the whole feature map; its `promotion` replaces the default offer, and `promotion: null` disables that default for the item. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Only ads supplied a `promotion` receive live readback; multi-create batches those reads in groups of up to 50 IDs without per-ad fallback. Inspect `ad.creative.promotionStatus` (or `ads[].creative.promotionStatus`). `not_returned` means Meta omitted the metadata; successful creation does not by itself prove the offer was applied or will display. 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.
139
139
  # @param create_standalone_ad_request
140
140
  # @param [Hash] opts the optional parameters
141
141
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
@@ -481,6 +481,18 @@ describe 'AdCampaignsApi' do
481
481
  end
482
482
  end
483
483
 
484
+ # unit tests for list_google_asset_groups
485
+ # List Performance Max asset groups
486
+ # Read Performance Max asset groups and their linked text, image and YouTube assets. campaignId is the platform campaign id returned by creation or the campaign list. The campaign must be visible to the caller. Uses a 10-minute cache, with the last successful response served as stale when Google quota is exhausted. Removed groups and asset links are excluded. Campaign-level brand assets on campaigns with brand guidelines enabled are not included.
487
+ # @param campaign_id Google Ads campaign id.
488
+ # @param [Hash] opts the optional parameters
489
+ # @return [ListGoogleAssetGroups200Response]
490
+ describe 'list_google_asset_groups test' do
491
+ it 'should work' do
492
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
493
+ end
494
+ end
495
+
484
496
  # unit tests for remove_ad_group_assets
485
497
  # Remove ad-group assets
486
498
  # Removes the specified attachments only. Google assets cannot be deleted. Other attachments remain. assetResourceNames is retained for compatibility.
@@ -27,6 +27,18 @@ describe Zernio::AdCreative do
27
27
  end
28
28
  end
29
29
 
30
+ describe 'test attribute "asset_group"' 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 "asset_group_resource_name"' 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
+
30
42
  describe 'test attribute "headlines"' do
31
43
  it 'should work' do
32
44
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
@@ -30,7 +30,7 @@ describe Zernio::CreateStandaloneAd200ResponseResultsInner do
30
30
  describe 'test attribute "node"' do
31
31
  it 'should work' do
32
32
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
- # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["campaign", "adSet", "creative", "ad"])
33
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["campaign", "adSet", "creative", "ad", "performanceMaxCampaign"])
34
34
  # validator.allowable_values.each do |value|
35
35
  # expect { instance.node = value }.not_to raise_error
36
36
  # end
@@ -518,13 +518,19 @@ describe Zernio::CreateStandaloneAdRequest do
518
518
  describe 'test attribute "campaign_type"' do
519
519
  it 'should work' do
520
520
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
521
- # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["display", "search"])
521
+ # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["display", "search", "pmax"])
522
522
  # validator.allowable_values.each do |value|
523
523
  # expect { instance.campaign_type = value }.not_to raise_error
524
524
  # end
525
525
  end
526
526
  end
527
527
 
528
+ describe 'test attribute "asset_group"' do
529
+ it 'should work' do
530
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
531
+ end
532
+ end
533
+
528
534
  describe 'test attribute "keywords"' do
529
535
  it 'should work' do
530
536
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
@@ -0,0 +1,66 @@
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::GooglePmaxAssetGroupAssetsInner
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::GooglePmaxAssetGroupAssetsInner do
21
+ #let(:instance) { Zernio::GooglePmaxAssetGroupAssetsInner.new }
22
+
23
+ describe 'test an instance of GooglePmaxAssetGroupAssetsInner' do
24
+ it 'should create an instance of GooglePmaxAssetGroupAssetsInner' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::GooglePmaxAssetGroupAssetsInner)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "resource_name"' 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 "field_type"' 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 "status"' 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 "text"' 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
+ describe 'test attribute "image_url"' do
55
+ it 'should work' do
56
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
57
+ end
58
+ end
59
+
60
+ describe 'test attribute "youtube_video_id"' do
61
+ it 'should work' do
62
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,48 @@
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::GooglePmaxAssetGroupInputImages
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::GooglePmaxAssetGroupInputImages do
21
+ #let(:instance) { Zernio::GooglePmaxAssetGroupInputImages.new }
22
+
23
+ describe 'test an instance of GooglePmaxAssetGroupInputImages' do
24
+ it 'should create an instance of GooglePmaxAssetGroupInputImages' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::GooglePmaxAssetGroupInputImages)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "landscape"' 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 "square"' 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 "logo"' 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
+ end
@@ -0,0 +1,78 @@
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::GooglePmaxAssetGroupInput
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::GooglePmaxAssetGroupInput do
21
+ #let(:instance) { Zernio::GooglePmaxAssetGroupInput.new }
22
+
23
+ describe 'test an instance of GooglePmaxAssetGroupInput' do
24
+ it 'should create an instance of GooglePmaxAssetGroupInput' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::GooglePmaxAssetGroupInput)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "name"' 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 "final_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 "headlines"' 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 "long_headline"' 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
+ describe 'test attribute "descriptions"' do
55
+ it 'should work' do
56
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
57
+ end
58
+ end
59
+
60
+ describe 'test attribute "business_name"' do
61
+ it 'should work' do
62
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
63
+ end
64
+ end
65
+
66
+ describe 'test attribute "images"' do
67
+ it 'should work' do
68
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
69
+ end
70
+ end
71
+
72
+ describe 'test attribute "youtube_video_id"' do
73
+ it 'should work' do
74
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,66 @@
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::GooglePmaxAssetGroup
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::GooglePmaxAssetGroup do
21
+ #let(:instance) { Zernio::GooglePmaxAssetGroup.new }
22
+
23
+ describe 'test an instance of GooglePmaxAssetGroup' do
24
+ it 'should create an instance of GooglePmaxAssetGroup' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::GooglePmaxAssetGroup)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "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 "resource_name"' 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 "name"' 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 "status"' 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
+ describe 'test attribute "final_urls"' do
55
+ it 'should work' do
56
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
57
+ end
58
+ end
59
+
60
+ describe 'test attribute "assets"' do
61
+ it 'should work' do
62
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
63
+ end
64
+ end
65
+
66
+ end