Update an ad group’s schedule
Changes the schedule of an ad group. The path names the ad group, and the body holds only the change.
It starts a Mutation of the kind meta_update_schedule, the same change that POST /mutations starts with that kind. The MCP tool of the same name makes the same change.
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.
/mutations/{advertiserId}/ad-groups/{id}/scheduleAuthorizationBearer token · headerrequiredSend 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.
advertiserIdstringrequiredidstringrequiredapplication/jsonendTimestring | nullWhen 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. To undo a schedule change, send the times that it replaced (priorValue). An end time that is not in the future cannot go back: Meta refuses it, and AdCrunch refuses it too. To stop an ad set after you extend its end, set its status to PAUSED with meta_update_status.
startTimestringWhen 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.
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.
mutationIdstringrequiredThe 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.
priorValueobjectThe 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.
resultanyHow 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.
statusstringrequiredrunning 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.
runningawaiting_confirmationcompleteerroredThe 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[]requiredOne entry for each field that does not match.
Show propertiesHide properties
objectinstringrequiredThe part of the request that holds the field.
bodycookieheadersparamsquerymessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
pathstringrequiredA JSON Pointer into that part of the request, such as /filename. An empty string is the whole part.
errorstringrequiredA stable code for the failure. This is the field to branch on. It does not change for a given failure.
invalid_requestmessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
No API key, or one that does not resolve. See the security scheme. error is unauthorized.
errorstringrequiredA stable code for the failure. This is the field to branch on. It does not change for a given failure.
unauthorizedmessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
The organization has no active subscription. An owner subscribes at paywallUrl. error is organization_unentitled.
paywallUrlstring<uri>requiredThe page where an owner of the organization subscribes. Show it to the person.
errorstringrequiredA stable code for the failure. This is the field to branch on. It does not change for a given failure.
organization_unentitledmessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
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.
errorstringrequiredA stable code for the failure. This is the field to branch on. It does not change for a given failure.
forbiddenmessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
errorstringrequiredA stable code for the failure. This is the field to branch on. It does not change for a given failure.
missing_write_accessmessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
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.
errorstringrequiredA stable code for the failure. This is the field to branch on. It does not change for a given failure.
not_foundmessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.
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.
providerstringrequiredThe ad platform of the advertiser. It is meta today.
errorstringrequiredA stable code for the failure. This is the field to branch on. It does not change for a given failure.
provider_not_connectedmessagestringrequiredA sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.