Skip to content

Campaign.update

Pause a Campaign, or change its budget or end date, in one call.

Action class
spend
Approval
Asks above your rule
Emits
Campaign.updated
Price
Free
POST https://api.sb/{your-domain}/campaigns/update

Pauses a Campaign, or changes its budget, bid or end date on your ad account, inside your standing approval. This Verb is a sketch on the hub’s Campaign Noun.

Inputs

NameTypeDefaultMeaning
campaignCampaignRequiredThe Campaign to change.
state'live' | 'paused' | 'ended'nullpaused stops delivery and keeps every Ad; ended closes it for good. Unset: unchanged.
budgetmoneynullThe new total for its whole window, never per day. Unset: unchanged.
endsAtdatetimenullThe new end. Unset: unchanged.
targetingTargetingnullNew targeting, in the same account-neutral fields Campaign.create takes. Unset: unchanged.
keywordsstring[]nullFor a search ad account: the full new list of searches. Unset: unchanged.
negativesstring[]nullFor a search ad account: searches to stop showing on, added to the ones it has, such as those that spent with no signup. Unset: unchanged.
stopRulestringnullA new stop rule. Unset: unchanged.
reasonstringnullWhy, in one sentence. It is kept on the Action and shown in the Play’s readout.

Outputs

FieldTypeWhat null means
campaignCampaignNever null.
campaign.statestringNever null: the state after the change.
campaign.budgetmoney, in USDNever null: the budget after the change.
campaign.endsAtdatetimeNever null: the end after the change.
billBillNull unless the budget went up: then the Bill for the difference, owed for the ad spend.

Effects

Action class

spend: an approval rule on spend can make it wait for your OK

Modes
  • try: Validates the change on the ad account and returns the Campaign as it would stand; nothing changes.
  • send: Returns a pending Action; Campaign.updated fires when the ad account confirms the change.
  • do: Waits for the ad account to confirm and returns the changed Campaign.
Idempotency

Only with a key: the same Idempotency-Key and input return the first Action, and the same key with other input returns 409. A pause or a cut is safe to repeat: a Campaign already in that state returns unchanged.

Saved or shared

Each change is a new Version of the Campaign, with its reason. A cut lowers the open Bill; a raise books a Bill for the difference.

Emits

Campaign.updated with { campaign, changed, bill, reason }

Performed by

Paid Media Manager

Price

Free on your own account. The spend is billed by the site directly: Google, LinkedIn, Meta, Microsoft, Reddit, TikTok, X.

Standing approval

It asks you first above its seat rule, unless a standing approval covers it: a Mandate you grant once with Mandate.authorize.

On each Venue

SiteFieldsFormats
Google Search and Google Display and YouTubeobjective, budget, keywords, negatives2
LinkedInobjective, budget, endsAt, state, targeting3
Facebook and Instagramobjective, budget, state5
Bingobjective, budget, state, negatives, bid1
Redditobjective, budget, endsAt, state, bid3
TikTokobjective, budget, endsAt, state2
Xobjective, budget, endsAt, state, bid2

Through Google Ads.

Our fieldGoogle Ads’s field
Campaign.objectivecampaign.advertising_channel_type (With a conversion goal; leads runs a SEARCH campaign bidding toward your signup conversion)
Campaign.budgetcampaign_budget.amount_micros (A daily amount in millionths: $40 is 40000000)
Campaign.keywordsad_group_criterion.keyword (match_type EXACT for a test)
Campaign.negativescampaign_criterion.negative (With the wasted search term as its keyword)
  • A day’s spend. Google may spend up to twice the daily budget on one day and holds the month to about 30.4 days of it, so your standing approval’s cap is set on the month.
  • Spend. Your standing approval holds the cap; a budget change past it waits with over-mandate.
Google Search: Responsive search ad YouTube: Video

LinkedIn

Through LinkedIn Ads.

Our fieldLinkedIn Ads’s field
Campaign.objectiveadCampaign.objectiveType (leads is LEAD_GENERATION with LinkedIn’s lead form, traffic WEBSITE_VISIT, conversions WEBSITE_CONVERSION)
Campaign.budgetadCampaign.dailyBudget or adCampaign.totalBudget ({ amount, currencyCode }, the amount as a decimal string; a lifetime budget runs on lifetime pacing, which LinkedIn recommends)
Campaign.endsAtadCampaign.runSchedule.end
Campaign.stateadCampaign.status (draft is DRAFT, live ACTIVE, paused PAUSED)
Campaign.targetingadCampaign.targetingCriteria (Job titles, industries, staff count ranges and locations, each a LinkedIn targeting facet)
  • Spend. Your standing approval holds the daily and total cap; a change past it waits with over-mandate.
Feed post Single image ad, 1200 × 628, 1200 × 1200 or 720 × 900 Document ad

Facebook and Instagram

Through Meta Ads.

Our fieldMeta Ads’s field
Campaign.objectivecampaign.objective (leads is OUTCOME_LEADS, traffic OUTCOME_TRAFFIC, conversions OUTCOME_SALES)
Campaign.budgetadset.daily_budget or adset.lifetime_budget (In the account currency’s smallest unit: $40.00 is 4000)
Campaign.statecampaign.status (live is ACTIVE, paused is PAUSED)
  • Spend. Your standing approval holds the daily and total cap; a change past it waits with over-mandate.
Facebook: Feed image ad, 1440 × 1800, 4:5 Instagram: Feed image, 320 to 1,440 pixels wide, 4:5 to 1.91:1 Instagram: Carousel Instagram: Reel, 9:16 Instagram: Story, 9:16

Bing

Through Microsoft Ads.

Our fieldMicrosoft Ads’s field
Campaign.objectivecampaign goal (Set in Microsoft Ads’ own screens; leads bids toward the signup conversion the import brings over)
Campaign.budgetcampaign daily budget
Campaign.statecampaign status (live is Active, paused Paused)
Campaign.negativescampaign negative keywords
Campaign.bidad group default bid, or the bid strategy (lowest-cost is maximize clicks; a costPer cap is a manual CPC bid)
  • Spend. Your standing approval holds the cap; a budget change past it waits with over-mandate.
Responsive search ad

Reddit

Through Reddit Ads.

Our fieldReddit Ads’s field
Campaign.objectivecampaign objective (Picked in Ads Manager: traffic sends readers to your page; leads bids toward your signup event)
Campaign.budgetad group budget
Campaign.endsAtad group end date and time
Campaign.statecampaign and ad group status (live is active, paused paused)
Campaign.bidad group bid strategy (lowest-cost is automatic bidding; a costPer cap is a cost cap on clicks or conversions)
  • Comments on a promoted post. Stay open; each one reaches you as a Message, and your agent drafts the answer.
  • Spend. Your standing approval holds the cap; a change past it waits with over-mandate.
Text or link post Comment Promoted post

TikTok

Through TikTok Ads.

Our fieldTikTok Ads’s field
Campaign.objectivecampaign objective_type (traffic is TRAFFIC; leads is LEAD_GENERATION with TikTok’s instant form; conversions is WEB_CONVERSIONS on your pixel)
Campaign.budgetadgroup budget with budget_mode BUDGET_MODE_DAY (Over $20; the campaign budget stays unset unless you ask, and then it is over $50)
Campaign.endsAtadgroup schedule_end_time (Set with schedule_type SCHEDULE_START_END)
Campaign.stateadgroup operation_status (live is ENABLE, paused DISABLE)
  • Spend. Your standing approval holds the cap; a change past it waits with over-mandate.
Video Spark Ad

X

Through X Ads.

Our fieldX Ads’s field
Campaign.objectivecampaign objective (Picked in X Ads: traffic is website traffic; engagement is post engagement)
Campaign.budgetcampaign total and daily budget
Campaign.endsAtad group end time
Campaign.statecampaign status (live is active, paused paused)
Campaign.bidad group bid strategy (lowest-cost is autobid; a costPer cap is a target cost)
  • Spend. Your standing approval holds the cap; a change past it waits with over-mandate.
Standard post Promoted post

What try does

AccountWhat try does
Google AdsSends every change with validate_only set: Google Ads checks the whole build and returns any error, and creates nothing.
LinkedIn AdsReads your ad account, the matched count of each audience and the targeting facets, and checks the campaign against LinkedIn’s budget minimums; LinkedIn has no validate-only call, so nothing is sent to it and nothing is created.
Meta AdsSends the whole build with Meta’s validate_only execution option: Meta runs every check and creates nothing, and the response names any field it would reject.
Microsoft AdsReturns what the import would bring over, term by term with the budget it would set, and the steps the browser agent would take; no session opens and nothing changes.
Reddit AdsReturns the campaign and the promoted post as Ads Manager will hold them, with the steps the browser agent would take; no session opens and nothing is created.
TikTok AdsReturns the Spark Ad and its ad group as Ads Manager will hold them, checked against TikTok’s budget floors, with the steps the browser agent would take; nothing is created.
X AdsReturns the promotion as X Ads will hold it, with the steps the browser agent would take; no session opens and nothing is promoted.

Refuses when

CheckErrorFixThen call
A landing page fails its status or Price checklandingFix what the reason names, then turn the Play back on.Campaign.update

Every call through an account can also meet the shared account refusals: grant-missing, needs-reauth, account-not-connected, over-mandate, quota-reached, venue-rejected.

The landing payload
JSON
{
  "type": "https://startupbuilder.dev/errors/landing",
  "title": "Landing",
  "status": 422,
  "detail": "A landing Page fails its status or Price check.",
  "fix": "Fix what the reason names, then turn the Play back on.",
  "next": {
    "verb": "Campaign.update",
    "input": {}
  },
  "instance": "https://api.sb/leaseline.app/actions/action_1"
}

When it waits

FactValue
send returnsA pending Action until the ad account confirms the change; a raise over your approval rule waits for an Approval first.
Delivered byCampaign.updated

Example

Text
Pause the LinkedIn test: it has spent $61.20 for one lead, over the $40
stop rule.

To retry, send the same Idempotency-Key: the retry returns the first answer for $0. A new key reads again.

Test values

A sk_test_ key answers these the same way every time, at $0 (every test value).

Test valueAlways returnsWhat it is for
campaign_test_linkedinRefuses with over-mandateA raise to $999,999 is over the Limit of every test standing approval, so it refuses and the test Campaign keeps its budget.
maxCost: 0.0001Refuses with max-costAny priced call with a maxCost of 0.0001 is refused before it spends: the price is above the cap.
rate-limited.testRefuses with rate-limitedAny call naming this hostname answers 429 with Retry-After, so your retry logic runs.
sources-busy.testRefuses with sources-busyAny call naming this hostname answers 503 as if every route were busy, and nothing is spent.

Used by