Skip to content

Plan a campaign

Write down what you intend to run — channels, budgets, targeting, dates — as a structured Campaign Plan your agent can sum, approve, execute and record against.

On this page

The read tools tell an agent what is running. The campaign_plan_* and line_item_* tools let it write down what you intend to run — before anything is bought — in a form that adds up, that a human can approve, and that the mutation tools can then build from.

This is the document that usually lives in a spreadsheet: €120,000 across four channels and six markets, ten weeks, with an argument for the split. Here it is data, so nothing has to be retyped into an ad account by hand.

Warning

A Campaign Plan is not a provider campaign

It is AdCrunch’s own planning document, and one Campaign Plan may become several provider campaigns, or none at all. For campaigns that already exist on Meta or Google, use list_entities and get_entity.

Three ideas

  • A Campaign Plan is what your organization intends to run: an envelope, a currency, a window, optionally a brand, plus the rationale for the split and how measurement will judge it. It belongs to your organization, is authored incrementally, and is approved by a person.
  • A Line Item is one row of that intent — a channel, an objective, an audience, an amount, a window. It holds only what stays constant across everything it spawns, which is why it carries no optimization goal and no campaign-tree shape.
  • An execution record is one row per provider object a Line Item created. It is written by the agent that did the creating, and it is what later answers “which of these campaigns came from row 3?”

The workflow

  1. Create the Campaign Plan

    campaign_plan_create needs a name, a one-line description and a currency. Everything else — the envelope, the window, the brand — can arrive later, because every amount written afterwards is read through that currency.

  2. Add the Line Items

    One line_item_create per intent: channel, objective, and whatever of budget, countries, age_min / age_max, gender and dates you have decided. A line with no dates inherits the Campaign Plan’s.

  3. Read it back

    campaign_plan_get returns the Line Items in full — there is no line_item_get — along with the money figures and four facts derived per line: provider, executable, the effective window, and unit. Read these back rather than assuming them.

  4. Approve, or validate one line

    campaign_plan_approve is the human act: it approves the Campaign Plan and validates every draft line on it. When only one row is ready, use line_item_validate so your approval does not reach somebody else’s half-written row.

  5. Execute with the mutation tools

    Creating the campaigns and ad sets is the ordinary write path — meta_create_campaign, meta_create_adset — against the advertiser_id on the line, and it needs the mutation:write scope.

  6. Record what you created

    After each create, call line_item_record_execution with the native id. Nothing does this for you: one line may create any number of objects and you chose the shape, so only you know which came from where.

Three money figures, not one

campaign_plan_get returns an allocation block. The numbers in it answer different questions and are allowed to disagree.

Figure What it is
totalBudget The envelope — what you have. null means no declared constraint, never zero.
allocated The sum of the Line Item budgets.
unallocated The envelope minus the allocated sum — what is still unplaced.
comparable Whether that sum means anything at all.

Warning

Amounts are integer minor units

Send 4050 for €40.50, never 40.50. A fractional amount is refused rather than rounded — rounding would silently turn €40.50 into 40 cents. The currency lives on the Campaign Plan; a Line Item carries an amount only.

Note

A mixed-unit plan has no sum

The unit is derived: a line with an effective end date holds a total for that period, one without holds a daily rate. Mix the two and comparable comes back false with unallocated: null — an envelope minus a rate is not a quantity. Say so rather than printing a total that looks right and is not.

Statuses you’ll see

On Value Meaning
Campaign Plan draft Being authored. Editable, and not approved by anyone.
Campaign Plan approved A person signed off on the content at a specific revision.
Line Item draft Not cleared to run.
Line Item validated Cleared to run — by its own validation, or by the approval that cascaded over it.

Tip

Editing reverts, and only locally

Edit a Line Item and that line returns to draft. Edit the Campaign Plan’s own fields, or add a line, and the Campaign Plan returns to draft. What has already been created on a provider is untouched — reverting a line changes your plan, never your delivery.

Before you execute

Approval is a gate on the plan, not a lock on the ad account: the Meta tools know nothing about your Campaign Plan and will happily create from a row nobody validated. Check these yourself, from the campaign_plan_get response, before you create anything:

  • The line is validated. This is the gate; walking through it is your job.
  • executable is true. A channel nobody has connected yet still plans, sums and approves — it simply cannot be built.
  • The advertiser_id is set, owned by your organization, and on the line’s provider.
  • The account currency equals the Campaign Plan’s. AdCrunch never converts — Meta reads daily_budget in the account’s currency, so a EUR plan built into a USD account creates the same number in dollars. A converted budget is a different plan.
  • The window resolves, after inheritance, and starts before it ends.
  • Send the budget in the unit the line says. total is a lifetime budget; daily is a rate.

Warning

A line that ran but was never recorded looks unrun

It is already spending while the plan says nothing came of it. Record each object as you create it, and report “3 objects created” rather than “complete” — how many objects a line should produce was never declared, so completeness is not knowable.

Scopes

Authoring needs campaign_plan:read and campaign_plan:write; recording an execution is a write on the plan, so it needs campaign_plan:write too. Actually creating campaigns needs mutation:write, granted separately.

That separation is the point: an agent can plan an entire quarter — restructure it, re-budget it, approve nothing — without being able to move a cent. See Auth & scopes.

Channels and providers

Ten channels can be planned: meta, tiktok, snapchat, google_search, google_pmax, google_display, youtube, programmatic_display, linkedin and x. Your media plan already spans them, and a planning surface that covered one would be a planning surface you kept a spreadsheet beside.

Execution is a different question, and a narrower one: executable is true for Meta today. It is derived per request from what AdCrunch can write to, never stored — as more providers come online, the same rows become executable with nothing to migrate.

Next