---
title: "Update an ad rule"
method: PATCH
path: "/v1/ads/rules/{ruleId}"
tags: ["Ad Rules"]
---

# Update an ad rule

`PATCH /v1/ads/rules/{ruleId}`

## Request

- Base URL: `https://zernio.com/api`
- URL: `https://zernio.com/api/v1/ads/rules/{ruleId}`
- Auth: HTTP bearer

Changes any field of a rule except its connection and ad account. Send `campaignIds: null` to
check the whole ad account again. Changing the schedule, or enabling a disabled rule, moves the
next run; re-sending `enabled: true` on an enabled rule does not.

## Request body

- object
  - `name` string
  - `level` 'campaign' | 'adset' | 'ad': Whether the rule checks campaigns, ad sets or single ads. Each one is evaluated on its own.
  - `campaignIds` string[], nullable
  - `conditions` AdRuleConditions: Every condition must hold for an object to match. A rate with no denominator (a CPA with no conversions) never matches.
    - `all` AdRuleCondition[], required
      - `metric` union, required: `ctr` is a percentage. `spend`, `cpc`, `cpm` and `cpa` are in the ad account currency. `reach` and `frequency` use the platform's de-duplicated reach, so they are accepted on Meta and TikTok only. `result:<key>` reads one of your own results (see [Campaign results](/guides/campaign-results)), on campaign rules only: the values you sent for the window, or a formula over them and the platform's numbers. A campaign with no value for it never matches.
        - 'spend' | 'impressions' | 'clicks' | 'conversions' | 'ctr' | 'cpc' | 'cpm' | 'cpa' | 'roas' | 'reach' | 'frequency'
        - string
      - `window` 'today' | 'yesterday' | 'last_3d' | 'last_7d' | 'last_14d' | 'last_30d', required: Days in the ad account's own timezone. `last_7d` is the 7 full days before today; only `today` reads the day in progress.
      - `op` '>' | '>=' | '<' | '<=', required
      - `value` number, required
  - `actions` AdRuleAction[]: Each type at most once, and at most one of `pause`, `activate` and `adjust_budget`.
    - union
      - object
        - `type` 'notify', required: Send the `ad_rule.triggered` webhook.
      - object
        - `type` 'pause', required: Pause the campaign, ad set or ad.
        - `maxChangesPerDay` integer: At most this many objects changed in any 24 hours, across runs. Matches over the limit are skipped with `daily_limit_reached` and tried again later.
      - object
        - `type` 'activate', required: Reactivate a campaign, ad set or ad a rule paused, once `cooldownMinutes` has passed since the pause. Objects you paused yourself are never touched.
        - `maxChangesPerDay` integer: At most this many objects changed in any 24 hours, across runs. Matches over the limit are skipped with `daily_limit_reached` and tried again later.
      - object
        - `type` 'adjust_budget', required: Change the daily budget. Not on ad-level rules (an ad has no budget), and on Google it needs a campaign-level rule (ad groups have no budget of their own).
        - `direction` 'increase' | 'decrease', required
        - `percent` integer, required: Change in percent: up to 100 for an increase, up to 90 for a decrease.
        - `limit` number, required: The budget never goes above this on an increase, or below it on a decrease, in the ad account currency.
        - `maxChangesPerDay` integer: At most this many objects changed in any 24 hours, across runs. Matches over the limit are skipped with `daily_limit_reached` and tried again later.
  - `schedule` AdRuleSchedule
    - `everyMinutes` 60 | 180 | 360 | 720 | 1440, required: How often the rule runs, in minutes.
  - `cooldownMinutes` integer
  - `enabled` boolean

## Response `200`

Rule updated

- object
  - `rule` AdRule, required
    - `id` string, required
    - `name` string, required
    - `accountId` string, required: The ads connection the rule acts through.
    - `platform` string, required: Ad platform, for example `facebook` (Meta) or `google`.
    - `adAccountId` string, required: Platform ad account ID.
    - `level` 'campaign' | 'adset' | 'ad', required: Whether the rule checks campaigns, ad sets or single ads. Each one is evaluated on its own.
    - `campaignIds` string[], nullable, required: Platform campaign IDs the rule is limited to. Null checks the whole ad account.
    - `conditions` AdRuleConditions, required: Every condition must hold for an object to match. A rate with no denominator (a CPA with no conversions) never matches.
      - `all` AdRuleCondition[], required
        - `metric` union, required: `ctr` is a percentage. `spend`, `cpc`, `cpm` and `cpa` are in the ad account currency. `reach` and `frequency` use the platform's de-duplicated reach, so they are accepted on Meta and TikTok only. `result:<key>` reads one of your own results (see [Campaign results](/guides/campaign-results)), on campaign rules only: the values you sent for the window, or a formula over them and the platform's numbers. A campaign with no value for it never matches.
          - 'spend' | 'impressions' | 'clicks' | 'conversions' | 'ctr' | 'cpc' | 'cpm' | 'cpa' | 'roas' | 'reach' | 'frequency'
          - string
        - `window` 'today' | 'yesterday' | 'last_3d' | 'last_7d' | 'last_14d' | 'last_30d', required: Days in the ad account's own timezone. `last_7d` is the 7 full days before today; only `today` reads the day in progress.
        - `op` '>' | '>=' | '<' | '<=', required
        - `value` number, required
    - `actions` AdRuleAction[], required: Each type at most once, and at most one of `pause`, `activate` and `adjust_budget`.
      - union
        - object
          - `type` 'notify', required: Send the `ad_rule.triggered` webhook.
        - object
          - `type` 'pause', required: Pause the campaign, ad set or ad.
          - `maxChangesPerDay` integer: At most this many objects changed in any 24 hours, across runs. Matches over the limit are skipped with `daily_limit_reached` and tried again later.
        - object
          - `type` 'activate', required: Reactivate a campaign, ad set or ad a rule paused, once `cooldownMinutes` has passed since the pause. Objects you paused yourself are never touched.
          - `maxChangesPerDay` integer: At most this many objects changed in any 24 hours, across runs. Matches over the limit are skipped with `daily_limit_reached` and tried again later.
        - object
          - `type` 'adjust_budget', required: Change the daily budget. Not on ad-level rules (an ad has no budget), and on Google it needs a campaign-level rule (ad groups have no budget of their own).
          - `direction` 'increase' | 'decrease', required
          - `percent` integer, required: Change in percent: up to 100 for an increase, up to 90 for a decrease.
          - `limit` number, required: The budget never goes above this on an increase, or below it on a decrease, in the ad account currency.
          - `maxChangesPerDay` integer: At most this many objects changed in any 24 hours, across runs. Matches over the limit are skipped with `daily_limit_reached` and tried again later.
    - `schedule` AdRuleSchedule, required
      - `everyMinutes` 60 | 180 | 360 | 720 | 1440, required: How often the rule runs, in minutes.
    - `cooldownMinutes` integer, required
    - `enabled` boolean, required
    - `lastRunAt` string, date-time, nullable, required
    - `nextRunAt` string, date-time, nullable, required: Null while the rule is disabled.
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required

## Other responses

- `400`: Invalid request
- `401`: Missing or invalid API key. `code` is `missing_credentials` when no Authorization header was sent and `invalid_credentials` when the key is unknown, revoked or expired.
- `403`: Code `ads_addon_required` when the team has no ads access, or `ads_allowance_exceeded` when the change enables a rule that reactivates or raises budgets for a team past its free live-ads allowance with no payment method.
- `404`: Resource not found

## Changes

- **2026-10-30** `c319eb5d95b6`: 11 breaking, 13 info
  - removed the enum value `clicks` of the request property `conditions/all/items/metric`
  - removed the enum value `conversions` of the request property `conditions/all/items/metric`
  - removed the enum value `cpa` of the request property `conditions/all/items/metric`
  - removed the enum value `cpc` of the request property `conditions/all/items/metric`
  - …20 more
- **2026-10-30** `f239e5073e14`: 2 breaking, 3 warning, 5 info
  - removed `subschema #2, subschema #3, subschema #4` from the `actions/items/` request property `oneOf` list
  - added `subschema #2, subschema #3, subschema #4` to the `rule/actions/items/` response property `oneOf` list for the response status `200`
  - added the new `ad` enum value to the `rule/level` response property for the response status `200`
  - added the new `frequency` enum value to the `rule/conditions/all/items/metric` response property for the response status `200`
  - …6 more
- **2026-10-25** `4d3c3acfbcea`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/ads/rules/:ruleId/patch.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) - [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/c319eb5d95b6?raw)
