line_item_update
Edit a Line Item. A real change returns that Line Item to draft, and no other.
Ask the agent to change one Line Item: its channel, its objective, its money, its audience, its dates, its ad account or its persona.
“Raise the Meta Line Item of the spring sale Campaign Plan to €3,000, and add the Netherlands.”
The agent calls line_item_list to get the id and the revision of the Line Item. Then it calls line_item_update with only the fields that change. You see the Line Item as it is now. A real change returns a validated Line Item to draft. The approval of the Campaign Plan stays. A campaign that the Line Item created on Meta does not change.
The target of a Line Item changes as a pair: the agent sends target_metric and target_value together, even when only the value changes. To remove the target, it sends null for both.
The name of a Line Item is a short label of at most 60 characters. It is not unique. The agent sends name to change it. To clear it, the agent sends null or a blank name. A blank name is no name. A real change of the name returns a validated Line Item to draft, as each other field does. The agent can use the name in the name of the provider objects that it creates for the Line Item.
Plan a campaign walks the whole job.
Reference
Update a Line Item. Omit a field to leave it alone; send null to clear it. Pass base_revision from line_item_list or line_item_get: it is the revision of the Line Item, not of the Campaign Plan. The name is a short label, at most 60 characters after trimming: send a new name to set it, null or a blank string to clear it. It is not unique. The target is written as a pair: send target_metric and target_value together, or both null to clear it. Any real change returns a validated line to draft, and only that line — the plan’s own approval stands. The provider objects the line already created are untouched: a live campaign is never altered from here.
Input
| Argument | Type | Required | Description |
|---|---|---|---|
advertiser_id |
string or null | no | null unlinks the ad account. |
age_max |
integer, 0 to 120 or null | no | |
age_min |
integer, 0 to 120 or null | no | |
base_revision |
integer | yes | The revision of the Line Item, as you last read it: the revision of that Line Item in line_item_list or line_item_get. It is not the revision of the Campaign Plan. It guards against a write over a change that another person made after your read. |
budget |
number, at least 0 or null | no | |
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 |
no | |
countries |
array of (string, 2 characters) | no | The array is the value — send [] to clear the geography. |
end_date |
string or null | no | null makes the line inherit the plan’s end, which can flip its budget between a total and a daily rate. That is allowed, and it returns the line to draft. |
gender |
one of all, men, women or null |
no | |
line_item_id |
string | yes | The Line Item id, as returned by line_item_list. |
name |
string or null | no | Omit to keep the name. null or a blank string clears it. At most 60 characters after trimming. |
objective |
one of awareness, engagement, leads, sales, traffic, app_promotion |
no | |
persona_name |
string or null | no | A persona slug, looked up on the brand this plan is for; null clears it. |
start_date |
string or null | no | |
target_metric |
one of cpa, cpc, cpm, roas or null |
no | Send it with target_value: both to set the target, both null to clear it, or neither to keep it. One alone is refused with invalid_target. |
target_value |
number or null | no |
Output
A successful call returns this object in structuredContent.
| Field | Type | Always present | Description |
|---|---|---|---|
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. The entity tools, such as list_campaigns and get_ad, 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[].mutationId |
string or null | yes | The mutationId 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.name |
string or null | yes | A short label of the Line Item, at most 60 characters, or null for no name. It is not unique, and it is not a handle: nothing looks a Line Item up by it. |
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 or line_item_delete. |
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 validated the Line Item in the AdCrunch console, alone or with the approval of the Campaign Plan. It is a record, not a gate: the provider write tools do not check it. A real change to the Line Item returns it to draft. |
lineItem.targetMetric |
one of cpa, cpc, cpm, roas or null |
yes | The metric of the target, or null for no target. cpa, cpc and cpm are costs: lower is better. roas is a return: higher is better. A target blocks nothing: approval and readiness do not read it. |
lineItem.targetValue |
number or null | yes | The value of the target: whole units of the currency of the Campaign Plan for cpa, cpc and cpm, a ratio for roas. null for no target. |
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_windowinvalid_targetinvalid_namepersona_not_in_brandadvertiser_not_ownedrevision_mismatchorganization_unentitledforbiddeninvalid_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:
{
"base_revision": 2,
"budget": 3000,
"campaign_plan_name": "spring-sale",
"countries": [
"FR",
"BE",
"NL"
],
"line_item_id": "lni_2d9e77",
"name": "France, Belgium and Netherlands"
}
The result, in structuredContent:
{
"lineItem": {
"advertiserId": "acc_1203456789012345",
"ageMax": 44,
"ageMin": 25,
"budget": 3000,
"campaignPlanId": "cpl_4e1a08",
"channel": "meta",
"countries": [
"FR",
"BE",
"NL"
],
"createdAt": 1768435200000,
"createdBy": "usr_5d2b71",
"effectiveEndDate": "2026-05-31",
"effectiveStartDate": "2026-03-01",
"endDate": null,
"executable": true,
"executions": [],
"gender": "all",
"id": "lni_2d9e77",
"name": "France, Belgium and Netherlands",
"objective": "sales",
"personaId": "psn_8c4a20",
"provider": "meta",
"revision": 3,
"startDate": null,
"status": "draft",
"targetMetric": "cpa",
"targetValue": 24.5,
"unit": "total",
"updatedAt": 1769644800000
}
}