late-sdk 0.0.930 → 0.0.932

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/docs/AdCampaignsApi.md +6 -10
  4. data/docs/AdCreative.md +0 -4
  5. data/docs/AdCreativesApi.md +1 -1
  6. data/docs/BoostPostRequest.md +1 -1
  7. data/docs/ConnectApi.md +140 -0
  8. data/docs/CreateAdCreative201Response.md +1 -5
  9. data/docs/CreateAdCreativeRequest.md +2 -2
  10. data/docs/CreateStandaloneAdRequest.md +2 -2
  11. data/docs/CreateStandaloneAdRequestCreativesInner.md +0 -2
  12. data/docs/GetPageWebhookSubscription200Response.md +26 -0
  13. data/docs/ResyncPageWebhookSubscription200Response.md +28 -0
  14. data/docs/UpdateAdRequestCreative.md +2 -2
  15. data/lib/zernio-sdk/api/ad_campaigns_api.rb +4 -7
  16. data/lib/zernio-sdk/api/ad_creatives_api.rb +2 -2
  17. data/lib/zernio-sdk/api/connect_api.rb +126 -0
  18. data/lib/zernio-sdk/models/ad_creative.rb +1 -42
  19. data/lib/zernio-sdk/models/boost_post_request.rb +1 -1
  20. data/lib/zernio-sdk/models/create_ad_creative201_response.rb +4 -44
  21. data/lib/zernio-sdk/models/create_ad_creative_request.rb +3 -2
  22. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +3 -2
  23. data/lib/zernio-sdk/models/create_standalone_ad_request_creatives_inner.rb +1 -11
  24. data/lib/zernio-sdk/models/get_page_webhook_subscription200_response.rb +189 -0
  25. data/lib/zernio-sdk/models/resync_page_webhook_subscription200_response.rb +195 -0
  26. data/lib/zernio-sdk/models/update_ad_request_creative.rb +4 -3
  27. data/lib/zernio-sdk/version.rb +1 -1
  28. data/lib/zernio-sdk.rb +2 -2
  29. data/openapi.yaml +94 -71
  30. data/spec/api/ad_campaigns_api_spec.rb +2 -3
  31. data/spec/api/ad_creatives_api_spec.rb +1 -1
  32. data/spec/api/connect_api_spec.rb +24 -0
  33. data/spec/models/ad_creative_spec.rb +0 -12
  34. data/spec/models/create_ad_creative201_response_spec.rb +0 -12
  35. data/spec/models/create_standalone_ad_request_creatives_inner_spec.rb +0 -6
  36. data/spec/models/{meta_promotion_spec.rb → get_page_webhook_subscription200_response_spec.rb} +11 -15
  37. data/spec/models/resync_page_webhook_subscription200_response_spec.rb +66 -0
  38. data/zernio-sdk-0.0.932.gem +0 -0
  39. metadata +10 -10
  40. data/docs/MetaPromotion.md +0 -26
  41. data/docs/MetaPromotionStatus.md +0 -15
  42. data/lib/zernio-sdk/models/meta_promotion.rb +0 -275
  43. data/lib/zernio-sdk/models/meta_promotion_status.rb +0 -41
  44. data/spec/models/meta_promotion_status_spec.rb +0 -30
  45. data/zernio-sdk-0.0.930.gem +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2f1020934465a40b3d3b9dc7b7b4786998d988b2d2ce98aa64ff49d9a06c12a0
4
- data.tar.gz: 7a6497059af6badc53984f349f6d776a5f4bc69058aa6be8227a5fa852ec8a5e
3
+ metadata.gz: 431510065efbb2e1717f2592b76e02d02717f913510477b6c1d5af1f7ad44ce1
4
+ data.tar.gz: f9786200c6089215f2bc17923fb52db08429a5133379fed155f1f75f28251d94
5
5
  SHA512:
6
- metadata.gz: 50aca6aa491c7549eae8db4eb5891915843056cd864a3f476e53417157d35e6f494a23c3ba781753ce5144012d597956c11aa0fdb118fcab94397cd144df4075
7
- data.tar.gz: ed3b210b3ac2c239d357afaee95d0157a75d1c19405ad873d85015087635ff8179445e1dedd30ef00197a0b68f9002088369fb279bbf47d701fc01bd833e1035
6
+ metadata.gz: cc5aa9231c666921115320624760269b42982bcea6771d576a1b62c18f8a36903d6002e4d832915f89751799fcb3775ff3506b4c97dc74a68d824655e751afc7
7
+ data.tar.gz: 7e2d8a09b0477cf215ec324bbd1e7728b244716c2f476597c02ea34d6437ba7d9c54c1b7fab6924374f36409ab04d2ff8ec8b8aba9d7efdd2236deb9165f2f19
data/README.md CHANGED
@@ -383,6 +383,7 @@ Class | Method | HTTP request | Description
383
383
  *Zernio::ConnectApi* | [**get_facebook_pages**](docs/ConnectApi.md#get_facebook_pages) | **GET** /v1/accounts/{accountId}/facebook-page | List Facebook pages
384
384
  *Zernio::ConnectApi* | [**get_gmb_locations**](docs/ConnectApi.md#get_gmb_locations) | **GET** /v1/accounts/{accountId}/gmb-locations | List Google Business Profile locations
385
385
  *Zernio::ConnectApi* | [**get_linked_in_organizations**](docs/ConnectApi.md#get_linked_in_organizations) | **GET** /v1/accounts/{accountId}/linkedin-organizations | List LinkedIn orgs
386
+ *Zernio::ConnectApi* | [**get_page_webhook_subscription**](docs/ConnectApi.md#get_page_webhook_subscription) | **GET** /v1/accounts/{accountId}/webhook-subscription | Read a Facebook Page's webhook subscription
386
387
  *Zernio::ConnectApi* | [**get_pending_o_auth_data**](docs/ConnectApi.md#get_pending_o_auth_data) | **GET** /v1/connect/pending-data | Get pending OAuth data
387
388
  *Zernio::ConnectApi* | [**get_pinterest_boards**](docs/ConnectApi.md#get_pinterest_boards) | **GET** /v1/accounts/{accountId}/pinterest-boards | List Pinterest boards
388
389
  *Zernio::ConnectApi* | [**get_reddit_flairs**](docs/ConnectApi.md#get_reddit_flairs) | **GET** /v1/accounts/{accountId}/reddit-flairs | List subreddit flairs
@@ -403,6 +404,7 @@ Class | Method | HTTP request | Description
403
404
  *Zernio::ConnectApi* | [**list_slack_channels**](docs/ConnectApi.md#list_slack_channels) | **GET** /v1/connect/slack | List Slack channels for the channel picker
404
405
  *Zernio::ConnectApi* | [**list_snapchat_profiles**](docs/ConnectApi.md#list_snapchat_profiles) | **GET** /v1/connect/snapchat/select-profile | List Snapchat profiles
405
406
  *Zernio::ConnectApi* | [**list_whats_app_phone_numbers**](docs/ConnectApi.md#list_whats_app_phone_numbers) | **GET** /v1/connect/whatsapp/select-phone-number | List numbers for selection
407
+ *Zernio::ConnectApi* | [**resync_page_webhook_subscription**](docs/ConnectApi.md#resync_page_webhook_subscription) | **POST** /v1/accounts/{accountId}/webhook-subscription | Re-subscribe a Facebook Page to Zernio's webhooks
406
408
  *Zernio::ConnectApi* | [**select_facebook_page**](docs/ConnectApi.md#select_facebook_page) | **POST** /v1/connect/facebook/select-page | Select Facebook page
407
409
  *Zernio::ConnectApi* | [**select_google_business_location**](docs/ConnectApi.md#select_google_business_location) | **POST** /v1/connect/googlebusiness/select-location | Select Google Business Profile location
408
410
  *Zernio::ConnectApi* | [**select_instagram_account**](docs/ConnectApi.md#select_instagram_account) | **POST** /v1/connect/instagram/select-account | Select the Page whose Instagram account to connect
@@ -1568,6 +1570,7 @@ Class | Method | HTTP request | Description
1568
1570
  - [Zernio::GetMediaPresignedUrlRequest](docs/GetMediaPresignedUrlRequest.md)
1569
1571
  - [Zernio::GetMessageAttachment200Response](docs/GetMessageAttachment200Response.md)
1570
1572
  - [Zernio::GetMessengerMenu200Response](docs/GetMessengerMenu200Response.md)
1573
+ - [Zernio::GetPageWebhookSubscription200Response](docs/GetPageWebhookSubscription200Response.md)
1571
1574
  - [Zernio::GetPendingOAuthData200Response](docs/GetPendingOAuthData200Response.md)
1572
1575
  - [Zernio::GetPendingOAuthData200ResponseOrganizationsInner](docs/GetPendingOAuthData200ResponseOrganizationsInner.md)
1573
1576
  - [Zernio::GetPhoneNumber200Response](docs/GetPhoneNumber200Response.md)
@@ -2037,8 +2040,6 @@ Class | Method | HTTP request | Description
2037
2040
  - [Zernio::MetaInstagramIdentityRef](docs/MetaInstagramIdentityRef.md)
2038
2041
  - [Zernio::MetaLeadFormPlatformData](docs/MetaLeadFormPlatformData.md)
2039
2042
  - [Zernio::MetaLeadFormPlatformDataContextCard](docs/MetaLeadFormPlatformDataContextCard.md)
2040
- - [Zernio::MetaPromotion](docs/MetaPromotion.md)
2041
- - [Zernio::MetaPromotionStatus](docs/MetaPromotionStatus.md)
2042
2043
  - [Zernio::Money](docs/Money.md)
2043
2044
  - [Zernio::MoneyAmount](docs/MoneyAmount.md)
2044
2045
  - [Zernio::MoveAccountToProfile200Response](docs/MoveAccountToProfile200Response.md)
@@ -2180,6 +2181,7 @@ Class | Method | HTTP request | Description
2180
2181
  - [Zernio::RespondToSmsRegistrationReviewRequest](docs/RespondToSmsRegistrationReviewRequest.md)
2181
2182
  - [Zernio::RestoreWorkflowVersion200Response](docs/RestoreWorkflowVersion200Response.md)
2182
2183
  - [Zernio::RestoreWorkflowVersion200ResponseWorkflow](docs/RestoreWorkflowVersion200ResponseWorkflow.md)
2184
+ - [Zernio::ResyncPageWebhookSubscription200Response](docs/ResyncPageWebhookSubscription200Response.md)
2183
2185
  - [Zernio::RetryPost207Response](docs/RetryPost207Response.md)
2184
2186
  - [Zernio::RetweetPost200Response](docs/RetweetPost200Response.md)
2185
2187
  - [Zernio::RetweetPostRequest](docs/RetweetPostRequest.md)
@@ -627,7 +627,7 @@ end
627
627
 
628
628
  Create standalone ad
629
629
 
630
- Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Google Performance Max: set `campaignType: \"pmax\"` and supply `assetGroup` with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. `validateOnly: true` validates the complete request with Google without creating or persisting resources. Read assets with `GET /v1/ads/campaigns/{campaignId}/asset-groups`. The logo is required; video is optional via `assetGroup.youtubeVideoId`. Brand guidelines are disabled at creation. All supplied asset links are validated together against Google's minimum asset requirements. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS. Other mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `promotion` and `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`. An item replaces the whole feature map; its `promotion` replaces the default offer, and `promotion: null` disables that default for the item. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Only ads supplied a `promotion` receive live readback; multi-create batches those reads in groups of up to 50 IDs without per-ad fallback. Inspect `ad.creative.promotionStatus` (or `ads[].creative.promotionStatus`). `not_returned` means Meta omitted the metadata; successful creation does not by itself prove the offer was applied or will display. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
630
+ Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Google Performance Max: set `campaignType: \"pmax\"` and supply `assetGroup` with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. `validateOnly: true` validates the complete request with Google without creating or persisting resources. Read assets with `GET /v1/ads/campaigns/{campaignId}/asset-groups`. The logo is required; video is optional via `assetGroup.youtubeVideoId`. Brand guidelines are disabled at creation. All supplied asset links are validated together against Google's minimum asset requirements. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS. Other mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`; an item replaces the whole feature map. `promotion` is not supported on any shape and any object is rejected with 400. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
631
631
 
632
632
  ### Examples
633
633
 
@@ -1130,11 +1130,11 @@ end
1130
1130
 
1131
1131
  ## get_ad
1132
1132
 
1133
- > <GetAd200Response> get_ad(ad_id, opts)
1133
+ > <GetAd200Response> get_ad(ad_id)
1134
1134
 
1135
1135
  Get ad details
1136
1136
 
1137
- Returns an ad with its creative, targeting, status, and performance metrics. Google Search ads include current creative.headlines, creative.descriptions and creative.finalUrls, preserving pinnedField. Top-level cachedAt and stale report cache freshness. Google mutations invalidate this read. RSA enrichment requires a stored advertisingChannelType of SEARCH. Ads with an unknown or other channel return their stored details without a Google read. If RSA enrichment fails, the stored ad is returned with HTTP 200 and without cache metadata. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step. By default, creative.promotion and creative.creativeFeatures contain stored requested settings, which do not confirm platform application. With `refreshPromotion=true`, Meta promotion metadata is read live and exposed as `ad.creative.promotion` with `promotionStatus`. Only `applied` confirms an offer; `not_returned` means the creative read succeeded without promotion metadata, and `unavailable` means it failed.
1137
+ Returns an ad with its creative, targeting, status, and performance metrics. Google Search ads include current creative.headlines, creative.descriptions and creative.finalUrls, preserving pinnedField. Top-level cachedAt and stale report cache freshness. Google mutations invalidate this read. RSA enrichment requires a stored advertisingChannelType of SEARCH. Ads with an unknown or other channel return their stored details without a Google read. If RSA enrichment fails, the stored ad is returned with HTTP 200 and without cache metadata. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step. `creative.creativeFeatures` holds the stored requested settings, which do not confirm platform application.
1138
1138
 
1139
1139
  ### Examples
1140
1140
 
@@ -1149,13 +1149,10 @@ end
1149
1149
 
1150
1150
  api_instance = Zernio::AdCampaignsApi.new
1151
1151
  ad_id = 'ad_id_example' # String | Zernio `_id` (hex), Meta `platformAdId` (numeric), or one of the creative's effective story/media IDs. See description for details.
1152
- opts = {
1153
- refresh_promotion: true # Boolean | Meta only. Read current promotion metadata from Meta and include promotionStatus. Omit for stored creative settings with no promotion-specific Graph call.
1154
- }
1155
1152
 
1156
1153
  begin
1157
1154
  # Get ad details
1158
- result = api_instance.get_ad(ad_id, opts)
1155
+ result = api_instance.get_ad(ad_id)
1159
1156
  p result
1160
1157
  rescue Zernio::ApiError => e
1161
1158
  puts "Error when calling AdCampaignsApi->get_ad: #{e}"
@@ -1166,12 +1163,12 @@ end
1166
1163
 
1167
1164
  This returns an Array which contains the response data, status code and headers.
1168
1165
 
1169
- > <Array(<GetAd200Response>, Integer, Hash)> get_ad_with_http_info(ad_id, opts)
1166
+ > <Array(<GetAd200Response>, Integer, Hash)> get_ad_with_http_info(ad_id)
1170
1167
 
1171
1168
  ```ruby
1172
1169
  begin
1173
1170
  # Get ad details
1174
- data, status_code, headers = api_instance.get_ad_with_http_info(ad_id, opts)
1171
+ data, status_code, headers = api_instance.get_ad_with_http_info(ad_id)
1175
1172
  p status_code # => 2xx
1176
1173
  p headers # => { ... }
1177
1174
  p data # => <GetAd200Response>
@@ -1185,7 +1182,6 @@ end
1185
1182
  | Name | Type | Description | Notes |
1186
1183
  | ---- | ---- | ----------- | ----- |
1187
1184
  | **ad_id** | **String** | Zernio &#x60;_id&#x60; (hex), Meta &#x60;platformAdId&#x60; (numeric), or one of the creative&#39;s effective story/media IDs. See description for details. | |
1188
- | **refresh_promotion** | **Boolean** | Meta only. Read current promotion metadata from Meta and include promotionStatus. Omit for stored creative settings with no promotion-specific Graph call. | [optional][default to false] |
1189
1185
 
1190
1186
  ### Return type
1191
1187
 
data/docs/AdCreative.md CHANGED
@@ -13,8 +13,6 @@
13
13
  | **image_url** | **String** | Alternative image URL | [optional] |
14
14
  | **video_id** | **String** | Meta video ID for VIDEO-type ads. Null for non-video ads. Callers that need an embeddable MP4 can call GET /{videoId}?fields&#x3D;source with the page access token. | [optional] |
15
15
  | **video_url** | **String** | Public Facebook watch URL for VIDEO-type ads (https://www.facebook.com/watch/?v&#x3D;{videoId}). Null for non-video ads. | [optional] |
16
- | **promotion** | [**MetaPromotion**](MetaPromotion.md) | Meta offer read from the live creative on creation or GET /v1/ads/{adId}. Null when metadata is not returned or cannot be read. Requested values are never echoed as applied. | [optional] |
17
- | **promotion_status** | [**MetaPromotionStatus**](MetaPromotionStatus.md) | | [optional] |
18
16
  | **creative_id** | **String** | Meta ad creative id backing this ad. Reusable via existingCreativeId on POST /v1/ads/create. | [optional] |
19
17
  | **object_type** | **String** | Meta creative object_type (e.g. SHARE, VIDEO, PRIVACY_CHECK_FAIL, POST_DELETED). Use this to render state-aware previews: when Meta moderation strips image/video fields, only thumbnailUrl at 64x64 is available. | [optional] |
20
18
  | **object_story_id** | **String** | Meta creative &#x60;object_story_id&#x60; (the SHARE reference). Frequently absent, because Meta omits it for SHARE creatives. Use effectiveObjectStoryId instead. | [optional] |
@@ -50,8 +48,6 @@ instance = Zernio::AdCreative.new(
50
48
  image_url: null,
51
49
  video_id: null,
52
50
  video_url: null,
53
- promotion: null,
54
- promotion_status: null,
55
51
  creative_id: null,
56
52
  object_type: null,
57
53
  object_story_id: null,
@@ -30,7 +30,7 @@ All URIs are relative to *https://zernio.com/api*
30
30
 
31
31
  Create a standalone creative
32
32
 
33
- Creates a creative in the library WITHOUT an ad, reusable on the create endpoints via `existingCreativeId`. Provide exactly one of `imageUrl` (uploaded server-side), `imageHash` (from POST /v1/ads/images or the library list), or `carouselCards` (2-10 hand-built cards). The Page (and linked Instagram account, when present) is resolved from `accountId` as the story actor. `promotion` configures an explicit offer separately from Advantage+ `creativeFeatures`. Only when `promotion` is supplied does the response read the creative back from Meta; `promotionStatus: not_returned` means Meta accepted creation but omitted promotion metadata, so the requested offer is not confirmed as applied.
33
+ Creates a creative in the library WITHOUT an ad, reusable on the create endpoints via `existingCreativeId`. Provide exactly one of `imageUrl` (uploaded server-side), `imageHash` (from POST /v1/ads/images or the library list), or `carouselCards` (2-10 hand-built cards). The Page (and linked Instagram account, when present) is resolved from `accountId` as the story actor. `creativeFeatures` configures Advantage+ enhancements. `promotion` is not supported and any object is rejected with 400.
34
34
 
35
35
  ### Examples
36
36
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **creative_features** | **Hash&lt;String, String&gt;** | Meta Advantage+ creative enhancements. Map snake_case feature names to OPT_IN or OPT_OUT; Meta validates supported keys and unspecified features default to OPT_OUT. auto_promotion_tag is an enhancement; use the separate promotion field for an explicit offer. The deprecated standard_enhancements bundle is rejected by Meta. | [optional] |
7
+ | **creative_features** | **Hash&lt;String, String&gt;** | Meta Advantage+ creative enhancements. Map snake_case feature names to OPT_IN or OPT_OUT; Meta validates supported keys and unspecified features default to OPT_OUT. auto_promotion_tag is an Advantage+ enhancement, not the Ads Manager Promotion setting. The deprecated standard_enhancements bundle is rejected by Meta. | [optional] |
8
8
  | **post_id** | **String** | Zernio post ID (provide this or platformPostId) | [optional] |
9
9
  | **platform_post_id** | **String** | Platform post ID (alternative to postId) | [optional] |
10
10
  | **account_id** | **String** | Account ID | |
data/docs/ConnectApi.md CHANGED
@@ -22,6 +22,7 @@ All URIs are relative to *https://zernio.com/api*
22
22
  | [**get_facebook_pages**](ConnectApi.md#get_facebook_pages) | **GET** /v1/accounts/{accountId}/facebook-page | List Facebook pages |
23
23
  | [**get_gmb_locations**](ConnectApi.md#get_gmb_locations) | **GET** /v1/accounts/{accountId}/gmb-locations | List Google Business Profile locations |
24
24
  | [**get_linked_in_organizations**](ConnectApi.md#get_linked_in_organizations) | **GET** /v1/accounts/{accountId}/linkedin-organizations | List LinkedIn orgs |
25
+ | [**get_page_webhook_subscription**](ConnectApi.md#get_page_webhook_subscription) | **GET** /v1/accounts/{accountId}/webhook-subscription | Read a Facebook Page&#39;s webhook subscription |
25
26
  | [**get_pending_o_auth_data**](ConnectApi.md#get_pending_o_auth_data) | **GET** /v1/connect/pending-data | Get pending OAuth data |
26
27
  | [**get_pinterest_boards**](ConnectApi.md#get_pinterest_boards) | **GET** /v1/accounts/{accountId}/pinterest-boards | List Pinterest boards |
27
28
  | [**get_reddit_flairs**](ConnectApi.md#get_reddit_flairs) | **GET** /v1/accounts/{accountId}/reddit-flairs | List subreddit flairs |
@@ -42,6 +43,7 @@ All URIs are relative to *https://zernio.com/api*
42
43
  | [**list_slack_channels**](ConnectApi.md#list_slack_channels) | **GET** /v1/connect/slack | List Slack channels for the channel picker |
43
44
  | [**list_snapchat_profiles**](ConnectApi.md#list_snapchat_profiles) | **GET** /v1/connect/snapchat/select-profile | List Snapchat profiles |
44
45
  | [**list_whats_app_phone_numbers**](ConnectApi.md#list_whats_app_phone_numbers) | **GET** /v1/connect/whatsapp/select-phone-number | List numbers for selection |
46
+ | [**resync_page_webhook_subscription**](ConnectApi.md#resync_page_webhook_subscription) | **POST** /v1/accounts/{accountId}/webhook-subscription | Re-subscribe a Facebook Page to Zernio&#39;s webhooks |
45
47
  | [**select_facebook_page**](ConnectApi.md#select_facebook_page) | **POST** /v1/connect/facebook/select-page | Select Facebook page |
46
48
  | [**select_google_business_location**](ConnectApi.md#select_google_business_location) | **POST** /v1/connect/googlebusiness/select-location | Select Google Business Profile location |
47
49
  | [**select_instagram_account**](ConnectApi.md#select_instagram_account) | **POST** /v1/connect/instagram/select-account | Select the Page whose Instagram account to connect |
@@ -1362,6 +1364,75 @@ end
1362
1364
  - **Accept**: application/json
1363
1365
 
1364
1366
 
1367
+ ## get_page_webhook_subscription
1368
+
1369
+ > <GetPageWebhookSubscription200Response> get_page_webhook_subscription(account_id)
1370
+
1371
+ Read a Facebook Page's webhook subscription
1372
+
1373
+ Returns the webhook fields Zernio's app is subscribed to on the connected Page, read live from Meta. Use it to confirm `leadgen` is present: a Page missing it keeps delivering every other event while lead ads stop arriving, with nothing to indicate it.
1374
+
1375
+ ### Examples
1376
+
1377
+ ```ruby
1378
+ require 'time'
1379
+ require 'zernio-sdk'
1380
+ # setup authorization
1381
+ Zernio.configure do |config|
1382
+ # Configure Bearer authorization (JWT): bearerAuth
1383
+ config.access_token = 'YOUR_BEARER_TOKEN'
1384
+ end
1385
+
1386
+ api_instance = Zernio::ConnectApi.new
1387
+ account_id = 'account_id_example' # String |
1388
+
1389
+ begin
1390
+ # Read a Facebook Page's webhook subscription
1391
+ result = api_instance.get_page_webhook_subscription(account_id)
1392
+ p result
1393
+ rescue Zernio::ApiError => e
1394
+ puts "Error when calling ConnectApi->get_page_webhook_subscription: #{e}"
1395
+ end
1396
+ ```
1397
+
1398
+ #### Using the get_page_webhook_subscription_with_http_info variant
1399
+
1400
+ This returns an Array which contains the response data, status code and headers.
1401
+
1402
+ > <Array(<GetPageWebhookSubscription200Response>, Integer, Hash)> get_page_webhook_subscription_with_http_info(account_id)
1403
+
1404
+ ```ruby
1405
+ begin
1406
+ # Read a Facebook Page's webhook subscription
1407
+ data, status_code, headers = api_instance.get_page_webhook_subscription_with_http_info(account_id)
1408
+ p status_code # => 2xx
1409
+ p headers # => { ... }
1410
+ p data # => <GetPageWebhookSubscription200Response>
1411
+ rescue Zernio::ApiError => e
1412
+ puts "Error when calling ConnectApi->get_page_webhook_subscription_with_http_info: #{e}"
1413
+ end
1414
+ ```
1415
+
1416
+ ### Parameters
1417
+
1418
+ | Name | Type | Description | Notes |
1419
+ | ---- | ---- | ----------- | ----- |
1420
+ | **account_id** | **String** | | |
1421
+
1422
+ ### Return type
1423
+
1424
+ [**GetPageWebhookSubscription200Response**](GetPageWebhookSubscription200Response.md)
1425
+
1426
+ ### Authorization
1427
+
1428
+ [bearerAuth](../README.md#bearerAuth)
1429
+
1430
+ ### HTTP request headers
1431
+
1432
+ - **Content-Type**: Not defined
1433
+ - **Accept**: application/json
1434
+
1435
+
1365
1436
  ## get_pending_o_auth_data
1366
1437
 
1367
1438
  > <GetPendingOAuthData200Response> get_pending_o_auth_data(token)
@@ -2822,6 +2893,75 @@ end
2822
2893
  - **Accept**: application/json
2823
2894
 
2824
2895
 
2896
+ ## resync_page_webhook_subscription
2897
+
2898
+ > <ResyncPageWebhookSubscription200Response> resync_page_webhook_subscription(account_id)
2899
+
2900
+ Re-subscribe a Facebook Page to Zernio's webhooks
2901
+
2902
+ Re-sends the full field set to Meta and returns the subscription read back afterwards. Meta only honours the field set sent at subscribe time, so a Page connected before a field existed stays without it until this runs. The response reflects what Meta actually granted, not what was requested.
2903
+
2904
+ ### Examples
2905
+
2906
+ ```ruby
2907
+ require 'time'
2908
+ require 'zernio-sdk'
2909
+ # setup authorization
2910
+ Zernio.configure do |config|
2911
+ # Configure Bearer authorization (JWT): bearerAuth
2912
+ config.access_token = 'YOUR_BEARER_TOKEN'
2913
+ end
2914
+
2915
+ api_instance = Zernio::ConnectApi.new
2916
+ account_id = 'account_id_example' # String |
2917
+
2918
+ begin
2919
+ # Re-subscribe a Facebook Page to Zernio's webhooks
2920
+ result = api_instance.resync_page_webhook_subscription(account_id)
2921
+ p result
2922
+ rescue Zernio::ApiError => e
2923
+ puts "Error when calling ConnectApi->resync_page_webhook_subscription: #{e}"
2924
+ end
2925
+ ```
2926
+
2927
+ #### Using the resync_page_webhook_subscription_with_http_info variant
2928
+
2929
+ This returns an Array which contains the response data, status code and headers.
2930
+
2931
+ > <Array(<ResyncPageWebhookSubscription200Response>, Integer, Hash)> resync_page_webhook_subscription_with_http_info(account_id)
2932
+
2933
+ ```ruby
2934
+ begin
2935
+ # Re-subscribe a Facebook Page to Zernio's webhooks
2936
+ data, status_code, headers = api_instance.resync_page_webhook_subscription_with_http_info(account_id)
2937
+ p status_code # => 2xx
2938
+ p headers # => { ... }
2939
+ p data # => <ResyncPageWebhookSubscription200Response>
2940
+ rescue Zernio::ApiError => e
2941
+ puts "Error when calling ConnectApi->resync_page_webhook_subscription_with_http_info: #{e}"
2942
+ end
2943
+ ```
2944
+
2945
+ ### Parameters
2946
+
2947
+ | Name | Type | Description | Notes |
2948
+ | ---- | ---- | ----------- | ----- |
2949
+ | **account_id** | **String** | | |
2950
+
2951
+ ### Return type
2952
+
2953
+ [**ResyncPageWebhookSubscription200Response**](ResyncPageWebhookSubscription200Response.md)
2954
+
2955
+ ### Authorization
2956
+
2957
+ [bearerAuth](../README.md#bearerAuth)
2958
+
2959
+ ### HTTP request headers
2960
+
2961
+ - **Content-Type**: Not defined
2962
+ - **Accept**: application/json
2963
+
2964
+
2825
2965
  ## select_facebook_page
2826
2966
 
2827
2967
  > <SelectFacebookPage200Response> select_facebook_page(select_facebook_page_request)
@@ -6,8 +6,6 @@
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **ad_account_id** | **String** | | [optional] |
8
8
  | **creative_id** | **String** | Platform creative id, reusable via existingCreativeId. | [optional] |
9
- | **promotion** | [**MetaPromotion**](MetaPromotion.md) | | [optional] |
10
- | **promotion_status** | [**MetaPromotionStatus**](MetaPromotionStatus.md) | | [optional] |
11
9
 
12
10
  ## Example
13
11
 
@@ -16,9 +14,7 @@ require 'zernio-sdk'
16
14
 
17
15
  instance = Zernio::CreateAdCreative201Response.new(
18
16
  ad_account_id: null,
19
- creative_id: null,
20
- promotion: null,
21
- promotion_status: null
17
+ creative_id: null
22
18
  )
23
19
  ```
24
20
 
@@ -15,8 +15,8 @@
15
15
  | **image_hash** | **String** | Existing library image hash (POST /v1/ads/images or GET /v1/ads/images). | [optional] |
16
16
  | **carousel_cards** | [**Array&lt;CreateAdCreativeRequestCarouselCardsInner&gt;**](CreateAdCreativeRequestCarouselCardsInner.md) | | [optional] |
17
17
  | **url_tags** | **String** | Appended to every outbound URL (e.g. utm_source&#x3D;fb). | [optional] |
18
- | **promotion** | [**MetaPromotion**](MetaPromotion.md) | | [optional] |
19
- | **creative_features** | **Hash&lt;String, String&gt;** | Meta only. Applied to each new creative, including standalone and attach shapes. With creatives[], these are defaults; an item replaces the whole feature map, including an empty map. auto_promotion_tag is an enhancement; an explicit offer uses promotion. | [optional] |
18
+ | **promotion** | [**Null**](Null.md) | Not supported. Meta validates creative_sourcing_spec.promotion_metadata_spec on the create call and then discards it, so a Promotion set through the Marketing API never reaches the creative. Any object is rejected with 400 invalid_field_value. Send null or omit the field, and set the Promotion on the ad in Ads Manager. Verified on 2026-09-11 across Graph v19.0 to v25.0 and every write path. | [optional] |
19
+ | **creative_features** | **Hash&lt;String, String&gt;** | Meta only. Applied to each new creative, including standalone and attach shapes. With creatives[], these are defaults; an item replaces the whole feature map, including an empty map. auto_promotion_tag is an Advantage+ enhancement, not the Ads Manager Promotion setting. | [optional] |
20
20
  | **multi_advertiser** | **String** | Meta only. Multi-advertiser ads: whether Meta may show this ad alongside other advertisers&#39; in one unit. Meta auto-enrols since Aug 2024, so send OPT_OUT to leave. It is a top-level creative field, NOT a &#x60;creativeFeatures&#x60; key, and Meta rejects it there. | [optional] |
21
21
 
22
22
  ## Example
@@ -16,8 +16,8 @@
16
16
  | **billing_event** | **String** | Meta only. Explicit ad-set &#x60;billing_event&#x60;. Defaults to &#x60;IMPRESSIONS&#x60;. Forwarded verbatim to Meta, which validates compatibility with the optimization goal. | [optional] |
17
17
  | **buying_type** | **String** | Meta only. Defaults to AUCTION and is explicitly sent on new campaigns, including validateOnly. Reusing existingCampaignId does not change the campaign. RESERVED &#x3D; Reach &amp; Frequency: requires &#x60;rfPredictionId&#x60; (a RESERVED prediction from /v1/ads/rf-predictions + /reserve). Budget, schedule and pricing come from the reservation, so budgetAmount/budgetType are not required and bid fields are ignored. Only the plain single-ad shape (no creatives[], adSetId, existingCampaignId or dynamicCreative). | [optional][default to &#39;AUCTION&#39;] |
18
18
  | **rf_prediction_id** | **String** | Meta only. The RESERVED prediction id the R&amp;F ad set runs on (reserving mints a new id, so pass that one). Requires buyingType RESERVED. | [optional] |
19
- | **promotion** | [**MetaPromotion**](MetaPromotion.md) | | [optional] |
20
- | **creative_features** | **Hash&lt;String, String&gt;** | Meta only. Applied to each new creative, including standalone and attach shapes. With creatives[], these are defaults; an item replaces the whole feature map, including an empty map. auto_promotion_tag is an enhancement; an explicit offer uses promotion. | [optional] |
19
+ | **promotion** | [**Null**](Null.md) | Not supported. Meta validates creative_sourcing_spec.promotion_metadata_spec on the create call and then discards it, so a Promotion set through the Marketing API never reaches the creative. Any object is rejected with 400 invalid_field_value. Send null or omit the field, and set the Promotion on the ad in Ads Manager. Verified on 2026-09-11 across Graph v19.0 to v25.0 and every write path. | [optional] |
20
+ | **creative_features** | **Hash&lt;String, String&gt;** | Meta only. Applied to each new creative, including standalone and attach shapes. With creatives[], these are defaults; an item replaces the whole feature map, including an empty map. auto_promotion_tag is an Advantage+ enhancement, not the Ads Manager Promotion setting. | [optional] |
21
21
  | **multi_advertiser** | **String** | Meta only. Multi-advertiser ads: whether Meta may show this ad alongside other advertisers&#39; in one unit. Meta auto-enrols since Aug 2024, so send OPT_OUT to leave. It is a top-level creative field, NOT a &#x60;creativeFeatures&#x60; key, and Meta rejects it there. | [optional] |
22
22
  | **validate_only** | **Boolean** | Google Performance Max validates the complete atomic campaign and asset group with no resource creation or local persistence. Google validation still downloads image URLs and consumes quota. On Meta, validates the complete inline campaign, ad set, creative and ad with execution_options validate_only. Nothing is uploaded or created, and validation bypasses Idempotency-Key storage. Supports a single image, all-image placementAssets with per-rule copy, existing video.id or existingCreativeId; other media pools, new video uploads, creatives[], adSetId and RESERVED buying return 400. Placement validation uses existing Instagram identities only. Existing campaign or creative nodes are marked skipped. Success returns 200 with per-node results; Meta rejection returns an error. | [optional] |
23
23
  | **budget_amount** | **Float** | Budget in WHOLE currency units (USD: 50 &#x3D; $50.00), NOT cents. Meta&#39;s own Marketing API takes this same number in minor units, so it is an easy and expensive mix-up. Required on legacy, multi-creative and Performance Max shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType). | [optional] |
@@ -4,7 +4,6 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **promotion** | [**MetaPromotion**](MetaPromotion.md) | Overrides the top-level offer for this item. Omit to inherit; null disables the inherited offer. | [optional] |
8
7
  | **creative_features** | **Hash&lt;String, String&gt;** | Replaces the entire top-level creativeFeatures map for this item. Omit to inherit; an empty map clears these defaults. | [optional] |
9
8
  | **name** | **String** | Exact name for this ad. Falls back to &#x60;&lt;name&gt; #N&#x60; (N &#x3D; 1-based position). | [optional] |
10
9
  | **headline** | **String** | | |
@@ -21,7 +20,6 @@
21
20
  require 'zernio-sdk'
22
21
 
23
22
  instance = Zernio::CreateStandaloneAdRequestCreativesInner.new(
24
- promotion: null,
25
23
  creative_features: {auto_promotion_tag&#x3D;OPT_IN},
26
24
  name: null,
27
25
  headline: null,
@@ -0,0 +1,26 @@
1
+ # Zernio::GetPageWebhookSubscription200Response
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **page_id** | **String** | | [optional] |
8
+ | **app_subscribed** | **Boolean** | False when the Page carries no subscription for our app at all. | [optional] |
9
+ | **leadgen** | **Boolean** | Whether lead ads submitted on this Page reach Zernio in real time. | [optional] |
10
+ | **subscribed_fields** | **Array&lt;String&gt;** | | [optional] |
11
+ | **warning** | **String** | Present only when leadgen is missing. | [optional] |
12
+
13
+ ## Example
14
+
15
+ ```ruby
16
+ require 'zernio-sdk'
17
+
18
+ instance = Zernio::GetPageWebhookSubscription200Response.new(
19
+ page_id: null,
20
+ app_subscribed: null,
21
+ leadgen: null,
22
+ subscribed_fields: null,
23
+ warning: null
24
+ )
25
+ ```
26
+
@@ -0,0 +1,28 @@
1
+ # Zernio::ResyncPageWebhookSubscription200Response
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **resubscribed** | **Boolean** | | [optional] |
8
+ | **page_id** | **String** | | [optional] |
9
+ | **app_subscribed** | **Boolean** | | [optional] |
10
+ | **leadgen** | **Boolean** | | [optional] |
11
+ | **subscribed_fields** | **Array&lt;String&gt;** | | [optional] |
12
+ | **warning** | **String** | | [optional] |
13
+
14
+ ## Example
15
+
16
+ ```ruby
17
+ require 'zernio-sdk'
18
+
19
+ instance = Zernio::ResyncPageWebhookSubscription200Response.new(
20
+ resubscribed: null,
21
+ page_id: null,
22
+ app_subscribed: null,
23
+ leadgen: null,
24
+ subscribed_fields: null,
25
+ warning: null
26
+ )
27
+ ```
28
+
@@ -4,8 +4,8 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
- | **promotion** | [**MetaPromotion**](MetaPromotion.md) | | [optional] |
8
- | **creative_features** | **Hash&lt;String, String&gt;** | Meta Advantage+ creative enhancements. Map snake_case feature names to OPT_IN or OPT_OUT; Meta validates supported keys and unspecified features default to OPT_OUT. auto_promotion_tag is an enhancement; use the separate promotion field for an explicit offer. The deprecated standard_enhancements bundle is rejected by Meta. | [optional] |
7
+ | **promotion** | [**Null**](Null.md) | Not supported. Meta validates creative_sourcing_spec.promotion_metadata_spec on the create call and then discards it, so a Promotion set through the Marketing API never reaches the creative. Any object is rejected with 400 invalid_field_value. Send null or omit the field, and set the Promotion on the ad in Ads Manager. Verified on 2026-09-11 across Graph v19.0 to v25.0 and every write path. | [optional] |
8
+ | **creative_features** | **Hash&lt;String, String&gt;** | Meta Advantage+ creative enhancements. Map snake_case feature names to OPT_IN or OPT_OUT; Meta validates supported keys and unspecified features default to OPT_OUT. auto_promotion_tag is an Advantage+ enhancement, not the Ads Manager Promotion setting. The deprecated standard_enhancements bundle is rejected by Meta. | [optional] |
9
9
  | **headline** | **String** | Meta and LinkedIn (TikTok has no headline slot) | [optional] |
10
10
  | **long_headline** | **String** | Google Display only. Replaces the responsive display ad&#39;s long headline. | [optional] |
11
11
  | **business_name** | **String** | Google Display only. Replaces the responsive display ad&#39;s business name. | [optional] |
@@ -607,7 +607,7 @@ module Zernio
607
607
  end
608
608
 
609
609
  # Create standalone ad
610
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Google Performance Max: set `campaignType: \"pmax\"` and supply `assetGroup` with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. `validateOnly: true` validates the complete request with Google without creating or persisting resources. Read assets with `GET /v1/ads/campaigns/{campaignId}/asset-groups`. The logo is required; video is optional via `assetGroup.youtubeVideoId`. Brand guidelines are disabled at creation. All supplied asset links are validated together against Google's minimum asset requirements. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS. Other mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `promotion` and `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`. An item replaces the whole feature map; its `promotion` replaces the default offer, and `promotion: null` disables that default for the item. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Only ads supplied a `promotion` receive live readback; multi-create batches those reads in groups of up to 50 IDs without per-ad fallback. Inspect `ad.creative.promotionStatus` (or `ads[].creative.promotionStatus`). `not_returned` means Meta omitted the metadata; successful creation does not by itself prove the offer was applied or will display. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
610
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Google Performance Max: set `campaignType: \"pmax\"` and supply `assetGroup` with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. `validateOnly: true` validates the complete request with Google without creating or persisting resources. Read assets with `GET /v1/ads/campaigns/{campaignId}/asset-groups`. The logo is required; video is optional via `assetGroup.youtubeVideoId`. Brand guidelines are disabled at creation. All supplied asset links are validated together against Google's minimum asset requirements. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS. Other mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`; an item replaces the whole feature map. `promotion` is not supported on any shape and any object is rejected with 400. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
611
611
  # @param create_standalone_ad_request [CreateStandaloneAdRequest]
612
612
  # @param [Hash] opts the optional parameters
613
613
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
@@ -618,7 +618,7 @@ module Zernio
618
618
  end
619
619
 
620
620
  # Create standalone ad
621
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Google Performance Max: set &#x60;campaignType: \&quot;pmax\&quot;&#x60; and supply &#x60;assetGroup&#x60; with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. &#x60;validateOnly: true&#x60; validates the complete request with Google without creating or persisting resources. Read assets with &#x60;GET /v1/ads/campaigns/{campaignId}/asset-groups&#x60;. The logo is required; video is optional via &#x60;assetGroup.youtubeVideoId&#x60;. Brand guidelines are disabled at creation. All supplied asset links are validated together against Google&#39;s minimum asset requirements. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS. Other mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts &#x60;promotion&#x60; and &#x60;creativeFeatures&#x60; on the single and attach shapes and as defaults for &#x60;creatives[]&#x60;. An item replaces the whole feature map; its &#x60;promotion&#x60; replaces the default offer, and &#x60;promotion: null&#x60; disables that default for the item. Reusing &#x60;existingCreativeId&#x60; uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Only ads supplied a &#x60;promotion&#x60; receive live readback; multi-create batches those reads in groups of up to 50 IDs without per-ad fallback. Inspect &#x60;ad.creative.promotionStatus&#x60; (or &#x60;ads[].creative.promotionStatus&#x60;). &#x60;not_returned&#x60; means Meta omitted the metadata; successful creation does not by itself prove the offer was applied or will display. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \&quot;dark post\&quot; authored by a Company Page (see &#x60;organizationId&#x60;). Supported goals are engagement, traffic, awareness, and video_views (video ads use the &#x60;video&#x60; field; video_views requires a video), and traffic ads require &#x60;linkUrl&#x60;. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an &#x60;Idempotency-Key&#x60; header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with &#x60;Idempotent-Replayed: true&#x60;) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
621
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Google Performance Max: set &#x60;campaignType: \&quot;pmax\&quot;&#x60; and supply &#x60;assetGroup&#x60; with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. &#x60;validateOnly: true&#x60; validates the complete request with Google without creating or persisting resources. Read assets with &#x60;GET /v1/ads/campaigns/{campaignId}/asset-groups&#x60;. The logo is required; video is optional via &#x60;assetGroup.youtubeVideoId&#x60;. Brand guidelines are disabled at creation. All supplied asset links are validated together against Google&#39;s minimum asset requirements. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS. Other mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts &#x60;creativeFeatures&#x60; on the single and attach shapes and as defaults for &#x60;creatives[]&#x60;; an item replaces the whole feature map. &#x60;promotion&#x60; is not supported on any shape and any object is rejected with 400. Reusing &#x60;existingCreativeId&#x60; uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \&quot;dark post\&quot; authored by a Company Page (see &#x60;organizationId&#x60;). Supported goals are engagement, traffic, awareness, and video_views (video ads use the &#x60;video&#x60; field; video_views requires a video), and traffic ads require &#x60;linkUrl&#x60;. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an &#x60;Idempotency-Key&#x60; header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with &#x60;Idempotent-Replayed: true&#x60;) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
622
622
  # @param create_standalone_ad_request [CreateStandaloneAdRequest]
623
623
  # @param [Hash] opts the optional parameters
624
624
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
@@ -1121,10 +1121,9 @@ module Zernio
1121
1121
  end
1122
1122
 
1123
1123
  # Get ad details
1124
- # Returns an ad with its creative, targeting, status, and performance metrics. Google Search ads include current creative.headlines, creative.descriptions and creative.finalUrls, preserving pinnedField. Top-level cachedAt and stale report cache freshness. Google mutations invalidate this read. RSA enrichment requires a stored advertisingChannelType of SEARCH. Ads with an unknown or other channel return their stored details without a Google read. If RSA enrichment fails, the stored ad is returned with HTTP 200 and without cache metadata. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step. By default, creative.promotion and creative.creativeFeatures contain stored requested settings, which do not confirm platform application. With `refreshPromotion=true`, Meta promotion metadata is read live and exposed as `ad.creative.promotion` with `promotionStatus`. Only `applied` confirms an offer; `not_returned` means the creative read succeeded without promotion metadata, and `unavailable` means it failed.
1124
+ # Returns an ad with its creative, targeting, status, and performance metrics. Google Search ads include current creative.headlines, creative.descriptions and creative.finalUrls, preserving pinnedField. Top-level cachedAt and stale report cache freshness. Google mutations invalidate this read. RSA enrichment requires a stored advertisingChannelType of SEARCH. Ads with an unknown or other channel return their stored details without a Google read. If RSA enrichment fails, the stored ad is returned with HTTP 200 and without cache metadata. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step. `creative.creativeFeatures` holds the stored requested settings, which do not confirm platform application.
1125
1125
  # @param ad_id [String] Zernio &#x60;_id&#x60; (hex), Meta &#x60;platformAdId&#x60; (numeric), or one of the creative&#39;s effective story/media IDs. See description for details.
1126
1126
  # @param [Hash] opts the optional parameters
1127
- # @option opts [Boolean] :refresh_promotion Meta only. Read current promotion metadata from Meta and include promotionStatus. Omit for stored creative settings with no promotion-specific Graph call. (default to false)
1128
1127
  # @return [GetAd200Response]
1129
1128
  def get_ad(ad_id, opts = {})
1130
1129
  data, _status_code, _headers = get_ad_with_http_info(ad_id, opts)
@@ -1132,10 +1131,9 @@ module Zernio
1132
1131
  end
1133
1132
 
1134
1133
  # Get ad details
1135
- # Returns an ad with its creative, targeting, status, and performance metrics. Google Search ads include current creative.headlines, creative.descriptions and creative.finalUrls, preserving pinnedField. Top-level cachedAt and stale report cache freshness. Google mutations invalidate this read. RSA enrichment requires a stored advertisingChannelType of SEARCH. Ads with an unknown or other channel return their stored details without a Google read. If RSA enrichment fails, the stored ad is returned with HTTP 200 and without cache metadata. The &#x60;{adId}&#x60; path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal &#x60;_id&#x60; (24-char hex) - Meta&#39;s numeric &#x60;platformAdId&#x60; (the value shipped in &#x60;comment.received&#x60; webhooks as &#x60;comment.ad.id&#x60;) - the creative&#39;s &#x60;effective_object_story_id&#x60; (&#x60;{pageId}_{postId}&#x60; shape, Facebook side) - the creative&#39;s &#x60;effective_instagram_media_id&#x60; (Instagram side) Any of the four resolve to the same ad. Caller doesn&#39;t need a translation step. By default, creative.promotion and creative.creativeFeatures contain stored requested settings, which do not confirm platform application. With &#x60;refreshPromotion&#x3D;true&#x60;, Meta promotion metadata is read live and exposed as &#x60;ad.creative.promotion&#x60; with &#x60;promotionStatus&#x60;. Only &#x60;applied&#x60; confirms an offer; &#x60;not_returned&#x60; means the creative read succeeded without promotion metadata, and &#x60;unavailable&#x60; means it failed.
1134
+ # Returns an ad with its creative, targeting, status, and performance metrics. Google Search ads include current creative.headlines, creative.descriptions and creative.finalUrls, preserving pinnedField. Top-level cachedAt and stale report cache freshness. Google mutations invalidate this read. RSA enrichment requires a stored advertisingChannelType of SEARCH. Ads with an unknown or other channel return their stored details without a Google read. If RSA enrichment fails, the stored ad is returned with HTTP 200 and without cache metadata. The &#x60;{adId}&#x60; path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal &#x60;_id&#x60; (24-char hex) - Meta&#39;s numeric &#x60;platformAdId&#x60; (the value shipped in &#x60;comment.received&#x60; webhooks as &#x60;comment.ad.id&#x60;) - the creative&#39;s &#x60;effective_object_story_id&#x60; (&#x60;{pageId}_{postId}&#x60; shape, Facebook side) - the creative&#39;s &#x60;effective_instagram_media_id&#x60; (Instagram side) Any of the four resolve to the same ad. Caller doesn&#39;t need a translation step. &#x60;creative.creativeFeatures&#x60; holds the stored requested settings, which do not confirm platform application.
1136
1135
  # @param ad_id [String] Zernio &#x60;_id&#x60; (hex), Meta &#x60;platformAdId&#x60; (numeric), or one of the creative&#39;s effective story/media IDs. See description for details.
1137
1136
  # @param [Hash] opts the optional parameters
1138
- # @option opts [Boolean] :refresh_promotion Meta only. Read current promotion metadata from Meta and include promotionStatus. Omit for stored creative settings with no promotion-specific Graph call. (default to false)
1139
1137
  # @return [Array<(GetAd200Response, Integer, Hash)>] GetAd200Response data, response status code and response headers
1140
1138
  def get_ad_with_http_info(ad_id, opts = {})
1141
1139
  if @api_client.config.debugging
@@ -1150,7 +1148,6 @@ module Zernio
1150
1148
 
1151
1149
  # query parameters
1152
1150
  query_params = opts[:query_params] || {}
1153
- query_params[:'refreshPromotion'] = opts[:'refresh_promotion'] if !opts[:'refresh_promotion'].nil?
1154
1151
 
1155
1152
  # header parameters
1156
1153
  header_params = opts[:header_params] || {}
@@ -20,7 +20,7 @@ module Zernio
20
20
  @api_client = api_client
21
21
  end
22
22
  # Create a standalone creative
23
- # Creates a creative in the library WITHOUT an ad, reusable on the create endpoints via `existingCreativeId`. Provide exactly one of `imageUrl` (uploaded server-side), `imageHash` (from POST /v1/ads/images or the library list), or `carouselCards` (2-10 hand-built cards). The Page (and linked Instagram account, when present) is resolved from `accountId` as the story actor. `promotion` configures an explicit offer separately from Advantage+ `creativeFeatures`. Only when `promotion` is supplied does the response read the creative back from Meta; `promotionStatus: not_returned` means Meta accepted creation but omitted promotion metadata, so the requested offer is not confirmed as applied.
23
+ # Creates a creative in the library WITHOUT an ad, reusable on the create endpoints via `existingCreativeId`. Provide exactly one of `imageUrl` (uploaded server-side), `imageHash` (from POST /v1/ads/images or the library list), or `carouselCards` (2-10 hand-built cards). The Page (and linked Instagram account, when present) is resolved from `accountId` as the story actor. `creativeFeatures` configures Advantage+ enhancements. `promotion` is not supported and any object is rejected with 400.
24
24
  # @param create_ad_creative_request [CreateAdCreativeRequest]
25
25
  # @param [Hash] opts the optional parameters
26
26
  # @return [CreateAdCreative201Response]
@@ -30,7 +30,7 @@ module Zernio
30
30
  end
31
31
 
32
32
  # Create a standalone creative
33
- # Creates a creative in the library WITHOUT an ad, reusable on the create endpoints via &#x60;existingCreativeId&#x60;. Provide exactly one of &#x60;imageUrl&#x60; (uploaded server-side), &#x60;imageHash&#x60; (from POST /v1/ads/images or the library list), or &#x60;carouselCards&#x60; (2-10 hand-built cards). The Page (and linked Instagram account, when present) is resolved from &#x60;accountId&#x60; as the story actor. &#x60;promotion&#x60; configures an explicit offer separately from Advantage+ &#x60;creativeFeatures&#x60;. Only when &#x60;promotion&#x60; is supplied does the response read the creative back from Meta; &#x60;promotionStatus: not_returned&#x60; means Meta accepted creation but omitted promotion metadata, so the requested offer is not confirmed as applied.
33
+ # Creates a creative in the library WITHOUT an ad, reusable on the create endpoints via &#x60;existingCreativeId&#x60;. Provide exactly one of &#x60;imageUrl&#x60; (uploaded server-side), &#x60;imageHash&#x60; (from POST /v1/ads/images or the library list), or &#x60;carouselCards&#x60; (2-10 hand-built cards). The Page (and linked Instagram account, when present) is resolved from &#x60;accountId&#x60; as the story actor. &#x60;creativeFeatures&#x60; configures Advantage+ enhancements. &#x60;promotion&#x60; is not supported and any object is rejected with 400.
34
34
  # @param create_ad_creative_request [CreateAdCreativeRequest]
35
35
  # @param [Hash] opts the optional parameters
36
36
  # @return [Array<(CreateAdCreative201Response, Integer, Hash)>] CreateAdCreative201Response data, response status code and response headers