---
title: "Create a paused Meta image campaign"
method: POST
path: "/api/v1/tools/meta_create_image_campaign/execute"
tags: ["Meta Ads"]
---

# Create a paused Meta image campaign

`POST /api/v1/tools/meta_create_image_campaign/execute`

## Request

- Base URL: `https://adako.ai`
- URL: `https://adako.ai/api/v1/tools/meta_create_image_campaign/execute`
- Auth: HTTP bearer

Builds a complete single-image campaign: campaign, one ad set, the image upload, the creative and one ad. The campaign is created PAUSED and its ad set and ad ACTIVE inside it, so nothing spends until the campaign is turned on, and turning it on launches the ad. Say that the campaign is paused when you report the result, with the two links the result gives (Ads Manager and the campaign's page in Adako), and offer "enable all": one meta_resume_entity call on the campaign, listed in the result as go_live.enable_all, one approval.
Use when: the user has agreed on objective, budget, audience, image and copy. Gather those first — resolve locations and interests with meta_search_targeting, the Page with meta_list_pages, the pixel with meta_list_pixels, and check the image with meta_validate_creative_url.
Do not use to add another ad or audience to something that already exists; this always creates a new campaign, and calling it twice for the same brief creates two campaigns that both spend.
Do not pass free text for locations or interests — only ids from the resolver tools are accepted.
Returns the four new ids and reads the statuses back so you can confirm the campaign is paused (the ad set and ad read ACTIVE, held by the campaign).
Refuses to start when: the account has no promotable Page; the account has several Pages and none was chosen; a sales or leads objective has no pixel; a country code is not ISO or a region or city key is unknown to Meta; the targeting reaches the EU/EEA without dsa_beneficiary and dsa_payor; a date is in the past or a timestamp has no UTC offset; the budget is below Meta's minimum for this account; the objective is app promotion or the goal is an instant form; a special ad category is combined with targeting Meta forbids for it; or image_url does not answer with a JPEG, PNG or GIF file under 30 MB. Ask the user for the missing piece rather than substituting a value.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `arguments` object, required
    - `ad_account_id` string: Meta ad account id such as act_1234567890. Omit it to use the primary account; if several accounts are active and none is primary the call fails and lists the valid ids.
    - `campaign_name` string, required: Name shown in Ads Manager. Say what it sells and to whom.
    - `objective` 'OUTCOME_AWARENESS' | 'OUTCOME_TRAFFIC' | 'OUTCOME_ENGAGEMENT' | 'OUTCOME_LEADS' | 'OUTCOME_SALES' | 'OUTCOME_APP_PROMOTION', required: What Meta should optimise the campaign for. OUTCOME_SALES and OUTCOME_LEADS need a pixel; OUTCOME_TRAFFIC, OUTCOME_ENGAGEMENT and OUTCOME_AWARENESS do not. OUTCOME_APP_PROMOTION is refused here: use meta_create_app_install_campaign.
    - `daily_budget` number: Daily budget as a decimal in the account currency (25 means 25 dollars, not 2500 cents). One of daily_budget or lifetime_budget is required.
    - `lifetime_budget` number: Total budget for the whole flight, decimal in the account currency. Requires end_time.
    - `budget_level` 'ad_set' | 'campaign': Which level holds the budget. "ad_set" (the default) gives this ad set its own budget, so every ad set is funded separately. "campaign" is Meta's campaign budget optimisation (Advantage campaign budget): the campaign holds one budget and Meta decides how much each ad set gets — ad sets added later must then carry no budget of their own. Only "campaign" can be edited with meta_update_campaign_budget.
    - `start_time` string: When delivery may start: YYYY-MM-DD (00:00 in the ad account's time zone) or an ISO timestamp with a UTC offset, e.g. 2026-10-01T09:00:00+02:00. Not in the past; today or omitted means as soon as the user activates it.
    - `end_time` string: When delivery must stop: YYYY-MM-DD (runs to 23:59:59 in the ad account's time zone) or an ISO timestamp with a UTC offset. Required with lifetime_budget.
    - `optimization_goal` string: Override what the ad set optimises for. Leave empty to use the objective default. LEAD_GENERATION (instant forms) is not supported; PAGE_LIKES promotes the Page.
    - `billing_event` string: What Meta charges for. Leave empty to use IMPRESSIONS.
    - `pixel_id` string: Pixel that records the conversion. Required for sales and leads objectives; get it from meta_list_pixels.
    - `conversion_event` 'PURCHASE' | 'LEAD' | 'COMPLETE_REGISTRATION' | 'ADD_TO_CART' | 'INITIATED_CHECKOUT' | 'ADD_PAYMENT_INFO' | 'SUBSCRIBE' | 'START_TRIAL' | 'SUBMIT_APPLICATION' | 'CONTACT' | 'SCHEDULE' | 'SEARCH' | 'CONTENT_VIEW' | 'DONATE' | 'FIND_LOCATION': The pixel event to optimise for. Defaults to PURCHASE for sales, LEAD for leads.
    - `countries` string[]: ISO 3166-1 two-letter country codes from meta_search_targeting: GB, not UK; GR, not EL.
    - `region_keys` string[]: Region keys from meta_search_targeting (never region names). Checked with Meta first.
    - `city_keys` string[]: City keys from meta_search_targeting (never city names, postcodes or media markets). Each city is targeted with a 25 km radius.
    - `age_min` integer: Youngest age to target. Minimum 18.
    - `age_max` integer: Oldest age to target. 65 means 65 and over.
    - `genders` 'all' | 'men' | 'women': Restrict by gender. Defaults to all — narrow only when the user asks.
    - `interest_ids` string[]: Interest ids from meta_search_targeting. Never free text.
    - `behavior_ids` string[]: Behaviour ids from meta_search_targeting. Never free text.
    - `custom_audience_ids` string[]: Custom audience ids from meta_list_custom_audiences.
    - `excluded_custom_audience_ids` string[]: Custom audiences to exclude, e.g. existing customers.
    - `advantage_audience` boolean: Let Meta deliver beyond the listed interests. Defaults to off so the targeting the user asked for is the targeting they get.
    - `dsa_beneficiary` string: Who benefits from the ad. Required whenever the targeting reaches the EU or EEA — a country, or a region or city inside one, including territories such as Réunion.
    - `dsa_payor` string: Who pays for the ad. Required whenever the targeting reaches the EU or EEA — a country, or a region or city inside one.
    - `special_ad_categories` string[]: Declare a restricted category (housing, employment, credit, politics, gambling, financial products). Leave empty unless the ad genuinely falls into one — a wrong declaration limits delivery, a missing one breaks Meta policy. CREDIT is sent as FINANCIAL_PRODUCTS_SERVICES, which replaced it. Housing, employment and financial products keep the audience at ages 18–65+, all genders, no behaviours and no lookalikes. Political ads (ISSUES_ELECTIONS_POLITICS) cannot be created here.
    - `special_ad_category_country` string[]: Countries the special ad category ads run in (ISO two-letter codes). Meta requires it with any special_ad_categories; omit it to use the targeted countries.
    - `facebook_page_id` string: Page the ad runs from, from meta_list_pages. Required when the account has more than one Page.
    - `instagram_account_id` string: Instagram account to run the ad from, from meta_list_pages.
    - `image_url` string, uri: The image the ad will show, as a link to the file itself. Adako hosts no files: the platform downloads this URL itself, from its own servers and often hours later, so it must be a public link straight to the file — not a file on the computer, not a Drive, Dropbox or design-tool share page, not a link that expires or asks for a login. Call check_media first: it repairs the usual share links, checks the file against this platform, and says where to put a file that has no link yet.
    - `image_hash` string: An image already in the account library, from meta_list_media (its `image_hash`). Pass this instead of image_url when the file is already in the account — nothing is downloaded or uploaded, so it works for a file that has no public link at all.
    - `primary_text` string, required: Main ad copy. About 125 characters show before "See more".
    - `headline` string: Headline under the image. About 40 characters show.
    - `description` string: Description line. About 30 characters show, and only on some placements.
    - `landing_page_url` string, uri, required: Where the ad sends people. Must be HTTPS.
    - `call_to_action` 'LEARN_MORE' | 'SHOP_NOW' | 'SIGN_UP' | 'SUBSCRIBE' | 'DOWNLOAD' | 'BOOK_NOW' | 'GET_QUOTE' | 'CONTACT_US' | 'APPLY_NOW' | 'GET_OFFER' | 'ORDER_NOW' | 'SEE_MORE' | 'GET_STARTED' | 'BUY_NOW' | 'DONATE_NOW' | 'NO_BUTTON': Button label. Defaults to LEARN_MORE.
    - `ad_set_name` string: Ad set name. Defaults to the campaign name plus a suffix.
    - `ad_name` string: Ad name. Defaults to the campaign name plus a suffix.
    - `idempotency_key` string: Optional caller-supplied key; identical keys never execute twice.
    - `raw_data` boolean: Return compact JSON only (no markdown). Use when you will compute on the result.

## Response `200`

The tool ran. A write returns proposal_id and approve_url while the change waits for approval.

- SuccessEnvelope
  - `success` unknown, required
  - `tool` string, required
  - `data` object, required: Machine-readable result.
  - `markdown` string, required: The same result written for a person or a model.
  - `quota` Quota: Task usage for the current billing period.
    - `plan` string
    - `used` integer
    - `limit` integer
    - `period_end` string
    - `upgrade_url` string
  - `proposal_id` string: Present for writes. Nothing changes on the ad platform until it is approved.
  - `approve_url` string: Where a person approves the proposal.
  - `request_id` string, required

## Other responses

- `400`: Invalid arguments, or the ad account could not be resolved.
- `401`: Missing, invalid, revoked or expired API key.
- `402`: Monthly task quota used up, or the plan does not include this tool.
- `403`: The connected ad account lacks the access level this tool needs.
- `404`: Unknown tool name.
- `409`: Not connected, reconnect needed, confirmation required, a proposal already pending or no longer pending, an identical create that failed earlier today (proposal_failed_before), a create that duplicates an approved one (duplicate_create), the ad-account limit of the plan reached (account_limit), or an Idempotency-Key reused with different arguments.
- `429`: Rate limited by Adako or by the ad platform. See Retry-After.
- `500`: Unexpected error inside Adako.
- `502`: The ad platform returned an error.

---

[API](https://skmtc.dev/adako/apis/adako-rest-api.md) · [All operations](https://skmtc.dev/adako/apis/adako-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/adako/apis/adako-rest-api/revisions/59ee60d48a56?raw)
