Policy states

What happens to a proposal after you POST it — and why "queued" is a success.

This is the page to read before automating writes. The write model is the one part of this API that doesn't behave like a normal REST resource, and it's deliberate: every change here moves real money against an API with no dry-run and no sandbox.

A write creates a decision, not a change

POST /accounts/{projectId}/actions/budget-change does not set a budget. It records an action and asks the safe-apply policy what to do with it:

{
  "actionId": "9f2c…",
  "kind": "budget_change",
  "mode": "auto_applied",
  "riskTier": "safe",
  "policyReasons": [
    "Budget raise of 20% is within the 30% safe bound.",
    "30d CPA $3.10 is inside the target band."
  ],
  "summary": "Set \"Brand US\" daily budget → $150.00 (+20%)"
}

Two outcomes, both 2xx:

  • auto_applied — the policy cleared it and an apply job is enqueued.
  • queued — it's waiting in /approvals for a human decision.

Call GET /accounts/{projectId}/policy to see the live rules and predict which you'll get before you send.

mode is a snapshot, not an outcome

The apply worker re-runs the policy immediately before touching Apple, and can demote an auto-approved action back to proposed if conditions changed. It also re-runs local validation and hard-caps any budget change at 3× the warehouse value.

So mode: "auto_applied" means "cleared at propose time", not "done". For terminal state, poll the ledger:

curl ".../api/v1/accounts/current/actions?limit=10" -H "Authorization: Bearer tsk_…"

The Location header on a 201 points at the action.

Queued is not an error

These all force review rather than failing:

  • The org kill switch (asaAutoApply off) — the global stop mechanism, checked at both propose and apply time.
  • The account isn't active.
  • The 24-hour cap — 20 auto-applies per account, database-derived and therefore genuinely global (unlike the per-instance HTTP rate limits).
  • The action's own risk tier — some kinds are always review, notably switching a campaign's bid strategy, because it resets Apple's automated bidding learning.

policyReasons always says which of these applied. Treat a queued result as work successfully filed, not as a rejection.

What auto-applies

Bounded, low-risk, reversible changes only:

  • Negative keywords — adds and removes
  • Up to 10 EXACT keywords with bids ≤1.5× the account's 30-day average CPT
  • Pausing a keyword or an ad group
  • Budget raises ≤30% when the campaign's 30-day CPA is inside the operator's band
  • Budget cuts ≤30%
  • One ≤10% step on an existing targetCpa or ad-group cpaGoal
  • Reverting a change that auto-applied

Everything else queues.

Partial application is real

Apple's bulk endpoints can return 200 with per-row errors. An action that added 40 keywords where 3 failed is applied with warnings — at least one row succeeded, so it isn't a failure, but it isn't complete either. Always check warnings on applied actions in the ledger.

Composite kinds (create_campaign, clone_campaign, create_ad_group, clone_ad_group, change_match_type) sequence several Apple calls and are not atomic. A mid-sequence failure rolls back on a best-effort basis and reports the step that broke, so a failed composite can still have left partial state behind. Re-read the account before retrying one.

Undo

Applied actions are revertible where prior state was snapshotted — which is most of them, because Apple has no change history and every payload therefore carries its own prior* fields:

curl -X POST ".../api/v1/accounts/current/actions/9f2c…/revert" \
  -H "Authorization: Bearer tsk_…"

This proposes and immediately applies the compensating change. Kinds with no computable inverse return 422 not_revertible.

Safe automation checklist

  1. GET /accounts/{projectId}/syncs — is the data fresh?
  2. GET /accounts/{projectId}/policy — is the kill switch on? How many auto-applies are left today?
  3. GET /accounts/{projectId}/plan — what's worth doing?
  4. POST …/actions/<kind> with an Idempotency-Key.
  5. Read mode and policyReasons. Poll the ledger for terminal state.
  6. Check warnings on anything that reached applied.

On this page