Campaign Plans

Approve a Campaign Plan

Approves a Campaign Plan and validates its draft Line Items. This opens the gate for execution: AdCrunch executes a line only after somebody validates it.

This call blocks on nothing. You can approve a Campaign Plan with no budget, with more allocated than the envelope, or with parts missing. Approval is the human act, and execution makes its own checks.

This call creates nothing and spends nothing. To execute a line, use the mutation tools with the mutation:write permission.

This call moves the revision of the Campaign Plan, and the revision of each Line Item it validates. Read the Campaign Plan again before your next guarded write.

A line that you add after the approval starts in draft, and it puts the Campaign Plan back into draft. The answer is 409 with error=revision_mismatch if the Campaign Plan changed after you read it.

post/context/campaign-plans/{slug}/approve

Request

  • Base URL: https://api.adcrunch.dev
  • URL: https://api.adcrunch.dev/context/campaign-plans/{slug}/approve
  • Auth: HTTP bearer

Path parameters

slugstring required

Request body

base_revisioninteger required

The revision last read via GET. This is what makes it an approval of the content that was read, rather than of whatever the row holds now.

Example request

{
  "base_revision": 2
}

Response

The approved plan, and how many Line Items this call validated. A line that was already validated is not counted. Approving spends nothing and creates nothing — it opens the execution gate, and executing goes through the mutation tools on mutation:write.

lineItemsValidatednumber required

How many draft Line Items this approval moved to validated. Zero when they were all validated already.

Example response

{
  "campaignPlan": {
    "allocation": {
      "allocated": 2500,
      "comparable": true,
      "unallocated": 2500,
      "unit": "total"
    },
    "brandId": "brd_6a9c33",
    "createdAt": 1768435200000,
    "createdBy": "usr_5d2b71",
    "currency": "EUR",
    "description": "The spring sale of Acme, on Meta, in France and Belgium.",
    "endDate": "2026-05-31",
    "id": "cpl_4e1a08",
    "lineItems": [
      {
        "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": [
          {
            "advertiserId": "acc_1203456789012345",
            "createdAt": 1772409600000,
            "entityId": "120210000000000",
            "entityType": "campaign",
            "id": "exe_7a4c12",
            "mutationWorkflowId": "b3d1f0c4-6a2e-4a1f-9f77-2c0d1e5a8b94",
            "provider": "meta"
          }
        ],
        "gender": "all",
        "id": "lni_2d9e77",
        "objective": "sales",
        "personaId": "psn_8c4a20",
        "provider": "meta",
        "revision": 2,
        "startDate": null,
        "status": "validated",
        "unit": "total",
        "updatedAt": 1769040000000
      }
    ],
    "measurement": "Revenue in the window, against the spring of 2025.",
    "name": "Spring Sale 2026",
    "rationale": "Meta carries the reach. One Line Item keeps the budget in one place.",
    "revision": 3,
    "slug": "spring-sale",
    "startDate": "2026-03-01",
    "status": "approved",
    "totalBudget": 5000,
    "updatedAt": 1769040000000
  },
  "lineItemsValidated": 1
}

Changes

No recorded changes to this operation across all 1 revision of this API.