Prepare one TikTok create operation in new, append-campaign, or append-adgroup mode. Returns a confirm_token and a human-readable summary; **does NOT publish until campaigns_quick_create_confirm is called with the token**.
REQUIRED (always): advertiser_id (call assets_list_ad_accounts to discover), a saved template_id or exact template_name, plus exactly one creative source: tenant-owned creative.creative_id from creatives_list with readiness.create_eligible=true, ordered local creative.image_creative_ids for one carousel, or creative.{video_id | image_ids | tiktok_item_id}. A local creative_id is synced to the exact advertiser only after explicit confirmation. For Spark, pass the complete identity_id, identity_type, tiktok_item_id, and spark_receipt row from spark_ads_list_posts unchanged as creative; the server moves the identity fields into TikTok's native ad parameters and rejects any conflicting duplicate values. Set ad_params.ad_format to one of that row's supported_ad_formats values; the signed receipt rejects a video/carousel mismatch before approval.
TEMPLATE SETTINGS: read templates_get.effective_creation_defaults and let the server fill saved campaign/ad-group/ad settings. MCP new and append modes require a saved template; without a selector, preparation returns needs_input/template_required. The resolved campaign_params.objective_type (APP_PROMOTION / WEB_CONVERSIONS / VIDEO_VIEWS / LEAD_GENERATION), adgroup_params.{optimization_goal, billing_event, bid_type}, ad_params.ad_format (SINGLE_VIDEO / SINGLE_IMAGE / CAROUSEL_ADS) must form a supported recipe. WEB_CONVERSIONS also requires adgroup_params.pixel_id; APP_PROMOTION requires adgroup_params.app_id from assets_list_apps. APP RECIPES (Smart+): one app_id per campaign — dual Android+iOS means two prepares. iOS APP_IOS defaults campaign_type=IOS14_CAMPAIGN, campaign BUDGET_MODE_INFINITE (ABO), adgroup BUDGET_MODE_DYNAMIC_DAILY_BUDGET 50. Android APP_ANDROID defaults campaign_type=REGULAR_CAMPAIGN, campaign BUDGET_MODE_DYNAMIC_DAILY_BUDGET 50 (CBO), adgroup BUDGET_MODE_INFINITE. Both use placement AUTOMATIC (TikTok+Pangle+GAB), optimization_goal=IN_APP_EVENT, and deep_bid_type=AEO when optimization_event is set (SUBSCRIBE is the live reference event). Pass app_id and a create_eligible local creative. When the advertiser has exactly one BC_AUTH_TT identity (TikTok's FB-page analog), the server fills identity_id / identity_type / identity_authorized_bc_id. Do not rewrite IOS14_CAMPAIGN to REGULAR_CAMPAIGN. INSTALL_NOW is the default CTA when neither call_to_action nor call_to_action_id is set. Local READY_LOCAL images/videos from creatives_list with readiness.create_eligible=true are valid App ad sources via creative.creative_id — do not require a TikTok Material Center image_id first. A web landing_page_url is stripped on APP_PROMOTION unless a deeplink is also present. Regular ads that can deliver on TikTok also require ad_params.call_to_action or ad_params.call_to_action_id; for Spark Pull, LEARN_MORE is the documented minimum CTA example. REGULAR CAROUSEL: CAROUSEL_ADS is compatible only with TRAFFIC, WEB_CONVERSIONS, APP_PROMOTION, LEAD_GENERATION, PRODUCT_SALES, CATALOG_SALES, or REACH; correct the selected objective or ad_format explicitly, never auto-rewrite the objective. REGULAR LOCAL MEDIA: exact advertiser-linked CUSTOMIZED_USER is required for local video/image. AUTH_CODE is Spark-only on regular create: use an eligible Spark post and pass its signed receipt unchanged when available; a legacy receipt-less item incurs one bounded live provider verification before approval. TT_USER and BC_AUTH_TT are not regular-local choices and may be used only on a server-verified compatible Smart+ route.
REGULAR CAMPAIGN BUDGET: new regular campaigns default a missing campaign_params.budget_mode to BUDGET_MODE_INFINITE (non-CBO / ABO). Bounded DAY, DYNAMIC_DAILY_BUDGET, or TOTAL modes require a positive campaign budget, and dynamic daily mode requires budget_optimize_on=true (CBO). Meta-portable aliases campaign_params.budget_level=CBO|ABO|campaign|adgroup are accepted and rewritten to those native fields. Append modes reuse their existing campaign and do not apply this contract.
REGULAR AD-GROUP BUDGET/SCHEDULE: new and append-campaign modes require adgroup_params.budget_mode (BUDGET_MODE_DAY, BUDGET_MODE_DYNAMIC_DAILY_BUDGET, or BUDGET_MODE_TOTAL) plus a positive budget. Daily modes default a missing schedule to SCHEDULE_FROM_NOW; stale template start/end values are removed and the UTC start is stamped only at write time. BUDGET_MODE_TOTAL requires SCHEDULE_START_END with both UTC timestamps. Smart+ and append-adgroup do not use this new-ad-group contract.
WITH template_id or template_name (Meta-portable): pass just advertiser_id + template_name (or template_id) + creative — propose pulls campaign_params / adgroup_params / ad_params from the template (caller-set keys win), derives campaign_name/adgroup_name from template.campaign_naming / template.adgroup_naming, stamps ad_name as `{adgroup_name}-{utc}`, and reads is_smart_plus from template.campaign_params.is_smart_performance. The selected media determines the compatible image/video format; do not force SINGLE_VIDEO onto a local image from a video template. Smart+ APP_PROMOTION defaults call_to_action to INSTALL_NOW. Meta copy aliases title/headline→display_name, body/text/message→ad_text, and cta→call_to_action are accepted. App display_name defaults from the linked app name.
TEMPLATE/ROOT COMPATIBILITY: prefer the compact template selector plus creative shape above, with overrides in campaign_params / adgroup_params / ad_params and execution. adset_params is accepted as an adgroup_params alias; both maps are preserved for conflict validation. A templates_get row spread may supply id, name, and campaign_naming as selector echoes; other read-only row metadata is ignored. Supported root budget, counts, statuses, bid, schedule, Smart+ switches, copy, and identity fields are passed to the same normalizer as execution/native fields. Conflicting duplicates must be corrected before confirmation.
AUTO-FILLED FROM USER ASSETS: identity_authorized_bc_id (when identity_type=BC_AUTH_TT), promotion_type/app_type/package/app_download_url (for APP_PROMOTION when app_id is set), placements default to [PLACEMENT_TIKTOK] for PLACEMENT_TYPE_NORMAL, top-level targeting fields (location_ids, operating_systems, age_groups, …) fold into adgroup_params.targeting.
INITIAL STATUS: omit entity status fields such as campaign_params.status, adgroup_params.status, and ad_params.status; `status` is unsupported. Where a native field is needed for payload compatibility, use operation_status. Campaign, ad group, and ad statuses default to DISABLE; explicit ACTIVE/ENABLE is preserved in the approved plan. Smart+ adgroup/create does not accept operation_status. When a new Smart+ ad group is requested DISABLE, a separate durable post-create disable step must be acknowledged before ad creation. ENABLE requires no disable step.
SMART+ IMAGE MUSIC: SINGLE_IMAGE and CAROUSEL_ADS require a music_id because TikTok's image creative wire requires music. When music_info is omitted (or music_id is auto/random), the server selects one advertiser-available track from assets_list_music and revalidates that exact ID on the recorded create route. An explicit music_id still wins. Append-adgroup may inherit one unambiguous parent track. Preserve an explicit template track, including across advertisers, and verify that exact ID for the target; unavailable music requires another explicit selection, never silent replacement. If no usable track is available, use a video creative.
LOCAL IMAGE GROUPS: creative.image_creative_ids is an ordered list of 2..35 JPEG/PNG images for one native CAROUSEL_ADS creative, and the same field is accepted inside ad_params.creative_list[].creative_info for one carousel variant. Use only create_eligible image rows from the tenant library. SINGLE_IMAGE is a separate format; one image is not a native multi-card carousel. For TikTok Android App carousel ads, use CAROUSEL_ADS with music and the ordered image group. Do not split cards into separate creative_list entries or pass local IDs as provider image_ids. Inspect the prepared plan's final format and ordered members before confirmation. If the receipt reports creative_image_not_ready, wait the returned retry_after_seconds (10s), then prepare the same local IDs for a new approval; existing acknowledged image uploads are reused. creative_image_not_usable requires different eligible material. An uncertain upload must be reconciled, never automatically reuploaded or replayed.
META EXECUTION BLOCK: pass execution like Meta QuickCreate — execution.budget.level=campaign|adset (CBO/ABO), execution.budget.type=daily|lifetime, execution.budget.amount, execution.is_smart_plus / execution.advantage_plus / execution.is_smart_performance for Smart+, execution.statuses.{campaign,adset,ad} (ACTIVE/PAUSED -> ENABLE/DISABLE), execution.bid.{strategy,cap}, execution.start_time / execution.end_time, execution.start_mode (immediate or tomorrow = advertiser TZ next day 00:05 UTC wire), and legacy flat execution.budget_level / execution.budget_amount. execution.campaign_count and execution.adset_count expand into a bounded serial batch (product <= 20, append_mode=new only). creative_distribution=all_per_adset (default) keeps Smart+ multi-creative on one ad via ad_params.creative_list; one_per_adset expands Smart+ to one ad group per creative (not Meta ad objects).
OPTIONAL: creative_distribution (all_per_adset|one_per_adset), is_smart_plus (bool, default derived from template), execution (object), call_to_action_id (str — portfolio id, alternative to ad_params.call_to_action enum), campaign_params.budget_level (CBO/ABO).
APPEND MODES (TikTok-native): append_mode="append-campaign" with target_campaign_id creates one ad group + one ad under that exact campaign; omit campaign_params. append_mode="append-adgroup" with target_adgroup_id creates one ad under that exact ad group; omit campaign_params and adgroup_params. Existing APP_PROMOTION ad groups keep their app_id / promotion_type; pass only the new ad plus a create_eligible local creative_id, ordered image_creative_ids, or provider image_ids. The server verifies advertiser ownership, exact authorization route, parent status, hierarchy, and Smart+ compatibility before prepare and again before mutation. Do not use Meta append-adset naming, do not guess by name, and never supply both target IDs.
If required fields are missing, returns status="needs_input" with bounded rejected_paths and next_action — fix and re-call. Confirm tokens expire after 10 minutes. Successful proposals include a summary with `recipe` and `launch_readiness`, matching the dashboard's core readiness model. Smart+ is intentionally limited to locally verified recipes: APP_PROMOTION, WEB_CONVERSIONS, PRODUCT_SALES, and LEAD_GENERATION.
EXAMPLE (template path, Meta-portable name): campaigns_quick_create({"advertiser_id": "7563...", "template_name": "iOS14 AEO", "creative": {"creative_id": "<owned-ready-creative-id>"}})