late 0.0.1048

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.99.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 BoostPostRequest {
    /// Meta Advantage+ creative enhancements. Map snake_case feature names to OPT_IN or OPT_OUT; Meta validates supported keys and unspecified features default to OPT_OUT. auto_promotion_tag is an Advantage+ enhancement, not the Ads Manager Promotion setting. The deprecated standard_enhancements bundle is rejected by Meta.
    #[serde(rename = "creativeFeatures", skip_serializing_if = "Option::is_none")]
    pub creative_features: Option<CreativeFeatures>,
    /// Zernio post ID (provide this or platformPostId)
    #[serde(rename = "postId", skip_serializing_if = "Option::is_none")]
    pub post_id: Option<String>,
    /// Platform post ID (alternative to postId). Meta: a Page post id (`<pageId>_<postId>` or the bare post id) or an Instagram media id. On a Meta Ads business-login connection (platform metaads) the id is resolved live: an Instagram media id is boosted as that media, running as the Instagram account that owns it.
    #[serde(rename = "platformPostId", skip_serializing_if = "Option::is_none")]
    pub platform_post_id: Option<String>,
    /// Zernio account id. Normally the connected posting account (facebook, instagram, tiktok, linkedin, pinterest, twitter) or a googleads account. TikTok: the TikTok Ads connection (platform tiktokads) is accepted too when the post brings its own authorization (sparkAuthCode or sparkPosts), so Spark ads need no organic TikTok account connected; such a call must use platformPostId, not postId.
    #[serde(rename = "accountId")]
    pub account_id: String,
    /// Platform ad account ID
    #[serde(rename = "adAccountId")]
    pub ad_account_id: String,
    #[serde(rename = "name")]
    pub name: String,
    /// Exact name for the campaign this boost provisions. Omitted keeps the default `<name> - Campaign`. Every platform: on LinkedIn it names the campaign group. Ignored on the Meta attach shape (`adSetId`), which creates no campaign.
    #[serde(rename = "campaignName", skip_serializing_if = "Option::is_none")]
    pub campaign_name: Option<String>,
    /// Exact name for the ad-group level this boost provisions. Omitted keeps the default `<name> - Ad Group`. Meta: ad set; TikTok, Pinterest, Google: ad group; X: line item; LinkedIn: the campaign under the campaign group. Ignored on the Meta attach shape.
    #[serde(rename = "adSetName", skip_serializing_if = "Option::is_none")]
    pub ad_set_name: Option<String>,
    /// Available goals vary by platform. Meta (Facebook/Instagram) and TikTok support all 7. LinkedIn supports all except app_promotion. X supports engagement, traffic, awareness, video_views, app_promotion. Pinterest and Google Ads support only engagement, traffic, awareness, video_views.
    #[serde(rename = "goal")]
    pub goal: Goal,
    /// Meta, or TikTok with `smartPlus: true`. Attach the boosted post to this existing ad set instead of creating a campaign. On TikTok the id is an existing Smart+ ad group: the post is added as one more Spark ad in it (up to 30 per ad group), under the identity its `sparkAuthCode` creates; goal and budget are inherited from the Smart+ campaign; a regular ad group is rejected with a 400. Meta: The ad set then owns budget, schedule and targeting; sending those too is a 400.
    #[serde(rename = "adSetId", skip_serializing_if = "Option::is_none")]
    pub ad_set_id: Option<String>,
    /// TikTok only. Create the ad group and the Spark ad under this existing TikTok campaign instead of creating a new campaign. The campaign keeps its own status and objective (the objective must fit `goal`). Cannot be combined with adSetId or smartPlus. On Meta use POST /v1/ads/create with existingCampaignId.
    #[serde(rename = "existingCampaignId", skip_serializing_if = "Option::is_none")]
    pub existing_campaign_id: Option<String>,
    /// TikTok only. The identity the ad runs as (the profile shown on the ad), from GET /v1/ads/tiktok-identities. Default: the connected TikTok account's own identity. Must be authorized on the advertiser or the call fails naming the available ones.
    #[serde(rename = "identityId", skip_serializing_if = "Option::is_none")]
    pub identity_id: Option<String>,
    /// TikTok only. Type of identityId; resolved from the advertiser's identity list when omitted.
    #[serde(rename = "identityType", skip_serializing_if = "Option::is_none")]
    pub identity_type: Option<IdentityType>,
    /// Budget in whole currency units, the same flat field as POST /v1/ads/create. Required unless adSetId is set. Minimum varies: TikTok=$20, Pinterest=$5, others=$1
    #[serde(rename = "budgetAmount", skip_serializing_if = "Option::is_none")]
    pub budget_amount: Option<f64>,
    /// Goes together with budgetAmount. lifetime requires schedule.endDate.
    #[serde(rename = "budgetType", skip_serializing_if = "Option::is_none")]
    pub budget_type: Option<BudgetType>,
    #[serde(rename = "budget", skip_serializing_if = "Option::is_none")]
    pub budget: Option<Box<models::BoostPostRequestBudget>>,
    /// Meta only. Instagram identity the ad runs AS (creative.instagram_user_id), overriding the account linked to the Page. Live-verified against a Page-post creative.
    #[serde(rename = "instagramAccountId", skip_serializing_if = "Option::is_none")]
    pub instagram_account_id: Option<String>,
    /// Meta only. Ad-set destination_type: where the click LANDS, as opposed to instagramAccountId which is who the ad runs as. Independent of plain link CTAs and their goal. A messaging callToAction selects its destination automatically; an explicit destinationType must then match. Lead ads use ON_AD.
    #[serde(rename = "destinationType", skip_serializing_if = "Option::is_none")]
    pub destination_type: Option<DestinationType>,
    /// Meta WhatsApp only. E.164 number already paired with the Page. Omit to use the default pairing. Requires WHATSAPP_MESSAGE callToAction. Stored as creative.whatsappPhoneNumber on the ad.
    #[serde(
        rename = "whatsappPhoneNumber",
        skip_serializing_if = "Option::is_none"
    )]
    pub whatsapp_phone_number: Option<String>,
    /// ISO 4217 currency code matching the ad account's currency. Meta only. 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>,
    /// 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. Same field as on POST /v1/ads/create.
    #[serde(rename = "startDate", skip_serializing_if = "Option::is_none")]
    pub start_date: Option<String>,
    /// Ad-set end time (ISO 8601), mapped to the ad set's `end_time`. Required for lifetime budgets. Same field as on POST /v1/ads/create.
    #[serde(rename = "endDate", skip_serializing_if = "Option::is_none")]
    pub end_date: Option<String>,
    #[serde(rename = "schedule", skip_serializing_if = "Option::is_none")]
    pub schedule: Option<Box<models::BoostPostRequestSchedule>>,
    #[serde(rename = "targeting", skip_serializing_if = "Option::is_none")]
    pub targeting: Option<Box<models::BoostPostRequestTargeting>>,
    /// Google only (400 elsewhere). Written on the campaign the boost creates.
    #[serde(
        rename = "locationTargetingType",
        skip_serializing_if = "Option::is_none"
    )]
    pub location_targeting_type: Option<models::GoogleLocationTargetingType>,
    /// Meta only. A Meta-native targeting spec (e.g. `{ \"geo_locations\": { \"cities\": [{ \"key\": \"...\", \"radius\": 15, \"distance_unit\": \"kilometer\" }] } }`). Sent alone it is forwarded unchanged. Use for advanced fields the structured object does not expose (flexible_spec, excluded audiences, business places, user_os, wireless_carrier).  Can be combined with `targeting`: rawTargeting is the BASE layer and the built camelCase spec is merged on top, key by key (camelCase wins on collision). The merge goes one level deep inside `geo_locations` and `excluded_geo_locations` (built sub-keys win; raw-only sub-keys such as `location_types` survive). Array values (`flexible_spec`, ...) are replaced as a whole key, never element-merged.  When `rawTargeting` is present the `advantage_audience: 0` default that Zernio normally applies is no longer emitted, so it cannot clobber a `targeting_automation` sent in the raw spec. Meta requires `targeting_automation` on ad set creation, so include it in the raw spec, or send `targeting.advantage_audience` (0 or 1), which is merged over raw as `targeting_automation`.
    #[serde(rename = "rawTargeting", skip_serializing_if = "Option::is_none")]
    pub raw_targeting: Option<std::collections::HashMap<String, serde_json::Value>>,
    /// Deprecated: send it inside `platformSpecificData` instead (Meta today; TikTok's nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400.  Meta bid strategy applied to the ad set. On TikTok, mapped to `bid_type` / `bid_price` / `deep_bid_type` automatically.
    #[serde(rename = "bidStrategy", skip_serializing_if = "Option::is_none")]
    pub bid_strategy: Option<models::BidStrategy>,
    /// Deprecated: send it inside `platformSpecificData` instead (Meta today; TikTok's nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400.  Bid cap in WHOLE currency units (USD: 5 = $5.00; JPY: 100 = ¥100). Required when `bidStrategy` is `LOWEST_COST_WITH_BID_CAP` or `COST_CAP`. Backward-compat: providing `bidAmount` without `bidStrategy` is treated as `LOWEST_COST_WITH_BID_CAP`.
    #[serde(rename = "bidAmount", skip_serializing_if = "Option::is_none")]
    pub bid_amount: Option<f64>,
    /// Deprecated: send it inside `platformSpecificData` instead (Meta today; TikTok's nested shape is planned). The flat field keeps working during the deprecation window; sending both shapes returns a 400.  Minimum ROAS as a decimal multiplier (e.g. 2.0 = 2.0x ROAS). Required when `bidStrategy` is `LOWEST_COST_WITH_MIN_ROAS`. Sent to Meta as `bid_constraints.roas_average_floor` × 10000 (Meta uses fixed-point integers).
    #[serde(rename = "roasAverageFloor", skip_serializing_if = "Option::is_none")]
    pub roas_average_floor: Option<f64>,
    #[serde(
        rename = "platformSpecificData",
        skip_serializing_if = "Option::is_none"
    )]
    pub platform_specific_data: Option<Box<models::BoostPostRequestPlatformSpecificData>>,
    #[serde(rename = "tracking", skip_serializing_if = "Option::is_none")]
    pub tracking: Option<Box<models::BoostPostRequestTracking>>,
    /// Meta only. Required for housing, employment, credit, or political ads.
    #[serde(
        rename = "specialAdCategories",
        skip_serializing_if = "Option::is_none"
    )]
    pub special_ad_categories: Option<Vec<SpecialAdCategories>>,
    /// Meta (metaads) only. 2-letter ISO country codes the special ad category applies to. Requires specialAdCategories to be set (400 otherwise).
    #[serde(
        rename = "specialAdCategoryCountry",
        skip_serializing_if = "Option::is_none"
    )]
    pub special_ad_category_country: Option<Vec<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 for regionalRegulatedCategories. Values are numeric IDs from Meta verification. Keys vary by category (e.g. universal_beneficiary / universal_payer for BRAZIL_REGULATION and THAILAND_UNIVERSAL). If omitted, Meta uses Ads Manager defaults when configured.
    #[serde(
        rename = "regionalRegulationIdentities",
        skip_serializing_if = "Option::is_none"
    )]
    pub regional_regulation_identities: Option<std::collections::HashMap<String, i32>>,
    /// Website URL for non-messaging CTA buttons. Send it with `callToAction`. Omit for messaging boosts.  **Meta**: adds a top-level `call_to_action` to the post-reference creative. This is what gives a `traffic` boost a clickable destination without replacing the creative and losing the post's social proof. Ignored when `leadGenFormId` is set, which supplies its own destination. Live-verified against a Page-post creative.  **TikTok**: maps to `landing_page_url` on the Spark Ad creative (`AdcreateCreatives.landing_page_url`); Spark Ads have no clickable destination without it.  Ignored on LinkedIn / Pinterest / X / Google, which infer the destination from the boosted post.
    #[serde(rename = "linkUrl", skip_serializing_if = "Option::is_none")]
    pub link_url: Option<String>,
    /// CTA button label. Non-messaging CTAs require `linkUrl`. WHATSAPP_MESSAGE, MESSAGE_PAGE, and INSTAGRAM_MESSAGE do not require a URL and reject linkUrl.  **Meta**: the CTA enum of POST /v1/ads/create plus `VIEW_INSTAGRAM_PROFILE`, `WHATSAPP_MESSAGE`, `MESSAGE_PAGE`, and `INSTAGRAM_MESSAGE`. VIEW_INSTAGRAM_PROFILE requires linkUrl; the messaging CTAs select their destination automatically.  **TikTok**: pass-through to `call_to_action` on the Spark Ad creative; the platform validates the value. See TikTok's \"Enumeration - Call-to-Action\".
    #[serde(rename = "callToAction", skip_serializing_if = "Option::is_none")]
    pub call_to_action: Option<String>,
    /// TikTok-only. Spark Code (creator's `auth_code`) authorizing cross-creator Spark Ads: the advertiser can boost a video owned by a DIFFERENT TikTok account. Without this, boosts are limited to videos owned by the same account running the ads (same-BC creators only). The creator generates the code in their TikTok app's Promote settings and shares it with the advertiser. Maps to `auth_code` on the creative entry of /v2/ad/create/.
    #[serde(rename = "sparkAuthCode", skip_serializing_if = "Option::is_none")]
    pub spark_auth_code: Option<String>,
    /// TikTok only. Run the Spark post in a Smart+ campaign (goal `conversions` = Smart+ Web Conversions, `lead_generation` = Smart+ Lead Generation) instead of a regular campaign. Requires `sparkAuthCode` (the Smart+ ad runs the post under the identity that redeeming its Spark code creates; a Business Center-owned post is not accepted there) and `promotedObject.pixelId` + `customEventType`. `app_promotion` is not available on a Spark post. Rejected with a 400 on other platforms. A Smart+ Spark ad uses a dynamic CTA portfolio, sent as ad_configuration.call_to_action_id (TikTok does not accept a named call to action there): Zernio creates one per ad account and reuses it, and `callToAction` is rejected with a 400 on this path.
    #[serde(rename = "smartPlus", skip_serializing_if = "Option::is_none")]
    pub smart_plus: Option<bool>,
    /// TikTok Smart+ only (requires `smartPlus: true`). Several Spark posts as creatives of ONE Smart+ ad, each with its own post code (TikTok allows 1-50 per ad; posts from different creators mix). Replaces `platformPostId` + `sparkAuthCode`. Without `adSetId` it creates campaign + ad group + one ad carrying all of them; with `adSetId` it creates one new ad with all of them in that ad group. Rejected with a 400 on other platforms.
    #[serde(rename = "sparkPosts", skip_serializing_if = "Option::is_none")]
    pub spark_posts: Option<Vec<models::BoostPostRequestSparkPostsInner>>,
    /// TikTok Smart+ Web Conversions only (requires `smartPlus: true`, goal `conversions`). Promo codes or offers TikTok highlights on the ad (Ads Manager's \"Add promo code or offer\"). A promo code needs shoppers to enter it at checkout; an entry without `promoCode` is an offer applied automatically. Rejected with a 400 on other platforms and on Lead Generation campaigns.
    #[serde(rename = "promoCodes", skip_serializing_if = "Option::is_none")]
    pub promo_codes: Option<Vec<models::BoostPostRequestPromoCodesInner>>,
    #[serde(rename = "promotedObject", skip_serializing_if = "Option::is_none")]
    pub promoted_object: Option<Box<models::BoostPostRequestPromotedObject>>,
    /// 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>,
    /// Lead Gen form ID to attach to the boosted ad's creative. REQUIRED when `goal` is `lead_generation`. On Meta this is the leadgen_forms ID (create one via POST /v1/ads/lead-forms). On LinkedIn this is the adForm ID (create one via POST /v1/ads/lead-forms with a LinkedIn account); the creative's `leadgenCallToAction.destination` is set to `urn:li:adForm:{id}`. Ignored for other goals.
    #[serde(rename = "leadGenFormId", skip_serializing_if = "Option::is_none")]
    pub lead_gen_form_id: Option<String>,
    /// Meta, TikTok, LinkedIn, and Google. Publish state of the created entities. Omitted or ACTIVE publishes live (default); PAUSED creates them paused so you can review before they spend. On Meta a new campaign stays paused until explicitly activated; an attached ad is itself paused. On Google the pause is held on the campaign the boost creates (ad group and ad switched on), so PUT /v1/ads/campaigns/{campaignId}/status with `active` brings it live. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each).
    #[serde(rename = "status", skip_serializing_if = "Option::is_none")]
    pub status: Option<Status>,
    /// Meta only, same semantics as POST /v1/ads/create: campaign = Advantage campaign budget (CBO), the budget and bid strategy sit on the campaign and the ad set inherits them. Default adset. Not allowed with adSetId.
    #[serde(rename = "budgetLevel", skip_serializing_if = "Option::is_none")]
    pub budget_level: Option<BudgetLevel>,
    /// Meta only. Ad-set attribution windows, same shape as POST /v1/ads/create. Applied on OUTCOME_SALES, OUTCOME_LEADS and OUTCOME_APP_PROMOTION campaigns (conversions, lead_conversion, lead_generation, app_promotion); other objectives keep Meta's default. Not allowed with adSetId.
    #[serde(rename = "attributionSpec", skip_serializing_if = "Option::is_none")]
    pub attribution_spec: Option<Vec<models::BoostPostRequestAttributionSpecInner>>,
    /// Meta only. Extra primary-text options Meta rotates on the boosted post (asset_feed_spec.bodies with DEGREES_OF_FREEDOM); the post keeps its own text as one of the options. Works for Facebook posts and Instagram media. Under a conversions or traffic goal Meta also wants a website URL on the options, taken from `linkUrl` (send it with a `callToAction`); engagement boosts need none.
    #[serde(rename = "bodies", skip_serializing_if = "Option::is_none")]
    pub bodies: Option<Vec<String>>,
    /// Meta, or TikTok with `goal: video_views`. TikTok: ENGAGED_VIEW (6-second Focused View, the default) or ENGAGED_VIEW_FIFTEEN (15-second views), both billed per view (CPV); any other value is a 400. Meta: explicit ad-set `optimization_goal` override. When omitted, defaults to the value derived from `goal`. Messaging boosts always use CONVERSATIONS and reject another optimizationGoal. Otherwise the value must be compatible with the objective Meta derives from `goal`, not with the objective used by `POST /v1/ads/create` for the same `goal` name: boost maps `goal: \"engagement\"` to objective `OUTCOME_AWARENESS`, which accepts `REACH`, `IMPRESSIONS`, `AD_RECALL_LIFT`, or THRUPLAY-class values, and rejects `POST_ENGAGEMENT` (that value is only valid under `OUTCOME_ENGAGEMENT`, which create uses for the same goal name).
    #[serde(rename = "optimizationGoal", skip_serializing_if = "Option::is_none")]
    pub optimization_goal: Option<String>,
}

impl BoostPostRequest {
    pub fn new(
        account_id: String,
        ad_account_id: String,
        name: String,
        goal: Goal,
    ) -> BoostPostRequest {
        BoostPostRequest {
            creative_features: None,
            post_id: None,
            platform_post_id: None,
            account_id,
            ad_account_id,
            name,
            campaign_name: None,
            ad_set_name: None,
            goal,
            ad_set_id: None,
            existing_campaign_id: None,
            identity_id: None,
            identity_type: None,
            budget_amount: None,
            budget_type: None,
            budget: None,
            instagram_account_id: None,
            destination_type: None,
            whatsapp_phone_number: None,
            currency: None,
            start_date: None,
            end_date: None,
            schedule: None,
            targeting: None,
            location_targeting_type: None,
            raw_targeting: None,
            bid_strategy: None,
            bid_amount: None,
            roas_average_floor: None,
            platform_specific_data: None,
            tracking: None,
            special_ad_categories: None,
            special_ad_category_country: None,
            regional_regulated_categories: None,
            regional_regulation_identities: None,
            link_url: None,
            call_to_action: None,
            spark_auth_code: None,
            smart_plus: None,
            spark_posts: None,
            promo_codes: None,
            promoted_object: None,
            dsa_beneficiary: None,
            dsa_payor: None,
            lead_gen_form_id: None,
            status: None,
            budget_level: None,
            attribution_spec: None,
            bodies: None,
            optimization_goal: None,
        }
    }
}
/// Meta Advantage+ creative enhancements. Map snake_case feature names to OPT_IN or OPT_OUT; Meta validates supported keys and unspecified features default to OPT_OUT. auto_promotion_tag is an Advantage+ enhancement, not the Ads Manager Promotion setting. The deprecated standard_enhancements bundle is rejected by Meta.
#[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
    }
}
/// Available goals vary by platform. Meta (Facebook/Instagram) and TikTok support all 7. LinkedIn supports all except app_promotion. X supports engagement, traffic, awareness, video_views, app_promotion. Pinterest and Google Ads support only engagement, traffic, awareness, video_views.
#[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 = "conversions")]
    Conversions,
    #[serde(rename = "app_promotion")]
    AppPromotion,
}

impl Default for Goal {
    fn default() -> Goal {
        Self::Engagement
    }
}
/// TikTok only. Type of identityId; resolved from the advertiser's identity list when omitted.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum IdentityType {
    #[serde(rename = "TT_USER")]
    TtUser,
    #[serde(rename = "CUSTOMIZED_USER")]
    CustomizedUser,
    #[serde(rename = "BC_AUTH_TT")]
    BcAuthTt,
}

impl Default for IdentityType {
    fn default() -> IdentityType {
        Self::TtUser
    }
}
/// Goes together with budgetAmount. lifetime requires schedule.endDate.
#[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. Ad-set destination_type: where the click LANDS, as opposed to instagramAccountId which is who the ad runs as. Independent of plain link CTAs and their goal. A messaging callToAction selects its destination automatically; an explicit destinationType must then match. Lead ads use ON_AD.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum DestinationType {
    #[serde(rename = "INSTAGRAM_PROFILE")]
    InstagramProfile,
    #[serde(rename = "WEBSITE")]
    Website,
    #[serde(rename = "ON_AD")]
    OnAd,
    #[serde(rename = "MESSENGER")]
    Messenger,
    #[serde(rename = "WHATSAPP")]
    Whatsapp,
    #[serde(rename = "INSTAGRAM_DIRECT")]
    InstagramDirect,
}

impl Default for DestinationType {
    fn default() -> DestinationType {
        Self::InstagramProfile
    }
}
/// Meta only. Required for housing, employment, credit, or political ads.
#[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 = "FINANCIAL_PRODUCTS_SERVICES")]
    FinancialProductsServices,
    #[serde(rename = "ISSUES_ELECTIONS_POLITICS")]
    IssuesElectionsPolitics,
    #[serde(rename = "ONLINE_GAMBLING_AND_GAMING")]
    OnlineGamblingAndGaming,
}

impl Default for SpecialAdCategories {
    fn default() -> SpecialAdCategories {
        Self::Housing
    }
}
/// Meta, TikTok, LinkedIn, and Google. Publish state of the created entities. Omitted or ACTIVE publishes live (default); PAUSED creates them paused so you can review before they spend. On Meta a new campaign stays paused until explicitly activated; an attached ad is itself paused. On Google the pause is held on the campaign the boost creates (ad group and ad switched on), so PUT /v1/ads/campaigns/{campaignId}/status with `active` brings it live. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each).
#[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
    }
}
/// Meta only, same semantics as POST /v1/ads/create: campaign = Advantage campaign budget (CBO), the budget and bid strategy sit on the campaign and the ad set inherits them. Default adset. Not allowed with adSetId.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum BudgetLevel {
    #[serde(rename = "adset")]
    Adset,
    #[serde(rename = "campaign")]
    Campaign,
}

impl Default for BudgetLevel {
    fn default() -> BudgetLevel {
        Self::Adset
    }
}