line_item_create
Add a Line Item to a Campaign Plan: one thing that you buy, with the limits of an intent.
Ask the agent to add one thing that you buy to a Campaign Plan: a channel, an objective, and the money, the audience and the dates that you know.
“Add a Line Item to the spring sale Campaign Plan: Meta, for sales, €2,500, in France and Belgium, ages 25 to 44.”
The agent calls line_item_create. You see the new Line Item as a draft. You also see if AdCrunch can build it today, and if its budget is a total for the period or a rate for each day. A Line Item with no dates of its own uses the dates of the Campaign Plan. When the Campaign Plan was approved, the new Line Item returns it to draft.
Plan a campaign walks the whole job.
Reference
Add a Line Item to a Campaign Plan: one thing being bought, coarser than an ad set and deliberately not one-to-one with a campaign. It carries the envelope of an intent, never an execution script — one line may create any number of provider objects, and it holds only what is constant across all of them, which is why there is no optimization goal here. Only the channel and the objective are required. The budget is in whole units of the plan’s currency, and whether it reads as a total or a daily rate follows from the effective end date. A persona explains the audience; the countries, age range and gender are what actually execute. Adding a line returns an approved plan to draft.
Input
| Argument | Type | Required | Description |
|---|---|---|---|
advertiser_id |
string | no | The ad account, from list_advertisers. It sits on a Line Item rather than the plan because an account belongs to one provider, while a plan spans channels. |
age_max |
integer, 0 to 120 | no | |
age_min |
integer, 0 to 120 | no | |
budget |
number, at least 0 | no | Whole units of the plan’s currency (40.5 is 40.50). Whether it reads as a total or a daily rate follows from the effective end date — never send a unit. |
campaign_plan_name |
string | yes | The Campaign Plan slug — its stable per-organization handle. |
channel |
one of meta, tiktok, snapchat, google_search, google_pmax, google_display, youtube, programmatic_display, linkedin, x |
yes | What is being bought, in planning vocabulary rather than provider names. Only meta can be executed today; the rest are authorable and inert. |
countries |
array of (string, 2 characters) | no | ISO 3166-1 alpha-2 codes, e.g. [“FR”, “BE”]. An empty list is a normal drafting state. |
end_date |
string | no | Omit to inherit the plan’s. Present — here or inherited — makes the budget a total for the period; absent makes it a daily rate. |
gender |
one of all, men, women |
no | Omit for undecided, which executes the same as “all”. |
objective |
one of awareness, engagement, leads, sales, traffic, app_promotion |
yes | |
persona_name |
string | no | A persona slug. It is looked up on the brand this plan is for — a Line Item may only name one of those — so there is no brand to pass. It explains the audience for whoever reads the plan; the countries, age range and gender above are what actually execute. |
start_date |
string | no | Omit to inherit the plan’s. |
Output
A successful call returns this object in structuredContent.
| Field | Type | Always present | Description |
|---|---|---|---|
campaignPlanStatus |
one of draft, approved |
yes | The status of the Campaign Plan after the write. It is always draft, because a Line Item that is added or deleted returns an approved Campaign Plan to draft. |
lineItem |
object | yes | A Line Item: one thing that the Campaign Plan buys. |
lineItem.advertiserId |
string or null | yes | The ad account that the Line Item runs through, acc_…, or null. |
lineItem.ageMax |
number or null | yes | The highest age, or null for no upper bound. |
lineItem.ageMin |
number or null | yes | The lowest age, or null for no lower bound. |
lineItem.budget |
number or null | yes | The amount in whole units of the currency of the Campaign Plan, or null when it is not set. unit tells how to read it. |
lineItem.campaignPlanId |
string | yes | The id of the Campaign Plan that holds the Line Item, cpl_…. |
lineItem.channel |
one of meta, tiktok, snapchat, google_search, google_pmax, google_display, youtube, programmatic_display, linkedin, x |
yes | What the Line Item buys, in planning words. A channel is not a provider. |
lineItem.countries |
array of string | yes | ISO 3166-1 alpha-2 codes. An empty list means that the geography is not decided. |
lineItem.createdAt |
number | yes | Milliseconds since the Unix epoch, UTC. |
lineItem.createdBy |
string | yes | The user who added the Line Item, usr_…. |
lineItem.effectiveEndDate |
string or null | yes | The end that applies: the end date of the Line Item, else the end date of the Campaign Plan. null when neither has one. |
lineItem.effectiveStartDate |
string or null | yes | The start that applies: the start date of the Line Item, else the start date of the Campaign Plan. null when neither has one. |
lineItem.endDate |
string or null | yes | The end date of the Line Item itself, or null when the Line Item uses the end date of the Campaign Plan. |
lineItem.executable |
boolean | yes | true when AdCrunch can create objects for this channel today. It is not a promise that a create succeeds. |
lineItem.executions |
array of object | yes | The provider objects that the Line Item created, as line_item_record_execution recorded them. The list does not tell whether the Line Item is complete. |
lineItem.executions[].advertiserId |
string | yes | The ad account that holds the object, acc_…. |
lineItem.executions[].createdAt |
number | yes | When AdCrunch recorded the object, in milliseconds since the Unix epoch, UTC. |
lineItem.executions[].entityId |
string | yes | The id of the object on the provider, with no prefix. get_entity and list_entities use the same id. |
lineItem.executions[].entityType |
string | yes | The word of the provider for the level of the object, such as campaign, adset or ad. |
lineItem.executions[].id |
string | yes | The id of the record, exe_…. |
lineItem.executions[].mutationWorkflowId |
string or null | yes | The workflowId of the change that created the object, or null when the record names none. |
lineItem.executions[].provider |
one of meta, gads, tiktok, x, openai, snapchat, dv360 |
yes | The provider of the object. |
lineItem.gender |
one of all, men, women or null |
yes | The gender of the audience, or null when it is not decided. null executes as all. |
lineItem.id |
string | yes | The id of the Line Item, lni_…. |
lineItem.objective |
one of awareness, engagement, leads, sales, traffic, app_promotion |
yes | What the Line Item is for. |
lineItem.personaId |
string or null | yes | The Persona that explains the audience, psn_…, or null. The countries, the ages and the gender are what execute. |
lineItem.provider |
one of meta, gads, tiktok, x, openai, snapchat, dv360 or null |
yes | The provider that sells the channel, or null when AdCrunch has no integration for it. |
lineItem.revision |
number | yes | The revision of the Line Item. It increments when the Line Item changes. Send it as base_revision to line_item_update, line_item_delete or line_item_validate. |
lineItem.startDate |
string or null | yes | The start date of the Line Item itself, or null when the Line Item uses the start date of the Campaign Plan. |
lineItem.status |
one of draft, validated |
yes | validated when a person cleared the Line Item to run, by line_item_validate or by the approval of the Campaign Plan. A real change to the Line Item returns it to draft. |
lineItem.unit |
one of total, daily |
yes | How to read budget. total when the Line Item has an effective end date: the budget is for the whole period. daily when it has none: the budget is for each day. |
lineItem.updatedAt |
number or null | yes | When the Line Item last changed, or null when it never changed. |
Failure codes
A failed call has isError set, and structuredContent.error holds one of these codes. Errors describes the shape of a failed call.
not_foundinvalid_countriesinvalid_age_rangeinvalid_amountinvalid_windowpersona_not_in_brandadvertiser_not_ownedforbiddeninvalid_requestinternal_error
Scope
The token must hold campaign_plan:write. Auth & scopes lists each scope.
Annotations
A client reads these hints. A hint that the tool does not declare has the default value of the MCP specification.
- Writes. The tool can change data.
- Destructive. The tool can make a change that you cannot undo. A client can ask you to confirm before it calls the tool.
- Not idempotent. A second call with the same arguments can change more.
- Closed world. The tool reads and writes the data of AdCrunch only.
Example
The arguments:
{
"advertiser_id": "acc_1203456789012345",
"age_max": 44,
"age_min": 25,
"budget": 2500,
"campaign_plan_name": "spring-sale",
"channel": "meta",
"countries": [
"FR",
"BE"
],
"gender": "all",
"objective": "sales",
"persona_name": "young-parents"
}
The result, in structuredContent:
{
"campaignPlanStatus": "draft",
"lineItem": {
"advertiserId": "acc_1203456789012345",
"ageMax": 44,
"ageMin": 25,
"budget": 2500,
"campaignPlanId": "cpl_4e1a08",
"channel": "meta",
"countries": [
"FR",
"BE"
],
"createdAt": 1768435200000,
"createdBy": "usr_5d2b71",
"effectiveEndDate": "2026-05-31",
"effectiveStartDate": "2026-03-01",
"endDate": null,
"executable": true,
"executions": [],
"gender": "all",
"id": "lni_2d9e77",
"objective": "sales",
"personaId": "psn_8c4a20",
"provider": "meta",
"revision": 1,
"startDate": null,
"status": "draft",
"unit": "total",
"updatedAt": null
}
}