---
title: line_item_validate
description: 'Validate one Line Item, so that the agent can build it.'
---

Ask the agent to validate one Line Item when that Line Item is ready and the rest of the Campaign Plan is not.

> "The Meta Line Item of the spring sale Campaign Plan is ready. Validate only that Line Item."

The agent reads the Campaign Plan to get the id and the revision of the Line Item. Then it calls `line_item_validate`. You see the Line Item as validated. The other Line Items and the status of the Campaign Plan do not change. A validation changes nothing on Meta: to build the Line Item, the agent uses the Meta tools.

[Plan a campaign](/mcp/tools/plan-a-campaign) walks the whole job.

## Reference

Validate one Line Item, which is what lets it be executed. Use this instead of campaign_plan_approve when one line is ready and the rest of the plan is not — approving cascades over every draft line, which would apply your approval to somebody else's half-written row. This changes nothing on any provider; executing still needs the mutation tools and the mutation:write scope.

### Input

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `base_revision` | integer | yes | The revision of the Line Item, as you last read it: the `revision` of that Line Item in `lineItems` of campaign_plan_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. |
| `campaign_plan_name` | string | yes | The Campaign Plan slug — its stable per-organization handle. |
| `line_item_id` | string | yes | The Line Item id, as returned by campaign_plan_get. |

### 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. `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](/mcp/errors) describes the shape of a failed call.

- `not_found`
- `revision_mismatch`
- `forbidden`
- `invalid_request`
- `internal_error`

### Scope

The token must hold `campaign_plan:write`. [Auth & scopes](/mcp/auth) 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.
- **Idempotent.** A second call with the same arguments changes nothing more.
- **Closed world.** The tool reads and writes the data of AdCrunch only.

### Example

The arguments:

```json
{
  "base_revision": 1,
  "campaign_plan_name": "spring-sale",
  "line_item_id": "lni_2d9e77"
}
```

The result, in `structuredContent`:

```json
{
  "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": 2,
    "startDate": null,
    "status": "validated",
    "unit": "total",
    "updatedAt": 1769040000000
  }
}
```
