zernio-sdk 0.0.804 → 0.0.806
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 +4 -4
- data/docs/AdCampaignsApi.md +1 -1
- data/docs/BoostPostRequest.md +4 -0
- data/docs/BulkUploadResult.md +1 -1
- data/docs/CreateStandaloneAdRequest.md +3 -3
- data/docs/PostCreateResponse.md +3 -1
- data/docs/PostsApi.md +1 -1
- data/lib/zernio-sdk/api/ad_campaigns_api.rb +2 -2
- data/lib/zernio-sdk/api/posts_api.rb +2 -2
- data/lib/zernio-sdk/models/boost_post_request.rb +33 -1
- data/lib/zernio-sdk/models/bulk_upload_result.rb +1 -1
- data/lib/zernio-sdk/models/create_standalone_ad_request.rb +3 -3
- data/lib/zernio-sdk/models/post_create_response.rb +16 -4
- data/lib/zernio-sdk/models/update_ad_request_creative.rb +1 -1
- data/lib/zernio-sdk/models/update_ad_request_targeting.rb +1 -1
- data/lib/zernio-sdk/version.rb +1 -1
- data/openapi.yaml +46 -10
- data/spec/api/ad_campaigns_api_spec.rb +1 -1
- data/spec/api/posts_api_spec.rb +1 -1
- data/spec/models/boost_post_request_spec.rb +16 -0
- data/spec/models/post_create_response_spec.rb +6 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d91182d227cba8a3f1c482347300303f38c32616ea4edf351fad9d25b8623c3d
|
|
4
|
+
data.tar.gz: da87c3ea30706fef9a9e4b0f488ab88e98f1e4c57d6ae3846688b9f21b16cf73
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7dd6cd78db4369858d39f2d74485a05f33aed44c9e25da069e65c02b666bc590b3285b51a35828dea7222f9d667c31242c2bf5bb91dfdacc8043c0109031267b
|
|
7
|
+
data.tar.gz: 2dc2eaf066d78dee7443e302e3697e6af03028d95655bc24e62e43e9fdcc2ef43873c4216dec6370140408f441b78f04d8a71be6a330e22c2c195b7857787241
|
data/docs/AdCampaignsApi.md
CHANGED
|
@@ -1442,7 +1442,7 @@ end
|
|
|
1442
1442
|
|
|
1443
1443
|
Update ad
|
|
1444
1444
|
|
|
1445
|
-
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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **Pinterest / X /
|
|
1445
|
+
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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **LinkedIn**: status, budget, targeting (geo countries only, applied to the LinkedIn Campaign via PARTIAL_UPDATE), 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).
|
|
1446
1446
|
|
|
1447
1447
|
### Examples
|
|
1448
1448
|
|
data/docs/BoostPostRequest.md
CHANGED
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
| **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] |
|
|
31
31
|
| **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] |
|
|
32
32
|
| **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] |
|
|
33
|
+
| **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] |
|
|
34
|
+
| **status** | **String** | Meta, TikTok, and LinkedIn. Publish state of the created entities. Omitted or ACTIVE publishes live (default); PAUSED creates them paused so you can review before they spend. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each). | [optional] |
|
|
33
35
|
| **optimization_goal** | **String** | Meta only. Explicit ad-set `optimization_goal` override. When omitted, defaults to the value derived from `goal`. The value must be compatible with the objective Meta derives from `goal`, not with the objective used by `POST /v1/ads/create` for the same `goal` name: boost maps `goal: \"engagement\"` to objective `OUTCOME_AWARENESS`, which accepts `REACH`, `IMPRESSIONS`, `AD_RECALL_LIFT`, or THRUPLAY-class values, and rejects `POST_ENGAGEMENT` (that value is only valid under `OUTCOME_ENGAGEMENT`, which create uses for the same goal name). | [optional] |
|
|
34
36
|
|
|
35
37
|
## Example
|
|
@@ -64,6 +66,8 @@ instance = Zernio::BoostPostRequest.new(
|
|
|
64
66
|
spark_auth_code: null,
|
|
65
67
|
dsa_beneficiary: null,
|
|
66
68
|
dsa_payor: null,
|
|
69
|
+
lead_gen_form_id: null,
|
|
70
|
+
status: null,
|
|
67
71
|
optimization_goal: null
|
|
68
72
|
)
|
|
69
73
|
```
|
data/docs/BulkUploadResult.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
| **valid** | **Integer** | Count of rows that succeeded (results[].ok === true) | [optional] |
|
|
9
9
|
| **invalid** | **Integer** | Count of rows that failed (total - valid) | [optional] |
|
|
10
10
|
| **results** | [**Array<BulkUploadResultResultsInner>**](BulkUploadResultResultsInner.md) | One entry per CSV data row, in row order. | [optional] |
|
|
11
|
-
| **warnings** | **Array<String>** | Top-level advisory warnings
|
|
11
|
+
| **warnings** | **Array<String>** | Top-level advisory warnings, e.g. `rows_exceed_advisory_limit:500` or `unknown_columns:<a,b,c>` (comma-separated unrecognized CSV column names). Empty when none. | [optional] |
|
|
12
12
|
| **rate_limited_accounts** | [**Array<BulkUploadResultRateLimitedAccountsInner>**](BulkUploadResultRateLimitedAccountsInner.md) | Present only when one or more rows targeted an account currently in cooldown. Lets callers map `rate_limited:*` row errors back to structured metadata without parsing the error strings. | [optional] |
|
|
13
13
|
|
|
14
14
|
## Example
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| **ad_set_name** | **String** | Meta only. Exact ad set name. Overrides the default `<name> - Ad Set`. (For per-ad names on the multi-creative shape, set `name` on each `creatives[]` entry.) | [optional] |
|
|
12
12
|
| **ad_name** | **String** | Meta only. Exact ad name (the single-creative ad object's name). Overrides the default, which is `name`. (For per-ad names on the multi-creative shape, set `name` on each `creatives[]` entry instead.) | [optional] |
|
|
13
13
|
| **tracking** | [**CreateStandaloneAdRequestTracking**](CreateStandaloneAdRequestTracking.md) | | [optional] |
|
|
14
|
-
| **goal** | **String** | Required on legacy and multi-creative shapes; the attach shape inherits it from the ad set. Available goals vary by platform. **Meta** - `conversions`: OUTCOME_SALES. Requires `promotedObject.pixelId` and `promotedObject.customEventType` with a commerce event such as PURCHASE or START_TRIAL, or `promotedObject.customConversionId` to optimise against a Custom Conversion, or `customEventType: OTHER` + `customEventStr` to optimise against a pixel custom event. - `lead_conversion`: OUTCOME_LEADS optimizing website pixel leads. Same pixel and event fields, but with a leads-class event such as LEAD, SUBMIT_APPLICATION, SCHEDULE or CONTACT (or `promotedObject.customConversionId` to optimise against a Custom Conversion instead). Meta gates conversion events by objective, so leads-class events are rejected under `conversions`. - `lead_generation`: OUTCOME_LEADS with instant forms. Requires `leadGenFormId`. `promotedObject.pageId` is optional and auto-filled from the connected Page. - `app_promotion`: requires `promotedObject.applicationId` and `promotedObject.objectStoreUrl`. - `catalog_sales`: Advantage+ catalog ads, for example vehicle inventory. Requires `promotedObject.productSetId`, `promotedObject.pixelId` and `promotedObject.customEventType`. Builds a catalog TEMPLATE creative from the copy fields, which may carry template tags like {{product.name}} or {{vehicle.make}}. No imageUrl or video is sent; Meta renders the visuals per catalog item. Discover catalogs via GET /v1/ads/catalogs and product sets via GET /v1/ads/catalogs/{catalogId}/product-sets. Single shape only, no creatives[], adSetId, dynamicCreative or placementAssets. - `page_likes`: Page Likes conversion location under OUTCOME_ENGAGEMENT (destination_type ON_PAGE, optimization PAGE_LIKES). `promotedObject.pageId` is optional and auto-filled from the connected Page. The creative CTA is fixed to LIKE_PAGE targeting that Page; headline / body / linkUrl / callToAction / imageUrl / video are all optional (Meta derives the link and the Like button from the Page). **TikTok** - `conversions`: website-conversion ad group. Requires `promotedObject.pixelId`, your TikTok Pixel ID. Accepts an optional `promotedObject.customEventType` with a TikTok optimization_event code your pixel tracks (newer pixels use e.g. SHOPPING for purchase events; legacy pixels use ON_WEB_ORDER, INITIATE_ORDER, ON_WEB_REGISTER or FORM). To inherit pixel and event from an existing ad group, pass `adSetId` instead. **LinkedIn** - `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`. - `job_applicants` requires a `platformSpecificData.jobs` creative. - For `
|
|
14
|
+
| **goal** | **String** | Required on legacy and multi-creative shapes; the attach shape inherits it from the ad set. Available goals vary by platform. **Meta** - `conversions`: OUTCOME_SALES. Requires `promotedObject.pixelId` and `promotedObject.customEventType` with a commerce event such as PURCHASE or START_TRIAL, or `promotedObject.customConversionId` to optimise against a Custom Conversion, or `customEventType: OTHER` + `customEventStr` to optimise against a pixel custom event. - `lead_conversion`: OUTCOME_LEADS optimizing website pixel leads. Same pixel and event fields, but with a leads-class event such as LEAD, SUBMIT_APPLICATION, SCHEDULE or CONTACT (or `promotedObject.customConversionId` to optimise against a Custom Conversion instead). Meta gates conversion events by objective, so leads-class events are rejected under `conversions`. - `lead_generation`: OUTCOME_LEADS with instant forms. Requires `leadGenFormId`. `promotedObject.pageId` is optional and auto-filled from the connected Page. - `app_promotion`: requires `promotedObject.applicationId` and `promotedObject.objectStoreUrl`. - `catalog_sales`: Advantage+ catalog ads, for example vehicle inventory. Requires `promotedObject.productSetId`, `promotedObject.pixelId` and `promotedObject.customEventType`. Builds a catalog TEMPLATE creative from the copy fields, which may carry template tags like {{product.name}} or {{vehicle.make}}. No imageUrl or video is sent; Meta renders the visuals per catalog item. Discover catalogs via GET /v1/ads/catalogs and product sets via GET /v1/ads/catalogs/{catalogId}/product-sets. Single shape only, no creatives[], adSetId, dynamicCreative or placementAssets. - `page_likes`: Page Likes conversion location under OUTCOME_ENGAGEMENT (destination_type ON_PAGE, optimization PAGE_LIKES). `promotedObject.pageId` is optional and auto-filled from the connected Page. The creative CTA is fixed to LIKE_PAGE targeting that Page; headline / body / linkUrl / callToAction / imageUrl / video are all optional (Meta derives the link and the Like button from the Page). **TikTok** - `conversions`: website-conversion ad group. Requires `promotedObject.pixelId`, your TikTok Pixel ID. Accepts an optional `promotedObject.customEventType` with a TikTok optimization_event code your pixel tracks (newer pixels use e.g. SHOPPING for purchase events; legacy pixels use ON_WEB_ORDER, INITIATE_ORDER, ON_WEB_REGISTER or FORM). To inherit pixel and event from an existing ad group, pass `adSetId` instead. **LinkedIn** - `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`. - `lead_generation`: requires `leadGenFormId` (an adForm ID from POST /v1/ads/lead-forms). The campaign objective is set to MAX_LEAD and the creative's `leadgenCallToAction` destination is set to `urn:li:adForm:{id}`. - `job_applicants` requires a `platformSpecificData.jobs` creative. - For `conversions` on LinkedIn, or to promote an existing post, use POST /v1/ads/boost. **OpenAI Ads** - Only `traffic`, `awareness`, and `conversions` are supported (other goals return 400). Maps to OpenAI's `bidding_type` (clicks, impressions, conversions respectively). `conversions` requires an active conversion event setting on the account; create a tracking tag with `defaultEventType` via the tracking-tags API (`POST /v1/accounts/{accountId}/tracking-tags`), or configure a conversion event in OpenAI Ads Manager, or the request returns 422. | [optional] |
|
|
15
15
|
| **optimization_goal** | **String** | Meta only. Explicit ad-set `optimization_goal` (e.g. `LANDING_PAGE_VIEWS`, `LINK_CLICKS`, `REACH`, `IMPRESSIONS`, `OFFSITE_CONVERSIONS`, `THRUPLAY`, `LEAD_GENERATION`). Overrides the default derived from `goal` (e.g. `traffic` defaults to `LINK_CLICKS`). Forwarded verbatim to Meta, which validates compatibility with the campaign objective and rejects incompatible combinations. | [optional] |
|
|
16
16
|
| **billing_event** | **String** | Meta only. Explicit ad-set `billing_event`. Defaults to `IMPRESSIONS`. Forwarded verbatim to Meta, which validates compatibility with the optimization goal. | [optional] |
|
|
17
17
|
| **buying_type** | **String** | Meta only. RESERVED = Reach & Frequency: requires `rfPredictionId` (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] |
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
| **validate_only** | **Boolean** | Meta only, single standalone shape only (no creatives[], adSetId, or RESERVED). Dry-run: each node runs Meta'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 — 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
22
|
| **budget_amount** | **Float** | Budget in WHOLE currency units (USD: 50 = $50.00), NOT cents — Meta's own Marketing API takes this same number in minor units, so it is an easy and expensive mix-up. Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType). | [optional] |
|
|
23
23
|
| **budget_type** | **String** | Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads accepts lifetime only (no daily-budget concept on the platform); sending daily returns 422. OpenAI Ads lifetime budgets require `endDate` to give the lifetime cap a spend window. | [optional] |
|
|
24
|
-
| **status** | **String** | Meta and
|
|
24
|
+
| **status** | **String** | Meta, TikTok, and LinkedIn. Publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each). | [optional] |
|
|
25
25
|
| **campaign_status** | **String** | Meta only. Overrides `status` for the campaign level alone, so you can create a live campaign whose ad set and ad stay paused, or the reverse. Omitted, it follows `status`. | [optional] |
|
|
26
26
|
| **budget_level** | **String** | Meta only. Where the budget lives, which selects the Meta budget model: - `adset` (default): ABO (Ad-set Budget Optimization). The budget is set on the ad set. This is the back-compatible behaviour — omit this field to keep it. - `campaign`: CBO (Campaign Budget Optimization / Advantage Campaign Budget). The budget AND `bidStrategy` are set on the CAMPAIGN, and Meta distributes spend across ad sets automatically. Meta requires the budget at exactly one level, never both. Non-Meta platforms ignore this field. Ignored on the attach shape (`adSetId`), which inherits the existing budget. | [optional][default to 'adset'] |
|
|
27
27
|
| **currency** | **String** | ISO 4217 currency code matching the ad account's currency (e.g. `USD`). Meta only. Optional: Zernio resolves it from the ad account when omitted. The value selects the minor-unit exponent Zernio converts budget/bid amounts by before calling Meta (most currencies are cents; zero-decimal currencies like JPY/KRW are sent as-is). | [optional] |
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
| **description** | **String** | Meta only (facebook/instagram). Link description — the secondary text shown below the headline (Meta's link_data.description; on video creatives mapped to video_data.link_description). When omitted, Meta auto-pulls the destination URL's OpenGraph description. Applies on legacy, attach, and placementAssets shapes; for multi-creative use creatives[].description (this field is the shared fallback). For multi-text variations use dynamicCreative.descriptions instead. | [optional] |
|
|
32
32
|
| **call_to_action** | **String** | Required on legacy + attach shapes for Meta. Honoured on TikTok (passes through to the Spark Ad creative's `call_to_action`) and on LinkedIn (the CTA button on the ad; defaults to LEARN_MORE when `linkUrl` is set). LinkedIn accepts: LEARN_MORE, SIGN_UP, DOWNLOAD, SUBSCRIBE, REGISTER, JOIN, ATTEND, REQUEST_DEMO, VIEW_QUOTE, APPLY, SEE_MORE, SHOP_NOW, BUY_NOW. Ignored by Google, Pinterest, and X/Twitter. | [optional] |
|
|
33
33
|
| **link_url** | **String** | Required on legacy + attach shapes (skip for multi-creative). On LinkedIn it's the ad's destination URL; required for `traffic` ads, optional for `engagement` / `awareness`. NOT required when `goal` is `lead_generation` (the ad opens a Lead Gen form instead of a destination). On LinkedIn, `imageUrl` + `linkUrl` publishes an ARTICLE-content creative; this is LinkedIn's article ad format, with the image as thumbnail and `longHeadline` as description. Required for OpenAI Ads (the chat card's target_url). | [optional] |
|
|
34
|
-
| **lead_gen_form_id** | **String** |
|
|
34
|
+
| **lead_gen_form_id** | **String** | Lead Gen form ID to attach to the ad's creative. REQUIRED when `goal` is `lead_generation`. Create one via POST /v1/ads/lead-forms. On Meta (facebook/instagram) this is the leadgen_forms ID; the ad set's promoted_object.page_id + LEAD_GENERATION optimization + destination_type ON_AD are derived automatically from the goal. On LinkedIn this is the adForm ID; the creative's `leadgenCallToAction.destination` is set to `urn:li:adForm:{id}` and the campaign objective is set to MAX_LEAD. Forms must be owned by the sponsoredAccount (not the organization) for the URN to resolve. Also required on every Meta ATTACH (`adSetId`) call that targets a lead ad set (the form attaches per-ad; Meta rejects a formless ad in a lead ad set). Both `placementAssets` (per-placement creative) and `dynamicCreative` (multi-text / multi-asset pool, e.g. multiple headlines and primary texts) ARE supported on Meta instant-form lead ads. | [optional] |
|
|
35
35
|
| **image_url** | **String** | Image creative for Meta/Google/Pinterest/LinkedIn on legacy + attach shapes (mutually exclusive with `video`). Required for LinkedIn ads unless `video` is set. Not required for Google Search campaigns. For TikTok, this field carries the VIDEO URL (the TikTok ads endpoint is video-only; the field retains the `imageUrl` name for cross-platform consistency). Ignored for X/Twitter. For Google Display, treated as the landscape image (alias of `images.landscape`); supply `images.square` alongside or the request is rejected. For LinkedIn the image is uploaded to LinkedIn under the authoring Company Page (see `organizationId`); recommended ratio 1.91:1 (e.g. 1200×627). Required for OpenAI Ads (uploaded as the chat card's image; OpenAI has no video ad format). | [optional] |
|
|
36
36
|
| **images** | [**CreateStandaloneAdRequestImages**](CreateStandaloneAdRequestImages.md) | | [optional] |
|
|
37
37
|
| **video** | [**CreateStandaloneAdRequestVideo**](CreateStandaloneAdRequestVideo.md) | | [optional] |
|
data/docs/PostCreateResponse.md
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **message** | **String** | | [optional] |
|
|
8
8
|
| **post** | [**Post**](Post.md) | | [optional] |
|
|
9
|
+
| **warnings** | **Array<String>** | Advisory notices about a post that was still created: media truncated for a platform, a recycling caveat, or a field that was ignored because it sat outside platforms[].platformSpecificData. Absent when there are none. | [optional] |
|
|
9
10
|
|
|
10
11
|
## Example
|
|
11
12
|
|
|
@@ -14,7 +15,8 @@ require 'zernio-sdk'
|
|
|
14
15
|
|
|
15
16
|
instance = Zernio::PostCreateResponse.new(
|
|
16
17
|
message: null,
|
|
17
|
-
post: null
|
|
18
|
+
post: null,
|
|
19
|
+
warnings: null
|
|
18
20
|
)
|
|
19
21
|
```
|
|
20
22
|
|
data/docs/PostsApi.md
CHANGED
|
@@ -22,7 +22,7 @@ All URIs are relative to *https://zernio.com/api*
|
|
|
22
22
|
|
|
23
23
|
Bulk upload from CSV
|
|
24
24
|
|
|
25
|
-
Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts.
|
|
25
|
+
Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts. CSV columns: - Required: `platforms`, `profiles`, and a schedule (one of `schedule_time`, a `schedule_time_<platform>` override, `publish_now=true`, `use_queue=true`, or `is_draft=true`). - Content: at least one of `post_content`, `title`, or `media_urls` is required. - Aliases: a handful of columns accept the JSON field name from POST /v1/posts, since integrators infer the CSV shape from that endpoint's body. When both are present the real CSV column wins, unless it is blank for that row, in which case the alias value is used. - `content` aliases `post_content` - `timezone` aliases `tz` - `scheduledFor` aliases `schedule_time` - `mediaUrls` aliases `media_urls` - Per-platform overrides use three dynamic column prefixes, one column per platform (e.g. `schedule_time_instagram`, `custom_content_tiktok`, `custom_media_youtube`): `schedule_time_<platform>`, `custom_content_<platform>`, `custom_media_<platform>`. - Any other column is not read. It does not error, but it is reported in the response's `warnings` array as `unknown_columns:<a,b,c>` (see BulkUploadResult), so a misnamed or unsupported column is never silently dropped. - Row limits: 5000 rows is a hard cap that returns 400 above it. 500 rows is only an advisory threshold, it adds `rows_exceed_advisory_limit:500` to `warnings` and the request still processes. Example row (header + one data row): ``` post_content,platforms,profiles,schedule_time,tz \"Hello world\",instagram,MyProfile,2026-09-01 10:00,America/New_York ```
|
|
26
26
|
|
|
27
27
|
### Examples
|
|
28
28
|
|
|
@@ -1545,7 +1545,7 @@ module Zernio
|
|
|
1545
1545
|
end
|
|
1546
1546
|
|
|
1547
1547
|
# Update ad
|
|
1548
|
-
# 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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **Pinterest / X /
|
|
1548
|
+
# 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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **LinkedIn**: status, budget, targeting (geo countries only, applied to the LinkedIn Campaign via PARTIAL_UPDATE), 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).
|
|
1549
1549
|
# @param ad_id [String]
|
|
1550
1550
|
# @param update_ad_request [UpdateAdRequest]
|
|
1551
1551
|
# @param [Hash] opts the optional parameters
|
|
@@ -1556,7 +1556,7 @@ module Zernio
|
|
|
1556
1556
|
end
|
|
1557
1557
|
|
|
1558
1558
|
# Update ad
|
|
1559
|
-
# 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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **Pinterest / X /
|
|
1559
|
+
# 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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **LinkedIn**: status, budget, targeting (geo countries only, applied to the LinkedIn Campaign via PARTIAL_UPDATE), 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).
|
|
1560
1560
|
# @param ad_id [String]
|
|
1561
1561
|
# @param update_ad_request [UpdateAdRequest]
|
|
1562
1562
|
# @param [Hash] opts the optional parameters
|
|
@@ -20,7 +20,7 @@ module Zernio
|
|
|
20
20
|
@api_client = api_client
|
|
21
21
|
end
|
|
22
22
|
# Bulk upload from CSV
|
|
23
|
-
# Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts.
|
|
23
|
+
# Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts. CSV columns: - Required: `platforms`, `profiles`, and a schedule (one of `schedule_time`, a `schedule_time_<platform>` override, `publish_now=true`, `use_queue=true`, or `is_draft=true`). - Content: at least one of `post_content`, `title`, or `media_urls` is required. - Aliases: a handful of columns accept the JSON field name from POST /v1/posts, since integrators infer the CSV shape from that endpoint's body. When both are present the real CSV column wins, unless it is blank for that row, in which case the alias value is used. - `content` aliases `post_content` - `timezone` aliases `tz` - `scheduledFor` aliases `schedule_time` - `mediaUrls` aliases `media_urls` - Per-platform overrides use three dynamic column prefixes, one column per platform (e.g. `schedule_time_instagram`, `custom_content_tiktok`, `custom_media_youtube`): `schedule_time_<platform>`, `custom_content_<platform>`, `custom_media_<platform>`. - Any other column is not read. It does not error, but it is reported in the response's `warnings` array as `unknown_columns:<a,b,c>` (see BulkUploadResult), so a misnamed or unsupported column is never silently dropped. - Row limits: 5000 rows is a hard cap that returns 400 above it. 500 rows is only an advisory threshold, it adds `rows_exceed_advisory_limit:500` to `warnings` and the request still processes. Example row (header + one data row): ``` post_content,platforms,profiles,schedule_time,tz \"Hello world\",instagram,MyProfile,2026-09-01 10:00,America/New_York ```
|
|
24
24
|
# @param [Hash] opts the optional parameters
|
|
25
25
|
# @option opts [Boolean] :dry_run (default to false)
|
|
26
26
|
# @option opts [File] :file
|
|
@@ -31,7 +31,7 @@ module Zernio
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Bulk upload from CSV
|
|
34
|
-
# Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts.
|
|
34
|
+
# Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts. CSV columns: - Required: `platforms`, `profiles`, and a schedule (one of `schedule_time`, a `schedule_time_<platform>` override, `publish_now=true`, `use_queue=true`, or `is_draft=true`). - Content: at least one of `post_content`, `title`, or `media_urls` is required. - Aliases: a handful of columns accept the JSON field name from POST /v1/posts, since integrators infer the CSV shape from that endpoint's body. When both are present the real CSV column wins, unless it is blank for that row, in which case the alias value is used. - `content` aliases `post_content` - `timezone` aliases `tz` - `scheduledFor` aliases `schedule_time` - `mediaUrls` aliases `media_urls` - Per-platform overrides use three dynamic column prefixes, one column per platform (e.g. `schedule_time_instagram`, `custom_content_tiktok`, `custom_media_youtube`): `schedule_time_<platform>`, `custom_content_<platform>`, `custom_media_<platform>`. - Any other column is not read. It does not error, but it is reported in the response's `warnings` array as `unknown_columns:<a,b,c>` (see BulkUploadResult), so a misnamed or unsupported column is never silently dropped. - Row limits: 5000 rows is a hard cap that returns 400 above it. 500 rows is only an advisory threshold, it adds `rows_exceed_advisory_limit:500` to `warnings` and the request still processes. Example row (header + one data row): ``` post_content,platforms,profiles,schedule_time,tz \"Hello world\",instagram,MyProfile,2026-09-01 10:00,America/New_York ```
|
|
35
35
|
# @param [Hash] opts the optional parameters
|
|
36
36
|
# @option opts [Boolean] :dry_run (default to false)
|
|
37
37
|
# @option opts [File] :file
|
|
@@ -87,6 +87,12 @@ module Zernio
|
|
|
87
87
|
# 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.
|
|
88
88
|
attr_accessor :dsa_payor
|
|
89
89
|
|
|
90
|
+
# 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.
|
|
91
|
+
attr_accessor :lead_gen_form_id
|
|
92
|
+
|
|
93
|
+
# Meta, TikTok, and LinkedIn. Publish state of the created entities. Omitted or ACTIVE publishes live (default); PAUSED creates them paused so you can review before they spend. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each).
|
|
94
|
+
attr_accessor :status
|
|
95
|
+
|
|
90
96
|
# Meta only. Explicit ad-set `optimization_goal` override. When omitted, defaults to the value derived from `goal`. The value must be compatible with the objective Meta derives from `goal`, not with the objective used by `POST /v1/ads/create` for the same `goal` name: boost maps `goal: \"engagement\"` to objective `OUTCOME_AWARENESS`, which accepts `REACH`, `IMPRESSIONS`, `AD_RECALL_LIFT`, or THRUPLAY-class values, and rejects `POST_ENGAGEMENT` (that value is only valid under `OUTCOME_ENGAGEMENT`, which create uses for the same goal name).
|
|
91
97
|
attr_accessor :optimization_goal
|
|
92
98
|
|
|
@@ -141,6 +147,8 @@ module Zernio
|
|
|
141
147
|
:'spark_auth_code' => :'sparkAuthCode',
|
|
142
148
|
:'dsa_beneficiary' => :'dsaBeneficiary',
|
|
143
149
|
:'dsa_payor' => :'dsaPayor',
|
|
150
|
+
:'lead_gen_form_id' => :'leadGenFormId',
|
|
151
|
+
:'status' => :'status',
|
|
144
152
|
:'optimization_goal' => :'optimizationGoal'
|
|
145
153
|
}
|
|
146
154
|
end
|
|
@@ -184,6 +192,8 @@ module Zernio
|
|
|
184
192
|
:'spark_auth_code' => :'String',
|
|
185
193
|
:'dsa_beneficiary' => :'String',
|
|
186
194
|
:'dsa_payor' => :'String',
|
|
195
|
+
:'lead_gen_form_id' => :'String',
|
|
196
|
+
:'status' => :'String',
|
|
187
197
|
:'optimization_goal' => :'String'
|
|
188
198
|
}
|
|
189
199
|
end
|
|
@@ -328,6 +338,14 @@ module Zernio
|
|
|
328
338
|
self.dsa_payor = attributes[:'dsa_payor']
|
|
329
339
|
end
|
|
330
340
|
|
|
341
|
+
if attributes.key?(:'lead_gen_form_id')
|
|
342
|
+
self.lead_gen_form_id = attributes[:'lead_gen_form_id']
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
if attributes.key?(:'status')
|
|
346
|
+
self.status = attributes[:'status']
|
|
347
|
+
end
|
|
348
|
+
|
|
331
349
|
if attributes.key?(:'optimization_goal')
|
|
332
350
|
self.optimization_goal = attributes[:'optimization_goal']
|
|
333
351
|
end
|
|
@@ -394,6 +412,8 @@ module Zernio
|
|
|
394
412
|
return false if !@currency.nil? && @currency.to_s.length < 3
|
|
395
413
|
return false if !@dsa_beneficiary.nil? && @dsa_beneficiary.to_s.length > 100
|
|
396
414
|
return false if !@dsa_payor.nil? && @dsa_payor.to_s.length > 100
|
|
415
|
+
status_validator = EnumAttributeValidator.new('String', ["ACTIVE", "PAUSED"])
|
|
416
|
+
return false unless status_validator.valid?(@status)
|
|
397
417
|
true
|
|
398
418
|
end
|
|
399
419
|
|
|
@@ -497,6 +517,16 @@ module Zernio
|
|
|
497
517
|
@dsa_payor = dsa_payor
|
|
498
518
|
end
|
|
499
519
|
|
|
520
|
+
# Custom attribute writer method checking allowed values (enum).
|
|
521
|
+
# @param [Object] status Object to be assigned
|
|
522
|
+
def status=(status)
|
|
523
|
+
validator = EnumAttributeValidator.new('String', ["ACTIVE", "PAUSED"])
|
|
524
|
+
unless validator.valid?(status)
|
|
525
|
+
fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}."
|
|
526
|
+
end
|
|
527
|
+
@status = status
|
|
528
|
+
end
|
|
529
|
+
|
|
500
530
|
# Checks equality by comparing each attribute.
|
|
501
531
|
# @param [Object] Object to be compared
|
|
502
532
|
def ==(o)
|
|
@@ -528,6 +558,8 @@ module Zernio
|
|
|
528
558
|
spark_auth_code == o.spark_auth_code &&
|
|
529
559
|
dsa_beneficiary == o.dsa_beneficiary &&
|
|
530
560
|
dsa_payor == o.dsa_payor &&
|
|
561
|
+
lead_gen_form_id == o.lead_gen_form_id &&
|
|
562
|
+
status == o.status &&
|
|
531
563
|
optimization_goal == o.optimization_goal
|
|
532
564
|
end
|
|
533
565
|
|
|
@@ -540,7 +572,7 @@ module Zernio
|
|
|
540
572
|
# Calculates hash code according to all attributes.
|
|
541
573
|
# @return [Integer] Hash code
|
|
542
574
|
def hash
|
|
543
|
-
[post_id, platform_post_id, account_id, ad_account_id, name, goal, ad_set_id, budget, instagram_account_id, destination_type, currency, schedule, targeting, raw_targeting, bid_strategy, bid_amount, roas_average_floor, platform_specific_data, tracking, special_ad_categories, special_ad_category_country, link_url, call_to_action, spark_auth_code, dsa_beneficiary, dsa_payor, optimization_goal].hash
|
|
575
|
+
[post_id, platform_post_id, account_id, ad_account_id, name, goal, ad_set_id, budget, instagram_account_id, destination_type, currency, schedule, targeting, raw_targeting, bid_strategy, bid_amount, roas_average_floor, platform_specific_data, tracking, special_ad_categories, special_ad_category_country, link_url, call_to_action, spark_auth_code, dsa_beneficiary, dsa_payor, lead_gen_form_id, status, optimization_goal].hash
|
|
544
576
|
end
|
|
545
577
|
|
|
546
578
|
# Builds the object from hash
|
|
@@ -28,7 +28,7 @@ module Zernio
|
|
|
28
28
|
# One entry per CSV data row, in row order.
|
|
29
29
|
attr_accessor :results
|
|
30
30
|
|
|
31
|
-
# Top-level advisory warnings
|
|
31
|
+
# Top-level advisory warnings, e.g. `rows_exceed_advisory_limit:500` or `unknown_columns:<a,b,c>` (comma-separated unrecognized CSV column names). Empty when none.
|
|
32
32
|
attr_accessor :warnings
|
|
33
33
|
|
|
34
34
|
# Present only when one or more rows targeted an account currently in cooldown. Lets callers map `rate_limited:*` row errors back to structured metadata without parsing the error strings.
|
|
@@ -32,7 +32,7 @@ module Zernio
|
|
|
32
32
|
|
|
33
33
|
attr_accessor :tracking
|
|
34
34
|
|
|
35
|
-
# Required on legacy and multi-creative shapes; the attach shape inherits it from the ad set. Available goals vary by platform. **Meta** - `conversions`: OUTCOME_SALES. Requires `promotedObject.pixelId` and `promotedObject.customEventType` with a commerce event such as PURCHASE or START_TRIAL, or `promotedObject.customConversionId` to optimise against a Custom Conversion, or `customEventType: OTHER` + `customEventStr` to optimise against a pixel custom event. - `lead_conversion`: OUTCOME_LEADS optimizing website pixel leads. Same pixel and event fields, but with a leads-class event such as LEAD, SUBMIT_APPLICATION, SCHEDULE or CONTACT (or `promotedObject.customConversionId` to optimise against a Custom Conversion instead). Meta gates conversion events by objective, so leads-class events are rejected under `conversions`. - `lead_generation`: OUTCOME_LEADS with instant forms. Requires `leadGenFormId`. `promotedObject.pageId` is optional and auto-filled from the connected Page. - `app_promotion`: requires `promotedObject.applicationId` and `promotedObject.objectStoreUrl`. - `catalog_sales`: Advantage+ catalog ads, for example vehicle inventory. Requires `promotedObject.productSetId`, `promotedObject.pixelId` and `promotedObject.customEventType`. Builds a catalog TEMPLATE creative from the copy fields, which may carry template tags like {{product.name}} or {{vehicle.make}}. No imageUrl or video is sent; Meta renders the visuals per catalog item. Discover catalogs via GET /v1/ads/catalogs and product sets via GET /v1/ads/catalogs/{catalogId}/product-sets. Single shape only, no creatives[], adSetId, dynamicCreative or placementAssets. - `page_likes`: Page Likes conversion location under OUTCOME_ENGAGEMENT (destination_type ON_PAGE, optimization PAGE_LIKES). `promotedObject.pageId` is optional and auto-filled from the connected Page. The creative CTA is fixed to LIKE_PAGE targeting that Page; headline / body / linkUrl / callToAction / imageUrl / video are all optional (Meta derives the link and the Like button from the Page). **TikTok** - `conversions`: website-conversion ad group. Requires `promotedObject.pixelId`, your TikTok Pixel ID. Accepts an optional `promotedObject.customEventType` with a TikTok optimization_event code your pixel tracks (newer pixels use e.g. SHOPPING for purchase events; legacy pixels use ON_WEB_ORDER, INITIATE_ORDER, ON_WEB_REGISTER or FORM). To inherit pixel and event from an existing ad group, pass `adSetId` instead. **LinkedIn** - `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`. - `job_applicants` requires a `platformSpecificData.jobs` creative. - For `
|
|
35
|
+
# Required on legacy and multi-creative shapes; the attach shape inherits it from the ad set. Available goals vary by platform. **Meta** - `conversions`: OUTCOME_SALES. Requires `promotedObject.pixelId` and `promotedObject.customEventType` with a commerce event such as PURCHASE or START_TRIAL, or `promotedObject.customConversionId` to optimise against a Custom Conversion, or `customEventType: OTHER` + `customEventStr` to optimise against a pixel custom event. - `lead_conversion`: OUTCOME_LEADS optimizing website pixel leads. Same pixel and event fields, but with a leads-class event such as LEAD, SUBMIT_APPLICATION, SCHEDULE or CONTACT (or `promotedObject.customConversionId` to optimise against a Custom Conversion instead). Meta gates conversion events by objective, so leads-class events are rejected under `conversions`. - `lead_generation`: OUTCOME_LEADS with instant forms. Requires `leadGenFormId`. `promotedObject.pageId` is optional and auto-filled from the connected Page. - `app_promotion`: requires `promotedObject.applicationId` and `promotedObject.objectStoreUrl`. - `catalog_sales`: Advantage+ catalog ads, for example vehicle inventory. Requires `promotedObject.productSetId`, `promotedObject.pixelId` and `promotedObject.customEventType`. Builds a catalog TEMPLATE creative from the copy fields, which may carry template tags like {{product.name}} or {{vehicle.make}}. No imageUrl or video is sent; Meta renders the visuals per catalog item. Discover catalogs via GET /v1/ads/catalogs and product sets via GET /v1/ads/catalogs/{catalogId}/product-sets. Single shape only, no creatives[], adSetId, dynamicCreative or placementAssets. - `page_likes`: Page Likes conversion location under OUTCOME_ENGAGEMENT (destination_type ON_PAGE, optimization PAGE_LIKES). `promotedObject.pageId` is optional and auto-filled from the connected Page. The creative CTA is fixed to LIKE_PAGE targeting that Page; headline / body / linkUrl / callToAction / imageUrl / video are all optional (Meta derives the link and the Like button from the Page). **TikTok** - `conversions`: website-conversion ad group. Requires `promotedObject.pixelId`, your TikTok Pixel ID. Accepts an optional `promotedObject.customEventType` with a TikTok optimization_event code your pixel tracks (newer pixels use e.g. SHOPPING for purchase events; legacy pixels use ON_WEB_ORDER, INITIATE_ORDER, ON_WEB_REGISTER or FORM). To inherit pixel and event from an existing ad group, pass `adSetId` instead. **LinkedIn** - `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`. - `lead_generation`: requires `leadGenFormId` (an adForm ID from POST /v1/ads/lead-forms). The campaign objective is set to MAX_LEAD and the creative's `leadgenCallToAction` destination is set to `urn:li:adForm:{id}`. - `job_applicants` requires a `platformSpecificData.jobs` creative. - For `conversions` on LinkedIn, or to promote an existing post, use POST /v1/ads/boost. **OpenAI Ads** - Only `traffic`, `awareness`, and `conversions` are supported (other goals return 400). Maps to OpenAI's `bidding_type` (clicks, impressions, conversions respectively). `conversions` requires an active conversion event setting on the account; create a tracking tag with `defaultEventType` via the tracking-tags API (`POST /v1/accounts/{accountId}/tracking-tags`), or configure a conversion event in OpenAI Ads Manager, or the request returns 422.
|
|
36
36
|
attr_accessor :goal
|
|
37
37
|
|
|
38
38
|
# Meta only. Explicit ad-set `optimization_goal` (e.g. `LANDING_PAGE_VIEWS`, `LINK_CLICKS`, `REACH`, `IMPRESSIONS`, `OFFSITE_CONVERSIONS`, `THRUPLAY`, `LEAD_GENERATION`). Overrides the default derived from `goal` (e.g. `traffic` defaults to `LINK_CLICKS`). Forwarded verbatim to Meta, which validates compatibility with the campaign objective and rejects incompatible combinations.
|
|
@@ -62,7 +62,7 @@ module Zernio
|
|
|
62
62
|
# Required on legacy + multi-creative shapes. Inherited on attach. OpenAI Ads accepts lifetime only (no daily-budget concept on the platform); sending daily returns 422. OpenAI Ads lifetime budgets require `endDate` to give the lifetime cap a spend window.
|
|
63
63
|
attr_accessor :budget_type
|
|
64
64
|
|
|
65
|
-
# Meta and
|
|
65
|
+
# Meta, TikTok, and LinkedIn. Publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each).
|
|
66
66
|
attr_accessor :status
|
|
67
67
|
|
|
68
68
|
# Meta only. Overrides `status` for the campaign level alone, so you can create a live campaign whose ad set and ad stay paused, or the reverse. Omitted, it follows `status`.
|
|
@@ -92,7 +92,7 @@ module Zernio
|
|
|
92
92
|
# Required on legacy + attach shapes (skip for multi-creative). On LinkedIn it's the ad's destination URL; required for `traffic` ads, optional for `engagement` / `awareness`. NOT required when `goal` is `lead_generation` (the ad opens a Lead Gen form instead of a destination). On LinkedIn, `imageUrl` + `linkUrl` publishes an ARTICLE-content creative; this is LinkedIn's article ad format, with the image as thumbnail and `longHeadline` as description. Required for OpenAI Ads (the chat card's target_url).
|
|
93
93
|
attr_accessor :link_url
|
|
94
94
|
|
|
95
|
-
#
|
|
95
|
+
# Lead Gen form ID to attach to the ad's creative. REQUIRED when `goal` is `lead_generation`. Create one via POST /v1/ads/lead-forms. On Meta (facebook/instagram) this is the leadgen_forms ID; the ad set's promoted_object.page_id + LEAD_GENERATION optimization + destination_type ON_AD are derived automatically from the goal. On LinkedIn this is the adForm ID; the creative's `leadgenCallToAction.destination` is set to `urn:li:adForm:{id}` and the campaign objective is set to MAX_LEAD. Forms must be owned by the sponsoredAccount (not the organization) for the URN to resolve. Also required on every Meta ATTACH (`adSetId`) call that targets a lead ad set (the form attaches per-ad; Meta rejects a formless ad in a lead ad set). Both `placementAssets` (per-placement creative) and `dynamicCreative` (multi-text / multi-asset pool, e.g. multiple headlines and primary texts) ARE supported on Meta instant-form lead ads.
|
|
96
96
|
attr_accessor :lead_gen_form_id
|
|
97
97
|
|
|
98
98
|
# Image creative for Meta/Google/Pinterest/LinkedIn on legacy + attach shapes (mutually exclusive with `video`). Required for LinkedIn ads unless `video` is set. Not required for Google Search campaigns. For TikTok, this field carries the VIDEO URL (the TikTok ads endpoint is video-only; the field retains the `imageUrl` name for cross-platform consistency). Ignored for X/Twitter. For Google Display, treated as the landscape image (alias of `images.landscape`); supply `images.square` alongside or the request is rejected. For LinkedIn the image is uploaded to LinkedIn under the authoring Company Page (see `organizationId`); recommended ratio 1.91:1 (e.g. 1200×627). Required for OpenAI Ads (uploaded as the chat card's image; OpenAI has no video ad format).
|
|
@@ -19,11 +19,15 @@ module Zernio
|
|
|
19
19
|
|
|
20
20
|
attr_accessor :post
|
|
21
21
|
|
|
22
|
+
# Advisory notices about a post that was still created: media truncated for a platform, a recycling caveat, or a field that was ignored because it sat outside platforms[].platformSpecificData. Absent when there are none.
|
|
23
|
+
attr_accessor :warnings
|
|
24
|
+
|
|
22
25
|
# Attribute mapping from ruby-style variable name to JSON key.
|
|
23
26
|
def self.attribute_map
|
|
24
27
|
{
|
|
25
28
|
:'message' => :'message',
|
|
26
|
-
:'post' => :'post'
|
|
29
|
+
:'post' => :'post',
|
|
30
|
+
:'warnings' => :'warnings'
|
|
27
31
|
}
|
|
28
32
|
end
|
|
29
33
|
|
|
@@ -41,7 +45,8 @@ module Zernio
|
|
|
41
45
|
def self.openapi_types
|
|
42
46
|
{
|
|
43
47
|
:'message' => :'String',
|
|
44
|
-
:'post' => :'Post'
|
|
48
|
+
:'post' => :'Post',
|
|
49
|
+
:'warnings' => :'Array<String>'
|
|
45
50
|
}
|
|
46
51
|
end
|
|
47
52
|
|
|
@@ -74,6 +79,12 @@ module Zernio
|
|
|
74
79
|
if attributes.key?(:'post')
|
|
75
80
|
self.post = attributes[:'post']
|
|
76
81
|
end
|
|
82
|
+
|
|
83
|
+
if attributes.key?(:'warnings')
|
|
84
|
+
if (value = attributes[:'warnings']).is_a?(Array)
|
|
85
|
+
self.warnings = value
|
|
86
|
+
end
|
|
87
|
+
end
|
|
77
88
|
end
|
|
78
89
|
|
|
79
90
|
# Show invalid properties with the reasons. Usually used together with valid?
|
|
@@ -97,7 +108,8 @@ module Zernio
|
|
|
97
108
|
return true if self.equal?(o)
|
|
98
109
|
self.class == o.class &&
|
|
99
110
|
message == o.message &&
|
|
100
|
-
post == o.post
|
|
111
|
+
post == o.post &&
|
|
112
|
+
warnings == o.warnings
|
|
101
113
|
end
|
|
102
114
|
|
|
103
115
|
# @see the `==` method
|
|
@@ -109,7 +121,7 @@ module Zernio
|
|
|
109
121
|
# Calculates hash code according to all attributes.
|
|
110
122
|
# @return [Integer] Hash code
|
|
111
123
|
def hash
|
|
112
|
-
[message, post].hash
|
|
124
|
+
[message, post, warnings].hash
|
|
113
125
|
end
|
|
114
126
|
|
|
115
127
|
# Builds the object from hash
|
|
@@ -14,7 +14,7 @@ require 'date'
|
|
|
14
14
|
require 'time'
|
|
15
15
|
|
|
16
16
|
module Zernio
|
|
17
|
-
# Replace the ad's creative. Meta
|
|
17
|
+
# Replace the ad's creative. Meta, TikTok, and LinkedIn. - **Meta**: requires `headline`, `body`, `callToAction`, `linkUrl`, `imageUrl`. The ad's existing creative is replaced via a new `/act_X/adcreatives` upload + ad update. The old creative is retained on the ad account for historical reporting. - **TikTok**: patch-style. Pass any subset; `headline` is ignored (TikTok creatives have no headline slot). `body` becomes the in-feed `ad_text`; `linkUrl` becomes `landing_page_url`; `videoUrl` triggers a fresh upload. - **LinkedIn**: uploads new media (image via `imageUrl` or video via `videoUrl`), creates a new inline media creative on the same campaign, and pauses the old creative (best-effort). The old creative is retained for historical reporting.
|
|
18
18
|
class UpdateAdRequestCreative < ApiModelBase
|
|
19
19
|
# Meta only
|
|
20
20
|
attr_accessor :headline
|
|
@@ -14,7 +14,7 @@ require 'date'
|
|
|
14
14
|
require 'time'
|
|
15
15
|
|
|
16
16
|
module Zernio
|
|
17
|
-
# Meta + TikTok (demographics/interests)
|
|
17
|
+
# Meta + TikTok (demographics/interests), Google (keyword edits only), and LinkedIn (geo countries). Pinterest / X return 501.
|
|
18
18
|
class UpdateAdRequestTargeting < ApiModelBase
|
|
19
19
|
# Google only. The FULL new set of positive keywords for the ad group; live keywords not listed are removed. Entries are strings (BROAD) or { text, matchType } with matchType exact | phrase | broad. Mirrored to GET /v1/ads/keywords immediately.
|
|
20
20
|
attr_accessor :keywords
|
data/lib/zernio-sdk/version.rb
CHANGED
data/openapi.yaml
CHANGED
|
@@ -1384,7 +1384,7 @@ components:
|
|
|
1384
1384
|
items: { type: string }
|
|
1385
1385
|
warnings:
|
|
1386
1386
|
type: array
|
|
1387
|
-
description: "Top-level advisory warnings
|
|
1387
|
+
description: "Top-level advisory warnings, e.g. `rows_exceed_advisory_limit:500` or `unknown_columns:<a,b,c>` (comma-separated unrecognized CSV column names). Empty when none."
|
|
1388
1388
|
items: { type: string }
|
|
1389
1389
|
rateLimitedAccounts:
|
|
1390
1390
|
type: array
|
|
@@ -7577,6 +7577,11 @@ components:
|
|
|
7577
7577
|
type: string
|
|
7578
7578
|
post:
|
|
7579
7579
|
$ref: '#/components/schemas/Post'
|
|
7580
|
+
warnings:
|
|
7581
|
+
type: array
|
|
7582
|
+
description: 'Advisory notices about a post that was still created: media truncated for a platform, a recycling caveat, or a field that was ignored because it sat outside platforms[].platformSpecificData. Absent when there are none.'
|
|
7583
|
+
items:
|
|
7584
|
+
type: string
|
|
7580
7585
|
PostUpdateResponse:
|
|
7581
7586
|
type: object
|
|
7582
7587
|
properties:
|
|
@@ -15299,7 +15304,26 @@ paths:
|
|
|
15299
15304
|
operationId: bulkUploadPosts
|
|
15300
15305
|
tags: [Posts]
|
|
15301
15306
|
summary: Bulk upload from CSV
|
|
15302
|
-
description:
|
|
15307
|
+
description: |
|
|
15308
|
+
Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts.
|
|
15309
|
+
|
|
15310
|
+
CSV columns:
|
|
15311
|
+
- Required: `platforms`, `profiles`, and a schedule (one of `schedule_time`, a `schedule_time_<platform>` override, `publish_now=true`, `use_queue=true`, or `is_draft=true`).
|
|
15312
|
+
- Content: at least one of `post_content`, `title`, or `media_urls` is required.
|
|
15313
|
+
- Aliases: a handful of columns accept the JSON field name from POST /v1/posts, since integrators infer the CSV shape from that endpoint's body. When both are present the real CSV column wins, unless it is blank for that row, in which case the alias value is used.
|
|
15314
|
+
- `content` aliases `post_content`
|
|
15315
|
+
- `timezone` aliases `tz`
|
|
15316
|
+
- `scheduledFor` aliases `schedule_time`
|
|
15317
|
+
- `mediaUrls` aliases `media_urls`
|
|
15318
|
+
- Per-platform overrides use three dynamic column prefixes, one column per platform (e.g. `schedule_time_instagram`, `custom_content_tiktok`, `custom_media_youtube`): `schedule_time_<platform>`, `custom_content_<platform>`, `custom_media_<platform>`.
|
|
15319
|
+
- Any other column is not read. It does not error, but it is reported in the response's `warnings` array as `unknown_columns:<a,b,c>` (see BulkUploadResult), so a misnamed or unsupported column is never silently dropped.
|
|
15320
|
+
- Row limits: 5000 rows is a hard cap that returns 400 above it. 500 rows is only an advisory threshold, it adds `rows_exceed_advisory_limit:500` to `warnings` and the request still processes.
|
|
15321
|
+
|
|
15322
|
+
Example row (header + one data row):
|
|
15323
|
+
```
|
|
15324
|
+
post_content,platforms,profiles,schedule_time,tz
|
|
15325
|
+
"Hello world",instagram,MyProfile,2026-09-01 10:00,America/New_York
|
|
15326
|
+
```
|
|
15303
15327
|
parameters:
|
|
15304
15328
|
- name: dryRun
|
|
15305
15329
|
in: query
|
|
@@ -41290,7 +41314,10 @@ paths:
|
|
|
41290
41314
|
kind on the ad group (criteria not in the list are removed); a kind left out is
|
|
41291
41315
|
untouched. Any other `targeting` field returns 400: Google cannot mutate broad
|
|
41292
41316
|
targeting post-create without recreating the campaign. `creative` returns 501.
|
|
41293
|
-
- **
|
|
41317
|
+
- **LinkedIn**: status, budget, targeting (geo countries only, applied to the
|
|
41318
|
+
LinkedIn Campaign via PARTIAL_UPDATE), and creative (uploads new media, creates a
|
|
41319
|
+
replacement inline creative on the same campaign, pauses the old one).
|
|
41320
|
+
- **Pinterest / X / OpenAI Ads**: status + budget only. Sending
|
|
41294
41321
|
`targeting` or `creative` returns 501 with code `unsupported_platform_operation`.
|
|
41295
41322
|
OpenAI Ads budget is lifetime-only (see `budget.type` below).
|
|
41296
41323
|
security:
|
|
@@ -41313,8 +41340,8 @@ paths:
|
|
|
41313
41340
|
targeting:
|
|
41314
41341
|
type: object
|
|
41315
41342
|
description: |
|
|
41316
|
-
Meta + TikTok (demographics/interests)
|
|
41317
|
-
Pinterest / X
|
|
41343
|
+
Meta + TikTok (demographics/interests), Google (keyword edits only),
|
|
41344
|
+
and LinkedIn (geo countries). Pinterest / X return 501.
|
|
41318
41345
|
properties:
|
|
41319
41346
|
keywords:
|
|
41320
41347
|
type: array
|
|
@@ -41346,7 +41373,7 @@ paths:
|
|
|
41346
41373
|
creative:
|
|
41347
41374
|
type: object
|
|
41348
41375
|
description: |
|
|
41349
|
-
Replace the ad's creative. Meta
|
|
41376
|
+
Replace the ad's creative. Meta, TikTok, and LinkedIn.
|
|
41350
41377
|
|
|
41351
41378
|
- **Meta**: requires `headline`, `body`, `callToAction`, `linkUrl`, `imageUrl`. The
|
|
41352
41379
|
ad's existing creative is replaced via a new `/act_X/adcreatives` upload + ad
|
|
@@ -41354,6 +41381,9 @@ paths:
|
|
|
41354
41381
|
- **TikTok**: patch-style. Pass any subset; `headline` is ignored (TikTok creatives
|
|
41355
41382
|
have no headline slot). `body` becomes the in-feed `ad_text`; `linkUrl` becomes
|
|
41356
41383
|
`landing_page_url`; `videoUrl` triggers a fresh upload.
|
|
41384
|
+
- **LinkedIn**: uploads new media (image via `imageUrl` or video via `videoUrl`),
|
|
41385
|
+
creates a new inline media creative on the same campaign, and pauses the old
|
|
41386
|
+
creative (best-effort). The old creative is retained for historical reporting.
|
|
41357
41387
|
properties:
|
|
41358
41388
|
headline: { type: string, description: "Meta only" }
|
|
41359
41389
|
body: { type: string }
|
|
@@ -41376,7 +41406,7 @@ paths:
|
|
|
41376
41406
|
description: Invalid status transition or budget below minimum
|
|
41377
41407
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41378
41408
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
41379
|
-
'501': { description: "targeting or creative not supported on the platform (Meta
|
|
41409
|
+
'501': { description: "targeting or creative not supported on the platform (supported on Meta, TikTok, and LinkedIn)" }
|
|
41380
41410
|
'502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
|
|
41381
41411
|
delete:
|
|
41382
41412
|
x-resource-group: "ads"
|
|
@@ -43665,6 +43695,11 @@ paths:
|
|
|
43665
43695
|
(for example, an agency paying for a client's ads). Same rules as
|
|
43666
43696
|
`dsaBeneficiary`: required for EU targeting unless the ad account has
|
|
43667
43697
|
a default payor.
|
|
43698
|
+
leadGenFormId: { type: string, description: "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." }
|
|
43699
|
+
status:
|
|
43700
|
+
type: string
|
|
43701
|
+
enum: [ACTIVE, PAUSED]
|
|
43702
|
+
description: 'Meta, TikTok, and LinkedIn. Publish state of the created entities. Omitted or ACTIVE publishes live (default); PAUSED creates them paused so you can review before they spend. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each).'
|
|
43668
43703
|
optimizationGoal:
|
|
43669
43704
|
type: string
|
|
43670
43705
|
description: |
|
|
@@ -43791,8 +43826,9 @@ paths:
|
|
|
43791
43826
|
|
|
43792
43827
|
**LinkedIn**
|
|
43793
43828
|
- `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`.
|
|
43829
|
+
- `lead_generation`: requires `leadGenFormId` (an adForm ID from POST /v1/ads/lead-forms). The campaign objective is set to MAX_LEAD and the creative's `leadgenCallToAction` destination is set to `urn:li:adForm:{id}`.
|
|
43794
43830
|
- `job_applicants` requires a `platformSpecificData.jobs` creative.
|
|
43795
|
-
- For `
|
|
43831
|
+
- For `conversions` on LinkedIn, or to promote an existing post, use POST /v1/ads/boost.
|
|
43796
43832
|
|
|
43797
43833
|
**OpenAI Ads**
|
|
43798
43834
|
- Only `traffic`, `awareness`, and `conversions` are supported (other goals return 400). Maps to OpenAI's `bidding_type` (clicks, impressions, conversions respectively). `conversions` requires an active conversion event setting on the account; create a tracking tag with `defaultEventType` via the tracking-tags API (`POST /v1/accounts/{accountId}/tracking-tags`), or configure a conversion event in OpenAI Ads Manager, or the request returns 422.
|
|
@@ -43816,7 +43852,7 @@ paths:
|
|
|
43816
43852
|
status:
|
|
43817
43853
|
type: string
|
|
43818
43854
|
enum: [ACTIVE, PAUSED]
|
|
43819
|
-
description: "Meta and
|
|
43855
|
+
description: "Meta, TikTok, and LinkedIn. Publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each)."
|
|
43820
43856
|
campaignStatus:
|
|
43821
43857
|
type: string
|
|
43822
43858
|
enum: [ACTIVE, PAUSED]
|
|
@@ -43841,7 +43877,7 @@ paths:
|
|
|
43841
43877
|
description: { type: string, maxLength: 255, description: "Meta only (facebook/instagram). Link description — the secondary text shown below the headline (Meta's link_data.description; on video creatives mapped to video_data.link_description). When omitted, Meta auto-pulls the destination URL's OpenGraph description. Applies on legacy, attach, and placementAssets shapes; for multi-creative use creatives[].description (this field is the shared fallback). For multi-text variations use dynamicCreative.descriptions instead." }
|
|
43842
43878
|
callToAction: { type: string, enum: [LEARN_MORE, SHOP_NOW, SIGN_UP, BOOK_TRAVEL, CONTACT_US, DOWNLOAD, GET_OFFER, GET_QUOTE, SUBSCRIBE, WATCH_MORE, ADD_TO_CART, APPLY_NOW, BOOK_NOW, BUY_TICKETS, DONATE, DONATE_NOW, GET_DIRECTIONS, GET_SHOWTIMES, LISTEN_NOW, ORDER_NOW, PLAY_GAME, REQUEST_TIME, SEE_MENU, START_ORDER, INSTALL_MOBILE_APP, USE_APP, REGISTER, JOIN, ATTEND, REQUEST_DEMO, VIEW_QUOTE, APPLY, SEE_MORE, BUY_NOW], description: "Required on legacy + attach shapes for Meta. Honoured on TikTok (passes through to the Spark Ad creative's `call_to_action`) and on LinkedIn (the CTA button on the ad; defaults to LEARN_MORE when `linkUrl` is set). LinkedIn accepts: LEARN_MORE, SIGN_UP, DOWNLOAD, SUBSCRIBE, REGISTER, JOIN, ATTEND, REQUEST_DEMO, VIEW_QUOTE, APPLY, SEE_MORE, SHOP_NOW, BUY_NOW. Ignored by Google, Pinterest, and X/Twitter." }
|
|
43843
43879
|
linkUrl: { type: string, format: uri, description: "Required on legacy + attach shapes (skip for multi-creative). On LinkedIn it's the ad's destination URL; required for `traffic` ads, optional for `engagement` / `awareness`. NOT required when `goal` is `lead_generation` (the ad opens a Lead Gen form instead of a destination). On LinkedIn, `imageUrl` + `linkUrl` publishes an ARTICLE-content creative; this is LinkedIn's article ad format, with the image as thumbnail and `longHeadline` as description. Required for OpenAI Ads (the chat card's target_url)." }
|
|
43844
|
-
leadGenFormId: { type: string, description: "
|
|
43880
|
+
leadGenFormId: { type: string, description: "Lead Gen form ID to attach to the ad's creative. REQUIRED when `goal` is `lead_generation`. Create one via POST /v1/ads/lead-forms. On Meta (facebook/instagram) this is the leadgen_forms ID; the ad set's promoted_object.page_id + LEAD_GENERATION optimization + destination_type ON_AD are derived automatically from the goal. On LinkedIn this is the adForm ID; the creative's `leadgenCallToAction.destination` is set to `urn:li:adForm:{id}` and the campaign objective is set to MAX_LEAD. Forms must be owned by the sponsoredAccount (not the organization) for the URN to resolve. Also required on every Meta ATTACH (`adSetId`) call that targets a lead ad set (the form attaches per-ad; Meta rejects a formless ad in a lead ad set). Both `placementAssets` (per-placement creative) and `dynamicCreative` (multi-text / multi-asset pool, e.g. multiple headlines and primary texts) ARE supported on Meta instant-form lead ads." }
|
|
43845
43881
|
imageUrl: { type: string, format: uri, description: "Image creative for Meta/Google/Pinterest/LinkedIn on legacy + attach shapes (mutually exclusive with `video`). Required for LinkedIn ads unless `video` is set. Not required for Google Search campaigns. For TikTok, this field carries the VIDEO URL (the TikTok ads endpoint is video-only; the field retains the `imageUrl` name for cross-platform consistency). Ignored for X/Twitter. For Google Display, treated as the landscape image (alias of `images.landscape`); supply `images.square` alongside or the request is rejected. For LinkedIn the image is uploaded to LinkedIn under the authoring Company Page (see `organizationId`); recommended ratio 1.91:1 (e.g. 1200×627). Required for OpenAI Ads (uploaded as the chat card's image; OpenAI has no video ad format)." }
|
|
43846
43882
|
images:
|
|
43847
43883
|
type: object
|
|
@@ -320,7 +320,7 @@ describe 'AdCampaignsApi' do
|
|
|
320
320
|
|
|
321
321
|
# unit tests for update_ad
|
|
322
322
|
# Update ad
|
|
323
|
-
# 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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **Pinterest / X /
|
|
323
|
+
# 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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **LinkedIn**: status, budget, targeting (geo countries only, applied to the LinkedIn Campaign via PARTIAL_UPDATE), 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).
|
|
324
324
|
# @param ad_id
|
|
325
325
|
# @param update_ad_request
|
|
326
326
|
# @param [Hash] opts the optional parameters
|
data/spec/api/posts_api_spec.rb
CHANGED
|
@@ -34,7 +34,7 @@ describe 'PostsApi' do
|
|
|
34
34
|
|
|
35
35
|
# unit tests for bulk_upload_posts
|
|
36
36
|
# Bulk upload from CSV
|
|
37
|
-
# Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts.
|
|
37
|
+
# Create multiple posts by uploading a CSV file. Use dryRun=true to validate without creating posts. CSV columns: - Required: `platforms`, `profiles`, and a schedule (one of `schedule_time`, a `schedule_time_<platform>` override, `publish_now=true`, `use_queue=true`, or `is_draft=true`). - Content: at least one of `post_content`, `title`, or `media_urls` is required. - Aliases: a handful of columns accept the JSON field name from POST /v1/posts, since integrators infer the CSV shape from that endpoint's body. When both are present the real CSV column wins, unless it is blank for that row, in which case the alias value is used. - `content` aliases `post_content` - `timezone` aliases `tz` - `scheduledFor` aliases `schedule_time` - `mediaUrls` aliases `media_urls` - Per-platform overrides use three dynamic column prefixes, one column per platform (e.g. `schedule_time_instagram`, `custom_content_tiktok`, `custom_media_youtube`): `schedule_time_<platform>`, `custom_content_<platform>`, `custom_media_<platform>`. - Any other column is not read. It does not error, but it is reported in the response's `warnings` array as `unknown_columns:<a,b,c>` (see BulkUploadResult), so a misnamed or unsupported column is never silently dropped. - Row limits: 5000 rows is a hard cap that returns 400 above it. 500 rows is only an advisory threshold, it adds `rows_exceed_advisory_limit:500` to `warnings` and the request still processes. Example row (header + one data row): ``` post_content,platforms,profiles,schedule_time,tz \"Hello world\",instagram,MyProfile,2026-09-01 10:00,America/New_York ```
|
|
38
38
|
# @param [Hash] opts the optional parameters
|
|
39
39
|
# @option opts [Boolean] :dry_run
|
|
40
40
|
# @option opts [File] :file
|
|
@@ -195,6 +195,22 @@ describe Zernio::BoostPostRequest do
|
|
|
195
195
|
end
|
|
196
196
|
end
|
|
197
197
|
|
|
198
|
+
describe 'test attribute "lead_gen_form_id"' do
|
|
199
|
+
it 'should work' do
|
|
200
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
describe 'test attribute "status"' do
|
|
205
|
+
it 'should work' do
|
|
206
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
207
|
+
# validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["ACTIVE", "PAUSED"])
|
|
208
|
+
# validator.allowable_values.each do |value|
|
|
209
|
+
# expect { instance.status = value }.not_to raise_error
|
|
210
|
+
# end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
198
214
|
describe 'test attribute "optimization_goal"' do
|
|
199
215
|
it 'should work' do
|
|
200
216
|
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|