> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apostra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Budgets and fees

> How gross budgets and locked fee terms work for existing percentage-based agreements, and how Apostra's standard 0% media-fee model differs.

## One denomination: gross

<Note>
  Apostra's standard commercial model takes no percentage of media spend. The
  percentage-based fee terms on this page apply only to existing agreements
  that still use the legacy compatibility model. Those terms remain in force
  until the organization accepts a replacement agreement.
</Note>

Every budget a buyer sets or reads on this platform is **gross** — the
fee-inclusive, all-in amount you pay. This holds at every level:

* Campaign `budget.total`
* Per-product budgets on a media buy
* Package budgets

What you type is what you pay. There is no separate "media budget" number to
set or track — the split between media and fee is derived for you and shown
read-only (see [Reading the split](#reading-the-split-budget_breakdown)).
Because everything shares one denomination, budget arithmetic is direct:
media buy budgets allocate against `budget.total`, and delivered spend
compares against the budget that was set.

Media-buy reads carry `budget_denomination: "gross"` so an agent never has to
guess which convention a number uses.

## Fee terms and the fee rate

For an existing percentage-based agreement, the fee comes from your
organization's **fee terms** — the commercial terms on your Apostra contract,
resolved from its rate card. These compatibility terms use a **fee rate**: a
percent of spend. The fee is carved out *inside* your gross budget:

```
fee   = gross budget × fee rate
media = gross budget − fee
```

## Provider minimums apply after fees

A provider's campaign-budget minimum applies to the **net media budget** it
receives, not to the gross buyer budget you set. Your gross budget must
therefore leave enough media after the fee is carved out.

For TikTok advertisers billed in USD or AUD, Apostra checks the verified
campaign floor before calling TikTok: the net campaign budget must exceed 50.
For USD accounts, it also checks that each daily-budget ad group exceeds 20 and
each lifetime-budget ad group receives at least 20 per scheduled day. A package
expanded into several promoted offerings creates one ad group per offering, so
each USD allocation must clear that ad-group floor. If a known floor is missed,
execution stops without a provider write and reports the submitted net budget
and minimum. Other TikTok currency/rule combinations continue to use the
provider's currency-specific validation until their value ranges are verified
locally. Increase the gross budget; do not add the fee on top as a separate
line item.

**The fee rate locks when the media buy is created.** At that moment the
platform resolves your contract's rate for that buy and fixes it for the buy's
whole life — the same way the [FX rate locks](/v2/concepts/cross-currency) on
a cross-currency buy. Budget increases and decreases on a live buy re-split at
the locked rate; a later change to your contract terms affects new media buys
only, never booked ones.

## Reading the split: `budget_breakdown`

Media-buy reads include a read-only `budget_breakdown` alongside the gross
budget. The fields inside it:

| Field                 | Meaning                                                                                                                                                    |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `media_budget`        | The portion of the gross budget that buys media                                                                                                            |
| `fee_amount`          | Apostra fee inside the gross budget                                                                                                                        |
| `fee_rate_percent`    | The fee rate locked when the media buy was created                                                                                                         |
| `effective_gross_cpm` | The buy's gross budget per thousand impressions of its impression goal — see below. `null` when the buy has no positive impression goal or no gross budget |

`budget_denomination` is a sibling of `budget_breakdown` on the media buy, not
a field inside it — always `"gross"`, confirming the buy's budgets are
fee-inclusive.

<Note>
  `budget_denomination` and `budget_breakdown` are snake\_case fields inside the
  otherwise camelCase campaign-embedded media buy object. That is intentional —
  they match the media-buy surface these fields come from.
</Note>

All amounts are in the buy's (buyer) currency. `budget_breakdown` is
informational — you operate on gross budgets only; the breakdown is never an
input. Legacy media buys created before fee terms were locked per buy carry
neither `budget_denomination` nor `budget_breakdown`.

## Effective gross CPM

The breakdown's `effective_gross_cpm` is the buy's all-in price per thousand
impressions, computed at the media buy grain — the buy's gross budget over its
impression goal (the sum of its package goals):

```
effective_gross_cpm = gross budget ÷ impression goal × 1000
```

It is `null` when the buy has no positive impression goal or no gross budget.

Why it matters: product CPMs are the **seller's own price** for media and are
never converted, so "gross budget ÷ seller CPM" overstates impressions — only
the `media_budget` portion buys media. The effective gross CPM prices the
impressions in the gross denomination you operate on (for a buy priced at a
single fixed seller CPM, it works out to `seller CPM ÷ (1 − fee rate)`). Use it
whenever you do "budget ÷ CPM" math on the numbers you operate on.

## Delivered spend is gross

Delivered spend on every buyer surface — campaign and media buy reads, pacing,
and [reporting metrics](/v2/guides/reporting-overview) — is **fee-inclusive**,
stated at the fee terms locked when each media buy was created. A media buy
that delivers in full shows delivered spend equal to its gross budget, so
budget-vs-delivery comparisons need no conversion. The one exception: legacy
media buys created before fee terms were locked per buy report delivered spend
net, exactly as the seller reported it (and carry neither
`budget_denomination` nor `budget_breakdown`).

## What sellers see

Sellers receive and report media demand with the buyer's fee already carved
out — the amount that actually buys media. Your fee rate is a term of *your*
contract with Apostra: it is never shared with a seller, and seller-side
reporting is unaffected by it.

Seller media-buy surfaces label seller-forwarded routed amounts `net_media`.
A pending manual buy with only the inbound buyer request shows commercial data
as unavailable; that request is gross and is never relabeled as seller net. A source-managed
total whose upstream contract does not declare gross or net is labeled
`source_total` instead of being guessed. Currency and CPM appear only when the
seller-visible transaction supplies enough information to state them honestly.
When available, the displayed routed CPM is seller net CPM. Buyer gross budget and effective gross CPM
belong to buyer demand and proposal surfaces, not the seller media-buy list.

## Manual bank deposits remain pending

Recording a bank deposit manually does not make that value available for
campaign spend. Until Apostra can verify the deposit against durable bank or
payment-provider evidence, it stays in a separate pending-origin balance and is
excluded from both the funded balance and the amount available to commit.

An operator-entered reference and a second-person approval authorize and audit
the manual record; neither proves that the money originated from the stated
account. The pending record therefore does not produce a verified-deposit
notification. Origin-verified release into spendable buyer funds is a separate
step and is not currently available for manually recorded deposits.

## The budget ceiling

Media buys allocate against the campaign's gross `budget.total` directly:

* `allocatedBudget` — the sum of the budgets of every media buy that still
  holds budget (`DRAFT`, `PENDING_APPROVAL`, `INPUT_REQUIRED`, `ACTIVE`,
  `PAUSED`), plus the delivered spend (all-in, at each buy's locked fee terms)
  of media buys that have ended or been archived. All gross. A `DRAFT` buy
  holds budget exactly as a live buy does, so it is already counted here.
* `unallocatedBudget` — `budget.total − allocatedBudget`: the room left to
  allocate, whether to a new media buy or as an increase to an existing one.
  Read it from the campaign; don't re-derive it. It can go negative when spend
  already delivered on ended buys exceeds `budget.total`.

When raising an existing media buy's budget, that buy's current budget is
already inside `allocatedBudget`. The most it can be raised to is
`currentBudget + unallocatedBudget` — adding its current budget to
`allocatedBudget` first counts it twice and makes a campaign with real
headroom look over-allocated.

Lowering `budget.total` below what live media buys have already allocated is
rejected with `INSUFFICIENT_MEDIA_BUDGET` — the error names the new ceiling
and the committed total. To lower both at once, put the campaign budget change
and the media buy/package reductions in one
[update request](/v2/buyer/campaigns/tasks/update-campaign); the request is
validated against the post-update allocation and applied atomically.

## Related

<CardGroup cols={2}>
  <Card title="Campaign" href="/v2/object-guides/campaign" icon="rocket">
    Budget fields on the campaign object
  </Card>

  <Card title="Media Buy" href="/v2/buyer/campaigns/media-buys" icon="receipt">
    Where the budget breakdown appears
  </Card>

  <Card title="Cross-currency buying" href="/v2/concepts/cross-currency" icon="money-bill-transfer">
    The FX lock the fee-rate lock mirrors
  </Card>

  <Card title="Reporting overview" href="/v2/guides/reporting-overview" icon="chart-line">
    Delivered spend and derived metrics
  </Card>
</CardGroup>
