Automated ad rules
Pause, reactivate or rebudget campaigns and ad sets automatically when their metrics cross a threshold, or get a webhook when they do.
An ad rule checks the campaigns or ad sets of one ad account on a schedule, and acts on each one that meets every condition. Rules work on Meta, Google, TikTok, LinkedIn, Pinterest, X and Reddit. The dashboard has them under Ads > Rules (Reddit is API only for now).
What a rule is made of
| Field | What it does |
|---|---|
accountId | The ads connection: the account from GET /v1/accounts whose platform is metaads, googleads, tiktokads, linkedinads, pinterestads, xads or redditads. Never a posting account. |
adAccountId | The ad account inside the connection, from GET /v1/ads/accounts?accountId=<accountId>. It must have selected: true there. |
level | campaign or adset. Each object at that level is checked on its own. |
campaignIds | Optional. Only these campaigns, or their ad sets. Leave it out to check the whole ad account. |
conditions.all | 1 to 10 conditions. Every one must hold. |
actions | What to do with each matching object. |
schedule.everyMinutes | How often the rule runs: 60, 180, 360, 720 or 1440. |
cooldownMinutes | How long the rule leaves an object alone after acting on it. Defaults to 1440. |
A condition compares one metric over one window with a number:
{ "metric": "cpa", "window": "last_7d", "op": ">", "value": 25 }- Metrics:
spend,impressions,clicks,conversions,ctr,cpc,cpm,cpa,roas.ctris a percentage. Money is in the ad account currency. - Windows:
today,yesterday,last_3d,last_7d,last_14d,last_30d. Days follow the ad account's own timezone, andlast_7dincludes today.
Actions
| Action | What it does |
|---|---|
notify | Sends the ad_rule.triggered webhook with the matched objects. Subscribe an endpoint to that event with POST /v1/webhooks/settings first, or a notify-only rule shows nothing but its run history. |
pause | Pauses the campaign or ad set. |
activate | Reactivates a campaign or ad set that a rule paused, once the cooldown has passed. |
adjust_budget | Raises or lowers the daily budget by percent, never past limit. |
A rule takes notify, plus at most one of pause, activate and adjust_budget. A rule that pauses, activates or adjusts budgets needs cooldownMinutes at least as long as its schedule.
adjust_budget takes direction (increase or decrease), percent (up to 100 on an increase, 90 on a decrease) and limit. On an increase the budget never goes above limit. On a decrease it never goes below it.
Create a rule
This rule pauses every ad set that spent at least 50 over the last 7 days at a cost per conversion above 25, checking every hour:
curl -X POST https://zernio.com/api/v1/ads/rules \
-H "Authorization: Bearer $ZERNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Pause expensive ad sets",
"accountId": "64f1c2e8a9b3d4e5f6a7b8c9",
"adAccountId": "act_1234567890",
"level": "adset",
"conditions": { "all": [
{ "metric": "cpa", "window": "last_7d", "op": ">", "value": 25 },
{ "metric": "spend", "window": "last_7d", "op": ">=", "value": 50 }
] },
"actions": [{ "type": "pause" }, { "type": "notify" }],
"schedule": { "everyMinutes": 60 },
"enabled": false
}'The response is 201 with the rule. Create it disabled, check it with a preview, then enable it:
curl -X PATCH https://zernio.com/api/v1/ads/rules/RULE_ID \
-H "Authorization: Bearer $ZERNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "enabled": true }'Preview before you enable
POST /v1/ads/rules/{ruleId}/preview runs the conditions against current metrics and changes nothing. For each campaign or ad set it returns whether it matches, and the actual value of every condition. The response also names the timezone the windows used.
Run history
GET /v1/ads/rules/{ruleId}/runs lists the latest runs, newest first, from the last 31 days. Each run has an outcome:
| Outcome | Meaning |
|---|---|
triggered | At least one object matched and the rule acted. actedObjectIds lists them. |
no_match | No object met every condition. |
cooldown | Objects matched, but all were still inside their cooldown. |
failed | The metrics could not be read, every action failed, or the webhook could not be sent on a notify-only rule. error says why. |
How it behaves
- Metrics are the ones Zernio syncs from the ad platform, so they can trail the platform's own reporting.
- A rate with no denominator never matches. A
cpacondition skips objects with no conversions. activatenever touches an object you paused yourself. If you reactivate and then pause such an object between two runs, Zernio cannot tell your pause from the rule's, and anactivaterule may reactivate it.- Google ad groups have no budget of their own. On Google,
adjust_budgetneeds a campaign-level rule. - A run pauses, reactivates or rebudgets at most 20 objects. The rest wait for the next run.
- An object whose action failed gets no cooldown, so the next run retries it.
- Rules stop running while the team has no ads access, and resume when it is back.
- Past the free live-ads allowance with no payment method, reactivations and budget increases are skipped with the reason
ads_allowance_exceeded. - Disabling a rule stops its runs until you enable it again.
If it fails
| Error | Cause | Fix |
|---|---|---|
403 ads_addon_required | The team has no ads access. | Enable ads on the plan. |
403 ad_account_not_selected | The ad account is not selected on the connection. | Add it in the dashboard ad account picker, or with GET /v1/connect/{platform}/ads and adAccountIds (the full list, since it replaces the selection). |
400 invalid_field_value on cooldownMinutes | A rule that changes objects has a cooldown shorter than its schedule. | Raise cooldownMinutes to at least schedule.everyMinutes. |
400 invalid_field_value on actions | adjust_budget on a Google ad set rule. | Use level: "campaign". |
403 ads_allowance_exceeded | A rule that reactivates or raises budgets, on a team past its free live-ads allowance with no payment method. | Add a payment method. Rules that pause or lower budgets still work. |
404 resource_not_found | The rule does not exist or belongs to another team. | Check the ruleId. |
Related
Pixels and tracking tags
One API for every ad platform's pixel or site tag: list, create, update, read stats, share, manage users and conversion events, and install on Shopify, WordPress, Wix or Webflow.
Commerce
One API over Shopify and WooCommerce stores: products, variants, inventory, collections, discounts, channels, markets, metafields, pages and menus, orders, plus syncing a store into a Meta catalog.