infrawrench-sdk 1.62.0 → 1.66.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6d3f0257a114595211cf176906366997598e9d06c8b54ce6de7aa6d408ab0a4
4
- data.tar.gz: c2a2ed23d72b11ca28681aa3c5c339a47a3bcef33db48b97e141c3391fd25dae
3
+ metadata.gz: 1b12c3510f623aa61a1409b1430c1cafccf89a939221ec5cee7d35a51650a6f1
4
+ data.tar.gz: a7bb4f300419ad8a0456d5f5d55e6253d0022d2fa98057469b8324c87409061d
5
5
  SHA512:
6
- metadata.gz: 5e91dcefd0cbf55894b809029a87ef3899328521a8978171d34256828c8d7e478a10fd6c48222a21eee4ab9fe08ba9488340d54d72546026d93bbc0597a2d3e2
7
- data.tar.gz: 75475f3d824638ebdedf7efd4cb9869b28928afa81b8c8986192fd37e009838fcb17c785067abf94d561fbcaa49a91c4de8b506035c6442c40ef04406ac5e85d
6
+ metadata.gz: 888eb1fb8fffd427d6646e6ab9f1b01f6e12234fbd163ed53a4555157d5dd53b08c2758924a3d458f19d1f154d3e96e7c128beb89986114974c66dd61527b050
7
+ data.tar.gz: e283026c7f55b494868da5f38ecc8f9d81019a325be0442a13ef414a15a14318fe11da077b512e4bf13847ef07b9fc76982819175967411d93f420953887d676
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # infrawrench-sdk
2
2
 
3
- Generated Ruby client for the Infrawrench API (API version `1.62.0`).
3
+ Generated Ruby client for the Infrawrench API (API version `1.66.0`).
4
4
 
5
5
  **Do not edit this gem by hand** — it is regenerated from `openapi.json` and is
6
6
  not checked into the repository. Run
@@ -41,7 +41,7 @@ Every method takes an optional trailing `request_options:` hash (`:headers`,
41
41
  Responses are the plain `Hash`/`Array` that `JSON.parse` returns, with String
42
42
  keys spelled exactly as the wire spells them. There are no model classes — see
43
43
  [`sig/infrawrench/sdk.rbs`](./sig/infrawrench/sdk.rbs) for the shape of every one of the
44
- 868 schemas, as RBS type aliases that steep and TypeProf can read.
44
+ 889 schemas, as RBS type aliases that steep and TypeProf can read.
45
45
 
46
46
  Non-2xx responses raise `Infrawrench::ApiError`, which carries `#status`,
47
47
  the parsed `#body`, and the machine-readable `#code` when the API sends one —
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # infrawrench-sdk v1.62.0 | MIT | Copyright (c) 2026 Infrawrench LLC
3
+ # infrawrench-sdk v1.66.0 | MIT | Copyright (c) 2026 Infrawrench LLC
4
4
  # https://github.com/Infrawrench/Infrawrench
5
5
  #
6
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.62.0).
6
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.66.0).
7
7
  #
8
8
  # DO NOT EDIT. Regenerate with:
9
9
  # pnpm --filter @infrawrench/web generate:sdk
@@ -17,8 +17,8 @@ require_relative "lib/infrawrench/version"
17
17
  Gem::Specification.new do |spec|
18
18
  spec.name = "infrawrench-sdk"
19
19
  spec.version = Infrawrench::VERSION
20
- spec.summary = "Generated Ruby client for the Infrawrench API (v1.62.0)."
21
- spec.description = "Generated Ruby client for the Infrawrench API (v1.62.0). Covers the published API surface only — operations marked x-internal in the spec are not generated. No runtime dependencies."
20
+ spec.summary = "Generated Ruby client for the Infrawrench API (v1.66.0)."
21
+ spec.description = "Generated Ruby client for the Infrawrench API (v1.66.0). Covers the published API surface only — operations marked x-internal in the spec are not generated. No runtime dependencies."
22
22
  spec.authors = ["Infrawrench LLC", "Astrid Gealer"]
23
23
  spec.email = ["astrid@infrawrench.com"]
24
24
  spec.homepage = "https://infrawrench.com/docs/team-and-billing/client-sdks"
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # infrawrench-sdk v1.62.0 | MIT | Copyright (c) 2026 Infrawrench LLC
3
+ # infrawrench-sdk v1.66.0 | MIT | Copyright (c) 2026 Infrawrench LLC
4
4
  # https://github.com/Infrawrench/Infrawrench
5
5
  #
6
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.62.0).
6
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.66.0).
7
7
  #
8
8
  # DO NOT EDIT. Regenerate with:
9
9
  # pnpm --filter @infrawrench/web generate:sdk
@@ -3039,12 +3039,85 @@ module Infrawrench
3039
3039
  end
3040
3040
  end
3041
3041
 
3042
+ # `client.budgets.events`
3043
+ class BudgetsEventsNamespace
3044
+ # @api private
3045
+ # @param transport [Transport]
3046
+ def initialize(transport)
3047
+ @transport = transport
3048
+ end
3049
+
3050
+ # Alert event history for a budget
3051
+ #
3052
+ # GET /api/org/{orgId}/budgets/{id}/events
3053
+ #
3054
+ # Raises on 404: Not found
3055
+ #
3056
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
3057
+ # constructed with.
3058
+ # @param id [String]
3059
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
3060
+ # @return [Array<Hash>] Parsed JSON, shaped as `Array<BudgetAlertEvent>` — see
3061
+ # `sig/infrawrench/sdk.rbs`.
3062
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
3063
+ def list(id:, org_id: nil, request_options: nil)
3064
+ @transport.request(
3065
+ http_method: "GET",
3066
+ path: "/api/org/{orgId}/budgets/{id}/events",
3067
+ path_params: { "orgId" => org_id, "id" => id },
3068
+ request_options: request_options
3069
+ )
3070
+ end
3071
+
3072
+ # Explain a fired budget alert
3073
+ #
3074
+ # Saves a note on one firing (who and when are recorded), draws it on every
3075
+ # cost chart as an org-wide annotation at the day the alert fired, and posts
3076
+ # it after the alert: a reply in each Slack message's thread and a follow-up
3077
+ # to the Teams webhooks it reached. Sending again rewrites the note and
3078
+ # rewords the same chart marker rather than adding another; a marker
3079
+ # somebody deleted is not recreated. Alerts that fired before notes existed,
3080
+ # or that quiet hours held, have no recorded chat messages to follow. Needs
3081
+ # `budgets:read` and `costs:write`.
3082
+ #
3083
+ # _Requires permission: `costs:write`._
3084
+ #
3085
+ # POST /api/org/{orgId}/budgets/{id}/events/{eventId}/note
3086
+ #
3087
+ # Raises on 400: Bad request
3088
+ #
3089
+ # Raises on 404: Not found
3090
+ #
3091
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
3092
+ # constructed with.
3093
+ # @param id [String]
3094
+ # @param event_id [String]
3095
+ # @param body [Hash] Request body, shaped as `BudgetAlertNoteInput`.
3096
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
3097
+ # @return [Hash] Parsed JSON, shaped as `BudgetAlertNoteResult` — see
3098
+ # `sig/infrawrench/sdk.rbs`.
3099
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
3100
+ def note(id:, event_id:, body:, org_id: nil, request_options: nil)
3101
+ @transport.request(
3102
+ http_method: "POST",
3103
+ path: "/api/org/{orgId}/budgets/{id}/events/{eventId}/note",
3104
+ path_params: { "orgId" => org_id, "id" => id, "eventId" => event_id },
3105
+ body: body,
3106
+ request_options: request_options
3107
+ )
3108
+ end
3109
+ end
3110
+
3042
3111
  # `client.budgets`
3043
3112
  class BudgetsNamespace
3113
+ # @return [BudgetsEventsNamespace] `client.budgets.events`
3114
+ attr_reader :events
3115
+
3044
3116
  # @api private
3045
3117
  # @param transport [Transport]
3046
3118
  def initialize(transport)
3047
3119
  @transport = transport
3120
+ @events = BudgetsEventsNamespace.new(@transport)
3048
3121
  end
3049
3122
 
3050
3123
  # Create a budget
@@ -3090,28 +3163,6 @@ module Infrawrench
3090
3163
  )
3091
3164
  end
3092
3165
 
3093
- # Alert event history for a budget
3094
- #
3095
- # GET /api/org/{orgId}/budgets/{id}/events
3096
- #
3097
- # Raises on 404: Not found
3098
- #
3099
- # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
3100
- # constructed with.
3101
- # @param id [String]
3102
- # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
3103
- # @return [Array<Hash>] Parsed JSON, shaped as `Array<BudgetAlertEvent>` — see
3104
- # `sig/infrawrench/sdk.rbs`.
3105
- # @raise [Infrawrench::ApiError] On any non-2xx response.
3106
- def events(id:, org_id: nil, request_options: nil)
3107
- @transport.request(
3108
- http_method: "GET",
3109
- path: "/api/org/{orgId}/budgets/{id}/events",
3110
- path_params: { "orgId" => org_id, "id" => id },
3111
- request_options: request_options
3112
- )
3113
- end
3114
-
3115
3166
  # Get a budget with current-period status
3116
3167
  #
3117
3168
  # GET /api/org/{orgId}/budgets/{id}
@@ -6402,6 +6453,40 @@ module Infrawrench
6402
6453
  @notifications = CostReportsNotificationsNamespace.new(@transport)
6403
6454
  end
6404
6455
 
6456
+ # Move or delete many reports and folders at once
6457
+ #
6458
+ # All or nothing. Every item is checked first: it exists, the caller's
6459
+ # per-object sharing allows the action (editor to move, owner to delete, or
6460
+ # editor when nobody owns it), and for a move, the folder tree that would
6461
+ # result keeps every folder within the three-level nesting limit and free of
6462
+ # cycles. Any problem is a 400 listing each blocking item, and nothing is
6463
+ # written. Deleting a report removes its dashboard cards and pauses its
6464
+ # delivery schedules; deleting a folder drops whatever remains inside it to
6465
+ # the top level. One audit entry is written per item.
6466
+ #
6467
+ # _Requires permission: `costs:write`._
6468
+ #
6469
+ # POST /api/org/{orgId}/cost-reports/bulk
6470
+ #
6471
+ # Raises on 400: Refused; nothing was changed
6472
+ #
6473
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
6474
+ # constructed with.
6475
+ # @param body [Hash] Request body, shaped as `CostReportBulkRequest`.
6476
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
6477
+ # @return [Hash] Parsed JSON, shaped as `CostReportBulkResult` — see
6478
+ # `sig/infrawrench/sdk.rbs`.
6479
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
6480
+ def bulk(body:, org_id: nil, request_options: nil)
6481
+ @transport.request(
6482
+ http_method: "POST",
6483
+ path: "/api/org/{orgId}/cost-reports/bulk",
6484
+ path_params: { "orgId" => org_id },
6485
+ body: body,
6486
+ request_options: request_options
6487
+ )
6488
+ end
6489
+
6405
6490
  # Create a cost report
6406
6491
  #
6407
6492
  # _Requires permission: `costs:write`._
@@ -6890,12 +6975,95 @@ module Infrawrench
6890
6975
  end
6891
6976
  end
6892
6977
 
6978
+ # `client.costs.anomalies.feedback`
6979
+ class CostsAnomaliesFeedbackNamespace
6980
+ # @api private
6981
+ # @param transport [Transport]
6982
+ def initialize(transport)
6983
+ @transport = transport
6984
+ end
6985
+
6986
+ # Mark a cost anomaly expected or unexpected
6987
+ #
6988
+ # Record whether a finding was expected (planned or known) or unexpected (a
6989
+ # real problem), with an optional reason category and note. The verdict
6990
+ # tunes detection: repeated `expected` verdicts on a provider or service
6991
+ # raise its spike threshold within bounds (see GET
6992
+ # /costs/anomaly-sensitivity), and an `expected` verdict with `suppress`
6993
+ # creates a suppression so the same pattern does not alert again.
6994
+ # `unexpected` keeps sensitivity where it is and removes any suppression an
6995
+ # earlier `expected` verdict on the same anomaly created. Sending again
6996
+ # replaces the verdict.
6997
+ #
6998
+ # _Requires permission: `costs:write`._
6999
+ #
7000
+ # POST /api/org/{orgId}/costs/anomalies/{anomalyId}/feedback
7001
+ #
7002
+ # Raises on 400: Bad request
7003
+ #
7004
+ # Raises on 403: Forbidden
7005
+ #
7006
+ # Raises on 404: Not found
7007
+ #
7008
+ # Raises on 409: Conflict
7009
+ #
7010
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7011
+ # constructed with.
7012
+ # @param anomaly_id [String]
7013
+ # @param body [Hash] Request body, shaped as `CostAnomalyFeedbackInput`.
7014
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7015
+ # @return [Hash] Parsed JSON, shaped as `CostAnomalyFeedbackResult` — see
7016
+ # `sig/infrawrench/sdk.rbs`.
7017
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7018
+ def create(anomaly_id:, body:, org_id: nil, request_options: nil)
7019
+ @transport.request(
7020
+ http_method: "POST",
7021
+ path: "/api/org/{orgId}/costs/anomalies/{anomalyId}/feedback",
7022
+ path_params: { "orgId" => org_id, "anomalyId" => anomaly_id },
7023
+ body: body,
7024
+ request_options: request_options
7025
+ )
7026
+ end
7027
+
7028
+ # Withdraw a cost anomaly verdict
7029
+ #
7030
+ # Clears the verdict and deletes the suppression it created, if any.
7031
+ # Suppressions made by hand are never touched.
7032
+ #
7033
+ # _Requires permission: `costs:write`._
7034
+ #
7035
+ # DELETE /api/org/{orgId}/costs/anomalies/{anomalyId}/feedback
7036
+ #
7037
+ # Raises on 403: Forbidden
7038
+ #
7039
+ # Raises on 404: Not found
7040
+ #
7041
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7042
+ # constructed with.
7043
+ # @param anomaly_id [String]
7044
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7045
+ # @return [Hash] Parsed JSON, shaped as `CostAnomaly` — see `sig/infrawrench/sdk.rbs`.
7046
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7047
+ def delete(anomaly_id:, org_id: nil, request_options: nil)
7048
+ @transport.request(
7049
+ http_method: "DELETE",
7050
+ path: "/api/org/{orgId}/costs/anomalies/{anomalyId}/feedback",
7051
+ path_params: { "orgId" => org_id, "anomalyId" => anomaly_id },
7052
+ request_options: request_options
7053
+ )
7054
+ end
7055
+ end
7056
+
6893
7057
  # `client.costs.anomalies`
6894
7058
  class CostsAnomaliesNamespace
7059
+ # @return [CostsAnomaliesFeedbackNamespace] `client.costs.anomalies.feedback`
7060
+ attr_reader :feedback
7061
+
6895
7062
  # @api private
6896
7063
  # @param transport [Transport]
6897
7064
  def initialize(transport)
6898
7065
  @transport = transport
7066
+ @feedback = CostsAnomaliesFeedbackNamespace.new(@transport)
6899
7067
  end
6900
7068
 
6901
7069
  # Explain a detected cost anomaly
@@ -7012,11 +7180,12 @@ module Infrawrench
7012
7180
  # Update the organization's anomaly detection thresholds
7013
7181
  #
7014
7182
  # Takes effect on the next detection pass (which runs after each cost
7015
- # collection). Anomalies already stored are not re-judged. All four fields
7016
- # are required — this is a PUT of the whole settings object, not a patch —
7017
- # and `smsAlerts` deliberately has no server-side default, so a client that
7018
- # omits it is rejected rather than silently switching an organization's SMS
7019
- # paging back off. `smsConfigured` is derived and is not accepted here.
7183
+ # collection). Anomalies already stored are not re-judged. The four
7184
+ # threshold fields are required — this is a PUT of the whole settings
7185
+ # object, not a patch — and `smsAlerts` deliberately has no server-side
7186
+ # default, so a client that omits it is rejected rather than silently
7187
+ # switching an organization's SMS paging back off. `smsConfigured` is
7188
+ # derived and is not accepted here.
7020
7189
  #
7021
7190
  # _Requires permission: `costs:write`._
7022
7191
  #
@@ -7042,6 +7211,156 @@ module Infrawrench
7042
7211
  end
7043
7212
  end
7044
7213
 
7214
+ # `client.costs.anomaly_suppressions`
7215
+ class CostsAnomalySuppressionsNamespace
7216
+ # @api private
7217
+ # @param transport [Transport]
7218
+ def initialize(transport)
7219
+ @transport = transport
7220
+ end
7221
+
7222
+ # Create an anomaly suppression
7223
+ #
7224
+ # Declare that spend in a scope is expected on a pattern of days until an
7225
+ # expiry. An organization can hold at most 100 active suppressions (409 past
7226
+ # that).
7227
+ #
7228
+ # _Requires permission: `costs:write`._
7229
+ #
7230
+ # POST /api/org/{orgId}/costs/anomaly-suppressions
7231
+ #
7232
+ # Raises on 400: Bad request
7233
+ #
7234
+ # Raises on 409: Conflict
7235
+ #
7236
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7237
+ # constructed with.
7238
+ # @param body [Hash] Request body, shaped as `CostAnomalySuppressionInput`.
7239
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7240
+ # @return [Hash] Parsed JSON, shaped as `CostAnomalySuppression & Hash` — see
7241
+ # `sig/infrawrench/sdk.rbs`.
7242
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7243
+ def create(body:, org_id: nil, request_options: nil)
7244
+ @transport.request(
7245
+ http_method: "POST",
7246
+ path: "/api/org/{orgId}/costs/anomaly-suppressions",
7247
+ path_params: { "orgId" => org_id },
7248
+ body: body,
7249
+ request_options: request_options
7250
+ )
7251
+ end
7252
+
7253
+ # Delete an anomaly suppression
7254
+ #
7255
+ # The findings it suppressed keep their rows. Any whose day detection still
7256
+ # re-judges (the last three days) becomes eligible to alert on the next
7257
+ # pass.
7258
+ #
7259
+ # _Requires permission: `costs:write`._
7260
+ #
7261
+ # DELETE /api/org/{orgId}/costs/anomaly-suppressions/{suppressionId}
7262
+ #
7263
+ # Raises on 404: Not found
7264
+ #
7265
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7266
+ # constructed with.
7267
+ # @param suppression_id [String]
7268
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7269
+ # @return [nil] This endpoint returns no content.
7270
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7271
+ def delete(suppression_id:, org_id: nil, request_options: nil)
7272
+ @transport.request(
7273
+ http_method: "DELETE",
7274
+ path: "/api/org/{orgId}/costs/anomaly-suppressions/{suppressionId}",
7275
+ path_params: { "orgId" => org_id, "suppressionId" => suppression_id },
7276
+ accept: :empty,
7277
+ request_options: request_options
7278
+ )
7279
+ end
7280
+
7281
+ # List anomaly suppressions
7282
+ #
7283
+ # Every suppression of the organization, active ones first (soonest expiry
7284
+ # first), then expired ones, most recent first. Expired suppressions are
7285
+ # kept so the list can show what they suppressed.
7286
+ #
7287
+ # _Requires permission: `costs:read`._
7288
+ #
7289
+ # GET /api/org/{orgId}/costs/anomaly-suppressions
7290
+ #
7291
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7292
+ # constructed with.
7293
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7294
+ # @return [Hash] Parsed JSON, shaped as `Hash` — see `sig/infrawrench/sdk.rbs`.
7295
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7296
+ def get(org_id: nil, request_options: nil)
7297
+ @transport.request(
7298
+ http_method: "GET",
7299
+ path: "/api/org/{orgId}/costs/anomaly-suppressions",
7300
+ path_params: { "orgId" => org_id },
7301
+ request_options: request_options
7302
+ )
7303
+ end
7304
+
7305
+ # Get an anomaly suppression
7306
+ #
7307
+ # _Requires permission: `costs:read`._
7308
+ #
7309
+ # GET /api/org/{orgId}/costs/anomaly-suppressions/{suppressionId}
7310
+ #
7311
+ # Raises on 404: Not found
7312
+ #
7313
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7314
+ # constructed with.
7315
+ # @param suppression_id [String]
7316
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7317
+ # @return [Hash] Parsed JSON, shaped as `CostAnomalySuppression & Hash` — see
7318
+ # `sig/infrawrench/sdk.rbs`.
7319
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7320
+ def get_org_org_id_costs_anomaly_suppressions_suppression_id(
7321
+ suppression_id:,
7322
+ org_id: nil,
7323
+ request_options: nil
7324
+ )
7325
+ @transport.request(
7326
+ http_method: "GET",
7327
+ path: "/api/org/{orgId}/costs/anomaly-suppressions/{suppressionId}",
7328
+ path_params: { "orgId" => org_id, "suppressionId" => suppression_id },
7329
+ request_options: request_options
7330
+ )
7331
+ end
7332
+
7333
+ # Update an anomaly suppression
7334
+ #
7335
+ # Replaces the whole object. Takes effect on the next detection pass.
7336
+ #
7337
+ # _Requires permission: `costs:write`._
7338
+ #
7339
+ # PUT /api/org/{orgId}/costs/anomaly-suppressions/{suppressionId}
7340
+ #
7341
+ # Raises on 400: Bad request
7342
+ #
7343
+ # Raises on 404: Not found
7344
+ #
7345
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7346
+ # constructed with.
7347
+ # @param suppression_id [String]
7348
+ # @param body [Hash] Request body, shaped as `CostAnomalySuppressionInput`.
7349
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7350
+ # @return [Hash] Parsed JSON, shaped as `CostAnomalySuppression & Hash` — see
7351
+ # `sig/infrawrench/sdk.rbs`.
7352
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7353
+ def update(suppression_id:, body:, org_id: nil, request_options: nil)
7354
+ @transport.request(
7355
+ http_method: "PUT",
7356
+ path: "/api/org/{orgId}/costs/anomaly-suppressions/{suppressionId}",
7357
+ path_params: { "orgId" => org_id, "suppressionId" => suppression_id },
7358
+ body: body,
7359
+ request_options: request_options
7360
+ )
7361
+ end
7362
+ end
7363
+
7045
7364
  # `client.costs.efficiency_alert_settings`
7046
7365
  class CostsEfficiencyAlertSettingsNamespace
7047
7366
  # @api private
@@ -7113,6 +7432,8 @@ module Infrawrench
7113
7432
  attr_reader :anomalies
7114
7433
  # @return [CostsAnomalySettingsNamespace] `client.costs.anomaly_settings`
7115
7434
  attr_reader :anomaly_settings
7435
+ # @return [CostsAnomalySuppressionsNamespace] `client.costs.anomaly_suppressions`
7436
+ attr_reader :anomaly_suppressions
7116
7437
  # @return [CostsEfficiencyAlertSettingsNamespace] `client.costs.efficiency_alert_settings`
7117
7438
  attr_reader :efficiency_alert_settings
7118
7439
 
@@ -7122,9 +7443,63 @@ module Infrawrench
7122
7443
  @transport = transport
7123
7444
  @anomalies = CostsAnomaliesNamespace.new(@transport)
7124
7445
  @anomaly_settings = CostsAnomalySettingsNamespace.new(@transport)
7446
+ @anomaly_suppressions = CostsAnomalySuppressionsNamespace.new(@transport)
7125
7447
  @efficiency_alert_settings = CostsEfficiencyAlertSettingsNamespace.new(@transport)
7126
7448
  end
7127
7449
 
7450
+ # Anomaly detection precision over time
7451
+ #
7452
+ # Per month of the anomalous day: findings detected, suppressed, and marked
7453
+ # expected or unexpected, and precision (the share of reviewed findings that
7454
+ # were real problems).
7455
+ #
7456
+ # _Requires permission: `costs:read`._
7457
+ #
7458
+ # GET /api/org/{orgId}/costs/anomaly-precision
7459
+ #
7460
+ # Raises on 400: Bad request
7461
+ #
7462
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7463
+ # constructed with.
7464
+ # @param months [String, nil] Months to cover, 1-24. Defaults to 6.
7465
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7466
+ # @return [Hash] Parsed JSON, shaped as `CostAnomalyPrecisionReport` — see
7467
+ # `sig/infrawrench/sdk.rbs`.
7468
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7469
+ def anomaly_precision(org_id: nil, months: nil, request_options: nil)
7470
+ @transport.request(
7471
+ http_method: "GET",
7472
+ path: "/api/org/{orgId}/costs/anomaly-precision",
7473
+ path_params: { "orgId" => org_id },
7474
+ query: { "months" => months },
7475
+ request_options: request_options
7476
+ )
7477
+ end
7478
+
7479
+ # Per-key sensitivity learned from feedback
7480
+ #
7481
+ # Every provider or service with a verdict in the last 90 days, the σ its
7482
+ # spikes are judged against, and one sentence saying why.
7483
+ #
7484
+ # _Requires permission: `costs:read`._
7485
+ #
7486
+ # GET /api/org/{orgId}/costs/anomaly-sensitivity
7487
+ #
7488
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7489
+ # constructed with.
7490
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7491
+ # @return [Hash] Parsed JSON, shaped as `CostAnomalySensitivity` — see
7492
+ # `sig/infrawrench/sdk.rbs`.
7493
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7494
+ def anomaly_sensitivity(org_id: nil, request_options: nil)
7495
+ @transport.request(
7496
+ http_method: "GET",
7497
+ path: "/api/org/{orgId}/costs/anomaly-sensitivity",
7498
+ path_params: { "orgId" => org_id },
7499
+ request_options: request_options
7500
+ )
7501
+ end
7502
+
7128
7503
  # List distinct values for a cost dimension
7129
7504
  #
7130
7505
  # Feeds the filter and group-by pickers. Pass dimension=tag-keys for tag
@@ -7523,8 +7898,8 @@ module Infrawrench
7523
7898
  # Delete one exchange rate
7524
7899
  #
7525
7900
  # Removing a rate makes the days it covered fall back to the next-older
7526
- # rate, or to unconverted if none remains. Spend never disappears — it
7527
- # reverts to its own currency.
7901
+ # rate, then the automatic feed when on, or to unconverted if none applies.
7902
+ # Spend never disappears: it reverts to its own currency.
7528
7903
  #
7529
7904
  # _Requires permission: `org:settings:write`._
7530
7905
  #
@@ -7549,11 +7924,12 @@ module Infrawrench
7549
7924
 
7550
7925
  # Create or replace one exchange rate
7551
7926
  #
7552
- # Upserts on (`fromCurrency`, `toCurrency`, `effectiveFrom`) — one rate per
7927
+ # Upserts on (`fromCurrency`, `toCurrency`, `effectiveFrom`): one rate per
7553
7928
  # pair per day, so correcting a rate replaces it rather than adding a second
7554
- # one whose precedence a reader would have to guess. Rates are stated to the
7555
- # display currency in one hop: nothing inverts a rate or chains two, because
7556
- # both produce a number you never stated.
7929
+ # one whose precedence a reader would have to guess. Stated rates are one
7930
+ # hop to the display currency and are never inverted or chained. A stated
7931
+ # rate always wins over the automatic feed for the days it covers; give it
7932
+ # an `effectiveTo` to hand the days after back to the feed.
7557
7933
  #
7558
7934
  # _Requires permission: `org:settings:write`._
7559
7935
  #
@@ -7590,11 +7966,41 @@ module Infrawrench
7590
7966
  @rates = CurrencyRatesNamespace.new(@transport)
7591
7967
  end
7592
7968
 
7593
- # The org's display currency and exchange rate table
7969
+ # Automatic reference rates for one day
7970
+ #
7971
+ # Every rate the ECB feed holds for `date` (default today; weekends and
7972
+ # holidays carry the last publication), expressed in `base` (default the
7973
+ # display currency, else EUR), plus the feed's state. Readable whether or
7974
+ # not the organization has automatic rates on.
7975
+ #
7976
+ # GET /api/org/{orgId}/currency/feed
7977
+ #
7978
+ # Raises on 400: Bad request
7979
+ #
7980
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7981
+ # constructed with.
7982
+ # @param date [String, nil]
7983
+ # @param base [String, nil] ISO 4217 code, upper-case.
7984
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7985
+ # @return [Hash] Parsed JSON, shaped as `FxFeedRates` — see `sig/infrawrench/sdk.rbs`.
7986
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
7987
+ def feed(org_id: nil, date: nil, base: nil, request_options: nil)
7988
+ @transport.request(
7989
+ http_method: "GET",
7990
+ path: "/api/org/{orgId}/currency/feed",
7991
+ path_params: { "orgId" => org_id },
7992
+ query: { "date" => date, "base" => base },
7993
+ request_options: request_options
7994
+ )
7995
+ end
7996
+
7997
+ # The org's currency settings, exchange rate table and feed state
7594
7998
  #
7595
7999
  # Readable with `costs:read` rather than a settings permission: anyone who
7596
8000
  # can see a converted total has to be able to see what it was converted at,
7597
- # or the number is unauditable.
8001
+ # or the number is unauditable. `feed` reports the automatic ECB
8002
+ # reference-rate feed (global, the same for every organization): its newest
8003
+ # publication, its coverage and its last error.
7598
8004
  #
7599
8005
  # _Requires permission: `costs:read`._
7600
8006
  #
@@ -7614,13 +8020,44 @@ module Infrawrench
7614
8020
  )
7615
8021
  end
7616
8022
 
7617
- # Set or clear the org's display currency
8023
+ # Which rate a day of spend converts at
8024
+ #
8025
+ # Applies the organization's precedence (a stated rate covering the day,
8026
+ # else the automatic feed when on, at the day or month-end rate per
8027
+ # `rateBasis`) and explains the outcome. `to` defaults to the display
8028
+ # currency; `date` defaults to today.
8029
+ #
8030
+ # GET /api/org/{orgId}/currency/lookup
8031
+ #
8032
+ # Raises on 400: Bad request
8033
+ #
8034
+ # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
8035
+ # constructed with.
8036
+ # @param from [String] ISO 4217 code, upper-case.
8037
+ # @param to [String, nil] ISO 4217 code, upper-case.
8038
+ # @param date [String, nil]
8039
+ # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
8040
+ # @return [Hash] Parsed JSON, shaped as `ExchangeRateLookup` — see
8041
+ # `sig/infrawrench/sdk.rbs`.
8042
+ # @raise [Infrawrench::ApiError] On any non-2xx response.
8043
+ def lookup(from:, org_id: nil, to: nil, date: nil, request_options: nil)
8044
+ @transport.request(
8045
+ http_method: "GET",
8046
+ path: "/api/org/{orgId}/currency/lookup",
8047
+ path_params: { "orgId" => org_id },
8048
+ query: { "from" => from, "to" => to, "date" => date },
8049
+ request_options: request_options
8050
+ )
8051
+ end
8052
+
8053
+ # Save the org's currency settings
7618
8054
  #
7619
- # Setting a currency opts the organization into converted totals; `null`
7620
- # turns conversion off everywhere and restores the per-currency view.
8055
+ # Setting a display currency opts the organization into converted totals;
8056
+ # `null` turns conversion off everywhere and restores the per-currency view.
7621
8057
  # Clearing does not delete the rate table, so conversion can be turned back
7622
- # on without re-stating anything. Only currencies with a configured rate are
7623
- # converted — Infrawrench never fetches live exchange rates.
8058
+ # on without re-stating anything. With `autoRates` off, only currencies with
8059
+ # a stated rate are converted; with it on, the daily ECB reference rates
8060
+ # fill the days no stated rate covers.
7624
8061
  #
7625
8062
  # _Requires permission: `org:settings:write`._
7626
8063
  #
@@ -7630,7 +8067,7 @@ module Infrawrench
7630
8067
  #
7631
8068
  # @param org_id [String, nil] Organization id. Defaults to the `org_id` the client was
7632
8069
  # constructed with.
7633
- # @param body [Hash] Request body, shaped as `CurrencySettings`.
8070
+ # @param body [Hash] Request body, shaped as `CurrencySettingsInput`.
7634
8071
  # @param request_options [Hash, nil] Per-call `:headers`, `:timeout` and `:open_timeout`.
7635
8072
  # @return [Hash] Parsed JSON, shaped as `CurrencySettings` — see `sig/infrawrench/sdk.rbs`.
7636
8073
  # @raise [Infrawrench::ApiError] On any non-2xx response.
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # infrawrench-sdk v1.62.0 | MIT | Copyright (c) 2026 Infrawrench LLC
3
+ # infrawrench-sdk v1.66.0 | MIT | Copyright (c) 2026 Infrawrench LLC
4
4
  # https://github.com/Infrawrench/Infrawrench
5
5
  #
6
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.62.0).
6
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.66.0).
7
7
  #
8
8
  # DO NOT EDIT. Regenerate with:
9
9
  # pnpm --filter @infrawrench/web generate:sdk
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # infrawrench-sdk v1.62.0 | MIT | Copyright (c) 2026 Infrawrench LLC
3
+ # infrawrench-sdk v1.66.0 | MIT | Copyright (c) 2026 Infrawrench LLC
4
4
  # https://github.com/Infrawrench/Infrawrench
5
5
  #
6
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.62.0).
6
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.66.0).
7
7
  #
8
8
  # DO NOT EDIT. Regenerate with:
9
9
  # pnpm --filter @infrawrench/web generate:sdk
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # infrawrench-sdk v1.62.0 | MIT | Copyright (c) 2026 Infrawrench LLC
3
+ # infrawrench-sdk v1.66.0 | MIT | Copyright (c) 2026 Infrawrench LLC
4
4
  # https://github.com/Infrawrench/Infrawrench
5
5
  #
6
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.62.0).
6
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.66.0).
7
7
  #
8
8
  # DO NOT EDIT. Regenerate with:
9
9
  # pnpm --filter @infrawrench/web generate:sdk
@@ -15,5 +15,5 @@
15
15
  # Kept in its own file so the gemspec can read the version without loading the
16
16
  # client — a gemspec that pulls in net/http is a gemspec that can fail to parse.
17
17
  module Infrawrench
18
- VERSION = "1.62.0"
18
+ VERSION = "1.66.0"
19
19
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # infrawrench-sdk v1.62.0 | MIT | Copyright (c) 2026 Infrawrench LLC
3
+ # infrawrench-sdk v1.66.0 | MIT | Copyright (c) 2026 Infrawrench LLC
4
4
  # https://github.com/Infrawrench/Infrawrench
5
5
  #
6
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.62.0).
6
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.66.0).
7
7
  #
8
8
  # DO NOT EDIT. Regenerate with:
9
9
  # pnpm --filter @infrawrench/web generate:sdk
@@ -1,7 +1,7 @@
1
- # infrawrench-sdk v1.62.0 | MIT | Copyright (c) 2026 Infrawrench LLC
1
+ # infrawrench-sdk v1.66.0 | MIT | Copyright (c) 2026 Infrawrench LLC
2
2
  # https://github.com/Infrawrench/Infrawrench
3
3
  #
4
- # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.62.0).
4
+ # Generated from the Infrawrench API OpenAPI 3.1 spec (API version 1.66.0).
5
5
  #
6
6
  # DO NOT EDIT. Regenerate with:
7
7
  # pnpm --filter @infrawrench/web generate:sdk
@@ -1080,9 +1080,28 @@ module Infrawrench
1080
1080
  "periodStart" => String | nil,
1081
1081
  "periodEnd" => String | nil,
1082
1082
  "actualUsage" => Numeric | nil,
1083
- "forecastUsage" => Numeric | nil
1083
+ "forecastUsage" => Numeric | nil,
1084
+ "note" => budget_alert_note
1084
1085
  }
1085
1086
 
1087
+ # Somebody's explanation of this firing. Null while there is none.
1088
+ #
1089
+ # Spec schema: `BudgetAlertNote`.
1090
+ type budget_alert_note = {
1091
+ "text" => String,
1092
+ "notedAt" => String,
1093
+ "notedByUserId" => String | nil,
1094
+ "notedByName" => String | nil,
1095
+ "annotationId" => String | nil
1096
+ }
1097
+ | nil
1098
+
1099
+ # Spec schema: `BudgetAlertNoteInput`.
1100
+ type budget_alert_note_input = { "note" => String }
1101
+
1102
+ # Spec schema: `BudgetAlertNoteResult`.
1103
+ type budget_alert_note_result = budget_alert_event & { "followUp" => { "slack" => Integer, "msTeams" => Integer } }
1104
+
1086
1105
  # The basis `actualCents` and `forecastCents` were measured on.
1087
1106
  #
1088
1107
  # Spec schema: `BudgetCostBasis`.
@@ -1212,7 +1231,8 @@ module Infrawrench
1212
1231
  "id" => String,
1213
1232
  "thresholdType" => "actual" | "forecast",
1214
1233
  "thresholdPercent" => Integer,
1215
- "triggeredAt" => String
1234
+ "triggeredAt" => String,
1235
+ ?"note" => budget_alert_note
1216
1236
  }],
1217
1237
  "placements" => Array[{ "widgetId" => String, "dashboardId" => String, "dashboardName" => String }],
1218
1238
  "measure" => budget_measure,
@@ -2080,7 +2100,8 @@ module Infrawrench
2080
2100
  "createdByUserId" => String | nil,
2081
2101
  "createdAt" => String,
2082
2102
  "updatedAt" => String,
2083
- "costAnomalyId" => String | nil
2103
+ "costAnomalyId" => String | nil,
2104
+ "budgetAlert" => { "budgetId" => String, "eventId" => String } | nil
2084
2105
  }
2085
2106
 
2086
2107
  # Spec schema: `CostAnnotationInput`.
@@ -2111,7 +2132,93 @@ module Infrawrench
2111
2132
  "acknowledgedByUserId" => String | nil,
2112
2133
  "annotationId" => String | nil
2113
2134
  }
2114
- | nil
2135
+ | nil,
2136
+ "feedback" => cost_anomaly_feedback,
2137
+ "suppressionId" => String | nil
2138
+ }
2139
+
2140
+ # Whether somebody marked this finding expected (planned or known) or
2141
+ # unexpected (a real problem), with who and when; null while nobody has. See
2142
+ # POST /costs/anomalies/{anomalyId}/feedback.
2143
+ #
2144
+ # Spec schema: `CostAnomalyFeedback`.
2145
+ type cost_anomaly_feedback = {
2146
+ "verdict" => "expected" | "unexpected",
2147
+ "reason" => cost_anomaly_feedback_reason,
2148
+ "note" => String | nil,
2149
+ "at" => String,
2150
+ "byUserId" => String | nil,
2151
+ "byName" => String | nil,
2152
+ "suppressionId" => String | nil
2153
+ }
2154
+ | nil
2155
+
2156
+ # Spec schema: `CostAnomalyFeedbackInput`.
2157
+ type cost_anomaly_feedback_input = {
2158
+ "verdict" => "expected" | "unexpected",
2159
+ ?"reason" => cost_anomaly_feedback_reason,
2160
+ ?"note" => String | nil,
2161
+ ?"explain" => bool,
2162
+ ?"suppress" => {
2163
+ "recurrence" => cost_anomaly_recurrence,
2164
+ ?"scope" => cost_anomaly_suppression_scope & untyped,
2165
+ ?"scopeKey" => String,
2166
+ ?"tagKey" => String,
2167
+ ?"expiresOn" => String
2168
+ }
2169
+ }
2170
+
2171
+ # Spec schema: `CostAnomalyFeedbackReason`.
2172
+ type cost_anomaly_feedback_reason = "planned_launch" | "migration" | "seasonal" | "pricing_change" | "data_issue" | "other"
2173
+ | nil
2174
+
2175
+ # Spec schema: `CostAnomalyFeedbackResult`.
2176
+ type cost_anomaly_feedback_result = { "anomaly" => cost_anomaly, "suppression" => cost_anomaly_suppression }
2177
+
2178
+ # Spec schema: `CostAnomalyPrecisionReport`.
2179
+ type cost_anomaly_precision_report = {
2180
+ "months" => Integer,
2181
+ "periods" => Array[{
2182
+ "month" => String,
2183
+ "detected" => Integer,
2184
+ "suppressed" => Integer,
2185
+ "expected" => Integer,
2186
+ "unexpected" => Integer,
2187
+ "precision" => Numeric | nil
2188
+ }],
2189
+ "totals" => {
2190
+ "detected" => Integer,
2191
+ "suppressed" => Integer,
2192
+ "expected" => Integer,
2193
+ "unexpected" => Integer,
2194
+ "precision" => Numeric | nil
2195
+ },
2196
+ "reasons" => Array[{ "reason" => cost_anomaly_feedback_reason & String, "count" => Integer }]
2197
+ }
2198
+
2199
+ # How the suppression repeats. `one_off` covers every day from `startsOn` to
2200
+ # `expiresOn`; `weekly` the anchor day's weekday; `monthly` the anchor day's
2201
+ # day of the month, give or take a day (an anchor past the end of a shorter
2202
+ # month falls on its last day); `seasonal` the anchor day's calendar date,
2203
+ # give or take three days, every year.
2204
+ #
2205
+ # Spec schema: `CostAnomalyRecurrence`.
2206
+ type cost_anomaly_recurrence = "one_off" | "weekly" | "monthly" | "seasonal"
2207
+
2208
+ # Spec schema: `CostAnomalySensitivity`.
2209
+ type cost_anomaly_sensitivity = {
2210
+ "enabled" => bool,
2211
+ "windowDays" => Integer,
2212
+ "baseSigmas" => Numeric,
2213
+ "adjustments" => Array[{
2214
+ "dimension" => "provider" | "service",
2215
+ "dimensionKey" => String,
2216
+ "baseSigmas" => Numeric,
2217
+ "sigmas" => Numeric,
2218
+ "expectedCount" => Integer,
2219
+ "unexpectedCount" => Integer,
2220
+ "explanation" => String
2221
+ }]
2115
2222
  }
2116
2223
 
2117
2224
  # Spec schema: `CostAnomalySettings`.
@@ -2119,12 +2226,57 @@ module Infrawrench
2119
2226
  "sigmas" => Numeric,
2120
2227
  "minDeltaCents" => Integer,
2121
2228
  "newSourceMinCents" => Integer,
2122
- "smsAlerts" => "off" | "new_source" | "all"
2229
+ "smsAlerts" => "off" | "new_source" | "all",
2230
+ ?"feedbackTuning" => bool
2123
2231
  }
2124
2232
 
2125
2233
  # Spec schema: `CostAnomalySettingsView`.
2126
2234
  type cost_anomaly_settings_view = cost_anomaly_settings & { "smsConfigured" => bool }
2127
2235
 
2236
+ # Spec schema: `CostAnomalySuppression`.
2237
+ type cost_anomaly_suppression = {
2238
+ "id" => String,
2239
+ "scope" => cost_anomaly_suppression_scope,
2240
+ "scopeKey" => String,
2241
+ "tagKey" => String | nil,
2242
+ "scopeLabel" => String | nil,
2243
+ "recurrence" => cost_anomaly_recurrence,
2244
+ "anchorDay" => String,
2245
+ "startsOn" => String,
2246
+ "expiresOn" => String,
2247
+ "reason" => cost_anomaly_feedback_reason,
2248
+ "note" => String | nil,
2249
+ "sourceAnomalyId" => String | nil,
2250
+ "createdByUserId" => String | nil,
2251
+ "createdByName" => String | nil,
2252
+ "createdAt" => String,
2253
+ "updatedAt" => String,
2254
+ "active" => bool,
2255
+ "suppressedCount" => Integer
2256
+ }
2257
+ | nil
2258
+
2259
+ # Spec schema: `CostAnomalySuppressionInput`.
2260
+ type cost_anomaly_suppression_input = {
2261
+ "scope" => cost_anomaly_suppression_scope,
2262
+ "scopeKey" => String,
2263
+ ?"tagKey" => String,
2264
+ "recurrence" => cost_anomaly_recurrence,
2265
+ "anchorDay" => String,
2266
+ ?"startsOn" => String,
2267
+ "expiresOn" => String,
2268
+ ?"reason" => cost_anomaly_feedback_reason,
2269
+ ?"note" => String | nil
2270
+ }
2271
+
2272
+ # What the suppression covers. On a covered day the scope's spend is set aside
2273
+ # before the day is judged; a finding that only existed because of it is
2274
+ # stored as suppressed and never alerted on, and one that survives (spend
2275
+ # beyond the expected slice) alerts as normal.
2276
+ #
2277
+ # Spec schema: `CostAnomalySuppressionScope`.
2278
+ type cost_anomaly_suppression_scope = "provider" | "service" | "account" | "tag" | "cost_centre"
2279
+
2128
2280
  # Which number to sum. `cash` is what the provider charged on the day it
2129
2281
  # charged it — the default, and what every query returned before this existed.
2130
2282
  # `amortized` spreads a commitment's up-front fee across the term it buys, so
@@ -2674,6 +2826,37 @@ module Infrawrench
2674
2826
  "placements" => Array[cost_report_placement]
2675
2827
  }
2676
2828
 
2829
+ # Spec schema: `CostReportBulkError`.
2830
+ type cost_report_bulk_error = {
2831
+ "error" => String,
2832
+ ?"problems" => Array[cost_report_bulk_problem],
2833
+ ?"issues" => Array[untyped]
2834
+ }
2835
+
2836
+ # Spec schema: `CostReportBulkProblem`.
2837
+ type cost_report_bulk_problem = {
2838
+ "kind" => "report" | "folder" | "target",
2839
+ "id" => String,
2840
+ "name" => String | nil,
2841
+ "message" => String
2842
+ }
2843
+
2844
+ # At least one id and at most 500 in total. Reports and folders are validated
2845
+ # together against the tree as it will be after every move, then applied in
2846
+ # one transaction.
2847
+ #
2848
+ # Spec schema: `CostReportBulkRequest`.
2849
+ type cost_report_bulk_request = {
2850
+ "action" => "move",
2851
+ "reportIds" => Array[String],
2852
+ "folderIds" => Array[String],
2853
+ "targetFolderId" => String | nil
2854
+ }
2855
+ | { "action" => "delete", "reportIds" => Array[String], "folderIds" => Array[String] }
2856
+
2857
+ # Spec schema: `CostReportBulkResult`.
2858
+ type cost_report_bulk_result = { "action" => "move" | "delete", "reports" => Integer, "folders" => Integer }
2859
+
2677
2860
  # Spec schema: `CostReportFilter`.
2678
2861
  type cost_report_filter = {
2679
2862
  "dimension" => "provider"
@@ -2980,7 +3163,7 @@ module Infrawrench
2980
3163
  ?"multiline" => bool,
2981
3164
  ?"defaultValue" => String,
2982
3165
  ?"regions" => Array[credential_field_region],
2983
- ?"providerOptions" => { "dependsOn" => Array[String], ?"emptyLabel" => String },
3166
+ ?"providerOptions" => { "dependsOn" => Array[String], ?"emptyLabel" => String, ?"multiple" => bool },
2984
3167
  ?"helpLink" => { "label" => String, "url" => String }
2985
3168
  }
2986
3169
 
@@ -3056,10 +3239,27 @@ module Infrawrench
3056
3239
  }
3057
3240
 
3058
3241
  # Spec schema: `CurrencyConfig`.
3059
- type currency_config = { "displayCurrency" => String | nil, "rates" => Array[exchange_rate] }
3242
+ type currency_config = {
3243
+ "displayCurrency" => String | nil,
3244
+ "autoRates" => bool,
3245
+ "rateBasis" => "daily" | "month_end",
3246
+ "rates" => Array[exchange_rate],
3247
+ "feed" => fx_feed_status
3248
+ }
3060
3249
 
3061
3250
  # Spec schema: `CurrencySettings`.
3062
- type currency_settings = { "displayCurrency" => String | nil }
3251
+ type currency_settings = {
3252
+ "displayCurrency" => String | nil,
3253
+ "autoRates" => bool,
3254
+ "rateBasis" => "daily" | "month_end"
3255
+ }
3256
+
3257
+ # Spec schema: `CurrencySettingsInput`.
3258
+ type currency_settings_input = {
3259
+ "displayCurrency" => String | nil,
3260
+ ?"autoRates" => bool,
3261
+ ?"rateBasis" => "daily" | "month_end"
3262
+ }
3063
3263
 
3064
3264
  # Spec schema: `CustomCostDeleted`.
3065
3265
  type custom_cost_deleted = { "ok" => bool, "zeroedRows" => Integer }
@@ -4058,6 +4258,7 @@ module Infrawrench
4058
4258
  "toCurrency" => String,
4059
4259
  "rate" => String,
4060
4260
  "effectiveFrom" => String,
4261
+ "effectiveTo" => String | nil,
4061
4262
  "createdBy" => String | nil,
4062
4263
  "createdAt" => String,
4063
4264
  "updatedAt" => String
@@ -4068,7 +4269,21 @@ module Infrawrench
4068
4269
  "fromCurrency" => String,
4069
4270
  "toCurrency" => String,
4070
4271
  "rate" => String,
4071
- "effectiveFrom" => String
4272
+ "effectiveFrom" => String,
4273
+ ?"effectiveTo" => String | nil
4274
+ }
4275
+
4276
+ # Spec schema: `ExchangeRateLookup`.
4277
+ type exchange_rate_lookup = {
4278
+ "fromCurrency" => String,
4279
+ "toCurrency" => String,
4280
+ "date" => String,
4281
+ "rateBasis" => "daily" | "month_end",
4282
+ "rate" => Numeric | nil,
4283
+ "source" => "manual" | "ecb" | nil,
4284
+ "rateDate" => String | nil,
4285
+ "manualRateId" => String | nil,
4286
+ "explanation" => String
4072
4287
  }
4073
4288
 
4074
4289
  # Spec schema: `ExpiryAlertSettings`.
@@ -4179,6 +4394,27 @@ module Infrawrench
4179
4394
  ?"chargeTypes" => Array[cost_charge_type]
4180
4395
  }
4181
4396
 
4397
+ # Spec schema: `FxFeedRates`.
4398
+ type fx_feed_rates = fx_feed_status
4399
+ & {
4400
+ "date" => String,
4401
+ "base" => String,
4402
+ "rateDate" => String | nil,
4403
+ "rates" => Array[{ "currency" => String, "rate" => Numeric }]
4404
+ }
4405
+
4406
+ # Spec schema: `FxFeedStatus`.
4407
+ type fx_feed_status = {
4408
+ "source" => "ecb",
4409
+ "sourceName" => String,
4410
+ "sourceUrl" => String,
4411
+ "latestRateDate" => String | nil,
4412
+ "earliestRateDate" => String | nil,
4413
+ "currencies" => Array[String],
4414
+ "lastSuccessAt" => String | nil,
4415
+ "lastError" => String | nil
4416
+ }
4417
+
4182
4418
  # Spec schema: `GenerateSshKeyRequest`.
4183
4419
  type generate_ssh_key_request = { "name" => String }
4184
4420
 
@@ -9438,11 +9674,17 @@ module Infrawrench
9438
9674
  def get: (resource_id: (resource_id & untyped), ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> blast_radius_report
9439
9675
  end
9440
9676
 
9677
+ class BudgetsEventsNamespace
9678
+ def initialize: (Transport) -> void
9679
+ def list: (id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> Array[budget_alert_event]
9680
+ def note: (id: String, event_id: String, body: budget_alert_note_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> budget_alert_note_result
9681
+ end
9682
+
9441
9683
  class BudgetsNamespace
9684
+ attr_reader events: BudgetsEventsNamespace
9442
9685
  def initialize: (Transport) -> void
9443
9686
  def create: (body: budget_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> budget_full
9444
9687
  def delete: (id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> ok
9445
- def events: (id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> Array[budget_alert_event]
9446
9688
  def get: (id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> budget_with_status
9447
9689
  def list: (?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> Array[budget_with_status]
9448
9690
  def update: (id: String, body: budget_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> budget_full
@@ -9678,6 +9920,7 @@ module Infrawrench
9678
9920
  class CostReportsNamespace
9679
9921
  attr_reader notifications: CostReportsNotificationsNamespace
9680
9922
  def initialize: (Transport) -> void
9923
+ def bulk: (body: cost_report_bulk_request, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_report_bulk_result
9681
9924
  def create: (body: cost_report_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_report
9682
9925
  def delete: (id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> ok
9683
9926
  def get: (id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_report
@@ -9709,7 +9952,14 @@ module Infrawrench
9709
9952
  def update: (?org_id: String?, ?body: cost_visibility_scope_input?, ?request_options: Hash[Symbol, untyped]?) -> cost_visibility_scope
9710
9953
  end
9711
9954
 
9955
+ class CostsAnomaliesFeedbackNamespace
9956
+ def initialize: (Transport) -> void
9957
+ def create: (anomaly_id: String, body: cost_anomaly_feedback_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_anomaly_feedback_result
9958
+ def delete: (anomaly_id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_anomaly
9959
+ end
9960
+
9712
9961
  class CostsAnomaliesNamespace
9962
+ attr_reader feedback: CostsAnomaliesFeedbackNamespace
9713
9963
  def initialize: (Transport) -> void
9714
9964
  def acknowledge: (anomaly_id: String, ?org_id: String?, ?body: { "explanation" => String }?, ?request_options: Hash[Symbol, untyped]?) -> cost_anomaly
9715
9965
  def get: (?org_id: String?, ?days: String?, ?request_options: Hash[Symbol, untyped]?) -> { "anomalies" => Array[cost_anomaly] }
@@ -9721,6 +9971,15 @@ module Infrawrench
9721
9971
  def update: (body: cost_anomaly_settings, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_anomaly_settings_view
9722
9972
  end
9723
9973
 
9974
+ class CostsAnomalySuppressionsNamespace
9975
+ def initialize: (Transport) -> void
9976
+ def create: (body: cost_anomaly_suppression_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> (cost_anomaly_suppression & Hash[String, untyped])
9977
+ def delete: (suppression_id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> nil
9978
+ def get: (?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> { "suppressions" => Array[cost_anomaly_suppression & Hash[String, untyped]] }
9979
+ def get_org_org_id_costs_anomaly_suppressions_suppression_id: (suppression_id: String, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> (cost_anomaly_suppression & Hash[String, untyped])
9980
+ def update: (suppression_id: String, body: cost_anomaly_suppression_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> (cost_anomaly_suppression & Hash[String, untyped])
9981
+ end
9982
+
9724
9983
  class CostsEfficiencyAlertSettingsNamespace
9725
9984
  def initialize: (Transport) -> void
9726
9985
  def get: (?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_efficiency_settings
@@ -9730,8 +9989,11 @@ module Infrawrench
9730
9989
  class CostsNamespace
9731
9990
  attr_reader anomalies: CostsAnomaliesNamespace
9732
9991
  attr_reader anomaly_settings: CostsAnomalySettingsNamespace
9992
+ attr_reader anomaly_suppressions: CostsAnomalySuppressionsNamespace
9733
9993
  attr_reader efficiency_alert_settings: CostsEfficiencyAlertSettingsNamespace
9734
9994
  def initialize: (Transport) -> void
9995
+ def anomaly_precision: (?org_id: String?, ?months: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_anomaly_precision_report
9996
+ def anomaly_sensitivity: (?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> cost_anomaly_sensitivity
9735
9997
  def dimensions: (dimension: "provider" | "account" | "service" | "region" | "resource" | "tag" | "charge_type" | "commitment" | "virtual_tag" | "tag-keys" | "usage-units" | "virtual-tag-keys", ?org_id: String?, ?tag_key: String?, ?include_hidden: "true" | "false"?, ?request_options: Hash[Symbol, untyped]?) -> cost_dimension_values
9736
9998
  def efficiency_alerts: (?org_id: String?, ?kind: "commitment_expiry" | "commitment_idle" | "unit_cost_regression"?, ?limit: Integer?, ?request_options: Hash[Symbol, untyped]?) -> { "events" => Array[efficiency_alert_event] }
9737
9999
  def focus_export: (body: focus_export_request, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> String
@@ -9761,8 +10023,10 @@ module Infrawrench
9761
10023
  class CurrencyNamespace
9762
10024
  attr_reader rates: CurrencyRatesNamespace
9763
10025
  def initialize: (Transport) -> void
10026
+ def feed: (?org_id: String?, ?date: String?, ?base: String?, ?request_options: Hash[Symbol, untyped]?) -> fx_feed_rates
9764
10027
  def get: (?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> currency_config
9765
- def update: (body: currency_settings, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> currency_settings
10028
+ def lookup: (from: String, ?org_id: String?, ?to: String?, ?date: String?, ?request_options: Hash[Symbol, untyped]?) -> exchange_rate_lookup
10029
+ def update: (body: currency_settings_input, ?org_id: String?, ?request_options: Hash[Symbol, untyped]?) -> currency_settings
9766
10030
  end
9767
10031
 
9768
10032
  class CustomCostSourcesUploadsNamespace
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: infrawrench-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.62.0
4
+ version: 1.66.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Infrawrench LLC
@@ -11,7 +11,7 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2026-10-05 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: Generated Ruby client for the Infrawrench API (v1.62.0). Covers the published
14
+ description: Generated Ruby client for the Infrawrench API (v1.66.0). Covers the published
15
15
  API surface only — operations marked x-internal in the spec are not generated. No
16
16
  runtime dependencies.
17
17
  email:
@@ -58,5 +58,5 @@ requirements: []
58
58
  rubygems_version: 3.5.22
59
59
  signing_key:
60
60
  specification_version: 4
61
- summary: Generated Ruby client for the Infrawrench API (v1.62.0).
61
+ summary: Generated Ruby client for the Infrawrench API (v1.66.0).
62
62
  test_files: []