/*
* 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.162.2
* 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 run as the media owner (resolved from the media on a Meta ads business-login connection, so no Instagram connection is needed). 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>,
/// Link description, independent of `headline` and `body` (Meta's `link_data.description`, `video_data.link_description` on video, and the shared description of a `placementAssets` feed). Meta shows it mainly on Facebook Feed placements, under the headline, when there is room; Instagram, Stories, Reels and Messenger placements do not display it. Also accepted per entry in `creatives[]`. Not allowed with an existing post creative.
#[serde(rename = "description", skip_serializing_if = "Option::is_none")]
pub description: 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`, `budgetLevel`, `startDate`, `endDate`, `objective`, `campaignStatus`, `existingCampaignId`, the special ad category fields and every targeting field except `ageMin`, `ageMax`, `placements` and `advantageAudience` 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>,
/// Create the new messaging ad set (and its ads) under this EXISTING Meta campaign instead of a new one, e.g. several audience ad sets under one campaign. The campaign's objective must be OUTCOME_ENGAGEMENT, OUTCOME_SALES or OUTCOME_LEADS (400 otherwise). If the campaign has a campaign budget, omit `budgetAmount` and `budgetType` (400 if sent); otherwise they are required and land on the new ad set. `objective`, `campaignName`, `campaignStatus`, `budgetLevel`, `specialAdCategories`, `specialAdCategoryCountry` and `adSetId` are rejected alongside it. To add ads to an existing ad set instead, use `adSetId`.
#[serde(rename = "existingCampaignId", skip_serializing_if = "Option::is_none")]
pub existing_campaign_id: Option<String>,
/// Where the budget lives. `adset` (default) puts it on the new ad set. `campaign` creates an Advantage campaign budget (CBO): the budget and bid strategy sit on the campaign and the ad set inherits them, same as POST /v1/ads/create. Not allowed with `adSetId` or `existingCampaignId`.
#[serde(rename = "budgetLevel", skip_serializing_if = "Option::is_none")]
pub budget_level: Option<BudgetLevel>,
/// 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 (the ad set owns it) or `existingCampaignId` names a campaign with a campaign budget.
#[serde(rename = "budgetAmount", skip_serializing_if = "Option::is_none")]
pub budget_amount: Option<f64>,
/// Required unless `adSetId` is set or `existingCampaignId` names a campaign with a campaign budget. `lifetime` requires `endDate`.
#[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>,
/// When the ad set starts delivering. ISO 8601 date or date-time. A value with an offset (`2027-01-15T10:00:00+01:00`, `...Z`) is used as is; one without an offset (`2027-01-15T10:00:00`) is read in the ad account's timezone, and a date-only value starts at 00:00 local. Defaults to now.
#[serde(rename = "startDate", skip_serializing_if = "Option::is_none")]
pub start_date: Option<String>,
/// ISO 8601 date or date-time, read like `startDate`; a date-only value ends at 23:59:59 local. 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>>,
/// Restrict the audience by gender (Meta `genders`). Stored on the ad and read back in `targeting.gender`.
#[serde(rename = "gender", skip_serializing_if = "Option::is_none")]
pub gender: Option<Gender>,
/// Audience languages (Meta `locales`). A bare ISO 639-1 code targets all regional variants (\"en\" = all English), a region-qualified code a specific one (\"en_GB\", \"pt_BR\"); unknown codes are rejected.
#[serde(rename = "languages", skip_serializing_if = "Option::is_none")]
pub languages: Option<Vec<String>>,
/// Meta place keys (from GET /v1/ads/targeting/search).
#[serde(rename = "places", skip_serializing_if = "Option::is_none")]
pub places: Option<Vec<models::CtwaAdRequestBodyPlacesInner>>,
/// Meta neighborhood keys (from GET /v1/ads/targeting/search).
#[serde(rename = "neighborhoods", skip_serializing_if = "Option::is_none")]
pub neighborhoods: Option<Vec<models::CtwaAdRequestBodyPlacesInner>>,
/// Geo to exclude, same shape as POST /v1/ads/create (countries, countryGroups, regions, cities, zips, places, neighborhoods, customLocations).
#[serde(rename = "excludedLocations", skip_serializing_if = "Option::is_none")]
pub excluded_locations: Option<std::collections::HashMap<String, serde_json::Value>>,
/// Meta behavior ids. Each dimension is its own flexible_spec entry: OR within, AND across.
#[serde(rename = "behaviors", skip_serializing_if = "Option::is_none")]
pub behaviors: Option<Vec<models::CreateStandaloneAdRequestBehaviorsInner>>,
#[serde(rename = "workPositions", skip_serializing_if = "Option::is_none")]
pub work_positions: Option<Vec<models::CreateStandaloneAdRequestBehaviorsInner>>,
#[serde(rename = "workEmployers", skip_serializing_if = "Option::is_none")]
pub work_employers: Option<Vec<models::CreateStandaloneAdRequestBehaviorsInner>>,
#[serde(rename = "workIndustries", skip_serializing_if = "Option::is_none")]
pub work_industries: Option<Vec<models::CreateStandaloneAdRequestBehaviorsInner>>,
/// Normalized household-income tier, same as POST /v1/ads/create. Incompatible with housing, employment and credit specialAdCategories.
#[serde(rename = "incomeTier", skip_serializing_if = "Option::is_none")]
pub income_tier: Option<IncomeTier>,
/// Meta `user_os`, e.g. [\"iOS_ver_14.0_and_above\"].
#[serde(rename = "userOs", skip_serializing_if = "Option::is_none")]
pub user_os: Option<Vec<String>>,
/// Meta `user_device`.
#[serde(rename = "userDevice", skip_serializing_if = "Option::is_none")]
pub user_device: Option<Vec<String>>,
/// Custom or lookalike audience ids to include.
#[serde(rename = "audienceInclude", skip_serializing_if = "Option::is_none")]
pub audience_include: Option<Vec<String>>,
/// Custom or lookalike audience ids to exclude.
#[serde(rename = "audienceExclude", skip_serializing_if = "Option::is_none")]
pub audience_exclude: Option<Vec<String>>,
/// ID of a saved_targeting audience (POST /v1/ads/audiences), expanded as the base targeting. Precedence: savedTargetingId, then `targeting`, then the flat fields.
#[serde(rename = "savedTargetingId", skip_serializing_if = "Option::is_none")]
pub saved_targeting_id: Option<String>,
/// Nested targeting object, same contract as POST /v1/ads/create and boost. Flat fields win per key.
#[serde(rename = "targeting", skip_serializing_if = "Option::is_none")]
pub targeting: Option<Box<models::TargetingSpec>>,
/// Meta targeting spec sent as the BASE layer of the ad set's `targeting`, exactly as POST /v1/ads/create does: use it for anything the flat fields cannot express, such as a layered `flexible_spec` (entries AND together, ids inside one entry OR). Flat fields you also send are layered on top and win per key. With rawTargeting present the US geo and `advantage_audience: 0` defaults are not injected, so include `targeting_automation` in it (or send `advantageAudience`), as Meta requires it on create.
#[serde(rename = "rawTargeting", skip_serializing_if = "Option::is_none")]
pub raw_targeting: Option<std::collections::HashMap<String, serde_json::Value>>,
/// Meta special ad categories on the new campaign.
#[serde(
rename = "specialAdCategories",
skip_serializing_if = "Option::is_none"
)]
pub special_ad_categories: Option<Vec<SpecialAdCategories>>,
/// Countries the special ad category applies to. Requires specialAdCategories.
#[serde(
rename = "specialAdCategoryCountry",
skip_serializing_if = "Option::is_none"
)]
pub special_ad_category_country: Option<Vec<String>>,
/// 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,
description: None,
image_url: None,
video: None,
welcome_message: None,
creatives: None,
ad_set_id: None,
existing_campaign_id: None,
budget_level: None,
budget_amount: None,
budget_type: None,
currency: None,
start_date: 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,
gender: None,
languages: None,
places: None,
neighborhoods: None,
excluded_locations: None,
behaviors: None,
work_positions: None,
work_employers: None,
work_industries: None,
income_tier: None,
user_os: None,
user_device: None,
audience_include: None,
audience_exclude: None,
saved_targeting_id: None,
targeting: None,
raw_targeting: None,
special_ad_categories: None,
special_ad_category_country: 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
}
}
/// Where the budget lives. `adset` (default) puts it on the new ad set. `campaign` creates an Advantage campaign budget (CBO): the budget and bid strategy sit on the campaign and the ad set inherits them, same as POST /v1/ads/create. Not allowed with `adSetId` or `existingCampaignId`.
#[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
}
}
/// Required unless `adSetId` is set or `existingCampaignId` names a campaign with a campaign budget. `lifetime` requires `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. 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
}
}
/// Restrict the audience by gender (Meta `genders`). Stored on the ad and read back in `targeting.gender`.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum Gender {
#[serde(rename = "all")]
All,
#[serde(rename = "male")]
Male,
#[serde(rename = "female")]
Female,
}
impl Default for Gender {
fn default() -> Gender {
Self::All
}
}
/// Normalized household-income tier, same as POST /v1/ads/create. Incompatible with housing, employment and credit specialAdCategories.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum IncomeTier {
#[serde(rename = "top_5")]
Top5,
#[serde(rename = "top_10")]
Top10,
#[serde(rename = "top_10_25")]
Top1025,
#[serde(rename = "top_25_50")]
Top2550,
}
impl Default for IncomeTier {
fn default() -> IncomeTier {
Self::Top5
}
}
/// Meta special ad categories on the new campaign.
#[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
}
}
/// 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
}
}