late 0.0.1055

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.104.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>,
    /// Ad-level status. Defaults to `ACTIVE`. `PAUSED` skips activating the newly created ad(s) after Meta accepts them.
    #[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 `ACTIVE`. `PAUSED` holds activation at the campaign so it never spends before the advertiser reviews it, while the ad set and ad still switch on (one resume call brings the whole hierarchy live). 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
    }
}
/// Ad-level status. Defaults to `ACTIVE`. `PAUSED` skips activating the newly created ad(s) after Meta accepts them.
#[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 `ACTIVE`. `PAUSED` holds activation at the campaign so it never spends before the advertiser reviews it, while the ad set and ad still switch on (one resume call brings the whole hierarchy live). 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
    }
}