Skip to main content

Overview

Pacing periods let you express a non-flat campaign flight as a sequence of dated periods, each with its own spend intensity. Use them when a campaign needs to spend more during a holiday window, less during a quiet stretch, or explicit dollar amounts in specific months. When a campaign with pacing periods executes, every selected product is automatically split into one package per period, with budget allocated according to the schedule. The campaign-level pacing schedule is the source of truth — you do not have to compute or set per-package budgets yourself.

Weight mode

Express each period as a relative multiplier (1.0 = normal, 2.5 = 150% heavier). Scope3 distributes the campaign budget proportionally by days × weight.

Budget mode

Set explicit dollar amounts per period. Useful when finance hands you a monthly spend plan you must hit exactly.

Concept

A pacingPeriods object has two fields:
FieldDescription
mode"weight" or "budget"
periods[]Ordered, non-overlapping list of dated periods
Each period has:
FieldRequired whenDescription
labelAlwaysHuman-readable name (e.g. "Memorial Day Heavy-Up")
startAlwaysInclusive YYYY-MM-DD start date
endAlwaysInclusive YYYY-MM-DD end date
weightmode = "weight"Positive number ≤ 10 (relative intensity)
budgetmode = "budget"Positive dollar amount
Periods must be inside the campaign flight dates and must not overlap. Gaps between periods are allowed and are treated as pauses — the campaign spends $0 during a gap.

How to use

Weight mode

Weight mode is the most common: declare the shape, let Scope3 do the math.
curl -X POST 'https://api.agentic.scope3.com/api/buyer/campaigns' \
  -H 'Authorization: Bearer scope3_<your_api_key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "advertiserId": "12345",
    "name": "Summer 2026",
    "flightDates": { "startDate": "2026-06-01T00:00:00Z", "endDate": "2026-08-31T23:59:59Z" },
    "budget": { "total": 300000, "currency": "USD" },
    "pacingPeriods": {
      "mode": "weight",
      "periods": [
        { "label": "June ramp",       "start": "2026-06-01", "end": "2026-06-30", "weight": 1.0 },
        { "label": "July 4th heavy",  "start": "2026-07-01", "end": "2026-07-15", "weight": 2.5 },
        { "label": "Mid-summer cool", "start": "2026-07-16", "end": "2026-08-15", "weight": 0.5 },
        { "label": "Back to school",  "start": "2026-08-16", "end": "2026-08-31", "weight": 1.5 }
      ]
    }
  }'
When the campaign executes, each product is split four ways with budget proportional to days × weight.

Budget mode

Budget mode pins explicit dollars to each period. The sum of period budgets must not exceed budget.total on the campaign — anything left over stays as unallocated headroom.
curl -X POST 'https://api.agentic.scope3.com/api/buyer/campaigns' \
  -H 'Authorization: Bearer scope3_<your_api_key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "advertiserId": "12345",
    "name": "Q3 Plan",
    "flightDates": { "startDate": "2026-07-01T00:00:00Z", "endDate": "2026-09-30T23:59:59Z" },
    "budget": { "total": 150000, "currency": "USD" },
    "pacingPeriods": {
      "mode": "budget",
      "periods": [
        { "label": "July",      "start": "2026-07-01", "end": "2026-07-31", "budget": 60000 },
        { "label": "August",    "start": "2026-08-01", "end": "2026-08-31", "budget": 60000 },
        { "label": "September", "start": "2026-09-01", "end": "2026-09-30", "budget": 30000 }
      ]
    }
  }'

Updating a schedule

PUT /api/buyer/campaigns/:id accepts the full pacingPeriods object. To clear an existing schedule, send "pacingPeriods": null.
curl -X PUT 'https://api.agentic.scope3.com/api/buyer/campaigns/cmp_987654321' \
  -H 'Authorization: Bearer scope3_<your_api_key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "pacingPeriods": {
      "mode": "weight",
      "periods": [
        { "label": "June ramp",      "start": "2026-06-01", "end": "2026-06-30", "weight": 1.0 },
        { "label": "July 4th heavy", "start": "2026-07-01", "end": "2026-07-15", "weight": 3.0 },
        { "label": "Mid-summer cool","start": "2026-07-16", "end": "2026-08-15", "weight": 0.5 },
        { "label": "Back to school", "start": "2026-08-16", "end": "2026-08-31", "weight": 1.5 }
      ]
    }
  }'
Periods that have already started or ended cannot be modified or removed. Updates may only change future periods. Changing the mode is rejected if any existing period is already in progress or past.

Response shape

Campaign GET responses surface the schedule with resolved budgets for every period. In weight mode, the resolved dollar amount is computed by (days × weight) proportional split of budget.total; weights are preserved alongside the resolved budget so you can audit the math.
{
  "campaign": {
    "id": "cmp_987654321",
    "budget": { "total": 300000, "currency": "USD" },
    "allocatedBudget": 240000,
    "unallocatedBudget": 60000,
    "pacingPeriods": {
      "mode": "weight",
      "periods": [
        { "label": "June ramp",       "start": "2026-06-01", "end": "2026-06-30", "weight": 1.0, "budget": 60000 },
        { "label": "July 4th heavy",  "start": "2026-07-01", "end": "2026-07-15", "weight": 2.5, "budget": 75000 },
        { "label": "Mid-summer cool", "start": "2026-07-16", "end": "2026-08-15", "weight": 0.5, "budget": 31000 },
        { "label": "Back to school",  "start": "2026-08-16", "end": "2026-08-31", "weight": 1.5, "budget": 74000 }
      ]
    }
  }
}
unallocatedBudget is the dollar gap between mediaBudget.total and the sum of active media buy budgets — it tells you how much room is left for new media buys to fill the schedule.

Automatic package splitting

When a campaign with pacing periods executes:
1

Resolve per-product budgets

Each selected product gets a budget — either set by the user or derived from a discovery proposal.
2

Split per period

For every product, Scope3 creates one package per pacing period. In weight mode, the per-period budget is (days × weight) / sum(all weighted days) × product_budget. In budget mode, each period’s fixed budget is split across products proportionally to each product’s share of total product budgets.
3

Round to last

Each period after the first uses banker’s rounding to two decimals; the last period absorbs any rounding remainder so per-product totals match exactly.
4

Submit to sales agent

The split packages are sent to the sales agent as the media buy composition. Each package carries its own start, end, and budget.
This means a campaign with 10 products and 4 periods produces 40 packages on execution, each one a discrete dated bucket of spend.

Validation

The campaign endpoints validate pacingPeriods against the campaign before saving:
  • Date order: every period’s start must be ≤ end.
  • Inside flight: every period must lie within flightDates.startDate and flightDates.endDate.
  • No overlaps: when sorted by start, no period may begin on or before the previous period’s end.
  • Budget sum (budget mode): the sum of period budgets must not exceed budget.total.
  • Required fields per mode: weight periods need a weight; budget periods need a budget.
  • Update safety: a period that has already started cannot be changed or removed; the mode cannot change while any period is in progress or past.
A failing validation returns a 400 with a clear error message identifying the offending period by label.

Best practices

  • Start in weight mode. It’s easier to reason about “2× during the holiday week” than to recompute exact dollar splits when the budget moves.
  • Use labels generously. Period labels show up in package metadata and in reporting — names like "July 4th heavy" beat "Period 2".
  • Keep periods aligned with media buy intent. A media buy can have any start/end inside the campaign flight, but matching its dates to a period boundary keeps reporting clean.
  • Treat gaps as pauses. If you don’t want spend on July 16–18, leave that range out of periods rather than setting weight: 0 (which is rejected as non-positive).
  • Plan ahead — past periods are immutable. Once a period starts, its shape is locked. Front-load decisions you might need to revisit.
  • Cap period count. The schema allows up to 52 periods; in practice, monthly or weekly granularity is plenty.

Limits

LimitValue
Periods per campaign1–52
weight range(0, 10]
budget per periodPositive dollar amount
budget sum (budget mode)budget.total
Max label length100 characters
Date formatYYYY-MM-DD (UTC, inclusive on both ends)