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