late 0.0.1087

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.
Documentation
/*
 * 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.152.0
 * Contact: support@zernio.com
 * Generated by: https://openapi-generator.tech
 */

use crate::models;
use serde::{Deserialize, Serialize};

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
pub struct CreateCallAdRequest {
    /// Meta enhancement settings for single or attached ads, and defaults for creatives[]. An item replaces the entire map, including with an empty object.
    #[serde(rename = "creativeFeatures", skip_serializing_if = "Option::is_none")]
    pub creative_features: Option<CreativeFeatures>,
    #[serde(rename = "tracking", skip_serializing_if = "Option::is_none")]
    pub tracking: Option<Box<models::AdTracking>>,
    /// Facebook or Instagram SocialAccount ID.
    #[serde(rename = "accountId")]
    pub account_id: String,
    /// Meta ad account ID, e.g. `act_123456789`.
    #[serde(rename = "adAccountId")]
    pub ad_account_id: String,
    /// Ad display name. Used to derive campaign / ad set names. On the multi-creative shape, each ad's Meta name gets a \" #N\" suffix (1-indexed) so Ads Manager shows them as a numbered batch.
    #[serde(rename = "name")]
    pub name: String,
    /// Exact name for the campaign this request provisions. Omitted keeps `<name> - Campaign`. Ignored with `adSetId` (the ad set already has a campaign).
    #[serde(rename = "campaignName", skip_serializing_if = "Option::is_none")]
    pub campaign_name: Option<String>,
    /// Exact name for the ad set this request provisions. Omitted keeps `<name> - Ad Set`. Ignored with `adSetId`.
    #[serde(rename = "adSetName", skip_serializing_if = "Option::is_none")]
    pub ad_set_name: Option<String>,
    /// Messaging and CTWA only. Platform post or reel ID, the same input boostPost takes as platformPostId. Facebook IDs become object_story_id; Instagram IDs become source_instagram_media_id using the connected Instagram identity. Mutually exclusive with objectStoryId and fresh creative fields.
    #[serde(rename = "platformPostId", skip_serializing_if = "Option::is_none")]
    pub platform_post_id: Option<String>,
    /// Alias of platformPostId, kept for existing callers. Sending both with different values is a 400.
    #[serde(rename = "existingPostId", skip_serializing_if = "Option::is_none")]
    pub existing_post_id: Option<String>,
    /// Messaging and CTWA only. Raw Facebook pageId_postId reference, used as object_story_id even with an Instagram account. Mutually exclusive with platformPostId and fresh creative fields.
    #[serde(rename = "objectStoryId", skip_serializing_if = "Option::is_none")]
    pub object_story_id: Option<String>,
    /// Facebook Page the ad runs as, when the connection was granted several Pages. Defaults to the Page bound to the connection. Any Page granted to the connection is accepted; other ids answer 400 listing the granted Pages. Same semantics as `pageId` on POST /v1/ads/create.
    #[serde(rename = "pageId", skip_serializing_if = "Option::is_none")]
    pub page_id: Option<String>,
    /// WhatsApp only. Optional E.164 number already paired with the Facebook Page. Omit to let Meta select the paired number. Sent to the creative CTA and, when creating a new ad set, its promoted_object. Attach requests do not change the existing ad set. Stored as creative.whatsappPhoneNumber on every created ad.
    #[serde(
        rename = "whatsappPhoneNumber",
        skip_serializing_if = "Option::is_none"
    )]
    pub whatsapp_phone_number: Option<String>,
    /// Single-creative shape only. Mutually exclusive with `creatives[]`.
    #[serde(rename = "headline", skip_serializing_if = "Option::is_none")]
    pub headline: Option<String>,
    /// Primary text shown above the image / video. Single-creative shape only. Mutually exclusive with `creatives[]`.
    #[serde(rename = "body", skip_serializing_if = "Option::is_none")]
    pub body: Option<String>,
    /// Image asset for single-creative shape. Mutually exclusive with `video` and with `creatives[]`. Required on the single-creative shape if neither `video` nor an existing post reference is supplied.
    #[serde(rename = "imageUrl", skip_serializing_if = "Option::is_none")]
    pub image_url: Option<String>,
    #[serde(rename = "video", skip_serializing_if = "Option::is_none")]
    pub video: Option<Box<models::CtwaAdRequestBodyVideo>>,
    #[serde(rename = "welcomeMessage", skip_serializing_if = "Option::is_none")]
    pub welcome_message: Option<Box<models::CtwaAdRequestBodyWelcomeMessage>>,
    /// Multi-creative shape: N CTWA ads under one campaign + one ad set, sharing budget and targeting. Mutually exclusive with the top-level single-creative fields (`headline` / `body` / `imageUrl` / `video`): setting both is a 400, unlike `POST /v1/ads/create` where the top-level fields are silently ignored in multi-creative mode. Each entry supplies headline, body, and image/video, or a platformPostId or objectStoryId reference. Fresh and existing creatives can be mixed.
    #[serde(rename = "creatives", skip_serializing_if = "Option::is_none")]
    pub creatives: Option<Vec<models::CtwaAdRequestBodyCreativesInner>>,
    /// Attach the creatives to this EXISTING messaging ad set instead of building a campaign, so the ad set keeps its learning phase. It then owns budget, targeting and schedule, so `budgetAmount`, `budgetType`, `endDate`, `objective`, `countries`, `interests`, `audienceId` and `campaignStatus` are rejected with a 400 alongside it. Its `destination_type` must match the ad's destination.
    #[serde(rename = "adSetId", skip_serializing_if = "Option::is_none")]
    pub ad_set_id: Option<String>,
    /// Budget amount in the ad account's currency major units (e.g. dollars for USD, not cents). Must be > 0. Required unless `adSetId` is set, where the ad set owns it.
    #[serde(rename = "budgetAmount", skip_serializing_if = "Option::is_none")]
    pub budget_amount: Option<f64>,
    /// Required unless `adSetId` is set.
    #[serde(rename = "budgetType", skip_serializing_if = "Option::is_none")]
    pub budget_type: Option<BudgetType>,
    /// ISO 4217 currency code matching the ad account's currency (e.g. `USD`). Optional: Zernio resolves it from the ad account when omitted. The value selects the minor-unit exponent Zernio converts budget/bid amounts by before calling Meta (most currencies are cents; zero-decimal currencies like JPY/KRW are sent as-is).
    #[serde(rename = "currency", skip_serializing_if = "Option::is_none")]
    pub currency: Option<String>,
    /// ISO 8601 datetime. Required when `budgetType` is `lifetime`.
    #[serde(rename = "endDate", skip_serializing_if = "Option::is_none")]
    pub end_date: Option<String>,
    /// ISO 3166-1 alpha-2 country codes. Defaults to `[\"US\"]` only when no other geo (`cities`, `regions`, `zips`, `metros`, `customLocations`) is supplied.
    #[serde(rename = "countries", skip_serializing_if = "Option::is_none")]
    pub countries: Option<Vec<String>>,
    /// City-level geo targeting for local CTWA campaigns. Each entry maps to Meta's TargetingGeoLocationCity. `key` is Meta's city ID. `radius` and `distance_unit` are coupled: set both or neither. Meta enforces a minimum city radius (~17 km / 10 mi); smaller values resolve to a 0-size audience and the ad fails at launch. For a tighter catchment use customLocations (lat/lng).
    #[serde(rename = "cities", skip_serializing_if = "Option::is_none")]
    pub cities: Option<Vec<models::CtwaAdRequestBodyCitiesInner>>,
    /// Region / state-level geo targeting. `key` is Meta's region ID (lookupable via GET /v1/ads/targeting/search?type=region).
    #[serde(rename = "regions", skip_serializing_if = "Option::is_none")]
    pub regions: Option<Vec<models::CtwaAdRequestBodyRegionsInner>>,
    /// ZIP / postal-code geo targeting. `key` is the platform's postal id resolved via /v1/ads/targeting/search.
    #[serde(rename = "zips", skip_serializing_if = "Option::is_none")]
    pub zips: Option<Vec<models::CtwaAdRequestBodyZipsInner>>,
    /// DMA / metro-area geo targeting. `key` is Meta's metro id (e.g. `DMA:807`).
    #[serde(rename = "metros", skip_serializing_if = "Option::is_none")]
    pub metros: Option<Vec<models::CtwaAdRequestBodyZipsInner>>,
    /// Meta only. Continents and trade blocs (`geo_locations.country_groups`), for targeting a whole region without listing its countries. Combines with `countries` rather than replacing it, and is also accepted under `excludedLocations`. Discoverable via `GET /v1/ads/targeting/search?dimension=geo&geoType=country_group`.
    #[serde(rename = "countryGroups", skip_serializing_if = "Option::is_none")]
    pub country_groups: Option<Vec<CountryGroups>>,
    /// Point-radius geo (Meta `geo_locations.custom_locations`). Use for targeting a radius around a specific lat/long when no Meta city/region key fits. `distanceUnit` is required.
    #[serde(rename = "customLocations", skip_serializing_if = "Option::is_none")]
    pub custom_locations: Option<Vec<models::CreateStandaloneAdRequestCustomLocationsInner>>,
    #[serde(rename = "ageMin", skip_serializing_if = "Option::is_none")]
    pub age_min: Option<i32>,
    #[serde(rename = "ageMax", skip_serializing_if = "Option::is_none")]
    pub age_max: Option<i32>,
    #[serde(rename = "interests", skip_serializing_if = "Option::is_none")]
    pub interests: Option<Vec<models::CreateStandaloneAdRequestBehaviorsInner>>,
    /// Custom audience ID to target.
    #[serde(rename = "audienceId", skip_serializing_if = "Option::is_none")]
    pub audience_id: Option<String>,
    #[serde(rename = "placements", skip_serializing_if = "Option::is_none")]
    pub placements: Option<Box<models::CtwaAdRequestBodyPlacements>>,
    /// Meta's Advantage+ audience expansion. `0` (default) keeps targeting strict; `1` lets Meta expand beyond the supplied targeting when its delivery system finds better matches. Always sent on CREATE (Meta requires it).
    #[serde(rename = "advantageAudience", skip_serializing_if = "Option::is_none")]
    pub advantage_audience: Option<AdvantageAudience>,
    /// Defaults to `OUTCOME_ENGAGEMENT`. `OUTCOME_SALES` and `OUTCOME_LEADS` require additional account configuration (Dataset linked to the WABA for sales) and may be rejected by Meta if missing.
    #[serde(rename = "objective", skip_serializing_if = "Option::is_none")]
    pub objective: Option<Objective>,
    /// Defaults to `ACTIVE`. `PAUSED` pauses only the top-most object this call creates: the new campaign (ad set and ads switched on), or, with `adSetId`, the new ads themselves.
    #[serde(rename = "status", skip_serializing_if = "Option::is_none")]
    pub status: Option<Status>,
    /// Campaign-level status, same semantics as `POST /v1/ads/create`. Defaults to `status`. `PAUSED` holds the new campaign off while the ad set and ads switch on (one resume call brings the whole hierarchy live); `ACTIVE` with `status: PAUSED` switches the campaign on and pauses the new ad set instead. Only meaningful when a new campaign is being created; rejected with a 400 alongside `adSetId` (the attach shape reuses an existing campaign).
    #[serde(rename = "campaignStatus", skip_serializing_if = "Option::is_none")]
    pub campaign_status: Option<CampaignStatus>,
    /// Meta bid strategy applied to the shared ad set. Defaults to `LOWEST_COST_WITHOUT_CAP` (auto-bid) when omitted. `LOWEST_COST_WITH_BID_CAP` and `COST_CAP` require `bidAmount`. `LOWEST_COST_WITH_MIN_ROAS` requires `roasAverageFloor`. CTWA's `optimization_goal` is fixed to `CONVERSATIONS`, but the bid strategy is independent.
    #[serde(rename = "bidStrategy", skip_serializing_if = "Option::is_none")]
    pub bid_strategy: Option<BidStrategy>,
    /// Whole currency units (e.g. `5` = $5.00 on a USD account). Required when `bidStrategy` is `LOWEST_COST_WITH_BID_CAP` or `COST_CAP`; rejected otherwise.
    #[serde(rename = "bidAmount", skip_serializing_if = "Option::is_none")]
    pub bid_amount: Option<f64>,
    /// Decimal ROAS multiplier (e.g. `2.0` = 2.0× ROAS floor). Required when `bidStrategy` is `LOWEST_COST_WITH_MIN_ROAS`; rejected otherwise. Meta enforces its own upper bound server-side.
    #[serde(rename = "roasAverageFloor", skip_serializing_if = "Option::is_none")]
    pub roas_average_floor: Option<f64>,
    /// Legal entity that benefits from the ad. Required when targeting EU users (EU DSA, Article 26). Optional if the ad account has a default beneficiary: set it once via `PATCH /v1/ads/accounts` or in Meta Ads Manager, and Meta fills it in whenever the field is omitted.
    #[serde(rename = "dsaBeneficiary", skip_serializing_if = "Option::is_none")]
    pub dsa_beneficiary: Option<String>,
    /// Legal entity that pays for the ad. Can differ from `dsaBeneficiary` (for example, an agency paying for a client's ads). Same rules as `dsaBeneficiary`: required for EU targeting unless the ad account has a default payor.
    #[serde(rename = "dsaPayor", skip_serializing_if = "Option::is_none")]
    pub dsa_payor: Option<String>,
    /// Meta only. Regional regulation categories required when the ad set targets certain countries (e.g. BRAZIL_REGULATION, SINGAPORE_UNIVERSAL, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL, AUSTRALIA_FINSERV, INDIA_FINSERV, TAIWAN_FINSERV). Forwarded to the ad set.
    #[serde(
        rename = "regionalRegulatedCategories",
        skip_serializing_if = "Option::is_none"
    )]
    pub regional_regulated_categories: Option<Vec<String>>,
    /// Meta only. Beneficiary/payer entity IDs required alongside regionalRegulatedCategories. Values are numeric IDs from the advertiser's Meta verification/authorization setup. Keys depend on the declared category: BRAZIL_REGULATION and THAILAND_UNIVERSAL use universal_beneficiary / universal_payer; SINGAPORE_UNIVERSAL uses singapore_universal_beneficiary / singapore_universal_payer; TAIWAN_UNIVERSAL uses taiwan_universal_beneficiary / taiwan_universal_payer; TAIWAN_FINSERV uses taiwan_finserv_beneficiary / taiwan_finserv_payer; AUSTRALIA_FINSERV uses australia_finserv_beneficiary / australia_finserv_payer; INDIA_FINSERV uses india_finserv_beneficiary / india_finserv_payer. Both beneficiary and payer must be included. If omitted and the advertiser has set defaults in Meta Ads Manager advertising settings, Meta auto-fills them.
    #[serde(
        rename = "regionalRegulationIdentities",
        skip_serializing_if = "Option::is_none"
    )]
    pub regional_regulation_identities: Option<std::collections::HashMap<String, i32>>,
    /// E.164 number the CALL_NOW CTA dials (e.g. +34600111222).
    #[serde(rename = "phoneNumber")]
    pub phone_number: String,
    /// Website shown as the creative's link. Required: Meta rejects tel: as link_data.link; the phone number rides only the CTA.
    #[serde(rename = "linkUrl")]
    pub link_url: String,
}

impl CreateCallAdRequest {
    pub fn new(
        account_id: String,
        ad_account_id: String,
        name: String,
        phone_number: String,
        link_url: String,
    ) -> CreateCallAdRequest {
        CreateCallAdRequest {
            creative_features: None,
            tracking: None,
            account_id,
            ad_account_id,
            name,
            campaign_name: None,
            ad_set_name: None,
            platform_post_id: None,
            existing_post_id: None,
            object_story_id: None,
            page_id: None,
            whatsapp_phone_number: None,
            headline: None,
            body: None,
            image_url: None,
            video: None,
            welcome_message: None,
            creatives: None,
            ad_set_id: None,
            budget_amount: None,
            budget_type: None,
            currency: None,
            end_date: None,
            countries: None,
            cities: None,
            regions: None,
            zips: None,
            metros: None,
            country_groups: None,
            custom_locations: None,
            age_min: None,
            age_max: None,
            interests: None,
            audience_id: None,
            placements: None,
            advantage_audience: None,
            objective: None,
            status: None,
            campaign_status: None,
            bid_strategy: None,
            bid_amount: None,
            roas_average_floor: None,
            dsa_beneficiary: None,
            dsa_payor: None,
            regional_regulated_categories: None,
            regional_regulation_identities: None,
            phone_number,
            link_url,
        }
    }
}
/// Meta enhancement settings for single or attached ads, and defaults for creatives[]. An item replaces the entire map, including with an empty object.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum CreativeFeatures {
    #[serde(rename = "OPT_IN")]
    OptIn,
    #[serde(rename = "OPT_OUT")]
    OptOut,
}

impl Default for CreativeFeatures {
    fn default() -> CreativeFeatures {
        Self::OptIn
    }
}
/// Required unless `adSetId` is set.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum BudgetType {
    #[serde(rename = "daily")]
    Daily,
    #[serde(rename = "lifetime")]
    Lifetime,
}

impl Default for BudgetType {
    fn default() -> BudgetType {
        Self::Daily
    }
}
/// Meta only. Continents and trade blocs (`geo_locations.country_groups`), for targeting a whole region without listing its countries. Combines with `countries` rather than replacing it, and is also accepted under `excludedLocations`. Discoverable via `GET /v1/ads/targeting/search?dimension=geo&geoType=country_group`.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum CountryGroups {
    #[serde(rename = "africa")]
    Africa,
    #[serde(rename = "asia")]
    Asia,
    #[serde(rename = "europe")]
    Europe,
    #[serde(rename = "north_america")]
    NorthAmerica,
    #[serde(rename = "south_america")]
    SouthAmerica,
    #[serde(rename = "oceania")]
    Oceania,
    #[serde(rename = "central_america")]
    CentralAmerica,
    #[serde(rename = "caribbean")]
    Caribbean,
    #[serde(rename = "eea")]
    Eea,
    #[serde(rename = "euro_area")]
    EuroArea,
    #[serde(rename = "nafta")]
    Nafta,
    #[serde(rename = "mercosur")]
    Mercosur,
    #[serde(rename = "afta")]
    Afta,
    #[serde(rename = "apec")]
    Apec,
    #[serde(rename = "gcc")]
    Gcc,
    #[serde(rename = "cisfta")]
    Cisfta,
    #[serde(rename = "emerging_markets")]
    EmergingMarkets,
    #[serde(rename = "itunes_app_store")]
    ItunesAppStore,
    #[serde(rename = "android_free_store")]
    AndroidFreeStore,
    #[serde(rename = "android_paid_store")]
    AndroidPaidStore,
}

impl Default for CountryGroups {
    fn default() -> CountryGroups {
        Self::Africa
    }
}
/// Meta's Advantage+ audience expansion. `0` (default) keeps targeting strict; `1` lets Meta expand beyond the supplied targeting when its delivery system finds better matches. Always sent on CREATE (Meta requires it).
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum AdvantageAudience {
    #[serde(rename = "0")]
    Variant0,
    #[serde(rename = "1")]
    Variant1,
}

impl Default for AdvantageAudience {
    fn default() -> AdvantageAudience {
        Self::Variant0
    }
}
/// Defaults to `OUTCOME_ENGAGEMENT`. `OUTCOME_SALES` and `OUTCOME_LEADS` require additional account configuration (Dataset linked to the WABA for sales) and may be rejected by Meta if missing.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Objective {
    #[serde(rename = "OUTCOME_ENGAGEMENT")]
    OutcomeEngagement,
    #[serde(rename = "OUTCOME_SALES")]
    OutcomeSales,
    #[serde(rename = "OUTCOME_LEADS")]
    OutcomeLeads,
}

impl Default for Objective {
    fn default() -> Objective {
        Self::OutcomeEngagement
    }
}
/// Defaults to `ACTIVE`. `PAUSED` pauses only the top-most object this call creates: the new campaign (ad set and ads switched on), or, with `adSetId`, the new ads themselves.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Status {
    #[serde(rename = "ACTIVE")]
    Active,
    #[serde(rename = "PAUSED")]
    Paused,
}

impl Default for Status {
    fn default() -> Status {
        Self::Active
    }
}
/// Campaign-level status, same semantics as `POST /v1/ads/create`. Defaults to `status`. `PAUSED` holds the new campaign off while the ad set and ads switch on (one resume call brings the whole hierarchy live); `ACTIVE` with `status: PAUSED` switches the campaign on and pauses the new ad set instead. Only meaningful when a new campaign is being created; rejected with a 400 alongside `adSetId` (the attach shape reuses an existing campaign).
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum CampaignStatus {
    #[serde(rename = "ACTIVE")]
    Active,
    #[serde(rename = "PAUSED")]
    Paused,
}

impl Default for CampaignStatus {
    fn default() -> CampaignStatus {
        Self::Active
    }
}
/// Meta bid strategy applied to the shared ad set. Defaults to `LOWEST_COST_WITHOUT_CAP` (auto-bid) when omitted. `LOWEST_COST_WITH_BID_CAP` and `COST_CAP` require `bidAmount`. `LOWEST_COST_WITH_MIN_ROAS` requires `roasAverageFloor`. CTWA's `optimization_goal` is fixed to `CONVERSATIONS`, but the bid strategy is independent.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum BidStrategy {
    #[serde(rename = "LOWEST_COST_WITHOUT_CAP")]
    LowestCostWithoutCap,
    #[serde(rename = "LOWEST_COST_WITH_BID_CAP")]
    LowestCostWithBidCap,
    #[serde(rename = "COST_CAP")]
    CostCap,
    #[serde(rename = "LOWEST_COST_WITH_MIN_ROAS")]
    LowestCostWithMinRoas,
}

impl Default for BidStrategy {
    fn default() -> BidStrategy {
        Self::LowestCostWithoutCap
    }
}