late-sdk 0.0.951 → 0.0.952

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c38482d68545143ff205c891ce5e6f1a6d824a6e83d1eb1fd10e65e62d7a9e98
4
- data.tar.gz: be5e50f485a2d0eb88d5b91357758d192fab39270b263b982e99c98454d6d8b6
3
+ metadata.gz: eed8e34a9d28c6ef98df32373b486797e6dae1892c1dcf3156c6d5a37b531115
4
+ data.tar.gz: 3559a8687037d49da50acf85a1b8bb9bfae801020408710f5b46660a08fa204c
5
5
  SHA512:
6
- metadata.gz: 6df6ec89b065b420e1c11e634c5317377e6e7c1d9032ac13724f42b372bc93afd36a01e667d981eaf91cf03c654bc48c46d758a680f4081f623940b7b65f5d9f
7
- data.tar.gz: 701448b7c9ac469dfb720ea00f8cb9a1b860dea2595136114d86c4dd3808d12a8adb88b5ac0b9aeb182d2f4d4fb4c7dbce01a49f09f980b7e0f969701689b511
6
+ metadata.gz: 46d5db8b6ea45da7bd1ad175c75b0fe770199ecb5ec48fb97aba1d13801e498e6c2f788d33e2a52e0d538d981a04d557c15da75e795503ba8257f114c0574fbb
7
+ data.tar.gz: 4155725a1c179eb38a721795887824d177b098d94d146c522ba209f87649086d1d336ca6dddccbc4110912f303d8f2d0e4dc77b87ea2d557fc1deda3c8cbbefc
data/README.md CHANGED
@@ -930,6 +930,7 @@ Class | Method | HTTP request | Description
930
930
  - [Zernio::BoostPostRequest](docs/BoostPostRequest.md)
931
931
  - [Zernio::BoostPostRequestBudget](docs/BoostPostRequestBudget.md)
932
932
  - [Zernio::BoostPostRequestPlatformSpecificData](docs/BoostPostRequestPlatformSpecificData.md)
933
+ - [Zernio::BoostPostRequestPromotedObject](docs/BoostPostRequestPromotedObject.md)
933
934
  - [Zernio::BoostPostRequestSchedule](docs/BoostPostRequestSchedule.md)
934
935
  - [Zernio::BoostPostRequestTargeting](docs/BoostPostRequestTargeting.md)
935
936
  - [Zernio::BoostPostRequestTargetingCitiesInner](docs/BoostPostRequestTargetingCitiesInner.md)
@@ -2928,7 +2928,7 @@ end
2928
2928
 
2929
2929
  Update ad
2930
2930
 
2931
- Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead), and radius targeting (`customLocations`) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
2931
+ Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. An empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead). Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google radius targeting:** `customLocations` is editable and is replaced the same way, but as its OWN set. Google models a place (LOCATION) and a point plus radius (PROXIMITY) as different criterion types, so the two are independent: sending `customLocations` replaces every radius and leaves the cities and countries alone, and sending places replaces those and leaves the radius alone. Send `customLocations: []` to drop radius targeting entirely. A circle you re-send unchanged keeps its criterion ID rather than being removed and recreated. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
2932
2932
 
2933
2933
  ### Examples
2934
2934
 
@@ -32,6 +32,7 @@
32
32
  | **link_url** | **String** | Website URL for non-messaging CTA buttons. Send it with `callToAction`. Omit for messaging boosts. **Meta**: adds a top-level `call_to_action` to the post-reference creative. This is what gives a `traffic` boost a clickable destination without replacing the creative and losing the post's social proof. Ignored when `leadGenFormId` is set, which supplies its own destination. Live-verified against a Page-post creative. **TikTok**: maps to `landing_page_url` on the Spark Ad creative (`AdcreateCreatives.landing_page_url`); Spark Ads have no clickable destination without it. Ignored on LinkedIn / Pinterest / X / Google, which infer the destination from the boosted post. | [optional] |
33
33
  | **call_to_action** | **String** | CTA button label. Non-messaging CTAs require `linkUrl`. WHATSAPP_MESSAGE, MESSAGE_PAGE, and INSTAGRAM_MESSAGE do not require a URL and reject linkUrl. **Meta**: the CTA enum of POST /v1/ads/create plus `VIEW_INSTAGRAM_PROFILE`, `WHATSAPP_MESSAGE`, `MESSAGE_PAGE`, and `INSTAGRAM_MESSAGE`. VIEW_INSTAGRAM_PROFILE requires linkUrl; the messaging CTAs select their destination automatically. **TikTok**: pass-through to `call_to_action` on the Spark Ad creative; the platform validates the value. See TikTok's \"Enumeration - Call-to-Action\". | [optional] |
34
34
  | **spark_auth_code** | **String** | TikTok-only. Spark Code (creator's `auth_code`) authorizing cross-creator Spark Ads: the advertiser can boost a video owned by a DIFFERENT TikTok account. Without this, boosts are limited to videos owned by the same account running the ads (same-BC creators only). The creator generates the code in their TikTok app's Promote settings and shares it with the advertiser. Maps to `auth_code` on the creative entry of /v2/ad/create/. | [optional] |
35
+ | **promoted_object** | [**BoostPostRequestPromotedObject**](BoostPostRequestPromotedObject.md) | | [optional] |
35
36
  | **dsa_beneficiary** | **String** | Legal entity that benefits from the ad. Required when targeting EU users (EU DSA, Article 26). Optional if the ad account has a default beneficiary: set it once via `PATCH /v1/ads/accounts` or in Meta Ads Manager, and Meta fills it in whenever the field is omitted. | [optional] |
36
37
  | **dsa_payor** | **String** | Legal entity that pays for the ad. Can differ from `dsaBeneficiary` (for example, an agency paying for a client's ads). Same rules as `dsaBeneficiary`: required for EU targeting unless the ad account has a default payor. | [optional] |
37
38
  | **lead_gen_form_id** | **String** | Lead Gen form ID to attach to the boosted ad's creative. REQUIRED when `goal` is `lead_generation`. On Meta this is the leadgen_forms ID (create one via POST /v1/ads/lead-forms). On LinkedIn this is the adForm ID (create one via POST /v1/ads/lead-forms with a LinkedIn account); the creative's `leadgenCallToAction.destination` is set to `urn:li:adForm:{id}`. Ignored for other goals. | [optional] |
@@ -72,6 +73,7 @@ instance = Zernio::BoostPostRequest.new(
72
73
  link_url: null,
73
74
  call_to_action: null,
74
75
  spark_auth_code: null,
76
+ promoted_object: null,
75
77
  dsa_beneficiary: null,
76
78
  dsa_payor: null,
77
79
  lead_gen_form_id: null,
@@ -0,0 +1,20 @@
1
+ # Zernio::BoostPostRequestPromotedObject
2
+
3
+ ## Properties
4
+
5
+ | Name | Type | Description | Notes |
6
+ | ---- | ---- | ----------- | ----- |
7
+ | **pixel_id** | **String** | TikTok Pixel. Either the numeric pixel id or the alphanumeric pixel code from Events Manager, which is resolved for you. | [optional] |
8
+ | **custom_event_type** | **String** | Optimization event, as a TikTok optimization_event code (e.g. ON_WEB_ORDER, SHOPPING, FORM) or the exact event name shown in Events Manager, which is resolved to its code. Omit to let TikTok optimize for the ad group default. | [optional] |
9
+
10
+ ## Example
11
+
12
+ ```ruby
13
+ require 'zernio-sdk'
14
+
15
+ instance = Zernio::BoostPostRequestPromotedObject.new(
16
+ pixel_id: null,
17
+ custom_event_type: null
18
+ )
19
+ ```
20
+
@@ -3067,7 +3067,7 @@ module Zernio
3067
3067
  end
3068
3068
 
3069
3069
  # Update ad
3070
- # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead), and radius targeting (`customLocations`) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
3070
+ # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. An empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead). Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google radius targeting:** `customLocations` is editable and is replaced the same way, but as its OWN set. Google models a place (LOCATION) and a point plus radius (PROXIMITY) as different criterion types, so the two are independent: sending `customLocations` replaces every radius and leaves the cities and countries alone, and sending places replaces those and leaves the radius alone. Send `customLocations: []` to drop radius targeting entirely. A circle you re-send unchanged keeps its criterion ID rather than being removed and recreated. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
3071
3071
  # @param ad_id [String]
3072
3072
  # @param update_ad_request [UpdateAdRequest]
3073
3073
  # @param [Hash] opts the optional parameters
@@ -3078,7 +3078,7 @@ module Zernio
3078
3078
  end
3079
3079
 
3080
3080
  # Update ad
3081
- # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead), and radius targeting (`customLocations`) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
3081
+ # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. An empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead). Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google radius targeting:** `customLocations` is editable and is replaced the same way, but as its OWN set. Google models a place (LOCATION) and a point plus radius (PROXIMITY) as different criterion types, so the two are independent: sending `customLocations` replaces every radius and leaves the cities and countries alone, and sending places replaces those and leaves the radius alone. Send `customLocations: []` to drop radius targeting entirely. A circle you re-send unchanged keeps its criterion ID rather than being removed and recreated. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
3082
3082
  # @param ad_id [String]
3083
3083
  # @param update_ad_request [UpdateAdRequest]
3084
3084
  # @param [Hash] opts the optional parameters
@@ -93,6 +93,8 @@ module Zernio
93
93
  # TikTok-only. Spark Code (creator's `auth_code`) authorizing cross-creator Spark Ads: the advertiser can boost a video owned by a DIFFERENT TikTok account. Without this, boosts are limited to videos owned by the same account running the ads (same-BC creators only). The creator generates the code in their TikTok app's Promote settings and shares it with the advertiser. Maps to `auth_code` on the creative entry of /v2/ad/create/.
94
94
  attr_accessor :spark_auth_code
95
95
 
96
+ attr_accessor :promoted_object
97
+
96
98
  # Legal entity that benefits from the ad. Required when targeting EU users (EU DSA, Article 26). Optional if the ad account has a default beneficiary: set it once via `PATCH /v1/ads/accounts` or in Meta Ads Manager, and Meta fills it in whenever the field is omitted.
97
99
  attr_accessor :dsa_beneficiary
98
100
 
@@ -161,6 +163,7 @@ module Zernio
161
163
  :'link_url' => :'linkUrl',
162
164
  :'call_to_action' => :'callToAction',
163
165
  :'spark_auth_code' => :'sparkAuthCode',
166
+ :'promoted_object' => :'promotedObject',
164
167
  :'dsa_beneficiary' => :'dsaBeneficiary',
165
168
  :'dsa_payor' => :'dsaPayor',
166
169
  :'lead_gen_form_id' => :'leadGenFormId',
@@ -210,6 +213,7 @@ module Zernio
210
213
  :'link_url' => :'String',
211
214
  :'call_to_action' => :'String',
212
215
  :'spark_auth_code' => :'String',
216
+ :'promoted_object' => :'BoostPostRequestPromotedObject',
213
217
  :'dsa_beneficiary' => :'String',
214
218
  :'dsa_payor' => :'String',
215
219
  :'lead_gen_form_id' => :'String',
@@ -372,6 +376,10 @@ module Zernio
372
376
  self.spark_auth_code = attributes[:'spark_auth_code']
373
377
  end
374
378
 
379
+ if attributes.key?(:'promoted_object')
380
+ self.promoted_object = attributes[:'promoted_object']
381
+ end
382
+
375
383
  if attributes.key?(:'dsa_beneficiary')
376
384
  self.dsa_beneficiary = attributes[:'dsa_beneficiary']
377
385
  end
@@ -623,6 +631,7 @@ module Zernio
623
631
  link_url == o.link_url &&
624
632
  call_to_action == o.call_to_action &&
625
633
  spark_auth_code == o.spark_auth_code &&
634
+ promoted_object == o.promoted_object &&
626
635
  dsa_beneficiary == o.dsa_beneficiary &&
627
636
  dsa_payor == o.dsa_payor &&
628
637
  lead_gen_form_id == o.lead_gen_form_id &&
@@ -639,7 +648,7 @@ module Zernio
639
648
  # Calculates hash code according to all attributes.
640
649
  # @return [Integer] Hash code
641
650
  def hash
642
- [creative_features, post_id, platform_post_id, account_id, ad_account_id, name, goal, ad_set_id, budget, instagram_account_id, destination_type, whatsapp_phone_number, currency, schedule, targeting, raw_targeting, bid_strategy, bid_amount, roas_average_floor, platform_specific_data, tracking, special_ad_categories, special_ad_category_country, regional_regulated_categories, regional_regulation_identities, link_url, call_to_action, spark_auth_code, dsa_beneficiary, dsa_payor, lead_gen_form_id, status, optimization_goal].hash
651
+ [creative_features, post_id, platform_post_id, account_id, ad_account_id, name, goal, ad_set_id, budget, instagram_account_id, destination_type, whatsapp_phone_number, currency, schedule, targeting, raw_targeting, bid_strategy, bid_amount, roas_average_floor, platform_specific_data, tracking, special_ad_categories, special_ad_category_country, regional_regulated_categories, regional_regulation_identities, link_url, call_to_action, spark_auth_code, promoted_object, dsa_beneficiary, dsa_payor, lead_gen_form_id, status, optimization_goal].hash
643
652
  end
644
653
 
645
654
  # Builds the object from hash
@@ -0,0 +1,159 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
5
+
6
+ The version of the OpenAPI document: 1.0.4
7
+ Contact: support@zernio.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.19.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Zernio
17
+ # TikTok-only on this endpoint. The pixel a Website Conversion ad group optimizes toward, so a Spark Ad built from an existing organic post can optimize for a conversion instead of only engagement or traffic. Required when `goal` is `conversions`; ignored on every other goal, because only a WEB_CONVERSIONS ad group accepts these fields. Combine freely with `platformPostId` + `sparkAuthCode`: the pixel lives on the ad group and the Spark item on the creative, so they never conflict.
18
+ class BoostPostRequestPromotedObject < ApiModelBase
19
+ # TikTok Pixel. Either the numeric pixel id or the alphanumeric pixel code from Events Manager, which is resolved for you.
20
+ attr_accessor :pixel_id
21
+
22
+ # Optimization event, as a TikTok optimization_event code (e.g. ON_WEB_ORDER, SHOPPING, FORM) or the exact event name shown in Events Manager, which is resolved to its code. Omit to let TikTok optimize for the ad group default.
23
+ attr_accessor :custom_event_type
24
+
25
+ # Attribute mapping from ruby-style variable name to JSON key.
26
+ def self.attribute_map
27
+ {
28
+ :'pixel_id' => :'pixelId',
29
+ :'custom_event_type' => :'customEventType'
30
+ }
31
+ end
32
+
33
+ # Returns attribute mapping this model knows about
34
+ def self.acceptable_attribute_map
35
+ attribute_map
36
+ end
37
+
38
+ # Returns all the JSON keys this model knows about
39
+ def self.acceptable_attributes
40
+ acceptable_attribute_map.values
41
+ end
42
+
43
+ # Attribute type mapping.
44
+ def self.openapi_types
45
+ {
46
+ :'pixel_id' => :'String',
47
+ :'custom_event_type' => :'String'
48
+ }
49
+ end
50
+
51
+ # List of attributes with nullable: true
52
+ def self.openapi_nullable
53
+ Set.new([
54
+ ])
55
+ end
56
+
57
+ # Initializes the object
58
+ # @param [Hash] attributes Model attributes in the form of hash
59
+ def initialize(attributes = {})
60
+ if (!attributes.is_a?(Hash))
61
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::BoostPostRequestPromotedObject` initialize method"
62
+ end
63
+
64
+ # check to see if the attribute exists and convert string to symbol for hash key
65
+ acceptable_attribute_map = self.class.acceptable_attribute_map
66
+ attributes = attributes.each_with_object({}) { |(k, v), h|
67
+ if (!acceptable_attribute_map.key?(k.to_sym))
68
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::BoostPostRequestPromotedObject`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
69
+ end
70
+ h[k.to_sym] = v
71
+ }
72
+
73
+ if attributes.key?(:'pixel_id')
74
+ self.pixel_id = attributes[:'pixel_id']
75
+ end
76
+
77
+ if attributes.key?(:'custom_event_type')
78
+ self.custom_event_type = attributes[:'custom_event_type']
79
+ end
80
+ end
81
+
82
+ # Show invalid properties with the reasons. Usually used together with valid?
83
+ # @return Array for valid properties with the reasons
84
+ def list_invalid_properties
85
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
86
+ invalid_properties = Array.new
87
+ invalid_properties
88
+ end
89
+
90
+ # Check to see if the all the properties in the model are valid
91
+ # @return true if the model is valid
92
+ def valid?
93
+ warn '[DEPRECATED] the `valid?` method is obsolete'
94
+ true
95
+ end
96
+
97
+ # Checks equality by comparing each attribute.
98
+ # @param [Object] Object to be compared
99
+ def ==(o)
100
+ return true if self.equal?(o)
101
+ self.class == o.class &&
102
+ pixel_id == o.pixel_id &&
103
+ custom_event_type == o.custom_event_type
104
+ end
105
+
106
+ # @see the `==` method
107
+ # @param [Object] Object to be compared
108
+ def eql?(o)
109
+ self == o
110
+ end
111
+
112
+ # Calculates hash code according to all attributes.
113
+ # @return [Integer] Hash code
114
+ def hash
115
+ [pixel_id, custom_event_type].hash
116
+ end
117
+
118
+ # Builds the object from hash
119
+ # @param [Hash] attributes Model attributes in the form of hash
120
+ # @return [Object] Returns the model itself
121
+ def self.build_from_hash(attributes)
122
+ return nil unless attributes.is_a?(Hash)
123
+ attributes = attributes.transform_keys(&:to_sym)
124
+ transformed_hash = {}
125
+ openapi_types.each_pair do |key, type|
126
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
127
+ transformed_hash["#{key}"] = nil
128
+ elsif type =~ /\AArray<(.*)>/i
129
+ # check to ensure the input is an array given that the attribute
130
+ # is documented as an array but the input is not
131
+ if attributes[attribute_map[key]].is_a?(Array)
132
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
133
+ end
134
+ elsif !attributes[attribute_map[key]].nil?
135
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
136
+ end
137
+ end
138
+ new(transformed_hash)
139
+ end
140
+
141
+ # Returns the object in the form of hash
142
+ # @return [Hash] Returns the object in the form of hash
143
+ def to_hash
144
+ hash = {}
145
+ self.class.attribute_map.each_pair do |attr, param|
146
+ value = self.send(attr)
147
+ if value.nil?
148
+ is_nullable = self.class.openapi_nullable.include?(attr)
149
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
150
+ end
151
+
152
+ hash[param] = _to_hash(value)
153
+ end
154
+ hash
155
+ end
156
+
157
+ end
158
+
159
+ end
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.951'
14
+ VERSION = '0.0.952'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -142,6 +142,7 @@ require 'zernio-sdk/models/bookmark_post_request'
142
142
  require 'zernio-sdk/models/boost_post_request'
143
143
  require 'zernio-sdk/models/boost_post_request_budget'
144
144
  require 'zernio-sdk/models/boost_post_request_platform_specific_data'
145
+ require 'zernio-sdk/models/boost_post_request_promoted_object'
145
146
  require 'zernio-sdk/models/boost_post_request_schedule'
146
147
  require 'zernio-sdk/models/boost_post_request_targeting'
147
148
  require 'zernio-sdk/models/boost_post_request_targeting_cities_inner'
data/openapi.yaml CHANGED
@@ -46085,12 +46085,18 @@ paths:
46085
46085
  the campaign's live criteria and sends the removes and the creates in ONE
46086
46086
  `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria
46087
46087
  already in the list keep their criterion ID and history. Excluded (negative)
46088
- locations are left untouched. Two cases are refused rather than applied: an empty
46089
- location list returns 400 (a Google campaign with no location criteria targets every
46090
- country, which is never what "remove my locations" means, so omit the field instead),
46091
- and radius targeting (`customLocations`) returns 422 because it is a separate Google
46092
- criterion type that this replacement neither creates nor removes. Send either
46093
- `targeting.locations` or the top-level geo fields, not both: mixing them returns 400.
46088
+ locations are left untouched. An empty location list returns 400 (a Google campaign
46089
+ with no location criteria targets every country, which is never what "remove my
46090
+ locations" means, so omit the field instead). Send either `targeting.locations` or the
46091
+ top-level geo fields, not both: mixing them returns 400.
46092
+
46093
+ **Google radius targeting:** `customLocations` is editable and is replaced the same
46094
+ way, but as its OWN set. Google models a place (LOCATION) and a point plus radius
46095
+ (PROXIMITY) as different criterion types, so the two are independent: sending
46096
+ `customLocations` replaces every radius and leaves the cities and countries alone,
46097
+ and sending places replaces those and leaves the radius alone. Send
46098
+ `customLocations: []` to drop radius targeting entirely. A circle you re-send
46099
+ unchanged keeps its criterion ID rather than being removed and recreated.
46094
46100
 
46095
46101
  **Google keyword replacement:** These edits affect the ad's entire ad group,
46096
46102
  including sibling ads. Positive (`targeting.keywords`) and negative
@@ -51649,6 +51655,24 @@ paths:
51649
51655
  account running the ads (same-BC creators only). The creator generates the
51650
51656
  code in their TikTok app's Promote settings and shares it with the
51651
51657
  advertiser. Maps to `auth_code` on the creative entry of /v2/ad/create/.
51658
+ promotedObject:
51659
+ type: object
51660
+ description: |
51661
+ TikTok-only on this endpoint. The pixel a Website Conversion ad group
51662
+ optimizes toward, so a Spark Ad built from an existing organic post can
51663
+ optimize for a conversion instead of only engagement or traffic. Required
51664
+ when `goal` is `conversions`; ignored on every other goal, because only a
51665
+ WEB_CONVERSIONS ad group accepts these fields.
51666
+
51667
+ Combine freely with `platformPostId` + `sparkAuthCode`: the pixel lives on
51668
+ the ad group and the Spark item on the creative, so they never conflict.
51669
+ properties:
51670
+ pixelId:
51671
+ type: string
51672
+ description: 'TikTok Pixel. Either the numeric pixel id or the alphanumeric pixel code from Events Manager, which is resolved for you.'
51673
+ customEventType:
51674
+ type: string
51675
+ description: 'Optimization event, as a TikTok optimization_event code (e.g. ON_WEB_ORDER, SHOPPING, FORM) or the exact event name shown in Events Manager, which is resolved to its code. Omit to let TikTok optimize for the ad group default.'
51652
51676
  dsaBeneficiary:
51653
51677
  type: string
51654
51678
  maxLength: 100
@@ -589,7 +589,7 @@ describe 'AdCampaignsApi' do
589
589
 
590
590
  # unit tests for update_ad
591
591
  # Update ad
592
- # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via &#x60;/v2/adgroup/update/&#x60;), and creative (via &#x60;/v2/ad/update/&#x60; patch-style: &#x60;headline&#x60; is ignored, &#x60;body&#x60; becomes &#x60;ad_text&#x60;). - **Google**: status, budget, KEYWORD edits via &#x60;targeting.keywords&#x60; / &#x60;targeting.negativeKeywords&#x60;, DEVICE bid adjustments via &#x60;targeting.devices&#x60;, LOCATION edits via &#x60;targeting.locations&#x60; (or the equivalent top-level &#x60;targeting.countries&#x60; / &#x60;regions&#x60; / &#x60;cities&#x60; / &#x60;zips&#x60; / &#x60;metros&#x60;), and LANGUAGE edits via &#x60;targeting.languages&#x60;. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other &#x60;targeting&#x60; field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad&#39;s &#x60;advertisingChannelType&#x60;, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level &#x60;headlines&#x60;, &#x60;descriptions&#x60; and &#x60;finalUrls&#x60;. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level &#x60;headlines&#x60; (1-5, no pinnedField, display ads have no pinned positions), &#x60;descriptions&#x60; (1-5) and &#x60;finalUrls&#x60;, plus &#x60;creative.longHeadline&#x60;, &#x60;creative.businessName&#x60;, &#x60;creative.imageUrl&#x60; (the landscape marketing image) and &#x60;creative.squareImageUrl&#x60;. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account&#39;s asset library. - **Performance Max**: top-level &#x60;assetGroup&#x60;, which swaps asset roles on the ad&#39;s asset group. The other creative fields return 422 for this channel, and &#x60;assetGroup&#x60; returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign&#39;s entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending &#x60;targeting&#x60; or &#x60;creative&#x60; returns 501 with code &#x60;unsupported_platform_operation&#x60;. OpenAI Ads budget is lifetime-only (see &#x60;budget.type&#x60; below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad&#39;s campaign. Send the complete list you want to keep. Zernio diffs it against the campaign&#39;s live criteria and sends the removes and the creates in ONE &#x60;googleAds:mutate&#x60;, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \&quot;remove my locations\&quot; means, so omit the field instead), and radius targeting (&#x60;customLocations&#x60;) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either &#x60;targeting.locations&#x60; or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad&#39;s entire ad group, including sibling ads. Positive (&#x60;targeting.keywords&#x60;) and negative (&#x60;targeting.negativeKeywords&#x60;) sets are independent: omit a field to leave that set unchanged, or send &#x60;[]&#x60; to remove every keyword of that kind. Zernio compares each supplied set with Google&#39;s live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without &#x60;matchType&#x60; means &#x60;broad&#x60;, not the existing criterion&#39;s match type. For example, resending an existing &#x60;{ \&quot;text\&quot;: \&quot;plumber\&quot;, \&quot;matchType\&quot;: \&quot;exact\&quot; }&#x60; preserves it; sending &#x60;\&quot;plumber\&quot;&#x60; instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria&#39;s bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use &#x60;PATCH /v1/ads/keywords/{keywordId}&#x60; to pause/enable one keyword, or &#x60;DELETE /v1/ads/keywords/{keywordId}&#x60; to remove it.
592
+ # Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via &#x60;/v2/adgroup/update/&#x60;), and creative (via &#x60;/v2/ad/update/&#x60; patch-style: &#x60;headline&#x60; is ignored, &#x60;body&#x60; becomes &#x60;ad_text&#x60;). - **Google**: status, budget, KEYWORD edits via &#x60;targeting.keywords&#x60; / &#x60;targeting.negativeKeywords&#x60;, DEVICE bid adjustments via &#x60;targeting.devices&#x60;, LOCATION edits via &#x60;targeting.locations&#x60; (or the equivalent top-level &#x60;targeting.countries&#x60; / &#x60;regions&#x60; / &#x60;cities&#x60; / &#x60;zips&#x60; / &#x60;metros&#x60;), and LANGUAGE edits via &#x60;targeting.languages&#x60;. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other &#x60;targeting&#x60; field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad&#39;s &#x60;advertisingChannelType&#x60;, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level &#x60;headlines&#x60;, &#x60;descriptions&#x60; and &#x60;finalUrls&#x60;. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level &#x60;headlines&#x60; (1-5, no pinnedField, display ads have no pinned positions), &#x60;descriptions&#x60; (1-5) and &#x60;finalUrls&#x60;, plus &#x60;creative.longHeadline&#x60;, &#x60;creative.businessName&#x60;, &#x60;creative.imageUrl&#x60; (the landscape marketing image) and &#x60;creative.squareImageUrl&#x60;. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account&#39;s asset library. - **Performance Max**: top-level &#x60;assetGroup&#x60;, which swaps asset roles on the ad&#39;s asset group. The other creative fields return 422 for this channel, and &#x60;assetGroup&#x60; returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign&#39;s entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending &#x60;targeting&#x60; or &#x60;creative&#x60; returns 501 with code &#x60;unsupported_platform_operation&#x60;. OpenAI Ads budget is lifetime-only (see &#x60;budget.type&#x60; below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad&#39;s campaign. Send the complete list you want to keep. Zernio diffs it against the campaign&#39;s live criteria and sends the removes and the creates in ONE &#x60;googleAds:mutate&#x60;, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. An empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \&quot;remove my locations\&quot; means, so omit the field instead). Send either &#x60;targeting.locations&#x60; or the top-level geo fields, not both: mixing them returns 400. **Google radius targeting:** &#x60;customLocations&#x60; is editable and is replaced the same way, but as its OWN set. Google models a place (LOCATION) and a point plus radius (PROXIMITY) as different criterion types, so the two are independent: sending &#x60;customLocations&#x60; replaces every radius and leaves the cities and countries alone, and sending places replaces those and leaves the radius alone. Send &#x60;customLocations: []&#x60; to drop radius targeting entirely. A circle you re-send unchanged keeps its criterion ID rather than being removed and recreated. **Google keyword replacement:** These edits affect the ad&#39;s entire ad group, including sibling ads. Positive (&#x60;targeting.keywords&#x60;) and negative (&#x60;targeting.negativeKeywords&#x60;) sets are independent: omit a field to leave that set unchanged, or send &#x60;[]&#x60; to remove every keyword of that kind. Zernio compares each supplied set with Google&#39;s live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without &#x60;matchType&#x60; means &#x60;broad&#x60;, not the existing criterion&#39;s match type. For example, resending an existing &#x60;{ \&quot;text\&quot;: \&quot;plumber\&quot;, \&quot;matchType\&quot;: \&quot;exact\&quot; }&#x60; preserves it; sending &#x60;\&quot;plumber\&quot;&#x60; instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria&#39;s bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use &#x60;PATCH /v1/ads/keywords/{keywordId}&#x60; to pause/enable one keyword, or &#x60;DELETE /v1/ads/keywords/{keywordId}&#x60; to remove it.
593
593
  # @param ad_id
594
594
  # @param update_ad_request
595
595
  # @param [Hash] opts the optional parameters
@@ -0,0 +1,42 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
5
+
6
+ The version of the OpenAPI document: 1.0.4
7
+ Contact: support@zernio.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.19.0
10
+
11
+ =end
12
+
13
+ require 'spec_helper'
14
+ require 'json'
15
+ require 'date'
16
+
17
+ # Unit tests for Zernio::BoostPostRequestPromotedObject
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::BoostPostRequestPromotedObject do
21
+ #let(:instance) { Zernio::BoostPostRequestPromotedObject.new }
22
+
23
+ describe 'test an instance of BoostPostRequestPromotedObject' do
24
+ it 'should create an instance of BoostPostRequestPromotedObject' do
25
+ # uncomment below to test the instance creation
26
+ #expect(instance).to be_instance_of(Zernio::BoostPostRequestPromotedObject)
27
+ end
28
+ end
29
+
30
+ describe 'test attribute "pixel_id"' do
31
+ it 'should work' do
32
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
33
+ end
34
+ end
35
+
36
+ describe 'test attribute "custom_event_type"' do
37
+ it 'should work' do
38
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
+ end
40
+ end
41
+
42
+ end
@@ -211,6 +211,12 @@ describe Zernio::BoostPostRequest do
211
211
  end
212
212
  end
213
213
 
214
+ describe 'test attribute "promoted_object"' do
215
+ it 'should work' do
216
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
217
+ end
218
+ end
219
+
214
220
  describe 'test attribute "dsa_beneficiary"' do
215
221
  it 'should work' do
216
222
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: late-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.951
4
+ version: 0.0.952
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenAPI-Generator
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-14 00:00:00.000000000 Z
11
+ date: 2026-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: typhoeus
@@ -205,6 +205,7 @@ files:
205
205
  - docs/BoostPostRequest.md
206
206
  - docs/BoostPostRequestBudget.md
207
207
  - docs/BoostPostRequestPlatformSpecificData.md
208
+ - docs/BoostPostRequestPromotedObject.md
208
209
  - docs/BoostPostRequestSchedule.md
209
210
  - docs/BoostPostRequestTargeting.md
210
211
  - docs/BoostPostRequestTargetingCitiesInner.md
@@ -2400,6 +2401,7 @@ files:
2400
2401
  - lib/zernio-sdk/models/boost_post_request.rb
2401
2402
  - lib/zernio-sdk/models/boost_post_request_budget.rb
2402
2403
  - lib/zernio-sdk/models/boost_post_request_platform_specific_data.rb
2404
+ - lib/zernio-sdk/models/boost_post_request_promoted_object.rb
2403
2405
  - lib/zernio-sdk/models/boost_post_request_schedule.rb
2404
2406
  - lib/zernio-sdk/models/boost_post_request_targeting.rb
2405
2407
  - lib/zernio-sdk/models/boost_post_request_targeting_cities_inner.rb
@@ -4532,6 +4534,7 @@ files:
4532
4534
  - spec/models/bookmark_post_request_spec.rb
4533
4535
  - spec/models/boost_post_request_budget_spec.rb
4534
4536
  - spec/models/boost_post_request_platform_specific_data_spec.rb
4537
+ - spec/models/boost_post_request_promoted_object_spec.rb
4535
4538
  - spec/models/boost_post_request_schedule_spec.rb
4536
4539
  - spec/models/boost_post_request_spec.rb
4537
4540
  - spec/models/boost_post_request_targeting_cities_inner_spec.rb
@@ -6472,7 +6475,7 @@ files:
6472
6475
  - spec/models/you_tube_video_retention_response_retention_curve_inner_spec.rb
6473
6476
  - spec/models/you_tube_video_retention_response_spec.rb
6474
6477
  - spec/spec_helper.rb
6475
- - zernio-sdk-0.0.951.gem
6478
+ - zernio-sdk-0.0.952.gem
6476
6479
  - zernio-sdk.gemspec
6477
6480
  homepage: https://openapi-generator.tech
6478
6481
  licenses:
@@ -7117,6 +7120,7 @@ test_files:
7117
7120
  - spec/models/update_campaign_targeting200_response_locations_inner_spec.rb
7118
7121
  - spec/models/update_google_business_location_details200_response_spec.rb
7119
7122
  - spec/models/list_business_agent_settings200_response_spec.rb
7123
+ - spec/models/boost_post_request_promoted_object_spec.rb
7120
7124
  - spec/models/update_sequence200_response_spec.rb
7121
7125
  - spec/models/reply_to_mention_request_spec.rb
7122
7126
  - spec/models/set_business_agent_connector_credentials_request_one_of1_spec.rb
Binary file