zernio-sdk 0.0.805 → 0.0.807
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/README.md +2 -0
- 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/PostsApi.md +1 -1
- data/docs/RedeliverWebhookEventRequest.md +20 -0
- data/docs/WebhooksApi.md +70 -0
- 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/api/webhooks_api.rb +68 -0
- 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/redeliver_webhook_event_request.rb +210 -0
- 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/lib/zernio-sdk.rb +1 -0
- data/openapi.yaml +113 -10
- data/spec/api/ad_campaigns_api_spec.rb +1 -1
- data/spec/api/posts_api_spec.rb +1 -1
- data/spec/api/webhooks_api_spec.rb +12 -0
- data/spec/models/boost_post_request_spec.rb +16 -0
- data/spec/models/redeliver_webhook_event_request_spec.rb +42 -0
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0957d46aef50176f650d15e9dafcd06f9e69993e05e93a0517e7b69d670af9f9'
|
|
4
|
+
data.tar.gz: f2dbb363ac46d9a2a6690390dd92badab898760d34772133cfc492484b0379a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b383d3f69556ad3483c9c31c4bac127d1a820a3b8601de68674ad6cba64956e052b7812d1ed13904f8bdc3400cd7891cac95010b79eb419b55ff8b2f7128da82
|
|
7
|
+
data.tar.gz: 2ed440f19d876f1ce8faa9975926819e53bdbf356d0152239490ba59f74c5846acb4c016746e964c5905d0e15f9253fd99dbaaf3020ffc4eb47a16b38c1715f4
|
data/README.md
CHANGED
|
@@ -568,6 +568,7 @@ Class | Method | HTTP request | Description
|
|
|
568
568
|
*Zernio::WebhooksApi* | [**delete_webhook_settings**](docs/WebhooksApi.md#delete_webhook_settings) | **DELETE** /v1/webhooks/settings | Delete webhook
|
|
569
569
|
*Zernio::WebhooksApi* | [**get_webhook_logs**](docs/WebhooksApi.md#get_webhook_logs) | **GET** /v1/webhooks/logs | List webhook delivery logs
|
|
570
570
|
*Zernio::WebhooksApi* | [**get_webhook_settings**](docs/WebhooksApi.md#get_webhook_settings) | **GET** /v1/webhooks/settings | List webhooks
|
|
571
|
+
*Zernio::WebhooksApi* | [**redeliver_webhook_event**](docs/WebhooksApi.md#redeliver_webhook_event) | **POST** /v1/webhooks/logs/redeliver | Redeliver a webhook event
|
|
571
572
|
*Zernio::WebhooksApi* | [**test_webhook**](docs/WebhooksApi.md#test_webhook) | **POST** /v1/webhooks/test | Send test webhook
|
|
572
573
|
*Zernio::WebhooksApi* | [**update_webhook_settings**](docs/WebhooksApi.md#update_webhook_settings) | **PUT** /v1/webhooks/settings | Update webhook
|
|
573
574
|
*Zernio::WhatsAppApi* | [**add_whats_app_group_participants**](docs/WhatsAppApi.md#add_whats_app_group_participants) | **POST** /v1/whatsapp/wa-groups/{groupId}/participants | Add participants
|
|
@@ -1827,6 +1828,7 @@ Class | Method | HTTP request | Description
|
|
|
1827
1828
|
- [Zernio::RecyclingState](docs/RecyclingState.md)
|
|
1828
1829
|
- [Zernio::RedditPlatformData](docs/RedditPlatformData.md)
|
|
1829
1830
|
- [Zernio::RedditPost](docs/RedditPost.md)
|
|
1831
|
+
- [Zernio::RedeliverWebhookEventRequest](docs/RedeliverWebhookEventRequest.md)
|
|
1830
1832
|
- [Zernio::RegisterWhatsAppNumber200Response](docs/RegisterWhatsAppNumber200Response.md)
|
|
1831
1833
|
- [Zernio::RegisterWhatsAppNumberRequest](docs/RegisterWhatsAppNumberRequest.md)
|
|
1832
1834
|
- [Zernio::RejectWhatsAppGroupJoinRequestsRequest](docs/RejectWhatsAppGroupJoinRequestsRequest.md)
|
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/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
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Zernio::RedeliverWebhookEventRequest
|
|
2
|
+
|
|
3
|
+
## Properties
|
|
4
|
+
|
|
5
|
+
| Name | Type | Description | Notes |
|
|
6
|
+
| ---- | ---- | ----------- | ----- |
|
|
7
|
+
| **webhook_id** | **String** | ID of the webhook subscription that delivered the event | |
|
|
8
|
+
| **event_id** | **String** | Stable event ID of the delivery to replay | |
|
|
9
|
+
|
|
10
|
+
## Example
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
require 'zernio-sdk'
|
|
14
|
+
|
|
15
|
+
instance = Zernio::RedeliverWebhookEventRequest.new(
|
|
16
|
+
webhook_id: null,
|
|
17
|
+
event_id: null
|
|
18
|
+
)
|
|
19
|
+
```
|
|
20
|
+
|
data/docs/WebhooksApi.md
CHANGED
|
@@ -8,6 +8,7 @@ All URIs are relative to *https://zernio.com/api*
|
|
|
8
8
|
| [**delete_webhook_settings**](WebhooksApi.md#delete_webhook_settings) | **DELETE** /v1/webhooks/settings | Delete webhook |
|
|
9
9
|
| [**get_webhook_logs**](WebhooksApi.md#get_webhook_logs) | **GET** /v1/webhooks/logs | List webhook delivery logs |
|
|
10
10
|
| [**get_webhook_settings**](WebhooksApi.md#get_webhook_settings) | **GET** /v1/webhooks/settings | List webhooks |
|
|
11
|
+
| [**redeliver_webhook_event**](WebhooksApi.md#redeliver_webhook_event) | **POST** /v1/webhooks/logs/redeliver | Redeliver a webhook event |
|
|
11
12
|
| [**test_webhook**](WebhooksApi.md#test_webhook) | **POST** /v1/webhooks/test | Send test webhook |
|
|
12
13
|
| [**update_webhook_settings**](WebhooksApi.md#update_webhook_settings) | **PUT** /v1/webhooks/settings | Update webhook |
|
|
13
14
|
|
|
@@ -297,6 +298,75 @@ This endpoint does not need any parameter.
|
|
|
297
298
|
- **Accept**: application/json
|
|
298
299
|
|
|
299
300
|
|
|
301
|
+
## redeliver_webhook_event
|
|
302
|
+
|
|
303
|
+
> <UnpublishPost200Response> redeliver_webhook_event(redeliver_webhook_event_request)
|
|
304
|
+
|
|
305
|
+
Redeliver a webhook event
|
|
306
|
+
|
|
307
|
+
Replay a past delivery: the original payload is re-sent, byte for byte, to the subscription's current URL. The original event ID is preserved so your endpoint can dedupe, and the replay is recorded as a fresh attempt, so it shows up in `GET /v1/webhooks/logs` next to the delivery it replays. Both `webhookId` and `eventId` come from a row of `GET /v1/webhooks/logs`. Because the stored payload is replayed as-is, a redelivery reflects the event as it was emitted, not the current state of the resource. Only deliveries inside the 30-day log retention window can be replayed; past that the payload is gone and the request fails with a 500. Replays run the same resource-group checks as live delivery, against both the key's groups and the subscription's `disabledResourceGroups`.
|
|
308
|
+
|
|
309
|
+
### Examples
|
|
310
|
+
|
|
311
|
+
```ruby
|
|
312
|
+
require 'time'
|
|
313
|
+
require 'zernio-sdk'
|
|
314
|
+
# setup authorization
|
|
315
|
+
Zernio.configure do |config|
|
|
316
|
+
# Configure Bearer authorization (JWT): bearerAuth
|
|
317
|
+
config.access_token = 'YOUR_BEARER_TOKEN'
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
api_instance = Zernio::WebhooksApi.new
|
|
321
|
+
redeliver_webhook_event_request = Zernio::RedeliverWebhookEventRequest.new({webhook_id: 'webhook_id_example', event_id: 'event_id_example'}) # RedeliverWebhookEventRequest |
|
|
322
|
+
|
|
323
|
+
begin
|
|
324
|
+
# Redeliver a webhook event
|
|
325
|
+
result = api_instance.redeliver_webhook_event(redeliver_webhook_event_request)
|
|
326
|
+
p result
|
|
327
|
+
rescue Zernio::ApiError => e
|
|
328
|
+
puts "Error when calling WebhooksApi->redeliver_webhook_event: #{e}"
|
|
329
|
+
end
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### Using the redeliver_webhook_event_with_http_info variant
|
|
333
|
+
|
|
334
|
+
This returns an Array which contains the response data, status code and headers.
|
|
335
|
+
|
|
336
|
+
> <Array(<UnpublishPost200Response>, Integer, Hash)> redeliver_webhook_event_with_http_info(redeliver_webhook_event_request)
|
|
337
|
+
|
|
338
|
+
```ruby
|
|
339
|
+
begin
|
|
340
|
+
# Redeliver a webhook event
|
|
341
|
+
data, status_code, headers = api_instance.redeliver_webhook_event_with_http_info(redeliver_webhook_event_request)
|
|
342
|
+
p status_code # => 2xx
|
|
343
|
+
p headers # => { ... }
|
|
344
|
+
p data # => <UnpublishPost200Response>
|
|
345
|
+
rescue Zernio::ApiError => e
|
|
346
|
+
puts "Error when calling WebhooksApi->redeliver_webhook_event_with_http_info: #{e}"
|
|
347
|
+
end
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### Parameters
|
|
351
|
+
|
|
352
|
+
| Name | Type | Description | Notes |
|
|
353
|
+
| ---- | ---- | ----------- | ----- |
|
|
354
|
+
| **redeliver_webhook_event_request** | [**RedeliverWebhookEventRequest**](RedeliverWebhookEventRequest.md) | | |
|
|
355
|
+
|
|
356
|
+
### Return type
|
|
357
|
+
|
|
358
|
+
[**UnpublishPost200Response**](UnpublishPost200Response.md)
|
|
359
|
+
|
|
360
|
+
### Authorization
|
|
361
|
+
|
|
362
|
+
[bearerAuth](../README.md#bearerAuth)
|
|
363
|
+
|
|
364
|
+
### HTTP request headers
|
|
365
|
+
|
|
366
|
+
- **Content-Type**: application/json
|
|
367
|
+
- **Accept**: application/json
|
|
368
|
+
|
|
369
|
+
|
|
300
370
|
## test_webhook
|
|
301
371
|
|
|
302
372
|
> <UnpublishPost200Response> test_webhook(test_webhook_request)
|
|
@@ -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
|
|
@@ -332,6 +332,74 @@ module Zernio
|
|
|
332
332
|
return data, status_code, headers
|
|
333
333
|
end
|
|
334
334
|
|
|
335
|
+
# Redeliver a webhook event
|
|
336
|
+
# Replay a past delivery: the original payload is re-sent, byte for byte, to the subscription's current URL. The original event ID is preserved so your endpoint can dedupe, and the replay is recorded as a fresh attempt, so it shows up in `GET /v1/webhooks/logs` next to the delivery it replays. Both `webhookId` and `eventId` come from a row of `GET /v1/webhooks/logs`. Because the stored payload is replayed as-is, a redelivery reflects the event as it was emitted, not the current state of the resource. Only deliveries inside the 30-day log retention window can be replayed; past that the payload is gone and the request fails with a 500. Replays run the same resource-group checks as live delivery, against both the key's groups and the subscription's `disabledResourceGroups`.
|
|
337
|
+
# @param redeliver_webhook_event_request [RedeliverWebhookEventRequest]
|
|
338
|
+
# @param [Hash] opts the optional parameters
|
|
339
|
+
# @return [UnpublishPost200Response]
|
|
340
|
+
def redeliver_webhook_event(redeliver_webhook_event_request, opts = {})
|
|
341
|
+
data, _status_code, _headers = redeliver_webhook_event_with_http_info(redeliver_webhook_event_request, opts)
|
|
342
|
+
data
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Redeliver a webhook event
|
|
346
|
+
# Replay a past delivery: the original payload is re-sent, byte for byte, to the subscription's current URL. The original event ID is preserved so your endpoint can dedupe, and the replay is recorded as a fresh attempt, so it shows up in `GET /v1/webhooks/logs` next to the delivery it replays. Both `webhookId` and `eventId` come from a row of `GET /v1/webhooks/logs`. Because the stored payload is replayed as-is, a redelivery reflects the event as it was emitted, not the current state of the resource. Only deliveries inside the 30-day log retention window can be replayed; past that the payload is gone and the request fails with a 500. Replays run the same resource-group checks as live delivery, against both the key's groups and the subscription's `disabledResourceGroups`.
|
|
347
|
+
# @param redeliver_webhook_event_request [RedeliverWebhookEventRequest]
|
|
348
|
+
# @param [Hash] opts the optional parameters
|
|
349
|
+
# @return [Array<(UnpublishPost200Response, Integer, Hash)>] UnpublishPost200Response data, response status code and response headers
|
|
350
|
+
def redeliver_webhook_event_with_http_info(redeliver_webhook_event_request, opts = {})
|
|
351
|
+
if @api_client.config.debugging
|
|
352
|
+
@api_client.config.logger.debug 'Calling API: WebhooksApi.redeliver_webhook_event ...'
|
|
353
|
+
end
|
|
354
|
+
# verify the required parameter 'redeliver_webhook_event_request' is set
|
|
355
|
+
if @api_client.config.client_side_validation && redeliver_webhook_event_request.nil?
|
|
356
|
+
fail ArgumentError, "Missing the required parameter 'redeliver_webhook_event_request' when calling WebhooksApi.redeliver_webhook_event"
|
|
357
|
+
end
|
|
358
|
+
# resource path
|
|
359
|
+
local_var_path = '/v1/webhooks/logs/redeliver'
|
|
360
|
+
|
|
361
|
+
# query parameters
|
|
362
|
+
query_params = opts[:query_params] || {}
|
|
363
|
+
|
|
364
|
+
# header parameters
|
|
365
|
+
header_params = opts[:header_params] || {}
|
|
366
|
+
# HTTP header 'Accept' (if needed)
|
|
367
|
+
header_params['Accept'] = @api_client.select_header_accept(['application/json']) unless header_params['Accept']
|
|
368
|
+
# HTTP header 'Content-Type'
|
|
369
|
+
content_type = @api_client.select_header_content_type(['application/json'])
|
|
370
|
+
if !content_type.nil?
|
|
371
|
+
header_params['Content-Type'] = content_type
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# form parameters
|
|
375
|
+
form_params = opts[:form_params] || {}
|
|
376
|
+
|
|
377
|
+
# http body (model)
|
|
378
|
+
post_body = opts[:debug_body] || @api_client.object_to_http_body(redeliver_webhook_event_request)
|
|
379
|
+
|
|
380
|
+
# return_type
|
|
381
|
+
return_type = opts[:debug_return_type] || 'UnpublishPost200Response'
|
|
382
|
+
|
|
383
|
+
# auth_names
|
|
384
|
+
auth_names = opts[:debug_auth_names] || ['bearerAuth']
|
|
385
|
+
|
|
386
|
+
new_options = opts.merge(
|
|
387
|
+
:operation => :"WebhooksApi.redeliver_webhook_event",
|
|
388
|
+
:header_params => header_params,
|
|
389
|
+
:query_params => query_params,
|
|
390
|
+
:form_params => form_params,
|
|
391
|
+
:body => post_body,
|
|
392
|
+
:auth_names => auth_names,
|
|
393
|
+
:return_type => return_type
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
|
|
397
|
+
if @api_client.config.debugging
|
|
398
|
+
@api_client.config.logger.debug "API called: WebhooksApi#redeliver_webhook_event\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
399
|
+
end
|
|
400
|
+
return data, status_code, headers
|
|
401
|
+
end
|
|
402
|
+
|
|
335
403
|
# Send test webhook
|
|
336
404
|
# Send a test webhook to verify your endpoint is configured correctly. The test payload includes event: \"webhook.test\" to distinguish it from real events. `webhook.test` belongs to the `webhooks` resource group, so a key with that group disabled is rejected with 403, as is a test fire on a subscription that lists `webhooks` in its own `disabledResourceGroups` (a 403, not a reported delivery failure). Replays of real events (redelivery, dead-letter requeue) run the same checks as live delivery, against both the key's groups and the subscription's.
|
|
337
405
|
# @param test_webhook_request [TestWebhookRequest]
|
|
@@ -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).
|
|
@@ -0,0 +1,210 @@
|
|
|
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
|
+
class RedeliverWebhookEventRequest < ApiModelBase
|
|
18
|
+
# ID of the webhook subscription that delivered the event
|
|
19
|
+
attr_accessor :webhook_id
|
|
20
|
+
|
|
21
|
+
# Stable event ID of the delivery to replay
|
|
22
|
+
attr_accessor :event_id
|
|
23
|
+
|
|
24
|
+
# Attribute mapping from ruby-style variable name to JSON key.
|
|
25
|
+
def self.attribute_map
|
|
26
|
+
{
|
|
27
|
+
:'webhook_id' => :'webhookId',
|
|
28
|
+
:'event_id' => :'eventId'
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Returns attribute mapping this model knows about
|
|
33
|
+
def self.acceptable_attribute_map
|
|
34
|
+
attribute_map
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns all the JSON keys this model knows about
|
|
38
|
+
def self.acceptable_attributes
|
|
39
|
+
acceptable_attribute_map.values
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Attribute type mapping.
|
|
43
|
+
def self.openapi_types
|
|
44
|
+
{
|
|
45
|
+
:'webhook_id' => :'String',
|
|
46
|
+
:'event_id' => :'String'
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# List of attributes with nullable: true
|
|
51
|
+
def self.openapi_nullable
|
|
52
|
+
Set.new([
|
|
53
|
+
])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Initializes the object
|
|
57
|
+
# @param [Hash] attributes Model attributes in the form of hash
|
|
58
|
+
def initialize(attributes = {})
|
|
59
|
+
if (!attributes.is_a?(Hash))
|
|
60
|
+
fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::RedeliverWebhookEventRequest` initialize method"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# check to see if the attribute exists and convert string to symbol for hash key
|
|
64
|
+
acceptable_attribute_map = self.class.acceptable_attribute_map
|
|
65
|
+
attributes = attributes.each_with_object({}) { |(k, v), h|
|
|
66
|
+
if (!acceptable_attribute_map.key?(k.to_sym))
|
|
67
|
+
fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::RedeliverWebhookEventRequest`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
|
|
68
|
+
end
|
|
69
|
+
h[k.to_sym] = v
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if attributes.key?(:'webhook_id')
|
|
73
|
+
self.webhook_id = attributes[:'webhook_id']
|
|
74
|
+
else
|
|
75
|
+
self.webhook_id = nil
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if attributes.key?(:'event_id')
|
|
79
|
+
self.event_id = attributes[:'event_id']
|
|
80
|
+
else
|
|
81
|
+
self.event_id = nil
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Show invalid properties with the reasons. Usually used together with valid?
|
|
86
|
+
# @return Array for valid properties with the reasons
|
|
87
|
+
def list_invalid_properties
|
|
88
|
+
warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
|
|
89
|
+
invalid_properties = Array.new
|
|
90
|
+
if @webhook_id.nil?
|
|
91
|
+
invalid_properties.push('invalid value for "webhook_id", webhook_id cannot be nil.')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if @webhook_id.to_s.length < 1
|
|
95
|
+
invalid_properties.push('invalid value for "webhook_id", the character length must be greater than or equal to 1.')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if @event_id.nil?
|
|
99
|
+
invalid_properties.push('invalid value for "event_id", event_id cannot be nil.')
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
if @event_id.to_s.length < 1
|
|
103
|
+
invalid_properties.push('invalid value for "event_id", the character length must be greater than or equal to 1.')
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
invalid_properties
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Check to see if the all the properties in the model are valid
|
|
110
|
+
# @return true if the model is valid
|
|
111
|
+
def valid?
|
|
112
|
+
warn '[DEPRECATED] the `valid?` method is obsolete'
|
|
113
|
+
return false if @webhook_id.nil?
|
|
114
|
+
return false if @webhook_id.to_s.length < 1
|
|
115
|
+
return false if @event_id.nil?
|
|
116
|
+
return false if @event_id.to_s.length < 1
|
|
117
|
+
true
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Custom attribute writer method with validation
|
|
121
|
+
# @param [Object] webhook_id Value to be assigned
|
|
122
|
+
def webhook_id=(webhook_id)
|
|
123
|
+
if webhook_id.nil?
|
|
124
|
+
fail ArgumentError, 'webhook_id cannot be nil'
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
if webhook_id.to_s.length < 1
|
|
128
|
+
fail ArgumentError, 'invalid value for "webhook_id", the character length must be greater than or equal to 1.'
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
@webhook_id = webhook_id
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Custom attribute writer method with validation
|
|
135
|
+
# @param [Object] event_id Value to be assigned
|
|
136
|
+
def event_id=(event_id)
|
|
137
|
+
if event_id.nil?
|
|
138
|
+
fail ArgumentError, 'event_id cannot be nil'
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
if event_id.to_s.length < 1
|
|
142
|
+
fail ArgumentError, 'invalid value for "event_id", the character length must be greater than or equal to 1.'
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
@event_id = event_id
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Checks equality by comparing each attribute.
|
|
149
|
+
# @param [Object] Object to be compared
|
|
150
|
+
def ==(o)
|
|
151
|
+
return true if self.equal?(o)
|
|
152
|
+
self.class == o.class &&
|
|
153
|
+
webhook_id == o.webhook_id &&
|
|
154
|
+
event_id == o.event_id
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# @see the `==` method
|
|
158
|
+
# @param [Object] Object to be compared
|
|
159
|
+
def eql?(o)
|
|
160
|
+
self == o
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Calculates hash code according to all attributes.
|
|
164
|
+
# @return [Integer] Hash code
|
|
165
|
+
def hash
|
|
166
|
+
[webhook_id, event_id].hash
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Builds the object from hash
|
|
170
|
+
# @param [Hash] attributes Model attributes in the form of hash
|
|
171
|
+
# @return [Object] Returns the model itself
|
|
172
|
+
def self.build_from_hash(attributes)
|
|
173
|
+
return nil unless attributes.is_a?(Hash)
|
|
174
|
+
attributes = attributes.transform_keys(&:to_sym)
|
|
175
|
+
transformed_hash = {}
|
|
176
|
+
openapi_types.each_pair do |key, type|
|
|
177
|
+
if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
|
|
178
|
+
transformed_hash["#{key}"] = nil
|
|
179
|
+
elsif type =~ /\AArray<(.*)>/i
|
|
180
|
+
# check to ensure the input is an array given that the attribute
|
|
181
|
+
# is documented as an array but the input is not
|
|
182
|
+
if attributes[attribute_map[key]].is_a?(Array)
|
|
183
|
+
transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
|
|
184
|
+
end
|
|
185
|
+
elsif !attributes[attribute_map[key]].nil?
|
|
186
|
+
transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
new(transformed_hash)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Returns the object in the form of hash
|
|
193
|
+
# @return [Hash] Returns the object in the form of hash
|
|
194
|
+
def to_hash
|
|
195
|
+
hash = {}
|
|
196
|
+
self.class.attribute_map.each_pair do |attr, param|
|
|
197
|
+
value = self.send(attr)
|
|
198
|
+
if value.nil?
|
|
199
|
+
is_nullable = self.class.openapi_nullable.include?(attr)
|
|
200
|
+
next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
hash[param] = _to_hash(value)
|
|
204
|
+
end
|
|
205
|
+
hash
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
end
|
|
@@ -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/lib/zernio-sdk.rb
CHANGED
|
@@ -1169,6 +1169,7 @@ require 'zernio-sdk/models/recycling_config'
|
|
|
1169
1169
|
require 'zernio-sdk/models/recycling_state'
|
|
1170
1170
|
require 'zernio-sdk/models/reddit_platform_data'
|
|
1171
1171
|
require 'zernio-sdk/models/reddit_post'
|
|
1172
|
+
require 'zernio-sdk/models/redeliver_webhook_event_request'
|
|
1172
1173
|
require 'zernio-sdk/models/register_whats_app_number200_response'
|
|
1173
1174
|
require 'zernio-sdk/models/register_whats_app_number_request'
|
|
1174
1175
|
require 'zernio-sdk/models/reject_whats_app_group_join_requests_request'
|
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
|
|
@@ -15304,7 +15304,26 @@ paths:
|
|
|
15304
15304
|
operationId: bulkUploadPosts
|
|
15305
15305
|
tags: [Posts]
|
|
15306
15306
|
summary: Bulk upload from CSV
|
|
15307
|
-
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
|
+
```
|
|
15308
15327
|
parameters:
|
|
15309
15328
|
- name: dryRun
|
|
15310
15329
|
in: query
|
|
@@ -25490,6 +25509,78 @@ paths:
|
|
|
25490
25509
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
25491
25510
|
'403': { $ref: '#/components/responses/ResourceGroupForbidden' }
|
|
25492
25511
|
|
|
25512
|
+
/v1/webhooks/logs/redeliver:
|
|
25513
|
+
post:
|
|
25514
|
+
x-resource-group: "webhooks"
|
|
25515
|
+
operationId: redeliverWebhookEvent
|
|
25516
|
+
tags: [Webhooks]
|
|
25517
|
+
summary: Redeliver a webhook event
|
|
25518
|
+
description: |
|
|
25519
|
+
Replay a past delivery: the original payload is re-sent, byte for byte, to the
|
|
25520
|
+
subscription's current URL. The original event ID is preserved so your endpoint can
|
|
25521
|
+
dedupe, and the replay is recorded as a fresh attempt, so it shows up in
|
|
25522
|
+
`GET /v1/webhooks/logs` next to the delivery it replays.
|
|
25523
|
+
|
|
25524
|
+
Both `webhookId` and `eventId` come from a row of `GET /v1/webhooks/logs`. Because
|
|
25525
|
+
the stored payload is replayed as-is, a redelivery reflects the event as it was
|
|
25526
|
+
emitted, not the current state of the resource.
|
|
25527
|
+
|
|
25528
|
+
Only deliveries inside the 30-day log retention window can be replayed; past that
|
|
25529
|
+
the payload is gone and the request fails with a 500. Replays run the same
|
|
25530
|
+
resource-group checks as live delivery, against both the key's groups and the
|
|
25531
|
+
subscription's `disabledResourceGroups`.
|
|
25532
|
+
security:
|
|
25533
|
+
- bearerAuth: []
|
|
25534
|
+
requestBody:
|
|
25535
|
+
required: true
|
|
25536
|
+
content:
|
|
25537
|
+
application/json:
|
|
25538
|
+
schema:
|
|
25539
|
+
type: object
|
|
25540
|
+
required:
|
|
25541
|
+
- webhookId
|
|
25542
|
+
- eventId
|
|
25543
|
+
properties:
|
|
25544
|
+
webhookId:
|
|
25545
|
+
type: string
|
|
25546
|
+
minLength: 1
|
|
25547
|
+
description: ID of the webhook subscription that delivered the event
|
|
25548
|
+
eventId:
|
|
25549
|
+
type: string
|
|
25550
|
+
minLength: 1
|
|
25551
|
+
description: Stable event ID of the delivery to replay
|
|
25552
|
+
example:
|
|
25553
|
+
webhookId: "507f1f77bcf86cd799439011"
|
|
25554
|
+
eventId: "evt_9f2c1b7a4d8e"
|
|
25555
|
+
responses:
|
|
25556
|
+
'200':
|
|
25557
|
+
description: Event re-delivered successfully
|
|
25558
|
+
content:
|
|
25559
|
+
application/json:
|
|
25560
|
+
schema:
|
|
25561
|
+
type: object
|
|
25562
|
+
properties:
|
|
25563
|
+
success: { type: boolean }
|
|
25564
|
+
message: { type: string }
|
|
25565
|
+
example:
|
|
25566
|
+
success: true
|
|
25567
|
+
message: "Webhook re-delivered"
|
|
25568
|
+
'400': { description: 'webhookId or eventId missing or empty' }
|
|
25569
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
25570
|
+
'403': { $ref: '#/components/responses/ResourceGroupForbidden' }
|
|
25571
|
+
'500': { description: 'Webhook no longer exists, has no URL configured, or the original payload is outside the 30-day retention window' }
|
|
25572
|
+
'502':
|
|
25573
|
+
description: |
|
|
25574
|
+
Re-delivery was attempted but your endpoint errored again. The attempt is still
|
|
25575
|
+
logged; `message` describes the failure.
|
|
25576
|
+
content:
|
|
25577
|
+
application/json:
|
|
25578
|
+
schema:
|
|
25579
|
+
type: object
|
|
25580
|
+
properties:
|
|
25581
|
+
success: { type: boolean }
|
|
25582
|
+
message: { type: string }
|
|
25583
|
+
|
|
25493
25584
|
/v1/webhooks/test:
|
|
25494
25585
|
post:
|
|
25495
25586
|
x-resource-group: "webhooks"
|
|
@@ -41295,7 +41386,10 @@ paths:
|
|
|
41295
41386
|
kind on the ad group (criteria not in the list are removed); a kind left out is
|
|
41296
41387
|
untouched. Any other `targeting` field returns 400: Google cannot mutate broad
|
|
41297
41388
|
targeting post-create without recreating the campaign. `creative` returns 501.
|
|
41298
|
-
- **
|
|
41389
|
+
- **LinkedIn**: status, budget, targeting (geo countries only, applied to the
|
|
41390
|
+
LinkedIn Campaign via PARTIAL_UPDATE), and creative (uploads new media, creates a
|
|
41391
|
+
replacement inline creative on the same campaign, pauses the old one).
|
|
41392
|
+
- **Pinterest / X / OpenAI Ads**: status + budget only. Sending
|
|
41299
41393
|
`targeting` or `creative` returns 501 with code `unsupported_platform_operation`.
|
|
41300
41394
|
OpenAI Ads budget is lifetime-only (see `budget.type` below).
|
|
41301
41395
|
security:
|
|
@@ -41318,8 +41412,8 @@ paths:
|
|
|
41318
41412
|
targeting:
|
|
41319
41413
|
type: object
|
|
41320
41414
|
description: |
|
|
41321
|
-
Meta + TikTok (demographics/interests)
|
|
41322
|
-
Pinterest / X
|
|
41415
|
+
Meta + TikTok (demographics/interests), Google (keyword edits only),
|
|
41416
|
+
and LinkedIn (geo countries). Pinterest / X return 501.
|
|
41323
41417
|
properties:
|
|
41324
41418
|
keywords:
|
|
41325
41419
|
type: array
|
|
@@ -41351,7 +41445,7 @@ paths:
|
|
|
41351
41445
|
creative:
|
|
41352
41446
|
type: object
|
|
41353
41447
|
description: |
|
|
41354
|
-
Replace the ad's creative. Meta
|
|
41448
|
+
Replace the ad's creative. Meta, TikTok, and LinkedIn.
|
|
41355
41449
|
|
|
41356
41450
|
- **Meta**: requires `headline`, `body`, `callToAction`, `linkUrl`, `imageUrl`. The
|
|
41357
41451
|
ad's existing creative is replaced via a new `/act_X/adcreatives` upload + ad
|
|
@@ -41359,6 +41453,9 @@ paths:
|
|
|
41359
41453
|
- **TikTok**: patch-style. Pass any subset; `headline` is ignored (TikTok creatives
|
|
41360
41454
|
have no headline slot). `body` becomes the in-feed `ad_text`; `linkUrl` becomes
|
|
41361
41455
|
`landing_page_url`; `videoUrl` triggers a fresh upload.
|
|
41456
|
+
- **LinkedIn**: uploads new media (image via `imageUrl` or video via `videoUrl`),
|
|
41457
|
+
creates a new inline media creative on the same campaign, and pauses the old
|
|
41458
|
+
creative (best-effort). The old creative is retained for historical reporting.
|
|
41362
41459
|
properties:
|
|
41363
41460
|
headline: { type: string, description: "Meta only" }
|
|
41364
41461
|
body: { type: string }
|
|
@@ -41381,7 +41478,7 @@ paths:
|
|
|
41381
41478
|
description: Invalid status transition or budget below minimum
|
|
41382
41479
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41383
41480
|
'404': { $ref: '#/components/responses/NotFound' }
|
|
41384
|
-
'501': { description: "targeting or creative not supported on the platform (Meta
|
|
41481
|
+
'501': { description: "targeting or creative not supported on the platform (supported on Meta, TikTok, and LinkedIn)" }
|
|
41385
41482
|
'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`." }
|
|
41386
41483
|
delete:
|
|
41387
41484
|
x-resource-group: "ads"
|
|
@@ -43670,6 +43767,11 @@ paths:
|
|
|
43670
43767
|
(for example, an agency paying for a client's ads). Same rules as
|
|
43671
43768
|
`dsaBeneficiary`: required for EU targeting unless the ad account has
|
|
43672
43769
|
a default payor.
|
|
43770
|
+
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." }
|
|
43771
|
+
status:
|
|
43772
|
+
type: string
|
|
43773
|
+
enum: [ACTIVE, PAUSED]
|
|
43774
|
+
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).'
|
|
43673
43775
|
optimizationGoal:
|
|
43674
43776
|
type: string
|
|
43675
43777
|
description: |
|
|
@@ -43796,8 +43898,9 @@ paths:
|
|
|
43796
43898
|
|
|
43797
43899
|
**LinkedIn**
|
|
43798
43900
|
- `engagement`, `traffic`, `awareness` and `video_views` create standalone Direct Sponsored Content ads. `traffic` requires `linkUrl`; `video_views` requires `video`.
|
|
43901
|
+
- `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}`.
|
|
43799
43902
|
- `job_applicants` requires a `platformSpecificData.jobs` creative.
|
|
43800
|
-
- For `
|
|
43903
|
+
- For `conversions` on LinkedIn, or to promote an existing post, use POST /v1/ads/boost.
|
|
43801
43904
|
|
|
43802
43905
|
**OpenAI Ads**
|
|
43803
43906
|
- 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.
|
|
@@ -43821,7 +43924,7 @@ paths:
|
|
|
43821
43924
|
status:
|
|
43822
43925
|
type: string
|
|
43823
43926
|
enum: [ACTIVE, PAUSED]
|
|
43824
|
-
description: "Meta and
|
|
43927
|
+
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)."
|
|
43825
43928
|
campaignStatus:
|
|
43826
43929
|
type: string
|
|
43827
43930
|
enum: [ACTIVE, PAUSED]
|
|
@@ -43846,7 +43949,7 @@ paths:
|
|
|
43846
43949
|
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." }
|
|
43847
43950
|
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." }
|
|
43848
43951
|
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)." }
|
|
43849
|
-
leadGenFormId: { type: string, description: "
|
|
43952
|
+
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." }
|
|
43850
43953
|
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)." }
|
|
43851
43954
|
images:
|
|
43852
43955
|
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
|
|
@@ -84,6 +84,18 @@ describe 'WebhooksApi' do
|
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
# unit tests for redeliver_webhook_event
|
|
88
|
+
# Redeliver a webhook event
|
|
89
|
+
# Replay a past delivery: the original payload is re-sent, byte for byte, to the subscription's current URL. The original event ID is preserved so your endpoint can dedupe, and the replay is recorded as a fresh attempt, so it shows up in `GET /v1/webhooks/logs` next to the delivery it replays. Both `webhookId` and `eventId` come from a row of `GET /v1/webhooks/logs`. Because the stored payload is replayed as-is, a redelivery reflects the event as it was emitted, not the current state of the resource. Only deliveries inside the 30-day log retention window can be replayed; past that the payload is gone and the request fails with a 500. Replays run the same resource-group checks as live delivery, against both the key's groups and the subscription's `disabledResourceGroups`.
|
|
90
|
+
# @param redeliver_webhook_event_request
|
|
91
|
+
# @param [Hash] opts the optional parameters
|
|
92
|
+
# @return [UnpublishPost200Response]
|
|
93
|
+
describe 'redeliver_webhook_event test' do
|
|
94
|
+
it 'should work' do
|
|
95
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
87
99
|
# unit tests for test_webhook
|
|
88
100
|
# Send test webhook
|
|
89
101
|
# Send a test webhook to verify your endpoint is configured correctly. The test payload includes event: \"webhook.test\" to distinguish it from real events. `webhook.test` belongs to the `webhooks` resource group, so a key with that group disabled is rejected with 403, as is a test fire on a subscription that lists `webhooks` in its own `disabledResourceGroups` (a 403, not a reported delivery failure). Replays of real events (redelivery, dead-letter requeue) run the same checks as live delivery, against both the key's groups and the subscription's.
|
|
@@ -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/
|
|
@@ -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::RedeliverWebhookEventRequest
|
|
18
|
+
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
|
+
# Please update as you see appropriate
|
|
20
|
+
describe Zernio::RedeliverWebhookEventRequest do
|
|
21
|
+
#let(:instance) { Zernio::RedeliverWebhookEventRequest.new }
|
|
22
|
+
|
|
23
|
+
describe 'test an instance of RedeliverWebhookEventRequest' do
|
|
24
|
+
it 'should create an instance of RedeliverWebhookEventRequest' do
|
|
25
|
+
# uncomment below to test the instance creation
|
|
26
|
+
#expect(instance).to be_instance_of(Zernio::RedeliverWebhookEventRequest)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe 'test attribute "webhook_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 "event_id"' 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
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zernio-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.807
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenAPI-Generator
|
|
@@ -1265,6 +1265,7 @@ files:
|
|
|
1265
1265
|
- docs/RedditPlatformData.md
|
|
1266
1266
|
- docs/RedditPost.md
|
|
1267
1267
|
- docs/RedditSearchApi.md
|
|
1268
|
+
- docs/RedeliverWebhookEventRequest.md
|
|
1268
1269
|
- docs/RegisterWhatsAppNumber200Response.md
|
|
1269
1270
|
- docs/RegisterWhatsAppNumberRequest.md
|
|
1270
1271
|
- docs/RejectWhatsAppGroupJoinRequestsRequest.md
|
|
@@ -3117,6 +3118,7 @@ files:
|
|
|
3117
3118
|
- lib/zernio-sdk/models/recycling_state.rb
|
|
3118
3119
|
- lib/zernio-sdk/models/reddit_platform_data.rb
|
|
3119
3120
|
- lib/zernio-sdk/models/reddit_post.rb
|
|
3121
|
+
- lib/zernio-sdk/models/redeliver_webhook_event_request.rb
|
|
3120
3122
|
- lib/zernio-sdk/models/register_whats_app_number200_response.rb
|
|
3121
3123
|
- lib/zernio-sdk/models/register_whats_app_number_request.rb
|
|
3122
3124
|
- lib/zernio-sdk/models/reject_whats_app_group_join_requests_request.rb
|
|
@@ -4944,6 +4946,7 @@ files:
|
|
|
4944
4946
|
- spec/models/recycling_state_spec.rb
|
|
4945
4947
|
- spec/models/reddit_platform_data_spec.rb
|
|
4946
4948
|
- spec/models/reddit_post_spec.rb
|
|
4949
|
+
- spec/models/redeliver_webhook_event_request_spec.rb
|
|
4947
4950
|
- spec/models/register_whats_app_number200_response_spec.rb
|
|
4948
4951
|
- spec/models/register_whats_app_number_request_spec.rb
|
|
4949
4952
|
- spec/models/reject_whats_app_group_join_requests_request_spec.rb
|
|
@@ -7287,6 +7290,7 @@ test_files:
|
|
|
7287
7290
|
- spec/models/gbp_free_form_service_item_label_spec.rb
|
|
7288
7291
|
- spec/models/generate_keyword_ideas200_response_paging_spec.rb
|
|
7289
7292
|
- spec/models/create_inbox_conversation_request_spec.rb
|
|
7293
|
+
- spec/models/redeliver_webhook_event_request_spec.rb
|
|
7290
7294
|
- spec/models/ctwa_ad_request_body_welcome_message_spec.rb
|
|
7291
7295
|
- spec/models/send_inbox_message_request_interactive_action_one_of_spec.rb
|
|
7292
7296
|
- spec/models/edit_inbox_comment_request_spec.rb
|