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

Update a campaign’s budget

Available on: Meta

Changes the budget of a campaign. The path names the campaign, and the body holds only the change.

It starts a Mutation of the kind meta_update_budget, the same change that POST /mutations starts with that kind. The MCP tool of the same name makes the same change.

Change the daily or the lifetime budget of a campaign with Advantage campaign budget, or of an ad set. Before you change a budget, read its live amount: GET /observe/{advertiserId}/campaigns and GET /observe/{advertiserId}/ad-groups read Meta now. A daily budget is not a hard limit for one day: Meta can spend up to 175% of it on one day, and up to 7 times it in one week.

The change does not happen during this request. The answer is 202, and Location names the Mutation. Poll GET /mutations/{id} until it reports complete or errored. 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.

PATCH/mutations/{advertiserId}/campaigns/{id}/budget
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.

Path parameters
advertiserIdstringrequired
matches ^(acc_)[\s\S]{0,}$
idstringrequired
matches ^\d+$
Request body
requiredapplication/json
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.

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.

Responses
202

The Mutation started, and it has not ended. The body is the answer of GET /mutations/{id}, with status of running. Poll the path in Location for the outcome.

mutationIdstringrequired

The id of the Mutation, for example mut_k3x9q2v7m4n8p1r5t6w0y2z4. A start answers it, and also gives the path to poll in Location. A Mutation that started before the mut_ prefix keeps its UUID id.

priorValueobject

The values that the change replaced, read from the provider just before the change. It uses the field names and the units of action, for example {"dailyBudget": 800}, {"status": "ACTIVE"}, {"bidStrategy": "COST_CAP", "costCap": 4}, {"startTime": "2026-10-01T00:00:00+0200", "endTime": null} or {"name": "Spring sale"}. To undo the change, send the same kind again with these values. A bid change on a campaign also gives the amount of each ad set in adsets: undo it on each ad set. A create and a copy have none.

resultany

How the change ended. Present only when status is complete. ok of true carries what the provider gave back: a create carries the new object id, a copy carries the id of the copy and the budget that the copy carries, and every other action carries success. The budget is {"dailyBudget": 50} or {"lifetimeBudget": 500} in whole units of the account currency, "campaign" for an ad set copy that spends the budget of its campaign, or "adset" for a campaign copy whose ad sets each carry a budget. A schedule change also carries deliveryStartsAgain of true when it gave an ACTIVE ad set that had ended a new end: the ad set then delivers again. ok of false is a refusal, with a stable error code and a sentence: a provider refusal, or, for a change that an AI agent started through MCP, rejected (a person rejected it in the console) or expired (nobody confirmed it within 24 hours). After rejected or expired, nothing changed at the provider.

statusstringrequired

running means poll again. awaiting_confirmation means a person must confirm the change in the AdCrunch console first: only a change that an AI agent started through MCP waits, never one started through this API. complete means the change finished, and result says how it ended. errored means the Mutation itself broke down, and AdCrunch cannot say whether the change happened.

Allowed:runningawaiting_confirmationcompleteerrored
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.

402

The organization has no active subscription. An owner subscribes at paywallUrl. error is organization_unentitled.

paywallUrlstring<uri>required

The page where an owner of the organization subscribes. Show it to the person.

errorstringrequired

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

Allowed:organization_unentitled
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 PATCH 'https://api.pr-1099.adcrunch.dev/mutations/acc_1203456789012345/campaigns/120210000000000/budget' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
  "dailyBudget": 1
}'
Response
{
  "mutationId": "mut_k3x9q2v7m4n8p1r5t6w0y2z4",
  "status": "running"
}