late-sdk 0.0.890 → 0.0.892

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5276c61a7a83ea4f82d665041d6dd5e6d2bafdbadaa9db3ec83713b6bc68362
4
- data.tar.gz: 6ce9ffb1852bf974f33503512edebe0dd3ec0c1f0cb656a4f8710e584c23d560
3
+ metadata.gz: f083d160652c89b9de7a411e6bf22dcd253a488b42e7b5460d6264c1b442c2ac
4
+ data.tar.gz: 0b168b58de20cbf909677feca0f634376f41bf2b7cd2d9d82fee9d0265bd638f
5
5
  SHA512:
6
- metadata.gz: e94acf7ce1317ccc976cab938c2170a876652d47bb1af2934463d8e8a8e36efc3c080fab89c7eb4e3bee02e23ad00a2fc6dcb1dc4065c3b87049112991507c07
7
- data.tar.gz: 5c90400f53199e0d595f6dc016436524bbb98f3464d1f51f20d2b7a76bdce3699453cdf6180d76bc53a13bbb27c820da22590c95d6ed40cbb128836c7051fb3c
6
+ metadata.gz: 231c93d8824c7abfcbc832f877dffd9a7a211c692a30afcdfd7f669791d25b93c5157ba2b6e3ae33c63cac7652ce28796499eefc2d93860f4925544eaa7cb817
7
+ data.tar.gz: 2924855878176b9a501c6b441878458ac40b0026098251de2c94c492ca98a6dc08b635ff19fe14069fcc72a638c53f682ec000bd3da9cb6fcea58df30439d276
data/README.md CHANGED
@@ -979,7 +979,6 @@ Class | Method | HTTP request | Description
979
979
  - [Zernio::Connected](docs/Connected.md)
980
980
  - [Zernio::ConnectedAccount](docs/ConnectedAccount.md)
981
981
  - [Zernio::ConnectedApp](docs/ConnectedApp.md)
982
- - [Zernio::Conversation](docs/Conversation.md)
983
982
  - [Zernio::ConversionAction](docs/ConversionAction.md)
984
983
  - [Zernio::ConversionActionTagSnippetsInner](docs/ConversionActionTagSnippetsInner.md)
985
984
  - [Zernio::ConversionDestination](docs/ConversionDestination.md)
@@ -1655,6 +1654,7 @@ Class | Method | HTTP request | Description
1655
1654
  - [Zernio::InboxMessageEditHistoryEntry](docs/InboxMessageEditHistoryEntry.md)
1656
1655
  - [Zernio::InboxWebhookAccount](docs/InboxWebhookAccount.md)
1657
1656
  - [Zernio::InboxWebhookConversation](docs/InboxWebhookConversation.md)
1657
+ - [Zernio::InboxWebhookConversationDetail](docs/InboxWebhookConversationDetail.md)
1658
1658
  - [Zernio::InboxWebhookMessage](docs/InboxWebhookMessage.md)
1659
1659
  - [Zernio::InboxWebhookMessageAttachmentsInner](docs/InboxWebhookMessageAttachmentsInner.md)
1660
1660
  - [Zernio::InboxWebhookMessageSender](docs/InboxWebhookMessageSender.md)
@@ -2569,7 +2569,6 @@ Class | Method | HTTP request | Description
2569
2569
  - [Zernio::WebhookPayloadConversationControlChanged](docs/WebhookPayloadConversationControlChanged.md)
2570
2570
  - [Zernio::WebhookPayloadConversationControlChangedControl](docs/WebhookPayloadConversationControlChangedControl.md)
2571
2571
  - [Zernio::WebhookPayloadConversationStarted](docs/WebhookPayloadConversationStarted.md)
2572
- - [Zernio::WebhookPayloadConversationStartedConversation](docs/WebhookPayloadConversationStartedConversation.md)
2573
2572
  - [Zernio::WebhookPayloadExternalPost](docs/WebhookPayloadExternalPost.md)
2574
2573
  - [Zernio::WebhookPayloadLead](docs/WebhookPayloadLead.md)
2575
2574
  - [Zernio::WebhookPayloadLeadAccount](docs/WebhookPayloadLeadAccount.md)
@@ -404,7 +404,7 @@ end
404
404
 
405
405
  Create a standalone ad group
406
406
 
407
- Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via `existingAdGroupId` on POST /v1/ads/create. Google only; every other platform returns 501. Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from `ads` rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an `Idempotency-Key` header to make retries safe.
407
+ Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via `adSetId` on POST /v1/ads/create. Google only; every other platform returns 501. Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from `ads` rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an `Idempotency-Key` header to make retries safe.
408
408
 
409
409
  ### Examples
410
410
 
@@ -546,7 +546,7 @@ end
546
546
 
547
547
  Create standalone ad
548
548
 
549
- Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
549
+ Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
550
550
 
551
551
  ### Examples
552
552
 
@@ -1717,7 +1717,7 @@ end
1717
1717
 
1718
1718
  List ad sets
1719
1719
 
1720
- Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the `ad_sets` table directly, independent of the `ads` rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via `existingAdGroupId`. Returns at most 500 rows, newest first.
1720
+ Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the `ad_sets` table directly, independent of the `ads` rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via `adSetId` on POST /v1/ads/create. Returns at most 500 rows, newest first.
1721
1721
 
1722
1722
  ### Examples
1723
1723
 
@@ -34,13 +34,13 @@
34
34
  | **descriptions** | **Array<String>** | Meta only. Optional description variations for Multiple Text Options. Sent alongside `bodies` and `headlines`. | [optional] |
35
35
  | **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. | [optional] |
36
36
  | **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] |
37
- | **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] |
37
+ | **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). `placementAssets`, `dynamicCreative` and `carouselCards` (Meta multi-card Instant-Form lead ad; `linkUrl` and per-card `linkUrl` are optional and forwarded as real destinations when sent, falling back to Meta's lead-form link when omitted) ARE supported on Meta instant-form lead ads. | [optional] |
38
38
  | **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. 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] |
39
39
  | **images** | [**CreateStandaloneAdRequestImages**](CreateStandaloneAdRequestImages.md) | | [optional] |
40
40
  | **video** | [**CreateStandaloneAdRequestVideo**](CreateStandaloneAdRequestVideo.md) | | [optional] |
41
41
  | **creatives** | [**Array<CreateStandaloneAdRequestCreativesInner>**](CreateStandaloneAdRequestCreativesInner.md) | Meta-only. When present, switches to the multi-creative shape: creates 1 campaign + 1 ad set + N ads (one per entry here). Top-level `headline` / `body` / `imageUrl` / `linkUrl` / `callToAction` are ignored in this mode. Mutually exclusive with `adSetId`. | [optional] |
42
- | **ad_set_id** | **String** | When present, switches to the attach shape: adds one new ad to this existing ad set without creating a new campaign. Budget, targeting, goal, schedule, AND bid strategy are inherited from the ad set on Meta, and passing `bidStrategy` in attach mode returns 400. To change an existing ad set's bid, use `PUT /v1/ads/ad-sets/{adSetId}`. Mutually exclusive with `creatives[]`. The attached ad takes the full single-creative surface: `headline`/`body`/`description`/`callToAction` plus either `imageUrl`/`video` OR `placementAssets` (its own per-placement Feed/Story assets) OR `translations`/`defaultLocale` (its own per-locale asset feed, Meta only), and `leadGenFormId` when the target is a lead ad set (the parent must be ON_AD, true for ad sets created via goal `lead_generation`; Meta rejects a formless ad there, so pass the form on EVERY attached ad). This is the way to build N full ads sharing one ad set: create the first ad via the normal shape, then attach the rest one call each. Supported on Meta (facebook, instagram), TikTok, and LinkedIn. On TikTok the `adSetId` is the ad group ID; the new ad inherits the ad group's bid + budget + targeting. On LinkedIn the `adSetId` is the LinkedIn Campaign ID (numeric); we attach a new Creative to that Campaign, so the Campaign's `platformSpecificData` bidding, targeting, budget and schedule are inherited (passing those fields returns 400). | [optional] |
43
- | **existing_campaign_id** | **String** | Meta + LinkedIn. On Meta: add the new ad set under this EXISTING campaign instead of creating a new one (multi-ad-set audience testing). The new ad set's budget is matched to the campaign's mode automatically: for a CBO campaign (campaign-level budget) omit `budgetAmount`/`budgetType`, since the campaign owns the budget; for an ABO campaign pass them (they go on the new ad set). On LinkedIn: create a new Campaign (and its Creative) under this EXISTING CampaignGroup. On failure only the entities we authored are cleaned up; the pre-existing parent is left untouched and is never (re)activated. Mutually exclusive with `adSetId` and `creatives[]`. | [optional] |
42
+ | **ad_set_id** | **String** | When present, switches to the attach shape: adds one new ad to this existing ad set without creating a new campaign. Budget, targeting, goal, schedule, AND bid strategy are inherited from the ad set on Meta, and passing `bidStrategy` in attach mode returns 400. To change an existing ad set's bid, use `PUT /v1/ads/ad-sets/{adSetId}`. Mutually exclusive with `creatives[]`. The attached ad takes the full single-creative surface: `headline`/`body`/`description`/`callToAction` plus either `imageUrl`/`video` OR `placementAssets` (its own per-placement Feed/Story assets) OR `translations`/`defaultLocale` (its own per-locale asset feed, Meta only), and `leadGenFormId` when the target is a lead ad set (the parent must be ON_AD, true for ad sets created via goal `lead_generation`; Meta rejects a formless ad there, so pass the form on EVERY attached ad). This is the way to build N full ads sharing one ad set: create the first ad via the normal shape, then attach the rest one call each. Supported on Meta (facebook, instagram), Google Ads, TikTok, and LinkedIn. On TikTok the `adSetId` is the ad group ID; the new ad inherits the ad group's bid + budget + targeting. On LinkedIn the `adSetId` is the LinkedIn Campaign ID (numeric); we attach a new Creative to that Campaign, so the Campaign's `platformSpecificData` bidding, targeting, budget and schedule are inherited (passing those fields returns 400). On Google Ads the `adSetId` is the AD GROUP id. `goal` is still REQUIRED even though budget and targeting are inherited from the ad group. Send `campaignType: \"search\"` to attach into a Search ad group, including one created by `POST /v1/ads/ad-sets` (always SEARCH_STANDARD): without it the request is treated as Display and requires `images.landscape` + `images.square` + `businessName`, and the resulting display creative does not match a Search ad group. `budgetAmount`/`budgetType` and bidding fields (`bidStrategy`, `bidAmount`, `portfolioBidStrategyId`) return 400 on this shape; the ad group already owns them. | [optional] |
43
+ | **existing_campaign_id** | **String** | Meta, Google Ads, and LinkedIn. On Meta: add the new ad set under this EXISTING campaign instead of creating a new one (multi-ad-set audience testing). The new ad set's budget is matched to the campaign's mode automatically: for a CBO campaign (campaign-level budget) omit `budgetAmount`/`budgetType`, since the campaign owns the budget; for an ABO campaign pass them (they go on the new ad set). On LinkedIn: create a new Campaign (and its Creative) under this EXISTING CampaignGroup. On Google Ads: create a new ad group under this EXISTING campaign; the new ad group inherits the campaign's budget, so omit `budgetAmount`/`budgetType` (and any bidding field), or the request returns 400. On failure only the entities we authored are cleaned up; the pre-existing parent is left untouched and is never (re)activated. Mutually exclusive with `adSetId` and `creatives[]`. | [optional] |
44
44
  | **existing_creative_id** | **String** | Meta only. Reuse an EXISTING ad creative by id instead of building a new one from the copy/media fields (which are then ignored). Combine with `existingCampaignId` to build a multi-ad-set campaign that shares one creative. Mutually exclusive with `creatives[]`, `dynamicCreative`, and `placementAssets`. The creative id used is returned as `creativeId` on the create response. | [optional] |
45
45
  | **business_name** | **String** | Google Display only | [optional] |
46
46
  | **board_id** | **String** | Pinterest only. Board ID (auto-creates if not provided). | [optional] |
@@ -72,7 +72,7 @@
72
72
  | **start_date** | **Time** | Meta only. Ad-set start time (ISO 8601, e.g. \"2026-06-10T09:00:00Z\"), mapped to the ad set's `start_time`. When omitted the ad starts delivering immediately. For lifetime budgets Meta also requires `endDate`. (Same `schedule.startDate` semantics already available on `POST /v1/ads/boost`.) | [optional] |
73
73
  | **instagram_account_id** | **String** | Meta only. Override the Instagram account the ad is delivered as. Pass an Instagram Business Account ID (e.g. 17841...), mapped to the creative's `instagram_user_id`. When omitted we use the Instagram actor Meta already runs the Page's other ads as, falling back to the Page's page-backed Instagram account. Useful when a Page has more than one eligible IG account. | [optional] |
74
74
  | **dynamic_creative** | [**CreateStandaloneAdRequestDynamicCreative**](CreateStandaloneAdRequestDynamicCreative.md) | | [optional] |
75
- | **carousel_cards** | [**Array<CreateStandaloneAdRequestCarouselCardsInner>**](CreateStandaloneAdRequestCarouselCardsInner.md) | Meta only. Hand-built carousel: 2-10 authored cards in DETERMINISTIC order, mapped to the creative's `link_data.child_attachments`. Unlike `dynamicCreative`, you control the card order and per-card copy/link. Requires top-level `body`, `linkUrl` and `callToAction`. Those become the ad's own Destination and button (`link_data.link` / `link_data.call_to_action`), and double as the per-card fallback when a card omits its own. Mutually exclusive with `imageUrl`/`video`, `creatives[]`, `dynamicCreative`, `placementAssets`, `existingCreativeId`, `adSetId`, `leadGenFormId` and goal `catalog_sales`. | [optional] |
75
+ | **carousel_cards** | [**Array<CreateStandaloneAdRequestCarouselCardsInner>**](CreateStandaloneAdRequestCarouselCardsInner.md) | Meta only. Hand-built carousel: 2-10 authored cards in DETERMINISTIC order, mapped to the creative's `link_data.child_attachments`. Unlike `dynamicCreative`, you control the card order and per-card copy/link. Requires top-level `body` and `callToAction`; `linkUrl` is also required UNLESS `leadGenFormId` is set. Those become the ad's own Destination and button (`link_data.link` / `link_data.call_to_action`), and double as the per-card fallback when a card omits its own. Mutually exclusive with `imageUrl`/`video`, `creatives[]`, `dynamicCreative`, `placementAssets`, `existingCreativeId`, `adSetId` and goal `catalog_sales`. Combines with `leadGenFormId` to build a carousel Instant-Form lead ad: `linkUrl` and per-card `linkUrl` become OPTIONAL and, when sent, are forwarded as the real card and top-level destinations; when omitted, the destination falls back to Meta's lead-form link. | [optional] |
76
76
  | **default_locale** | **String** | Meta only. Language the top-level copy is written in (e.g. `en`, `pt_BR`), used by the `translations` default rule. Defaults to `en`. Meta rejects a language asset feed whose default rule carries no locales of its own. Must NOT also appear as an entry in `translations`. | [optional] |
77
77
  | **translations** | [**Array<CreateStandaloneAdRequestTranslationsInner>**](CreateStandaloneAdRequestTranslationsInner.md) | Meta only. Multi-language ads (Dynamic Language Optimization): ONE ad carrying per-locale copy and, optionally, per-locale media: the \"Languages\" toggle in Ads Manager. Keeps social proof (likes/comments/shares) on a SINGLE post instead of splitting it across one ad per language. The ad's top-level copy is the DEFAULT shown to every locale you do NOT list, and it counts as one of the language variants. IMPORTANT, and the opposite of what you might expect: text does NOT inherit. Every entry must carry its own `headline`, `body` AND `description`, and all of them must be DISTINCT from each other and from the ad's top-level copy. Meta deduplicates identical strings inside the asset feed, so two locales sharing a string collapse into one asset and the create fails with a misleading \"Too few ... texts provided in asset creation\" (subcode 1885817) that names a field which is actually present. We validate this before calling Meta and return a 400 naming the offending locale and field. `description` is therefore effectively required on the ad whenever `translations` is present, even though it is optional otherwise. Do NOT list `defaultLocale` inside `translations`: Meta rejects the duplicate with \"The language asset feed includes an unsupported targeting field\" (subcode 1885985). Media DOES inherit and is uploaded once when shared, and `linkUrl` inherits too: each locale may name its own landing page and unlisted locales fall back to the ad's top-level `linkUrl`. Meta enforces Dynamic Creative image dimensions on language feeds, so an `imageUrl` that works on a normal ad may be rejected with \"The following images have invalid dimensions for Dynamic Creative\" (subcode 1885558). Video is not affected. Mutually exclusive with `dynamicCreative`, `placementAssets`, `carouselCards`, `existingCreativeId` and `creatives[]`. Meta allows one `asset_feed_spec` shape per creative. | [optional] |
78
78
  | **placement_assets** | [**CreateStandaloneAdRequestPlacementAssets**](CreateStandaloneAdRequestPlacementAssets.md) | | [optional] |
@@ -5,7 +5,7 @@
5
5
  | Name | Type | Description | Notes |
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **image_url** | **String** | Card image; uploaded to the ad account and referenced by hash. | |
8
- | **link_url** | **String** | Card destination URL. Defaults to the top-level linkUrl. | [optional] |
8
+ | **link_url** | **String** | Card destination URL. Defaults to the top-level linkUrl, or Meta's lead-form link when leadGenFormId is set and neither is provided. | [optional] |
9
9
  | **headline** | **String** | Card headline, shown below the card image. | [optional] |
10
10
  | **description** | **String** | Card description, shown under the headline. | [optional] |
11
11
  | **call_to_action** | **String** | Card CTA override. Defaults to the top-level callToAction; same enum. | [optional] |
@@ -1,4 +1,4 @@
1
- # Zernio::Conversation
1
+ # Zernio::InboxWebhookConversationDetail
2
2
 
3
3
  ## Properties
4
4
 
@@ -19,7 +19,7 @@
19
19
  ```ruby
20
20
  require 'zernio-sdk'
21
21
 
22
- instance = Zernio::Conversation.new(
22
+ instance = Zernio::InboxWebhookConversationDetail.new(
23
23
  id: null,
24
24
  platform: null,
25
25
  platform_conversation_id: null,
@@ -6,7 +6,7 @@
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **id** | **String** | Stable webhook event ID | |
8
8
  | **event** | **String** | | |
9
- | **conversation** | [**WebhookPayloadConversationStartedConversation**](WebhookPayloadConversationStartedConversation.md) | | |
9
+ | **conversation** | [**InboxWebhookConversationDetail**](InboxWebhookConversationDetail.md) | | |
10
10
  | **account** | [**InboxWebhookAccount**](InboxWebhookAccount.md) | | |
11
11
  | **control** | [**WebhookPayloadConversationControlChangedControl**](WebhookPayloadConversationControlChangedControl.md) | | |
12
12
  | **changed_at** | **Time** | | |
@@ -6,7 +6,7 @@
6
6
  | ---- | ---- | ----------- | ----- |
7
7
  | **id** | **String** | Stable webhook event ID | |
8
8
  | **event** | **String** | | |
9
- | **conversation** | [**WebhookPayloadConversationStartedConversation**](WebhookPayloadConversationStartedConversation.md) | | |
9
+ | **conversation** | [**InboxWebhookConversationDetail**](InboxWebhookConversationDetail.md) | | |
10
10
  | **account** | [**InboxWebhookAccount**](InboxWebhookAccount.md) | | |
11
11
  | **started_at** | **Time** | When the conversation document was created. | |
12
12
  | **timestamp** | **Time** | UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt. | |
@@ -380,7 +380,7 @@ module Zernio
380
380
  end
381
381
 
382
382
  # Create a standalone ad group
383
- # Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via `existingAdGroupId` on POST /v1/ads/create. Google only; every other platform returns 501. Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from `ads` rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an `Idempotency-Key` header to make retries safe.
383
+ # Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via `adSetId` on POST /v1/ads/create. Google only; every other platform returns 501. Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from `ads` rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an `Idempotency-Key` header to make retries safe.
384
384
  # @param create_ad_set_request [CreateAdSetRequest]
385
385
  # @param [Hash] opts the optional parameters
386
386
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409. Only 2xx responses are stored, so a request that failed with a 4xx can be retried with a corrected body under the SAME key.
@@ -391,7 +391,7 @@ module Zernio
391
391
  end
392
392
 
393
393
  # Create a standalone ad group
394
- # Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via `existingAdGroupId` on POST /v1/ads/create. Google only; every other platform returns 501. Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from `ads` rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an `Idempotency-Key` header to make retries safe.
394
+ # Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via `adSetId` on POST /v1/ads/create. Google only; every other platform returns 501. Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from `ads` rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an `Idempotency-Key` header to make retries safe.
395
395
  # @param create_ad_set_request [CreateAdSetRequest]
396
396
  # @param [Hash] opts the optional parameters
397
397
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409. Only 2xx responses are stored, so a request that failed with a 4xx can be retried with a corrected body under the SAME key.
@@ -523,7 +523,7 @@ module Zernio
523
523
  end
524
524
 
525
525
  # Create standalone ad
526
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
526
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
527
527
  # @param create_standalone_ad_request [CreateStandaloneAdRequest]
528
528
  # @param [Hash] opts the optional parameters
529
529
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
@@ -534,7 +534,7 @@ module Zernio
534
534
  end
535
535
 
536
536
  # Create standalone ad
537
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
537
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \"dark post\" authored by a Company Page (see `organizationId`). Supported goals are engagement, traffic, awareness, and video_views (video ads use the `video` field; video_views requires a video), and traffic ads require `linkUrl`. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an `Idempotency-Key` header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with `Idempotent-Replayed: true`) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
538
538
  # @param create_standalone_ad_request [CreateStandaloneAdRequest]
539
539
  # @param [Hash] opts the optional parameters
540
540
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
@@ -1789,7 +1789,7 @@ module Zernio
1789
1789
  end
1790
1790
 
1791
1791
  # List ad sets
1792
- # Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the `ad_sets` table directly, independent of the `ads` rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via `existingAdGroupId`. Returns at most 500 rows, newest first.
1792
+ # Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the `ad_sets` table directly, independent of the `ads` rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via `adSetId` on POST /v1/ads/create. Returns at most 500 rows, newest first.
1793
1793
  # @param [Hash] opts the optional parameters
1794
1794
  # @option opts [String] :account_id Account ID
1795
1795
  # @option opts [String] :campaign_id Platform campaign ID
@@ -1801,7 +1801,7 @@ module Zernio
1801
1801
  end
1802
1802
 
1803
1803
  # List ad sets
1804
- # Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the `ad_sets` table directly, independent of the `ads` rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via `existingAdGroupId`. Returns at most 500 rows, newest first.
1804
+ # Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the `ad_sets` table directly, independent of the `ads` rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via `adSetId` on POST /v1/ads/create. Returns at most 500 rows, newest first.
1805
1805
  # @param [Hash] opts the optional parameters
1806
1806
  # @option opts [String] :account_id Account ID
1807
1807
  # @option opts [String] :campaign_id Platform campaign ID
@@ -101,7 +101,7 @@ module Zernio
101
101
  # 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).
102
102
  attr_accessor :link_url
103
103
 
104
- # 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.
104
+ # 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). `placementAssets`, `dynamicCreative` and `carouselCards` (Meta multi-card Instant-Form lead ad; `linkUrl` and per-card `linkUrl` are optional and forwarded as real destinations when sent, falling back to Meta's lead-form link when omitted) ARE supported on Meta instant-form lead ads.
105
105
  attr_accessor :lead_gen_form_id
106
106
 
107
107
  # 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. 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).
@@ -114,10 +114,10 @@ module Zernio
114
114
  # Meta-only. When present, switches to the multi-creative shape: creates 1 campaign + 1 ad set + N ads (one per entry here). Top-level `headline` / `body` / `imageUrl` / `linkUrl` / `callToAction` are ignored in this mode. Mutually exclusive with `adSetId`.
115
115
  attr_accessor :creatives
116
116
 
117
- # When present, switches to the attach shape: adds one new ad to this existing ad set without creating a new campaign. Budget, targeting, goal, schedule, AND bid strategy are inherited from the ad set on Meta, and passing `bidStrategy` in attach mode returns 400. To change an existing ad set's bid, use `PUT /v1/ads/ad-sets/{adSetId}`. Mutually exclusive with `creatives[]`. The attached ad takes the full single-creative surface: `headline`/`body`/`description`/`callToAction` plus either `imageUrl`/`video` OR `placementAssets` (its own per-placement Feed/Story assets) OR `translations`/`defaultLocale` (its own per-locale asset feed, Meta only), and `leadGenFormId` when the target is a lead ad set (the parent must be ON_AD, true for ad sets created via goal `lead_generation`; Meta rejects a formless ad there, so pass the form on EVERY attached ad). This is the way to build N full ads sharing one ad set: create the first ad via the normal shape, then attach the rest one call each. Supported on Meta (facebook, instagram), TikTok, and LinkedIn. On TikTok the `adSetId` is the ad group ID; the new ad inherits the ad group's bid + budget + targeting. On LinkedIn the `adSetId` is the LinkedIn Campaign ID (numeric); we attach a new Creative to that Campaign, so the Campaign's `platformSpecificData` bidding, targeting, budget and schedule are inherited (passing those fields returns 400).
117
+ # When present, switches to the attach shape: adds one new ad to this existing ad set without creating a new campaign. Budget, targeting, goal, schedule, AND bid strategy are inherited from the ad set on Meta, and passing `bidStrategy` in attach mode returns 400. To change an existing ad set's bid, use `PUT /v1/ads/ad-sets/{adSetId}`. Mutually exclusive with `creatives[]`. The attached ad takes the full single-creative surface: `headline`/`body`/`description`/`callToAction` plus either `imageUrl`/`video` OR `placementAssets` (its own per-placement Feed/Story assets) OR `translations`/`defaultLocale` (its own per-locale asset feed, Meta only), and `leadGenFormId` when the target is a lead ad set (the parent must be ON_AD, true for ad sets created via goal `lead_generation`; Meta rejects a formless ad there, so pass the form on EVERY attached ad). This is the way to build N full ads sharing one ad set: create the first ad via the normal shape, then attach the rest one call each. Supported on Meta (facebook, instagram), Google Ads, TikTok, and LinkedIn. On TikTok the `adSetId` is the ad group ID; the new ad inherits the ad group's bid + budget + targeting. On LinkedIn the `adSetId` is the LinkedIn Campaign ID (numeric); we attach a new Creative to that Campaign, so the Campaign's `platformSpecificData` bidding, targeting, budget and schedule are inherited (passing those fields returns 400). On Google Ads the `adSetId` is the AD GROUP id. `goal` is still REQUIRED even though budget and targeting are inherited from the ad group. Send `campaignType: \"search\"` to attach into a Search ad group, including one created by `POST /v1/ads/ad-sets` (always SEARCH_STANDARD): without it the request is treated as Display and requires `images.landscape` + `images.square` + `businessName`, and the resulting display creative does not match a Search ad group. `budgetAmount`/`budgetType` and bidding fields (`bidStrategy`, `bidAmount`, `portfolioBidStrategyId`) return 400 on this shape; the ad group already owns them.
118
118
  attr_accessor :ad_set_id
119
119
 
120
- # Meta + LinkedIn. On Meta: add the new ad set under this EXISTING campaign instead of creating a new one (multi-ad-set audience testing). The new ad set's budget is matched to the campaign's mode automatically: for a CBO campaign (campaign-level budget) omit `budgetAmount`/`budgetType`, since the campaign owns the budget; for an ABO campaign pass them (they go on the new ad set). On LinkedIn: create a new Campaign (and its Creative) under this EXISTING CampaignGroup. On failure only the entities we authored are cleaned up; the pre-existing parent is left untouched and is never (re)activated. Mutually exclusive with `adSetId` and `creatives[]`.
120
+ # Meta, Google Ads, and LinkedIn. On Meta: add the new ad set under this EXISTING campaign instead of creating a new one (multi-ad-set audience testing). The new ad set's budget is matched to the campaign's mode automatically: for a CBO campaign (campaign-level budget) omit `budgetAmount`/`budgetType`, since the campaign owns the budget; for an ABO campaign pass them (they go on the new ad set). On LinkedIn: create a new Campaign (and its Creative) under this EXISTING CampaignGroup. On Google Ads: create a new ad group under this EXISTING campaign; the new ad group inherits the campaign's budget, so omit `budgetAmount`/`budgetType` (and any bidding field), or the request returns 400. On failure only the entities we authored are cleaned up; the pre-existing parent is left untouched and is never (re)activated. Mutually exclusive with `adSetId` and `creatives[]`.
121
121
  attr_accessor :existing_campaign_id
122
122
 
123
123
  # Meta only. Reuse an EXISTING ad creative by id instead of building a new one from the copy/media fields (which are then ignored). Combine with `existingCampaignId` to build a multi-ad-set campaign that shares one creative. Mutually exclusive with `creatives[]`, `dynamicCreative`, and `placementAssets`. The creative id used is returned as `creativeId` on the create response.
@@ -209,7 +209,7 @@ module Zernio
209
209
 
210
210
  attr_accessor :dynamic_creative
211
211
 
212
- # Meta only. Hand-built carousel: 2-10 authored cards in DETERMINISTIC order, mapped to the creative's `link_data.child_attachments`. Unlike `dynamicCreative`, you control the card order and per-card copy/link. Requires top-level `body`, `linkUrl` and `callToAction`. Those become the ad's own Destination and button (`link_data.link` / `link_data.call_to_action`), and double as the per-card fallback when a card omits its own. Mutually exclusive with `imageUrl`/`video`, `creatives[]`, `dynamicCreative`, `placementAssets`, `existingCreativeId`, `adSetId`, `leadGenFormId` and goal `catalog_sales`.
212
+ # Meta only. Hand-built carousel: 2-10 authored cards in DETERMINISTIC order, mapped to the creative's `link_data.child_attachments`. Unlike `dynamicCreative`, you control the card order and per-card copy/link. Requires top-level `body` and `callToAction`; `linkUrl` is also required UNLESS `leadGenFormId` is set. Those become the ad's own Destination and button (`link_data.link` / `link_data.call_to_action`), and double as the per-card fallback when a card omits its own. Mutually exclusive with `imageUrl`/`video`, `creatives[]`, `dynamicCreative`, `placementAssets`, `existingCreativeId`, `adSetId` and goal `catalog_sales`. Combines with `leadGenFormId` to build a carousel Instant-Form lead ad: `linkUrl` and per-card `linkUrl` become OPTIONAL and, when sent, are forwarded as the real card and top-level destinations; when omitted, the destination falls back to Meta's lead-form link.
213
213
  attr_accessor :carousel_cards
214
214
 
215
215
  # Meta only. Language the top-level copy is written in (e.g. `en`, `pt_BR`), used by the `translations` default rule. Defaults to `en`. Meta rejects a language asset feed whose default rule carries no locales of its own. Must NOT also appear as an entry in `translations`.
@@ -18,7 +18,7 @@ module Zernio
18
18
  # Card image; uploaded to the ad account and referenced by hash.
19
19
  attr_accessor :image_url
20
20
 
21
- # Card destination URL. Defaults to the top-level linkUrl.
21
+ # Card destination URL. Defaults to the top-level linkUrl, or Meta's lead-form link when leadGenFormId is set and neither is provided.
22
22
  attr_accessor :link_url
23
23
 
24
24
  # Card headline, shown below the card image.
@@ -14,7 +14,8 @@ require 'date'
14
14
  require 'time'
15
15
 
16
16
  module Zernio
17
- class Conversation < ApiModelBase
17
+ # The conversation object included in conversation lifecycle webhook payloads (conversation.started, conversation.control_changed).
18
+ class InboxWebhookConversationDetail < ApiModelBase
18
19
  # Internal conversation ID
19
20
  attr_accessor :id
20
21
 
@@ -109,14 +110,14 @@ module Zernio
109
110
  # @param [Hash] attributes Model attributes in the form of hash
110
111
  def initialize(attributes = {})
111
112
  if (!attributes.is_a?(Hash))
112
- fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::Conversation` initialize method"
113
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::InboxWebhookConversationDetail` initialize method"
113
114
  end
114
115
 
115
116
  # check to see if the attribute exists and convert string to symbol for hash key
116
117
  acceptable_attribute_map = self.class.acceptable_attribute_map
117
118
  attributes = attributes.each_with_object({}) { |(k, v), h|
118
119
  if (!acceptable_attribute_map.key?(k.to_sym))
119
- fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::Conversation`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
120
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::InboxWebhookConversationDetail`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
120
121
  end
121
122
  h[k.to_sym] = v
122
123
  }
@@ -82,7 +82,7 @@ module Zernio
82
82
  {
83
83
  :'id' => :'String',
84
84
  :'event' => :'String',
85
- :'conversation' => :'WebhookPayloadConversationStartedConversation',
85
+ :'conversation' => :'InboxWebhookConversationDetail',
86
86
  :'account' => :'InboxWebhookAccount',
87
87
  :'control' => :'WebhookPayloadConversationControlChangedControl',
88
88
  :'changed_at' => :'Time',
@@ -80,7 +80,7 @@ module Zernio
80
80
  {
81
81
  :'id' => :'String',
82
82
  :'event' => :'String',
83
- :'conversation' => :'WebhookPayloadConversationStartedConversation',
83
+ :'conversation' => :'InboxWebhookConversationDetail',
84
84
  :'account' => :'InboxWebhookAccount',
85
85
  :'started_at' => :'Time',
86
86
  :'timestamp' => :'Time'
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.890'
14
+ VERSION = '0.0.892'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -238,7 +238,6 @@ require 'zernio-sdk/models/connect_whats_app_embedded_signup_request'
238
238
  require 'zernio-sdk/models/connected'
239
239
  require 'zernio-sdk/models/connected_account'
240
240
  require 'zernio-sdk/models/connected_app'
241
- require 'zernio-sdk/models/conversation'
242
241
  require 'zernio-sdk/models/conversion_action'
243
242
  require 'zernio-sdk/models/conversion_action_tag_snippets_inner'
244
243
  require 'zernio-sdk/models/conversion_destination'
@@ -914,6 +913,7 @@ require 'zernio-sdk/models/inbox_message_edit_attachment'
914
913
  require 'zernio-sdk/models/inbox_message_edit_history_entry'
915
914
  require 'zernio-sdk/models/inbox_webhook_account'
916
915
  require 'zernio-sdk/models/inbox_webhook_conversation'
916
+ require 'zernio-sdk/models/inbox_webhook_conversation_detail'
917
917
  require 'zernio-sdk/models/inbox_webhook_message'
918
918
  require 'zernio-sdk/models/inbox_webhook_message_attachments_inner'
919
919
  require 'zernio-sdk/models/inbox_webhook_message_sender'
@@ -1828,7 +1828,6 @@ require 'zernio-sdk/models/webhook_payload_comment_post'
1828
1828
  require 'zernio-sdk/models/webhook_payload_conversation_control_changed'
1829
1829
  require 'zernio-sdk/models/webhook_payload_conversation_control_changed_control'
1830
1830
  require 'zernio-sdk/models/webhook_payload_conversation_started'
1831
- require 'zernio-sdk/models/webhook_payload_conversation_started_conversation'
1832
1831
  require 'zernio-sdk/models/webhook_payload_external_post'
1833
1832
  require 'zernio-sdk/models/webhook_payload_lead'
1834
1833
  require 'zernio-sdk/models/webhook_payload_lead_account'
data/openapi.yaml CHANGED
@@ -3599,6 +3599,32 @@ components:
3599
3599
  integrators join any inbox webhook back to the CRM Contact without
3600
3600
  needing to look at the sender, which matters for outgoing and
3601
3601
  delivery-status events whose sender is the business.
3602
+ InboxWebhookConversationDetail:
3603
+ type: object
3604
+ description: The conversation object included in conversation lifecycle webhook payloads (conversation.started, conversation.control_changed).
3605
+ required: [id, platform, platformConversationId, participantName, status]
3606
+ properties:
3607
+ id: { type: string, description: Internal conversation ID }
3608
+ platform:
3609
+ type: string
3610
+ enum: [instagram, facebook, telegram, whatsapp, twitter, reddit, bluesky, sms, slack]
3611
+ platformConversationId: { type: string }
3612
+ participantId: { type: string, description: "Contact's platform identifier (IGSID, PSID, wa_id, etc.)" }
3613
+ participantName: { type: string }
3614
+ participantUsername: { type: string, description: Contact's handle when the platform exposes one }
3615
+ participantPicture: { type: string }
3616
+ status:
3617
+ type: string
3618
+ enum: [active, archived]
3619
+ contactId:
3620
+ type: string
3621
+ description: |
3622
+ Zernio CRM Contact ID for the participant, when one exists. Resolved by
3623
+ joining `participantId` to the ContactChannel collection (same join
3624
+ used by message.*, reaction.received, and call.* webhooks). Best-effort:
3625
+ omitted when no channel matches or `participantId` is absent. Lets
3626
+ integrators seed the CRM straight from `conversation.started` without
3627
+ waiting for the first `message.*` event.
3602
3628
  InboxWebhookAccount:
3603
3629
  type: object
3604
3630
  description: The account context included in inbox webhook payloads.
@@ -4518,30 +4544,7 @@ components:
4518
4544
  type: string
4519
4545
  enum: [conversation.started]
4520
4546
  conversation:
4521
- type: object
4522
- required: [id, platform, platformConversationId, participantName, status]
4523
- properties:
4524
- id: { type: string, description: Internal conversation ID }
4525
- platform:
4526
- type: string
4527
- enum: [instagram, facebook, telegram, whatsapp, twitter, reddit, bluesky, sms, slack]
4528
- platformConversationId: { type: string }
4529
- participantId: { type: string, description: "Contact's platform identifier (IGSID, PSID, wa_id, etc.)" }
4530
- participantName: { type: string }
4531
- participantUsername: { type: string, description: Contact's handle when the platform exposes one }
4532
- participantPicture: { type: string }
4533
- status:
4534
- type: string
4535
- enum: [active, archived]
4536
- contactId:
4537
- type: string
4538
- description: |
4539
- Zernio CRM Contact ID for the participant, when one exists. Resolved by
4540
- joining `participantId` to the ContactChannel collection (same join
4541
- used by message.*, reaction.received, and call.* webhooks). Best-effort:
4542
- omitted when no channel matches or `participantId` is absent. Lets
4543
- integrators seed the CRM straight from `conversation.started` without
4544
- waiting for the first `message.*` event.
4547
+ $ref: '#/components/schemas/InboxWebhookConversationDetail'
4545
4548
  account:
4546
4549
  $ref: '#/components/schemas/InboxWebhookAccount'
4547
4550
  startedAt:
@@ -4564,7 +4567,7 @@ components:
4564
4567
  type: string
4565
4568
  enum: [conversation.control_changed]
4566
4569
  conversation:
4567
- $ref: '#/components/schemas/WebhookPayloadConversationStarted/properties/conversation'
4570
+ $ref: '#/components/schemas/InboxWebhookConversationDetail'
4568
4571
  account:
4569
4572
  $ref: '#/components/schemas/InboxWebhookAccount'
4570
4573
  control:
@@ -43499,7 +43502,7 @@ paths:
43499
43502
  directly, independent of the `ads` rollup GET /v1/ads/tree uses, so a
43500
43503
  newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets,
43501
43504
  Google only) is visible here even though it is invisible in the tree
43502
- until an ad joins it via `existingAdGroupId`. Returns at most 500
43505
+ until an ad joins it via `adSetId` on POST /v1/ads/create. Returns at most 500
43503
43506
  rows, newest first.
43504
43507
  security:
43505
43508
  - bearerAuth: []
@@ -43546,7 +43549,7 @@ paths:
43546
43549
  summary: Create a standalone ad group
43547
43550
  description: |-
43548
43551
  Google Ads compliance row C.190: creates an ad group WITHOUT an ad,
43549
- under an existing campaign. Ads join it later via `existingAdGroupId`
43552
+ under an existing campaign. Ads join it later via `adSetId`
43550
43553
  on POST /v1/ads/create. Google only; every other platform returns 501.
43551
43554
 
43552
43555
  Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad
@@ -46881,7 +46884,7 @@ paths:
46881
46884
 
46882
46885
  - Legacy single-creative shape (all platforms, the default).
46883
46886
  - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting.
46884
- - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted.
46887
+ - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted.
46885
46888
 
46886
46889
  Per-platform required fields, budget minimums, and video-ad rules are documented on each property below.
46887
46890
 
@@ -47020,7 +47023,7 @@ paths:
47020
47023
  description: 'Meta only. Optional description variations for Multiple Text Options. Sent alongside `bodies` and `headlines`.'
47021
47024
  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." }
47022
47025
  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)." }
47023
- 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." }
47026
+ 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). `placementAssets`, `dynamicCreative` and `carouselCards` (Meta multi-card Instant-Form lead ad; `linkUrl` and per-card `linkUrl` are optional and forwarded as real destinations when sent, falling back to Meta's lead-form link when omitted) ARE supported on Meta instant-form lead ads." }
47024
47027
  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. 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)." }
47025
47028
  images:
47026
47029
  type: object
@@ -47084,30 +47087,46 @@ paths:
47084
47087
  to build N full ads sharing one ad set: create the first ad
47085
47088
  via the normal shape, then attach the rest one call each.
47086
47089
 
47087
- Supported on Meta (facebook, instagram), TikTok, and
47088
- LinkedIn. On TikTok the `adSetId` is the ad group ID; the
47090
+ Supported on Meta (facebook, instagram), Google Ads, TikTok,
47091
+ and LinkedIn. On TikTok the `adSetId` is the ad group ID; the
47089
47092
  new ad inherits the ad group's bid + budget + targeting.
47090
47093
  On LinkedIn the `adSetId` is the LinkedIn Campaign ID
47091
47094
  (numeric); we attach a new Creative to that Campaign, so
47092
47095
  the Campaign's `platformSpecificData` bidding, targeting,
47093
47096
  budget and schedule are inherited (passing those fields
47094
47097
  returns 400).
47098
+
47099
+ On Google Ads the `adSetId` is the AD GROUP id. `goal` is
47100
+ still REQUIRED even though budget and targeting are
47101
+ inherited from the ad group. Send `campaignType: "search"`
47102
+ to attach into a Search ad group, including one created by
47103
+ `POST /v1/ads/ad-sets` (always SEARCH_STANDARD): without it
47104
+ the request is treated as Display and requires
47105
+ `images.landscape` + `images.square` + `businessName`, and
47106
+ the resulting display creative does not match a Search ad
47107
+ group.
47108
+ `budgetAmount`/`budgetType` and bidding fields
47109
+ (`bidStrategy`, `bidAmount`, `portfolioBidStrategyId`)
47110
+ return 400 on this shape; the ad group already owns them.
47095
47111
  existingCampaignId:
47096
47112
  type: string
47097
47113
  description: |
47098
- Meta + LinkedIn. On Meta: add the new ad set under this
47099
- EXISTING campaign instead of creating a new one
47100
- (multi-ad-set audience testing). The new ad set's budget
47101
- is matched to the campaign's mode automatically: for a
47102
- CBO campaign (campaign-level budget) omit
47114
+ Meta, Google Ads, and LinkedIn. On Meta: add the new ad
47115
+ set under this EXISTING campaign instead of creating a new
47116
+ one (multi-ad-set audience testing). The new ad set's
47117
+ budget is matched to the campaign's mode automatically:
47118
+ for a CBO campaign (campaign-level budget) omit
47103
47119
  `budgetAmount`/`budgetType`, since the campaign owns the
47104
47120
  budget; for an ABO campaign pass them (they go on the new
47105
47121
  ad set). On LinkedIn: create a new Campaign (and its
47106
- Creative) under this EXISTING CampaignGroup. On failure
47107
- only the entities we authored are cleaned up; the
47108
- pre-existing parent is left untouched and is never
47109
- (re)activated. Mutually exclusive with `adSetId` and
47110
- `creatives[]`.
47122
+ Creative) under this EXISTING CampaignGroup. On Google
47123
+ Ads: create a new ad group under this EXISTING campaign;
47124
+ the new ad group inherits the campaign's budget, so omit
47125
+ `budgetAmount`/`budgetType` (and any bidding field), or
47126
+ the request returns 400. On failure only the entities we
47127
+ authored are cleaned up; the pre-existing parent is left
47128
+ untouched and is never (re)activated. Mutually exclusive
47129
+ with `adSetId` and `creatives[]`.
47111
47130
  existingCreativeId:
47112
47131
  type: string
47113
47132
  description: |
@@ -47410,18 +47429,22 @@ paths:
47410
47429
  description: |
47411
47430
  Meta only. Hand-built carousel: 2-10 authored cards in DETERMINISTIC order, mapped to
47412
47431
  the creative's `link_data.child_attachments`. Unlike `dynamicCreative`,
47413
- you control the card order and per-card copy/link. Requires top-level `body`,
47414
- `linkUrl` and `callToAction`. Those become the ad's own Destination and
47415
- button (`link_data.link` / `link_data.call_to_action`), and double as the per-card fallback when a card omits its own.
47432
+ you control the card order and per-card copy/link. Requires top-level `body`
47433
+ and `callToAction`; `linkUrl` is also required UNLESS `leadGenFormId` is set. Those
47434
+ become the ad's own Destination and button (`link_data.link` / `link_data.call_to_action`),
47435
+ and double as the per-card fallback when a card omits its own.
47416
47436
  Mutually exclusive with `imageUrl`/`video`, `creatives[]`, `dynamicCreative`,
47417
- `placementAssets`, `existingCreativeId`, `adSetId`, `leadGenFormId` and goal
47418
- `catalog_sales`.
47437
+ `placementAssets`, `existingCreativeId`, `adSetId` and goal
47438
+ `catalog_sales`. Combines with `leadGenFormId` to build a carousel Instant-Form
47439
+ lead ad: `linkUrl` and per-card `linkUrl` become OPTIONAL and, when sent, are
47440
+ forwarded as the real card and top-level destinations; when omitted, the
47441
+ destination falls back to Meta's lead-form link.
47419
47442
  items:
47420
47443
  type: object
47421
47444
  required: [imageUrl]
47422
47445
  properties:
47423
47446
  imageUrl: { type: string, format: uri, description: "Card image; uploaded to the ad account and referenced by hash." }
47424
- linkUrl: { type: string, format: uri, description: "Card destination URL. Defaults to the top-level linkUrl." }
47447
+ linkUrl: { type: string, format: uri, description: "Card destination URL. Defaults to the top-level linkUrl, or Meta's lead-form link when leadGenFormId is set and neither is provided." }
47425
47448
  headline: { type: string, maxLength: 255, description: "Card headline, shown below the card image." }
47426
47449
  description: { type: string, maxLength: 255, description: "Card description, shown under the headline." }
47427
47450
  callToAction: { type: string, description: "Card CTA override. Defaults to the top-level callToAction; same enum." }
@@ -97,7 +97,7 @@ describe 'AdCampaignsApi' do
97
97
 
98
98
  # unit tests for create_ad_set
99
99
  # Create a standalone ad group
100
- # Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via &#x60;existingAdGroupId&#x60; on POST /v1/ads/create. Google only; every other platform returns 501. Created &#x60;PAUSED&#x60; unless &#x60;status: ACTIVE&#x60;. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from &#x60;ads&#x60; rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an &#x60;Idempotency-Key&#x60; header to make retries safe.
100
+ # Google Ads compliance row C.190: creates an ad group WITHOUT an ad, under an existing campaign. Ads join it later via &#x60;adSetId&#x60; on POST /v1/ads/create. Google only; every other platform returns 501. Created &#x60;PAUSED&#x60; unless &#x60;status: ACTIVE&#x60;. The new ad group has no ad yet, so it will not appear in GET /v1/ads/tree (built purely from &#x60;ads&#x60; rows) until one is added; use GET /v1/ads/ad-sets to see it in the meantime. **Idempotency:** send an &#x60;Idempotency-Key&#x60; header to make retries safe.
101
101
  # @param create_ad_set_request
102
102
  # @param [Hash] opts the optional parameters
103
103
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409. Only 2xx responses are stored, so a request that failed with a 4xx can be retried with a corrected body under the SAME key.
@@ -122,7 +122,7 @@ describe 'AdCampaignsApi' do
122
122
 
123
123
  # unit tests for create_standalone_ad
124
124
  # Create standalone ad
125
- # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \&quot;dark post\&quot; authored by a Company Page (see &#x60;organizationId&#x60;). Supported goals are engagement, traffic, awareness, and video_views (video ads use the &#x60;video&#x60; field; video_views requires a video), and traffic ads require &#x60;linkUrl&#x60;. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an &#x60;Idempotency-Key&#x60; header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with &#x60;Idempotent-Replayed: true&#x60;) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
125
+ # Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads). Three mutually-exclusive request shapes are selected by the body: - Legacy single-creative shape (all platforms, the default). - Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting. - Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content \&quot;dark post\&quot; authored by a Company Page (see &#x60;organizationId&#x60;). Supported goals are engagement, traffic, awareness, and video_views (video ads use the &#x60;video&#x60; field; video_views requires a video), and traffic ads require &#x60;linkUrl&#x60;. **Idempotency:** this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an &#x60;Idempotency-Key&#x60; header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with &#x60;Idempotent-Replayed: true&#x60;) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
126
126
  # @param create_standalone_ad_request
127
127
  # @param [Hash] opts the optional parameters
128
128
  # @option opts [String] :idempotency_key Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
@@ -359,7 +359,7 @@ describe 'AdCampaignsApi' do
359
359
 
360
360
  # unit tests for list_ad_sets
361
361
  # List ad sets
362
- # Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the &#x60;ad_sets&#x60; table directly, independent of the &#x60;ads&#x60; rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via &#x60;existingAdGroupId&#x60;. Returns at most 500 rows, newest first.
362
+ # Ad sets (Google ad groups) synced for the connection, optionally filtered by platform and campaignId. Reads the &#x60;ad_sets&#x60; table directly, independent of the &#x60;ads&#x60; rollup GET /v1/ads/tree uses, so a newly created standalone ad group with no ad yet (POST /v1/ads/ad-sets, Google only) is visible here even though it is invisible in the tree until an ad joins it via &#x60;adSetId&#x60; on POST /v1/ads/create. Returns at most 500 rows, newest first.
363
363
  # @param [Hash] opts the optional parameters
364
364
  # @option opts [String] :account_id Account ID
365
365
  # @option opts [String] :campaign_id Platform campaign ID
@@ -14,16 +14,16 @@ require 'spec_helper'
14
14
  require 'json'
15
15
  require 'date'
16
16
 
17
- # Unit tests for Zernio::Conversation
17
+ # Unit tests for Zernio::InboxWebhookConversationDetail
18
18
  # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
19
  # Please update as you see appropriate
20
- describe Zernio::Conversation do
21
- #let(:instance) { Zernio::Conversation.new }
20
+ describe Zernio::InboxWebhookConversationDetail do
21
+ #let(:instance) { Zernio::InboxWebhookConversationDetail.new }
22
22
 
23
- describe 'test an instance of Conversation' do
24
- it 'should create an instance of Conversation' do
23
+ describe 'test an instance of InboxWebhookConversationDetail' do
24
+ it 'should create an instance of InboxWebhookConversationDetail' do
25
25
  # uncomment below to test the instance creation
26
- #expect(instance).to be_instance_of(Zernio::Conversation)
26
+ #expect(instance).to be_instance_of(Zernio::InboxWebhookConversationDetail)
27
27
  end
28
28
  end
29
29
 
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: late-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.890
4
+ version: 0.0.892
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenAPI-Generator
@@ -309,7 +309,6 @@ files:
309
309
  - docs/ConnectedApp.md
310
310
  - docs/ConnectedAppsApi.md
311
311
  - docs/ContactsApi.md
312
- - docs/Conversation.md
313
312
  - docs/ConversionAction.md
314
313
  - docs/ConversionActionTagSnippetsInner.md
315
314
  - docs/ConversionDestination.md
@@ -997,6 +996,7 @@ files:
997
996
  - docs/InboxMessageEditHistoryEntry.md
998
997
  - docs/InboxWebhookAccount.md
999
998
  - docs/InboxWebhookConversation.md
999
+ - docs/InboxWebhookConversationDetail.md
1000
1000
  - docs/InboxWebhookMessage.md
1001
1001
  - docs/InboxWebhookMessageAttachmentsInner.md
1002
1002
  - docs/InboxWebhookMessageSender.md
@@ -1938,7 +1938,6 @@ files:
1938
1938
  - docs/WebhookPayloadConversationControlChanged.md
1939
1939
  - docs/WebhookPayloadConversationControlChangedControl.md
1940
1940
  - docs/WebhookPayloadConversationStarted.md
1941
- - docs/WebhookPayloadConversationStartedConversation.md
1942
1941
  - docs/WebhookPayloadExternalPost.md
1943
1942
  - docs/WebhookPayloadLead.md
1944
1943
  - docs/WebhookPayloadLeadAccount.md
@@ -2360,7 +2359,6 @@ files:
2360
2359
  - lib/zernio-sdk/models/connected.rb
2361
2360
  - lib/zernio-sdk/models/connected_account.rb
2362
2361
  - lib/zernio-sdk/models/connected_app.rb
2363
- - lib/zernio-sdk/models/conversation.rb
2364
2362
  - lib/zernio-sdk/models/conversion_action.rb
2365
2363
  - lib/zernio-sdk/models/conversion_action_tag_snippets_inner.rb
2366
2364
  - lib/zernio-sdk/models/conversion_destination.rb
@@ -3036,6 +3034,7 @@ files:
3036
3034
  - lib/zernio-sdk/models/inbox_message_edit_history_entry.rb
3037
3035
  - lib/zernio-sdk/models/inbox_webhook_account.rb
3038
3036
  - lib/zernio-sdk/models/inbox_webhook_conversation.rb
3037
+ - lib/zernio-sdk/models/inbox_webhook_conversation_detail.rb
3039
3038
  - lib/zernio-sdk/models/inbox_webhook_message.rb
3040
3039
  - lib/zernio-sdk/models/inbox_webhook_message_attachments_inner.rb
3041
3040
  - lib/zernio-sdk/models/inbox_webhook_message_sender.rb
@@ -3950,7 +3949,6 @@ files:
3950
3949
  - lib/zernio-sdk/models/webhook_payload_conversation_control_changed.rb
3951
3950
  - lib/zernio-sdk/models/webhook_payload_conversation_control_changed_control.rb
3952
3951
  - lib/zernio-sdk/models/webhook_payload_conversation_started.rb
3953
- - lib/zernio-sdk/models/webhook_payload_conversation_started_conversation.rb
3954
3952
  - lib/zernio-sdk/models/webhook_payload_external_post.rb
3955
3953
  - lib/zernio-sdk/models/webhook_payload_lead.rb
3956
3954
  - lib/zernio-sdk/models/webhook_payload_lead_account.rb
@@ -4358,7 +4356,6 @@ files:
4358
4356
  - spec/models/connected_account_spec.rb
4359
4357
  - spec/models/connected_app_spec.rb
4360
4358
  - spec/models/connected_spec.rb
4361
- - spec/models/conversation_spec.rb
4362
4359
  - spec/models/conversion_action_spec.rb
4363
4360
  - spec/models/conversion_action_tag_snippets_inner_spec.rb
4364
4361
  - spec/models/conversion_destination_spec.rb
@@ -5033,6 +5030,7 @@ files:
5033
5030
  - spec/models/inbox_message_edit_attachment_spec.rb
5034
5031
  - spec/models/inbox_message_edit_history_entry_spec.rb
5035
5032
  - spec/models/inbox_webhook_account_spec.rb
5033
+ - spec/models/inbox_webhook_conversation_detail_spec.rb
5036
5034
  - spec/models/inbox_webhook_conversation_spec.rb
5037
5035
  - spec/models/inbox_webhook_message_attachments_inner_spec.rb
5038
5036
  - spec/models/inbox_webhook_message_sender_instagram_profile_spec.rb
@@ -5946,7 +5944,6 @@ files:
5946
5944
  - spec/models/webhook_payload_comment_spec.rb
5947
5945
  - spec/models/webhook_payload_conversation_control_changed_control_spec.rb
5948
5946
  - spec/models/webhook_payload_conversation_control_changed_spec.rb
5949
- - spec/models/webhook_payload_conversation_started_conversation_spec.rb
5950
5947
  - spec/models/webhook_payload_conversation_started_spec.rb
5951
5948
  - spec/models/webhook_payload_external_post_spec.rb
5952
5949
  - spec/models/webhook_payload_lead_account_spec.rb
@@ -6067,7 +6064,7 @@ files:
6067
6064
  - spec/models/you_tube_video_retention_response_retention_curve_inner_spec.rb
6068
6065
  - spec/models/you_tube_video_retention_response_spec.rb
6069
6066
  - spec/spec_helper.rb
6070
- - zernio-sdk-0.0.890.gem
6067
+ - zernio-sdk-0.0.892.gem
6071
6068
  - zernio-sdk.gemspec
6072
6069
  homepage: https://openapi-generator.tech
6073
6070
  licenses:
@@ -6941,7 +6938,6 @@ test_files:
6941
6938
  - spec/models/list_inbox_conversation_analytics200_response_spec.rb
6942
6939
  - spec/models/targeting_spec_excluded_locations_places_inner_spec.rb
6943
6940
  - spec/models/list_high_demand_periods200_response_spec.rb
6944
- - spec/models/conversation_spec.rb
6945
6941
  - spec/models/create_voice_call200_response_spec.rb
6946
6942
  - spec/models/create_standalone_ad_request_dynamic_creative_spec.rb
6947
6943
  - spec/models/inbox_webhook_message_sender_instagram_profile_spec.rb
@@ -7751,6 +7747,7 @@ test_files:
7751
7747
  - spec/models/get_whats_app_sdk_config200_response_spec.rb
7752
7748
  - spec/models/whats_app_carousel_component_cards_inner_spec.rb
7753
7749
  - spec/models/get_inbox_conversation_messages200_response_messages_inner_attachments_inner_spec.rb
7750
+ - spec/models/inbox_webhook_conversation_detail_spec.rb
7754
7751
  - spec/models/validate_post_request_spec.rb
7755
7752
  - spec/models/list_users200_response_spec.rb
7756
7753
  - spec/models/ad_keyword_metrics_spec.rb
@@ -8023,7 +8020,6 @@ test_files:
8023
8020
  - spec/models/webhook_payload_call_received_spec.rb
8024
8021
  - spec/models/update_discord_settings200_response_account_spec.rb
8025
8022
  - spec/models/get_whats_app_business_profile200_response_spec.rb
8026
- - spec/models/webhook_payload_conversation_started_conversation_spec.rb
8027
8023
  - spec/models/get_inbox_conversation_messages200_response_spec.rb
8028
8024
  - spec/models/get_google_business_reviews200_response_spec.rb
8029
8025
  - spec/models/list_whats_app_flow_versions200_response_spec.rb
@@ -1,34 +0,0 @@
1
- # Zernio::WebhookPayloadConversationStartedConversation
2
-
3
- ## Properties
4
-
5
- | Name | Type | Description | Notes |
6
- | ---- | ---- | ----------- | ----- |
7
- | **id** | **String** | Internal conversation ID | |
8
- | **platform** | **String** | | |
9
- | **platform_conversation_id** | **String** | | |
10
- | **participant_id** | **String** | Contact&#39;s platform identifier (IGSID, PSID, wa_id, etc.) | [optional] |
11
- | **participant_name** | **String** | | |
12
- | **participant_username** | **String** | Contact&#39;s handle when the platform exposes one | [optional] |
13
- | **participant_picture** | **String** | | [optional] |
14
- | **status** | **String** | | |
15
- | **contact_id** | **String** | Zernio CRM Contact ID for the participant, when one exists. Resolved by joining &#x60;participantId&#x60; to the ContactChannel collection (same join used by message.*, reaction.received, and call.* webhooks). Best-effort: omitted when no channel matches or &#x60;participantId&#x60; is absent. Lets integrators seed the CRM straight from &#x60;conversation.started&#x60; without waiting for the first &#x60;message.*&#x60; event. | [optional] |
16
-
17
- ## Example
18
-
19
- ```ruby
20
- require 'zernio-sdk'
21
-
22
- instance = Zernio::WebhookPayloadConversationStartedConversation.new(
23
- id: null,
24
- platform: null,
25
- platform_conversation_id: null,
26
- participant_id: null,
27
- participant_name: null,
28
- participant_username: null,
29
- participant_picture: null,
30
- status: null,
31
- contact_id: null
32
- )
33
- ```
34
-
@@ -1,334 +0,0 @@
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 WebhookPayloadConversationStartedConversation < ApiModelBase
18
- # Internal conversation ID
19
- attr_accessor :id
20
-
21
- attr_accessor :platform
22
-
23
- attr_accessor :platform_conversation_id
24
-
25
- # Contact's platform identifier (IGSID, PSID, wa_id, etc.)
26
- attr_accessor :participant_id
27
-
28
- attr_accessor :participant_name
29
-
30
- # Contact's handle when the platform exposes one
31
- attr_accessor :participant_username
32
-
33
- attr_accessor :participant_picture
34
-
35
- attr_accessor :status
36
-
37
- # Zernio CRM Contact ID for the participant, when one exists. Resolved by joining `participantId` to the ContactChannel collection (same join used by message.*, reaction.received, and call.* webhooks). Best-effort: omitted when no channel matches or `participantId` is absent. Lets integrators seed the CRM straight from `conversation.started` without waiting for the first `message.*` event.
38
- attr_accessor :contact_id
39
-
40
- class EnumAttributeValidator
41
- attr_reader :datatype
42
- attr_reader :allowable_values
43
-
44
- def initialize(datatype, allowable_values)
45
- @allowable_values = allowable_values.map do |value|
46
- case datatype.to_s
47
- when /Integer/i
48
- value.to_i
49
- when /Float/i
50
- value.to_f
51
- else
52
- value
53
- end
54
- end
55
- end
56
-
57
- def valid?(value)
58
- !value || allowable_values.include?(value)
59
- end
60
- end
61
-
62
- # Attribute mapping from ruby-style variable name to JSON key.
63
- def self.attribute_map
64
- {
65
- :'id' => :'id',
66
- :'platform' => :'platform',
67
- :'platform_conversation_id' => :'platformConversationId',
68
- :'participant_id' => :'participantId',
69
- :'participant_name' => :'participantName',
70
- :'participant_username' => :'participantUsername',
71
- :'participant_picture' => :'participantPicture',
72
- :'status' => :'status',
73
- :'contact_id' => :'contactId'
74
- }
75
- end
76
-
77
- # Returns attribute mapping this model knows about
78
- def self.acceptable_attribute_map
79
- attribute_map
80
- end
81
-
82
- # Returns all the JSON keys this model knows about
83
- def self.acceptable_attributes
84
- acceptable_attribute_map.values
85
- end
86
-
87
- # Attribute type mapping.
88
- def self.openapi_types
89
- {
90
- :'id' => :'String',
91
- :'platform' => :'String',
92
- :'platform_conversation_id' => :'String',
93
- :'participant_id' => :'String',
94
- :'participant_name' => :'String',
95
- :'participant_username' => :'String',
96
- :'participant_picture' => :'String',
97
- :'status' => :'String',
98
- :'contact_id' => :'String'
99
- }
100
- end
101
-
102
- # List of attributes with nullable: true
103
- def self.openapi_nullable
104
- Set.new([
105
- ])
106
- end
107
-
108
- # Initializes the object
109
- # @param [Hash] attributes Model attributes in the form of hash
110
- def initialize(attributes = {})
111
- if (!attributes.is_a?(Hash))
112
- fail ArgumentError, "The input argument (attributes) must be a hash in `Zernio::WebhookPayloadConversationStartedConversation` initialize method"
113
- end
114
-
115
- # check to see if the attribute exists and convert string to symbol for hash key
116
- acceptable_attribute_map = self.class.acceptable_attribute_map
117
- attributes = attributes.each_with_object({}) { |(k, v), h|
118
- if (!acceptable_attribute_map.key?(k.to_sym))
119
- fail ArgumentError, "`#{k}` is not a valid attribute in `Zernio::WebhookPayloadConversationStartedConversation`. Please check the name to make sure it's valid. List of attributes: " + acceptable_attribute_map.keys.inspect
120
- end
121
- h[k.to_sym] = v
122
- }
123
-
124
- if attributes.key?(:'id')
125
- self.id = attributes[:'id']
126
- else
127
- self.id = nil
128
- end
129
-
130
- if attributes.key?(:'platform')
131
- self.platform = attributes[:'platform']
132
- else
133
- self.platform = nil
134
- end
135
-
136
- if attributes.key?(:'platform_conversation_id')
137
- self.platform_conversation_id = attributes[:'platform_conversation_id']
138
- else
139
- self.platform_conversation_id = nil
140
- end
141
-
142
- if attributes.key?(:'participant_id')
143
- self.participant_id = attributes[:'participant_id']
144
- end
145
-
146
- if attributes.key?(:'participant_name')
147
- self.participant_name = attributes[:'participant_name']
148
- else
149
- self.participant_name = nil
150
- end
151
-
152
- if attributes.key?(:'participant_username')
153
- self.participant_username = attributes[:'participant_username']
154
- end
155
-
156
- if attributes.key?(:'participant_picture')
157
- self.participant_picture = attributes[:'participant_picture']
158
- end
159
-
160
- if attributes.key?(:'status')
161
- self.status = attributes[:'status']
162
- else
163
- self.status = nil
164
- end
165
-
166
- if attributes.key?(:'contact_id')
167
- self.contact_id = attributes[:'contact_id']
168
- end
169
- end
170
-
171
- # Show invalid properties with the reasons. Usually used together with valid?
172
- # @return Array for valid properties with the reasons
173
- def list_invalid_properties
174
- warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
175
- invalid_properties = Array.new
176
- if @id.nil?
177
- invalid_properties.push('invalid value for "id", id cannot be nil.')
178
- end
179
-
180
- if @platform.nil?
181
- invalid_properties.push('invalid value for "platform", platform cannot be nil.')
182
- end
183
-
184
- if @platform_conversation_id.nil?
185
- invalid_properties.push('invalid value for "platform_conversation_id", platform_conversation_id cannot be nil.')
186
- end
187
-
188
- if @participant_name.nil?
189
- invalid_properties.push('invalid value for "participant_name", participant_name cannot be nil.')
190
- end
191
-
192
- if @status.nil?
193
- invalid_properties.push('invalid value for "status", status cannot be nil.')
194
- end
195
-
196
- invalid_properties
197
- end
198
-
199
- # Check to see if the all the properties in the model are valid
200
- # @return true if the model is valid
201
- def valid?
202
- warn '[DEPRECATED] the `valid?` method is obsolete'
203
- return false if @id.nil?
204
- return false if @platform.nil?
205
- platform_validator = EnumAttributeValidator.new('String', ["instagram", "facebook", "telegram", "whatsapp", "twitter", "reddit", "bluesky", "sms", "slack"])
206
- return false unless platform_validator.valid?(@platform)
207
- return false if @platform_conversation_id.nil?
208
- return false if @participant_name.nil?
209
- return false if @status.nil?
210
- status_validator = EnumAttributeValidator.new('String', ["active", "archived"])
211
- return false unless status_validator.valid?(@status)
212
- true
213
- end
214
-
215
- # Custom attribute writer method with validation
216
- # @param [Object] id Value to be assigned
217
- def id=(id)
218
- if id.nil?
219
- fail ArgumentError, 'id cannot be nil'
220
- end
221
-
222
- @id = id
223
- end
224
-
225
- # Custom attribute writer method checking allowed values (enum).
226
- # @param [Object] platform Object to be assigned
227
- def platform=(platform)
228
- validator = EnumAttributeValidator.new('String', ["instagram", "facebook", "telegram", "whatsapp", "twitter", "reddit", "bluesky", "sms", "slack"])
229
- unless validator.valid?(platform)
230
- fail ArgumentError, "invalid value for \"platform\", must be one of #{validator.allowable_values}."
231
- end
232
- @platform = platform
233
- end
234
-
235
- # Custom attribute writer method with validation
236
- # @param [Object] platform_conversation_id Value to be assigned
237
- def platform_conversation_id=(platform_conversation_id)
238
- if platform_conversation_id.nil?
239
- fail ArgumentError, 'platform_conversation_id cannot be nil'
240
- end
241
-
242
- @platform_conversation_id = platform_conversation_id
243
- end
244
-
245
- # Custom attribute writer method with validation
246
- # @param [Object] participant_name Value to be assigned
247
- def participant_name=(participant_name)
248
- if participant_name.nil?
249
- fail ArgumentError, 'participant_name cannot be nil'
250
- end
251
-
252
- @participant_name = participant_name
253
- end
254
-
255
- # Custom attribute writer method checking allowed values (enum).
256
- # @param [Object] status Object to be assigned
257
- def status=(status)
258
- validator = EnumAttributeValidator.new('String', ["active", "archived"])
259
- unless validator.valid?(status)
260
- fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}."
261
- end
262
- @status = status
263
- end
264
-
265
- # Checks equality by comparing each attribute.
266
- # @param [Object] Object to be compared
267
- def ==(o)
268
- return true if self.equal?(o)
269
- self.class == o.class &&
270
- id == o.id &&
271
- platform == o.platform &&
272
- platform_conversation_id == o.platform_conversation_id &&
273
- participant_id == o.participant_id &&
274
- participant_name == o.participant_name &&
275
- participant_username == o.participant_username &&
276
- participant_picture == o.participant_picture &&
277
- status == o.status &&
278
- contact_id == o.contact_id
279
- end
280
-
281
- # @see the `==` method
282
- # @param [Object] Object to be compared
283
- def eql?(o)
284
- self == o
285
- end
286
-
287
- # Calculates hash code according to all attributes.
288
- # @return [Integer] Hash code
289
- def hash
290
- [id, platform, platform_conversation_id, participant_id, participant_name, participant_username, participant_picture, status, contact_id].hash
291
- end
292
-
293
- # Builds the object from hash
294
- # @param [Hash] attributes Model attributes in the form of hash
295
- # @return [Object] Returns the model itself
296
- def self.build_from_hash(attributes)
297
- return nil unless attributes.is_a?(Hash)
298
- attributes = attributes.transform_keys(&:to_sym)
299
- transformed_hash = {}
300
- openapi_types.each_pair do |key, type|
301
- if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
302
- transformed_hash["#{key}"] = nil
303
- elsif type =~ /\AArray<(.*)>/i
304
- # check to ensure the input is an array given that the attribute
305
- # is documented as an array but the input is not
306
- if attributes[attribute_map[key]].is_a?(Array)
307
- transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
308
- end
309
- elsif !attributes[attribute_map[key]].nil?
310
- transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
311
- end
312
- end
313
- new(transformed_hash)
314
- end
315
-
316
- # Returns the object in the form of hash
317
- # @return [Hash] Returns the object in the form of hash
318
- def to_hash
319
- hash = {}
320
- self.class.attribute_map.each_pair do |attr, param|
321
- value = self.send(attr)
322
- if value.nil?
323
- is_nullable = self.class.openapi_nullable.include?(attr)
324
- next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
325
- end
326
-
327
- hash[param] = _to_hash(value)
328
- end
329
- hash
330
- end
331
-
332
- end
333
-
334
- end
@@ -1,92 +0,0 @@
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::WebhookPayloadConversationStartedConversation
18
- # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
- # Please update as you see appropriate
20
- describe Zernio::WebhookPayloadConversationStartedConversation do
21
- #let(:instance) { Zernio::WebhookPayloadConversationStartedConversation.new }
22
-
23
- describe 'test an instance of WebhookPayloadConversationStartedConversation' do
24
- it 'should create an instance of WebhookPayloadConversationStartedConversation' do
25
- # uncomment below to test the instance creation
26
- #expect(instance).to be_instance_of(Zernio::WebhookPayloadConversationStartedConversation)
27
- end
28
- end
29
-
30
- describe 'test attribute "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 "platform"' do
37
- it 'should work' do
38
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
39
- # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["instagram", "facebook", "telegram", "whatsapp", "twitter", "reddit", "bluesky", "sms", "slack"])
40
- # validator.allowable_values.each do |value|
41
- # expect { instance.platform = value }.not_to raise_error
42
- # end
43
- end
44
- end
45
-
46
- describe 'test attribute "platform_conversation_id"' do
47
- it 'should work' do
48
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
49
- end
50
- end
51
-
52
- describe 'test attribute "participant_id"' do
53
- it 'should work' do
54
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
55
- end
56
- end
57
-
58
- describe 'test attribute "participant_name"' do
59
- it 'should work' do
60
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
61
- end
62
- end
63
-
64
- describe 'test attribute "participant_username"' do
65
- it 'should work' do
66
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
67
- end
68
- end
69
-
70
- describe 'test attribute "participant_picture"' do
71
- it 'should work' do
72
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
73
- end
74
- end
75
-
76
- describe 'test attribute "status"' do
77
- it 'should work' do
78
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
79
- # validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["active", "archived"])
80
- # validator.allowable_values.each do |value|
81
- # expect { instance.status = value }.not_to raise_error
82
- # end
83
- end
84
- end
85
-
86
- describe 'test attribute "contact_id"' do
87
- it 'should work' do
88
- # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
89
- end
90
- end
91
-
92
- end
Binary file