Skip to content
AdCrunch
Esc
↑↓navigate↵open⌘Jpreview

Start a mutation

Available on: Meta

Starts a change on a live advertiser and answers immediately.

The change does not happen during this request. The answer carries a workflowId. Poll GET /mutations/{id} with it to find out how the change ended. A Mutation is durable, so the id stays valid across retries and restarts.

A refused request starts nothing. AdCrunch refuses a body that does not match, an advertiser that is not yours, an advertiser with no usable connection, and an advertiser connected without write access before a Mutation exists. So a failed call leaves no row in the history.

This operation checks the credential first and the body second. A missing or unusable credential answers 401 even when the body is wrong as well. A body that does not match then answers 400 with error of invalid_request, and issues names each field.

A create never starts delivery: a campaign, an ad set and an ad all arrive paused, and so does a copy of a campaign or an ad set. This API also cannot delete, so meta_set_status with ARCHIVED is how an object is retired.

POST/mutations
Authorization
AuthorizationBearer token · headerrequired

Send Authorization: Bearer <credential>.

Use an API key (acr_…), from the AdCrunch console under Settings → API keys.

The credential names the organization, and no operation takes an organization parameter.

See https://docs.adcrunch.dev/api/authentication.

Request body
requiredapplication/json
actionobjectrequired

What to do. The kind field selects the action, and each kind takes its own fields.

Show properties
One of:
object
idstringrequired

The Meta id of the object to change: the native id, digits only, not an AdCrunch id. The object must be in the ad account of the advertiser, else the change ends with not_found.

matches ^\d+$
kindstringrequired
Allowed:meta_set_status
levelstringrequired

Which object the id refers to.

Allowed:campaignadsetad
statusstringrequired

The status to set. ACTIVE starts delivery and starts spend. PAUSED stops delivery and can be reversed. ARCHIVED retires the object, and on Meta it is close to one-way: you cannot make an archived object active again from this API. Archive is the only way to retire an object, because this API never deletes one.

Allowed:ACTIVEPAUSEDARCHIVED
object
dailyBudgetnumber

The amount to spend each day. The amount is in whole units of the ad account currency: 10.5 is 10.50. Meta refuses more decimals than the currency has, and it counts some currencies, such as JPY and HUF, with none. Give a daily budget or a lifetime budget, not both. To change a daily budget to a lifetime budget, first set an end time with meta_update_schedule, then set the lifetime budget. To change a lifetime budget to a daily budget, first set the daily budget, then remove the end time with meta_update_schedule. Meta refuses a lifetime budget with no end time.

idstringrequired

The Meta id of the campaign or ad set to change: the native id, digits only, not an AdCrunch id. The object must be in the ad account of the advertiser, else the change ends with not_found.

matches ^\d+$
kindstringrequired
Allowed:meta_update_budget
levelstringrequired

Which object the id refers to. An ad has no budget of its own.

Allowed:campaignadset
lifetimeBudgetnumber

The amount to spend across the whole schedule. The amount is in whole units of the ad account currency: 10.5 is 10.50. Meta refuses more decimals than the currency has, and it counts some currencies, such as JPY and HUF, with none. A lifetime budget needs an end time on the ad set. To change a daily budget to a lifetime budget, first set an end time with meta_update_schedule, then set the lifetime budget. To change a lifetime budget to a daily budget, first set the daily budget, then remove the end time with meta_update_schedule. Meta refuses a lifetime budget with no end time.

object
endTimestring | null

When delivery stops, as an ISO 8601 timestamp in the future, for example 2026-12-31T23:59:00+01:00. Send null for no end. An ad set with a lifetime budget must keep an end time. A later end time adds days of spend, so the total spend of a daily budget increases. With no end, the ad set spends until you pause it, up to 7 times its daily budget in one week. With a lifetime budget, the total spend stays within the lifetime budget. An ACTIVE ad set that has ended delivers again when it gets a new end time or no end, with no status change. To change a daily budget to a lifetime budget, first set an end time with meta_update_schedule, then set the lifetime budget. To change a lifetime budget to a daily budget, first set the daily budget, then remove the end time with meta_update_schedule. Meta refuses a lifetime budget with no end time.

idstringrequired

The Meta id of the ad set to change: the native id, digits only, not an AdCrunch id. The ad set must be in the ad account of the advertiser, else the change ends with not_found. A campaign has no schedule that this API can change.

matches ^\d+$
kindstringrequired
Allowed:meta_update_schedule
startTimestring

When delivery starts, as an ISO 8601 timestamp. Meta gets it as you send it, also on an ad set that has started, and Meta decides what it does. Give startTime, endTime, or both.

object
adsetBudgetSharingboolean

Let the ad sets share their budgets. Only when both campaign budgets are omitted; false when omitted. Each ad set can then share up to 20 % of its daily budget with the other ad sets of the campaign. Sharing works with daily budgets only. It needs a bidStrategy, and it locks that bid strategy for the life of the campaign. Sharing cannot be turned on later.

bidStrategystring

How Meta bids. LOWEST_COST_WITHOUT_CAP ("Highest volume" in Ads Manager) gets the most results for the budget and takes no amount. LOWEST_COST_WITH_BID_CAP ("Bid cap") takes bidCap. COST_CAP ("Cost per result goal") takes costCap. LOWEST_COST_WITH_MIN_ROAS ("ROAS goal") takes roasFloor, and needs the optimization goal VALUE. Give exactly the amount that the strategy takes, and no other amount. A higher bid cap, a higher cost cap or a lower ROAS floor can make an ad set spend its full budget, never more. On a campaign, give only the strategy. It applies when the campaign carries a budget, or when adsetBudgetSharing is true, which requires it. Give the amount of a bid cap, a cost cap or a ROAS goal on each ad set, with the same bidStrategy. Omit it to let Meta apply its default strategy.

Allowed:LOWEST_COST_WITHOUT_CAPLOWEST_COST_WITH_BID_CAPCOST_CAPLOWEST_COST_WITH_MIN_ROAS
dailyBudgetnumber

The amount the campaign spends each day, shared across its ad sets. The amount is in whole units of the ad account currency: 10.5 is 10.50. Meta refuses more decimals than the currency has, and it counts some currencies, such as JPY and HUF, with none. Give one of the two budgets, or neither. When each ad set carries its own budget, for example one ad set for each Line Item, omit both budgets.

kindstringrequired
Allowed:meta_create_campaign
lifetimeBudgetnumber

The amount the campaign spends across its whole schedule, shared across its ad sets. The amount is in whole units of the ad account currency: 10.5 is 10.50. Meta refuses more decimals than the currency has, and it counts some currencies, such as JPY and HUF, with none. Give one of the two budgets, or neither. When each ad set carries its own budget, for example one ad set for each Line Item, omit both budgets.

namestringrequired

The campaign name. It is visible in Meta Ads Manager.

min length 1
objectivestringrequired

The result the campaign optimizes for. It cannot be changed after the campaign is created, and it limits which optimization goals the ad sets below it can use.

Allowed:OUTCOME_AWARENESSOUTCOME_ENGAGEMENTOUTCOME_LEADSOUTCOME_SALESOUTCOME_TRAFFICOUTCOME_APP_PROMOTION
specialAdCategoriesstring[]required

Declare a regulated category when the campaign advertises one: EMPLOYMENT, HOUSING, CREDIT, ISSUES_ELECTIONS_POLITICS, ONLINE_GAMBLING_AND_GAMING, or FINANCIAL_PRODUCTS_SERVICES. Meta restricts targeting for each of them, and a wrong declaration breaks the advertiser policy agreement. Send an empty array or NONE when none applies. Do not guess: ask the advertiser.

default: []
object
ageMaxinteger

The oldest age to target, from 13 to 65. Omit it to target every age above the minimum. 65 and above is one group on Meta.

min 13 · max 65
bidCapnumber

The highest bid Meta places in an auction. Only with LOWEST_COST_WITH_BID_CAP. A bid is per optimization event, for example per purchase, and per 1,000 impressions when the optimization goal is IMPRESSIONS or REACH. The amount is in whole units of the ad account currency: 2.5 is 2.50. Meta refuses more decimals than the currency has.

costCapnumber

The average cost per result that Meta tries to keep. Only with COST_CAP. A bid is per optimization event, for example per purchase, and per 1,000 impressions when the optimization goal is IMPRESSIONS or REACH. The amount is in whole units of the ad account currency: 2.5 is 2.50. Meta refuses more decimals than the currency has. A cost cap can stop the ad set before it spends its full budget.

roasFloornumber

The lowest return on ad spend that Meta bids for, as a ratio: 1.5 means purchase value of 1.5 times the spend. Only with LOWEST_COST_WITH_MIN_ROAS. From 0.01 to 1000, with at most 4 decimals.

min 0.01 · max 1000
bidStrategystring

How Meta bids. LOWEST_COST_WITHOUT_CAP ("Highest volume" in Ads Manager) gets the most results for the budget and takes no amount. LOWEST_COST_WITH_BID_CAP ("Bid cap") takes bidCap. COST_CAP ("Cost per result goal") takes costCap. LOWEST_COST_WITH_MIN_ROAS ("ROAS goal") takes roasFloor, and needs the optimization goal VALUE. Give exactly the amount that the strategy takes, and no other amount. A higher bid cap, a higher cost cap or a lower ROAS floor can make an ad set spend its full budget, never more. When the campaign carries the budget, or shares the ad set budgets, the campaign holds the strategy: give the same bidStrategy here, with the amount for this ad set. Omit it, with every amount, to let Meta apply its default strategy.

Allowed:LOWEST_COST_WITHOUT_CAPLOWEST_COST_WITH_BID_CAPCOST_CAPLOWEST_COST_WITH_MIN_ROAS
ageMinintegerrequired

The youngest age to target, from 13 to 65. This field is required, and it is the one targeting field with no default. Many advertisers must not show ads to people under 18, and a default would spend their money on an audience they cannot legally address. State the age deliberately: send 18 to exclude minors.

min 13 · max 65
campaignIdstringrequired

The Meta id of the campaign this ad set belongs to, digits only. Create the campaign first and use the id it returns.

matches ^\d+$
countriesstring[]required

The countries to target, as two-letter ISO 3166-1 alpha-2 codes, for example US or GB. Give at least one.

min items 1
customEventTypestring

The conversion the pixel reports, for example PURCHASE. Required with a conversion optimization goal, and it must be sent together with pixelId.

Allowed:PURCHASELEADCOMPLETE_REGISTRATIONADD_TO_CARTINITIATED_CHECKOUTADD_PAYMENT_INFOVIEW_CONTENTSEARCHSUBSCRIBESTART_TRIALCONTACTOTHER
dailyBudgetnumber

The amount this ad set spends each day. The amount is in whole units of the ad account currency: 10.5 is 10.50. Meta refuses more decimals than the currency has, and it counts some currencies, such as JPY and HUF, with none. Omit both budgets when the campaign carries one. When the campaign carries none, give exactly one.

endTimestring

When delivery stops, as an ISO 8601 timestamp. Required with a lifetime budget.

gendersstringrequired

Which genders to target. The default targets everybody.

default: "all"
Allowed:allmenwomen
kindstringrequired
Allowed:meta_create_adset
lifetimeBudgetnumber

The amount this ad set spends across its whole schedule. The amount is in whole units of the ad account currency: 10.5 is 10.50. Meta refuses more decimals than the currency has, and it counts some currencies, such as JPY and HUF, with none. It needs an end time.

namestringrequired

The ad set name. It is visible in Meta Ads Manager.

min length 1
optimizationGoalstringrequired

What Meta optimizes delivery for. The campaign objective limits which goals are valid. A conversion goal also needs pixelId and customEventType. The billing event follows from this goal, so there is no separate field for it.

Allowed:IMPRESSIONSREACHLINK_CLICKSLANDING_PAGE_VIEWSOFFSITE_CONVERSIONSPOST_ENGAGEMENTTHRUPLAYLEAD_GENERATIONVALUE
pixelIdstring

The Meta pixel that reports conversions. Required with a conversion optimization goal. AdCrunch can list the pixels this ad account can use.

startTimestring

When delivery starts, as an ISO 8601 timestamp. Omit it to start when the ad set becomes active. The ad set is created paused either way.

object
adsetIdstringrequired

The Meta id of the ad set this ad runs in, digits only. Create the ad set first and use the id it returns.

matches ^\d+$
creativeIdstringrequired

The Meta id of the creative this ad shows, digits only. Create the creative first with meta_create_creative and use the id it returns. One creative can be used by more than one ad.

matches ^\d+$
kindstringrequired
Allowed:meta_create_ad
namestringrequired

The ad name. It is visible in Meta Ads Manager.

min length 1
object
assetIdstringrequired

The AdCrunch Asset to build the creative from, as the ast_ id that Asset registration returned. The Asset must already be registered to this advertiser. Do not send a Meta image hash or video id. Whether the creative becomes an image or a video follows from the Asset.

matches ^ast_[\s\S]{0,}$
callToActionstringrequired

The label on the button, for example SHOP_NOW.

Allowed:LEARN_MORESHOP_NOWSIGN_UPBOOK_TRAVELDOWNLOADGET_OFFERGET_QUOTECONTACT_USSUBSCRIBEAPPLY_NOWNO_BUTTON
descriptionstring

The text below the headline. Meta can truncate it.

headlinestringrequired

The short bold line next to the button.

min length 1
kindstringrequired
Allowed:meta_create_creative
linkstring<uri>required

The page the ad opens when somebody clicks it.

messagestringrequired

The main body text, shown above the media.

min length 1
namestringrequired

The creative name. It is visible in Meta Ads Manager, and it is not shown to a person who sees the ad.

min length 1
pageIdstringrequired

The Facebook Page the ad is published from. AdCrunch can list the Pages this ad account can publish from.

object
bidCapnumber

The highest bid Meta places in an auction. Only with LOWEST_COST_WITH_BID_CAP. A bid is per optimization event, for example per purchase, and per 1,000 impressions when the optimization goal is IMPRESSIONS or REACH. The amount is in whole units of the ad account currency: 2.5 is 2.50. Meta refuses more decimals than the currency has.

costCapnumber

The average cost per result that Meta tries to keep. Only with COST_CAP. A bid is per optimization event, for example per purchase, and per 1,000 impressions when the optimization goal is IMPRESSIONS or REACH. The amount is in whole units of the ad account currency: 2.5 is 2.50. Meta refuses more decimals than the currency has. A cost cap can stop the ad set before it spends its full budget.

roasFloornumber

The lowest return on ad spend that Meta bids for, as a ratio: 1.5 means purchase value of 1.5 times the spend. Only with LOWEST_COST_WITH_MIN_ROAS. From 0.01 to 1000, with at most 4 decimals.

min 0.01 · max 1000
bidStrategystringrequired

How Meta bids. LOWEST_COST_WITHOUT_CAP ("Highest volume" in Ads Manager) gets the most results for the budget and takes no amount. LOWEST_COST_WITH_BID_CAP ("Bid cap") takes bidCap. COST_CAP ("Cost per result goal") takes costCap. LOWEST_COST_WITH_MIN_ROAS ("ROAS goal") takes roasFloor, and needs the optimization goal VALUE. Give exactly the amount that the strategy takes, and no other amount. A higher bid cap, a higher cost cap or a lower ROAS floor can make an ad set spend its full budget, never more. Send the strategy also to change only an amount. A change of strategy starts the learning phase again, and a large change of amount can too. Meta refuses a change of strategy on a campaign with ad set budget sharing, on a campaign budget with more than 70 ad sets, and on a campaign budget on ROAS goal. Meta advises at most 2 or 3 bid or budget changes a day, and 15 minutes between a budget change and a bid change.

Allowed:LOWEST_COST_WITHOUT_CAPLOWEST_COST_WITH_BID_CAPCOST_CAPLOWEST_COST_WITH_MIN_ROAS
idstringrequired

The Meta id of the campaign or ad set to change: the native id, digits only, not an AdCrunch id. The object must be in the ad account of the advertiser, else the change ends with not_found.

matches ^\d+$
kindstringrequired
Allowed:meta_update_bidding
levelstringrequired

Which object the id refers to. The strategy sits where the budget sits: on the campaign under a campaign budget, otherwise on each ad set. Under a campaign budget, an ad set takes only its amount: send the bidStrategy of the campaign with the amount for this ad set. Another strategy ends with wrong_level. A campaign without a campaign budget ends with wrong_level. On a campaign, a bid cap or a cost cap applies one amount to every ad set of the campaign. A ROAS floor sits on each ad set: on a campaign, LOWEST_COST_WITH_MIN_ROAS is refused.

Allowed:campaignadset
object
idstringrequired

The Meta id of the campaign to copy: the native id, digits only, not an AdCrunch id. The campaign must be in the ad account of the advertiser, else the copy ends with not_found. The copy stays in that ad account.

matches ^\d+$
kindstringrequired
Allowed:meta_copy_campaign
object
campaignIdstring

The Meta id of the campaign that receives the copy, digits only. Omit it to keep the copy in the campaign of the source. The copy takes the settings of that campaign: under a campaign budget, it spends the campaign budget. Meta decides whether the campaign accepts the copy.

matches ^\d+$
endTimestring

When delivery of the copy stops, as an ISO 8601 timestamp. Omit it to keep the end time of the source.

idstringrequired

The Meta id of the ad set to copy: the native id, digits only, not an AdCrunch id. The ad set must be in the ad account of the advertiser, else the copy ends with not_found.

matches ^\d+$
kindstringrequired
Allowed:meta_copy_adset
startTimestring

When delivery of the copy starts, as an ISO 8601 timestamp. Omit it to keep the start time of the source. A copy of an ad set that has ended starts when Meta makes it, with the duration of the source.

object
idstringrequired

The Meta id of the object to rename: the native id, digits only, not an AdCrunch id. The object must be in the ad account of the advertiser, else the rename ends with not_found.

matches ^\d+$
kindstringrequired
Allowed:meta_rename
levelstringrequired

Which object the id refers to.

Allowed:campaignadsetad
namestringrequired

The new name, which replaces the whole name. It is visible in Meta Ads Manager.

min length 1
advertiserIdstringrequired

The advertiser to act on, as an AdCrunch acc_ id. It must belong to your organization and be connected with write access.

matches ^(acc_)[\s\S]{0,}$
Responses
200

The Mutation started. Poll it for the outcome.

workflowIdstringrequired

The id of the Mutation. Poll GET /mutations/{id} with it to find out whether the change succeeded.

400

The request does not match the schema of this operation: a field is missing or has the wrong type, or the body is not valid JSON. error is invalid_request, and issues names each field. Nothing was changed.

issuesobject[]required

One entry for each field that does not match.

Show properties
Array of object
instringrequired

The part of the request that holds the field.

Allowed:bodycookieheadersparamsquery
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

pathstringrequired

A JSON Pointer into that part of the request, such as /filename. An empty string is the whole part.

errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:invalid_request
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

401

No API key, or one that does not resolve. See the security scheme. error is unauthorized.

errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:unauthorized
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

403

The caller does not hold mutation:write, or the advertiser is connected without write access. In the second case error is missing_write_access and message says how to fix it. AdCrunch started nothing.

Any of:
object
errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:forbidden
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

object
errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:missing_write_access
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

404

The advertiser does not exist, it belongs to another organization, or it is not a Meta ad account. error is not_found in each case. An advertiser that does not exist and an advertiser of another organization get the same answer on purpose, so a caller cannot learn which ids exist. AdCrunch started nothing.

errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:not_found
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

409

The advertiser has no usable connection: a person removed it, it expired, or the provider refused it. A person must connect it again. error is provider_not_connected, the code that a live read of Observe sends for the same failure. AdCrunch started nothing.

providerstringrequired

The ad platform of the advertiser. It is meta today.

errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:provider_not_connected
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

Request
curl -X POST 'https://api.pr-910.adcrunch.dev/mutations' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
  "action": {
    "id": "120210000000000",
    "kind": "meta_set_status",
    "level": "campaign",
    "status": "PAUSED"
  },
  "advertiserId": "acc_1203456789012345"
}'
Response
{
  "workflowId": "b3d1f0c4-6a2e-4a1f-9f77-2c0d1e5a8b94"
}