Skip to main content
A daily budget cap is a hard ceiling on what a buy, or one line item in it, spends in one day. It is AdCP’s daily_budget_cap: the seller stops delivery for the rest of the day once the cap is reached, and starts again the next day. A cap never spends money on its own. It only limits what the buy’s budget can spend in a day. You set it when you create a media buy with save_media_buy, from sellerAccountId and products. Both caps are numbers in the buy’s currency, gross of fees, like its budgets. You can set either or both. A line item’s cap is its own ceiling: it does not take a share of the buy’s cap, and the line items’ caps need not add up to it.

The rules

  • A buy’s cap is at most its total budget, and a line item’s cap is at most its own budget. A larger cap is refused before anything is staged.
  • A line item’s budget is the one it is staged with. If you leave it out, the line item gets a share of the campaign’s budget, and a budget you state can be scaled down to fit what the campaign has left. A cap above the staged budget is refused, and nothing is staged.
  • With budgetAllocation.mode seller_optimized the seller splits one shared budget across the buy, so no line item has a budget of its own to cap. Such a buy takes only the buy’s daily_budget_cap.
  • A campaign’s budget.dailyCap bounds the sum of its buys’ own caps. It does not count line item caps. See Buyer workflows.
  • The caps are saved with the draft and go to the seller when you launch, net of the buy’s fees, like its budgets.
  • budget_cap_timezone needs a cap on the buy or on a line item. Omit it to use the seller’s default day.
  • You set caps when you create the buy. Setting or changing a cap on an existing buy is not supported yet: save_media_buy with mediaBuyId refuses daily_budget_cap and products[].daily_budget_cap as not implemented.
  • get(kind: "media_buy") shows the buy’s daily_budget_cap and budget_cap_timezone, and with include: ["products"] each line item’s daily_budget_cap.

Which sellers enforce a cap

A seller enforces a cap only when it says so in its AdCP get_adcp_capabilities, under media_buy.budget_capping:
  • supported_scopes lists where it enforces caps: media_buy for a cap on the whole buy, package for a cap on one line item.
  • timezone_basis and fixed_timezone say whose day the caps run on: the account’s timezone, or one fixed timezone, such as an ad server’s network timezone.
  • buyer_timezone_override says whether it takes your budget_cap_timezone.
Apostra checks the seller’s declaration when you create the buy. A cap at a scope the seller does not declare is refused with UNSUPPORTED_FEATURE, naming the field, before anything is staged or sent. Apostra never accepts a cap and then drops it, so a buy you launch with a cap carries the cap at the seller or does not launch. A seller can change its declaration after you create the buy, so Apostra checks it again when you launch. If the seller no longer enforces a cap the buy carries, or no longer takes its budget_cap_timezone, the launch is refused with UNSUPPORTED_FEATURE before anything is sent, and the buy fails. Caps cannot be changed on an existing buy yet, so create the buy again without that cap. When a seller is backed by several sources, every one of them must declare the scope, since any of them may carry the buy. A seller connected through a platform adapter takes a cap on the whole buy only when that adapter enforces a hard daily cap, which none does today, and never takes a line item cap.

When the seller sets the day itself

Some sellers run every cap on their own day and do not take budget_cap_timezone (buyer_timezone_override is absent or false).
  • If the seller runs its caps in one fixed timezone, you can omit budget_cap_timezone or send that same timezone. Any other timezone is refused with UNSUPPORTED_FEATURE, and the message names the seller’s timezone. The cap resets at midnight in that timezone.
  • If the seller runs its caps on the account’s timezone, any budget_cap_timezone is refused. Omit it; the cap resets at midnight in the account’s timezone.
Apostra keeps the timezone you sent on the buy, so your reads show it, but does not send it to a seller that sets the day itself.

A daily cap is not pacing

Pacing (asap, even, front_loaded) is how a seller spreads delivery over a flight. A daily cap is a ceiling. They are separate, and Apostra never turns one into the other: it never adds a daily cap because you asked for even pacing. This matters on products that cannot pace. A Google Ad Manager product sold as a Price Priority line item delivers asap, as fast as it can win, whatever pacing it is asked for, and even on such a product stays asap. To limit how much of its budget such a line item spends each day, set products[].daily_budget_cap on a seller that declares package caps.