late-sdk 0.0.900 → 0.0.901

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 (156) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -6
  3. data/docs/AdAccountsApi.md +657 -19
  4. data/docs/AdCampaignsApi.md +521 -9
  5. data/docs/AdCreative.md +6 -0
  6. data/docs/AddAccountCalloutsRequest.md +3 -3
  7. data/docs/AddAccountSitelinks201Response.md +20 -0
  8. data/docs/AddAccountSitelinks201ResponseSitelinksInner.md +26 -0
  9. data/docs/AddAccountSitelinksRequest.md +22 -0
  10. data/docs/AddAccountStructuredSnippets201Response.md +20 -0
  11. data/docs/AddAccountStructuredSnippets201ResponseStructuredSnippetsInner.md +22 -0
  12. data/docs/AddAccountStructuredSnippetsRequest.md +22 -0
  13. data/docs/AttachAdGroupAssets201Response.md +24 -0
  14. data/docs/AttachCampaignAssetsRequest.md +4 -4
  15. data/docs/CreateStandaloneAdRequest.md +4 -4
  16. data/docs/CreateStandaloneAdRequestAdditionalDescriptionsInner.md +49 -0
  17. data/docs/CreateStandaloneAdRequestAdditionalHeadlinesInner.md +49 -0
  18. data/docs/GetAd200Response.md +5 -1
  19. data/docs/GoogleAssetUpdate.md +26 -0
  20. data/docs/GoogleRsaDescription.md +20 -0
  21. data/docs/GoogleRsaHeadline.md +20 -0
  22. data/docs/{AttachCampaignAssetsRequestSitelinksInner.md → GoogleSitelink.md} +2 -2
  23. data/docs/{AttachCampaignAssetsRequestStructuredSnippetsInner.md → GoogleStructuredSnippet.md} +2 -2
  24. data/docs/ListAccountCallouts200Response.md +2 -2
  25. data/docs/ListAccountCallouts200ResponseCalloutsInner.md +3 -3
  26. data/docs/ListAccountSitelinks200Response.md +24 -0
  27. data/docs/ListAccountSitelinks200ResponseSitelinksInner.md +32 -0
  28. data/docs/ListAccountStructuredSnippets200Response.md +24 -0
  29. data/docs/ListAccountStructuredSnippets200ResponseStructuredSnippetsInner.md +28 -0
  30. data/docs/ListAdGroupAssets200Response.md +28 -0
  31. data/docs/ListAdGroupAssets200ResponseCalloutsInner.md +22 -0
  32. data/docs/ListAdGroupAssets200ResponseSitelinksInner.md +28 -0
  33. data/docs/ListAdGroupAssets200ResponseStructuredSnippetsInner.md +24 -0
  34. data/docs/ListCampaignAssets200Response.md +28 -0
  35. data/docs/ListCampaignAssets200ResponseCalloutsInner.md +22 -0
  36. data/docs/ListCampaignAssets200ResponseSitelinksInner.md +28 -0
  37. data/docs/ListCampaignAssets200ResponseStructuredSnippetsInner.md +24 -0
  38. data/docs/RemoveAccountCalloutRequest.md +3 -3
  39. data/docs/RemoveAdGroupAssetsRequest.md +24 -0
  40. data/docs/RemoveCampaignAssets200Response.md +18 -0
  41. data/docs/RemoveCampaignAssetsRequest.md +24 -0
  42. data/docs/UpdateAccountCallouts200Response.md +20 -0
  43. data/docs/UpdateAccountCalloutsRequest.md +22 -0
  44. data/docs/UpdateAccountCalloutsRequestUpdatesInner.md +20 -0
  45. data/docs/UpdateAccountCalloutsRequestUpdatesInnerCalloutAsset.md +18 -0
  46. data/docs/UpdateAccountSitelinksRequest.md +22 -0
  47. data/docs/UpdateAccountSitelinksRequestUpdatesInner.md +22 -0
  48. data/docs/UpdateAccountSitelinksRequestUpdatesInnerSitelinkAsset.md +24 -0
  49. data/docs/UpdateAccountStructuredSnippetsRequest.md +22 -0
  50. data/docs/UpdateAccountStructuredSnippetsRequestUpdatesInner.md +20 -0
  51. data/docs/UpdateAdRequest.md +6 -0
  52. data/docs/UpdateCampaignAssets200Response.md +18 -0
  53. data/docs/UpdateCampaignAssetsRequest.md +22 -0
  54. data/lib/zernio-sdk/api/ad_accounts_api.rb +656 -16
  55. data/lib/zernio-sdk/api/ad_campaigns_api.rb +586 -10
  56. data/lib/zernio-sdk/models/ad_creative.rb +112 -1
  57. data/lib/zernio-sdk/models/add_account_callouts_request.rb +34 -3
  58. data/lib/zernio-sdk/models/add_account_sitelinks201_response.rb +158 -0
  59. data/lib/zernio-sdk/models/add_account_sitelinks201_response_sitelinks_inner.rb +267 -0
  60. data/lib/zernio-sdk/models/add_account_sitelinks_request.rb +253 -0
  61. data/lib/zernio-sdk/models/add_account_structured_snippets201_response.rb +158 -0
  62. data/lib/zernio-sdk/models/add_account_structured_snippets201_response_structured_snippets_inner.rb +229 -0
  63. data/lib/zernio-sdk/models/add_account_structured_snippets_request.rb +253 -0
  64. data/lib/zernio-sdk/models/attach_ad_group_assets201_response.rb +180 -0
  65. data/lib/zernio-sdk/models/attach_campaign_assets_request.rb +37 -5
  66. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +4 -4
  67. data/lib/zernio-sdk/models/create_standalone_ad_request_additional_descriptions_inner.rb +104 -0
  68. data/lib/zernio-sdk/models/create_standalone_ad_request_additional_headlines_inner.rb +104 -0
  69. data/lib/zernio-sdk/models/get_ad200_response.rb +25 -4
  70. data/lib/zernio-sdk/models/google_asset_update.rb +234 -0
  71. data/lib/zernio-sdk/models/google_rsa_description.rb +226 -0
  72. data/lib/zernio-sdk/models/google_rsa_headline.rb +226 -0
  73. data/lib/zernio-sdk/models/{attach_campaign_assets_request_sitelinks_inner.rb → google_sitelink.rb} +3 -3
  74. data/lib/zernio-sdk/models/{attach_campaign_assets_request_structured_snippets_inner.rb → google_structured_snippet.rb} +3 -3
  75. data/lib/zernio-sdk/models/list_account_callouts200_response.rb +2 -2
  76. data/lib/zernio-sdk/models/list_account_callouts200_response_callouts_inner.rb +13 -14
  77. data/lib/zernio-sdk/models/list_account_sitelinks200_response.rb +179 -0
  78. data/lib/zernio-sdk/models/list_account_sitelinks200_response_sitelinks_inner.rb +210 -0
  79. data/lib/zernio-sdk/models/list_account_structured_snippets200_response.rb +179 -0
  80. data/lib/zernio-sdk/models/list_account_structured_snippets200_response_structured_snippets_inner.rb +194 -0
  81. data/lib/zernio-sdk/models/list_ad_group_assets200_response.rb +201 -0
  82. data/lib/zernio-sdk/models/list_ad_group_assets200_response_callouts_inner.rb +165 -0
  83. data/lib/zernio-sdk/models/list_ad_group_assets200_response_sitelinks_inner.rb +192 -0
  84. data/lib/zernio-sdk/models/list_ad_group_assets200_response_structured_snippets_inner.rb +176 -0
  85. data/lib/zernio-sdk/models/list_campaign_assets200_response.rb +201 -0
  86. data/lib/zernio-sdk/models/list_campaign_assets200_response_callouts_inner.rb +165 -0
  87. data/lib/zernio-sdk/models/list_campaign_assets200_response_sitelinks_inner.rb +192 -0
  88. data/lib/zernio-sdk/models/list_campaign_assets200_response_structured_snippets_inner.rb +176 -0
  89. data/lib/zernio-sdk/models/remove_account_callout_request.rb +45 -3
  90. data/lib/zernio-sdk/models/remove_ad_group_assets_request.rb +281 -0
  91. data/lib/zernio-sdk/models/remove_campaign_assets200_response.rb +147 -0
  92. data/lib/zernio-sdk/models/remove_campaign_assets_request.rb +281 -0
  93. data/lib/zernio-sdk/models/update_account_callouts200_response.rb +156 -0
  94. data/lib/zernio-sdk/models/update_account_callouts_request.rb +253 -0
  95. data/lib/zernio-sdk/models/update_account_callouts_request_updates_inner.rb +186 -0
  96. data/lib/zernio-sdk/models/update_account_callouts_request_updates_inner_callout_asset.rb +182 -0
  97. data/lib/zernio-sdk/models/update_account_sitelinks_request.rb +253 -0
  98. data/lib/zernio-sdk/models/update_account_sitelinks_request_updates_inner.rb +216 -0
  99. data/lib/zernio-sdk/models/update_account_sitelinks_request_updates_inner_sitelink_asset.rb +241 -0
  100. data/lib/zernio-sdk/models/update_account_structured_snippets_request.rb +253 -0
  101. data/lib/zernio-sdk/models/update_account_structured_snippets_request_updates_inner.rb +186 -0
  102. data/lib/zernio-sdk/models/update_ad_request.rb +112 -1
  103. data/lib/zernio-sdk/models/update_campaign_assets200_response.rb +147 -0
  104. data/lib/zernio-sdk/models/update_campaign_assets_request.rb +253 -0
  105. data/lib/zernio-sdk/version.rb +1 -1
  106. data/lib/zernio-sdk.rb +40 -2
  107. data/openapi.yaml +2010 -320
  108. data/spec/api/ad_accounts_api_spec.rb +118 -8
  109. data/spec/api/ad_campaigns_api_spec.rb +98 -5
  110. data/spec/models/ad_creative_spec.rb +18 -0
  111. data/spec/models/add_account_sitelinks201_response_sitelinks_inner_spec.rb +60 -0
  112. data/spec/models/add_account_sitelinks201_response_spec.rb +42 -0
  113. data/spec/models/add_account_sitelinks_request_spec.rb +48 -0
  114. data/spec/models/add_account_structured_snippets201_response_spec.rb +42 -0
  115. data/spec/models/add_account_structured_snippets201_response_structured_snippets_inner_spec.rb +52 -0
  116. data/spec/models/add_account_structured_snippets_request_spec.rb +48 -0
  117. data/spec/models/attach_ad_group_assets201_response_spec.rb +54 -0
  118. data/spec/models/create_standalone_ad_request_additional_descriptions_inner_spec.rb +32 -0
  119. data/spec/models/create_standalone_ad_request_additional_headlines_inner_spec.rb +32 -0
  120. data/spec/models/get_ad200_response_spec.rb +12 -0
  121. data/spec/models/google_asset_update_spec.rb +60 -0
  122. data/spec/models/google_rsa_description_spec.rb +46 -0
  123. data/spec/models/google_rsa_headline_spec.rb +46 -0
  124. data/spec/models/{attach_campaign_assets_request_sitelinks_inner_spec.rb → google_sitelink_spec.rb} +6 -6
  125. data/spec/models/{attach_campaign_assets_request_structured_snippets_inner_spec.rb → google_structured_snippet_spec.rb} +6 -6
  126. data/spec/models/list_account_callouts200_response_callouts_inner_spec.rb +2 -2
  127. data/spec/models/list_account_sitelinks200_response_sitelinks_inner_spec.rb +78 -0
  128. data/spec/models/list_account_sitelinks200_response_spec.rb +54 -0
  129. data/spec/models/list_account_structured_snippets200_response_spec.rb +54 -0
  130. data/spec/models/list_account_structured_snippets200_response_structured_snippets_inner_spec.rb +66 -0
  131. data/spec/models/list_ad_group_assets200_response_callouts_inner_spec.rb +48 -0
  132. data/spec/models/list_ad_group_assets200_response_sitelinks_inner_spec.rb +66 -0
  133. data/spec/models/list_ad_group_assets200_response_spec.rb +66 -0
  134. data/spec/models/list_ad_group_assets200_response_structured_snippets_inner_spec.rb +54 -0
  135. data/spec/models/list_campaign_assets200_response_callouts_inner_spec.rb +48 -0
  136. data/spec/models/list_campaign_assets200_response_sitelinks_inner_spec.rb +66 -0
  137. data/spec/models/list_campaign_assets200_response_spec.rb +66 -0
  138. data/spec/models/list_campaign_assets200_response_structured_snippets_inner_spec.rb +54 -0
  139. data/spec/models/remove_ad_group_assets_request_spec.rb +54 -0
  140. data/spec/models/remove_campaign_assets200_response_spec.rb +36 -0
  141. data/spec/models/remove_campaign_assets_request_spec.rb +54 -0
  142. data/spec/models/update_account_callouts200_response_spec.rb +42 -0
  143. data/spec/models/update_account_callouts_request_spec.rb +48 -0
  144. data/spec/models/update_account_callouts_request_updates_inner_callout_asset_spec.rb +36 -0
  145. data/spec/models/update_account_callouts_request_updates_inner_spec.rb +42 -0
  146. data/spec/models/update_account_sitelinks_request_spec.rb +48 -0
  147. data/spec/models/update_account_sitelinks_request_updates_inner_sitelink_asset_spec.rb +54 -0
  148. data/spec/models/update_account_sitelinks_request_updates_inner_spec.rb +48 -0
  149. data/spec/models/update_account_structured_snippets_request_spec.rb +48 -0
  150. data/spec/models/update_account_structured_snippets_request_updates_inner_spec.rb +42 -0
  151. data/spec/models/update_ad_request_spec.rb +18 -0
  152. data/spec/models/update_campaign_assets200_response_spec.rb +36 -0
  153. data/spec/models/update_campaign_assets_request_spec.rb +48 -0
  154. data/zernio-sdk-0.0.901.gem +0 -0
  155. metadata +162 -10
  156. data/zernio-sdk-0.0.900.gem +0 -0
data/openapi.yaml CHANGED
@@ -9175,6 +9175,135 @@ components:
9175
9175
  enum: [applied, not_returned, unavailable]
9176
9176
  description: 'Meta creative readback result. applied means Meta returned promotion metadata; not_returned means the read succeeded without promotion metadata; unavailable means the read failed. Only applied confirms the returned offer. Missing metadata is not proof that Ads Manager displays the requested Promotion.'
9177
9177
  example: not_returned
9178
+ GoogleSitelink:
9179
+ type: object
9180
+ required:
9181
+ - text
9182
+ - linkUrl
9183
+ properties:
9184
+ text:
9185
+ type: string
9186
+ minLength: 1
9187
+ maxLength: 25
9188
+ linkUrl:
9189
+ type: string
9190
+ format: uri
9191
+ description1:
9192
+ type: string
9193
+ minLength: 1
9194
+ maxLength: 35
9195
+ description2:
9196
+ type: string
9197
+ minLength: 1
9198
+ maxLength: 35
9199
+ GoogleStructuredSnippet:
9200
+ type: object
9201
+ required:
9202
+ - header
9203
+ - values
9204
+ properties:
9205
+ header:
9206
+ type: string
9207
+ enum:
9208
+ - Amenities
9209
+ - Brands
9210
+ - Courses
9211
+ - Degree programs
9212
+ - Destinations
9213
+ - Featured hotels
9214
+ - Insurance coverage
9215
+ - Models
9216
+ - Neighborhoods
9217
+ - Service catalog
9218
+ - Shows
9219
+ - Styles
9220
+ - Types
9221
+ values:
9222
+ type: array
9223
+ minItems: 3
9224
+ maxItems: 10
9225
+ items:
9226
+ type: string
9227
+ minLength: 1
9228
+ maxLength: 25
9229
+ GoogleAssetUpdate:
9230
+ type: object
9231
+ required:
9232
+ - assetResourceName
9233
+ properties:
9234
+ assetResourceName:
9235
+ type: string
9236
+ pattern: ^customers/\d+/assets/\d+$
9237
+ description: "Asset resource name returned by a list operation. Must belong to the selected customer."
9238
+ sitelinkAsset:
9239
+ type: object
9240
+ properties:
9241
+ linkText:
9242
+ type: string
9243
+ minLength: 1
9244
+ maxLength: 25
9245
+ description1:
9246
+ type: string
9247
+ maxLength: 35
9248
+ description2:
9249
+ type: string
9250
+ maxLength: 35
9251
+ linkUrl:
9252
+ type: string
9253
+ format: uri
9254
+ description: "Alias for finalUrls with one URL. Do not supply both."
9255
+ minProperties: 1
9256
+ finalUrls:
9257
+ type: array
9258
+ items:
9259
+ type: string
9260
+ format: uri
9261
+ minItems: 1
9262
+ calloutAsset:
9263
+ type: object
9264
+ required:
9265
+ - calloutText
9266
+ properties:
9267
+ calloutText:
9268
+ type: string
9269
+ minLength: 1
9270
+ maxLength: 25
9271
+ structuredSnippetAsset:
9272
+ $ref: '#/components/schemas/GoogleStructuredSnippet'
9273
+ description: "Supply fields for exactly one asset type per update. finalUrls may accompany sitelinkAsset. Shared asset edits affect every attachment using the asset."
9274
+
9275
+ GoogleRsaHeadline:
9276
+ type: object
9277
+ required:
9278
+ - text
9279
+ properties:
9280
+ text:
9281
+ type: string
9282
+ minLength: 1
9283
+ maxLength: 30
9284
+ pinnedField:
9285
+ type: string
9286
+ enum:
9287
+ - HEADLINE_1
9288
+ - HEADLINE_2
9289
+ - HEADLINE_3
9290
+ description: "Optional fixed headline position. Omit to leave the asset unpinned."
9291
+ GoogleRsaDescription:
9292
+ type: object
9293
+ required:
9294
+ - text
9295
+ properties:
9296
+ text:
9297
+ type: string
9298
+ minLength: 1
9299
+ maxLength: 90
9300
+ pinnedField:
9301
+ type: string
9302
+ enum:
9303
+ - DESCRIPTION_1
9304
+ - DESCRIPTION_2
9305
+ description: "Optional fixed description position. Omit to leave the asset unpinned."
9306
+
9178
9307
  Ad:
9179
9308
  type: object
9180
9309
  properties:
@@ -9331,6 +9460,27 @@ components:
9331
9460
  type: [object, "null"]
9332
9461
  description: Platform-specific creative data. Fields vary by platform.
9333
9462
  properties:
9463
+ headlines:
9464
+ type: array
9465
+ minItems: 3
9466
+ maxItems: 15
9467
+ items:
9468
+ $ref: '#/components/schemas/GoogleRsaHeadline'
9469
+ description: "Google RSA only. Replaces the complete headline list. No padding or truncation on update."
9470
+ descriptions:
9471
+ type: array
9472
+ minItems: 2
9473
+ maxItems: 4
9474
+ items:
9475
+ $ref: '#/components/schemas/GoogleRsaDescription'
9476
+ description: "Google RSA only. Replaces the complete description list. No padding or truncation on update."
9477
+ finalUrls:
9478
+ type: array
9479
+ minItems: 1
9480
+ items:
9481
+ type: string
9482
+ format: uri
9483
+ description: "Google RSA only. Replaces final URLs. Omitted lists stay unchanged."
9334
9484
  thumbnailUrl: { type: [string, "null"], description: Primary thumbnail/image URL }
9335
9485
  imageUrl: { type: string, description: Alternative image URL }
9336
9486
  videoId: { type: [string, "null"], description: "Meta video ID for VIDEO-type ads. Null for non-video ads. Callers that need an embeddable MP4 can call GET /{videoId}?fields=source with the page access token." }
@@ -44491,6 +44641,11 @@ paths:
44491
44641
  summary: Get ad details
44492
44642
  description: |
44493
44643
  Returns an ad with its creative, targeting, status, and performance metrics.
44644
+ Google Search ads include current creative.headlines, creative.descriptions and creative.finalUrls,
44645
+ preserving pinnedField. Top-level cachedAt and stale report cache freshness. Google mutations invalidate this read.
44646
+ RSA enrichment requires a stored advertisingChannelType of SEARCH. Ads with an unknown or other channel
44647
+ return their stored details without a Google read. If RSA enrichment fails, the stored ad is returned
44648
+ with HTTP 200 and without cache metadata.
44494
44649
 
44495
44650
  The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad:
44496
44651
  - the Zernio internal `_id` (24-char hex)
@@ -44523,10 +44678,26 @@ paths:
44523
44678
  description: Ad details
44524
44679
  content:
44525
44680
  application/json:
44681
+ example:
44682
+ ad:
44683
+ platform: google
44684
+ creative:
44685
+ headlines:
44686
+ - { text: "Social Media API", pinnedField: HEADLINE_1 }
44687
+ - { text: "Schedule Your Posts" }
44688
+ - { text: "Build With Zernio" }
44689
+ descriptions:
44690
+ - { text: "Connect social accounts with one API.", pinnedField: DESCRIPTION_1 }
44691
+ - { text: "Build social publishing into your application." }
44692
+ finalUrls: ["https://zernio.com"]
44693
+ cachedAt: null
44694
+ stale: false
44526
44695
  schema:
44527
44696
  type: object
44528
44697
  properties:
44529
44698
  ad: { $ref: '#/components/schemas/Ad' }
44699
+ cachedAt: { type: [string, "null"], format: date-time, description: "Google RSA details cache timestamp." }
44700
+ stale: { type: boolean, description: "Whether Google RSA details use the last successful cached response." }
44530
44701
  '400': { $ref: '#/components/responses/BadRequest' }
44531
44702
  '401': { $ref: '#/components/responses/Unauthorized' }
44532
44703
  '404': { $ref: '#/components/responses/NotFound' }
@@ -44549,7 +44720,11 @@ paths:
44549
44720
  Each list you send becomes the FULL new set of its kind (criteria not in the
44550
44721
  list are removed); a kind left out is untouched. Any other `targeting` field
44551
44722
  returns 400: Google cannot mutate broad targeting post-create without recreating
44552
- the campaign. `creative` returns 501.
44723
+ the campaign. RSA text updates use top-level `headlines`, `descriptions` and `finalUrls`.
44724
+ Each supplied array replaces the full list; omit a field to preserve it. Use 3-15 headlines
44725
+ (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it;
44726
+ omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text.
44727
+ The legacy creative fields remain unsupported for Google.
44553
44728
  - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries),
44554
44729
  the B2B facets, and audience segments; applied to the LinkedIn Campaign via
44555
44730
  PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge),
@@ -44592,9 +44767,51 @@ paths:
44592
44767
  required: true
44593
44768
  content:
44594
44769
  application/json:
44770
+ examples:
44771
+ googleRsa:
44772
+ summary: "Replace and pin Google RSA text."
44773
+ value:
44774
+ headlines:
44775
+ - text: Social Media API
44776
+ pinnedField: HEADLINE_1
44777
+ - text: Schedule Your Posts
44778
+ - text: Build With Zernio
44779
+ descriptions:
44780
+ - text: Connect social accounts and schedule posts with the Zernio API.
44781
+ pinnedField: DESCRIPTION_1
44782
+ - text: Build social publishing into your application.
44783
+ finalUrls:
44784
+ - https://zernio.com
44785
+ metaPromotion:
44786
+ summary: "Remove a Meta promotion."
44787
+ value:
44788
+ creative:
44789
+ promotion: null
44790
+ creativeFeatures: { auto_promotion_tag: OPT_OUT }
44595
44791
  schema:
44596
44792
  type: object
44597
44793
  properties:
44794
+ headlines:
44795
+ type: array
44796
+ minItems: 3
44797
+ maxItems: 15
44798
+ items:
44799
+ $ref: '#/components/schemas/GoogleRsaHeadline'
44800
+ description: "Google RSA only. Replaces the complete headline list. No padding or truncation on update."
44801
+ descriptions:
44802
+ type: array
44803
+ minItems: 2
44804
+ maxItems: 4
44805
+ items:
44806
+ $ref: '#/components/schemas/GoogleRsaDescription'
44807
+ description: "Google RSA only. Replaces the complete description list. No padding or truncation on update."
44808
+ finalUrls:
44809
+ type: array
44810
+ minItems: 1
44811
+ items:
44812
+ type: string
44813
+ format: uri
44814
+ description: "Google RSA only. Replaces final URLs. Omitted lists stay unchanged."
44598
44815
  status: { type: string, enum: [active, paused] }
44599
44816
  budget:
44600
44817
  type: object
@@ -44702,10 +44919,6 @@ paths:
44702
44919
  videoId: { type: string, description: "Meta only. Reuse an already-uploaded ad video (from POST /v1/ads/videos or GET /v1/ads/videos) instead of re-uploading via videoUrl." }
44703
44920
  existingCreativeId: { type: string, description: "Meta only. Repoint the ad at an existing library creative (from GET /v1/ads/creatives); all other creative fields are ignored." }
44704
44921
  name: { type: string, maxLength: 255, description: "Rename the ad. Now propagated to Meta (POST /{ad-id}); non-Meta platforms return 501." }
44705
- example:
44706
- creative:
44707
- promotion: null
44708
- creativeFeatures: { auto_promotion_tag: OPT_OUT }
44709
44922
  responses:
44710
44923
  '200':
44711
44924
  description: Ad updated
@@ -44796,322 +45009,977 @@ paths:
44796
45009
  '404': { description: Ad not found }
44797
45010
 
44798
45011
  /v1/ads/campaigns/{campaignId}/assets:
45012
+ get:
45013
+ operationId: listCampaignAssets
45014
+ summary: List campaign assets
45015
+ x-resource-group: ads
45016
+ tags:
45017
+ - Ad Campaigns
45018
+ x-platforms:
45019
+ - google
45020
+ description: "Lists directly attached Google assets. Fresh reads are cached for 10 minutes; exhausted quota\
45021
+ \ may return the last successful read with stale=true. Inherited assets are not included."
45022
+ security:
45023
+ - bearerAuth: []
45024
+ parameters:
45025
+ - name: campaignId
45026
+ in: path
45027
+ required: true
45028
+ schema:
45029
+ type: string
45030
+ pattern: ^\d+$
45031
+ description: "Numeric Google platform id."
45032
+ - name: accountId
45033
+ in: query
45034
+ required: true
45035
+ schema:
45036
+ type: string
45037
+ pattern: ^[a-fA-F0-9]{24}$
45038
+ description: "Zernio Google Ads connection id."
45039
+ - name: customerId
45040
+ in: query
45041
+ schema:
45042
+ type: string
45043
+ pattern: ^\d+$
45044
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
45045
+ responses:
45046
+ '200':
45047
+ description: "Assets returned."
45048
+ content:
45049
+ application/json:
45050
+ schema:
45051
+ type: object
45052
+ properties:
45053
+ campaignId:
45054
+ type: string
45055
+ sitelinks:
45056
+ type: array
45057
+ items:
45058
+ type: object
45059
+ properties:
45060
+ assetResourceName:
45061
+ type: string
45062
+ campaignAssetResourceName:
45063
+ type: string
45064
+ text:
45065
+ type: string
45066
+ linkUrl:
45067
+ type: string
45068
+ format: uri
45069
+ description1:
45070
+ type: string
45071
+ description2:
45072
+ type: string
45073
+ callouts:
45074
+ type: array
45075
+ items:
45076
+ type: object
45077
+ properties:
45078
+ assetResourceName:
45079
+ type: string
45080
+ campaignAssetResourceName:
45081
+ type: string
45082
+ calloutText:
45083
+ type: string
45084
+ structuredSnippets:
45085
+ type: array
45086
+ items:
45087
+ type: object
45088
+ properties:
45089
+ assetResourceName:
45090
+ type: string
45091
+ campaignAssetResourceName:
45092
+ type: string
45093
+ header:
45094
+ type: string
45095
+ values:
45096
+ type: array
45097
+ items:
45098
+ type: string
45099
+ cachedAt:
45100
+ type:
45101
+ - string
45102
+ - 'null'
45103
+ format: date-time
45104
+ description: "Time of the cached Google read. Null when no cache was used."
45105
+ stale:
45106
+ type: boolean
45107
+ description: "True when exhausted quota required returning the last successful read."
45108
+ '400':
45109
+ $ref: '#/components/responses/BadRequest'
45110
+ '401':
45111
+ $ref: '#/components/responses/Unauthorized'
45112
+ '403':
45113
+ description: "Ads access is required."
45114
+ '404':
45115
+ $ref: '#/components/responses/NotFound'
45116
+ '429':
45117
+ description: "Google Ads operations budget or platform quota exhausted."
45118
+ '501':
45119
+ description: "Only supported on Google Ads."
44799
45120
  post:
44800
- x-resource-group: "ads"
44801
45121
  operationId: attachCampaignAssets
44802
- tags: ["Ad Campaigns"]
44803
- x-platforms: ["google"]
44804
- summary: Attach extension assets to a Google Search campaign
44805
- description: |-
44806
- Attach sitelinks, callouts and/or structured snippets to an already-existing Google
44807
- Search campaign. These are the same builders POST /v1/ads/create uses, but without rebuilding
44808
- the hierarchy. At least one of sitelinks, callouts or structuredSnippets is required.
44809
-
44810
- Google-only. Other platforms have no equivalent extension surface and return 501.
44811
-
44812
- Approval status is Google-async; poll `asset.policy_summary` after review. Assets
44813
- stay in the account library even if the campaign is later deleted.
45122
+ summary: Attach campaign assets
45123
+ x-resource-group: ads
45124
+ tags:
45125
+ - Ad Campaigns
45126
+ x-platforms:
45127
+ - google
45128
+ description: "Creates and attaches sitelinks, callouts and structured snippets in one Google mutation."
44814
45129
  security:
44815
- - bearerAuth: []
45130
+ - bearerAuth: []
44816
45131
  parameters:
44817
- - { name: campaignId, in: path, required: true, schema: { type: string }, description: "Numeric Google platform campaign id." }
45132
+ - name: campaignId
45133
+ in: path
45134
+ required: true
45135
+ schema:
45136
+ type: string
45137
+ pattern: ^\d+$
45138
+ description: "Numeric Google platform id."
44818
45139
  requestBody:
44819
45140
  required: true
44820
45141
  content:
44821
45142
  application/json:
44822
45143
  schema:
44823
45144
  type: object
44824
- required: [accountId]
45145
+ required:
45146
+ - accountId
44825
45147
  properties:
44826
- accountId: { type: string, description: "Zernio Google Ads SocialAccount id. Resolves the customer id + refresh token." }
44827
- customerId: { type: string, description: "Numeric Google Ads customer id. Required when the connection has multiple Google Ads accounts; optional (and inferred) when it has only one." }
45148
+ accountId:
45149
+ type: string
45150
+ pattern: ^[a-fA-F0-9]{24}$
45151
+ description: "Zernio Google Ads connection id."
45152
+ customerId:
45153
+ type: string
45154
+ pattern: ^\d+$
45155
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
44828
45156
  sitelinks:
44829
45157
  type: array
45158
+ items:
45159
+ $ref: '#/components/schemas/GoogleSitelink'
44830
45160
  minItems: 2
44831
45161
  maxItems: 20
44832
- description: "See POST /v1/ads/create sitelinks, same shape."
44833
- items:
44834
- type: object
44835
- required: [text, linkUrl]
44836
- properties:
44837
- text: { type: string, minLength: 1, maxLength: 25 }
44838
- linkUrl: { type: string, format: uri }
44839
- description1: { type: string, minLength: 1, maxLength: 35 }
44840
- description2: { type: string, minLength: 1, maxLength: 35 }
44841
45162
  callouts:
44842
45163
  type: array
45164
+ items:
45165
+ type: string
45166
+ minLength: 1
45167
+ maxLength: 25
44843
45168
  minItems: 1
44844
45169
  maxItems: 20
44845
- items: { type: string, minLength: 1, maxLength: 25 }
44846
45170
  structuredSnippets:
44847
45171
  type: array
45172
+ items:
45173
+ $ref: '#/components/schemas/GoogleStructuredSnippet'
44848
45174
  minItems: 1
44849
45175
  maxItems: 20
44850
- items:
44851
- type: object
44852
- required: [header, values]
44853
- properties:
44854
- header:
44855
- type: string
44856
- enum: [Amenities, Brands, Courses, Degree programs, Destinations, Featured hotels, Insurance coverage, Models, Neighborhoods, Service catalog, Shows, Styles, Types]
44857
- values:
44858
- type: array
44859
- minItems: 3
44860
- maxItems: 10
44861
- items: { type: string, minLength: 1, maxLength: 25 }
45176
+ description: "Provide at least one of sitelinks, callouts or structuredSnippets. Sitelink description1\
45177
+ \ and description2 must be supplied together."
45178
+ example:
45179
+ accountId: 64b1f0c8a1b2c3d4e5f60718
45180
+ customerId: '1234567890'
45181
+ sitelinks:
45182
+ - text: Pricing
45183
+ linkUrl: https://zernio.com/pricing
45184
+ - text: Documentation
45185
+ linkUrl: https://zernio.com/docs
45186
+ callouts:
45187
+ - Fast setup
45188
+ structuredSnippets:
45189
+ - header: Types
45190
+ values:
45191
+ - Scheduling
45192
+ - Analytics
45193
+ - Messaging
44862
45194
  responses:
44863
45195
  '201':
44864
- description: Assets attached
45196
+ description: "Assets created and attached."
44865
45197
  content:
44866
45198
  application/json:
44867
45199
  schema:
44868
45200
  type: object
44869
45201
  properties:
44870
- campaignId: { type: string }
44871
- sitelinkAssetResourceNames: { type: array, items: { type: string } }
44872
- calloutAssetResourceNames: { type: array, items: { type: string } }
44873
- structuredSnippetAssetResourceNames: { type: array, items: { type: string } }
44874
- '400': { description: "Invalid input, Google rejected the assets, an unknown customerId (not one of this connection's Google Ads accounts), or a required customerId missing when the connection has multiple Google Ads accounts" }
44875
- '401': { $ref: '#/components/responses/Unauthorized' }
45202
+ campaignId:
45203
+ type: string
45204
+ sitelinkAssetResourceNames:
45205
+ type: array
45206
+ items:
45207
+ type: string
45208
+ calloutAssetResourceNames:
45209
+ type: array
45210
+ items:
45211
+ type: string
45212
+ structuredSnippetAssetResourceNames:
45213
+ type: array
45214
+ items:
45215
+ type: string
45216
+ '400':
45217
+ $ref: '#/components/responses/BadRequest'
45218
+ '401':
45219
+ $ref: '#/components/responses/Unauthorized'
44876
45220
  '403':
44877
- description: 'Returned with code `ads_allowance_exceeded` when the team has no payment method on file and has reached the 500 free live ads: add a card to resume.'
44878
- '422': { description: "No Google Ads customer accounts on this connection. Reconnect Google Ads." }
44879
- '501': { description: Only supported on Google Ads }
44880
-
44881
- /v1/ads/campaigns/{campaignId}/analytics:
44882
- get:
44883
- x-resource-group: "ads"
44884
- operationId: getCampaignAnalytics
44885
- tags: ["Ad Insights"]
44886
- x-platforms: ["meta", "google", "tiktok", "linkedin", "pinterest", "x"]
44887
- summary: Get campaign analytics
44888
- description: |
44889
- Returns performance analytics for a whole campaign in one call: summary metrics, a daily
44890
- timeline over the requested date range (summed across the campaign's ads), and optional
44891
- demographic breakdowns. Breakdowns are fetched live from Meta at the campaign level (one call
44892
- per dimension, no per-ad fan-out), so an agency dashboard gets campaign-level age/gender/etc.
44893
- without summing thousands of per-ad reads. `campaignId` is the platform campaign id; pass
44894
- `platform` when a campaign id could be ambiguous across platforms. If no date range is provided,
44895
- defaults to the last 90 days. Date range is capped at 730 days max.
44896
- Google adds searchImpressionShare, searchBudgetLostImpressionShare,
44897
- searchRankLostImpressionShare, searchTopImpressionShare and searchAbsoluteTopImpressionShare
44898
- under analytics.summary for the requested inclusive range. These ratios are queried
44899
- together without daily segmentation and cached for 10 minutes. Unavailable values are
44900
- null. analytics.impressionShareCache reports cachedAt and stale independently of synced metrics.
45221
+ description: "Ads access is required."
45222
+ '404':
45223
+ $ref: '#/components/responses/NotFound'
45224
+ '429':
45225
+ description: "Google Ads operations budget or platform quota exhausted."
45226
+ '501':
45227
+ description: "Only supported on Google Ads."
45228
+ put:
45229
+ operationId: updateCampaignAssets
45230
+ summary: Update campaign assets
45231
+ x-resource-group: ads
45232
+ tags:
45233
+ - Ad Campaigns
45234
+ x-platforms:
45235
+ - google
45236
+ description: "Edits existing Google assets in place. Send updates with assetResourceName and the fields to change.\
45237
+ \ An asset is shared: changes affect every attachment using it. Omitted fields stay unchanged. The operation\
45238
+ \ consumes the Google operations budget and invalidates affected cached lists."
44901
45239
  security:
44902
- - bearerAuth: []
45240
+ - bearerAuth: []
44903
45241
  parameters:
44904
- - { name: campaignId, in: path, required: true, schema: { type: string }, description: "Platform campaign id (platformCampaignId)." }
44905
- - { name: platform, in: query, schema: { type: string }, description: "Disambiguate when the campaign id exists across platforms (e.g. facebook, instagram)." }
44906
- - { name: fromDate, in: query, schema: { type: string, format: date }, description: "Start of date range (YYYY-MM-DD). Defaults to 90 days ago." }
44907
- - { name: toDate, in: query, schema: { type: string, format: date }, description: "End of date range (YYYY-MM-DD). Defaults to today. Max 730-day range." }
44908
- - name: breakdowns
44909
- in: query
44910
- schema: { type: string }
44911
- description: |
44912
- Comma-separated breakdown dimensions.
44913
-
44914
- **Meta**: age, gender, country, publisher_platform, device_platform, region,
44915
- platform_position, impression_device, video_asset, image_asset, body_asset, title_asset.
44916
-
44917
- **LinkedIn** (firmographics): job_title, job_function, seniority, industry,
44918
- company, company_size, country, region. Rows carry the raw pivot `value`
44919
- plus a resolved `name`. LinkedIn serves these aggregated over the whole
44920
- range, delays the data 12-24h, and omits segments with fewer than 3 events.
45242
+ - name: campaignId
45243
+ in: path
45244
+ required: true
45245
+ schema:
45246
+ type: string
45247
+ pattern: ^\d+$
45248
+ description: "Numeric Google platform id."
45249
+ requestBody:
45250
+ required: true
45251
+ content:
45252
+ application/json:
45253
+ schema:
45254
+ type: object
45255
+ required:
45256
+ - accountId
45257
+ - updates
45258
+ properties:
45259
+ accountId:
45260
+ type: string
45261
+ pattern: ^[a-fA-F0-9]{24}$
45262
+ description: "Zernio Google Ads connection id."
45263
+ customerId:
45264
+ type: string
45265
+ pattern: ^\d+$
45266
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
45267
+ updates:
45268
+ type: array
45269
+ items:
45270
+ $ref: '#/components/schemas/GoogleAssetUpdate'
45271
+ minItems: 1
45272
+ maxItems: 20
45273
+ example:
45274
+ accountId: 64b1f0c8a1b2c3d4e5f60718
45275
+ customerId: '1234567890'
45276
+ updates:
45277
+ - assetResourceName: customers/1234567890/assets/123
45278
+ calloutAsset:
45279
+ calloutText: Simple integration
44921
45280
  responses:
44922
45281
  '200':
44923
- description: Campaign analytics
44924
- content:
44925
- application/json:
44926
- schema: { $ref: '#/components/schemas/CampaignAnalyticsResponse' }
44927
- example:
44928
- campaign: { id: "123456789", platform: google }
44929
- analytics:
44930
- summary:
44931
- searchImpressionShare: 0.42
44932
- searchBudgetLostImpressionShare: 0.13
44933
- searchRankLostImpressionShare: 0.45
44934
- searchTopImpressionShare: 0.31
44935
- searchAbsoluteTopImpressionShare: null
44936
- impressionShareCache: { cachedAt: "2026-09-09T10:00:00Z", stale: false }
44937
- daily: []
44938
- '202':
44939
- description: Historical data is incomplete and backfill remains pending.
44940
- headers:
44941
- Retry-After:
44942
- $ref: '#/components/headers/BackfillRetryAfter'
45282
+ description: "Assets returned."
44943
45283
  content:
44944
45284
  application/json:
44945
45285
  schema:
44946
- allOf:
44947
- - { $ref: '#/components/schemas/CampaignAnalyticsResponse' }
44948
- - type: object
44949
- required: [backfillPending]
44950
- properties:
44951
- backfillPending: { type: boolean, description: 'Always true on this response. Part of the requested range is still being backfilled; retry until the request returns 200.' }
45286
+ type: object
45287
+ properties:
45288
+ updated:
45289
+ type: integer
44952
45290
  '400':
44953
- description: "Invalid parameter (e.g. an unknown `breakdowns` dimension). The message lists the offending value(s) and the supported set."
44954
- content:
44955
- application/json:
44956
- schema: { $ref: '#/components/schemas/ErrorResponse' }
44957
- '401': { $ref: '#/components/responses/Unauthorized' }
45291
+ $ref: '#/components/responses/BadRequest'
45292
+ '401':
45293
+ $ref: '#/components/responses/Unauthorized'
44958
45294
  '403':
44959
- description: Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
44960
- '404': { $ref: '#/components/responses/NotFound' }
44961
- '429': { description: "Google operations budget or quota exhausted without a cached impression-share result." }
44962
-
44963
- /v1/ads/preview:
44964
- post:
44965
- x-resource-group: "ads"
44966
- operationId: generateAdPreviews
44967
- tags: ["Ad Creatives"]
44968
- x-platforms: ["meta"]
44969
- summary: Render pre-create ad previews
44970
- description: |
44971
- Renders how a creative would look per placement BEFORE any ad exists, via Meta's
44972
- `/generatepreviews`. Provide exactly one creative source: `existingCreativeId` or `creativeSpec`.
44973
- Each preview is an HTML `<iframe>` snippet embeddable directly. Unknown `formats` values
44974
- return Meta's 400 verbatim.
45295
+ description: "Ads access is required."
45296
+ '404':
45297
+ $ref: '#/components/responses/NotFound'
45298
+ '429':
45299
+ description: "Google Ads operations budget or platform quota exhausted."
45300
+ '501':
45301
+ description: "Only supported on Google Ads."
45302
+ delete:
45303
+ operationId: removeCampaignAssets
45304
+ summary: Remove campaign assets
45305
+ x-resource-group: ads
45306
+ tags:
45307
+ - Ad Campaigns
45308
+ x-platforms:
45309
+ - google
45310
+ description: "Removes the specified attachments only. Google assets cannot be deleted. Other attachments remain. assetResourceNames is retained for compatibility."
44975
45311
  security:
44976
- - bearerAuth: []
45312
+ - bearerAuth: []
45313
+ parameters:
45314
+ - name: campaignId
45315
+ in: path
45316
+ required: true
45317
+ schema:
45318
+ type: string
45319
+ pattern: ^\d+$
45320
+ description: "Numeric Google platform id."
44977
45321
  requestBody:
44978
45322
  required: true
44979
45323
  content:
44980
45324
  application/json:
44981
45325
  schema:
44982
45326
  type: object
44983
- required: [accountId, adAccountId]
45327
+ required:
45328
+ - accountId
45329
+ - assetResourceNames
45330
+ - campaignAssetResourceNames
44984
45331
  properties:
44985
- accountId: { type: string, description: "Zernio SocialAccount id used to resolve the Meta token." }
44986
- adAccountId: { type: string, description: "Platform ad account id (Meta act_<n>, Google customer id, LinkedIn account id, ...)." }
44987
- formats:
45332
+ accountId:
45333
+ type: string
45334
+ pattern: ^[a-fA-F0-9]{24}$
45335
+ description: "Zernio Google Ads connection id."
45336
+ customerId:
45337
+ type: string
45338
+ pattern: ^\d+$
45339
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
45340
+ assetResourceNames:
44988
45341
  type: array
45342
+ items:
45343
+ type: string
44989
45344
  minItems: 1
44990
- maxItems: 10
44991
- items: { type: string }
44992
- description: "Meta ad_format values, one preview per format. Defaults to [DESKTOP_FEED_STANDARD]."
44993
- existingCreativeId: { type: string, description: "Preview an existing ad-account creative by id. Mutually exclusive with creativeSpec." }
44994
- creativeSpec:
44995
- type: object
44996
- additionalProperties: true
44997
- description: "Raw Meta creative spec forwarded verbatim to /generatepreviews. Mutually exclusive with existingCreativeId."
45345
+ campaignAssetResourceNames:
45346
+ type: array
45347
+ items:
45348
+ type: string
45349
+ minItems: 1
45350
+ example:
45351
+ accountId: 64b1f0c8a1b2c3d4e5f60718
45352
+ customerId: '1234567890'
45353
+ assetResourceNames:
45354
+ - customers/1234567890/assets/123
45355
+ campaignAssetResourceNames:
45356
+ - customers/1234567890/campaignAssets/456~123~CALLOUT
44998
45357
  responses:
44999
45358
  '200':
45000
- description: Rendered previews
45359
+ description: "Assets returned."
45001
45360
  content:
45002
45361
  application/json:
45003
45362
  schema:
45004
45363
  type: object
45005
45364
  properties:
45006
- previews:
45007
- type: array
45008
- items:
45009
- type: object
45010
- properties:
45011
- format: { type: string }
45012
- html: { type: [string, "null"], description: "Meta's <iframe> snippet; null when Meta returned no preview for the format." }
45013
- '400': { description: "Invalid input, or Meta rejected the creative spec / ad_format; the message carries Meta's error" }
45014
- '401': { $ref: '#/components/responses/Unauthorized' }
45015
- '429': { description: Meta rate limit reached }
45016
- '501': { description: Only supported on Meta (facebook/instagram) }
45365
+ removed:
45366
+ type: boolean
45367
+ '400':
45368
+ $ref: '#/components/responses/BadRequest'
45369
+ '401':
45370
+ $ref: '#/components/responses/Unauthorized'
45371
+ '403':
45372
+ description: "Ads access is required."
45373
+ '404':
45374
+ $ref: '#/components/responses/NotFound'
45375
+ '429':
45376
+ description: "Google Ads operations budget or platform quota exhausted."
45377
+ '501':
45378
+ description: "Only supported on Google Ads."
45017
45379
 
45018
- /v1/ads/{adId}/preview:
45380
+ /v1/ads/ad-sets/{adSetId}/assets:
45019
45381
  get:
45020
- x-resource-group: "ads"
45021
- operationId: getAdPreviews
45022
- tags: ["Ad Creatives"]
45023
- x-platforms: ["meta"]
45024
- summary: Render previews of an existing ad
45025
- description: |
45026
- Renders an EXISTING ad per placement via Meta's `/{ad_id}/previews`. Each preview is an HTML
45027
- `<iframe>` snippet embeddable directly. Unknown `formats` values return Meta's 400 verbatim.
45382
+ operationId: listAdGroupAssets
45383
+ summary: List ad-group assets
45384
+ x-resource-group: ads
45385
+ tags:
45386
+ - Ad Campaigns
45387
+ x-platforms:
45388
+ - google
45389
+ description: "Lists directly attached Google assets. Fresh reads are cached for 10 minutes; exhausted quota\
45390
+ \ may return the last successful read with stale=true. Inherited assets are not included."
45028
45391
  security:
45029
- - bearerAuth: []
45392
+ - bearerAuth: []
45030
45393
  parameters:
45031
- - { name: adId, in: path, required: true, schema: { type: string }, description: "Zernio ad id (24-char hex)." }
45032
- - { name: formats, in: query, schema: { type: string }, description: "Comma-separated Meta ad_format values (max 10), one preview per format. Defaults to DESKTOP_FEED_STANDARD." }
45394
+ - name: adSetId
45395
+ in: path
45396
+ required: true
45397
+ schema:
45398
+ type: string
45399
+ pattern: ^\d+$
45400
+ description: "Numeric Google platform id."
45401
+ - name: accountId
45402
+ in: query
45403
+ required: true
45404
+ schema:
45405
+ type: string
45406
+ pattern: ^[a-fA-F0-9]{24}$
45407
+ description: "Zernio Google Ads connection id."
45408
+ - name: customerId
45409
+ in: query
45410
+ schema:
45411
+ type: string
45412
+ pattern: ^\d+$
45413
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
45033
45414
  responses:
45034
45415
  '200':
45035
- description: Rendered previews
45416
+ description: "Assets returned."
45036
45417
  content:
45037
45418
  application/json:
45038
45419
  schema:
45039
45420
  type: object
45040
45421
  properties:
45041
- adId: { type: string }
45042
- previews:
45422
+ adGroupId:
45423
+ type: string
45424
+ sitelinks:
45043
45425
  type: array
45044
45426
  items:
45045
45427
  type: object
45046
45428
  properties:
45047
- format: { type: string }
45048
- html: { type: [string, "null"], description: "Meta's <iframe> snippet; null when Meta returned no preview for the format." }
45049
- '400': { description: "Invalid input, or Meta rejected the ad_format; the message carries Meta's error" }
45050
- '401': { $ref: '#/components/responses/Unauthorized' }
45051
- '404': { description: Ad not found }
45052
- '429': { description: Meta rate limit reached }
45053
- '501': { description: Only supported on Meta (facebook/instagram) }
45054
-
45055
- /v1/ads/{adId}/media:
45056
- get:
45057
- x-resource-group: "ads"
45058
- operationId: getAdMedia
45059
- tags: ["Ad Creatives"]
45060
- x-platforms: ["meta"]
45061
- summary: Direct video and image URLs for an ad
45062
- description: |-
45063
- Returns the direct signed URLs for every video and image asset used by an ad's live
45064
- creative, normalised across shapes: single image/video, carousel,
45065
- Reels/Story (`object_story_spec.video_data`) and dynamic
45066
- creative (`asset_feed_spec`). Video items include Meta's poster thumbnail and the
45067
- video's Meta id when available.
45068
-
45069
- Reads Meta live rather than the stored creative blob because Meta's signed fbcdn
45070
- URLs carry an `oe=<hex>` expiration (image_url ~24 h, video source ~12 d). Treat
45071
- URLs as short-lived: re-fetch this endpoint before serving or downloading assets
45072
- instead of caching URLs beyond that window.
45073
- security:
45074
- - bearerAuth: []
45075
- parameters:
45076
- - { name: adId, in: path, required: true, schema: { type: string }, description: "Zernio ad id (24-char hex) or platform ad id." }
45077
- responses:
45078
- '200':
45079
- description: Media assets
45080
- content:
45081
- application/json:
45082
- schema:
45083
- type: object
45084
- properties:
45085
- adId: { type: string }
45086
- platform: { type: string, description: "'facebook' or 'instagram'. Only Meta is supported for now." }
45087
- media:
45429
+ assetResourceName:
45430
+ type: string
45431
+ adGroupAssetResourceName:
45432
+ type: string
45433
+ text:
45434
+ type: string
45435
+ linkUrl:
45436
+ type: string
45437
+ format: uri
45438
+ description1:
45439
+ type: string
45440
+ description2:
45441
+ type: string
45442
+ callouts:
45088
45443
  type: array
45089
45444
  items:
45090
45445
  type: object
45091
45446
  properties:
45092
- type: { type: string, enum: [image, video] }
45093
- url: { type: string, description: "Direct file URL (signed; short-lived, see description)." }
45094
- thumbnailUrl: { type: string, description: "Video poster URL (videos only)." }
45095
- videoId: { type: string, description: "Meta video id (videos only), reusable as video.id on the create endpoints." }
45096
- length: { type: number, description: "Video length in seconds (videos only)." }
45097
- index: { type: integer, description: "0-based position for carousel children or asset_feed_spec entries." }
45098
- '400': { description: "Invalid input" }
45099
- '401': { $ref: '#/components/responses/Unauthorized' }
45100
- '404': { description: Ad not found }
45101
- '422': { description: No active Meta connection for this ad. Reconnect the account. }
45102
- '501': { description: Only supported on Meta (facebook/instagram) }
45103
-
45104
- /v1/ads/keywords/ideas:
45447
+ assetResourceName:
45448
+ type: string
45449
+ adGroupAssetResourceName:
45450
+ type: string
45451
+ calloutText:
45452
+ type: string
45453
+ structuredSnippets:
45454
+ type: array
45455
+ items:
45456
+ type: object
45457
+ properties:
45458
+ assetResourceName:
45459
+ type: string
45460
+ adGroupAssetResourceName:
45461
+ type: string
45462
+ header:
45463
+ type: string
45464
+ values:
45465
+ type: array
45466
+ items:
45467
+ type: string
45468
+ cachedAt:
45469
+ type:
45470
+ - string
45471
+ - 'null'
45472
+ format: date-time
45473
+ description: "Time of the cached Google read. Null when no cache was used."
45474
+ stale:
45475
+ type: boolean
45476
+ description: "True when exhausted quota required returning the last successful read."
45477
+ '400':
45478
+ $ref: '#/components/responses/BadRequest'
45479
+ '401':
45480
+ $ref: '#/components/responses/Unauthorized'
45481
+ '403':
45482
+ description: "Ads access is required."
45483
+ '404':
45484
+ $ref: '#/components/responses/NotFound'
45485
+ '429':
45486
+ description: "Google Ads operations budget or platform quota exhausted."
45487
+ '501':
45488
+ description: "Only supported on Google Ads."
45105
45489
  post:
45106
- x-resource-group: "ads"
45107
- operationId: generateKeywordIdeas
45108
- tags: ["Ad Insights"]
45109
- x-platforms: ["google"]
45110
- summary: Generate keyword ideas (Google Keyword Planner)
45111
- description: |
45112
- Google Ads only. Runs Keyword Planner's generateKeywordIdeas from seed keywords, a seed URL,
45113
- or both, returning idea rows verbatim (avgMonthlySearches, competition, competitionIndex,
45114
- top-of-page bid micros, monthlySearchVolumes). Counters are int64s encoded as strings; bid
45490
+ operationId: attachAdGroupAssets
45491
+ summary: Attach ad-group assets
45492
+ x-resource-group: ads
45493
+ tags:
45494
+ - Ad Campaigns
45495
+ x-platforms:
45496
+ - google
45497
+ description: "Creates and attaches sitelinks, callouts and structured snippets in one Google mutation."
45498
+ security:
45499
+ - bearerAuth: []
45500
+ parameters:
45501
+ - name: adSetId
45502
+ in: path
45503
+ required: true
45504
+ schema:
45505
+ type: string
45506
+ pattern: ^\d+$
45507
+ description: "Numeric Google platform id."
45508
+ requestBody:
45509
+ required: true
45510
+ content:
45511
+ application/json:
45512
+ schema:
45513
+ type: object
45514
+ required:
45515
+ - accountId
45516
+ properties:
45517
+ accountId:
45518
+ type: string
45519
+ pattern: ^[a-fA-F0-9]{24}$
45520
+ description: "Zernio Google Ads connection id."
45521
+ customerId:
45522
+ type: string
45523
+ pattern: ^\d+$
45524
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
45525
+ sitelinks:
45526
+ type: array
45527
+ items:
45528
+ $ref: '#/components/schemas/GoogleSitelink'
45529
+ minItems: 2
45530
+ maxItems: 20
45531
+ callouts:
45532
+ type: array
45533
+ items:
45534
+ type: string
45535
+ minLength: 1
45536
+ maxLength: 25
45537
+ minItems: 1
45538
+ maxItems: 20
45539
+ structuredSnippets:
45540
+ type: array
45541
+ items:
45542
+ $ref: '#/components/schemas/GoogleStructuredSnippet'
45543
+ minItems: 1
45544
+ maxItems: 20
45545
+ description: "Provide at least one of sitelinks, callouts or structuredSnippets. Sitelink description1\
45546
+ \ and description2 must be supplied together."
45547
+ example:
45548
+ accountId: 64b1f0c8a1b2c3d4e5f60718
45549
+ customerId: '1234567890'
45550
+ sitelinks:
45551
+ - text: Pricing
45552
+ linkUrl: https://zernio.com/pricing
45553
+ - text: Documentation
45554
+ linkUrl: https://zernio.com/docs
45555
+ callouts:
45556
+ - Fast setup
45557
+ structuredSnippets:
45558
+ - header: Types
45559
+ values:
45560
+ - Scheduling
45561
+ - Analytics
45562
+ - Messaging
45563
+ responses:
45564
+ '201':
45565
+ description: "Assets created and attached."
45566
+ content:
45567
+ application/json:
45568
+ schema:
45569
+ type: object
45570
+ properties:
45571
+ adGroupId:
45572
+ type: string
45573
+ sitelinkAssetResourceNames:
45574
+ type: array
45575
+ items:
45576
+ type: string
45577
+ calloutAssetResourceNames:
45578
+ type: array
45579
+ items:
45580
+ type: string
45581
+ structuredSnippetAssetResourceNames:
45582
+ type: array
45583
+ items:
45584
+ type: string
45585
+ '400':
45586
+ $ref: '#/components/responses/BadRequest'
45587
+ '401':
45588
+ $ref: '#/components/responses/Unauthorized'
45589
+ '403':
45590
+ description: "Ads access is required."
45591
+ '404':
45592
+ $ref: '#/components/responses/NotFound'
45593
+ '429':
45594
+ description: "Google Ads operations budget or platform quota exhausted."
45595
+ '501':
45596
+ description: "Only supported on Google Ads."
45597
+ put:
45598
+ operationId: updateAdGroupAssets
45599
+ summary: Update ad-group assets
45600
+ x-resource-group: ads
45601
+ tags:
45602
+ - Ad Campaigns
45603
+ x-platforms:
45604
+ - google
45605
+ description: "Edits existing Google assets in place. Send updates with assetResourceName and the fields to change.\
45606
+ \ An asset is shared: changes affect every attachment using it. Omitted fields stay unchanged. The operation\
45607
+ \ consumes the Google operations budget and invalidates affected cached lists."
45608
+ security:
45609
+ - bearerAuth: []
45610
+ parameters:
45611
+ - name: adSetId
45612
+ in: path
45613
+ required: true
45614
+ schema:
45615
+ type: string
45616
+ pattern: ^\d+$
45617
+ description: "Numeric Google platform id."
45618
+ requestBody:
45619
+ required: true
45620
+ content:
45621
+ application/json:
45622
+ schema:
45623
+ type: object
45624
+ required:
45625
+ - accountId
45626
+ - updates
45627
+ properties:
45628
+ accountId:
45629
+ type: string
45630
+ pattern: ^[a-fA-F0-9]{24}$
45631
+ description: "Zernio Google Ads connection id."
45632
+ customerId:
45633
+ type: string
45634
+ pattern: ^\d+$
45635
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
45636
+ updates:
45637
+ type: array
45638
+ items:
45639
+ $ref: '#/components/schemas/GoogleAssetUpdate'
45640
+ minItems: 1
45641
+ maxItems: 20
45642
+ example:
45643
+ accountId: 64b1f0c8a1b2c3d4e5f60718
45644
+ customerId: '1234567890'
45645
+ updates:
45646
+ - assetResourceName: customers/1234567890/assets/123
45647
+ calloutAsset:
45648
+ calloutText: Simple integration
45649
+ responses:
45650
+ '200':
45651
+ description: "Assets returned."
45652
+ content:
45653
+ application/json:
45654
+ schema:
45655
+ type: object
45656
+ properties:
45657
+ updated:
45658
+ type: integer
45659
+ '400':
45660
+ $ref: '#/components/responses/BadRequest'
45661
+ '401':
45662
+ $ref: '#/components/responses/Unauthorized'
45663
+ '403':
45664
+ description: "Ads access is required."
45665
+ '404':
45666
+ $ref: '#/components/responses/NotFound'
45667
+ '429':
45668
+ description: "Google Ads operations budget or platform quota exhausted."
45669
+ '501':
45670
+ description: "Only supported on Google Ads."
45671
+ delete:
45672
+ operationId: removeAdGroupAssets
45673
+ summary: Remove ad-group assets
45674
+ x-resource-group: ads
45675
+ tags:
45676
+ - Ad Campaigns
45677
+ x-platforms:
45678
+ - google
45679
+ description: "Removes the specified attachments only. Google assets cannot be deleted. Other attachments remain. assetResourceNames is retained for compatibility."
45680
+ security:
45681
+ - bearerAuth: []
45682
+ parameters:
45683
+ - name: adSetId
45684
+ in: path
45685
+ required: true
45686
+ schema:
45687
+ type: string
45688
+ pattern: ^\d+$
45689
+ description: "Numeric Google platform id."
45690
+ requestBody:
45691
+ required: true
45692
+ content:
45693
+ application/json:
45694
+ schema:
45695
+ type: object
45696
+ required:
45697
+ - accountId
45698
+ - assetResourceNames
45699
+ - adGroupAssetResourceNames
45700
+ properties:
45701
+ accountId:
45702
+ type: string
45703
+ pattern: ^[a-fA-F0-9]{24}$
45704
+ description: "Zernio Google Ads connection id."
45705
+ customerId:
45706
+ type: string
45707
+ pattern: ^\d+$
45708
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
45709
+ assetResourceNames:
45710
+ type: array
45711
+ items:
45712
+ type: string
45713
+ minItems: 1
45714
+ adGroupAssetResourceNames:
45715
+ type: array
45716
+ items:
45717
+ type: string
45718
+ minItems: 1
45719
+ example:
45720
+ accountId: 64b1f0c8a1b2c3d4e5f60718
45721
+ customerId: '1234567890'
45722
+ assetResourceNames:
45723
+ - customers/1234567890/assets/123
45724
+ adGroupAssetResourceNames:
45725
+ - customers/1234567890/adGroupAssets/456~123~CALLOUT
45726
+ responses:
45727
+ '200':
45728
+ description: "Assets returned."
45729
+ content:
45730
+ application/json:
45731
+ schema:
45732
+ type: object
45733
+ properties:
45734
+ removed:
45735
+ type: boolean
45736
+ '400':
45737
+ $ref: '#/components/responses/BadRequest'
45738
+ '401':
45739
+ $ref: '#/components/responses/Unauthorized'
45740
+ '403':
45741
+ description: "Ads access is required."
45742
+ '404':
45743
+ $ref: '#/components/responses/NotFound'
45744
+ '429':
45745
+ description: "Google Ads operations budget or platform quota exhausted."
45746
+ '501':
45747
+ description: "Only supported on Google Ads."
45748
+
45749
+ /v1/ads/campaigns/{campaignId}/analytics:
45750
+ get:
45751
+ x-resource-group: "ads"
45752
+ operationId: getCampaignAnalytics
45753
+ tags: ["Ad Insights"]
45754
+ x-platforms: ["meta", "google", "tiktok", "linkedin", "pinterest", "x"]
45755
+ summary: Get campaign analytics
45756
+ description: |
45757
+ Returns performance analytics for a whole campaign in one call: summary metrics, a daily
45758
+ timeline over the requested date range (summed across the campaign's ads), and optional
45759
+ demographic breakdowns. Breakdowns are fetched live from Meta at the campaign level (one call
45760
+ per dimension, no per-ad fan-out), so an agency dashboard gets campaign-level age/gender/etc.
45761
+ without summing thousands of per-ad reads. `campaignId` is the platform campaign id; pass
45762
+ `platform` when a campaign id could be ambiguous across platforms. If no date range is provided,
45763
+ defaults to the last 90 days. Date range is capped at 730 days max.
45764
+ Google adds searchImpressionShare, searchBudgetLostImpressionShare,
45765
+ searchRankLostImpressionShare, searchTopImpressionShare and searchAbsoluteTopImpressionShare
45766
+ under analytics.summary for the requested inclusive range. These ratios are queried
45767
+ together without daily segmentation and cached for 10 minutes. Unavailable values are
45768
+ null. analytics.impressionShareCache reports cachedAt and stale independently of synced metrics.
45769
+ security:
45770
+ - bearerAuth: []
45771
+ parameters:
45772
+ - { name: campaignId, in: path, required: true, schema: { type: string }, description: "Platform campaign id (platformCampaignId)." }
45773
+ - { name: platform, in: query, schema: { type: string }, description: "Disambiguate when the campaign id exists across platforms (e.g. facebook, instagram)." }
45774
+ - { name: fromDate, in: query, schema: { type: string, format: date }, description: "Start of date range (YYYY-MM-DD). Defaults to 90 days ago." }
45775
+ - { name: toDate, in: query, schema: { type: string, format: date }, description: "End of date range (YYYY-MM-DD). Defaults to today. Max 730-day range." }
45776
+ - name: breakdowns
45777
+ in: query
45778
+ schema: { type: string }
45779
+ description: |
45780
+ Comma-separated breakdown dimensions.
45781
+
45782
+ **Meta**: age, gender, country, publisher_platform, device_platform, region,
45783
+ platform_position, impression_device, video_asset, image_asset, body_asset, title_asset.
45784
+
45785
+ **LinkedIn** (firmographics): job_title, job_function, seniority, industry,
45786
+ company, company_size, country, region. Rows carry the raw pivot `value`
45787
+ plus a resolved `name`. LinkedIn serves these aggregated over the whole
45788
+ range, delays the data 12-24h, and omits segments with fewer than 3 events.
45789
+ responses:
45790
+ '200':
45791
+ description: Campaign analytics
45792
+ content:
45793
+ application/json:
45794
+ schema: { $ref: '#/components/schemas/CampaignAnalyticsResponse' }
45795
+ example:
45796
+ campaign: { id: "123456789", platform: google }
45797
+ analytics:
45798
+ summary:
45799
+ searchImpressionShare: 0.42
45800
+ searchBudgetLostImpressionShare: 0.13
45801
+ searchRankLostImpressionShare: 0.45
45802
+ searchTopImpressionShare: 0.31
45803
+ searchAbsoluteTopImpressionShare: null
45804
+ impressionShareCache: { cachedAt: "2026-09-09T10:00:00Z", stale: false }
45805
+ daily: []
45806
+ '202':
45807
+ description: Historical data is incomplete and backfill remains pending.
45808
+ headers:
45809
+ Retry-After:
45810
+ $ref: '#/components/headers/BackfillRetryAfter'
45811
+ content:
45812
+ application/json:
45813
+ schema:
45814
+ allOf:
45815
+ - { $ref: '#/components/schemas/CampaignAnalyticsResponse' }
45816
+ - type: object
45817
+ required: [backfillPending]
45818
+ properties:
45819
+ backfillPending: { type: boolean, description: 'Always true on this response. Part of the requested range is still being backfilled; retry until the request returns 200.' }
45820
+ '400':
45821
+ description: "Invalid parameter (e.g. an unknown `breakdowns` dimension). The message lists the offending value(s) and the supported set."
45822
+ content:
45823
+ application/json:
45824
+ schema: { $ref: '#/components/schemas/ErrorResponse' }
45825
+ '401': { $ref: '#/components/responses/Unauthorized' }
45826
+ '403':
45827
+ description: Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
45828
+ '404': { $ref: '#/components/responses/NotFound' }
45829
+ '429': { description: "Google operations budget or quota exhausted without a cached impression-share result." }
45830
+
45831
+ /v1/ads/preview:
45832
+ post:
45833
+ x-resource-group: "ads"
45834
+ operationId: generateAdPreviews
45835
+ tags: ["Ad Creatives"]
45836
+ x-platforms: ["meta"]
45837
+ summary: Render pre-create ad previews
45838
+ description: |
45839
+ Renders how a creative would look per placement BEFORE any ad exists, via Meta's
45840
+ `/generatepreviews`. Provide exactly one creative source: `existingCreativeId` or `creativeSpec`.
45841
+ Each preview is an HTML `<iframe>` snippet embeddable directly. Unknown `formats` values
45842
+ return Meta's 400 verbatim.
45843
+ security:
45844
+ - bearerAuth: []
45845
+ requestBody:
45846
+ required: true
45847
+ content:
45848
+ application/json:
45849
+ schema:
45850
+ type: object
45851
+ required: [accountId, adAccountId]
45852
+ properties:
45853
+ accountId: { type: string, description: "Zernio SocialAccount id used to resolve the Meta token." }
45854
+ adAccountId: { type: string, description: "Platform ad account id (Meta act_<n>, Google customer id, LinkedIn account id, ...)." }
45855
+ formats:
45856
+ type: array
45857
+ minItems: 1
45858
+ maxItems: 10
45859
+ items: { type: string }
45860
+ description: "Meta ad_format values, one preview per format. Defaults to [DESKTOP_FEED_STANDARD]."
45861
+ existingCreativeId: { type: string, description: "Preview an existing ad-account creative by id. Mutually exclusive with creativeSpec." }
45862
+ creativeSpec:
45863
+ type: object
45864
+ additionalProperties: true
45865
+ description: "Raw Meta creative spec forwarded verbatim to /generatepreviews. Mutually exclusive with existingCreativeId."
45866
+ responses:
45867
+ '200':
45868
+ description: Rendered previews
45869
+ content:
45870
+ application/json:
45871
+ schema:
45872
+ type: object
45873
+ properties:
45874
+ previews:
45875
+ type: array
45876
+ items:
45877
+ type: object
45878
+ properties:
45879
+ format: { type: string }
45880
+ html: { type: [string, "null"], description: "Meta's <iframe> snippet; null when Meta returned no preview for the format." }
45881
+ '400': { description: "Invalid input, or Meta rejected the creative spec / ad_format; the message carries Meta's error" }
45882
+ '401': { $ref: '#/components/responses/Unauthorized' }
45883
+ '429': { description: Meta rate limit reached }
45884
+ '501': { description: Only supported on Meta (facebook/instagram) }
45885
+
45886
+ /v1/ads/{adId}/preview:
45887
+ get:
45888
+ x-resource-group: "ads"
45889
+ operationId: getAdPreviews
45890
+ tags: ["Ad Creatives"]
45891
+ x-platforms: ["meta"]
45892
+ summary: Render previews of an existing ad
45893
+ description: |
45894
+ Renders an EXISTING ad per placement via Meta's `/{ad_id}/previews`. Each preview is an HTML
45895
+ `<iframe>` snippet embeddable directly. Unknown `formats` values return Meta's 400 verbatim.
45896
+ security:
45897
+ - bearerAuth: []
45898
+ parameters:
45899
+ - { name: adId, in: path, required: true, schema: { type: string }, description: "Zernio ad id (24-char hex)." }
45900
+ - { name: formats, in: query, schema: { type: string }, description: "Comma-separated Meta ad_format values (max 10), one preview per format. Defaults to DESKTOP_FEED_STANDARD." }
45901
+ responses:
45902
+ '200':
45903
+ description: Rendered previews
45904
+ content:
45905
+ application/json:
45906
+ schema:
45907
+ type: object
45908
+ properties:
45909
+ adId: { type: string }
45910
+ previews:
45911
+ type: array
45912
+ items:
45913
+ type: object
45914
+ properties:
45915
+ format: { type: string }
45916
+ html: { type: [string, "null"], description: "Meta's <iframe> snippet; null when Meta returned no preview for the format." }
45917
+ '400': { description: "Invalid input, or Meta rejected the ad_format; the message carries Meta's error" }
45918
+ '401': { $ref: '#/components/responses/Unauthorized' }
45919
+ '404': { description: Ad not found }
45920
+ '429': { description: Meta rate limit reached }
45921
+ '501': { description: Only supported on Meta (facebook/instagram) }
45922
+
45923
+ /v1/ads/{adId}/media:
45924
+ get:
45925
+ x-resource-group: "ads"
45926
+ operationId: getAdMedia
45927
+ tags: ["Ad Creatives"]
45928
+ x-platforms: ["meta"]
45929
+ summary: Direct video and image URLs for an ad
45930
+ description: |-
45931
+ Returns the direct signed URLs for every video and image asset used by an ad's live
45932
+ creative, normalised across shapes: single image/video, carousel,
45933
+ Reels/Story (`object_story_spec.video_data`) and dynamic
45934
+ creative (`asset_feed_spec`). Video items include Meta's poster thumbnail and the
45935
+ video's Meta id when available.
45936
+
45937
+ Reads Meta live rather than the stored creative blob because Meta's signed fbcdn
45938
+ URLs carry an `oe=<hex>` expiration (image_url ~24 h, video source ~12 d). Treat
45939
+ URLs as short-lived: re-fetch this endpoint before serving or downloading assets
45940
+ instead of caching URLs beyond that window.
45941
+ security:
45942
+ - bearerAuth: []
45943
+ parameters:
45944
+ - { name: adId, in: path, required: true, schema: { type: string }, description: "Zernio ad id (24-char hex) or platform ad id." }
45945
+ responses:
45946
+ '200':
45947
+ description: Media assets
45948
+ content:
45949
+ application/json:
45950
+ schema:
45951
+ type: object
45952
+ properties:
45953
+ adId: { type: string }
45954
+ platform: { type: string, description: "'facebook' or 'instagram'. Only Meta is supported for now." }
45955
+ media:
45956
+ type: array
45957
+ items:
45958
+ type: object
45959
+ properties:
45960
+ type: { type: string, enum: [image, video] }
45961
+ url: { type: string, description: "Direct file URL (signed; short-lived, see description)." }
45962
+ thumbnailUrl: { type: string, description: "Video poster URL (videos only)." }
45963
+ videoId: { type: string, description: "Meta video id (videos only), reusable as video.id on the create endpoints." }
45964
+ length: { type: number, description: "Video length in seconds (videos only)." }
45965
+ index: { type: integer, description: "0-based position for carousel children or asset_feed_spec entries." }
45966
+ '400': { description: "Invalid input" }
45967
+ '401': { $ref: '#/components/responses/Unauthorized' }
45968
+ '404': { description: Ad not found }
45969
+ '422': { description: No active Meta connection for this ad. Reconnect the account. }
45970
+ '501': { description: Only supported on Meta (facebook/instagram) }
45971
+
45972
+ /v1/ads/keywords/ideas:
45973
+ post:
45974
+ x-resource-group: "ads"
45975
+ operationId: generateKeywordIdeas
45976
+ tags: ["Ad Insights"]
45977
+ x-platforms: ["google"]
45978
+ summary: Generate keyword ideas (Google Keyword Planner)
45979
+ description: |
45980
+ Google Ads only. Runs Keyword Planner's generateKeywordIdeas from seed keywords, a seed URL,
45981
+ or both, returning idea rows verbatim (avgMonthlySearches, competition, competitionIndex,
45982
+ top-of-page bid micros, monthlySearchVolumes). Counters are int64s encoded as strings; bid
45115
45983
  values are micros of the account currency. Omitting `countries` targets worldwide.
45116
45984
  security:
45117
45985
  - bearerAuth: []
@@ -47671,141 +48539,943 @@ paths:
47671
48539
 
47672
48540
  /v1/ads/accounts/callouts:
47673
48541
  get:
47674
- x-resource-group: "ads"
47675
48542
  operationId: listAccountCallouts
47676
- tags: ["Ad Accounts"]
47677
- x-platforms: ["google"]
47678
- summary: List account-level callout extensions
47679
- description: |-
47680
- Google Ads compliance row C.75: callout assets linked at the CUSTOMER
47681
- level via `customer_asset` (not a campaign or ad group), so they serve
47682
- fleet-wide across the account. Google only; every other platform
47683
- returns 501. Cached for the quota window (10 minutes fresh, up to 7
47684
- days last-good), and gated by the shared Google Ads operations budget
47685
- on a cache miss. The response carries `cachedAt` and `stale`, set when
47686
- a quota-exhausted call falls back to the last-good copy instead of a
47687
- live read.
48543
+ summary: List account callouts
48544
+ x-resource-group: ads
48545
+ tags:
48546
+ - Ad Accounts
48547
+ x-platforms:
48548
+ - google
48549
+ description: "Lists directly attached Google assets. Fresh reads are cached for 10 minutes; exhausted quota\
48550
+ \ may return the last successful read with stale=true. Inherited assets are not included. Preserves Google\
48551
+ \ RMF C.75 account-level callouts."
47688
48552
  security:
47689
- - bearerAuth: []
48553
+ - bearerAuth: []
47690
48554
  parameters:
47691
- - { name: accountId, in: query, required: true, schema: { type: string }, description: "Google ads SocialAccount id." }
47692
- - { name: customerId, in: query, schema: { type: string }, description: "Numeric Google Ads customer id (no dashes). Defaults to the account's connected customer." }
48555
+ - name: accountId
48556
+ in: query
48557
+ required: true
48558
+ schema:
48559
+ type: string
48560
+ pattern: ^[a-fA-F0-9]{24}$
48561
+ description: "Zernio Google Ads connection id."
48562
+ - name: customerId
48563
+ in: query
48564
+ schema:
48565
+ type: string
48566
+ pattern: ^\d+$
48567
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
47693
48568
  responses:
47694
48569
  '200':
47695
- description: Account-level callouts
48570
+ description: "Assets returned."
47696
48571
  content:
47697
48572
  application/json:
47698
48573
  schema:
47699
48574
  type: object
47700
48575
  properties:
47701
- customerId: { type: string }
48576
+ customerId:
48577
+ type: string
47702
48578
  callouts:
47703
48579
  type: array
47704
48580
  items:
47705
48581
  type: object
47706
48582
  properties:
47707
- assetId: { type: string }
47708
- text: { type: string }
47709
- status: { type: string, description: "customer_asset.status, e.g. ENABLED, REMOVED, PAUSED." }
47710
- cachedAt: { type: [string, "null"], format: date-time, description: "When this list was fetched from Google. Null when it was never served from cache." }
47711
- stale: { type: boolean, description: "True when Google's daily API quota was exhausted and this is the last successful fetch, not a live read." }
47712
- '400': { $ref: '#/components/responses/BadRequest' }
47713
- '401': { $ref: '#/components/responses/Unauthorized' }
48583
+ assetId:
48584
+ type: string
48585
+ status:
48586
+ type: string
48587
+ text:
48588
+ type: string
48589
+ cachedAt:
48590
+ type:
48591
+ - string
48592
+ - 'null'
48593
+ format: date-time
48594
+ description: "Time of the cached Google read. Null when no cache was used."
48595
+ stale:
48596
+ type: boolean
48597
+ description: "True when exhausted quota required returning the last successful read."
48598
+ '400':
48599
+ $ref: '#/components/responses/BadRequest'
48600
+ '401':
48601
+ $ref: '#/components/responses/Unauthorized'
47714
48602
  '403':
47715
- description: Ads access required (Ads add-on on legacy plans, included on usage-based plans).
47716
- '404': { $ref: '#/components/responses/NotFound' }
47717
- '429': { description: Google Ads operations budget exhausted; retry later }
47718
- '501': { description: Only available on Google Ads accounts }
47719
-
48603
+ description: "Ads access is required."
48604
+ '404':
48605
+ $ref: '#/components/responses/NotFound'
48606
+ '429':
48607
+ description: "Google Ads operations budget or platform quota exhausted."
48608
+ '501':
48609
+ description: "Only supported on Google Ads."
47720
48610
  post:
47721
- x-resource-group: "ads"
47722
48611
  operationId: addAccountCallouts
47723
- tags: ["Ad Accounts"]
47724
- x-platforms: ["google"]
47725
- summary: Add account-level callout extensions
47726
- description: |-
47727
- Creates one asset plus one `customerAsset` link (field type CALLOUT)
47728
- per callout text, in a single mutate. Google only; every other
47729
- platform returns 501.
48612
+ summary: Add account callouts
48613
+ x-resource-group: ads
48614
+ tags:
48615
+ - Ad Accounts
48616
+ x-platforms:
48617
+ - google
48618
+ description: "Creates assets and customer_asset links for this Google customer. Links apply at account level."
47730
48619
  security:
47731
- - bearerAuth: []
48620
+ - bearerAuth: []
47732
48621
  requestBody:
47733
48622
  required: true
47734
48623
  content:
47735
48624
  application/json:
47736
48625
  schema:
47737
48626
  type: object
47738
- required: [accountId, callouts]
48627
+ required:
48628
+ - accountId
48629
+ - callouts
47739
48630
  properties:
47740
- accountId: { type: string, description: "Zernio SocialAccount id owning the Google Ads connection." }
47741
- customerId: { type: string, description: "Numeric Google Ads customer id. Only required when the connection has more than one." }
48631
+ accountId:
48632
+ type: string
48633
+ pattern: ^[a-fA-F0-9]{24}$
48634
+ description: "Zernio Google Ads connection id."
48635
+ customerId:
48636
+ type: string
48637
+ pattern: ^\d+$
48638
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
47742
48639
  callouts:
47743
48640
  type: array
48641
+ items:
48642
+ type: string
48643
+ minLength: 1
48644
+ maxLength: 25
47744
48645
  minItems: 1
47745
48646
  maxItems: 20
47746
- items: { type: string, minLength: 1, maxLength: 25 }
47747
- description: 'Callout text, 1-25 characters each; up to 20 per request (Google''s CalloutAsset limits).'
48647
+ example:
48648
+ accountId: 64b1f0c8a1b2c3d4e5f60718
48649
+ customerId: '1234567890'
48650
+ callouts:
48651
+ - Fast setup
47748
48652
  responses:
47749
48653
  '201':
47750
- description: Callouts created
48654
+ description: "Assets created and attached."
47751
48655
  content:
47752
48656
  application/json:
47753
48657
  schema:
47754
48658
  type: object
47755
48659
  properties:
47756
- customerId: { type: string }
48660
+ customerId:
48661
+ type: string
47757
48662
  callouts:
47758
48663
  type: array
47759
48664
  items:
47760
48665
  type: object
47761
48666
  properties:
47762
- assetId: { type: string }
47763
- text: { type: string }
47764
- '400': { $ref: '#/components/responses/BadRequest' }
47765
- '401': { $ref: '#/components/responses/Unauthorized' }
48667
+ assetId:
48668
+ type: string
48669
+ text:
48670
+ type: string
48671
+ '400':
48672
+ $ref: '#/components/responses/BadRequest'
48673
+ '401':
48674
+ $ref: '#/components/responses/Unauthorized'
47766
48675
  '403':
47767
- description: Ads access required (Ads add-on on legacy plans, included on usage-based plans).
47768
- '404': { $ref: '#/components/responses/NotFound' }
47769
- '501': { description: Only supported on Google Ads }
47770
-
48676
+ description: "Ads access is required."
48677
+ '404':
48678
+ $ref: '#/components/responses/NotFound'
48679
+ '429':
48680
+ description: "Google Ads operations budget or platform quota exhausted."
48681
+ '501':
48682
+ description: "Only supported on Google Ads."
48683
+ put:
48684
+ operationId: updateAccountCallouts
48685
+ summary: Update account callouts
48686
+ x-resource-group: ads
48687
+ tags:
48688
+ - Ad Accounts
48689
+ x-platforms:
48690
+ - google
48691
+ description: "Edits existing Google assets in place. Send updates with assetResourceName and the fields to change.\
48692
+ \ An asset is shared: changes affect every attachment using it. Omitted fields stay unchanged. The operation\
48693
+ \ consumes the Google operations budget and invalidates affected cached lists."
48694
+ security:
48695
+ - bearerAuth: []
48696
+ requestBody:
48697
+ required: true
48698
+ content:
48699
+ application/json:
48700
+ schema:
48701
+ type: object
48702
+ required:
48703
+ - accountId
48704
+ - updates
48705
+ properties:
48706
+ accountId:
48707
+ type: string
48708
+ pattern: ^[a-fA-F0-9]{24}$
48709
+ description: "Zernio Google Ads connection id."
48710
+ customerId:
48711
+ type: string
48712
+ pattern: ^\d+$
48713
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
48714
+ updates:
48715
+ type: array
48716
+ items:
48717
+ type: object
48718
+ required:
48719
+ - assetResourceName
48720
+ properties:
48721
+ assetResourceName:
48722
+ type: string
48723
+ pattern: ^customers/\d+/assets/\d+$
48724
+ description: "Asset resource name returned by a list operation. Must belong to the selected\
48725
+ \ customer."
48726
+ calloutAsset:
48727
+ type: object
48728
+ required:
48729
+ - calloutText
48730
+ properties:
48731
+ calloutText:
48732
+ type: string
48733
+ minLength: 1
48734
+ maxLength: 25
48735
+ description: "Provide at least one field belonging to this asset type."
48736
+ minItems: 1
48737
+ maxItems: 20
48738
+ example:
48739
+ accountId: 64b1f0c8a1b2c3d4e5f60718
48740
+ customerId: '1234567890'
48741
+ updates:
48742
+ - assetResourceName: customers/1234567890/assets/123
48743
+ calloutAsset:
48744
+ calloutText: Simple integration
48745
+ responses:
48746
+ '200':
48747
+ description: "Assets returned."
48748
+ content:
48749
+ application/json:
48750
+ schema:
48751
+ type: object
48752
+ properties:
48753
+ updated:
48754
+ type: integer
48755
+ customerId:
48756
+ type: string
48757
+ '400':
48758
+ $ref: '#/components/responses/BadRequest'
48759
+ '401':
48760
+ $ref: '#/components/responses/Unauthorized'
48761
+ '403':
48762
+ description: "Ads access is required."
48763
+ '404':
48764
+ $ref: '#/components/responses/NotFound'
48765
+ '429':
48766
+ description: "Google Ads operations budget or platform quota exhausted."
48767
+ '501':
48768
+ description: "Only supported on Google Ads."
47771
48769
  delete:
47772
- x-resource-group: "ads"
47773
48770
  operationId: removeAccountCallout
47774
- tags: ["Ad Accounts"]
47775
- x-platforms: ["google"]
47776
- summary: Remove an account-level callout extension
47777
- description: |-
47778
- Removes the `customerAsset` link (`customers/{cid}/customerAssets/{assetId}~CALLOUT`).
47779
- Google only; every other platform returns 501.
48771
+ summary: Remove account callout
48772
+ x-resource-group: ads
48773
+ tags:
48774
+ - Ad Accounts
48775
+ x-platforms:
48776
+ - google
48777
+ description: "Removes the customer_asset attachment only. The underlying shared asset and its campaign or ad-group\
48778
+ \ attachments remain."
47780
48779
  security:
47781
- - bearerAuth: []
48780
+ - bearerAuth: []
47782
48781
  requestBody:
47783
48782
  required: true
47784
48783
  content:
47785
48784
  application/json:
47786
48785
  schema:
47787
48786
  type: object
47788
- required: [accountId, assetId]
48787
+ required:
48788
+ - accountId
48789
+ - assetId
47789
48790
  properties:
47790
- accountId: { type: string, description: "Zernio SocialAccount id owning the Google Ads connection." }
47791
- customerId: { type: string, description: "Numeric Google Ads customer id. Only required when the connection has more than one." }
47792
- assetId: { type: string, description: "Numeric asset id from GET /v1/ads/accounts/callouts." }
48791
+ accountId:
48792
+ type: string
48793
+ pattern: ^[a-fA-F0-9]{24}$
48794
+ description: "Zernio Google Ads connection id."
48795
+ customerId:
48796
+ type: string
48797
+ pattern: ^\d+$
48798
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
48799
+ assetId:
48800
+ type: string
48801
+ pattern: ^\d+$
48802
+ example:
48803
+ accountId: 64b1f0c8a1b2c3d4e5f60718
48804
+ customerId: '1234567890'
48805
+ assetId: '123'
47793
48806
  responses:
47794
48807
  '200':
47795
- description: Callout removed
48808
+ description: "Assets returned."
47796
48809
  content:
47797
48810
  application/json:
47798
48811
  schema:
47799
48812
  type: object
47800
48813
  properties:
47801
- removed: { type: boolean }
47802
- customerId: { type: string }
47803
- '400': { $ref: '#/components/responses/BadRequest' }
47804
- '401': { $ref: '#/components/responses/Unauthorized' }
48814
+ removed:
48815
+ type: boolean
48816
+ customerId:
48817
+ type: string
48818
+ '400':
48819
+ $ref: '#/components/responses/BadRequest'
48820
+ '401':
48821
+ $ref: '#/components/responses/Unauthorized'
47805
48822
  '403':
47806
- description: Ads access required (Ads add-on on legacy plans, included on usage-based plans).
47807
- '404': { $ref: '#/components/responses/NotFound' }
47808
- '501': { description: Only supported on Google Ads }
48823
+ description: "Ads access is required."
48824
+ '404':
48825
+ $ref: '#/components/responses/NotFound'
48826
+ '429':
48827
+ description: "Google Ads operations budget or platform quota exhausted."
48828
+ '501':
48829
+ description: "Only supported on Google Ads."
48830
+
48831
+ /v1/ads/accounts/sitelinks:
48832
+ get:
48833
+ operationId: listAccountSitelinks
48834
+ summary: List account sitelinks
48835
+ x-resource-group: ads
48836
+ tags:
48837
+ - Ad Accounts
48838
+ x-platforms:
48839
+ - google
48840
+ description: "Lists directly attached Google assets. Fresh reads are cached for 10 minutes; exhausted quota\
48841
+ \ may return the last successful read with stale=true. Inherited assets are not included."
48842
+ security:
48843
+ - bearerAuth: []
48844
+ parameters:
48845
+ - name: accountId
48846
+ in: query
48847
+ required: true
48848
+ schema:
48849
+ type: string
48850
+ pattern: ^[a-fA-F0-9]{24}$
48851
+ description: "Zernio Google Ads connection id."
48852
+ - name: customerId
48853
+ in: query
48854
+ schema:
48855
+ type: string
48856
+ pattern: ^\d+$
48857
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
48858
+ responses:
48859
+ '200':
48860
+ description: "Assets returned."
48861
+ content:
48862
+ application/json:
48863
+ schema:
48864
+ type: object
48865
+ properties:
48866
+ customerId:
48867
+ type: string
48868
+ sitelinks:
48869
+ type: array
48870
+ items:
48871
+ type: object
48872
+ properties:
48873
+ assetId:
48874
+ type: string
48875
+ status:
48876
+ type: string
48877
+ assetResourceName:
48878
+ type: string
48879
+ customerAssetResourceName:
48880
+ type: string
48881
+ text:
48882
+ type: string
48883
+ linkUrl:
48884
+ type: string
48885
+ format: uri
48886
+ description1:
48887
+ type: string
48888
+ description2:
48889
+ type: string
48890
+ cachedAt:
48891
+ type:
48892
+ - string
48893
+ - 'null'
48894
+ format: date-time
48895
+ description: "Time of the cached Google read. Null when no cache was used."
48896
+ stale:
48897
+ type: boolean
48898
+ description: "True when exhausted quota required returning the last successful read."
48899
+ '400':
48900
+ $ref: '#/components/responses/BadRequest'
48901
+ '401':
48902
+ $ref: '#/components/responses/Unauthorized'
48903
+ '403':
48904
+ description: "Ads access is required."
48905
+ '404':
48906
+ $ref: '#/components/responses/NotFound'
48907
+ '429':
48908
+ description: "Google Ads operations budget or platform quota exhausted."
48909
+ '501':
48910
+ description: "Only supported on Google Ads."
48911
+ post:
48912
+ operationId: addAccountSitelinks
48913
+ summary: Add account sitelinks
48914
+ x-resource-group: ads
48915
+ tags:
48916
+ - Ad Accounts
48917
+ x-platforms:
48918
+ - google
48919
+ description: "Creates assets and customer_asset links for this Google customer. Links apply at account level."
48920
+ security:
48921
+ - bearerAuth: []
48922
+ requestBody:
48923
+ required: true
48924
+ content:
48925
+ application/json:
48926
+ schema:
48927
+ type: object
48928
+ required:
48929
+ - accountId
48930
+ - sitelinks
48931
+ properties:
48932
+ accountId:
48933
+ type: string
48934
+ pattern: ^[a-fA-F0-9]{24}$
48935
+ description: "Zernio Google Ads connection id."
48936
+ customerId:
48937
+ type: string
48938
+ pattern: ^\d+$
48939
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
48940
+ sitelinks:
48941
+ type: array
48942
+ items:
48943
+ $ref: '#/components/schemas/GoogleSitelink'
48944
+ minItems: 1
48945
+ maxItems: 20
48946
+ example:
48947
+ accountId: 64b1f0c8a1b2c3d4e5f60718
48948
+ customerId: '1234567890'
48949
+ sitelinks:
48950
+ - text: Pricing
48951
+ linkUrl: https://zernio.com/pricing
48952
+ responses:
48953
+ '201':
48954
+ description: "Assets created and attached."
48955
+ content:
48956
+ application/json:
48957
+ schema:
48958
+ type: object
48959
+ properties:
48960
+ customerId:
48961
+ type: string
48962
+ sitelinks:
48963
+ type: array
48964
+ items:
48965
+ type: object
48966
+ properties:
48967
+ assetId:
48968
+ type: string
48969
+ text:
48970
+ type: string
48971
+ minLength: 1
48972
+ maxLength: 25
48973
+ linkUrl:
48974
+ type: string
48975
+ format: uri
48976
+ description1:
48977
+ type: string
48978
+ minLength: 1
48979
+ maxLength: 35
48980
+ description2:
48981
+ type: string
48982
+ minLength: 1
48983
+ maxLength: 35
48984
+ '400':
48985
+ $ref: '#/components/responses/BadRequest'
48986
+ '401':
48987
+ $ref: '#/components/responses/Unauthorized'
48988
+ '403':
48989
+ description: "Ads access is required."
48990
+ '404':
48991
+ $ref: '#/components/responses/NotFound'
48992
+ '429':
48993
+ description: "Google Ads operations budget or platform quota exhausted."
48994
+ '501':
48995
+ description: "Only supported on Google Ads."
48996
+ put:
48997
+ operationId: updateAccountSitelinks
48998
+ summary: Update account sitelinks
48999
+ x-resource-group: ads
49000
+ tags:
49001
+ - Ad Accounts
49002
+ x-platforms:
49003
+ - google
49004
+ description: "Edits existing Google assets in place. Send updates with assetResourceName and the fields to change.\
49005
+ \ An asset is shared: changes affect every attachment using it. Omitted fields stay unchanged. The operation\
49006
+ \ consumes the Google operations budget and invalidates affected cached lists."
49007
+ security:
49008
+ - bearerAuth: []
49009
+ requestBody:
49010
+ required: true
49011
+ content:
49012
+ application/json:
49013
+ schema:
49014
+ type: object
49015
+ required:
49016
+ - accountId
49017
+ - updates
49018
+ properties:
49019
+ accountId:
49020
+ type: string
49021
+ pattern: ^[a-fA-F0-9]{24}$
49022
+ description: "Zernio Google Ads connection id."
49023
+ customerId:
49024
+ type: string
49025
+ pattern: ^\d+$
49026
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
49027
+ updates:
49028
+ type: array
49029
+ items:
49030
+ type: object
49031
+ required:
49032
+ - assetResourceName
49033
+ properties:
49034
+ assetResourceName:
49035
+ type: string
49036
+ pattern: ^customers/\d+/assets/\d+$
49037
+ description: "Asset resource name returned by a list operation. Must belong to the selected\
49038
+ \ customer."
49039
+ sitelinkAsset:
49040
+ type: object
49041
+ properties:
49042
+ linkText:
49043
+ type: string
49044
+ minLength: 1
49045
+ maxLength: 25
49046
+ description1:
49047
+ type: string
49048
+ maxLength: 35
49049
+ description2:
49050
+ type: string
49051
+ maxLength: 35
49052
+ linkUrl:
49053
+ type: string
49054
+ format: uri
49055
+ description: "Alias for finalUrls with one URL. Do not supply both."
49056
+ minProperties: 1
49057
+ finalUrls:
49058
+ type: array
49059
+ items:
49060
+ type: string
49061
+ format: uri
49062
+ minItems: 1
49063
+ description: "Provide at least one field belonging to this asset type."
49064
+ minItems: 1
49065
+ maxItems: 20
49066
+ example:
49067
+ accountId: 64b1f0c8a1b2c3d4e5f60718
49068
+ customerId: '1234567890'
49069
+ updates:
49070
+ - assetResourceName: customers/1234567890/assets/123
49071
+ sitelinkAsset:
49072
+ linkText: Explore pricing
49073
+ finalUrls:
49074
+ - https://zernio.com/pricing
49075
+ responses:
49076
+ '200':
49077
+ description: "Assets returned."
49078
+ content:
49079
+ application/json:
49080
+ schema:
49081
+ type: object
49082
+ properties:
49083
+ updated:
49084
+ type: integer
49085
+ customerId:
49086
+ type: string
49087
+ '400':
49088
+ $ref: '#/components/responses/BadRequest'
49089
+ '401':
49090
+ $ref: '#/components/responses/Unauthorized'
49091
+ '403':
49092
+ description: "Ads access is required."
49093
+ '404':
49094
+ $ref: '#/components/responses/NotFound'
49095
+ '429':
49096
+ description: "Google Ads operations budget or platform quota exhausted."
49097
+ '501':
49098
+ description: "Only supported on Google Ads."
49099
+ delete:
49100
+ operationId: removeAccountSitelink
49101
+ summary: Remove account sitelink
49102
+ x-resource-group: ads
49103
+ tags:
49104
+ - Ad Accounts
49105
+ x-platforms:
49106
+ - google
49107
+ description: "Removes the customer_asset attachment only. The underlying shared asset and its campaign or ad-group\
49108
+ \ attachments remain."
49109
+ security:
49110
+ - bearerAuth: []
49111
+ requestBody:
49112
+ required: true
49113
+ content:
49114
+ application/json:
49115
+ schema:
49116
+ type: object
49117
+ required:
49118
+ - accountId
49119
+ - assetId
49120
+ properties:
49121
+ accountId:
49122
+ type: string
49123
+ pattern: ^[a-fA-F0-9]{24}$
49124
+ description: "Zernio Google Ads connection id."
49125
+ customerId:
49126
+ type: string
49127
+ pattern: ^\d+$
49128
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
49129
+ assetId:
49130
+ type: string
49131
+ pattern: ^\d+$
49132
+ example:
49133
+ accountId: 64b1f0c8a1b2c3d4e5f60718
49134
+ customerId: '1234567890'
49135
+ assetId: '123'
49136
+ responses:
49137
+ '200':
49138
+ description: "Assets returned."
49139
+ content:
49140
+ application/json:
49141
+ schema:
49142
+ type: object
49143
+ properties:
49144
+ removed:
49145
+ type: boolean
49146
+ customerId:
49147
+ type: string
49148
+ '400':
49149
+ $ref: '#/components/responses/BadRequest'
49150
+ '401':
49151
+ $ref: '#/components/responses/Unauthorized'
49152
+ '403':
49153
+ description: "Ads access is required."
49154
+ '404':
49155
+ $ref: '#/components/responses/NotFound'
49156
+ '429':
49157
+ description: "Google Ads operations budget or platform quota exhausted."
49158
+ '501':
49159
+ description: "Only supported on Google Ads."
49160
+
49161
+ /v1/ads/accounts/structured-snippets:
49162
+ get:
49163
+ operationId: listAccountStructuredSnippets
49164
+ summary: List account snippets
49165
+ x-resource-group: ads
49166
+ tags:
49167
+ - Ad Accounts
49168
+ x-platforms:
49169
+ - google
49170
+ description: "Lists directly attached Google assets. Fresh reads are cached for 10 minutes; exhausted quota\
49171
+ \ may return the last successful read with stale=true. Inherited assets are not included."
49172
+ security:
49173
+ - bearerAuth: []
49174
+ parameters:
49175
+ - name: accountId
49176
+ in: query
49177
+ required: true
49178
+ schema:
49179
+ type: string
49180
+ pattern: ^[a-fA-F0-9]{24}$
49181
+ description: "Zernio Google Ads connection id."
49182
+ - name: customerId
49183
+ in: query
49184
+ schema:
49185
+ type: string
49186
+ pattern: ^\d+$
49187
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
49188
+ responses:
49189
+ '200':
49190
+ description: "Assets returned."
49191
+ content:
49192
+ application/json:
49193
+ schema:
49194
+ type: object
49195
+ properties:
49196
+ customerId:
49197
+ type: string
49198
+ structuredSnippets:
49199
+ type: array
49200
+ items:
49201
+ type: object
49202
+ properties:
49203
+ assetId:
49204
+ type: string
49205
+ status:
49206
+ type: string
49207
+ assetResourceName:
49208
+ type: string
49209
+ customerAssetResourceName:
49210
+ type: string
49211
+ header:
49212
+ type: string
49213
+ values:
49214
+ type: array
49215
+ items:
49216
+ type: string
49217
+ cachedAt:
49218
+ type:
49219
+ - string
49220
+ - 'null'
49221
+ format: date-time
49222
+ description: "Time of the cached Google read. Null when no cache was used."
49223
+ stale:
49224
+ type: boolean
49225
+ description: "True when exhausted quota required returning the last successful read."
49226
+ '400':
49227
+ $ref: '#/components/responses/BadRequest'
49228
+ '401':
49229
+ $ref: '#/components/responses/Unauthorized'
49230
+ '403':
49231
+ description: "Ads access is required."
49232
+ '404':
49233
+ $ref: '#/components/responses/NotFound'
49234
+ '429':
49235
+ description: "Google Ads operations budget or platform quota exhausted."
49236
+ '501':
49237
+ description: "Only supported on Google Ads."
49238
+ post:
49239
+ operationId: addAccountStructuredSnippets
49240
+ summary: Add account snippets
49241
+ x-resource-group: ads
49242
+ tags:
49243
+ - Ad Accounts
49244
+ x-platforms:
49245
+ - google
49246
+ description: "Creates assets and customer_asset links for this Google customer. Links apply at account level."
49247
+ security:
49248
+ - bearerAuth: []
49249
+ requestBody:
49250
+ required: true
49251
+ content:
49252
+ application/json:
49253
+ schema:
49254
+ type: object
49255
+ required:
49256
+ - accountId
49257
+ - structuredSnippets
49258
+ properties:
49259
+ accountId:
49260
+ type: string
49261
+ pattern: ^[a-fA-F0-9]{24}$
49262
+ description: "Zernio Google Ads connection id."
49263
+ customerId:
49264
+ type: string
49265
+ pattern: ^\d+$
49266
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
49267
+ structuredSnippets:
49268
+ type: array
49269
+ items:
49270
+ $ref: '#/components/schemas/GoogleStructuredSnippet'
49271
+ minItems: 1
49272
+ maxItems: 20
49273
+ example:
49274
+ accountId: 64b1f0c8a1b2c3d4e5f60718
49275
+ customerId: '1234567890'
49276
+ structuredSnippets:
49277
+ - header: Types
49278
+ values:
49279
+ - Scheduling
49280
+ - Analytics
49281
+ - Messaging
49282
+ responses:
49283
+ '201':
49284
+ description: "Assets created and attached."
49285
+ content:
49286
+ application/json:
49287
+ schema:
49288
+ type: object
49289
+ properties:
49290
+ customerId:
49291
+ type: string
49292
+ structuredSnippets:
49293
+ type: array
49294
+ items:
49295
+ type: object
49296
+ properties:
49297
+ assetId:
49298
+ type: string
49299
+ header:
49300
+ type: string
49301
+ enum:
49302
+ - Amenities
49303
+ - Brands
49304
+ - Courses
49305
+ - Degree programs
49306
+ - Destinations
49307
+ - Featured hotels
49308
+ - Insurance coverage
49309
+ - Models
49310
+ - Neighborhoods
49311
+ - Service catalog
49312
+ - Shows
49313
+ - Styles
49314
+ - Types
49315
+ values:
49316
+ type: array
49317
+ minItems: 3
49318
+ maxItems: 10
49319
+ items:
49320
+ type: string
49321
+ minLength: 1
49322
+ maxLength: 25
49323
+ '400':
49324
+ $ref: '#/components/responses/BadRequest'
49325
+ '401':
49326
+ $ref: '#/components/responses/Unauthorized'
49327
+ '403':
49328
+ description: "Ads access is required."
49329
+ '404':
49330
+ $ref: '#/components/responses/NotFound'
49331
+ '429':
49332
+ description: "Google Ads operations budget or platform quota exhausted."
49333
+ '501':
49334
+ description: "Only supported on Google Ads."
49335
+ put:
49336
+ operationId: updateAccountStructuredSnippets
49337
+ summary: Update account snippets
49338
+ x-resource-group: ads
49339
+ tags:
49340
+ - Ad Accounts
49341
+ x-platforms:
49342
+ - google
49343
+ description: "Edits existing Google assets in place. Send updates with assetResourceName and the fields to change.\
49344
+ \ An asset is shared: changes affect every attachment using it. Omitted fields stay unchanged. The operation\
49345
+ \ consumes the Google operations budget and invalidates affected cached lists."
49346
+ security:
49347
+ - bearerAuth: []
49348
+ requestBody:
49349
+ required: true
49350
+ content:
49351
+ application/json:
49352
+ schema:
49353
+ type: object
49354
+ required:
49355
+ - accountId
49356
+ - updates
49357
+ properties:
49358
+ accountId:
49359
+ type: string
49360
+ pattern: ^[a-fA-F0-9]{24}$
49361
+ description: "Zernio Google Ads connection id."
49362
+ customerId:
49363
+ type: string
49364
+ pattern: ^\d+$
49365
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
49366
+ updates:
49367
+ type: array
49368
+ items:
49369
+ type: object
49370
+ required:
49371
+ - assetResourceName
49372
+ properties:
49373
+ assetResourceName:
49374
+ type: string
49375
+ pattern: ^customers/\d+/assets/\d+$
49376
+ description: "Asset resource name returned by a list operation. Must belong to the selected\
49377
+ \ customer."
49378
+ structuredSnippetAsset:
49379
+ $ref: '#/components/schemas/GoogleStructuredSnippet'
49380
+ description: "Provide at least one field belonging to this asset type."
49381
+ minItems: 1
49382
+ maxItems: 20
49383
+ example:
49384
+ accountId: 64b1f0c8a1b2c3d4e5f60718
49385
+ customerId: '1234567890'
49386
+ updates:
49387
+ - assetResourceName: customers/1234567890/assets/123
49388
+ structuredSnippetAsset:
49389
+ header: Types
49390
+ values:
49391
+ - Scheduling
49392
+ - Reporting
49393
+ - Messaging
49394
+ responses:
49395
+ '200':
49396
+ description: "Assets returned."
49397
+ content:
49398
+ application/json:
49399
+ schema:
49400
+ type: object
49401
+ properties:
49402
+ updated:
49403
+ type: integer
49404
+ customerId:
49405
+ type: string
49406
+ '400':
49407
+ $ref: '#/components/responses/BadRequest'
49408
+ '401':
49409
+ $ref: '#/components/responses/Unauthorized'
49410
+ '403':
49411
+ description: "Ads access is required."
49412
+ '404':
49413
+ $ref: '#/components/responses/NotFound'
49414
+ '429':
49415
+ description: "Google Ads operations budget or platform quota exhausted."
49416
+ '501':
49417
+ description: "Only supported on Google Ads."
49418
+ delete:
49419
+ operationId: removeAccountStructuredSnippet
49420
+ summary: Remove account snippet
49421
+ x-resource-group: ads
49422
+ tags:
49423
+ - Ad Accounts
49424
+ x-platforms:
49425
+ - google
49426
+ description: "Removes the customer_asset attachment only. The underlying shared asset and its campaign or ad-group\
49427
+ \ attachments remain."
49428
+ security:
49429
+ - bearerAuth: []
49430
+ requestBody:
49431
+ required: true
49432
+ content:
49433
+ application/json:
49434
+ schema:
49435
+ type: object
49436
+ required:
49437
+ - accountId
49438
+ - assetId
49439
+ properties:
49440
+ accountId:
49441
+ type: string
49442
+ pattern: ^[a-fA-F0-9]{24}$
49443
+ description: "Zernio Google Ads connection id."
49444
+ customerId:
49445
+ type: string
49446
+ pattern: ^\d+$
49447
+ description: "Google customer id without dashes. Required when the connection has multiple customers."
49448
+ assetId:
49449
+ type: string
49450
+ pattern: ^\d+$
49451
+ example:
49452
+ accountId: 64b1f0c8a1b2c3d4e5f60718
49453
+ customerId: '1234567890'
49454
+ assetId: '123'
49455
+ responses:
49456
+ '200':
49457
+ description: "Assets returned."
49458
+ content:
49459
+ application/json:
49460
+ schema:
49461
+ type: object
49462
+ properties:
49463
+ removed:
49464
+ type: boolean
49465
+ customerId:
49466
+ type: string
49467
+ '400':
49468
+ $ref: '#/components/responses/BadRequest'
49469
+ '401':
49470
+ $ref: '#/components/responses/Unauthorized'
49471
+ '403':
49472
+ description: "Ads access is required."
49473
+ '404':
49474
+ $ref: '#/components/responses/NotFound'
49475
+ '429':
49476
+ description: "Google Ads operations budget or platform quota exhausted."
49477
+ '501':
49478
+ description: "Only supported on Google Ads."
47809
49479
 
47810
49480
  /v1/ads/accounts/finance:
47811
49481
  get:
@@ -49145,8 +50815,28 @@ paths:
49145
50815
  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." }
49146
50816
  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." }
49147
50817
  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." }
49148
- additionalHeadlines: { type: array, items: { type: string }, description: "Google Search RSA only. Extra headlines." }
49149
- additionalDescriptions: { type: array, items: { type: string }, description: "Google Search RSA only. Extra descriptions." }
50818
+ additionalHeadlines:
50819
+ type: array
50820
+ items:
50821
+ oneOf:
50822
+ - type: string
50823
+ - $ref: '#/components/schemas/GoogleRsaHeadline'
50824
+ description: "Google Search RSA only. Extra text assets as strings or objects with text and optional pinnedField. Existing string input remains supported. The effective create lists, including primary text and deduplication, must contain 3-15 headlines and 2-4 descriptions; excess entries return 400."
50825
+ example:
50826
+ - Schedule Your Posts
50827
+ - text: Build With Zernio
50828
+ pinnedField: HEADLINE_2
50829
+ additionalDescriptions:
50830
+ type: array
50831
+ items:
50832
+ oneOf:
50833
+ - type: string
50834
+ - $ref: '#/components/schemas/GoogleRsaDescription'
50835
+ description: "Google Search RSA only. Extra text assets as strings or objects with text and optional pinnedField. Existing string input remains supported. The effective create lists, including primary text and deduplication, must contain 3-15 headlines and 2-4 descriptions; excess entries return 400."
50836
+ example:
50837
+ - Build social publishing into your application.
50838
+ - text: Connect social accounts with one API.
50839
+ pinnedField: DESCRIPTION_2
49150
50840
  sitelinks:
49151
50841
  type: array
49152
50842
  minItems: 2