late 0.0.954

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).
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).
 *
 * The version of the OpenAPI document: 1.8.1
 * 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 CreateAdCampaignRequest {
    /// Zernio SocialAccount id (posting or ads variant); its platform decides where the campaign is created.
    #[serde(rename = "accountId")]
    pub account_id: String,
    /// Platform ad account id (Meta act_<n>, Google customer id, LinkedIn account id, ...).
    #[serde(rename = "adAccountId")]
    pub ad_account_id: String,
    #[serde(rename = "name")]
    pub name: String,
    /// Mapped to the ODAX objective (same mapping as POST /v1/ads/create).
    #[serde(rename = "goal")]
    pub goal: Goal,
    /// Meta app promotion only. Immutable campaign flag. Set true for iOS 14+ SKAdNetwork campaigns and supply promotedObject.applicationId plus promotedObject.objectStoreUrl. The campaign receives promotedObject only when this flag is true. Cannot be changed on an existing campaign.
    #[serde(
        rename = "isSkadnetworkAttribution",
        skip_serializing_if = "Option::is_none"
    )]
    pub is_skadnetwork_attribution: Option<bool>,
    #[serde(rename = "promotedObject", skip_serializing_if = "Option::is_none")]
    pub promoted_object: Option<Box<models::AdPromotedObject>>,
    /// Every platform buys at auction by default, so this only needs sending on Meta, and only to choose RESERVED. `AUCTION` is accepted on every platform and changes nothing. `RESERVED` (Reach & Frequency) is Meta-only and is rejected with a 400 elsewhere. SKAdNetwork app promotion requires AUCTION.
    #[serde(rename = "buyingType", skip_serializing_if = "Option::is_none")]
    pub buying_type: Option<BuyingType>,
    /// Meta only. Runs campaign validation without creating or persisting a campaign; Idempotency-Key storage is bypassed. Returns HTTP 200 with validateOnly true and status VALIDATED.
    #[serde(rename = "validateOnly", skip_serializing_if = "Option::is_none")]
    pub validate_only: Option<bool>,
    #[serde(
        rename = "specialAdCategories",
        skip_serializing_if = "Option::is_none"
    )]
    pub special_ad_categories: Option<Vec<SpecialAdCategories>>,
    /// Campaign-level (CBO) budget in WHOLE currency units (USD: 50 = $50.00), NOT cents. Meta's own Marketing API takes this same number in minor units, so it is an easy and expensive mix-up. Requires budgetType.
    #[serde(rename = "budgetAmount", skip_serializing_if = "Option::is_none")]
    pub budget_amount: Option<f64>,
    #[serde(rename = "budgetType", skip_serializing_if = "Option::is_none")]
    pub budget_type: Option<BudgetType>,
    #[serde(rename = "status", skip_serializing_if = "Option::is_none")]
    pub status: Option<Status>,
    /// Campaign bid strategy. Meta stores `bid_strategy` alongside the budget, so this REQUIRES `budgetAmount` + `budgetType` on the same request; sending it without a campaign budget is a 400. A campaign carrying a strategy without its `bid_amount` makes every ad set created under it fail with an error that names the ad set (code 100, subcode 1815857), so the bad state is rejected up front rather than accepted. To bid at ad-set level on Meta, set the strategy there instead. On Google: LOWEST_COST_WITHOUT_CAP = Maximize Conversions, COST_CAP + bidAmount = Target CPA, LOWEST_COST_WITH_MIN_ROAS + roasAverageFloor = Target ROAS, LOWEST_COST_WITH_BID_CAP + bidAmount = Maximize Clicks with a CPC ceiling; portfolioBidStrategyId attaches a portfolio strategy instead.
    #[serde(rename = "bidStrategy", skip_serializing_if = "Option::is_none")]
    pub bid_strategy: Option<BidStrategy>,
    /// Whole currency units (USD: 5 = $5.00). Required for LOWEST_COST_WITH_BID_CAP and COST_CAP; ignored otherwise. On Meta, validated here but NOT stored: the campaign object has no bid_amount field, only bid_strategy lives on it, and the amount takes effect once an ad set joins this campaign (existingCampaignId on POST /v1/ads/create) and supplies its own bidAmount there. On Google, stored directly on the campaign's bidding strategy.
    #[serde(rename = "bidAmount", skip_serializing_if = "Option::is_none")]
    pub bid_amount: Option<f64>,
    /// Decimal ROAS multiplier (2.0 = 2.0x). Required for LOWEST_COST_WITH_MIN_ROAS.
    #[serde(rename = "roasAverageFloor", skip_serializing_if = "Option::is_none")]
    pub roas_average_floor: Option<f64>,
    /// Google only. Attach an existing portfolio bid strategy (numeric id from GET /v1/ads/bid-strategies) to the new campaign instead of a standard one. Exclusive with bidStrategy.
    #[serde(
        rename = "portfolioBidStrategyId",
        skip_serializing_if = "Option::is_none"
    )]
    pub portfolio_bid_strategy_id: Option<String>,
}

impl CreateAdCampaignRequest {
    pub fn new(
        account_id: String,
        ad_account_id: String,
        name: String,
        goal: Goal,
    ) -> CreateAdCampaignRequest {
        CreateAdCampaignRequest {
            account_id,
            ad_account_id,
            name,
            goal,
            is_skadnetwork_attribution: None,
            promoted_object: None,
            buying_type: None,
            validate_only: None,
            special_ad_categories: None,
            budget_amount: None,
            budget_type: None,
            status: None,
            bid_strategy: None,
            bid_amount: None,
            roas_average_floor: None,
            portfolio_bid_strategy_id: None,
        }
    }
}
/// Mapped to the ODAX objective (same mapping as POST /v1/ads/create).
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Goal {
    #[serde(rename = "engagement")]
    Engagement,
    #[serde(rename = "traffic")]
    Traffic,
    #[serde(rename = "awareness")]
    Awareness,
    #[serde(rename = "video_views")]
    VideoViews,
    #[serde(rename = "lead_generation")]
    LeadGeneration,
    #[serde(rename = "lead_conversion")]
    LeadConversion,
    #[serde(rename = "job_applicants")]
    JobApplicants,
    #[serde(rename = "conversions")]
    Conversions,
    #[serde(rename = "app_promotion")]
    AppPromotion,
    #[serde(rename = "catalog_sales")]
    CatalogSales,
    #[serde(rename = "page_likes")]
    PageLikes,
}

impl Default for Goal {
    fn default() -> Goal {
        Self::Engagement
    }
}
/// Every platform buys at auction by default, so this only needs sending on Meta, and only to choose RESERVED. `AUCTION` is accepted on every platform and changes nothing. `RESERVED` (Reach & Frequency) is Meta-only and is rejected with a 400 elsewhere. SKAdNetwork app promotion requires AUCTION.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum BuyingType {
    #[serde(rename = "AUCTION")]
    Auction,
    #[serde(rename = "RESERVED")]
    Reserved,
}

impl Default for BuyingType {
    fn default() -> BuyingType {
        Self::Auction
    }
}
///
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum SpecialAdCategories {
    #[serde(rename = "HOUSING")]
    Housing,
    #[serde(rename = "EMPLOYMENT")]
    Employment,
    #[serde(rename = "CREDIT")]
    Credit,
    #[serde(rename = "ISSUES_ELECTIONS_POLITICS")]
    IssuesElectionsPolitics,
    #[serde(rename = "FINANCIAL_PRODUCTS_SERVICES")]
    FinancialProductsServices,
    #[serde(rename = "ONLINE_GAMBLING_AND_GAMING")]
    OnlineGamblingAndGaming,
}

impl Default for SpecialAdCategories {
    fn default() -> SpecialAdCategories {
        Self::Housing
    }
}
///
#[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
    }
}
///
#[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 bid strategy. Meta stores `bid_strategy` alongside the budget, so this REQUIRES `budgetAmount` + `budgetType` on the same request; sending it without a campaign budget is a 400. A campaign carrying a strategy without its `bid_amount` makes every ad set created under it fail with an error that names the ad set (code 100, subcode 1815857), so the bad state is rejected up front rather than accepted. To bid at ad-set level on Meta, set the strategy there instead. On Google: LOWEST_COST_WITHOUT_CAP = Maximize Conversions, COST_CAP + bidAmount = Target CPA, LOWEST_COST_WITH_MIN_ROAS + roasAverageFloor = Target ROAS, LOWEST_COST_WITH_BID_CAP + bidAmount = Maximize Clicks with a CPC ceiling; portfolioBidStrategyId attaches a portfolio strategy instead.
#[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
    }
}