@zernio/node 0.2.1479 → 0.2.1481

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,6 +53,7 @@ const zernio = new Zernio({
53
53
  apiKey: 'your-api-key', // Defaults to process.env['ZERNIO_API_KEY']
54
54
  baseURL: 'https://zernio.com/api',
55
55
  timeout: 300000,
56
+ fetch: myFetch, // optional, wraps every request
56
57
  });
57
58
  ```
58
59
 
package/dist/index.d.mts CHANGED
@@ -19,6 +19,11 @@ interface ClientOptions {
19
19
  * Default headers to include with every request.
20
20
  */
21
21
  defaultHeaders?: Record<string, string>;
22
+ /**
23
+ * Custom fetch used for every request, e.g. to log, trace or proxy calls. It receives the final `Request`, auth header included. A `fetch` passed to a single call replaces it for that call.
24
+ * @default globalThis.fetch
25
+ */
26
+ fetch?: typeof fetch;
22
27
  }
23
28
  /**
24
29
  * API Client for the Zernio API.
@@ -74,6 +79,7 @@ declare class Zernio {
74
79
  * body runs. Each call gets its own timeout signal.
75
80
  */
76
81
  private _bind;
82
+ private static _findDotSegmentParam;
77
83
  /**
78
84
  * TODO: remove once hey-api ships a fix for
79
85
  * https://github.com/hey-api/hey-api/issues/4177 and we can upgrade.
@@ -3960,6 +3966,10 @@ type AdRuleAction = {
3960
3966
  * 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.
3961
3967
  */
3962
3968
  maxChangesPerDay?: number;
3969
+ /**
3970
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
3971
+ */
3972
+ maxChangesPerObject?: number;
3963
3973
  } | {
3964
3974
  /**
3965
3975
  * Reactivate a campaign, ad set or ad a rule paused, once `cooldownMinutes` has passed since the pause. Objects you paused yourself are left alone unless `includeManuallyPaused` is true.
@@ -3973,6 +3983,10 @@ type AdRuleAction = {
3973
3983
  * 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.
3974
3984
  */
3975
3985
  maxChangesPerDay?: number;
3986
+ /**
3987
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
3988
+ */
3989
+ maxChangesPerObject?: number;
3976
3990
  } | {
3977
3991
  /**
3978
3992
  * Copy the campaign or ad set with its ads, on Meta and TikTok campaigns and ad sets and LinkedIn campaigns. Not on ad-level rules.
@@ -3990,6 +4004,10 @@ type AdRuleAction = {
3990
4004
  * 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.
3991
4005
  */
3992
4006
  maxChangesPerDay?: number;
4007
+ /**
4008
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4009
+ */
4010
+ maxChangesPerObject?: number;
3993
4011
  } | {
3994
4012
  /**
3995
4013
  * Move the bid cap or cost cap of a Meta ad set, in the ad account currency. Ad set rules on Meta only. An ad set without a cap is skipped with `no_bid_cap`.
@@ -4012,6 +4030,10 @@ type AdRuleAction = {
4012
4030
  * 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.
4013
4031
  */
4014
4032
  maxChangesPerDay?: number;
4033
+ /**
4034
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4035
+ */
4036
+ maxChangesPerObject?: number;
4015
4037
  } | {
4016
4038
  /**
4017
4039
  * Tag the object by its name. Meta, Google and LinkedIn campaigns and ad sets, and TikTok campaigns, ad groups and ads. An object whose name already has the tag (or lacks it, for `remove`) is skipped with `name_unchanged`.
@@ -4033,6 +4055,10 @@ type AdRuleAction = {
4033
4055
  * 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.
4034
4056
  */
4035
4057
  maxChangesPerDay?: number;
4058
+ /**
4059
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4060
+ */
4061
+ maxChangesPerObject?: number;
4036
4062
  } | {
4037
4063
  /**
4038
4064
  * Set the daily budget to an exact amount, such as a reset every midnight. Same level rules as the percent change.
@@ -4046,6 +4072,10 @@ type AdRuleAction = {
4046
4072
  * 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.
4047
4073
  */
4048
4074
  maxChangesPerDay?: number;
4075
+ /**
4076
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4077
+ */
4078
+ maxChangesPerObject?: number;
4049
4079
  } | {
4050
4080
  /**
4051
4081
  * 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).
@@ -4064,6 +4094,10 @@ type AdRuleAction = {
4064
4094
  * 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.
4065
4095
  */
4066
4096
  maxChangesPerDay?: number;
4097
+ /**
4098
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4099
+ */
4100
+ maxChangesPerObject?: number;
4067
4101
  };
4068
4102
  /**
4069
4103
  * Send the `ad_rule.triggered` webhook, and the alert to every `send` destination.
@@ -4204,7 +4238,7 @@ type AdRuleEvaluation = {
4204
4238
  objects: Array<AdRuleObjectEvaluation>;
4205
4239
  };
4206
4240
  /**
4207
- * Narrows the objects the rule checks. Every filter must hold. A campaign rule reads `name`, `campaign_id`, `goal` and `days_live`; an ad set rule also `campaign_name` and `adset_id`; an ad rule also `adset_name` and `ad_id`.
4241
+ * Narrows the objects the rule checks. Every filter must hold. A campaign rule reads `name`, `campaign_id`, `goal`, `days_live` and `budget_level`; an ad set rule also `campaign_name` and `adset_id`; an ad rule also `adset_name` and `ad_id`.
4208
4242
  */
4209
4243
  type AdRuleFilters = Array<({
4210
4244
  /**
@@ -4217,6 +4251,10 @@ type AdRuleFilters = Array<({
4217
4251
  field: 'campaign_id' | 'adset_id' | 'ad_id';
4218
4252
  op: 'in' | 'not_in';
4219
4253
  values: Array<(string)>;
4254
+ } | {
4255
+ field: 'budget_level';
4256
+ op: 'equals';
4257
+ value: 'campaign' | 'adset';
4220
4258
  } | {
4221
4259
  field: 'days_live';
4222
4260
  op: '>=' | '<';
@@ -4366,6 +4404,13 @@ type AdRuleSchedule = {
4366
4404
  * The rule stops running after this time.
4367
4405
  */
4368
4406
  endsAt?: (string) | null;
4407
+ /**
4408
+ * A daily window in the ad account timezone when the rule does not run, like `{ "from": "22:00", "to": "06:00" }`. It may wrap past midnight; the first run after it comes on the next interval point or set time.
4409
+ */
4410
+ quietHours?: {
4411
+ from: string;
4412
+ to: string;
4413
+ } | null;
4369
4414
  };
4370
4415
  /**
4371
4416
  * How often the rule runs, in minutes. Null on a rule that runs at set times.
package/dist/index.d.ts CHANGED
@@ -19,6 +19,11 @@ interface ClientOptions {
19
19
  * Default headers to include with every request.
20
20
  */
21
21
  defaultHeaders?: Record<string, string>;
22
+ /**
23
+ * Custom fetch used for every request, e.g. to log, trace or proxy calls. It receives the final `Request`, auth header included. A `fetch` passed to a single call replaces it for that call.
24
+ * @default globalThis.fetch
25
+ */
26
+ fetch?: typeof fetch;
22
27
  }
23
28
  /**
24
29
  * API Client for the Zernio API.
@@ -74,6 +79,7 @@ declare class Zernio {
74
79
  * body runs. Each call gets its own timeout signal.
75
80
  */
76
81
  private _bind;
82
+ private static _findDotSegmentParam;
77
83
  /**
78
84
  * TODO: remove once hey-api ships a fix for
79
85
  * https://github.com/hey-api/hey-api/issues/4177 and we can upgrade.
@@ -3960,6 +3966,10 @@ type AdRuleAction = {
3960
3966
  * 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.
3961
3967
  */
3962
3968
  maxChangesPerDay?: number;
3969
+ /**
3970
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
3971
+ */
3972
+ maxChangesPerObject?: number;
3963
3973
  } | {
3964
3974
  /**
3965
3975
  * Reactivate a campaign, ad set or ad a rule paused, once `cooldownMinutes` has passed since the pause. Objects you paused yourself are left alone unless `includeManuallyPaused` is true.
@@ -3973,6 +3983,10 @@ type AdRuleAction = {
3973
3983
  * 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.
3974
3984
  */
3975
3985
  maxChangesPerDay?: number;
3986
+ /**
3987
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
3988
+ */
3989
+ maxChangesPerObject?: number;
3976
3990
  } | {
3977
3991
  /**
3978
3992
  * Copy the campaign or ad set with its ads, on Meta and TikTok campaigns and ad sets and LinkedIn campaigns. Not on ad-level rules.
@@ -3990,6 +4004,10 @@ type AdRuleAction = {
3990
4004
  * 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.
3991
4005
  */
3992
4006
  maxChangesPerDay?: number;
4007
+ /**
4008
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4009
+ */
4010
+ maxChangesPerObject?: number;
3993
4011
  } | {
3994
4012
  /**
3995
4013
  * Move the bid cap or cost cap of a Meta ad set, in the ad account currency. Ad set rules on Meta only. An ad set without a cap is skipped with `no_bid_cap`.
@@ -4012,6 +4030,10 @@ type AdRuleAction = {
4012
4030
  * 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.
4013
4031
  */
4014
4032
  maxChangesPerDay?: number;
4033
+ /**
4034
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4035
+ */
4036
+ maxChangesPerObject?: number;
4015
4037
  } | {
4016
4038
  /**
4017
4039
  * Tag the object by its name. Meta, Google and LinkedIn campaigns and ad sets, and TikTok campaigns, ad groups and ads. An object whose name already has the tag (or lacks it, for `remove`) is skipped with `name_unchanged`.
@@ -4033,6 +4055,10 @@ type AdRuleAction = {
4033
4055
  * 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.
4034
4056
  */
4035
4057
  maxChangesPerDay?: number;
4058
+ /**
4059
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4060
+ */
4061
+ maxChangesPerObject?: number;
4036
4062
  } | {
4037
4063
  /**
4038
4064
  * Set the daily budget to an exact amount, such as a reset every midnight. Same level rules as the percent change.
@@ -4046,6 +4072,10 @@ type AdRuleAction = {
4046
4072
  * 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.
4047
4073
  */
4048
4074
  maxChangesPerDay?: number;
4075
+ /**
4076
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4077
+ */
4078
+ maxChangesPerObject?: number;
4049
4079
  } | {
4050
4080
  /**
4051
4081
  * 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).
@@ -4064,6 +4094,10 @@ type AdRuleAction = {
4064
4094
  * 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.
4065
4095
  */
4066
4096
  maxChangesPerDay?: number;
4097
+ /**
4098
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
4099
+ */
4100
+ maxChangesPerObject?: number;
4067
4101
  };
4068
4102
  /**
4069
4103
  * Send the `ad_rule.triggered` webhook, and the alert to every `send` destination.
@@ -4204,7 +4238,7 @@ type AdRuleEvaluation = {
4204
4238
  objects: Array<AdRuleObjectEvaluation>;
4205
4239
  };
4206
4240
  /**
4207
- * Narrows the objects the rule checks. Every filter must hold. A campaign rule reads `name`, `campaign_id`, `goal` and `days_live`; an ad set rule also `campaign_name` and `adset_id`; an ad rule also `adset_name` and `ad_id`.
4241
+ * Narrows the objects the rule checks. Every filter must hold. A campaign rule reads `name`, `campaign_id`, `goal`, `days_live` and `budget_level`; an ad set rule also `campaign_name` and `adset_id`; an ad rule also `adset_name` and `ad_id`.
4208
4242
  */
4209
4243
  type AdRuleFilters = Array<({
4210
4244
  /**
@@ -4217,6 +4251,10 @@ type AdRuleFilters = Array<({
4217
4251
  field: 'campaign_id' | 'adset_id' | 'ad_id';
4218
4252
  op: 'in' | 'not_in';
4219
4253
  values: Array<(string)>;
4254
+ } | {
4255
+ field: 'budget_level';
4256
+ op: 'equals';
4257
+ value: 'campaign' | 'adset';
4220
4258
  } | {
4221
4259
  field: 'days_live';
4222
4260
  op: '>=' | '<';
@@ -4366,6 +4404,13 @@ type AdRuleSchedule = {
4366
4404
  * The rule stops running after this time.
4367
4405
  */
4368
4406
  endsAt?: (string) | null;
4407
+ /**
4408
+ * A daily window in the ad account timezone when the rule does not run, like `{ "from": "22:00", "to": "06:00" }`. It may wrap past midnight; the first run after it comes on the next interval point or set time.
4409
+ */
4410
+ quietHours?: {
4411
+ from: string;
4412
+ to: string;
4413
+ } | null;
4369
4414
  };
4370
4415
  /**
4371
4416
  * How often the rule runs, in minutes. Null on a rule that runs at set times.
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(index_exports);
36
36
  // package.json
37
37
  var package_default = {
38
38
  name: "@zernio/node",
39
- version: "0.2.1479",
39
+ version: "0.2.1481",
40
40
  description: "The official Node.js library for the Zernio API",
41
41
  main: "dist/index.js",
42
42
  module: "dist/index.mjs",
@@ -9445,7 +9445,8 @@ var Zernio = class _Zernio {
9445
9445
  headers: {
9446
9446
  "User-Agent": `zernio-node/${package_default.version}`,
9447
9447
  ...options.defaultHeaders ?? {}
9448
- }
9448
+ },
9449
+ fetch: options.fetch
9449
9450
  })
9450
9451
  );
9451
9452
  this._dispatchClient = _Zernio._stripClientSelector(this._client);
@@ -9473,6 +9474,14 @@ var Zernio = class _Zernio {
9473
9474
  */
9474
9475
  _bind(operation) {
9475
9476
  return ((options) => {
9477
+ const unsafeParam = _Zernio._findDotSegmentParam(options?.["path"]);
9478
+ if (unsafeParam !== void 0) {
9479
+ return Promise.reject(new ValidationError(
9480
+ `Path parameter "${unsafeParam}" cannot be empty, "." or "..": the URL parser would send the request to a different endpoint.`,
9481
+ { [unsafeParam]: ['must not be empty, "." or ".."'] },
9482
+ { code: "invalid_path_parameter", param: unsafeParam }
9483
+ ));
9484
+ }
9476
9485
  const withClient = { ...options };
9477
9486
  if (withClient["client"] === void 0) {
9478
9487
  withClient["client"] = this._dispatchClient;
@@ -9483,6 +9492,15 @@ var Zernio = class _Zernio {
9483
9492
  return operation(withClient);
9484
9493
  });
9485
9494
  }
9495
+ // WHATWG URL drops "." and ".." segments (and their %2e forms), so a dot-only param can't be escaped, only refused.
9496
+ static _findDotSegmentParam(path) {
9497
+ if (!path || typeof path !== "object") return void 0;
9498
+ for (const [name, value] of Object.entries(path)) {
9499
+ const segment = Array.isArray(value) ? value.join(",") : value;
9500
+ if (typeof segment === "string" && ["", ".", ".."].includes(segment)) return name;
9501
+ }
9502
+ return void 0;
9503
+ }
9486
9504
  /**
9487
9505
  * TODO: remove once hey-api ships a fix for
9488
9506
  * https://github.com/hey-api/hey-api/issues/4177 and we can upgrade.
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
5
5
  // package.json
6
6
  var package_default = {
7
7
  name: "@zernio/node",
8
- version: "0.2.1479",
8
+ version: "0.2.1481",
9
9
  description: "The official Node.js library for the Zernio API",
10
10
  main: "dist/index.js",
11
11
  module: "dist/index.mjs",
@@ -9414,7 +9414,8 @@ var Zernio = class _Zernio {
9414
9414
  headers: {
9415
9415
  "User-Agent": `zernio-node/${package_default.version}`,
9416
9416
  ...options.defaultHeaders ?? {}
9417
- }
9417
+ },
9418
+ fetch: options.fetch
9418
9419
  })
9419
9420
  );
9420
9421
  this._dispatchClient = _Zernio._stripClientSelector(this._client);
@@ -9442,6 +9443,14 @@ var Zernio = class _Zernio {
9442
9443
  */
9443
9444
  _bind(operation) {
9444
9445
  return ((options) => {
9446
+ const unsafeParam = _Zernio._findDotSegmentParam(options?.["path"]);
9447
+ if (unsafeParam !== void 0) {
9448
+ return Promise.reject(new ValidationError(
9449
+ `Path parameter "${unsafeParam}" cannot be empty, "." or "..": the URL parser would send the request to a different endpoint.`,
9450
+ { [unsafeParam]: ['must not be empty, "." or ".."'] },
9451
+ { code: "invalid_path_parameter", param: unsafeParam }
9452
+ ));
9453
+ }
9445
9454
  const withClient = { ...options };
9446
9455
  if (withClient["client"] === void 0) {
9447
9456
  withClient["client"] = this._dispatchClient;
@@ -9452,6 +9461,15 @@ var Zernio = class _Zernio {
9452
9461
  return operation(withClient);
9453
9462
  });
9454
9463
  }
9464
+ // WHATWG URL drops "." and ".." segments (and their %2e forms), so a dot-only param can't be escaped, only refused.
9465
+ static _findDotSegmentParam(path) {
9466
+ if (!path || typeof path !== "object") return void 0;
9467
+ for (const [name, value] of Object.entries(path)) {
9468
+ const segment = Array.isArray(value) ? value.join(",") : value;
9469
+ if (typeof segment === "string" && ["", ".", ".."].includes(segment)) return name;
9470
+ }
9471
+ return void 0;
9472
+ }
9455
9473
  /**
9456
9474
  * TODO: remove once hey-api ships a fix for
9457
9475
  * https://github.com/hey-api/hey-api/issues/4177 and we can upgrade.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zernio/node",
3
- "version": "0.2.1479",
3
+ "version": "0.2.1481",
4
4
  "description": "The official Node.js library for the Zernio API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/client.ts CHANGED
@@ -1144,7 +1144,7 @@ import {
1144
1144
  withdrawAdAccountUserInvitationApproval,
1145
1145
  } from './generated/sdk.gen';
1146
1146
 
1147
- import { ZernioApiError, parseApiError } from './errors';
1147
+ import { ZernioApiError, ValidationError, parseApiError } from './errors';
1148
1148
  export interface ClientOptions {
1149
1149
  /**
1150
1150
  * API key for authentication. Defaults to process.env['ZERNIO_API_KEY'] (falls back to LATE_API_KEY).
@@ -1167,6 +1167,12 @@ export interface ClientOptions {
1167
1167
  * Default headers to include with every request.
1168
1168
  */
1169
1169
  defaultHeaders?: Record<string, string>;
1170
+
1171
+ /**
1172
+ * Custom fetch used for every request, e.g. to log, trace or proxy calls. It receives the final `Request`, auth header included. A `fetch` passed to a single call replaces it for that call.
1173
+ * @default globalThis.fetch
1174
+ */
1175
+ fetch?: typeof fetch;
1170
1176
  }
1171
1177
  /**
1172
1178
  * API Client for the Zernio API.
@@ -1228,6 +1234,13 @@ export class Zernio {
1228
1234
  */
1229
1235
  private _bind<F>(operation: F): F {
1230
1236
  return ((options?: Record<string, unknown>) => {
1237
+ const unsafeParam = Zernio._findDotSegmentParam(options?.['path']);
1238
+ if (unsafeParam !== undefined) {
1239
+ return Promise.reject(new ValidationError(
1240
+ `Path parameter "${unsafeParam}" cannot be empty, "." or "..": the URL parser would send the request to a different endpoint.`,
1241
+ { [unsafeParam]: ['must not be empty, "." or ".."'] },
1242
+ { code: 'invalid_path_parameter', param: unsafeParam }));
1243
+ }
1231
1244
  const withClient = { ...options };
1232
1245
  if (withClient['client'] === undefined) {
1233
1246
  withClient['client'] = this._dispatchClient;
@@ -1240,6 +1253,16 @@ export class Zernio {
1240
1253
  }) as F;
1241
1254
  }
1242
1255
 
1256
+ // WHATWG URL drops "." and ".." segments (and their %2e forms), so a dot-only param can't be escaped, only refused.
1257
+ private static _findDotSegmentParam(path: unknown): string | undefined {
1258
+ if (!path || typeof path !== 'object') return undefined;
1259
+ for (const [name, value] of Object.entries(path)) {
1260
+ const segment = Array.isArray(value) ? value.join(',') : value;
1261
+ if (typeof segment === 'string' && ['', '.', '..'].includes(segment)) return name;
1262
+ }
1263
+ return undefined;
1264
+ }
1265
+
1243
1266
  /**
1244
1267
  * TODO: remove once hey-api ships a fix for
1245
1268
  * https://github.com/hey-api/hey-api/issues/4177 and we can upgrade.
@@ -3483,6 +3506,7 @@ export class Zernio {
3483
3506
  'User-Agent': `zernio-node/${packageJson.version}`,
3484
3507
  ...(options.defaultHeaders ?? {}),
3485
3508
  },
3509
+ fetch: options.fetch,
3486
3510
  })
3487
3511
  );
3488
3512
 
@@ -1733,6 +1733,10 @@ export type AdRuleAction = {
1733
1733
  * 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.
1734
1734
  */
1735
1735
  maxChangesPerDay?: number;
1736
+ /**
1737
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
1738
+ */
1739
+ maxChangesPerObject?: number;
1736
1740
  } | {
1737
1741
  /**
1738
1742
  * Reactivate a campaign, ad set or ad a rule paused, once `cooldownMinutes` has passed since the pause. Objects you paused yourself are left alone unless `includeManuallyPaused` is true.
@@ -1746,6 +1750,10 @@ export type AdRuleAction = {
1746
1750
  * 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.
1747
1751
  */
1748
1752
  maxChangesPerDay?: number;
1753
+ /**
1754
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
1755
+ */
1756
+ maxChangesPerObject?: number;
1749
1757
  } | {
1750
1758
  /**
1751
1759
  * Copy the campaign or ad set with its ads, on Meta and TikTok campaigns and ad sets and LinkedIn campaigns. Not on ad-level rules.
@@ -1763,6 +1771,10 @@ export type AdRuleAction = {
1763
1771
  * 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.
1764
1772
  */
1765
1773
  maxChangesPerDay?: number;
1774
+ /**
1775
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
1776
+ */
1777
+ maxChangesPerObject?: number;
1766
1778
  } | {
1767
1779
  /**
1768
1780
  * Move the bid cap or cost cap of a Meta ad set, in the ad account currency. Ad set rules on Meta only. An ad set without a cap is skipped with `no_bid_cap`.
@@ -1785,6 +1797,10 @@ export type AdRuleAction = {
1785
1797
  * 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.
1786
1798
  */
1787
1799
  maxChangesPerDay?: number;
1800
+ /**
1801
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
1802
+ */
1803
+ maxChangesPerObject?: number;
1788
1804
  } | {
1789
1805
  /**
1790
1806
  * Tag the object by its name. Meta, Google and LinkedIn campaigns and ad sets, and TikTok campaigns, ad groups and ads. An object whose name already has the tag (or lacks it, for `remove`) is skipped with `name_unchanged`.
@@ -1806,6 +1822,10 @@ export type AdRuleAction = {
1806
1822
  * 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.
1807
1823
  */
1808
1824
  maxChangesPerDay?: number;
1825
+ /**
1826
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
1827
+ */
1828
+ maxChangesPerObject?: number;
1809
1829
  } | {
1810
1830
  /**
1811
1831
  * Set the daily budget to an exact amount, such as a reset every midnight. Same level rules as the percent change.
@@ -1819,6 +1839,10 @@ export type AdRuleAction = {
1819
1839
  * 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.
1820
1840
  */
1821
1841
  maxChangesPerDay?: number;
1842
+ /**
1843
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
1844
+ */
1845
+ maxChangesPerObject?: number;
1822
1846
  } | {
1823
1847
  /**
1824
1848
  * 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).
@@ -1837,6 +1861,10 @@ export type AdRuleAction = {
1837
1861
  * 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.
1838
1862
  */
1839
1863
  maxChangesPerDay?: number;
1864
+ /**
1865
+ * At most this many changes to one object by this rule, counted over the last 400 days. An object at the limit is left alone like one in cooldown.
1866
+ */
1867
+ maxChangesPerObject?: number;
1840
1868
  };
1841
1869
 
1842
1870
  /**
@@ -1991,7 +2019,7 @@ export type AdRuleEvaluation = {
1991
2019
  };
1992
2020
 
1993
2021
  /**
1994
- * Narrows the objects the rule checks. Every filter must hold. A campaign rule reads `name`, `campaign_id`, `goal` and `days_live`; an ad set rule also `campaign_name` and `adset_id`; an ad rule also `adset_name` and `ad_id`.
2022
+ * Narrows the objects the rule checks. Every filter must hold. A campaign rule reads `name`, `campaign_id`, `goal`, `days_live` and `budget_level`; an ad set rule also `campaign_name` and `adset_id`; an ad rule also `adset_name` and `ad_id`.
1995
2023
  */
1996
2024
  export type AdRuleFilters = Array<({
1997
2025
  /**
@@ -2004,6 +2032,10 @@ export type AdRuleFilters = Array<({
2004
2032
  field: 'campaign_id' | 'adset_id' | 'ad_id';
2005
2033
  op: 'in' | 'not_in';
2006
2034
  values: Array<(string)>;
2035
+ } | {
2036
+ field: 'budget_level';
2037
+ op: 'equals';
2038
+ value: 'campaign' | 'adset';
2007
2039
  } | {
2008
2040
  field: 'days_live';
2009
2041
  op: '>=' | '<';
@@ -2160,6 +2192,13 @@ export type AdRuleSchedule = {
2160
2192
  * The rule stops running after this time.
2161
2193
  */
2162
2194
  endsAt?: (string) | null;
2195
+ /**
2196
+ * A daily window in the ad account timezone when the rule does not run, like `{ "from": "22:00", "to": "06:00" }`. It may wrap past midnight; the first run after it comes on the next interval point or set time.
2197
+ */
2198
+ quietHours?: {
2199
+ from: string;
2200
+ to: string;
2201
+ } | null;
2163
2202
  };
2164
2203
 
2165
2204
  /**