campaign_plan_delivery
Read what each Line Item of a Campaign Plan delivered: its spend and results, its pacing against its budget, and its target.
Ask the agent how a Campaign Plan runs against what you planned. The agent adds up the insights of the objects that each Line Item recorded, so you do not compare figures by hand.
“How is the spring sale Campaign Plan pacing? Does the Meta Line Item meet its CPA target?”
The agent calls campaign_plan_delivery. For each Line Item, the answer gives:
- The sums of spend, impressions, clicks, conversions and conversion value, from the start date that applies to today, or to the end date when it is in the past. AdCrunch calculates the CPA, the CPC, the CPM and the ROAS from these sums.
- The pacing: the spend against the spend that the budget expects by today. A total budget spreads over its dates, day by day. A daily budget is the rate times the days. The pacing is a ratio, such as
0.8. AdCrunch does not say “under” or “over”: you decide what is too low or too high. - The target against the same metric, delivered, and whether the Line Item meets it.
- The last day that the sums include. AdCrunch reads the insights once a day, and conversions keep arriving after the click.
AdCrunch counts each object once: a campaign holds the spend of its ad sets, so an ad set recorded with its campaign does not add its spend again. A Line Item that recorded no object answers “nothing recorded”, not a spend of 0. AdCrunch never converts a currency: when an object spends in another currency, the money of its Line Item is “not comparable”.
The token must hold campaign_plan:read and observe:read.
Plan a campaign walks the whole job.
Reference
Read what each Line Item of a Campaign Plan delivered: the sums of the provider objects that it recorded with line_item_record_execution, its pacing against its budget, and its target against the delivered value. It reads the insights that AdCrunch stores. It changes nothing and calls no provider. The sums start at the start date that applies, and they stop today, or at the end date that applies when it is in the past. asOf is the last day that the sums include: AdCrunch reads the insights once a day, and conversions keep arriving after the click. A Line Item with status nothing_recorded records no object: that is not a spend of 0. no_data_yet means that AdCrunch has no insight of its objects yet, and noDataYet names each object with no insight. advertiserNotOwned names each object in an ad account that this organization no longer owns: AdCrunch reads no insight of it. A campaign holds the spend of its ad sets, so an object with a recorded ancestor is not counted again. cpa, cpc, cpm and roas come from the sums. Money is in whole units of the currency of the Campaign Plan. AdCrunch never converts a currency: when an object spends in another currency, comparable is false and each money figure is null. pacing.ratio is spend divided by the spend that the budget expects by today. It is a ratio, not a verdict: decide with the user what is too low or too high. total reads the objects of all the Line Items over the window of the Campaign Plan, and counts each object once: when two Line Items record one object, or a campaign and an ad set inside it, the money counts once. So total can be less than the sum of the Line Items. total is not comparable when the Line Items do not share a unit, or when an object spends in another currency. A Campaign Plan is AdCrunch’s own planning document — it is not a campaign on Meta or Google. For those, use list_campaigns and get_campaign.
Input
| Argument | Type | Required | Description |
|---|---|---|---|
campaign_plan_name |
string | yes | The Campaign Plan slug — its stable per-organization handle. |
Output
A successful call returns this object in structuredContent.
| Field | Type | Always present | Description |
|---|---|---|---|
campaignPlanId |
string | yes | The Campaign Plan, cpl_…. |
currency |
string | yes | The currency of the Campaign Plan, ISO 4217. |
lineItems |
array of object | yes | The delivery of each Line Item. |
lineItems[].advertiserNotOwned |
array of object | yes | The recorded objects in an ad account that this organization no longer owns. AdCrunch reads no insight of them. |
lineItems[].advertiserNotOwned[].entityId |
string | yes | The native provider id. |
lineItems[].advertiserNotOwned[].entityType |
string | yes | The provider word for the level: campaign, adset, ad. |
lineItems[].advertiserNotOwned[].provider |
one of meta, gads, tiktok, x, openai, snapchat, dv360 |
yes | |
lineItems[].asOf |
string or null | yes | The most recent day that the sums include. AdCrunch reads the insights once a day, and conversions keep arriving after the click. |
lineItems[].budget |
number or null | yes | The budget of the Line Item, in whole units of the Campaign Plan currency. |
lineItems[].channel |
one of meta, tiktok, snapchat, google_search, google_pmax, google_display, youtube, programmatic_display, linkedin, x |
yes | |
lineItems[].counted |
array of object | yes | The recorded objects that the sums count: each one with no recorded ancestor. A campaign holds the spend of its ad sets, so an ad set recorded with its campaign is not counted twice. |
lineItems[].counted[].entityId |
string | yes | The native provider id. |
lineItems[].counted[].entityType |
string | yes | The provider word for the level: campaign, adset, ad. |
lineItems[].counted[].provider |
one of meta, gads, tiktok, x, openai, snapchat, dv360 |
yes | |
lineItems[].delivered |
object or null | yes | The sums. null unless status is delivered. |
lineItems[].delivered.clicks |
number | yes | The sum of the clicks. |
lineItems[].delivered.comparable |
boolean | yes | Whether the money is in the currency of the Campaign Plan. false when an object spent in another currency: each money figure is then null. |
lineItems[].delivered.conversionValue |
number or null | yes | The sum of the conversion value, in whole units of the Campaign Plan currency. null when comparable is false: AdCrunch never converts a currency. |
lineItems[].delivered.conversions |
number | yes | The sum of the conversions. |
lineItems[].delivered.cpa |
number or null | yes | spend / conversions, from the sums, in whole units of the Campaign Plan currency. null when the divisor is 0, or when comparable is false. |
lineItems[].delivered.cpc |
number or null | yes | spend / clicks, from the sums, in whole units of the Campaign Plan currency. null when the divisor is 0, or when comparable is false. |
lineItems[].delivered.cpm |
number or null | yes | spend × 1000 / impressions, from the sums, in whole units of the Campaign Plan currency. null when the divisor is 0, or when comparable is false. |
lineItems[].delivered.currencies |
array of string or null | yes | The account currencies of the counted objects. null is a currency that AdCrunch does not know. |
lineItems[].delivered.impressions |
number | yes | The sum of the impressions. |
lineItems[].delivered.roas |
number or null | yes | conversionValue / spend, from the sums, with two decimals. It needs one account currency, not the currency of the Campaign Plan. null when the spend is 0. |
lineItems[].delivered.spend |
number or null | yes | The sum of the spend, in whole units of the Campaign Plan currency. null when comparable is false: AdCrunch never converts a currency. |
lineItems[].lineItemId |
string | yes | The Line Item, lni_…. |
lineItems[].noDataYet |
array of object | yes | The recorded objects that have no insight in the window yet. They are not a spend of 0. |
lineItems[].noDataYet[].entityId |
string | yes | The native provider id. |
lineItems[].noDataYet[].entityType |
string | yes | The provider word for the level: campaign, adset, ad. |
lineItems[].noDataYet[].provider |
one of meta, gads, tiktok, x, openai, snapchat, dv360 |
yes | |
lineItems[].pacing |
object or null | yes | null with no budget, or with no start date that applies. |
lineItems[].pacing.elapsedDays |
number | yes | The days of the window up to today, today included. 0 before the start. |
lineItems[].pacing.expectedSpend |
number | yes | The spend that the budget expects by today, in whole units of the Campaign Plan currency. A total budget: budget × elapsed days / window days. A daily budget: budget × elapsed days. |
lineItems[].pacing.ratio |
number or null | yes | spend / expectedSpend, with two decimals. null when the expected spend is 0, or when the spend is not known or not comparable. A ratio, not a verdict: decide with the user what is too low or too high. |
lineItems[].pacing.windowDays |
number or null | yes | The days of the window of a total budget. null for a daily budget. |
lineItems[].since |
string or null | yes | The first day that the sums read: the start that applies. null reads from the first day. |
lineItems[].status |
one of nothing_recorded, no_data_yet, delivered |
yes | nothing_recorded: the Line Item records no object, which is not a spend of 0. no_data_yet: it records objects, and AdCrunch has no insight of them in the window. delivered: the sums of the counted objects. |
lineItems[].target |
object or null | yes | null when the Line Item has no target. |
lineItems[].target.delivered |
number or null | yes | The delivered value of the metric, or null when it is not a number. |
lineItems[].target.direction |
one of ceiling, floor |
yes | ceiling: a value at or below the target meets it (a cost). floor: a value at or above it meets it (a return). |
lineItems[].target.met |
boolean or null | yes | Whether the delivered value meets the target. null when the delivered value is null. |
lineItems[].target.metric |
one of cpa, cpc, cpm, roas |
yes | The metric. |
lineItems[].target.value |
number | yes | The target: whole units of the Campaign Plan currency for cpa, cpc and cpm, a plain ratio for roas. |
lineItems[].unit |
one of total, daily |
yes | How to read budget: total for the whole window, daily for each day. |
lineItems[].until |
string | yes | The last day that the sums read: today, or the end that applies when it is in the past. |
slug |
string | yes | The handle of the Campaign Plan. |
today |
string | yes | The day that the pacing counts to, UTC. |
total |
object or null | yes | null when no Line Item delivered in the window of the Campaign Plan. |
total.comparable |
true or false |
yes | false: The Line Items do not share one unit, or an object spent in another currency than the Campaign Plan, so there is no total to state: say “not comparable”. |
total.asOf |
string | yes | Only when comparable is true. The most recent day that the sums include. |
total.counted |
array of object | yes | Only when comparable is true. The objects that the total counts: across all the Line Items, each one once, and only when no other recorded object is its ancestor. |
total.counted[].entityId |
string | yes | The native provider id. |
total.counted[].entityType |
string | yes | The provider word for the level: campaign, adset, ad. |
total.counted[].provider |
one of meta, gads, tiktok, x, openai, snapchat, dv360 |
yes | |
total.since |
string or null | yes | Only when comparable is true. The first day that the total reads: the start of the Campaign Plan. null reads from the first day. |
total.until |
string | yes | Only when comparable is true. The last day that the total reads: today, or the end of the Campaign Plan when it is in the past. |
total.delivered |
object | yes | Only when comparable is true. The sums of the counted objects. Each metric comes from the sums, never from a mean of the days. |
total.delivered.clicks |
number | yes | The sum of the clicks. |
total.delivered.comparable |
boolean | yes | Whether the money is in the currency of the Campaign Plan. false when an object spent in another currency: each money figure is then null. |
total.delivered.conversionValue |
number or null | yes | The sum of the conversion value, in whole units of the Campaign Plan currency. null when comparable is false: AdCrunch never converts a currency. |
total.delivered.conversions |
number | yes | The sum of the conversions. |
total.delivered.cpa |
number or null | yes | spend / conversions, from the sums, in whole units of the Campaign Plan currency. null when the divisor is 0, or when comparable is false. |
total.delivered.cpc |
number or null | yes | spend / clicks, from the sums, in whole units of the Campaign Plan currency. null when the divisor is 0, or when comparable is false. |
total.delivered.cpm |
number or null | yes | spend × 1000 / impressions, from the sums, in whole units of the Campaign Plan currency. null when the divisor is 0, or when comparable is false. |
total.delivered.currencies |
array of string or null | yes | The account currencies of the counted objects. null is a currency that AdCrunch does not know. |
total.delivered.impressions |
number | yes | The sum of the impressions. |
total.delivered.roas |
number or null | yes | conversionValue / spend, from the sums, with two decimals. It needs one account currency, not the currency of the Campaign Plan. null when the spend is 0. |
total.delivered.spend |
number or null | yes | The sum of the spend, in whole units of the Campaign Plan currency. null when comparable is false: AdCrunch never converts a currency. |
total.asOf |
string | yes | Only when comparable is false. The most recent day that the sums include. |
total.counted |
array of object | yes | Only when comparable is false. The objects that the total counts: across all the Line Items, each one once, and only when no other recorded object is its ancestor. |
total.counted[].entityId |
string | yes | The native provider id. |
total.counted[].entityType |
string | yes | The provider word for the level: campaign, adset, ad. |
total.counted[].provider |
one of meta, gads, tiktok, x, openai, snapchat, dv360 |
yes | |
total.since |
string or null | yes | Only when comparable is false. The first day that the total reads: the start of the Campaign Plan. null reads from the first day. |
total.until |
string | yes | Only when comparable is false. The last day that the total reads: today, or the end of the Campaign Plan when it is in the past. |
total.delivered |
null | yes | Only when comparable is false. |
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_foundorganization_unentitledforbiddeninvalid_requestinternal_error
Scope
The token must hold campaign_plan:read and observe:read. 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.
- Read-only. The tool changes nothing.
- Closed world. The tool reads and writes the data of AdCrunch only.
Example
The arguments:
{
"campaign_plan_name": "spring-sale"
}
The result, in structuredContent:
{
"campaignPlanId": "cpl_8f2k1m",
"currency": "EUR",
"lineItems": [
{
"advertiserNotOwned": [],
"asOf": "2026-03-09",
"budget": 3100,
"channel": "meta",
"counted": [
{
"entityId": "120210000000000",
"entityType": "campaign",
"provider": "meta"
}
],
"delivered": {
"clicks": 1600,
"comparable": true,
"conversionValue": 2400,
"conversions": 40,
"cpa": 20,
"cpc": 0.5,
"cpm": 10,
"currencies": [
"EUR"
],
"impressions": 80000,
"roas": 3,
"spend": 800
},
"lineItemId": "lni_2d9e77",
"noDataYet": [],
"pacing": {
"elapsedDays": 10,
"expectedSpend": 1000,
"ratio": 0.8,
"windowDays": 31
},
"since": "2026-03-01",
"status": "delivered",
"target": {
"delivered": 20,
"direction": "ceiling",
"met": true,
"metric": "cpa",
"value": 25
},
"unit": "total",
"until": "2026-03-10"
}
],
"slug": "spring-sale",
"today": "2026-03-10",
"total": {
"asOf": "2026-03-09",
"comparable": true,
"counted": [
{
"entityId": "120210000000000",
"entityType": "campaign",
"provider": "meta"
}
],
"delivered": {
"clicks": 1600,
"comparable": true,
"conversionValue": 2400,
"conversions": 40,
"cpa": 20,
"cpc": 0.5,
"cpm": 10,
"currencies": [
"EUR"
],
"impressions": 80000,
"roas": 3,
"spend": 800
},
"since": "2026-03-01",
"until": "2026-03-10"
}
}