/*
* Zernio API
*
* 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). Request ids: responses carry an X-Request-Id header with the id we log the request under. Quote it when reporting a problem. A valid x-request-id you send is reused as that id.
*
* The version of the OpenAPI document: 1.212.1
* Contact: support@zernio.com
* Generated by: https://openapi-generator.tech
*/
use crate::models;
use serde::{Deserialize, Serialize};
/// UploadedOrDerivedAudience : customer_list, website, lookalike or engagement audience (uploaded or derived from a source).
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct UploadedOrDerivedAudience {
#[serde(rename = "accountId")]
pub account_id: String,
/// Platform ad account ID. Must start with act_ for Meta; bare platform id for others (Google customer id, X/TikTok/LinkedIn/Pinterest account id).
#[serde(rename = "adAccountId")]
pub ad_account_id: String,
#[serde(rename = "name")]
pub name: String,
#[serde(rename = "description", skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(rename = "type")]
pub r#type: Type,
/// Required for website_retargeting audiences (LinkedIn only). Each rule is a URL pattern; a member who visits any matching page enters the segment. Needs the LinkedIn Insight Tag installed on the customer's site; the segment only starts filling once the tag reports visits. The response's `platformAudienceId` is the LinkedIn adSegment id, valid for downstream use. These segments appear in GET /v1/ads/audiences with `type: website_retargeting` once LinkedIn has finished building them.
#[serde(rename = "matchRules", skip_serializing_if = "Option::is_none")]
pub match_rules: Option<Vec<models::UploadedOrDerivedAudienceMatchRulesInner>>,
/// Required for engagement audiences (LinkedIn only): what members engaged with: a video/leadgen/single-image ad campaign, a Company Page or an Event page.
#[serde(rename = "sourceType", skip_serializing_if = "Option::is_none")]
pub source_type: Option<SourceType>,
/// Required for engagement audiences. The action, validated by LinkedIn against `sourceType`. Common values: VIDEO_ADS FIRST_QUARTILE / MIDPOINT / THIRD_QUARTILE / FULL_COMPLETE; LEAD_GEN_FORMS VIEW_FORM / LEAD_FORM_SUBMIT; ORGANIZATION_PAGES VIEW / CTA_CLICK; EVENT_PAGES RSVPED / VIDEO_VIEWED / ENGAGEMENT / CLICK.
#[serde(rename = "trigger", skip_serializing_if = "Option::is_none")]
pub trigger: Option<String>,
/// Required for engagement audiences. Rolling window.
#[serde(rename = "lookbackDays", skip_serializing_if = "Option::is_none")]
pub lookback_days: Option<LookbackDays>,
/// Required for engagement audiences. Campaign URNs for the ad source types, organization URNs for pages and events. LinkedIn creates one rule per source, all sharing the same trigger and lookbackDays.
#[serde(rename = "engagementSources", skip_serializing_if = "Option::is_none")]
pub engagement_sources: Option<Vec<String>>,
/// Required for company_list audiences (LinkedIn only): plain-text company rows for account targeting. Each row needs at least one identifier. Not hashed, LinkedIn matches these against its own company graph. LinkedIn recommends 1,000+ companies for a usable match rate and takes up to 48h to process the list. Replace the list later with POST /v1/ads/audiences/{audienceId}/companies.
#[serde(rename = "companies", skip_serializing_if = "Option::is_none")]
pub companies: Option<Vec<models::UploadedOrDerivedAudienceCompaniesInner>>,
/// website: the Meta pixel, TikTok pixel or Pinterest tag id. Required on those three, rejected on Google.
#[serde(rename = "pixelId", skip_serializing_if = "Option::is_none")]
pub pixel_id: Option<String>,
/// Required for website (Meta max 180, TikTok 7/14/30/60/90/180, Pinterest and Google max 540), meta_engagement (max 365) and tiktok_engagement (7/14/30/60/90/180; organic and live video and most business-account events only 7/14/30).
#[serde(rename = "retentionDays", skip_serializing_if = "Option::is_none")]
pub retention_days: Option<i32>,
/// Required for meta_engagement audiences (Meta only): what people engaged with. `page` = a Facebook Page, `instagram` = an IG professional account, `video` = a video.
#[serde(rename = "engagementSource", skip_serializing_if = "Option::is_none")]
pub engagement_source: Option<EngagementSource>,
/// Required for meta_engagement: the Page / IG account / video id.
#[serde(rename = "sourceId", skip_serializing_if = "Option::is_none")]
pub source_id: Option<String>,
/// meta_engagement: the engagement event; defaults per source (page → page_engaged, instagram → ig_business_profile_all, video → video_watched). Ignored when `rule` is provided. website on TikTok: the pixel event (default `PAGE BROWSE`). website on Pinterest: the tag event (`pagevisit`, `signup`, `checkout`, `viewcategory`, `search`, `addtocart`, `watchvideo`, `lead`, `custom` or a partner-defined event). tiktok_engagement (required): the TikTok engagement event, validated per `source` (TikTok's filter values, spaces included): - ads: `CLICK`, `IMPRESSION`, `PLAY 2S`, `PLAY 6S`, `PLAY 25`, `PLAY 50`, `PLAY 75`, `PLAY OVER`, and the `ENGAGEMENT APP PROFILE` / `ENGAGEMENT TIKTOK INSTANT` / `ENGAGEMENT COLLECTION ADS` `CLICK` and `IMPRESSION` events. - organic_video: `ORGANIC VIDEO PLAY 2S`, `ORGANIC VIDEO PLAY 6S`, `ORGANIC VIDEO PLAY OVER`, `ORGANIC VIDEO ENGAGEMENT`. - live_video: `LIVE VIDEO VIEW`, `LIVE VIDEO ENGAGEMENT`. - business_account: `BUSINESS ACCOUNT PROFILE FOLLOW`, `BUSINESS ACCOUNT PROFILE VISIT`, `BUSINESS ACCOUNT ENGAGEMENT`, `BUSINESS ACCOUNT PLAY 2S`, `BUSINESS ACCOUNT PLAY 6S`, `BUSINESS ACCOUNT PLAY OVER` and the rest of TikTok's business-account events. An unknown value is a 400 that lists the valid ones.
#[serde(rename = "event", skip_serializing_if = "Option::is_none")]
pub event: Option<String>,
/// Required for lookalike audiences
#[serde(rename = "sourceAudienceId", skip_serializing_if = "Option::is_none")]
pub source_audience_id: Option<String>,
/// 2-letter code, required for lookalike audiences
#[serde(rename = "country", skip_serializing_if = "Option::is_none")]
pub country: Option<String>,
/// lookalike on Meta (0.01-0.20) and Pinterest (0.01-0.10, whole percents). Rejected on TikTok and Google.
#[serde(rename = "ratio", skip_serializing_if = "Option::is_none")]
pub ratio: Option<f64>,
/// lookalike on TikTok and Google: audience breadth. Rejected on Meta and Pinterest.
#[serde(rename = "size", skip_serializing_if = "Option::is_none")]
pub size: Option<Size>,
/// Required for tiktok_engagement: what people engaged with.
#[serde(rename = "source", skip_serializing_if = "Option::is_none")]
pub source: Option<Source>,
/// tiktok_engagement: ad group / campaign ids for `ads`, video ids for `organic_video` and `live_video` (max 10). Required except for `business_account`.
#[serde(rename = "sourceIds", skip_serializing_if = "Option::is_none")]
pub source_ids: Option<Vec<String>>,
/// tiktok_engagement: the TikTok identity that owns the videos or business account. Required for organic_video, live_video and business_account.
#[serde(rename = "identityId", skip_serializing_if = "Option::is_none")]
pub identity_id: Option<String>,
/// tiktok_engagement: type of `identityId`.
#[serde(rename = "identityType", skip_serializing_if = "Option::is_none")]
pub identity_type: Option<IdentityType>,
/// tiktok_engagement: required when identityType is BC_AUTH_TT.
#[serde(
rename = "identityAuthorizedBcId",
skip_serializing_if = "Option::is_none"
)]
pub identity_authorized_bc_id: Option<String>,
/// pinterest_engagement: Pinterest's `engager_type`, passed through when set.
#[serde(rename = "engagerType", skip_serializing_if = "Option::is_none")]
pub engager_type: Option<EngagerType>,
/// pinterest_engagement: limit to one engagement action.
#[serde(rename = "engagementType", skip_serializing_if = "Option::is_none")]
pub engagement_type: Option<EngagementType>,
/// pinterest_engagement: people who engaged with Pins from these domains. The domain must be claimed on the Pinterest account or Pinterest rejects it.
#[serde(rename = "engagementDomains", skip_serializing_if = "Option::is_none")]
pub engagement_domains: Option<Vec<String>>,
/// pinterest_engagement: people who engaged with these campaigns' ads.
#[serde(rename = "campaignIds", skip_serializing_if = "Option::is_none")]
pub campaign_ids: Option<Vec<String>>,
/// pinterest_engagement: people who engaged with these ads.
#[serde(rename = "adIds", skip_serializing_if = "Option::is_none")]
pub ad_ids: Option<Vec<String>>,
/// pinterest_engagement: people who engaged with these Pins. At least one of engagementDomains, campaignIds, adIds or pinIds is required.
#[serde(rename = "pinIds", skip_serializing_if = "Option::is_none")]
pub pin_ids: Option<Vec<String>>,
/// website on Meta, TikTok and Google. Narrows the audience from all visitors to visitors of URLs containing this substring. Ignored when `rule` is supplied. A 400 on Pinterest, which only matches exact URLs.
#[serde(rename = "urlContains", skip_serializing_if = "Option::is_none")]
pub url_contains: Option<String>,
/// Meta only (a 400 elsewhere). Optional raw Meta rule, replacing the one we build. Omit it for all visitors of `pixelId`, or use `urlContains` for the common page-match case. For `website` this is Meta's Flexible Audience Rule and is VALIDATED before we call Meta: every entry in `inclusions.rules` (and `exclusions.rules`) must carry `event_sources`, `retention_seconds` AND `filter`. Meta rejects a rule missing any of the three with code 100 / subcode 1713098 (\"Invalid rule JSON format\"), so a bad shape is a 400 here instead. The pre-2018 flat shapes (`{url: ...}`, `{event: ...}`) are not accepted by Meta at all (subcode 1870029). Example, visitors of /checkout in the last 30 days: `{\"inclusions\":{\"operator\":\"or\",\"rules\":[{\"event_sources\":[{\"id\":\"<pixelId>\",\"type\":\"pixel\"}],\"retention_seconds\":2592000,\"filter\":{\"operator\":\"and\",\"filters\":[{\"field\":\"url\",\"operator\":\"i_contains\",\"value\":\"/checkout\"}]}}]}}` Note Meta DERIVES `retention_days` from `retention_seconds` and stores `event_sources[].id` as a number, so a rule read back will not be byte-identical to the one you sent. For `meta_engagement` the rule is forwarded verbatim and NOT validated: that type has two dialects (the `video` source uses a legacy flat array), so no single schema covers both.
#[serde(rename = "rule", skip_serializing_if = "Option::is_none")]
pub rule: Option<serde_json::Value>,
/// Data source declaration for GDPR compliance (customer_list only)
#[serde(rename = "customerFileSource", skip_serializing_if = "Option::is_none")]
pub customer_file_source: Option<String>,
}
impl UploadedOrDerivedAudience {
/// customer_list, website, lookalike or engagement audience (uploaded or derived from a source).
pub fn new(
account_id: String,
ad_account_id: String,
name: String,
r#type: Type,
) -> UploadedOrDerivedAudience {
UploadedOrDerivedAudience {
account_id,
ad_account_id,
name,
description: None,
r#type,
match_rules: None,
source_type: None,
trigger: None,
lookback_days: None,
engagement_sources: None,
companies: None,
pixel_id: None,
retention_days: None,
engagement_source: None,
source_id: None,
event: None,
source_audience_id: None,
country: None,
ratio: None,
size: None,
source: None,
source_ids: None,
identity_id: None,
identity_type: None,
identity_authorized_bc_id: None,
engager_type: None,
engagement_type: None,
engagement_domains: None,
campaign_ids: None,
ad_ids: None,
pin_ids: None,
url_contains: None,
rule: None,
customer_file_source: None,
}
}
}
///
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Type {
#[serde(rename = "customer_list")]
CustomerList,
#[serde(rename = "company_list")]
CompanyList,
#[serde(rename = "engagement")]
Engagement,
#[serde(rename = "meta_engagement")]
MetaEngagement,
#[serde(rename = "tiktok_engagement")]
TiktokEngagement,
#[serde(rename = "pinterest_engagement")]
PinterestEngagement,
#[serde(rename = "website")]
Website,
#[serde(rename = "website_retargeting")]
WebsiteRetargeting,
#[serde(rename = "lookalike")]
Lookalike,
}
impl Default for Type {
fn default() -> Type {
Self::CustomerList
}
}
/// Required for engagement audiences (LinkedIn only): what members engaged with: a video/leadgen/single-image ad campaign, a Company Page or an Event page.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum SourceType {
#[serde(rename = "VIDEO_ADS")]
VideoAds,
#[serde(rename = "LEAD_GEN_FORMS")]
LeadGenForms,
#[serde(rename = "ORGANIZATION_PAGES")]
OrganizationPages,
#[serde(rename = "EVENT_PAGES")]
EventPages,
#[serde(rename = "SINGLE_IMAGE_ADS")]
SingleImageAds,
}
impl Default for SourceType {
fn default() -> SourceType {
Self::VideoAds
}
}
/// Required for engagement audiences. Rolling window.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum LookbackDays {
#[serde(rename = "30")]
Variant30,
#[serde(rename = "60")]
Variant60,
#[serde(rename = "90")]
Variant90,
#[serde(rename = "180")]
Variant180,
#[serde(rename = "365")]
Variant365,
}
impl Default for LookbackDays {
fn default() -> LookbackDays {
Self::Variant30
}
}
/// Required for meta_engagement audiences (Meta only): what people engaged with. `page` = a Facebook Page, `instagram` = an IG professional account, `video` = a video.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum EngagementSource {
#[serde(rename = "page")]
Page,
#[serde(rename = "instagram")]
Instagram,
#[serde(rename = "video")]
Video,
}
impl Default for EngagementSource {
fn default() -> EngagementSource {
Self::Page
}
}
/// lookalike on TikTok and Google: audience breadth. Rejected on Meta and Pinterest.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Size {
#[serde(rename = "narrow")]
Narrow,
#[serde(rename = "balanced")]
Balanced,
#[serde(rename = "broad")]
Broad,
}
impl Default for Size {
fn default() -> Size {
Self::Narrow
}
}
/// Required for tiktok_engagement: what people engaged with.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Source {
#[serde(rename = "ads")]
Ads,
#[serde(rename = "organic_video")]
OrganicVideo,
#[serde(rename = "live_video")]
LiveVideo,
#[serde(rename = "business_account")]
BusinessAccount,
}
impl Default for Source {
fn default() -> Source {
Self::Ads
}
}
/// tiktok_engagement: type of `identityId`.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum IdentityType {
#[serde(rename = "TT_USER")]
TtUser,
#[serde(rename = "BC_AUTH_TT")]
BcAuthTt,
}
impl Default for IdentityType {
fn default() -> IdentityType {
Self::TtUser
}
}
/// pinterest_engagement: Pinterest's `engager_type`, passed through when set.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum EngagerType {
#[serde(rename = "1")]
Variant1,
#[serde(rename = "2")]
Variant2,
}
impl Default for EngagerType {
fn default() -> EngagerType {
Self::Variant1
}
}
/// pinterest_engagement: limit to one engagement action.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum EngagementType {
#[serde(rename = "click")]
Click,
#[serde(rename = "save")]
Save,
#[serde(rename = "closeup")]
Closeup,
#[serde(rename = "comment")]
Comment,
#[serde(rename = "like")]
Like,
}
impl Default for EngagementType {
fn default() -> EngagementType {
Self::Click
}
}