late-sdk 0.0.897 → 0.0.899

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/docs/AdCampaignsApi.md +11 -7
  4. data/docs/AdCreative.md +4 -0
  5. data/docs/AdCreativesApi.md +2 -2
  6. data/docs/BoostPostRequest.md +2 -0
  7. data/docs/CreateAdCreative201Response.md +5 -1
  8. data/docs/CreateAdCreativeRequest.md +4 -2
  9. data/docs/CreateCallAdRequest.md +2 -0
  10. data/docs/CreateMessagingAdRequest.md +2 -0
  11. data/docs/CreateStandaloneAdRequest.md +5 -3
  12. data/docs/CreateStandaloneAdRequestCreativesInner.md +4 -0
  13. data/docs/CreateStandaloneAdRequestPromotedObject.md +2 -2
  14. data/docs/CtwaAdRequestBody.md +2 -0
  15. data/docs/CtwaAdRequestBodyCreativesInner.md +2 -0
  16. data/docs/MetaPromotion.md +26 -0
  17. data/docs/MetaPromotionStatus.md +15 -0
  18. data/docs/UpdateAdRequestCreative.md +4 -0
  19. data/lib/zernio-sdk/api/ad_campaigns_api.rb +9 -6
  20. data/lib/zernio-sdk/api/ad_creatives_api.rb +4 -4
  21. data/lib/zernio-sdk/models/ad_creative.rb +42 -1
  22. data/lib/zernio-sdk/models/boost_post_request.rb +13 -1
  23. data/lib/zernio-sdk/models/create_ad_creative201_response.rb +44 -4
  24. data/lib/zernio-sdk/models/create_ad_creative_request.rb +11 -2
  25. data/lib/zernio-sdk/models/create_call_ad_request.rb +13 -1
  26. data/lib/zernio-sdk/models/create_messaging_ad_request.rb +13 -1
  27. data/lib/zernio-sdk/models/create_standalone_ad_request.rb +12 -3
  28. data/lib/zernio-sdk/models/create_standalone_ad_request_creatives_inner.rb +23 -1
  29. data/lib/zernio-sdk/models/create_standalone_ad_request_dynamic_creative.rb +1 -1
  30. data/lib/zernio-sdk/models/create_standalone_ad_request_promoted_object.rb +2 -2
  31. data/lib/zernio-sdk/models/ctwa_ad_request_body.rb +13 -1
  32. data/lib/zernio-sdk/models/ctwa_ad_request_body_creatives_inner.rb +35 -1
  33. data/lib/zernio-sdk/models/meta_promotion.rb +275 -0
  34. data/lib/zernio-sdk/models/meta_promotion_status.rb +41 -0
  35. data/lib/zernio-sdk/models/update_ad_request_creative.rb +45 -2
  36. data/lib/zernio-sdk/version.rb +1 -1
  37. data/lib/zernio-sdk.rb +2 -0
  38. data/openapi.yaml +132 -13
  39. data/spec/api/ad_campaigns_api_spec.rb +4 -3
  40. data/spec/api/ad_creatives_api_spec.rb +2 -2
  41. data/spec/models/ad_creative_spec.rb +12 -0
  42. data/spec/models/boost_post_request_spec.rb +10 -0
  43. data/spec/models/create_ad_creative201_response_spec.rb +12 -0
  44. data/spec/models/create_ad_creative_request_spec.rb +6 -0
  45. data/spec/models/create_call_ad_request_spec.rb +10 -0
  46. data/spec/models/create_messaging_ad_request_spec.rb +10 -0
  47. data/spec/models/create_standalone_ad_request_creatives_inner_spec.rb +16 -0
  48. data/spec/models/create_standalone_ad_request_spec.rb +6 -0
  49. data/spec/models/ctwa_ad_request_body_creatives_inner_spec.rb +10 -0
  50. data/spec/models/ctwa_ad_request_body_spec.rb +10 -0
  51. data/spec/models/meta_promotion_spec.rb +64 -0
  52. data/spec/models/meta_promotion_status_spec.rb +30 -0
  53. data/spec/models/update_ad_request_creative_spec.rb +16 -0
  54. data/zernio-sdk-0.0.899.gem +0 -0
  55. metadata +10 -2
  56. data/zernio-sdk-0.0.897.gem +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8958df8e529d3c1779b84996c2f7e9f7985383f539b208fb1f869d34e694cad
4
- data.tar.gz: 2f7e91e736793f88f5e4c701ce037238c1cb4edd3144bded727e208d0d88dd50
3
+ metadata.gz: f1fe40764a586fc0337945b4adb251032343ea0ce91994b80288c687805230e5
4
+ data.tar.gz: ff9af29348094b89309c7ee7136ddc041ffae14eb880268f47ba6b3651c1eefd
5
5
  SHA512:
6
- metadata.gz: 4e406e07e57829db26c0942af4dbda76c8b3f9c13828016ffd77acf85775bdd552574932080334446e2d4c880b022d4d3b47a2daf21ad809475d0c233a6d5c92
7
- data.tar.gz: 16fa3ec320abc933c0ca307dab57bcda3cbb573ad115275f1e952f9e22edc4cf9ae275f7ad0b55cfce8d38a5d8ed64944fcdd26b2a418984fafcde85b4b279fc
6
+ metadata.gz: 61205f71c1173b26f4f3f7086a5ffd4ffaf39c5aaec6bc283e32aceb66282025a302e16903a01362a582c98229d190ecb94fff351181e042c46593034b73ecef
7
+ data.tar.gz: bb681fb5b0cd796f8da6f54a94e77ddcdec2d93b50d8bb6df3995e909766f60890cb8da9563d182f2c5c6a884a22aa21b6ac6e63e3d4c6aa2d78a0dd3967443f
data/README.md CHANGED
@@ -1949,6 +1949,8 @@ Class | Method | HTTP request | Description
1949
1949
  - [Zernio::MetaAdsPlatformData](docs/MetaAdsPlatformData.md)
1950
1950
  - [Zernio::MetaLeadFormPlatformData](docs/MetaLeadFormPlatformData.md)
1951
1951
  - [Zernio::MetaLeadFormPlatformDataContextCard](docs/MetaLeadFormPlatformDataContextCard.md)
1952
+ - [Zernio::MetaPromotion](docs/MetaPromotion.md)
1953
+ - [Zernio::MetaPromotionStatus](docs/MetaPromotionStatus.md)
1952
1954
  - [Zernio::Money](docs/Money.md)
1953
1955
  - [Zernio::MoneyAmount](docs/MoneyAmount.md)
1954
1956
  - [Zernio::MoveAccountToProfile200Response](docs/MoveAccountToProfile200Response.md)
@@ -548,7 +548,7 @@ end
548
548
 
549
549
  Create standalone ad
550
550
 
551
- Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. 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.
551
+ Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `promotion` and `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`. An item replaces the whole feature map; its `promotion` replaces the default offer, and `promotion: null` disables that default for the item. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Only ads supplied a `promotion` receive live readback; multi-create batches those reads in groups of up to 50 IDs without per-ad fallback. Inspect `ad.creative.promotionStatus` (or `ads[].creative.promotionStatus`). `not_returned` means Meta omitted the metadata; successful creation does not by itself prove the offer was applied or will display. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
552
552
 
553
553
  ### Examples
554
554
 
@@ -830,7 +830,7 @@ end
830
830
 
831
831
  Duplicate an ad
832
832
 
833
- Duplicates a single ad via Meta's native `POST /{ad-id}/copies`. The copy is created paused. `adSetId` retargets the copy into another ad set; omitted = the source's own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (`syncAfter: false` to skip).
833
+ Duplicates a single ad via Meta's native `POST /{ad-id}/copies`. The copy is created paused. `adSetId` retargets the copy into another ad set; omitted = the source's own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (`syncAfter: false` to skip). Creative settings returned by Meta, including explicit promotion metadata and creativeFeatures, are preserved when the native copy requires a creative rebuild. Metadata Meta does not return cannot be recovered.
834
834
 
835
835
  ### Examples
836
836
 
@@ -1051,11 +1051,11 @@ end
1051
1051
 
1052
1052
  ## get_ad
1053
1053
 
1054
- > <GetAd200Response> get_ad(ad_id)
1054
+ > <GetAd200Response> get_ad(ad_id, opts)
1055
1055
 
1056
1056
  Get ad details
1057
1057
 
1058
- Returns an ad with its creative, targeting, status, and performance metrics. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step.
1058
+ Returns an ad with its creative, targeting, status, and performance metrics. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step. 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.
1059
1059
 
1060
1060
  ### Examples
1061
1061
 
@@ -1070,10 +1070,13 @@ end
1070
1070
 
1071
1071
  api_instance = Zernio::AdCampaignsApi.new
1072
1072
  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.
1073
+ opts = {
1074
+ 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.
1075
+ }
1073
1076
 
1074
1077
  begin
1075
1078
  # Get ad details
1076
- result = api_instance.get_ad(ad_id)
1079
+ result = api_instance.get_ad(ad_id, opts)
1077
1080
  p result
1078
1081
  rescue Zernio::ApiError => e
1079
1082
  puts "Error when calling AdCampaignsApi->get_ad: #{e}"
@@ -1084,12 +1087,12 @@ end
1084
1087
 
1085
1088
  This returns an Array which contains the response data, status code and headers.
1086
1089
 
1087
- > <Array(<GetAd200Response>, Integer, Hash)> get_ad_with_http_info(ad_id)
1090
+ > <Array(<GetAd200Response>, Integer, Hash)> get_ad_with_http_info(ad_id, opts)
1088
1091
 
1089
1092
  ```ruby
1090
1093
  begin
1091
1094
  # Get ad details
1092
- data, status_code, headers = api_instance.get_ad_with_http_info(ad_id)
1095
+ data, status_code, headers = api_instance.get_ad_with_http_info(ad_id, opts)
1093
1096
  p status_code # => 2xx
1094
1097
  p headers # => { ... }
1095
1098
  p data # => <GetAd200Response>
@@ -1103,6 +1106,7 @@ end
1103
1106
  | Name | Type | Description | Notes |
1104
1107
  | ---- | ---- | ----------- | ----- |
1105
1108
  | **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. | |
1109
+ | **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] |
1106
1110
 
1107
1111
  ### Return type
1108
1112
 
data/docs/AdCreative.md CHANGED
@@ -8,6 +8,8 @@
8
8
  | **image_url** | **String** | Alternative image URL | [optional] |
9
9
  | **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] |
10
10
  | **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] |
11
+ | **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] |
12
+ | **promotion_status** | [**MetaPromotionStatus**](MetaPromotionStatus.md) | | [optional] |
11
13
  | **creative_id** | **String** | Meta ad creative id backing this ad. Reusable via existingCreativeId on POST /v1/ads/create. | [optional] |
12
14
  | **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] |
13
15
  | **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] |
@@ -38,6 +40,8 @@ instance = Zernio::AdCreative.new(
38
40
  image_url: null,
39
41
  video_id: null,
40
42
  video_url: null,
43
+ promotion: null,
44
+ promotion_status: null,
41
45
  creative_id: null,
42
46
  object_type: null,
43
47
  object_story_id: null,
@@ -27,7 +27,7 @@ All URIs are relative to *https://zernio.com/api*
27
27
 
28
28
  Create a standalone creative
29
29
 
30
- 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.
30
+ 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.
31
31
 
32
32
  ### Examples
33
33
 
@@ -526,7 +526,7 @@ end
526
526
 
527
527
  List a catalog's product sets
528
528
 
529
- Lists a Meta product catalog's product sets, the unit a catalog ad promotes. Pass the chosen set as `promotedObject.productSetId` on POST /v1/ads/create with `goal: catalog_sales`.
529
+ Lists a Meta product catalog's product sets, the unit a catalog ad promotes. Pass the chosen set id, not the parent catalog id, as `promotedObject.productSetId` on POST /v1/ads/create with `goal: catalog_sales`. Creation verifies set visibility and returns 400 for a catalog id or an inaccessible set.
530
530
 
531
531
  ### Examples
532
532
 
@@ -4,6 +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
8
  | **post_id** | **String** | Zernio post ID (provide this or platformPostId) | [optional] |
8
9
  | **platform_post_id** | **String** | Platform post ID (alternative to postId) | [optional] |
9
10
  | **account_id** | **String** | Account ID | |
@@ -43,6 +44,7 @@
43
44
  require 'zernio-sdk'
44
45
 
45
46
  instance = Zernio::BoostPostRequest.new(
47
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
46
48
  post_id: null,
47
49
  platform_post_id: null,
48
50
  account_id: null,
@@ -6,6 +6,8 @@
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] |
9
11
 
10
12
  ## Example
11
13
 
@@ -14,7 +16,9 @@ require 'zernio-sdk'
14
16
 
15
17
  instance = Zernio::CreateAdCreative201Response.new(
16
18
  ad_account_id: null,
17
- creative_id: null
19
+ creative_id: null,
20
+ promotion: null,
21
+ promotion_status: null
18
22
  )
19
23
  ```
20
24
 
@@ -15,7 +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
- | **creative_features** | **Hash&lt;String, String&gt;** | Advantage+ creative enhancements: partial map of Meta creative feature keys (snake_case) to enroll status, forwarded as degrees_of_freedom_spec.creative_features_spec. Unspecified features default to OPT_OUT. | [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] |
19
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] |
20
21
 
21
22
  ## Example
@@ -35,7 +36,8 @@ instance = Zernio::CreateAdCreativeRequest.new(
35
36
  image_hash: null,
36
37
  carousel_cards: null,
37
38
  url_tags: null,
38
- creative_features: null,
39
+ promotion: null,
40
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
39
41
  multi_advertiser: null
40
42
  )
41
43
  ```
@@ -4,6 +4,7 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
+ | **creative_features** | **Hash&lt;String, String&gt;** | Meta enhancement settings for single or attached ads, and defaults for creatives[]. An item replaces the entire map, including with an empty object. | [optional] |
7
8
  | **account_id** | **String** | Facebook or Instagram SocialAccount ID. | |
8
9
  | **ad_account_id** | **String** | Meta ad account ID, e.g. &#x60;act_123456789&#x60;. | |
9
10
  | **name** | **String** | Ad display name. Used to derive campaign / ad set names. On the multi-creative shape, each ad&#39;s Meta name gets a \&quot; #N\&quot; suffix (1-indexed) so Ads Manager shows them as a numbered batch. | |
@@ -52,6 +53,7 @@
52
53
  require 'zernio-sdk'
53
54
 
54
55
  instance = Zernio::CreateCallAdRequest.new(
56
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
55
57
  account_id: null,
56
58
  ad_account_id: null,
57
59
  name: null,
@@ -4,6 +4,7 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
+ | **creative_features** | **Hash&lt;String, String&gt;** | Meta enhancement settings for single or attached ads, and defaults for creatives[]. An item replaces the entire map, including with an empty object. | [optional] |
7
8
  | **account_id** | **String** | Facebook or Instagram SocialAccount ID. | |
8
9
  | **ad_account_id** | **String** | Meta ad account ID, e.g. &#x60;act_123456789&#x60;. | |
9
10
  | **name** | **String** | Ad display name. Used to derive campaign / ad set names. On the multi-creative shape, each ad&#39;s Meta name gets a \&quot; #N\&quot; suffix (1-indexed) so Ads Manager shows them as a numbered batch. | |
@@ -51,6 +52,7 @@
51
52
  require 'zernio-sdk'
52
53
 
53
54
  instance = Zernio::CreateMessagingAdRequest.new(
55
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
54
56
  account_id: null,
55
57
  ad_account_id: null,
56
58
  name: null,
@@ -16,7 +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. 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] |
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
- | **creative_features** | **Hash&lt;String, String&gt;** | Meta only. Advantage+ creative enhancements: a partial map of Meta creative feature keys (snake_case, e.g. enhance_cta, image_brightness_and_contrast, text_optimizations) to enroll status, forwarded as degrees_of_freedom_spec.creative_features_spec. Meta validates the keys; unspecified features default to OPT_OUT. The legacy standard_enhancements bundle is deprecated by Meta and rejected. | [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] |
20
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] |
21
22
  | **validate_only** | **Boolean** | Meta only, single standalone shape only (no creatives[], adSetId, or RESERVED). Dry-run: each node runs Meta&#39;s execution_options validate_only and NOTHING is created or persisted. Children need real parents, so a fresh tree validates the campaign + creative (the ad set needs its campaign to exist, so pass existingCampaignId to validate it too; the ad itself is never validatable pre-create). A Meta validation failure returns the 400 verbatim; success returns 200 with per-node results instead of an ad. | [optional] |
22
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 shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType). | [optional] |
@@ -39,7 +40,7 @@
39
40
  | **images** | [**CreateStandaloneAdRequestImages**](CreateStandaloneAdRequestImages.md) | | [optional] |
40
41
  | **video** | [**CreateStandaloneAdRequestVideo**](CreateStandaloneAdRequestVideo.md) | | [optional] |
41
42
  | **creatives** | [**Array&lt;CreateStandaloneAdRequestCreativesInner&gt;**](CreateStandaloneAdRequestCreativesInner.md) | Meta-only. When present, switches to the multi-creative shape: creates 1 campaign + 1 ad set + N ads (one per entry here). Top-level &#x60;headline&#x60; / &#x60;body&#x60; / &#x60;imageUrl&#x60; / &#x60;linkUrl&#x60; / &#x60;callToAction&#x60; are ignored in this mode. Mutually exclusive with &#x60;adSetId&#x60;. | [optional] |
42
- | **ad_set_id** | **String** | When present, switches to the attach shape: adds one new ad to this existing ad set without creating a new campaign. Budget, targeting, goal, schedule, AND bid strategy are inherited from the ad set on Meta, and passing &#x60;bidStrategy&#x60; in attach mode returns 400. To change an existing ad set&#39;s bid, use &#x60;PUT /v1/ads/ad-sets/{adSetId}&#x60;. Mutually exclusive with &#x60;creatives[]&#x60;. The attached ad takes the full single-creative surface: &#x60;headline&#x60;/&#x60;body&#x60;/&#x60;description&#x60;/&#x60;callToAction&#x60; plus either &#x60;imageUrl&#x60;/&#x60;video&#x60; OR &#x60;placementAssets&#x60; (its own per-placement Feed/Story assets) OR &#x60;translations&#x60;/&#x60;defaultLocale&#x60; (its own per-locale asset feed, Meta only), and &#x60;leadGenFormId&#x60; when the target is a lead ad set (the parent must be ON_AD, true for ad sets created via goal &#x60;lead_generation&#x60;; Meta rejects a formless ad there, so pass the form on EVERY attached ad). This is the way to build N full ads sharing one ad set: create the first ad via the normal shape, then attach the rest one call each. Supported on Meta (facebook, instagram), Google Ads, TikTok, and LinkedIn. On TikTok the &#x60;adSetId&#x60; is the ad group ID; the new ad inherits the ad group&#39;s bid + budget + targeting. On LinkedIn the &#x60;adSetId&#x60; is the LinkedIn Campaign ID (numeric); we attach a new Creative to that Campaign, so the Campaign&#39;s &#x60;platformSpecificData&#x60; bidding, targeting, budget and schedule are inherited (passing those fields returns 400). On Google Ads the &#x60;adSetId&#x60; is the AD GROUP id. &#x60;goal&#x60; is still REQUIRED even though budget and targeting are inherited from the ad group. Send &#x60;campaignType: \&quot;search\&quot;&#x60; to attach into a Search ad group, including one created by &#x60;POST /v1/ads/ad-sets&#x60; (always SEARCH_STANDARD): without it the request is treated as Display and requires &#x60;images.landscape&#x60; + &#x60;images.square&#x60; + &#x60;businessName&#x60;, and the resulting display creative does not match a Search ad group. &#x60;budgetAmount&#x60;/&#x60;budgetType&#x60; and bidding fields (&#x60;bidStrategy&#x60;, &#x60;bidAmount&#x60;, &#x60;portfolioBidStrategyId&#x60;) return 400 on this shape; the ad group already owns them. | [optional] |
43
+ | **ad_set_id** | **String** | When present, switches to the attach shape: adds one new ad to this existing ad set without creating a new campaign. Budget, targeting, goal, schedule, AND bid strategy are inherited from the ad set on Meta, and passing &#x60;bidStrategy&#x60; in attach mode returns 400. To change an existing ad set&#39;s bid, use &#x60;PUT /v1/ads/ad-sets/{adSetId}&#x60;. Mutually exclusive with &#x60;creatives[]&#x60;. &#x60;dynamicCreative&#x60; returns 400 in attach mode: create a new dynamic ad set by omitting &#x60;adSetId&#x60; instead. The attached ad takes the full single-creative surface: &#x60;headline&#x60;/&#x60;body&#x60;/&#x60;description&#x60;/&#x60;callToAction&#x60; plus either &#x60;imageUrl&#x60;/&#x60;video&#x60; OR &#x60;placementAssets&#x60; (its own per-placement Feed/Story assets) OR &#x60;translations&#x60;/&#x60;defaultLocale&#x60; (its own per-locale asset feed, Meta only), and &#x60;leadGenFormId&#x60; when the target is a lead ad set (the parent must be ON_AD, true for ad sets created via goal &#x60;lead_generation&#x60;; Meta rejects a formless ad there, so pass the form on EVERY attached ad). This is the way to build N full ads sharing one ad set: create the first ad via the normal shape, then attach the rest one call each. Supported on Meta (facebook, instagram), Google Ads, TikTok, and LinkedIn. On TikTok the &#x60;adSetId&#x60; is the ad group ID; the new ad inherits the ad group&#39;s bid + budget + targeting. On LinkedIn the &#x60;adSetId&#x60; is the LinkedIn Campaign ID (numeric); we attach a new Creative to that Campaign, so the Campaign&#39;s &#x60;platformSpecificData&#x60; bidding, targeting, budget and schedule are inherited (passing those fields returns 400). On Google Ads the &#x60;adSetId&#x60; is the AD GROUP id. &#x60;goal&#x60; is still REQUIRED even though budget and targeting are inherited from the ad group. Send &#x60;campaignType: \&quot;search\&quot;&#x60; to attach into a Search ad group, including one created by &#x60;POST /v1/ads/ad-sets&#x60; (always SEARCH_STANDARD): without it the request is treated as Display and requires &#x60;images.landscape&#x60; + &#x60;images.square&#x60; + &#x60;businessName&#x60;, and the resulting display creative does not match a Search ad group. &#x60;budgetAmount&#x60;/&#x60;budgetType&#x60; and bidding fields (&#x60;bidStrategy&#x60;, &#x60;bidAmount&#x60;, &#x60;portfolioBidStrategyId&#x60;) return 400 on this shape; the ad group already owns them. | [optional] |
43
44
  | **existing_campaign_id** | **String** | Meta, Google Ads, and LinkedIn. On Meta: add the new ad set under this EXISTING campaign instead of creating a new one (multi-ad-set audience testing). The new ad set&#39;s budget is matched to the campaign&#39;s mode automatically: for a CBO campaign (campaign-level budget) omit &#x60;budgetAmount&#x60;/&#x60;budgetType&#x60;, since the campaign owns the budget; for an ABO campaign pass them (they go on the new ad set). On LinkedIn: create a new Campaign (and its Creative) under this EXISTING CampaignGroup. On Google Ads: create a new ad group under this EXISTING campaign; the new ad group inherits the campaign&#39;s budget, so omit &#x60;budgetAmount&#x60;/&#x60;budgetType&#x60; (and any bidding field), or the request returns 400. On failure only the entities we authored are cleaned up; the pre-existing parent is left untouched and is never (re)activated. Mutually exclusive with &#x60;adSetId&#x60; and &#x60;creatives[]&#x60;. | [optional] |
44
45
  | **existing_creative_id** | **String** | Meta only. Reuse an EXISTING ad creative by id instead of building a new one from the copy/media fields (which are then ignored). Combine with &#x60;existingCampaignId&#x60; to build a multi-ad-set campaign that shares one creative. Mutually exclusive with &#x60;creatives[]&#x60;, &#x60;dynamicCreative&#x60;, and &#x60;placementAssets&#x60;. The creative id used is returned as &#x60;creativeId&#x60; on the create response. | [optional] |
45
46
  | **business_name** | **String** | Google Display only | [optional] |
@@ -121,7 +122,8 @@ instance = Zernio::CreateStandaloneAdRequest.new(
121
122
  billing_event: null,
122
123
  buying_type: null,
123
124
  rf_prediction_id: null,
124
- creative_features: null,
125
+ promotion: null,
126
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
125
127
  multi_advertiser: null,
126
128
  validate_only: null,
127
129
  budget_amount: null,
@@ -4,6 +4,8 @@
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
+ | **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] |
7
9
  | **name** | **String** | Exact name for this ad. Falls back to &#x60;&lt;name&gt; #N&#x60; (N &#x3D; 1-based position). | [optional] |
8
10
  | **headline** | **String** | | |
9
11
  | **body** | **String** | | |
@@ -19,6 +21,8 @@
19
21
  require 'zernio-sdk'
20
22
 
21
23
  instance = Zernio::CreateStandaloneAdRequestCreativesInner.new(
24
+ promotion: null,
25
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
22
26
  name: null,
23
27
  headline: null,
24
28
  body: null,
@@ -11,8 +11,8 @@
11
11
  | **application_id** | **String** | App ID. Required for &#x60;goal: app_promotion&#x60;. | [optional] |
12
12
  | **object_store_url** | **String** | App Store / Play Store listing URL. Required for &#x60;goal: app_promotion&#x60;. | [optional] |
13
13
  | **custom_conversion_id** | **String** | Custom Conversion ID, when optimising against one instead of a standard event. Accepted alone by this API, without &#x60;pixelId&#x60; or &#x60;customEventType&#x60;. If &#x60;pixelId&#x60; is also sent, &#x60;customEventType&#x60; is still required on the promoted_object (Meta rejects &#x60;pixel_id&#x60; without &#x60;custom_event_type&#x60;, error_subcode 1885014). | [optional] |
14
- | **product_catalog_id** | **String** | Catalog ID for catalog/Advantage+ Shopping campaigns. | [optional] |
15
- | **product_set_id** | **String** | Product Set ID inside the catalog. | [optional] |
14
+ | **product_catalog_id** | **String** | Optional catalog ID. If supplied with productSetId, the set must belong to this catalog. A catalog ID cannot replace productSetId. | [optional] |
15
+ | **product_set_id** | **String** | Meta product SET ID from GET /v1/ads/catalogs/{catalogId}/product-sets. Zernio checks that the token can read the set and its product_catalog before creation. A catalog ID or inaccessible set returns a precise 400 naming promotedObject.productSetId. A mismatch with productCatalogId names promotedObject.productCatalogId. | [optional] |
16
16
  | **offline_conversion_data_set_id** | **String** | Meta only. Offline event set (dataset) to optimise toward. Post-merger these are datasets: the id is the dataset id (for pixel-backed datasets, the pixel id). | [optional] |
17
17
  | **whatsapp_phone_number** | **String** | Meta only. WhatsApp number on messaging-destination ad sets. | [optional] |
18
18
 
@@ -4,6 +4,7 @@
4
4
 
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
+ | **creative_features** | **Hash&lt;String, String&gt;** | Meta enhancement settings for single or attached ads, and defaults for creatives[]. An item replaces the entire map, including with an empty object. | [optional] |
7
8
  | **account_id** | **String** | Facebook or Instagram SocialAccount ID. | |
8
9
  | **ad_account_id** | **String** | Meta ad account ID, e.g. &#x60;act_123456789&#x60;. | |
9
10
  | **name** | **String** | Ad display name. Used to derive campaign / ad set names. On the multi-creative shape, each ad&#39;s Meta name gets a \&quot; #N\&quot; suffix (1-indexed) so Ads Manager shows them as a numbered batch. | |
@@ -50,6 +51,7 @@
50
51
  require 'zernio-sdk'
51
52
 
52
53
  instance = Zernio::CtwaAdRequestBody.new(
54
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
53
55
  account_id: null,
54
56
  ad_account_id: null,
55
57
  name: null,
@@ -6,6 +6,7 @@
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **existing_post_id** | **String** | Messaging and CTWA only. Platform post or reel ID, resolved like boost platformPostId. Facebook IDs become object_story_id; Instagram IDs become source_instagram_media_id using the connected Instagram identity. Mutually exclusive with objectStoryId and fresh creative fields. | [optional] |
8
8
  | **object_story_id** | **String** | Messaging and CTWA only. Raw Facebook pageId_postId reference, used as object_story_id even with an Instagram account. Mutually exclusive with existingPostId and fresh creative fields. | [optional] |
9
+ | **creative_features** | **Hash&lt;String, String&gt;** | Replaces the top-level creativeFeatures map for this item. Omit to inherit; an empty object clears inherited enrollment choices. | [optional] |
9
10
  | **headline** | **String** | | [optional] |
10
11
  | **body** | **String** | Primary text shown above the image / video. | [optional] |
11
12
  | **image_url** | **String** | Image asset. Mutually exclusive with this entry&#39;s &#x60;video&#x60;. Required if neither &#x60;video&#x60; nor an existing post reference is supplied. | [optional] |
@@ -20,6 +21,7 @@ require 'zernio-sdk'
20
21
  instance = Zernio::CtwaAdRequestBodyCreativesInner.new(
21
22
  existing_post_id: null,
22
23
  object_story_id: null,
24
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
23
25
  headline: null,
24
26
  body: null,
25
27
  image_url: null,
@@ -0,0 +1,26 @@
1
+ # Zernio::MetaPromotion
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **type** | **String** | Promotion type accepted by Meta. PERCENTAGE_OFF values cannot exceed 100. | |
8
+ | **value** | **Float** | Nonnegative promotion value passed to Meta unchanged. AMOUNT_OFF units are not confirmed, including major versus minor currency units. For PERCENTAGE_OFF this is the percentage discount, at most 100. | |
9
+ | **code** | **String** | Optional promotion code. | [optional] |
10
+ | **start_date** | **Time** | Optional ISO 8601 start timestamp with a timezone offset or Z. | [optional] |
11
+ | **end_date** | **Time** | Optional ISO 8601 end timestamp with a timezone offset or Z. Must be after startDate when both are set. | [optional] |
12
+
13
+ ## Example
14
+
15
+ ```ruby
16
+ require 'zernio-sdk'
17
+
18
+ instance = Zernio::MetaPromotion.new(
19
+ type: null,
20
+ value: null,
21
+ code: null,
22
+ start_date: null,
23
+ end_date: null
24
+ )
25
+ ```
26
+
@@ -0,0 +1,15 @@
1
+ # Zernio::MetaPromotionStatus
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+
8
+ ## Example
9
+
10
+ ```ruby
11
+ require 'zernio-sdk'
12
+
13
+ instance = Zernio::MetaPromotionStatus.new()
14
+ ```
15
+
@@ -4,6 +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
9
  | **headline** | **String** | Meta and LinkedIn (TikTok has no headline slot) | [optional] |
8
10
  | **body** | **String** | | [optional] |
9
11
  | **description** | **String** | Link description slot (Meta &#x60;link_data.description&#x60; / &#x60;video_data.link_description&#x60;, LinkedIn creative description). | [optional] |
@@ -20,6 +22,8 @@
20
22
  require 'zernio-sdk'
21
23
 
22
24
  instance = Zernio::UpdateAdRequestCreative.new(
25
+ promotion: null,
26
+ creative_features: {auto_promotion_tag&#x3D;OPT_IN},
23
27
  headline: null,
24
28
  body: null,
25
29
  description: null,
@@ -523,7 +523,7 @@ module Zernio
523
523
  end
524
524
 
525
525
  # Create standalone ad
526
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. 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.
526
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts `promotion` and `creativeFeatures` on the single and attach shapes and as defaults for `creatives[]`. An item replaces the whole feature map; its `promotion` replaces the default offer, and `promotion: null` disables that default for the item. Reusing `existingCreativeId` uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads. Only ads supplied a `promotion` receive live readback; multi-create batches those reads in groups of up to 50 IDs without per-ad fallback. Inspect `ad.creative.promotionStatus` (or `ads[].creative.promotionStatus`). `not_returned` means Meta omitted the metadata; successful creation does not by itself prove the offer was applied or will display. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
527
527
  # @param create_standalone_ad_request [CreateStandaloneAdRequest]
528
528
  # @param [Hash] opts the optional parameters
529
529
  # @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.
@@ -534,7 +534,7 @@ module Zernio
534
534
  end
535
535
 
536
536
  # Create standalone ad
537
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. 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.
537
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Meta accepts &#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.
538
538
  # @param create_standalone_ad_request [CreateStandaloneAdRequest]
539
539
  # @param [Hash] opts the optional parameters
540
540
  # @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.
@@ -798,7 +798,7 @@ module Zernio
798
798
  end
799
799
 
800
800
  # Duplicate an ad
801
- # Duplicates a single ad via Meta's native `POST /{ad-id}/copies`. The copy is created paused. `adSetId` retargets the copy into another ad set; omitted = the source's own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (`syncAfter: false` to skip).
801
+ # Duplicates a single ad via Meta's native `POST /{ad-id}/copies`. The copy is created paused. `adSetId` retargets the copy into another ad set; omitted = the source's own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (`syncAfter: false` to skip). Creative settings returned by Meta, including explicit promotion metadata and creativeFeatures, are preserved when the native copy requires a creative rebuild. Metadata Meta does not return cannot be recovered.
802
802
  # @param ad_id [String] Zernio ad ID or platform ad ID
803
803
  # @param [Hash] opts the optional parameters
804
804
  # @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. Only 2xx responses are stored, so a request that failed with a 4xx can be retried with a corrected body under the SAME key.
@@ -810,7 +810,7 @@ module Zernio
810
810
  end
811
811
 
812
812
  # Duplicate an ad
813
- # Duplicates a single ad via Meta&#39;s native &#x60;POST /{ad-id}/copies&#x60;. The copy is created paused. &#x60;adSetId&#x60; retargets the copy into another ad set; omitted &#x3D; the source&#39;s own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (&#x60;syncAfter: false&#x60; to skip).
813
+ # Duplicates a single ad via Meta&#39;s native &#x60;POST /{ad-id}/copies&#x60;. The copy is created paused. &#x60;adSetId&#x60; retargets the copy into another ad set; omitted &#x3D; the source&#39;s own ad set. Accepts the Zernio ad id or the platform ad id. Sync discovery is triggered automatically (&#x60;syncAfter: false&#x60; to skip). Creative settings returned by Meta, including explicit promotion metadata and creativeFeatures, are preserved when the native copy requires a creative rebuild. Metadata Meta does not return cannot be recovered.
814
814
  # @param ad_id [String] Zernio ad ID or platform ad ID
815
815
  # @param [Hash] opts the optional parameters
816
816
  # @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. Only 2xx responses are stored, so a request that failed with a 4xx can be retried with a corrected body under the SAME key.
@@ -1037,9 +1037,10 @@ module Zernio
1037
1037
  end
1038
1038
 
1039
1039
  # Get ad details
1040
- # Returns an ad with its creative, targeting, status, and performance metrics. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step.
1040
+ # Returns an ad with its creative, targeting, status, and performance metrics. The `{adId}` path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal `_id` (24-char hex) - Meta's numeric `platformAdId` (the value shipped in `comment.received` webhooks as `comment.ad.id`) - the creative's `effective_object_story_id` (`{pageId}_{postId}` shape, Facebook side) - the creative's `effective_instagram_media_id` (Instagram side) Any of the four resolve to the same ad. Caller doesn't need a translation step. 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.
1041
1041
  # @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.
1042
1042
  # @param [Hash] opts the optional parameters
1043
+ # @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)
1043
1044
  # @return [GetAd200Response]
1044
1045
  def get_ad(ad_id, opts = {})
1045
1046
  data, _status_code, _headers = get_ad_with_http_info(ad_id, opts)
@@ -1047,9 +1048,10 @@ module Zernio
1047
1048
  end
1048
1049
 
1049
1050
  # Get ad details
1050
- # Returns an ad with its creative, targeting, status, and performance metrics. The &#x60;{adId}&#x60; path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal &#x60;_id&#x60; (24-char hex) - Meta&#39;s numeric &#x60;platformAdId&#x60; (the value shipped in &#x60;comment.received&#x60; webhooks as &#x60;comment.ad.id&#x60;) - the creative&#39;s &#x60;effective_object_story_id&#x60; (&#x60;{pageId}_{postId}&#x60; shape, Facebook side) - the creative&#39;s &#x60;effective_instagram_media_id&#x60; (Instagram side) Any of the four resolve to the same ad. Caller doesn&#39;t need a translation step.
1051
+ # Returns an ad with its creative, targeting, status, and performance metrics. The &#x60;{adId}&#x60; path segment accepts any identifier dialect Zernio indexes for the ad: - the Zernio internal &#x60;_id&#x60; (24-char hex) - Meta&#39;s numeric &#x60;platformAdId&#x60; (the value shipped in &#x60;comment.received&#x60; webhooks as &#x60;comment.ad.id&#x60;) - the creative&#39;s &#x60;effective_object_story_id&#x60; (&#x60;{pageId}_{postId}&#x60; shape, Facebook side) - the creative&#39;s &#x60;effective_instagram_media_id&#x60; (Instagram side) Any of the four resolve to the same ad. Caller doesn&#39;t need a translation step. 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.
1051
1052
  # @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.
1052
1053
  # @param [Hash] opts the optional parameters
1054
+ # @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)
1053
1055
  # @return [Array<(GetAd200Response, Integer, Hash)>] GetAd200Response data, response status code and response headers
1054
1056
  def get_ad_with_http_info(ad_id, opts = {})
1055
1057
  if @api_client.config.debugging
@@ -1064,6 +1066,7 @@ module Zernio
1064
1066
 
1065
1067
  # query parameters
1066
1068
  query_params = opts[:query_params] || {}
1069
+ query_params[:'refreshPromotion'] = opts[:'refresh_promotion'] if !opts[:'refresh_promotion'].nil?
1067
1070
 
1068
1071
  # header parameters
1069
1072
  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.
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.
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.
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.
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
@@ -505,7 +505,7 @@ module Zernio
505
505
  end
506
506
 
507
507
  # List a catalog's product sets
508
- # Lists a Meta product catalog's product sets, the unit a catalog ad promotes. Pass the chosen set as `promotedObject.productSetId` on POST /v1/ads/create with `goal: catalog_sales`.
508
+ # Lists a Meta product catalog's product sets, the unit a catalog ad promotes. Pass the chosen set id, not the parent catalog id, as `promotedObject.productSetId` on POST /v1/ads/create with `goal: catalog_sales`. Creation verifies set visibility and returns 400 for a catalog id or an inaccessible set.
509
509
  # @param catalog_id [String] Meta product catalog ID (from GET /v1/ads/catalogs)
510
510
  # @param account_id [String] A facebook, instagram, or metaads account ID
511
511
  # @param [Hash] opts the optional parameters
@@ -516,7 +516,7 @@ module Zernio
516
516
  end
517
517
 
518
518
  # List a catalog&#39;s product sets
519
- # Lists a Meta product catalog&#39;s product sets, the unit a catalog ad promotes. Pass the chosen set as &#x60;promotedObject.productSetId&#x60; on POST /v1/ads/create with &#x60;goal: catalog_sales&#x60;.
519
+ # Lists a Meta product catalog&#39;s product sets, the unit a catalog ad promotes. Pass the chosen set id, not the parent catalog id, as &#x60;promotedObject.productSetId&#x60; on POST /v1/ads/create with &#x60;goal: catalog_sales&#x60;. Creation verifies set visibility and returns 400 for a catalog id or an inaccessible set.
520
520
  # @param catalog_id [String] Meta product catalog ID (from GET /v1/ads/catalogs)
521
521
  # @param account_id [String] A facebook, instagram, or metaads account ID
522
522
  # @param [Hash] opts the optional parameters