using System.Text.Json.Serialization; namespace TikTokApi.Models; #region Campaign Payloads /// /// Create a TikTok campaign. /// TikTok hierarchy: Campaign → Ad Group → Ad (same as Google, unlike Meta's Ad Set). /// Campaign sets the objective and budget type. /// public sealed class CreateCampaignPayload { public string Name { get; set; } = string.Empty; public TikTokObjective Objective { get; set; } = TikTokObjective.Traffic; /// /// Budget mode. TikTok supports BUDGET_MODE_DAY and BUDGET_MODE_TOTAL at campaign level. /// public TikTokBudgetMode BudgetMode { get; set; } = TikTokBudgetMode.Day; /// /// Budget amount in account currency (float, e.g., 50.00). /// Minimum varies by country (typically $50/day for campaign-level budget). /// Null = no campaign budget (budget set at ad group level). /// public decimal? Budget { get; set; } /// /// Special industry categories: HOUSING, CREDIT, EMPLOYMENT. /// Empty = none (most campaigns). /// public List SpecialIndustries { get; set; } = new(); public TikTokCampaignStatus Status { get; set; } = TikTokCampaignStatus.Disable; } public sealed class GetCampaignPayload { public string CampaignId { get; set; } = string.Empty; } public sealed class UpdateCampaignPayload { public string CampaignId { get; set; } = string.Empty; public string? Name { get; set; } public TikTokCampaignStatus? Status { get; set; } public decimal? Budget { get; set; } } public sealed class ListCampaignsPayload { /// /// Filter by status. Null = return all. /// TikTok supports filtering by multiple statuses. /// public TikTokCampaignStatus? StatusFilter { get; set; } public int PageSize { get; set; } = 50; public int Page { get; set; } = 1; } #endregion #region Ad Group Payloads /// /// Create a TikTok Ad Group (equivalent to Google Ad Group / Meta Ad Set). /// Ad Groups define targeting, budget, schedule, placement, and bid strategy. /// public sealed class CreateAdGroupPayload { public string CampaignId { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; /// Budget amount in account currency (float). public decimal Budget { get; set; } public TikTokBudgetMode BudgetMode { get; set; } = TikTokBudgetMode.Day; /// Schedule start time in UTC (ISO 8601 / "yyyy-MM-dd HH:mm:ss"). public string? ScheduleStartTime { get; set; } /// Schedule end time in UTC. Null = no end date. public string? ScheduleEndTime { get; set; } public TikTokOptimizationGoal OptimizationGoal { get; set; } = TikTokOptimizationGoal.Click; public TikTokBillingEvent BillingEvent { get; set; } = TikTokBillingEvent.CPC; /// Bid amount in account currency. Required for non-auto-bid strategies. public decimal? BidPrice { get; set; } /// /// Placement: list of placements. Default = automatic (PLACEMENT_TYPE_AUTOMATIC). /// Options: PLACEMENT_TIKTOK, PLACEMENT_PANGLE, PLACEMENT_GLOBALAPP_BUNDLE /// public List Placements { get; set; } = new(); /// Target location codes (country/region codes). public List LocationIds { get; set; } = new(); public TikTokCampaignStatus Status { get; set; } = TikTokCampaignStatus.Disable; } #endregion #region Ad Account (Advertiser) Payloads /// /// Create a new advertiser account under USIM's Business Center. /// Endpoint: POST /bc/advertiser/create /// Requires BC admin access. /// public sealed class CreateAdvertiserPayload { /// Display name for the new advertiser account. public string Name { get; set; } = string.Empty; /// Currency code (e.g. "USD"). ISO 4217. public string Currency { get; set; } = "USD"; /// /// Timezone string. TikTok uses Olson/IANA format. /// e.g., "America/Los_Angeles", "UTC", "Europe/London" /// public string Timezone { get; set; } = "America/Los_Angeles"; /// Advertiser's company name. public string Company { get; set; } = string.Empty; /// Industry ID. Use /tool/industry/ endpoint to get valid IDs. public string? IndustryId { get; set; } /// Advertiser's contact email. public string? ContactEmail { get; set; } /// Advertiser's contact phone number. public string? ContactPhone { get; set; } } /// /// List advertiser accounts under the Business Center. /// Endpoint: GET /bc/advertiser/get /// public sealed class ListAdvertisersPayload { public int PageSize { get; set; } = 50; public int Page { get; set; } = 1; } #endregion #region Insights / Reporting Payloads /// /// Retrieve campaign/ad group/ad performance metrics. /// TikTok Reporting API: POST /report/integrated/get/ /// public sealed class ReportPayload { /// /// Report type: BASIC, AUDIENCE, PLAYABLE_MATERIAL, CATALOG /// public string ReportType { get; set; } = "BASIC"; /// /// Data level: AUCTION_CAMPAIGN, AUCTION_ADGROUP, AUCTION_AD /// public string DataLevel { get; set; } = "AUCTION_CAMPAIGN"; /// /// Dimensions to group by (e.g., ["campaign_id", "stat_time_day"]). /// public List Dimensions { get; set; } = new() { "campaign_id", "stat_time_day" }; /// /// Metrics to query (e.g., ["spend", "impressions", "clicks", "cpc", "ctr"]). /// public List Metrics { get; set; } = new() { "spend", "impressions", "clicks", "cpc", "ctr", "cpm" }; /// Start date in format "YYYY-MM-DD". public string? StartDate { get; set; } /// End date in format "YYYY-MM-DD". public string? EndDate { get; set; } /// Use lifetime stats instead of date range. public bool Lifetime { get; set; } = false; /// /// Filters (e.g., [{"field_name":"campaign_ids","filter_type":"IN","filter_value":"[\"123\"]"}]). /// public List? Filters { get; set; } public int PageSize { get; set; } = 50; public int Page { get; set; } = 1; } public sealed class ReportFilter { public string FieldName { get; set; } = string.Empty; public string FilterType { get; set; } = "IN"; public string FilterValue { get; set; } = string.Empty; } #endregion #region Fund Management Payloads /// /// Transfer funds to/from an advertiser account in the Business Center. /// Endpoint: POST /bc/transfer/ /// This is a unique TikTok feature — direct fund management via API. /// public sealed class TransferFundsPayload { /// Target advertiser account ID. public string AdvertiserId { get; set; } = string.Empty; /// Transfer type: "RECHARGE" (add funds) or "DEDUCT" (remove funds). public string TransferType { get; set; } = "RECHARGE"; /// Amount to transfer in account currency. public decimal Amount { get; set; } } #endregion #region Enums /// /// TikTok campaign objectives. /// See: https://business-api.tiktok.com/portal/docs?id=1739381516454913 /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum TikTokObjective { /// REACH - Maximize ad reach Reach = 0, /// TRAFFIC - Drive traffic to website/app Traffic = 1, /// VIDEO_VIEWS - Maximize video views VideoViews = 2, /// LEAD_GENERATION - Collect leads via instant forms LeadGeneration = 3, /// COMMUNITY_INTERACTION - Grow followers and profile visits CommunityInteraction = 4, /// APP_PROMOTION - Drive app installs/re-engagement AppPromotion = 5, /// WEB_CONVERSIONS - Drive website conversions WebConversions = 6, /// PRODUCT_SALES - Drive catalog/shop sales ProductSales = 7 } /// /// TikTok campaign/ad group status values. /// TikTok uses ENABLE/DISABLE rather than ACTIVE/PAUSED. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum TikTokCampaignStatus { /// ENABLE - Running/active Enable = 0, /// DISABLE - Paused Disable = 1, /// DELETE - Soft-deleted Delete = 2 } /// /// TikTok budget modes. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum TikTokBudgetMode { /// BUDGET_MODE_DAY - Daily budget Day = 0, /// BUDGET_MODE_TOTAL - Lifetime/total budget Total = 1, /// BUDGET_MODE_INFINITE - No budget limit (budget at ad group level) Infinite = 2 } /// /// TikTok billing events for ad groups. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum TikTokBillingEvent { CPC = 0, CPM = 1, CPV = 2, OCPM = 3 } /// /// TikTok optimization goals for ad groups. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum TikTokOptimizationGoal { Click = 0, Impression = 1, Reach = 2, VideoView = 3, Landing_Page_View = 4, Lead_Generation = 5, Convert = 6, Install = 7, Value = 8 } #endregion