Update an ad set
Changed onChanges an ad set's settings, such as its budget, bid strategy, status or delivery options.
Use this for ABO budget updates, ad-set-scoped pause/resume, bid-strategy edits, Meta value-rule-set attach/detach, and Meta-only post-launch delivery settings via platformSpecificData. At least one updatable field is required.
Value rule sets (Meta only, see /v1/ads/value-rule-sets):
- ATTACH or REPLACE: send valueRuleSetId. Attachment is driven by the id's presence, so valueRulesApplied: true is optional. Sending a different id replaces the previous association; there is no separate replace call.
- DETACH: send valueRulesApplied: false and OMIT valueRuleSetId.
- Sending valueRulesApplied: false TOGETHER with valueRuleSetId returns 400 mutually_exclusive_fields. This is deliberate: Meta attaches the rule set whenever value_rule_set_id is present, even with value_rules_applied false, so echoing stored state while asking to detach would silently keep the bid adjustments live.
- Eligibility: only ad sets on LOWEST_COST_WITHOUT_CAP or COST_CAP. Meta rejects the rest server-side.
- Read back with GET /v1/ads/ad-sets/{adSetId}?fields=value_rule_set_id. Meta does not document value_rules_applied as a readable ad-set field, so the boolean cannot be read back.
Bid strategy compatibility (per Meta's spec):
- LOWEST_COST_WITHOUT_CAP: no bidAmount, no roasAverageFloor.
- LOWEST_COST_WITH_BID_CAP / COST_CAP: bidAmount REQUIRED (whole currency units).
- LOWEST_COST_WITH_MIN_ROAS: roasAverageFloor REQUIRED (decimal multiplier, e.g. 2.0 = 2.0x ROAS).
- Meta only: send bidAmount WITHOUT bidStrategy to change the cap amount on an ad set whose strategy (its own, or the campaign's under CBO) is COST_CAP / LOWEST_COST_WITH_BID_CAP, leaving the strategy untouched. Send roasAverageFloor WITHOUT bidStrategy the same way to change the floor of a LOWEST_COST_WITH_MIN_ROAS ad set. Either field against an incompatible current strategy is a 400.
- Meta CBO (the campaign holds the budget): the campaign also holds the bid strategy, so only bidAmount or roasAverageFloor is written on the ad set. A bidStrategy equal to the campaign's is accepted; a different one is a 409 (change it with PUT /v1/ads/campaigns/{campaignId}).
Delivery settings are validated by Meta against the campaign objective; incompatible combinations (e.g. a billingEvent the optimization goal doesn't allow) surface as 400s from Meta.
When updating budget on an ad set whose campaign holds the budget (CBO), the response is 409 with code invalid_field_value. Send it to PUT /v1/ads/campaigns/{campaignId} instead.
Reddit Ads: budget changes the ad group's amount; an ad group that spends its campaign budget returns 422 (update the campaign instead), and Reddit cannot switch a published budget between daily and lifetime, so budget.type must match the current one (422 otherwise). name renames the ad group. bidStrategy maps to the ad group's bid_strategy: LOWEST_COST_WITHOUT_CAP = automatic bidding (BIDLESS), LOWEST_COST_WITH_BID_CAP = MANUAL_BIDDING with bidAmount as the bid, COST_CAP = MAXIMIZE_VOLUME with bidAmount as the cap; LOWEST_COST_WITH_MIN_ROAS returns 422.
status behaves exactly as PUT /v1/ads/ad-sets/{adSetId}/status describes: only the ad set's own switch is written, its ads keep theirs, and statusUpdated / statusSkipped report whether that switch was written or a live read showed it already in place.
Placements and targeting (Meta only): placements and targeting take the same shapes as POST /v1/ads/create. Meta replaces an ad set's targeting wholesale, so Zernio reads the live targeting first, changes only what the request names and writes the merged spec back: custom audiences, geo, age, interest groups and targeting_automation you do not send are kept. placements replaces the whole placement set, placements: null returns the ad set to automatic placements, and omitting it leaves placements as they are. Other platforms return 400 for either field before anything in the request is written (use PUT /v1/ads/{adId} with targeting where that platform supports it). The live read and the incomeTier lookup run before any other field is written, so a 502 or 422 from them leaves the ad set unchanged.
Request
- Base URL: https://zernio.com/api
- URL: https://zernio.com/api/v1/ads/ad-sets/{adSetId}
- Auth: HTTP bearer
Path parameters
Platform ad set ID
Request body
Response
Ad set updated
Changes
- info
added the new optional request property
/////
- info
- info
added the new optional request property
- info
added the new optional request property
- info
added the non-success response with the status
- info
added the optional property
to the response with the status
- info