add_meta_ad

Meta Ads Write

User wants to add another ad/creative variation to an EXISTING ad set

Endpoint

POST https://api.adspirer.ai/api/v1/tools/add_meta_ad/execute

Headers

Description

User wants to add another ad/creative variation to an EXISTING ad set. DO NOT USE to create a new campaign. For new campaigns: - Video campaign - `create_meta_video_campaign` - Image campaign - `create_meta_image_campaign` - Carousel campaign - `create_meta_carousel_campaign` Common scenarios: - A/B test ad copy: Different headlines, primary text, or CTAs for the same audience - A/B test creatives: Different images or videos for the same audience - Format testing within one audience: Image vs video ad in the same ad set - Dynamic Creative (DCO): Multiple images + text variations in one ad — Meta auto-optimizes KEY DISTINCTION — add_meta_ad vs add_meta_ad_set: - Same audience, different creative/copy - use THIS tool (add_meta_ad) - Different audience/targeting - use `add_meta_ad_set` instead (creates a new ad set) Ads in the same ad set SHARE: targeting, budget, schedule, pixel tracking. Each ad has its OWN: creative (image/video/carousel), headline, primary text, CTA, landing page. IMPORTANT: You need an ad_set_id from a previously created ad set. Use `list_meta_ad_sets` first if you don't have the ad_set_id. Supports all 3 ad types + Dynamic Creative: - `image`: Different image + copy variation - `video`: Different video + copy variation - `carousel`: Different card set + copy variation - **Dynamic Creative (DCO)**: Pass `image_urls` (2-10 images), `headlines` (up to 5), `primary_texts` (up to 5), `descriptions` (up to 5). Meta tests ALL combinations and optimizes delivery automatically. Dynamic Creative Optimization (DCO) workflow: 1. Create ad set with `is_dynamic_creative=true` via `add_meta_ad_set` 2. Call this tool with `image_urls` (list of 2-10 image URLs), plus optional `headlines`, `primary_texts`, `descriptions` arrays 3. Meta will test all image × headline × text combinations and optimize 4. DCO ad sets support only 1 ad — if the ad set already has is_dynamic_creative enabled, this tool auto-detects it Note: Cannot mix image_urls (DCO) with image_url (single image) or placement-specific images. Standard workflow: 1. Get ad_set_id from prior campaign creation or `list_meta_ad_sets` 2. Write variant ad copy (different headline/primary_text/image) 3. Call this tool with ad_set_id + new creative + copy

Request body

All tool arguments are wrapped in an arguments object.

FieldTypeDescription
ad_set_idstring required**REQUIRED.** The Meta Ad Set ID to add the ad to. If you don't have it, call `list_meta_ad_sets` first. Example: '120209876543210'.
ad_typestring required**REQUIRED.** Type of ad: 'image', 'video', or 'carousel'. Must match the creative source you're providing — image needs image_url/hash/bundle, video needs video_url/existing_video_id, carousel needs cards.
auto_copy_creativeboolean optionalWhen True and `existing_image_hash` (or carousel card image_hash) belongs to a DIFFERENT connected Meta account than `ad_account_id`, the image is automatically copied to the target account and the new hash is used in the ad. Default False = pre-validation blocks with an actionable error. ⚠️ **ASK THE USER FIRST.** Auto-copy creates a new image asset in the target Meta account. On accounts with many creatives (e.g. a library of seasonal images), running auto-copy can be wasteful and surprising. Only set this flag after the user explicitly confirms they want the asset copied. Does not apply to videos (`existing_video_id` mismatches still require manual handling). default: false
image_urlstring optionalImage URL (for image type)
existing_image_hashstring optionalExisting Meta image hash. For image ads, this is the image itself. For video ads, doubles as the video thumbnail (used when Meta's auto-generated thumbnail edge stays empty after upload, which happens for 10-30s on freshly uploaded videos).
asset_bundle_idstring optionalAsset bundle ID
story_image_urlstring optionalImage URL for Stories/Reels (9:16, recommended 1080x1920px). Uses asset_feed_spec for placement-specific creatives.
right_column_image_urlstring optionalImage URL for Right Column (1.91:1, recommended 1200x628px). Uses asset_feed_spec for placement-specific creatives.
video_urlstring optionalVideo URL (for video type)
existing_video_idstring optionalExisting video ID
thumbnail_urlstring optionalCustom thumbnail URL
placement_specific_videosobject optionalMap of placement name → video URL or existing Meta video ID. Keys: 'feed' (1:1 or 16:9 horizontal), 'stories_reels' (9:16 vertical), 'right_column' (1.91:1). Values: public MP4 URL or existing video ID. Backend uploads each, resolves thumbnails, builds asset_feed_spec.videos[] + asset_customization_rules[] mapping each video to its placement. Mutually exclusive with video_url / existing_video_id. ad_type='video' only.
cardsarray optionalCarousel cards (2-10). Each card MUST have: `headline` and ONE of `existing_image_hash` (preferred — use the hash from `discover_meta_assets`) OR `image_url` (will upload). `image_hash` is accepted as an alias for `existing_image_hash`. Per-card `landing_page_url` is optional — falls back to the carousel-level `landing_page_url` if omitted. Video-only cards (`video_id` / `existing_video_id` without an image source) are NOT supported; use `create_meta_video_campaign` for video ads. Optional per-card keys: `description` (≤20 chars), `call_to_action`.
primary_textstring optionalPrimary ad text (max 2200 chars, recommended 125). Provide EITHER this (single) OR `primary_texts` (a 2-5 item list for dynamic creative). One of the two is REQUIRED. Ask the user before calling. Supports emojis and line breaks. ⚠️ If the user gives you 2+ primary text variations, put ALL of them in `primary_texts` (one Dynamic-Creative ad) — do not pick one for this field.
headlinestring optionalHeadline (max 255 chars, recommended 40). If the user gives you 2+ headline variations, use the `headlines` array instead of this single field.
landing_page_urlstring required**REQUIRED.** Landing page URL (HTTPS). Ask the user for it before calling.
call_to_actionstring optionalCTA button default: "LEARN_MORE"
descriptionstring optionalDescription (max 255 chars, recommended 30). For 2+ description variations use the `descriptions` array instead.
display_linkstring optionalOptional display URL (caption) shown in the ad instead of the full landing page URL (e.g. 'brand.com'). Must match or redirect to the landing_page_url domain. NOT supported for ad_type='video'.
image_urlsarray optionalList of image URLs for multi-image Dynamic Creative (2-10). Meta automatically tests all combinations and optimizes delivery. Only valid with ad_type='image'. Mutually exclusive with image_url/existing_image_hash/story_image_url.
headlinesarray optionalList of headline variations (2-5). **USE THIS whenever the user gives you 2+ headlines** — one ad, Meta tests the combinations (Dynamic Creative); do not pick one into the singular headline field. Works with image_urls (multi-image DCO) OR on a single image/video. Not supported for carousel — use per-card cards[].headline.
primary_textsarray optionalList of primary text variations (2-5). **USE THIS whenever the user gives you 2+ primary texts** — one ad, Meta tests the combinations (Dynamic Creative); do not pick one into the singular primary_text field. Works with image_urls (multi-image DCO) OR on a single image/video. Not supported for carousel.
descriptionsarray optionalList of description variations (up to 5). Works with image_urls (multi-image DCO) OR on a single image/video (multi-text A/B testing without DCO). Not supported for carousel — use per-card cards[].description.
lead_form_idstring optionalLead form ID for OUTCOME_LEADS campaigns. If not provided, auto-fetched from the ad set's campaign.
facebook_page_idstring optionalFacebook Page ID
instagram_account_idstring optionalInstagram account ID
ad_namestring optionalCustom name for the ad. Also accepts 'name' as alias.
ad_account_idstring optionalMeta ad account ID
multi_advertiserboolean optionalSet to false to opt out of Meta's multi-advertiser ad format at the creative level. Default (None) = Meta's default behavior (enrolled).
url_tagsstring optionalURL parameters (e.g. 'utm_source=meta&utm_medium=cpc&utm_campaign=...') appended to the landing-page URL on every click. Use for UTM tracking. Leading '?' is stripped automatically. Set at the creative level — applies to every click on this ad.
advantage_plus_creativeboolean optionalMaster switch for Meta's Advantage+ Creative AI enhancements. Set False to opt OUT of ALL granular enhancements at once. Leave None or True to keep Meta's defaults.
disabled_creative_featuresarray optionalList of granular Advantage+ Creative features to opt OUT of individually. 'standard_enhancements' rejected (deprecated in Meta API v22, breaks duplicate_campaign).
deep_link_url_iosstring optionalOptional iOS deep link to open a specific app screen (e.g. 'myapp://product/123'). Only takes effect when the parent ad set's campaign is OUTCOME_APP_PROMOTION.
deep_link_url_androidstring optionalOptional Android deep link (e.g. 'myapp://product/123' or 'intent://...'). Only takes effect when the parent ad set's campaign is OUTCOME_APP_PROMOTION.

Example request

{
  "arguments": {
    "ad_set_id": "string",
    "ad_type": "https://example.com",
    "landing_page_url": "https://example.com",
    "auto_copy_creative": false,
    "image_url": "string",
    "existing_image_hash": "string",
    "asset_bundle_id": "string",
    "story_image_url": "string",
    "right_column_image_url": "string"
  }
}

Example responses

200 — Success

{
  "success": true,
  "data": {
    "text": "(tool-specific textual output for add_meta_ad)",
    "quota": {
      "used": 42,
      "limit": 150,
      "tier": "plus",
      "period_end": "2026-05-01"
    }
  },
  "tool": "add_meta_ad"
}

400 — Tool-level error (bad arguments / multi-account selection)

{
  "success": false,
  "error": "You have 25 meta_ads accounts connected. Please specify which account to use by passing the ad_account_id parameter:\n  - Acme Holdings (ad_account_id=\"act_123456789\")\n  - Acme EU (ad_account_id=\"act_987654321\")",
  "is_error": true,
  "tool": "add_meta_ad"
}

402 — Quota exhausted

{
  "success": false,
  "error": "\ud83d\udea8 Monthly limit reached (150/150 tool calls on Plus tier).\nUpgrade to Pro at https://adspirer.ai to keep building.",
  "is_error": true,
  "tool": "add_meta_ad",
  "quota": {
    "used": 150,
    "limit": 150,
    "tier": "plus",
    "period_end": "2026-05-01",
    "upgrade_url": "https://adspirer.ai"
  }
}

Try it live


Adspirer REST API — get an API key at adspirer.ai/keys · adspirer.ai