From 218c345ebb7f303ef0dda4bd71432304674287e0 Mon Sep 17 00:00:00 2001
From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com>
Date: Sat, 5 Sep 2026 06:37:36 +0000
Subject: [PATCH 1/2] [fern-generated] Update SDK
Generated by Fern
CLI Version: unknown
Generators:
- fernapi/fern-typescript-node-sdk: 3.90.0
---
.fern/metadata.json | 8 +-
conformance/SPEC.md | 446 -------
conformance/vectors/check-flow.json | 527 ---------
conformance/vectors/crash-windows.json | 271 -----
conformance/vectors/expiry.json | 198 ----
conformance/vectors/lease-lifecycle.json | 447 -------
conformance/vectors/lease-manager.json | 417 -------
.../vectors/reservation-lifecycle.json | 353 ------
conformance/vectors/track-settle.json | 194 ---
package.json | 5 +-
reference.md | 1047 +++++++++++++++--
src/BaseClient.ts | 4 +-
src/api/errors/PaymentRequiredError.ts | 24 +
src/api/errors/index.ts | 1 +
.../UpdateOnboardingStateRequestBody.ts | 1 +
src/api/resources/billing/client/Client.ts | 301 +++++
.../ListCompanyBillingProfilesRequest.ts | 23 +
.../UpdateCompanyBillingProfileRequestBody.ts | 18 +
.../billing/client/requests/index.ts | 2 +
.../types/ListCompanyBillingProfilesParams.ts | 16 +
.../ListCompanyBillingProfilesResponse.ts | 9 +
.../UpdateCompanyBillingProfileResponse.ts | 9 +
src/api/resources/billing/types/index.ts | 3 +
src/api/resources/credits/client/Client.ts | 896 ++++++++++++++
.../CountCreditSpendPoliciesRequest.ts | 27 +
.../CreateCreditSpendPolicyRequestBody.ts | 19 +
.../ListCreditSpendPoliciesRequest.ts | 27 +
.../UpdateCreditSpendPolicyRequestBody.ts | 10 +
.../credits/client/requests/index.ts | 4 +
.../types/CountCreditSpendPoliciesParams.ts | 18 +
.../types/CountCreditSpendPoliciesResponse.ts | 9 +
.../types/CreateCreditSpendPolicyResponse.ts | 9 +
.../types/DeleteCreditSpendPolicyResponse.ts | 9 +
.../types/GetCreditSpendPolicyResponse.ts | 9 +
.../types/ListCreditSpendPoliciesParams.ts | 18 +
.../types/ListCreditSpendPoliciesResponse.ts | 9 +
.../types/UpdateCreditSpendPolicyResponse.ts | 9 +
src/api/resources/credits/types/index.ts | 8 +
src/api/resources/events/client/Client.ts | 382 ++++++
...psertOtlpEnvironmentSettingsRequestBody.ts | 15 +
.../resources/events/client/requests/index.ts | 1 +
.../DeleteOtlpEnvironmentSettingsResponse.ts | 9 +
.../GetOtlpEnvironmentSettingsResponse.ts | 9 +
.../UpsertOtlpEnvironmentSettingsResponse.ts | 9 +
src/api/resources/events/types/index.ts | 3 +
.../integrationsapi/client/Client.ts | 646 ++++++++++
.../ClaimStripeSandboxKeysRequestBody.ts | 11 +
.../InstallStripeSandboxRequestBody.ts | 14 +
.../integrationsapi/client/requests/index.ts | 2 +
.../types/ClaimStripeSandboxKeysResponse.ts | 9 +
.../GetStripeSandboxClaimLinkResponse.ts | 9 +
.../types/GetStripeSandboxKeysResponse.ts | 9 +
.../InstallStripeClaimableSandboxResponse.ts | 9 +
.../ListStripeSandboxCountriesResponse.ts | 9 +
.../resources/integrationsapi/types/index.ts | 5 +
.../ClaimedStripeSandboxKeysResponseData.ts | 7 +
.../CompanyBillingProfileResponseData.ts | 20 +
src/api/types/CompanyDetailResponseData.ts | 2 +
src/api/types/CompanyOverrideResponseData.ts | 2 +
.../types/CreditSpendPolicyResponseData.ts | 15 +
src/api/types/CreditSpendPolicyScope.ts | 8 +
src/api/types/EventBodyInference.ts | 6 +-
src/api/types/GetOnboardingStateResp.ts | 1 +
.../OtlpEnvironmentSettingsResponseData.ts | 12 +
.../types/RuleConditionDetailResponseData.ts | 1 +
.../RuleConditionPlanVersionResponseData.ts | 10 +
src/api/types/StripeIntegrationConfig.ts | 6 +
src/api/types/StripeSandboxClaimLink.ts | 8 +
.../StripeSandboxCountriesResponseData.ts | 5 +
.../types/StripeSandboxInstallResponseData.ts | 13 +
.../types/StripeSandboxKeysResponseData.ts | 7 +
src/api/types/index.ts | 10 +
.../UpdateOnboardingStateRequestBody.ts | 2 +
.../UpdateCompanyBillingProfileRequestBody.ts | 30 +
.../billing/client/requests/index.ts | 1 +
.../types/ListCompanyBillingProfilesParams.ts | 27 +
.../ListCompanyBillingProfilesResponse.ts | 22 +
.../UpdateCompanyBillingProfileResponse.ts | 21 +
.../resources/billing/types/index.ts | 3 +
.../CreateCreditSpendPolicyRequestBody.ts | 26 +
.../UpdateCreditSpendPolicyRequestBody.ts | 20 +
.../credits/client/requests/index.ts | 2 +
.../types/CountCreditSpendPoliciesParams.ts | 31 +
.../types/CountCreditSpendPoliciesResponse.ts | 22 +
.../types/CreateCreditSpendPolicyResponse.ts | 21 +
.../types/DeleteCreditSpendPolicyResponse.ts | 21 +
.../types/GetCreditSpendPolicyResponse.ts | 21 +
.../types/ListCreditSpendPoliciesParams.ts | 31 +
.../types/ListCreditSpendPoliciesResponse.ts | 22 +
.../types/UpdateCreditSpendPolicyResponse.ts | 21 +
.../resources/credits/types/index.ts | 8 +
...psertOtlpEnvironmentSettingsRequestBody.ts | 26 +
.../resources/events/client/requests/index.ts | 1 +
.../DeleteOtlpEnvironmentSettingsResponse.ts | 21 +
.../GetOtlpEnvironmentSettingsResponse.ts | 21 +
.../UpsertOtlpEnvironmentSettingsResponse.ts | 21 +
.../resources/events/types/index.ts | 3 +
.../ClaimStripeSandboxKeysRequestBody.ts | 18 +
.../InstallStripeSandboxRequestBody.ts | 24 +
.../integrationsapi/client/requests/index.ts | 2 +
.../types/ClaimStripeSandboxKeysResponse.ts | 21 +
.../GetStripeSandboxClaimLinkResponse.ts | 21 +
.../types/GetStripeSandboxKeysResponse.ts | 21 +
.../InstallStripeClaimableSandboxResponse.ts | 21 +
.../ListStripeSandboxCountriesResponse.ts | 21 +
.../resources/integrationsapi/types/index.ts | 5 +
.../ClaimedStripeSandboxKeysResponseData.ts | 22 +
.../CompanyBillingProfileResponseData.ts | 47 +
.../types/CompanyDetailResponseData.ts | 8 +
.../types/CompanyOverrideResponseData.ts | 5 +
.../types/CreditSpendPolicyResponseData.ts | 35 +
.../types/CreditSpendPolicyScope.ts | 14 +
src/serialization/types/EventBodyInference.ts | 5 +
.../types/GetOnboardingStateResp.ts | 2 +
.../OtlpEnvironmentSettingsResponseData.ts | 32 +
.../types/RuleConditionDetailResponseData.ts | 6 +
.../RuleConditionPlanVersionResponseData.ts | 25 +
.../types/StripeIntegrationConfig.ts | 12 +
.../types/StripeSandboxClaimLink.ts | 24 +
.../StripeSandboxCountriesResponseData.ts | 18 +
.../types/StripeSandboxInstallResponseData.ts | 32 +
.../types/StripeSandboxKeysResponseData.ts | 22 +
src/serialization/types/index.ts | 10 +
tests/conformance/runner.test.ts | 720 ------------
tests/races/harness.ts | 676 -----------
tests/races/prng.ts | 50 -
tests/races/races.test.ts | 311 -----
tests/races/scripted-server.ts | 118 --
tests/wire/accounts.test.ts | 4 +
tests/wire/billing.test.ts | 304 +++++
tests/wire/checkout.test.ts | 144 +++
tests/wire/companies.test.ts | 380 ++++++
tests/wire/components.test.ts | 48 +
tests/wire/credits.test.ts | 920 ++++++++++++++-
tests/wire/entitlements.test.ts | 654 +++++++++-
tests/wire/events.test.ts | 331 ++++++
tests/wire/integrationsapi.test.ts | 661 +++++++++++
tests/wire/plans.test.ts | 106 ++
yarn.lock | 70 +-
139 files changed, 8195 insertions(+), 4909 deletions(-)
delete mode 100644 conformance/SPEC.md
delete mode 100644 conformance/vectors/check-flow.json
delete mode 100644 conformance/vectors/crash-windows.json
delete mode 100644 conformance/vectors/expiry.json
delete mode 100644 conformance/vectors/lease-lifecycle.json
delete mode 100644 conformance/vectors/lease-manager.json
delete mode 100644 conformance/vectors/reservation-lifecycle.json
delete mode 100644 conformance/vectors/track-settle.json
create mode 100644 src/api/errors/PaymentRequiredError.ts
create mode 100644 src/api/resources/billing/client/requests/ListCompanyBillingProfilesRequest.ts
create mode 100644 src/api/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts
create mode 100644 src/api/resources/billing/types/ListCompanyBillingProfilesParams.ts
create mode 100644 src/api/resources/billing/types/ListCompanyBillingProfilesResponse.ts
create mode 100644 src/api/resources/billing/types/UpdateCompanyBillingProfileResponse.ts
create mode 100644 src/api/resources/credits/client/requests/CountCreditSpendPoliciesRequest.ts
create mode 100644 src/api/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts
create mode 100644 src/api/resources/credits/client/requests/ListCreditSpendPoliciesRequest.ts
create mode 100644 src/api/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts
create mode 100644 src/api/resources/credits/types/CountCreditSpendPoliciesParams.ts
create mode 100644 src/api/resources/credits/types/CountCreditSpendPoliciesResponse.ts
create mode 100644 src/api/resources/credits/types/CreateCreditSpendPolicyResponse.ts
create mode 100644 src/api/resources/credits/types/DeleteCreditSpendPolicyResponse.ts
create mode 100644 src/api/resources/credits/types/GetCreditSpendPolicyResponse.ts
create mode 100644 src/api/resources/credits/types/ListCreditSpendPoliciesParams.ts
create mode 100644 src/api/resources/credits/types/ListCreditSpendPoliciesResponse.ts
create mode 100644 src/api/resources/credits/types/UpdateCreditSpendPolicyResponse.ts
create mode 100644 src/api/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts
create mode 100644 src/api/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts
create mode 100644 src/api/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts
create mode 100644 src/api/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts
create mode 100644 src/api/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts
create mode 100644 src/api/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts
create mode 100644 src/api/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts
create mode 100644 src/api/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts
create mode 100644 src/api/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts
create mode 100644 src/api/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts
create mode 100644 src/api/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts
create mode 100644 src/api/types/ClaimedStripeSandboxKeysResponseData.ts
create mode 100644 src/api/types/CompanyBillingProfileResponseData.ts
create mode 100644 src/api/types/CreditSpendPolicyResponseData.ts
create mode 100644 src/api/types/CreditSpendPolicyScope.ts
create mode 100644 src/api/types/OtlpEnvironmentSettingsResponseData.ts
create mode 100644 src/api/types/RuleConditionPlanVersionResponseData.ts
create mode 100644 src/api/types/StripeSandboxClaimLink.ts
create mode 100644 src/api/types/StripeSandboxCountriesResponseData.ts
create mode 100644 src/api/types/StripeSandboxInstallResponseData.ts
create mode 100644 src/api/types/StripeSandboxKeysResponseData.ts
create mode 100644 src/serialization/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts
create mode 100644 src/serialization/resources/billing/types/ListCompanyBillingProfilesParams.ts
create mode 100644 src/serialization/resources/billing/types/ListCompanyBillingProfilesResponse.ts
create mode 100644 src/serialization/resources/billing/types/UpdateCompanyBillingProfileResponse.ts
create mode 100644 src/serialization/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts
create mode 100644 src/serialization/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts
create mode 100644 src/serialization/resources/credits/types/CountCreditSpendPoliciesParams.ts
create mode 100644 src/serialization/resources/credits/types/CountCreditSpendPoliciesResponse.ts
create mode 100644 src/serialization/resources/credits/types/CreateCreditSpendPolicyResponse.ts
create mode 100644 src/serialization/resources/credits/types/DeleteCreditSpendPolicyResponse.ts
create mode 100644 src/serialization/resources/credits/types/GetCreditSpendPolicyResponse.ts
create mode 100644 src/serialization/resources/credits/types/ListCreditSpendPoliciesParams.ts
create mode 100644 src/serialization/resources/credits/types/ListCreditSpendPoliciesResponse.ts
create mode 100644 src/serialization/resources/credits/types/UpdateCreditSpendPolicyResponse.ts
create mode 100644 src/serialization/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts
create mode 100644 src/serialization/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts
create mode 100644 src/serialization/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts
create mode 100644 src/serialization/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts
create mode 100644 src/serialization/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts
create mode 100644 src/serialization/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts
create mode 100644 src/serialization/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts
create mode 100644 src/serialization/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts
create mode 100644 src/serialization/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts
create mode 100644 src/serialization/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts
create mode 100644 src/serialization/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts
create mode 100644 src/serialization/types/ClaimedStripeSandboxKeysResponseData.ts
create mode 100644 src/serialization/types/CompanyBillingProfileResponseData.ts
create mode 100644 src/serialization/types/CreditSpendPolicyResponseData.ts
create mode 100644 src/serialization/types/CreditSpendPolicyScope.ts
create mode 100644 src/serialization/types/OtlpEnvironmentSettingsResponseData.ts
create mode 100644 src/serialization/types/RuleConditionPlanVersionResponseData.ts
create mode 100644 src/serialization/types/StripeSandboxClaimLink.ts
create mode 100644 src/serialization/types/StripeSandboxCountriesResponseData.ts
create mode 100644 src/serialization/types/StripeSandboxInstallResponseData.ts
create mode 100644 src/serialization/types/StripeSandboxKeysResponseData.ts
delete mode 100644 tests/conformance/runner.test.ts
delete mode 100644 tests/races/harness.ts
delete mode 100644 tests/races/prng.ts
delete mode 100644 tests/races/races.test.ts
delete mode 100644 tests/races/scripted-server.ts
diff --git a/.fern/metadata.json b/.fern/metadata.json
index c82cc117..c50fd4be 100644
--- a/.fern/metadata.json
+++ b/.fern/metadata.json
@@ -1,7 +1,7 @@
{
"cliVersion": "5.50.0",
"generatorName": "fernapi/fern-typescript-node-sdk",
- "generatorVersion": "3.88.3",
+ "generatorVersion": "3.90.0",
"generatorConfig": {
"allowCustomFetcher": true,
"includeApiReference": true,
@@ -53,10 +53,10 @@
]
}
},
- "originGitCommit": "686551a0297d2f37075b3586b030ff32be5c94f7",
+ "originGitCommit": "31f498c0a9babdc0eec5ae88e1212a254b2f2561",
"originGitCommitIsDirty": false,
"invokedBy": "ci",
- "requestedVersion": "1.5.11",
+ "requestedVersion": "1.5.12",
"ciProvider": "github",
- "sdkVersion": "1.5.11"
+ "sdkVersion": "1.5.12"
}
diff --git a/conformance/SPEC.md b/conformance/SPEC.md
deleted file mode 100644
index 6191f101..00000000
--- a/conformance/SPEC.md
+++ /dev/null
@@ -1,446 +0,0 @@
-# Credit lease & reservation semantics — conformance spec
-
-This document specifies the client-side credit lease/reservation semantics implemented by the
-Schematic Node SDK (the reference implementation), in enough detail to reimplement them in another
-language without reading the Node source. The machine-readable test vectors in
-`conformance/vectors/*.json` pin the observable behavior; this spec explains the model, the
-configuration knobs, and the invariants that cannot be expressed as deterministic vectors.
-
-Where this document and the vectors disagree, the vectors win — they are generated from the
-reference implementation's behavior.
-
-- [Vector format](#vector-format)
-- [Model overview](#model-overview)
-- [State](#state)
-- [Store operations](#store-operations)
-- [Lease manager](#lease-manager)
-- [Check flow](#check-flow)
-- [Track / settle flow](#track--settle-flow)
-- [Configuration knobs](#configuration-knobs)
-- [Bounded-leak contract](#bounded-leak-contract)
-- [Invariants not expressible as vectors](#invariants-not-expressible-as-vectors)
-
-## Vector format
-
-Each file in `conformance/vectors/` is a JSON document:
-
-```json
-{
- "category": "reservation_lifecycle",
- "vectors": [
- {
- "name": "unique_snake_case_name",
- "description": "What this vector pins and why.",
- "backends": ["in_memory", "redis"],
- "given": {
- "config": { "lease_duration_ms": 300000, "reservation_ttl_ms": 60000, "lease_size": 1000, "low_water_mark": 0.25 },
- "leases": [ { "lease_id": "lse_1", "company_id": "co_1", "credit_type_id": "ct_1", "granted_amount": 1000, "expires_at_ms": 60000 } ]
- },
- "operations": [
- { "op": "try_reserve", "company_id": "co_1", "credit_type_id": "ct_1", "credits": 100, "expect": { "balance": 900 } }
- ]
- }
- ]
-}
-```
-
-Rules:
-
-- All keys are `snake_case`. Vectors are plain JSON — no language-specific types.
-- **Virtual clock.** The run starts at a fixed virtual instant `t0`. Every `*_at_ms` field is an
- offset in milliseconds from `t0` (an absolute position on the virtual timeline, not relative to
- the current operation). The `advance_clock` operation moves the clock forward; nothing else does.
- Runners must execute vectors against a controllable clock (no wall time).
-- `backends` restricts which store backends the vector runs against; when omitted, the vector must
- pass against every backend the SDK ships (in-memory and Redis for Node).
-- `given.leases` are installed via the store's `replace` operation at `t0` (each install must
- return "written").
-- Assertions are attached per-operation via `expect`. Final-state assertions are expressed as
- trailing read operations (`get_lease`, `reserved_credits`, `reservation_count`).
-- `expect.balance` / `expect.consumed` use JSON `null` for the "no / refused" result.
-- Reservation ids created by `check` operations are random; the vector names them via
- `save_reservation_as` and later operations reference them with `handle`.
-
-### Operations
-
-Store-level (exercise the lease store and reservation store directly):
-
-| op | fields | expect |
-| --- | --- | --- |
-| `advance_clock` | `ms` | — |
-| `replace_lease` | `lease_id`, `company_id`, `credit_type_id`, `granted_amount`, `expires_at_ms` | `written` (bool) |
-| `drop_lease` | `company_id`, `credit_type_id` | — |
-| `try_reserve` | `company_id`, `credit_type_id`, `credits` | `balance` (post-debit number, or `null`) |
-| `refund_lease` | `company_id`, `credit_type_id`, `credits`, `pin_lease_id`? | — |
-| `extend_lease` | `company_id`, `credit_type_id`, `granted_total`, `expires_at_ms`?, `pin_lease_id`? | — |
-| `get_lease` | `company_id`, `credit_type_id` | `exists`, `lease_id`?, `granted_amount`?, `local_remaining_credits`? |
-| `add_reservation` | `id`, `lease_id`, `company_id`, `credit_type_id`, `event_subtype`, `quantity_reserved`, `credits_reserved`, `consumption_rate`, `expires_at_ms` | — |
-| `consume_reservation` | `id` or `handle`, `credits`, `crash_before_refund`? (bool, one-shot) | `consumed` (number or `null`), `throws`? |
-| `get_reservation` | `id` or `handle` | `exists` |
-| `reserved_credits` | `company_id`, `credit_type_id` | `total` |
-| `reservation_count` | — | `count` |
-| `sweep_expired` | — | `swept` |
-
-Manager-level (exercise the lease manager with a scripted wire client):
-
-| op | fields | expect |
-| --- | --- | --- |
-| `acquire_if_needed` | `company_id`, `credit_type_id`, `server`? ( `{ "lease": {...} }` or `{ "error": "..." }` ), `install_during_wire`? (lease installed into the store while the wire call is in flight, emulating a sibling pod winning the race) | `lease_id` (or `null`), `wire_acquires` (cumulative count), `last_acquire_requested_amount`?, `released_lease_ids` (cumulative) |
-| `maybe_extend` | `company_id`, `credit_type_id`, `required_credits`?, `server`? ( `{ "lease": { "granted_total", "expires_at_ms" } }` or `{ "error": "..." }` ) | `wire_extends` (cumulative count), `last_extend_additional_amount`?, `last_extend_lease_id`? |
-| `release_all_local_leases` | — (in-memory backend only) | `released_lease_ids`, `remaining_slots` |
-
-Flow-level (exercise the full check/track orchestration with a scripted rules engine):
-
-| op | fields | expect |
-| --- | --- | --- |
-| `check` | `flag_key`, `company` (`{ id, credit_balances }`), `usage`, `event_subtype`?, `on_acquire_failure`?, `engine` (array of scripted engine results, consumed in call order), `server`? (as above), `save_reservation_as`? | `allowed`, `reason`?, `err`?, `has_reservation`, `reservation`? (field subset), `fallback_called`?, `engine_calls`? (per-call `{ credit_balance, credit_cost?, event_usage? }`; `credit_balance` may be the string `"max_safe_integer"`) |
-| `track` | `handle`, `actual_quantity` | `settled_locally`, `track` (`{ event, quantity, lease_id }`) |
-
-A scripted engine result is `{ "value": bool, "reason"?: string, "entitlement"?: { "value_type",
-"credit_id"?, "consumption_rate"?, "event_subtype"?, "feature_id"?, "feature_key"? } }`. The engine
-is an oracle: the vectors pin the *orchestration around* the rules engine (what it is called with,
-and what the SDK does with its answer), not the engine itself — the engine is shared WASM across
-SDKs and has its own tests.
-
-## Model overview
-
-Credit-metered features are gated client-side without a wire call per check. The SDK:
-
-1. **Leases** a tranche of credits from the server per `(company_id, credit_type_id)`. The server
- pre-debits the company balance by the granted amount; the SDK tracks a local view of how much
- of the tranche remains un-reserved (`local_remaining_credits`).
-2. **Reserves** `usage x consumption_rate` credits from the lease at `check()` time, atomically
- (check-and-debit). A successful, engine-approved check returns a *reservation handle*.
-3. **Settles** the reservation at `track()` time with the actual usage: the actually-consumed
- credits stay debited, the unspent slice is refunded to the lease, and a Track event bills the
- server (the server is the source of truth for real consumption).
-
-Everything client-side is *local bookkeeping against the leased tranche*. The server reconciles:
-an expired lease's unspent remainder is refunded to the company balance server-side, and Track
-events (keyed by `lease_id`) drive the authoritative consumption.
-
-Leases and reservations both expire:
-
-- A **lease** past its expiry must be treated as *released* — its local balance is stale (the
- server already refunded the remainder) and must never serve another reserve or be extended.
-- A **reservation** past its TTL is swept: removed from the table and its full hold refunded to
- the lease. Work that finishes after the sweep still bills the server (recovery emit) but does
- not re-debit the local lease.
-
-## State
-
-**Lease slot** — at most one lease per `(company_id, credit_type_id)` key:
-
-| field | meaning |
-| --- | --- |
-| `lease_id` | Server-issued id. |
-| `granted_amount` | Server-authoritative total granted to this lease (grows on extend). |
-| `local_remaining_credits` | Local view: granted minus outstanding holds/consumption. Initialized to `granted_amount` on install. |
-| `expires_at` | Expiry instant. Past it the lease is dead (see above). |
-
-**Reservation** — keyed by a unique id:
-
-| field | meaning |
-| --- | --- |
-| `id` | Unique (UUID in Node). |
-| `lease_id` | The lease the hold was carved from. Pins refunds. |
-| `company_id`, `credit_type_id` | Slot key. |
-| `event_subtype` | Event the settle will bill as. |
-| `quantity_reserved` | Caller-declared usage (event units). |
-| `credits_reserved` | `quantity_reserved x consumption_rate`. |
-| `consumption_rate` | Rate at reservation time. |
-| `expires_at` | Reservation TTL deadline (sweep target). |
-| `eval_ctx` | Company/user keys used at check time; threaded onto the Track event. |
-
-## Store operations
-
-These are the primitives both store backends (per-process in-memory; shared Redis) must implement
-with identical observable semantics. Each mutation must be atomic per slot/reservation (see
-[Invariants](#invariants-not-expressible-as-vectors)).
-
-### `replace(lease)` — install-if-not-live
-
-Install a fresh lease with `local_remaining_credits = granted_amount`, **only if** the slot is
-empty or the existing lease is expired *and carries a different `lease_id`*. If a *live* lease
-occupies the slot — even with a different `lease_id` (a sibling pod won the race) — leave it
-untouched (its already-debited balance wins) and report "kept". If an *expired* lease with the
-**same** `lease_id` occupies the slot (a stale acquire response for a lease the idempotent server
-also handed to a racing sibling, which may since have extended it), do not rewrite it either:
-rewriting would reset `local_remaining_credits` to the full grant and erase debits whose
-reservations are still open. Reconcile it like `extend` instead — granted to the incoming total
-(lower/equal totals are no-ops), expiry only forward, balance untouched — and report "kept".
-Returns written/kept so the caller can run the redundant-lease release logic (see manager).
-
-### `try_reserve(company, credit, credits)` — atomic check-and-debit
-
-- Reject (return `null`, touch nothing) if: no lease in the slot; the lease is **expired**; the
- remaining balance is `< credits`; or `credits` is not a finite non-negative number (NaN must
- never reach the arithmetic — it slips through every comparison and would poison the balance
- into approving everything).
-- Otherwise debit and return the **post-debit balance** (so the caller can derive the pre-debit
- figure as `returned + credits` without a racy follow-up read).
-- Reserving down to exactly 0 is allowed.
-
-### `refund(company, credit, credits, pin_lease_id?)`
-
-Add credits back to `local_remaining_credits`, **clamped at `granted_amount`**. No-op if
-`credits <= 0` or no lease is in the slot. When `pin_lease_id` is given, the refund applies
-**only if** the slot still holds that lease: a hold carved out of expired lease A must never
-inflate successor lease B — A's remainder (including this slice) was already refunded to the
-company balance server-side when A expired, so crediting B would double-count.
-
-### `extend(company, credit, granted_total, new_expires_at?, pin_lease_id?)` — reconcile to total
-
-After a remote extend, reconcile the slot to the **server-authoritative total**:
-
-- Compute `delta = granted_total - stored granted_amount` **atomically against the currently
- stored total** — never from a caller-held pre-wire-call read (two pods extending concurrently
- from the same stale read would each apply a delta and mint phantom credits). If `delta > 0`,
- set `granted_amount = granted_total` and add `delta` to `local_remaining_credits`. If
- `delta <= 0` (a total a sibling already applied, or a stale lower total) it is a **no-op** —
- applies converge in any order.
-- Expiry only ever moves **forward**: `new_expires_at` is applied only if later than the stored
- expiry, so an out-of-order apply cannot shorten a lease a sibling just extended.
-- When `pin_lease_id` is given and the slot holds a different lease, drop the whole extend
- (credits and expiry): the server granted the extension to the pinned lease; crediting a
- successor would mint credits the server refunds with the pinned lease at its expiry.
-- No-op if the slot is empty.
-
-### `drop(company, credit)`
-
-Remove the slot entry (after a remote release). Plain delete.
-
-### Reservation table: `add`, `get`, `consume`, `reserved_credits`, `sweep_expired`
-
-- `add(reservation)` — register. Idempotent on id. `add` does NOT debit the lease; the debit
- already happened in `try_reserve` (see [ordering](#bounded-leak-contract)).
-- `consume(id, credits_consumed)` — **exactly-once claim**: atomically remove the reservation
- from the table; if it was already gone (swept, or consumed by a racing caller) return `null`
- and touch nothing. On a successful claim, clamp `credits_consumed` to
- `[0, credits_reserved]`, refund `credits_reserved - clamped` to the lease (pinned to the
- reservation's `lease_id`), and return the clamped figure. The claim and the refund are two
- steps; the claim is the arbiter (see bounded-leak contract).
-- `reserved_credits(company, credit)` — sum of `credits_reserved` across open reservations for
- the slot. A reservation counts iff it is still in the table, so
- `local_remaining_credits + reserved_credits` stays exact between operations.
-- `sweep_expired(now)` — remove every reservation with `expires_at <= now` and refund its full
- hold to its lease (pinned to its `lease_id`; a stale-lease hold is dropped, not refunded).
- Returns the number swept. Runs on a background interval (`sweep_interval_ms`) in production;
- vectors call it explicitly.
-
-## Lease manager
-
-Owns the lease lifecycle against the server wire API (`acquire`, `extend`, `release`).
-
-### Acquire (`acquire_if_needed`)
-
-- If the slot holds a **live** lease, return it — no wire call.
-- Otherwise call the server: `requested_amount = lease_size`, `expires_at = now +
- lease_duration_ms`. An expired local entry is left in place for `replace` to overwrite
- atomically (deleting it first would open a race window against sibling pods; every reader
- re-guards on expiry anyway).
-- On response, `replace` the slot. If `replace` kept an existing lease (a sibling won, or the
- slot's expired row was reconciled in place):
- - If the installed lease has a **different id** than the one the server handed us, ours is a
- redundant hold nobody will draw on — release it (fire-and-forget; a failed release falls
- back to server-side lease expiry).
- - If the ids are the **same** (the server is idempotent for an active slot and handed the
- racing acquire the sibling's lease back), release **nothing** — releasing would pull the
- shared lease out from under every sibling.
- - If the slot reads empty (expired in the gap), also release nothing.
- - Either way, return whatever the slot now holds.
-- Wire or store failure: return "no lease" (never throw) — the caller routes it through
- fail-open/fail-closed.
-- Per-process single-flight per slot: concurrent callers share one in-flight wire call
- (best-effort; duplicates are absorbed by the idempotent server + `replace`).
-
-### Extend (`maybe_extend`)
-
-Triggered when EITHER:
-
-- `local_remaining_credits / max(granted_amount, 1) <= low_water_mark` (steady-state refresh), or
-- the caller passes `required_credits` and `local_remaining_credits < required_credits` (a check
- just failed a reserve of that size — extend opportunistically).
-
-Rules:
-
-- **Never extend an expired lease** — the server treats it as released; the right move is a fresh
- acquire on the next check.
-- Wire body: `additional_amount = max(lease_size, required_credits - local_remaining_credits)`.
- Sizing to the shortfall matters: a single check needing more than `remaining + lease_size`
- would otherwise fail its post-extend retry forever regardless of server balance.
- `expires_at = now + lease_duration_ms`.
-- On response, reconcile via the store's `extend` with the server's **total** and new expiry,
- **pinned** to the extended lease's id.
-- Failures resolve to "no lease" without throwing (often fire-and-forget).
-- Per-process single-flight per slot, kept separate from acquire's (an in-flight extend must not
- satisfy an acquire, or vice versa).
-
-### Release on close (`release_all_local_leases`)
-
-Only for a **per-process (in-memory) store**, whose leases are exclusively this process's:
-release every live lease over the wire (returning the unspent remainder to the company balance
-immediately) and drop it locally; **skip expired** leases (already swept server-side). A shared
-(Redis) store must never do this — sibling pods still draw on those leases. Best-effort:
-failures fall back to server-side expiry.
-
-## Check flow
-
-`check(eval_ctx, flag_key, { usage, event_subtype?, on_acquire_failure?, ... })` — the
-lease-gated feature check. Fallback = the plain (non-lease) flag check, which has its own
-degradation story; when the flow "falls back", no reservation is issued and no lease state is
-touched beyond what already happened.
-
-Guards, in order:
-
-1. `usage` missing → plain check (lease path not requested).
-2. `usage` not a finite non-negative number → resolve **statically** by `on_acquire_failure`
- (deny for fail-closed; blanket allow for fail-open, reason `invalid_usage`). The value must
- never reach the stores.
-3. `usage == 0` → nothing to reserve; fall back to the plain check (no 0-credit reservation).
-4. No datastream / cached flag / resolvable company (or named user) → fall back.
-
-Then:
-
-5. **Entitlement probe.** Run the rules engine once against the company's *real* balance — no
- substitution, no credit-cost preflight (a preflight against the lease-depleted server balance
- could fail the credit condition and hide the entitlement being probed for). Read the matched
- entitlement's shape:
- - Not credit-metered (`value_type != "credit"`: boolean/override grant, numeric allocation,
- unlimited, or not entitled) → **fall back**, no lease traffic at all.
- - Credit entitlement missing `credit_id`, a positive `consumption_rate`, or a resolvable
- `event_subtype` (caller's explicit subtype wins over the entitlement's) → fall back.
- - Probe error → fall back (it is a resolution step, not the gate).
-6. `credit_cost = usage x consumption_rate`.
-7. **Acquire** a lease for `(company, credit_id)`. Failure → [failure handling](#failure-handling)
- with reason `lease_acquire_failed`.
-8. **Reserve** `credit_cost` via `try_reserve`. On refusal, opportunistically
- `maybe_extend(required_credits = credit_cost)` (awaited) and retry the reserve **once**.
- Still refused → failure handling, reason `insufficient_lease_balance`. Store error →
- failure handling, reason `lease_store_error`.
-9. **Record the reservation** (TTL = `reservation_ttl_ms` from now) — *after* the debit, *before*
- the engine gate. If persisting fails, undo the debit (claim-and-refund; direct refund if
- nothing persisted; both pinned to the lease) and go to failure handling
- (`lease_store_error`). If even the undo fails, accept the bounded leak.
-10. **Engine gate.** Re-run the engine against a company snapshot whose
- `credit_balances[credit_id]` is substituted with the **pre-reservation** local balance
- (post-debit balance returned by `try_reserve` + `credit_cost` — exact as of the debit, no
- read race), passing `credit_cost = { credit_id: credit_cost }` so the engine evaluates
- `pre_reservation - credit_cost >= 0` — the same arithmetic `try_reserve` just enforced, plus
- every non-credit rule (plan targeting, overrides).
- - Engine **allows** → keep the hold; return `{ allowed: true, reservation }`. Fire-and-forget
- a watermark-driven `maybe_extend`.
- - Engine **denies** → cancel the reservation (claim + full refund) and return
- `{ allowed: false }` with the engine's reason.
- - Engine **errors** → cancel the reservation and resolve **statically** by mode (the engine
- itself is down, so no fail-open re-evaluation is possible).
-
-### Failure handling
-
-Every can't-gate outcome (acquire failed, store unreachable, lease exhausted) funnels through the
-configured `on_acquire_failure` mode (default **fail-closed**):
-
-- **fail-closed** → `{ allowed: false }`, reason = the failure reason. No reservation.
-- **fail-open** → *err on the side of assuming the credits are there*, **not** blanket allow:
- re-run the engine with the credit balance substituted to an effectively unlimited value
- (`MAX_SAFE_INTEGER` in Node) and the caller's usage preflight threaded through. Plan
- targeting, overrides, and every non-credit condition still apply — a company that is not
- entitled stays **denied** even with the lease backend down. No reservation is issued either
- way; `err` carries the failure reason. Only if that evaluation itself errors does the SDK
- fall back to a blanket allow.
-
-## Track / settle flow
-
-`track_with_reservation(reservation, actual_quantity)` settles a reservation:
-
-1. `credits = actual_quantity x reservation.consumption_rate`.
-2. `consume(reservation.id, credits)`:
- - **Settled locally** (claim succeeded): the clamped consumed slice stays debited; the unspent
- slice is refunded to the lease (pinned).
- - **Not settled** (`null`: already swept after TTL, already consumed, or store unreachable):
- local lease state is untouched — if the sweeper already refunded the full hold, nothing
- re-debits the consumed slice, so the local balance reads **high** until the lease rolls
- over. This is why `reservation_ttl_ms` should exceed the longest expected gap between
- `check()` and `track_with_reservation()`.
-3. Either way, emit the Track event built from the **caller-held handle** (not the store):
- `event = event_subtype`, `quantity = actual_quantity` (the *unclamped* actual — the server is
- the source of truth for real consumption; only local bookkeeping clamps to the reserved
- amount), `lease_id = reservation.lease_id` (routes the server-side consumption through the
- lease's sub-ledger instead of double-debiting the pre-debited grant), plus the reservation's
- `eval_ctx` company/user and any caller traits.
-4. The Track carries a deterministic idempotency key derived from the reservation id
- (`"lease-reservation:" + reservation.id` in Node); the server dedupes by it for 24h, so a
- recovery emit racing the normal emit, or an accidental double settle, collapses to one billed
- event across pods and restarts.
-5. Guard: a non-finite or negative `actual_quantity` skips the settle entirely (no store call, no
- event) — the untouched reservation expires at its TTL and the sweeper refunds the full hold.
-
-## Configuration knobs
-
-| knob (vector key) | Node name | default | meaning |
-| --- | --- | --- | --- |
-| `lease_duration_ms` | `defaultLeaseDuration` | 300 000 (5 min) | Lease lifetime requested at acquire/extend (`expires_at = now + duration`). |
-| `reservation_ttl_ms` | `defaultReservationTTL` | 60 000 (60 s) | Reservation lifetime; the sweep deadline. Size above the longest expected check→track gap. |
-| `lease_size` | `defaultLeaseSize` | 10 000 | Credits requested per acquire, and the minimum extend tranche. |
-| `low_water_mark` | `lowWaterMark` | 0.25 | Remaining/granted ratio at or below which a background extend is kicked off. |
-| `sweep_interval_ms` | `sweepIntervalMs` | 1 000 | Expired-reservation sweep cadence. |
-| — | `onAcquireFailure` | `fail-closed` | Per-check failure mode (see check flow). |
-
-Per-credit-type overrides of the first four are supported (keyed by credit type id); resolution is
-override → client config → default.
-
-## Bounded-leak contract
-
-The flow deliberately orders its two-step transitions so that a process crash between steps leaks
-*locally held credits* (which the server reclaims at lease expiry) rather than enabling a
-double-spend. The invariant direction is always: **the debit/claim is durable first; the
-record/refund may be lost.**
-
-| # | crash window | what leaks | bound | reclaimed by | must NOT happen |
-| --- | --- | --- | --- | --- | --- |
-| 1 | after `try_reserve` (debit), before `add` (record) | the debited hold — invisible to the reservation table, so the sweeper can never refund it | `credits_reserved` of that one check | lease expiry: the expired balance is never served again, and the server refunds the whole grant; the successor lease installs at full grant | a reservation record without a debit (a later consume would refund credits never held → double-spend). Vectors pin that the debit lands strictly before the record. |
-| 2 | inside `consume`: after the claim, before the refund | the unspent slice of that reservation | `credits_reserved` of that one reservation | lease expiry (same mechanism) | a double refund: the claim is exactly-once, so a retried settle or a sweeper finds nothing to claim and refunds nothing |
-| 3 | (Redis only) after the claim, before index cleanup | nothing (bookkeeping only): the per-slot reserved-credits index transiently over-counts | one index field | the sweeper reconciles the orphaned index entry — **without refunding** (without the claimed record, exactly-once cannot be arbitrated across racing sweepers) | a refund driven by an index entry alone |
-
-Additional pinned properties:
-
-- A leak never survives its lease: after lease expiry the stale balance is refused
- (`try_reserve → null`) and a successor lease restores the full grant.
-- A retried check after a window-1 crash settles independently: its own slice refunds exactly
- once; the leaked slice never refunds.
-- A late retried settle after a window-2 crash (even after a successor lease is installed)
- refunds nothing into the successor.
-
-## Invariants not expressible as vectors
-
-These hold in the reference implementation but need concurrency, wall clocks, or non-JSON values
-to demonstrate; ports must uphold them and should test them natively.
-
-1. **Per-slot atomicity.** `replace`, `try_reserve`, `refund`, `extend` are atomic per lease
- slot; `consume`'s claim is atomic per reservation. In-memory: per-key mutual exclusion. Redis:
- single-key Lua scripts (single-key keeps them Redis-Cluster-safe; the refund to the lease hash
- is deliberately a separate single-key step, never a multi-key script — see leak window 2/3).
-2. **Server-clock expiry (shared backend).** With a shared store, lease expiry must be decided
- against the *store's* clock (Redis `TIME`), not the calling process's — pods with skewed
- clocks must agree on liveness. Backend rows carry a TTL grace window past `expires_at`
- (60 s lease / 30 s reservation in Node) so the sweeper can still read them; expired-but-not-
- evicted rows must still refuse reserves.
-3. **NaN/precision guards.** Non-finite or negative amounts are rejected at every boundary
- (`usage`, `try_reserve`, `actual_quantity`) — JSON cannot encode NaN, so vectors only cover
- the negative case. Fractional credit amounts are legal throughout (rates like 0.1); Redis
- stores balances as strings to avoid integer truncation.
-4. **Single-flight.** Per-process, per-slot single-flight for acquire and for extend, tracked
- separately. Best-effort only: duplicate wire calls are safe (idempotent server + keep-first
- `replace` + reconcile-to-total `extend`).
-5. **Concurrent cross-pod extends converge.** Two pods extending from the same stale read must
- not double-count — guaranteed by reconcile-to-total computed inside the store (the sequential
- out-of-order-totals vector pins the arithmetic; the concurrent schedule needs a race).
-6. **Idempotent billing.** The Track idempotency key is deterministic from the reservation id;
- the server dedupes for 24h. Double settles and recovery emits collapse to one billed event.
-7. **Background sweep loop.** `start_sweep`/`stop` run `sweep_expired` on an interval; timers
- must not keep the process alive. Vectors call `sweep_expired` explicitly instead.
-8. **Fire-and-forget never rejects.** `acquire_if_needed`, `maybe_extend`, and release paths
- resolve (to "no lease") on failure rather than rejecting — they are often unawaited.
-9. **Offline/unconfigured degradation.** Lease config absent → `check` is a plain flag check;
- `track_with_reservation` on an unconfigured client still emits the billing event with the
- `lease_id` and idempotency key intact.
diff --git a/conformance/vectors/check-flow.json b/conformance/vectors/check-flow.json
deleted file mode 100644
index eff99903..00000000
--- a/conformance/vectors/check-flow.json
+++ /dev/null
@@ -1,527 +0,0 @@
-{
- "category": "check_flow",
- "vectors": [
- {
- "name": "check_happy_path_gates_on_pre_reservation_balance",
- "description": "A lease-bearing check: probe against the real balance (no substitution, no credit cost), reserve usage x rate from the lease, then gate the engine on the PRE-reservation local balance with credit_cost — the same arithmetic the atomic reserve just enforced. The hold sticks only because the engine allowed.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "save_reservation_as": "r1",
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": true, "reason": "ok" }
- ],
- "expect": {
- "allowed": true,
- "has_reservation": true,
- "reservation": {
- "lease_id": "lse_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10
- },
- "engine_calls": [{ "credit_balance": 5000 }, { "credit_balance": 1000, "credit_cost": 100 }]
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- },
- { "op": "reserved_credits", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "total": 100 } }
- ]
- },
- {
- "name": "check_denied_by_engine_cancels_the_hold",
- "description": "When the gate evaluation denies, the reservation made before the eval is cancelled: claimed and fully refunded, leaving no hold and no reservation.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": false, "reason": "denied_by_targeting" }
- ],
- "expect": { "allowed": false, "reason": "denied_by_targeting", "has_reservation": false }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- },
- { "op": "reserved_credits", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "total": 0 } },
- { "op": "reservation_count", "expect": { "count": 0 } }
- ]
- },
- {
- "name": "check_acquire_failure_fail_closed_denies",
- "description": "fail-closed (the default): when no lease can be acquired the check denies outright with the failure reason; no reservation is issued.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "on_acquire_failure": "fail-closed",
- "server": { "acquire": { "error": "wire down" } },
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- }
- ],
- "expect": {
- "allowed": false,
- "reason": "lease_acquire_failed",
- "err": "lease_acquire_failed",
- "has_reservation": false
- }
- },
- { "op": "reservation_count", "expect": { "count": 0 } }
- ]
- },
- {
- "name": "check_acquire_failure_fail_open_reevaluates",
- "description": "fail-open is NOT blanket allow: the engine re-runs with the credit balance substituted to an effectively unlimited value and the caller's usage preflight threaded through, so non-credit rules still apply. Here they pass, so the check allows — with the failure recorded in err and no reservation.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "on_acquire_failure": "fail-open",
- "server": { "acquire": { "error": "wire down" } },
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": true, "reason": "evaluated" }
- ],
- "expect": {
- "allowed": true,
- "reason": "evaluated (lease_acquire_failed_fail_open)",
- "err": "lease_acquire_failed",
- "has_reservation": false,
- "engine_calls": [
- { "credit_balance": 5000 },
- {
- "credit_balance": "max_safe_integer",
- "event_usage": { "event_subtype": "inference_tokens", "quantity": 10 }
- }
- ]
- }
- },
- { "op": "reservation_count", "expect": { "count": 0 } }
- ]
- },
- {
- "name": "check_fail_open_still_denies_when_rules_deny",
- "description": "fail-open with a denying rules evaluation stays denied: substituting an unlimited balance only bypasses the credit gate, never plan targeting or overrides.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "on_acquire_failure": "fail-open",
- "server": { "acquire": { "error": "wire down" } },
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": false, "reason": "not_targeted" }
- ],
- "expect": {
- "allowed": false,
- "reason": "not_targeted (lease_acquire_failed_fail_open)",
- "err": "lease_acquire_failed",
- "has_reservation": false
- }
- }
- ]
- },
- {
- "name": "check_insufficient_lease_extends_and_retries",
- "description": "A reserve refusal triggers an awaited opportunistic extend sized to cover the request (required_credits = credit_cost), then exactly one reserve retry. On success the check proceeds normally, gating on the post-extend pre-reservation balance.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 950,
- "expect": { "balance": 50 }
- },
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "server": { "extend": { "lease": { "granted_total": 2000, "expires_at_ms": 600000 } } },
- "save_reservation_as": "r1",
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": true, "reason": "ok" }
- ],
- "expect": {
- "allowed": true,
- "has_reservation": true,
- "wire_extends": 1,
- "last_extend_additional_amount": 1000,
- "engine_calls": [{ "credit_balance": 5000 }, { "credit_balance": 1050, "credit_cost": 100 }]
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 2000, "local_remaining_credits": 950 }
- }
- ]
- },
- {
- "name": "check_insufficient_lease_after_failed_extend_resolves_by_mode",
- "description": "When the opportunistic extend fails and the retry is still refused, the check resolves through the failure mode (fail-closed here) with reason insufficient_lease_balance, leaving the lease balance untouched.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 950,
- "expect": { "balance": 50 }
- },
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "on_acquire_failure": "fail-closed",
- "server": { "extend": { "error": "wire down" } },
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- }
- ],
- "expect": {
- "allowed": false,
- "reason": "insufficient_lease_balance",
- "err": "insufficient_lease_balance",
- "has_reservation": false
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 50 }
- },
- { "op": "reservation_count", "expect": { "count": 0 } }
- ]
- },
- {
- "name": "check_falls_back_without_usable_credit_entitlement",
- "description": "A non-credit matched entitlement (boolean/override/numeric/unlimited/not entitled) or an incomplete credit entitlement (no positive consumption rate) defers to the plain check: no lease traffic, no reservation.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": {} },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "engine": [{ "value": true, "reason": "probe", "entitlement": { "value_type": "boolean" } }],
- "expect": { "fallback_called": true, "reason": "fallback", "has_reservation": false }
- },
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 0,
- "event_subtype": "inference_tokens"
- }
- }
- ],
- "expect": { "fallback_called": true, "reason": "fallback", "has_reservation": false }
- },
- { "op": "reservation_count", "expect": { "count": 0 } }
- ]
- },
- {
- "name": "check_zero_usage_falls_back",
- "description": "usage = 0 means nothing to reserve: the check defers to the plain (preflight-threaded) check instead of issuing a no-op 0-credit reservation.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 0,
- "event_subtype": "inference_tokens",
- "engine": [],
- "expect": { "fallback_called": true, "reason": "fallback", "has_reservation": false }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- }
- ]
- },
- {
- "name": "check_invalid_usage_resolves_statically_by_mode",
- "description": "A negative (or non-finite) usage must never reach the stores; the check resolves statically by mode without any engine evaluation: deny for fail-closed, blanket allow for fail-open, reason invalid_usage either way.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": -5,
- "event_subtype": "inference_tokens",
- "on_acquire_failure": "fail-closed",
- "engine": [],
- "expect": {
- "allowed": false,
- "reason": "invalid_usage",
- "err": "invalid_usage",
- "has_reservation": false,
- "engine_calls": []
- }
- },
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": -5,
- "event_subtype": "inference_tokens",
- "on_acquire_failure": "fail-open",
- "engine": [],
- "expect": {
- "allowed": true,
- "reason": "invalid_usage_fail_open",
- "err": "invalid_usage",
- "has_reservation": false,
- "engine_calls": []
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- }
- ]
- }
- ]
-}
diff --git a/conformance/vectors/crash-windows.json b/conformance/vectors/crash-windows.json
deleted file mode 100644
index c8ee05b9..00000000
--- a/conformance/vectors/crash-windows.json
+++ /dev/null
@@ -1,271 +0,0 @@
-{
- "category": "crash_window",
- "vectors": [
- {
- "name": "debit_without_record_leaks_bounded",
- "description": "Crash window 1 (debit-then-add): the atomic debit landed but the reservation record never did. The leak is exactly the reserved amount; the sweeper can never refund a hold that was never recorded.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- { "op": "reserved_credits", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "total": 0 } },
- { "op": "advance_clock", "ms": 55000 },
- { "op": "sweep_expired", "expect": { "swept": 0 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- }
- ]
- },
- {
- "name": "debit_leak_reclaimed_at_lease_expiry",
- "description": "Crash window 1 recovery: the leaked balance is never served after lease expiry, and the successor lease installs at the full grant — the leak does not outlive the lease.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 1,
- "expect": { "balance": null }
- },
- {
- "op": "replace_lease",
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 180000,
- "expect": { "written": true }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- }
- ]
- },
- {
- "name": "retried_check_after_debit_leak_settles_once",
- "description": "A retry after a window-1 crash is a fresh check with a fresh reservation: its unspent slice refunds exactly once; the leaked slice never refunds — not on a repeat consume, not on a sweep.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 3600000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 800 }
- },
- {
- "op": "add_reservation",
- "id": "res_retry",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- { "op": "consume_reservation", "id": "res_retry", "credits": 40, "expect": { "consumed": 40 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 860 }
- },
- { "op": "consume_reservation", "id": "res_retry", "credits": 40, "expect": { "consumed": null } },
- { "op": "advance_clock", "ms": 70000 },
- { "op": "sweep_expired", "expect": { "swept": 0 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 860 }
- }
- ]
- },
- {
- "name": "crash_before_refund_claim_is_durable",
- "description": "Crash window 2 (consume-then-refund): the claim survives the crash, so the reservation is gone everywhere and nothing can double-spend; the unspent slice's refund is lost, bounded by credits_reserved. A retried settle neither re-claims nor double-refunds, and the sweeper cannot refund a claimed reservation.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 3600000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- {
- "op": "consume_reservation",
- "id": "res_1",
- "credits": 30,
- "crash_before_refund": true,
- "expect": { "throws": true }
- },
- { "op": "get_reservation", "id": "res_1", "expect": { "exists": false } },
- { "op": "reserved_credits", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "total": 0 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 30, "expect": { "consumed": null } },
- { "op": "advance_clock", "ms": 70000 },
- { "op": "sweep_expired", "expect": { "swept": 0 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- }
- ]
- },
- {
- "name": "crash_before_refund_reclaimed_at_lease_expiry",
- "description": "Crash window 2 recovery: after the lease expires and a successor takes the slot at full grant, a very late retried settle of the crashed reservation must not leak the lost refund into the successor.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- {
- "op": "consume_reservation",
- "id": "res_1",
- "credits": 30,
- "crash_before_refund": true,
- "expect": { "throws": true }
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 1,
- "expect": { "balance": null }
- },
- {
- "op": "replace_lease",
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 180000,
- "expect": { "written": true }
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 0, "expect": { "consumed": null } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "lease_id": "lse_2", "local_remaining_credits": 1000 }
- }
- ]
- }
- ]
-}
diff --git a/conformance/vectors/expiry.json b/conformance/vectors/expiry.json
deleted file mode 100644
index e1f7e2cc..00000000
--- a/conformance/vectors/expiry.json
+++ /dev/null
@@ -1,198 +0,0 @@
-{
- "category": "expiry",
- "vectors": [
- {
- "name": "expired_lease_never_serves_reserves",
- "description": "Past its expiry a lease's balance is stale (the server refunded the grant): reserves are refused even with ample local balance.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 1,
- "expect": { "balance": null }
- }
- ]
- },
- {
- "name": "successor_after_expiry_restores_full_grant",
- "description": "A successor lease installed over an expired slot starts at its full grant — nothing from the expired lease (debits or leaks) carries over.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 700,
- "expect": { "balance": 300 }
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "replace_lease",
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 180000,
- "expect": { "written": true }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "lease_id": "lse_2", "local_remaining_credits": 1000 }
- }
- ]
- },
- {
- "name": "sweep_refunds_expired_holds_only",
- "description": "The sweeper refunds an expired reservation's full hold to its lease and leaves live reservations untouched.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 300,
- "expect": { "balance": 700 }
- },
- {
- "op": "add_reservation",
- "id": "res_short",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 10000
- },
- {
- "op": "add_reservation",
- "id": "res_long",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 20,
- "credits_reserved": 200,
- "consumption_rate": 10,
- "expires_at_ms": 200000
- },
- { "op": "sweep_expired", "expect": { "swept": 0 } },
- { "op": "advance_clock", "ms": 10001 },
- { "op": "sweep_expired", "expect": { "swept": 1 } },
- { "op": "get_reservation", "id": "res_short", "expect": { "exists": false } },
- { "op": "get_reservation", "id": "res_long", "expect": { "exists": true } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 800 }
- },
- { "op": "reserved_credits", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "total": 200 } }
- ]
- },
- {
- "name": "sweep_of_stale_lease_hold_does_not_inflate_successor",
- "description": "Sweeping (or consuming) a reservation carved from an expired lease refunds nothing into the successor lease occupying the slot: the hold is pinned to its originating lease_id.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_stale",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 90000
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "replace_lease",
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000,
- "expect": { "written": true }
- },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 200,
- "expect": { "balance": 800 }
- },
- { "op": "advance_clock", "ms": 30000 },
- { "op": "sweep_expired", "expect": { "swept": 1 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "lease_id": "lse_2", "local_remaining_credits": 800 }
- }
- ]
- }
- ]
-}
diff --git a/conformance/vectors/lease-lifecycle.json b/conformance/vectors/lease-lifecycle.json
deleted file mode 100644
index 085b5faa..00000000
--- a/conformance/vectors/lease-lifecycle.json
+++ /dev/null
@@ -1,447 +0,0 @@
-{
- "category": "lease_lifecycle",
- "vectors": [
- {
- "name": "replace_installs_full_grant",
- "description": "A fresh install initializes local_remaining_credits to the full granted amount.",
- "operations": [
- {
- "op": "replace_lease",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000,
- "expect": { "written": true }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": {
- "exists": true,
- "lease_id": "lse_1",
- "granted_amount": 1000,
- "local_remaining_credits": 1000
- }
- }
- ]
- },
- {
- "name": "replace_keeps_live_lease_even_with_different_id",
- "description": "A live lease occupying the slot wins over any replace — even one carrying a different lease_id (a sibling raced this acquire). Its already-debited balance is preserved.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 400,
- "expect": { "balance": 600 }
- },
- {
- "op": "replace_lease",
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 5000,
- "expires_at_ms": 120000,
- "expect": { "written": false }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": {
- "exists": true,
- "lease_id": "lse_1",
- "granted_amount": 1000,
- "local_remaining_credits": 600
- }
- }
- ]
- },
- {
- "name": "replace_reconciles_expired_slot_with_same_id",
- "description": "A stale acquire response for the SAME lease landing over its own expired local row must not reinstall it: that would reset local_remaining_credits and erase debits whose reservations are still open. The row is reconciled like an extend (granted to total, expiry forward, balance untouched) and reported as kept.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 400,
- "expect": { "balance": 600 }
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "replace_lease",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1500,
- "expires_at_ms": 120000,
- "expect": { "written": false }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": {
- "exists": true,
- "lease_id": "lse_1",
- "granted_amount": 1500,
- "local_remaining_credits": 1100
- }
- },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 1000 }
- }
- ]
- },
- {
- "name": "replace_overwrites_expired_lease",
- "description": "An expired lease does not block the slot: replace overwrites it atomically and restores the full new grant.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 400,
- "expect": { "balance": 600 }
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "replace_lease",
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 180000,
- "expect": { "written": true }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "lease_id": "lse_2", "local_remaining_credits": 1000 }
- }
- ]
- },
- {
- "name": "try_reserve_insufficient_and_boundary",
- "description": "A reserve larger than the remaining balance is refused and touches nothing; reserving down to exactly zero is allowed; negative amounts are always refused.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 100,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 101,
- "expect": { "balance": null }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 100 }
- },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": -1,
- "expect": { "balance": null }
- },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 0 }
- },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 1,
- "expect": { "balance": null }
- },
- {
- "op": "try_reserve",
- "company_id": "co_9",
- "credit_type_id": "ct_1",
- "credits": 1,
- "expect": { "balance": null }
- }
- ]
- },
- {
- "name": "refund_clamped_at_granted_amount",
- "description": "A refund can never push the local balance above the granted amount.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- { "op": "refund_lease", "company_id": "co_1", "credit_type_id": "ct_1", "credits": 500 },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- }
- ]
- },
- {
- "name": "refund_pinned_to_lease_id_dropped_on_successor",
- "description": "A refund pinned to an expired lease's id must not inflate the successor lease occupying the slot — the expired lease's remainder was already returned to the company balance server-side. An unpinned refund still applies.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 200,
- "expect": { "balance": 800 }
- },
- {
- "op": "refund_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "pin_lease_id": "lse_1"
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 800 }
- },
- {
- "op": "refund_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "pin_lease_id": "lse_2"
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- }
- ]
- },
- {
- "name": "extend_reconciles_to_total_and_converges",
- "description": "Extend applies the server-authoritative TOTAL: the delta is computed against the stored total, so a repeated or stale-lower total is a no-op and out-of-order applies converge without minting credits.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 800,
- "expect": { "balance": 200 }
- },
- {
- "op": "extend_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_total": 3000,
- "expires_at_ms": 300000
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 3000, "local_remaining_credits": 2200 }
- },
- {
- "op": "extend_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_total": 3000,
- "expires_at_ms": 300000
- },
- {
- "op": "extend_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_total": 2000,
- "expires_at_ms": 300000
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 3000, "local_remaining_credits": 2200 }
- }
- ]
- },
- {
- "name": "extend_expiry_only_moves_forward",
- "description": "An extend carrying an earlier expiry must not shorten the lease: after an extend to a later expiry, a stale out-of-order apply with an earlier expiry leaves the lease live past that earlier instant.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "extend_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_total": 2000,
- "expires_at_ms": 120000
- },
- {
- "op": "extend_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_total": 2000,
- "expires_at_ms": 30000
- },
- { "op": "advance_clock", "ms": 90000 },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 1900 }
- }
- ]
- },
- {
- "name": "extend_pinned_to_lease_id_dropped_on_successor",
- "description": "An extend pinned to a lease the slot no longer holds is dropped entirely — crediting the successor would mint credits the server granted to the expired lease.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_2",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "extend_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_total": 5000,
- "expires_at_ms": 600000,
- "pin_lease_id": "lse_1"
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 1000, "local_remaining_credits": 1000 }
- },
- {
- "op": "extend_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_total": 2000,
- "expires_at_ms": 600000,
- "pin_lease_id": "lse_2"
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 2000, "local_remaining_credits": 2000 }
- }
- ]
- }
- ]
-}
diff --git a/conformance/vectors/lease-manager.json b/conformance/vectors/lease-manager.json
deleted file mode 100644
index 79ab1afa..00000000
--- a/conformance/vectors/lease-manager.json
+++ /dev/null
@@ -1,417 +0,0 @@
-{
- "category": "lease_manager",
- "vectors": [
- {
- "name": "acquire_installs_tranche_and_reuses_live_lease",
- "description": "First acquire requests lease_size from the server and installs the response at full grant; a second acquire while the lease is live makes no wire call.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "acquire_if_needed",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "server": {
- "lease": { "lease_id": "lse_1", "granted_amount": 1000, "expires_at_ms": 300000 }
- },
- "expect": {
- "lease_id": "lse_1",
- "wire_acquires": 1,
- "last_acquire_requested_amount": 1000,
- "released_lease_ids": []
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "lease_id": "lse_1", "local_remaining_credits": 1000 }
- },
- {
- "op": "acquire_if_needed",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "lease_id": "lse_1", "wire_acquires": 1 }
- }
- ]
- },
- {
- "name": "acquire_replaces_expired_slot_without_release",
- "description": "An expired slot triggers a fresh acquire that supplants the stale entry in place; the redundant-lease release path must not fire (replace wrote, it did not keep a live lease).",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_stale",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "acquire_if_needed",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "server": {
- "lease": { "lease_id": "lse_fresh", "granted_amount": 1000, "expires_at_ms": 360000 }
- },
- "expect": { "lease_id": "lse_fresh", "wire_acquires": 1, "released_lease_ids": [] }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "lease_id": "lse_fresh", "local_remaining_credits": 1000 }
- }
- ]
- },
- {
- "name": "lost_acquire_race_different_id_releases_redundant_lease",
- "description": "A sibling installs a live lease while this acquire's wire call is in flight. The installed lease (with its debited balance) wins; the lease the server minted for the loser is redundant and gets released so it is not orphaned against the company balance.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "acquire_if_needed",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "server": {
- "lease": { "lease_id": "lse_loser", "granted_amount": 1000, "expires_at_ms": 300000 }
- },
- "install_during_wire": {
- "lease_id": "lse_winner",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- },
- "expect": { "lease_id": "lse_winner", "wire_acquires": 1, "released_lease_ids": ["lse_loser"] }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "lease_id": "lse_winner" }
- }
- ]
- },
- {
- "name": "lost_acquire_race_same_id_releases_nothing",
- "description": "The server is idempotent for an active slot: a racing acquire is handed back the SAME lease the sibling installed. There is nothing to release — releasing would pull the shared lease out from under every sibling.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "acquire_if_needed",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "server": {
- "lease": { "lease_id": "lse_shared", "granted_amount": 1000, "expires_at_ms": 300000 }
- },
- "install_during_wire": {
- "lease_id": "lse_shared",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- },
- "expect": { "lease_id": "lse_shared", "wire_acquires": 1, "released_lease_ids": [] }
- }
- ]
- },
- {
- "name": "extend_triggered_at_low_water_mark_requests_tranche",
- "description": "At or below the low-water-mark ratio a steady-state extend fires, requesting the configured tranche (lease_size) and reconciling the local row to the server total.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 800,
- "expect": { "balance": 200 }
- },
- {
- "op": "maybe_extend",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "server": { "lease": { "granted_total": 2000, "expires_at_ms": 600000 } },
- "expect": {
- "wire_extends": 1,
- "last_extend_additional_amount": 1000,
- "last_extend_lease_id": "lse_1"
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 2000, "local_remaining_credits": 1200 }
- }
- ]
- },
- {
- "name": "extend_triggered_by_required_credits_above_watermark",
- "description": "Above the watermark no steady-state extend fires; a required_credits hint larger than the local remaining triggers one anyway (a check just failed a reserve of that size).",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "maybe_extend",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "wire_extends": 0 }
- },
- {
- "op": "maybe_extend",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "required_credits": 1500,
- "server": { "lease": { "granted_total": 2000, "expires_at_ms": 600000 } },
- "expect": { "wire_extends": 1, "last_extend_additional_amount": 1000 }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 2000, "local_remaining_credits": 1900 }
- }
- ]
- },
- {
- "name": "extend_sized_to_shortfall_when_larger_than_tranche",
- "description": "additional_amount = max(lease_size, required_credits - local_remaining): a single request larger than remaining + tranche must extend by the shortfall, or its post-extend retry would fail forever regardless of server balance.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "maybe_extend",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "required_credits": 5000,
- "server": { "lease": { "granted_total": 5100, "expires_at_ms": 600000 } },
- "expect": { "wire_extends": 1, "last_extend_additional_amount": 4100 }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 5100, "local_remaining_credits": 5000 }
- }
- ]
- },
- {
- "name": "never_extend_an_expired_lease",
- "description": "An expired lease is released as far as the server is concerned — the only correct move is a fresh acquire, never an extend, no matter how depleted the balance.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_old",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 900,
- "expect": { "balance": 100 }
- },
- { "op": "advance_clock", "ms": 60001 },
- {
- "op": "maybe_extend",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "required_credits": 1500,
- "expect": { "wire_extends": 0 }
- }
- ]
- },
- {
- "name": "wire_failures_resolve_to_no_lease_without_state_changes",
- "description": "A failed acquire yields no lease and installs nothing; a failed extend leaves the local row untouched. Neither throws (both are routed through fail-open/fail-closed by callers).",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- }
- },
- "operations": [
- {
- "op": "acquire_if_needed",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "server": { "error": "wire down" },
- "expect": { "lease_id": null, "wire_acquires": 1 }
- },
- { "op": "get_lease", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "exists": false } },
- {
- "op": "replace_lease",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000,
- "expect": { "written": true }
- },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 800,
- "expect": { "balance": 200 }
- },
- {
- "op": "maybe_extend",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "server": { "error": "wire down" },
- "expect": { "wire_extends": 1 }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "granted_amount": 1000, "local_remaining_credits": 200 }
- }
- ]
- },
- {
- "name": "release_all_releases_live_and_skips_expired",
- "description": "On close, a per-process store releases its live leases over the wire (returning remainders immediately) and drops them locally; expired leases are skipped — the server already swept them. Only valid for an exclusively-owned (in-memory) store; a shared backend must never enumerate-and-release.",
- "backends": ["in_memory"],
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_live",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- },
- {
- "lease_id": "lse_expired",
- "company_id": "co_2",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 30000
- }
- ]
- },
- "operations": [
- { "op": "advance_clock", "ms": 30001 },
- {
- "op": "release_all_local_leases",
- "expect": { "released_lease_ids": ["lse_live"] }
- },
- { "op": "get_lease", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "exists": false } }
- ]
- }
- ]
-}
diff --git a/conformance/vectors/reservation-lifecycle.json b/conformance/vectors/reservation-lifecycle.json
deleted file mode 100644
index eea6b50e..00000000
--- a/conformance/vectors/reservation-lifecycle.json
+++ /dev/null
@@ -1,353 +0,0 @@
-{
- "category": "reservation_lifecycle",
- "vectors": [
- {
- "name": "consume_exact_usage_no_refund",
- "description": "Consuming exactly the reserved amount removes the reservation and refunds nothing.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 100, "expect": { "consumed": 100 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- },
- { "op": "get_reservation", "id": "res_1", "expect": { "exists": false } }
- ]
- },
- {
- "name": "consume_under_reserved_refunds_unspent",
- "description": "Consuming less than reserved refunds the unspent slice to the lease in the same step.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 30, "expect": { "consumed": 30 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 970 }
- }
- ]
- },
- {
- "name": "consume_over_reserved_clamps_to_hold",
- "description": "Local consumption is clamped to credits_reserved: over-use consumes the full hold, refunds nothing, and never debits the lease beyond the reservation. (The billed Track quantity is NOT clamped — see track-settle vectors.)",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 999, "expect": { "consumed": 100 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- }
- ]
- },
- {
- "name": "consume_zero_cancels_with_full_refund",
- "description": "Consuming 0 credits acts as a cancel: the full hold is refunded. Negative consumption clamps to 0 the same way.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 0, "expect": { "consumed": 0 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- }
- ]
- },
- {
- "name": "consume_is_exactly_once",
- "description": "A missing reservation and a second consume of the same id both return null and refund nothing — the claim is the exactly-once arbiter.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- { "op": "consume_reservation", "id": "res_missing", "credits": 10, "expect": { "consumed": null } },
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 100,
- "expect": { "balance": 900 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 30, "expect": { "consumed": 30 } },
- { "op": "consume_reservation", "id": "res_1", "credits": 30, "expect": { "consumed": null } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 970 }
- }
- ]
- },
- {
- "name": "reserved_credits_sums_open_holds_per_slot",
- "description": "reserved_credits sums credits_reserved across open reservations for the exact (company, credit) slot only, and a hold stops counting the moment it is consumed.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 350,
- "expect": { "balance": 650 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 10,
- "credits_reserved": 100,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- {
- "op": "add_reservation",
- "id": "res_2",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 25,
- "credits_reserved": 250,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- {
- "op": "add_reservation",
- "id": "res_other_credit",
- "lease_id": "lse_9",
- "company_id": "co_1",
- "credit_type_id": "ct_2",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 99,
- "credits_reserved": 999,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- {
- "op": "add_reservation",
- "id": "res_other_company",
- "lease_id": "lse_8",
- "company_id": "co_2",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 99,
- "credits_reserved": 999,
- "consumption_rate": 10,
- "expires_at_ms": 60000
- },
- {
- "op": "reserved_credits",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "total": 350 }
- },
- {
- "op": "reserved_credits",
- "company_id": "co_1",
- "credit_type_id": "ct_2",
- "expect": { "total": 999 }
- },
- { "op": "reserved_credits", "company_id": "co_9", "credit_type_id": "ct_1", "expect": { "total": 0 } },
- { "op": "consume_reservation", "id": "res_1", "credits": 40, "expect": { "consumed": 40 } },
- { "op": "reserved_credits", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "total": 250 } }
- ]
- },
- {
- "name": "fractional_credit_amounts_are_exact",
- "description": "Fractional consumption rates produce fractional holds; reserve, consume, and refund arithmetic must not truncate.",
- "given": {
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 10,
- "expires_at_ms": 60000
- }
- ]
- },
- "operations": [
- {
- "op": "try_reserve",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "credits": 2.5,
- "expect": { "balance": 7.5 }
- },
- {
- "op": "add_reservation",
- "id": "res_1",
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "event_subtype": "inference_tokens",
- "quantity_reserved": 25,
- "credits_reserved": 2.5,
- "consumption_rate": 0.1,
- "expires_at_ms": 60000
- },
- { "op": "consume_reservation", "id": "res_1", "credits": 1.5, "expect": { "consumed": 1.5 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 8.5 }
- }
- ]
- }
- ]
-}
diff --git a/conformance/vectors/track-settle.json b/conformance/vectors/track-settle.json
deleted file mode 100644
index 1da71a09..00000000
--- a/conformance/vectors/track-settle.json
+++ /dev/null
@@ -1,194 +0,0 @@
-{
- "category": "track_settle",
- "vectors": [
- {
- "name": "track_underuse_settles_and_refunds_unspent",
- "description": "Settling with less than the reserved usage consumes actual x rate, refunds the unspent slice to the lease, and emits a Track billing the ACTUAL quantity keyed to the lease.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "save_reservation_as": "r1",
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": true, "reason": "ok" }
- ],
- "expect": { "allowed": true, "has_reservation": true }
- },
- {
- "op": "track",
- "handle": "r1",
- "actual_quantity": 4,
- "expect": {
- "settled_locally": true,
- "track": { "event": "inference_tokens", "quantity": 4, "lease_id": "lse_1" }
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 960 }
- },
- { "op": "reserved_credits", "company_id": "co_1", "credit_type_id": "ct_1", "expect": { "total": 0 } }
- ]
- },
- {
- "name": "track_overuse_bills_actual_but_clamps_local_debit",
- "description": "Actual usage above the reservation: the LOCAL settle clamps consumption to the reserved hold (the lease is never debited past the reservation), but the Track event bills the unclamped actual quantity — the server is the source of truth for real consumption.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "save_reservation_as": "r1",
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": true, "reason": "ok" }
- ],
- "expect": { "allowed": true, "has_reservation": true }
- },
- {
- "op": "track",
- "handle": "r1",
- "actual_quantity": 25,
- "expect": {
- "settled_locally": true,
- "track": { "event": "inference_tokens", "quantity": 25, "lease_id": "lse_1" }
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 900 }
- }
- ]
- },
- {
- "name": "track_after_sweep_is_a_recovery_emit",
- "description": "Work outliving the reservation TTL: the sweeper already refunded the full hold, so the late settle does not touch the lease (the local balance reads high until rollover) — but the Track is still emitted so the server bills the actual usage. Server-side idempotency (a deterministic key derived from the reservation id) is what keeps a racing normal emit from double-billing.",
- "given": {
- "config": {
- "lease_duration_ms": 300000,
- "reservation_ttl_ms": 60000,
- "lease_size": 1000,
- "low_water_mark": 0.25
- },
- "leases": [
- {
- "lease_id": "lse_1",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "granted_amount": 1000,
- "expires_at_ms": 300000
- }
- ]
- },
- "operations": [
- {
- "op": "check",
- "flag_key": "inference",
- "company": { "id": "co_1", "credit_balances": { "ct_1": 5000 } },
- "usage": 10,
- "event_subtype": "inference_tokens",
- "save_reservation_as": "r1",
- "engine": [
- {
- "value": true,
- "reason": "probe",
- "entitlement": {
- "value_type": "credit",
- "credit_id": "ct_1",
- "consumption_rate": 10,
- "event_subtype": "inference_tokens"
- }
- },
- { "value": true, "reason": "ok" }
- ],
- "expect": { "allowed": true, "has_reservation": true }
- },
- { "op": "advance_clock", "ms": 60001 },
- { "op": "sweep_expired", "expect": { "swept": 1 } },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- },
- {
- "op": "track",
- "handle": "r1",
- "actual_quantity": 4,
- "expect": {
- "settled_locally": false,
- "track": { "event": "inference_tokens", "quantity": 4, "lease_id": "lse_1" }
- }
- },
- {
- "op": "get_lease",
- "company_id": "co_1",
- "credit_type_id": "ct_1",
- "expect": { "exists": true, "local_remaining_credits": 1000 }
- }
- ]
- }
- ]
-}
diff --git a/package.json b/package.json
index 84df190d..d779590c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@schematichq/schematic-typescript-node",
- "version": "1.5.11",
+ "version": "1.5.12",
"private": false,
"repository": {
"type": "git",
@@ -57,9 +57,6 @@
"crypto": false,
"timers": false
},
- "resolutions": {
- "undici": "7.29.0"
- },
"packageManager": "yarn@1.22.22",
"engines": {
"node": ">=18.0.0"
diff --git a/reference.md b/reference.md
index 95eb181f..26f221a5 100644
--- a/reference.md
+++ b/reference.md
@@ -2382,6 +2382,120 @@ await client.billing.countBillingProducts({
+
+
+
+
+client.billing.listCompanyBillingProfiles({ ...params }) -> Schematic.ListCompanyBillingProfilesResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.billing.listCompanyBillingProfiles({
+ companyId: "company_id",
+ isDefault: true,
+ providerType: "metronome",
+ limit: 1000000,
+ offset: 1000000
+});
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `Schematic.ListCompanyBillingProfilesRequest`
+
+
+
+
+
+-
+
+**requestOptions:** `BillingClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.billing.updateCompanyBillingProfile(billing_profile_id, { ...params }) -> Schematic.UpdateCompanyBillingProfileResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ collectionMethod: "charge_automatically"
+});
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**billing_profile_id:** `string` — billing_profile_id
+
+
+
+
+
+-
+
+**request:** `Schematic.UpdateCompanyBillingProfileRequestBody`
+
+
+
+
+
+-
+
+**requestOptions:** `BillingClient.RequestOptions`
+
+
+
+
+
+
+
@@ -3991,7 +4105,7 @@ await client.credits.countBillingPlanCreditGrants({
-client.credits.listCreditEventLedger({ ...params }) -> Schematic.ListCreditEventLedgerResponse
+client.credits.listCreditSpendPolicies({ ...params }) -> Schematic.ListCreditSpendPoliciesResponse
-
@@ -4004,13 +4118,12 @@ await client.credits.countBillingPlanCreditGrants({
-
```typescript
-await client.credits.listCreditEventLedger({
+await client.credits.listCreditSpendPolicies({
billingCreditId: "billing_credit_id",
companyId: "company_id",
- endTime: "end_time",
- eventType: "grant",
- featureId: "feature_id",
- startTime: "start_time",
+ scopeType: "company",
+ userId: "user_id",
+ userIds: ["user_ids"],
limit: 1000000,
offset: 1000000
});
@@ -4029,7 +4142,7 @@ await client.credits.listCreditEventLedger({
-
-**request:** `Schematic.ListCreditEventLedgerRequest`
+**request:** `Schematic.ListCreditSpendPoliciesRequest`
@@ -4049,7 +4162,7 @@ await client.credits.listCreditEventLedger({
-client.credits.countCreditEventLedger({ ...params }) -> Schematic.CountCreditEventLedgerResponse
+client.credits.createCreditSpendPolicy({ ...params }) -> Schematic.CreateCreditSpendPolicyResponse
-
@@ -4062,15 +4175,9 @@ await client.credits.listCreditEventLedger({
-
```typescript
-await client.credits.countCreditEventLedger({
+await client.credits.createCreditSpendPolicy({
billingCreditId: "billing_credit_id",
- companyId: "company_id",
- endTime: "end_time",
- eventType: "grant",
- featureId: "feature_id",
- startTime: "start_time",
- limit: 1000000,
- offset: 1000000
+ maxPerDraw: 1.1
});
```
@@ -4087,7 +4194,7 @@ await client.credits.countCreditEventLedger({
-
-**request:** `Schematic.CountCreditEventLedgerRequest`
+**request:** `Schematic.CreateCreditSpendPolicyRequestBody`
@@ -4107,8 +4214,7 @@ await client.credits.countCreditEventLedger({
-## catalogs
-client.catalogs.listCatalogs({ ...params }) -> Schematic.ListCatalogsResponse
+client.credits.getCreditSpendPolicy(spend_policy_id) -> Schematic.GetCreditSpendPolicyResponse
-
@@ -4121,12 +4227,7 @@ await client.credits.countCreditEventLedger({
-
```typescript
-await client.catalogs.listCatalogs({
- isDefault: true,
- q: "q",
- limit: 1000000,
- offset: 1000000
-});
+await client.credits.getCreditSpendPolicy("spend_policy_id");
```
@@ -4142,7 +4243,7 @@ await client.catalogs.listCatalogs({
-
-**request:** `Schematic.ListCatalogsRequest`
+**spend_policy_id:** `string` — spend_policy_id
@@ -4150,7 +4251,7 @@ await client.catalogs.listCatalogs({
-
-**requestOptions:** `CatalogsClient.RequestOptions`
+**requestOptions:** `CreditsClient.RequestOptions`
@@ -4162,7 +4263,7 @@ await client.catalogs.listCatalogs({
-client.catalogs.createCatalog({ ...params }) -> Schematic.CreateCatalogResponse
+client.credits.updateCreditSpendPolicy(spend_policy_id, { ...params }) -> Schematic.UpdateCreditSpendPolicyResponse
-
@@ -4175,9 +4276,7 @@ await client.catalogs.listCatalogs({
-
```typescript
-await client.catalogs.createCatalog({
- name: "name"
-});
+await client.credits.updateCreditSpendPolicy("spend_policy_id");
```
@@ -4193,7 +4292,7 @@ await client.catalogs.createCatalog({
-
-**request:** `Schematic.CreateCatalogRequestBody`
+**spend_policy_id:** `string` — spend_policy_id
@@ -4201,7 +4300,15 @@ await client.catalogs.createCatalog({
-
-**requestOptions:** `CatalogsClient.RequestOptions`
+**request:** `Schematic.UpdateCreditSpendPolicyRequestBody`
+
+
+
+
+
+-
+
+**requestOptions:** `CreditsClient.RequestOptions`
@@ -4213,7 +4320,7 @@ await client.catalogs.createCatalog({
-client.catalogs.getCatalog(catalog_id) -> Schematic.GetCatalogResponse
+client.credits.deleteCreditSpendPolicy(spend_policy_id) -> Schematic.DeleteCreditSpendPolicyResponse
-
@@ -4226,7 +4333,7 @@ await client.catalogs.createCatalog({
-
```typescript
-await client.catalogs.getCatalog("catalog_id");
+await client.credits.deleteCreditSpendPolicy("spend_policy_id");
```
@@ -4242,7 +4349,7 @@ await client.catalogs.getCatalog("catalog_id");
-
-**catalog_id:** `string` — catalog_id
+**spend_policy_id:** `string` — spend_policy_id
@@ -4250,7 +4357,7 @@ await client.catalogs.getCatalog("catalog_id");
-
-**requestOptions:** `CatalogsClient.RequestOptions`
+**requestOptions:** `CreditsClient.RequestOptions`
@@ -4262,7 +4369,7 @@ await client.catalogs.getCatalog("catalog_id");
-client.catalogs.updateCatalog(catalog_id, { ...params }) -> Schematic.UpdateCatalogResponse
+client.credits.countCreditSpendPolicies({ ...params }) -> Schematic.CountCreditSpendPoliciesResponse
-
@@ -4275,7 +4382,15 @@ await client.catalogs.getCatalog("catalog_id");
-
```typescript
-await client.catalogs.updateCatalog("catalog_id");
+await client.credits.countCreditSpendPolicies({
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ scopeType: "company",
+ userId: "user_id",
+ userIds: ["user_ids"],
+ limit: 1000000,
+ offset: 1000000
+});
```
@@ -4291,15 +4406,7 @@ await client.catalogs.updateCatalog("catalog_id");
-
-**catalog_id:** `string` — catalog_id
-
-
-
-
-
--
-
-**request:** `Schematic.UpdateCatalogRequestBody`
+**request:** `Schematic.CountCreditSpendPoliciesRequest`
@@ -4307,7 +4414,7 @@ await client.catalogs.updateCatalog("catalog_id");
-
-**requestOptions:** `CatalogsClient.RequestOptions`
+**requestOptions:** `CreditsClient.RequestOptions`
@@ -4319,7 +4426,7 @@ await client.catalogs.updateCatalog("catalog_id");
-client.catalogs.deleteCatalog(catalog_id) -> Schematic.DeleteCatalogResponse
+client.credits.listCreditEventLedger({ ...params }) -> Schematic.ListCreditEventLedgerResponse
-
@@ -4332,7 +4439,16 @@ await client.catalogs.updateCatalog("catalog_id");
-
```typescript
-await client.catalogs.deleteCatalog("catalog_id");
+await client.credits.listCreditEventLedger({
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ endTime: "end_time",
+ eventType: "grant",
+ featureId: "feature_id",
+ startTime: "start_time",
+ limit: 1000000,
+ offset: 1000000
+});
```
@@ -4348,7 +4464,7 @@ await client.catalogs.deleteCatalog("catalog_id");
-
-**catalog_id:** `string` — catalog_id
+**request:** `Schematic.ListCreditEventLedgerRequest`
@@ -4356,7 +4472,7 @@ await client.catalogs.deleteCatalog("catalog_id");
-
-**requestOptions:** `CatalogsClient.RequestOptions`
+**requestOptions:** `CreditsClient.RequestOptions`
@@ -4368,7 +4484,7 @@ await client.catalogs.deleteCatalog("catalog_id");
-client.catalogs.getConfiguration(catalog_id) -> Schematic.GetConfigurationResponse
+client.credits.countCreditEventLedger({ ...params }) -> Schematic.CountCreditEventLedgerResponse
-
@@ -4381,7 +4497,16 @@ await client.catalogs.deleteCatalog("catalog_id");
-
```typescript
-await client.catalogs.getConfiguration("catalog_id");
+await client.credits.countCreditEventLedger({
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ endTime: "end_time",
+ eventType: "grant",
+ featureId: "feature_id",
+ startTime: "start_time",
+ limit: 1000000,
+ offset: 1000000
+});
```
@@ -4397,7 +4522,7 @@ await client.catalogs.getConfiguration("catalog_id");
-
-**catalog_id:** `string` — catalog_id
+**request:** `Schematic.CountCreditEventLedgerRequest`
@@ -4405,7 +4530,7 @@ await client.catalogs.getConfiguration("catalog_id");
-
-**requestOptions:** `CatalogsClient.RequestOptions`
+**requestOptions:** `CreditsClient.RequestOptions`
@@ -4417,7 +4542,8 @@ await client.catalogs.getConfiguration("catalog_id");
-client.catalogs.updateConfiguration(catalog_id, { ...params }) -> Schematic.UpdateConfigurationResponse
+## catalogs
+client.catalogs.listCatalogs({ ...params }) -> Schematic.ListCatalogsResponse
-
@@ -4430,7 +4556,12 @@ await client.catalogs.getConfiguration("catalog_id");
-
```typescript
-await client.catalogs.updateConfiguration("catalog_id");
+await client.catalogs.listCatalogs({
+ isDefault: true,
+ q: "q",
+ limit: 1000000,
+ offset: 1000000
+});
```
@@ -4446,15 +4577,7 @@ await client.catalogs.updateConfiguration("catalog_id");
-
-**catalog_id:** `string` — catalog_id
-
-
-
-
-
--
-
-**request:** `Schematic.UpdateCatalogConfigurationRequestBody`
+**request:** `Schematic.ListCatalogsRequest`
@@ -4474,7 +4597,7 @@ await client.catalogs.updateConfiguration("catalog_id");
-client.catalogs.getCreditBundlesInCatalog(catalog_id) -> Schematic.GetCreditBundlesInCatalogResponse
+client.catalogs.createCatalog({ ...params }) -> Schematic.CreateCatalogResponse
-
@@ -4487,7 +4610,9 @@ await client.catalogs.updateConfiguration("catalog_id");
-
```typescript
-await client.catalogs.getCreditBundlesInCatalog("catalog_id");
+await client.catalogs.createCatalog({
+ name: "name"
+});
```
@@ -4503,7 +4628,7 @@ await client.catalogs.getCreditBundlesInCatalog("catalog_id");
-
-**catalog_id:** `string` — catalog_id
+**request:** `Schematic.CreateCatalogRequestBody`
@@ -4523,7 +4648,7 @@ await client.catalogs.getCreditBundlesInCatalog("catalog_id");
-client.catalogs.addCreditBundle(catalog_id, credit_bundle_id) -> void
+client.catalogs.getCatalog(catalog_id) -> Schematic.GetCatalogResponse
-
@@ -4536,7 +4661,7 @@ await client.catalogs.getCreditBundlesInCatalog("catalog_id");
-
```typescript
-await client.catalogs.addCreditBundle("catalog_id", "credit_bundle_id");
+await client.catalogs.getCatalog("catalog_id");
```
@@ -4560,14 +4685,6 @@ await client.catalogs.addCreditBundle("catalog_id", "credit_bundle_id");
-
-**credit_bundle_id:** `string` — credit_bundle_id
-
-
-
-
-
--
-
**requestOptions:** `CatalogsClient.RequestOptions`
@@ -4580,7 +4697,7 @@ await client.catalogs.addCreditBundle("catalog_id", "credit_bundle_id");
-client.catalogs.removeCreditBundle(catalog_id, credit_bundle_id) -> void
+client.catalogs.updateCatalog(catalog_id, { ...params }) -> Schematic.UpdateCatalogResponse
-
@@ -4593,7 +4710,7 @@ await client.catalogs.addCreditBundle("catalog_id", "credit_bundle_id");
-
```typescript
-await client.catalogs.removeCreditBundle("catalog_id", "credit_bundle_id");
+await client.catalogs.updateCatalog("catalog_id");
```
@@ -4617,7 +4734,7 @@ await client.catalogs.removeCreditBundle("catalog_id", "credit_bundle_id");
-
-**credit_bundle_id:** `string` — credit_bundle_id
+**request:** `Schematic.UpdateCatalogRequestBody`
@@ -4637,7 +4754,7 @@ await client.catalogs.removeCreditBundle("catalog_id", "credit_bundle_id");
-client.catalogs.getDerivedFeatures(catalog_id) -> Schematic.GetDerivedFeaturesResponse
+client.catalogs.deleteCatalog(catalog_id) -> Schematic.DeleteCatalogResponse
-
@@ -4650,7 +4767,325 @@ await client.catalogs.removeCreditBundle("catalog_id", "credit_bundle_id");
-
```typescript
-await client.catalogs.getDerivedFeatures("catalog_id");
+await client.catalogs.deleteCatalog("catalog_id");
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**catalog_id:** `string` — catalog_id
+
+
+
+
+
+-
+
+**requestOptions:** `CatalogsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.catalogs.getConfiguration(catalog_id) -> Schematic.GetConfigurationResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.catalogs.getConfiguration("catalog_id");
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**catalog_id:** `string` — catalog_id
+
+
+
+
+
+-
+
+**requestOptions:** `CatalogsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.catalogs.updateConfiguration(catalog_id, { ...params }) -> Schematic.UpdateConfigurationResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.catalogs.updateConfiguration("catalog_id");
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**catalog_id:** `string` — catalog_id
+
+
+
+
+
+-
+
+**request:** `Schematic.UpdateCatalogConfigurationRequestBody`
+
+
+
+
+
+-
+
+**requestOptions:** `CatalogsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.catalogs.getCreditBundlesInCatalog(catalog_id) -> Schematic.GetCreditBundlesInCatalogResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.catalogs.getCreditBundlesInCatalog("catalog_id");
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**catalog_id:** `string` — catalog_id
+
+
+
+
+
+-
+
+**requestOptions:** `CatalogsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.catalogs.addCreditBundle(catalog_id, credit_bundle_id) -> void
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.catalogs.addCreditBundle("catalog_id", "credit_bundle_id");
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**catalog_id:** `string` — catalog_id
+
+
+
+
+
+-
+
+**credit_bundle_id:** `string` — credit_bundle_id
+
+
+
+
+
+-
+
+**requestOptions:** `CatalogsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.catalogs.removeCreditBundle(catalog_id, credit_bundle_id) -> void
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.catalogs.removeCreditBundle("catalog_id", "credit_bundle_id");
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**catalog_id:** `string` — catalog_id
+
+
+
+
+
+-
+
+**credit_bundle_id:** `string` — credit_bundle_id
+
+
+
+
+
+-
+
+**requestOptions:** `CatalogsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.catalogs.getDerivedFeatures(catalog_id) -> Schematic.GetDerivedFeaturesResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.catalogs.getDerivedFeatures("catalog_id");
```
@@ -11008,7 +11443,170 @@ await client.events.createEventBatch({
-client.events.getEventSummaries({ ...params }) -> Schematic.GetEventSummariesResponse
+client.events.getEventSummaries({ ...params }) -> Schematic.GetEventSummariesResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.events.getEventSummaries({
+ q: "q",
+ eventSubtypes: ["event_subtypes"],
+ limit: 1000000,
+ offset: 1000000
+});
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `Schematic.GetEventSummariesRequest`
+
+
+
+
+
+-
+
+**requestOptions:** `EventsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.events.listEvents({ ...params }) -> Schematic.ListEventsResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.events.listEvents({
+ companyId: "company_id",
+ eventSubtype: "event_subtype",
+ eventTypes: ["flag_check"],
+ flagId: "flag_id",
+ idempotencyKey: "idempotency_key",
+ userId: "user_id",
+ limit: 1000000,
+ offset: 1000000
+});
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `Schematic.ListEventsRequest`
+
+
+
+
+
+-
+
+**requestOptions:** `EventsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.events.createEvent({ ...params }) -> Schematic.CreateEventResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.events.createEvent({
+ eventType: "flag_check"
+});
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `Schematic.CreateEventRequestBody`
+
+
+
+
+
+-
+
+**requestOptions:** `EventsClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.events.getEvent(event_id) -> Schematic.GetEventResponse
-
@@ -11021,12 +11619,7 @@ await client.events.createEventBatch({
-
```typescript
-await client.events.getEventSummaries({
- q: "q",
- eventSubtypes: ["event_subtypes"],
- limit: 1000000,
- offset: 1000000
-});
+await client.events.getEvent("event_id");
```
@@ -11042,7 +11635,7 @@ await client.events.getEventSummaries({
-
-**request:** `Schematic.GetEventSummariesRequest`
+**event_id:** `string` — event_id
@@ -11062,7 +11655,7 @@ await client.events.getEventSummaries({
-client.events.listEvents({ ...params }) -> Schematic.ListEventsResponse
+client.events.getOtlpEnvironmentSettings() -> Schematic.GetOtlpEnvironmentSettingsResponse
-
@@ -11075,16 +11668,7 @@ await client.events.getEventSummaries({
-
```typescript
-await client.events.listEvents({
- companyId: "company_id",
- eventSubtype: "event_subtype",
- eventTypes: ["flag_check"],
- flagId: "flag_id",
- idempotencyKey: "idempotency_key",
- userId: "user_id",
- limit: 1000000,
- offset: 1000000
-});
+await client.events.getOtlpEnvironmentSettings();
```
@@ -11100,14 +11684,6 @@ await client.events.listEvents({
-
-**request:** `Schematic.ListEventsRequest`
-
-
-
-
-
--
-
**requestOptions:** `EventsClient.RequestOptions`
@@ -11120,7 +11696,7 @@ await client.events.listEvents({
-client.events.createEvent({ ...params }) -> Schematic.CreateEventResponse
+client.events.upsertOtlpEnvironmentSettings({ ...params }) -> Schematic.UpsertOtlpEnvironmentSettingsResponse
-
@@ -11133,8 +11709,8 @@ await client.events.listEvents({
-
```typescript
-await client.events.createEvent({
- eventType: "flag_check"
+await client.events.upsertOtlpEnvironmentSettings({
+ toolEventsEnabled: true
});
```
@@ -11151,7 +11727,7 @@ await client.events.createEvent({
-
-**request:** `Schematic.CreateEventRequestBody`
+**request:** `Schematic.UpsertOtlpEnvironmentSettingsRequestBody`
@@ -11171,7 +11747,7 @@ await client.events.createEvent({
-client.events.getEvent(event_id) -> Schematic.GetEventResponse
+client.events.deleteOtlpEnvironmentSettings() -> Schematic.DeleteOtlpEnvironmentSettingsResponse
-
@@ -11184,7 +11760,7 @@ await client.events.createEvent({
-
```typescript
-await client.events.getEvent("event_id");
+await client.events.deleteOtlpEnvironmentSettings();
```
@@ -11200,14 +11776,6 @@ await client.events.getEvent("event_id");
-
-**event_id:** `string` — event_id
-
-
-
-
-
--
-
**requestOptions:** `EventsClient.RequestOptions`
@@ -12803,6 +13371,139 @@ await client.integrationsapi.loadSampleDataSet();
+
+
+
+
+client.integrationsapi.getStripeSandboxClaimLink() -> Schematic.GetStripeSandboxClaimLinkResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.integrationsapi.getStripeSandboxClaimLink();
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**requestOptions:** `IntegrationsapiClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.integrationsapi.getStripeSandboxKeys() -> Schematic.GetStripeSandboxKeysResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.integrationsapi.getStripeSandboxKeys();
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**requestOptions:** `IntegrationsapiClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.integrationsapi.claimStripeSandboxKeys({ ...params }) -> Schematic.ClaimStripeSandboxKeysResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.integrationsapi.claimStripeSandboxKeys({
+ token: "token"
+});
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `Schematic.ClaimStripeSandboxKeysRequestBody`
+
+
+
+
+
+-
+
+**requestOptions:** `IntegrationsapiClient.RequestOptions`
+
+
+
+
+
+
+
@@ -12905,6 +13606,98 @@ await client.integrationsapi.installStripe({
+
+
+
+
+client.integrationsapi.installStripeClaimableSandbox({ ...params }) -> Schematic.InstallStripeClaimableSandboxResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.integrationsapi.installStripeClaimableSandbox({
+ email: "email"
+});
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**request:** `Schematic.InstallStripeSandboxRequestBody`
+
+
+
+
+
+-
+
+**requestOptions:** `IntegrationsapiClient.RequestOptions`
+
+
+
+
+
+
+
+
+
+
+
+client.integrationsapi.listStripeSandboxCountries() -> Schematic.ListStripeSandboxCountriesResponse
+
+-
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```typescript
+await client.integrationsapi.listStripeSandboxCountries();
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**requestOptions:** `IntegrationsapiClient.RequestOptions`
+
+
+
+
+
+
+
diff --git a/src/BaseClient.ts b/src/BaseClient.ts
index 243ba69d..906e05ac 100644
--- a/src/BaseClient.ts
+++ b/src/BaseClient.ts
@@ -66,8 +66,8 @@ export function normalizeClientOptions {
+ return core.HttpResponsePromise.fromPromise(this.__listCompanyBillingProfiles(request, requestOptions));
+ }
+
+ private async __listCompanyBillingProfiles(
+ request: Schematic.ListCompanyBillingProfilesRequest = {},
+ requestOptions?: BillingClient.RequestOptions,
+ ): Promise> {
+ const { companyId, isDefault, providerType, limit, offset } = request;
+ const _queryParams: Record = {
+ company_id: companyId,
+ is_default: isDefault,
+ provider_type:
+ providerType != null
+ ? serializers.BillingProviderType.jsonOrThrow(providerType, { unrecognizedObjectKeys: "strip" })
+ : undefined,
+ limit,
+ offset,
+ };
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "billing/profiles",
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url
+ .queryBuilder()
+ .addMany(_queryParams)
+ .mergeAdditional(requestOptions?.queryParams)
+ .build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.ListCompanyBillingProfilesResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/billing/profiles");
+ }
+
+ /**
+ * @param {string} billing_profile_id - billing_profile_id
+ * @param {Schematic.UpdateCompanyBillingProfileRequestBody} request
+ * @param {BillingClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ * collectionMethod: "charge_automatically"
+ * })
+ */
+ public updateCompanyBillingProfile(
+ billing_profile_id: string,
+ request: Schematic.UpdateCompanyBillingProfileRequestBody,
+ requestOptions?: BillingClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(
+ this.__updateCompanyBillingProfile(billing_profile_id, request, requestOptions),
+ );
+ }
+
+ private async __updateCompanyBillingProfile(
+ billing_profile_id: string,
+ request: Schematic.UpdateCompanyBillingProfileRequestBody,
+ requestOptions?: BillingClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ `billing/profiles/${core.url.encodePathParam(billing_profile_id)}`,
+ ),
+ method: "PUT",
+ headers: _headers,
+ contentType: "application/json",
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ requestType: "json",
+ body: mergeAdditionalBodyParameters(
+ serializers.UpdateCompanyBillingProfileRequestBody.jsonOrThrow(request, {
+ unrecognizedObjectKeys: "strip",
+ }),
+ requestOptions?.additionalBodyParameters,
+ ),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.UpdateCompanyBillingProfileResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "PUT",
+ "/billing/profiles/{billing_profile_id}",
+ );
+ }
+
/**
* @param {Schematic.CreateBillingSubscriptionRequestBody} request
* @param {BillingClient.RequestOptions} requestOptions - Request-specific configuration.
diff --git a/src/api/resources/billing/client/requests/ListCompanyBillingProfilesRequest.ts b/src/api/resources/billing/client/requests/ListCompanyBillingProfilesRequest.ts
new file mode 100644
index 00000000..56e8f42c
--- /dev/null
+++ b/src/api/resources/billing/client/requests/ListCompanyBillingProfilesRequest.ts
@@ -0,0 +1,23 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../index";
+
+/**
+ * @example
+ * {
+ * companyId: "company_id",
+ * isDefault: true,
+ * providerType: "metronome",
+ * limit: 1000000,
+ * offset: 1000000
+ * }
+ */
+export interface ListCompanyBillingProfilesRequest {
+ companyId?: string;
+ isDefault?: boolean;
+ providerType?: Schematic.BillingProviderType;
+ /** Page limit (default 100) */
+ limit?: number;
+ /** Page offset (default 0) */
+ offset?: number;
+}
diff --git a/src/api/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts b/src/api/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts
new file mode 100644
index 00000000..690249ec
--- /dev/null
+++ b/src/api/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts
@@ -0,0 +1,18 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../index";
+
+/**
+ * @example
+ * {
+ * collectionMethod: "charge_automatically"
+ * }
+ */
+export interface UpdateCompanyBillingProfileRequestBody {
+ collectionMethod: Schematic.BillingCollectionMethod;
+ daysUntilDue?: number;
+ isDefault?: boolean;
+ name?: string;
+ paymentMethodId?: string;
+ prorationBehavior?: Schematic.ProrationBehavior;
+}
diff --git a/src/api/resources/billing/client/requests/index.ts b/src/api/resources/billing/client/requests/index.ts
index fc3aa928..9ebade65 100644
--- a/src/api/resources/billing/client/requests/index.ts
+++ b/src/api/resources/billing/client/requests/index.ts
@@ -11,8 +11,10 @@ export type { CreatePaymentMethodRequestBody } from "./CreatePaymentMethodReques
export type { ListBillingPricesRequest } from "./ListBillingPricesRequest";
export type { ListBillingProductPricesRequest } from "./ListBillingProductPricesRequest";
export type { ListBillingProductsRequest } from "./ListBillingProductsRequest";
+export type { ListCompanyBillingProfilesRequest } from "./ListCompanyBillingProfilesRequest";
export type { ListCouponsRequest } from "./ListCouponsRequest";
export type { ListCustomersWithSubscriptionsRequest } from "./ListCustomersWithSubscriptionsRequest";
export type { ListInvoicesRequest } from "./ListInvoicesRequest";
export type { ListMetersRequest } from "./ListMetersRequest";
export type { ListPaymentMethodsRequest } from "./ListPaymentMethodsRequest";
+export type { UpdateCompanyBillingProfileRequestBody } from "./UpdateCompanyBillingProfileRequestBody";
diff --git a/src/api/resources/billing/types/ListCompanyBillingProfilesParams.ts b/src/api/resources/billing/types/ListCompanyBillingProfilesParams.ts
new file mode 100644
index 00000000..b17a1b1a
--- /dev/null
+++ b/src/api/resources/billing/types/ListCompanyBillingProfilesParams.ts
@@ -0,0 +1,16 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+/**
+ * Input parameters
+ */
+export interface ListCompanyBillingProfilesParams {
+ companyId?: string;
+ isDefault?: boolean;
+ /** Page limit (default 100) */
+ limit?: number;
+ /** Page offset (default 0) */
+ offset?: number;
+ providerType?: Schematic.BillingProviderType;
+}
diff --git a/src/api/resources/billing/types/ListCompanyBillingProfilesResponse.ts b/src/api/resources/billing/types/ListCompanyBillingProfilesResponse.ts
new file mode 100644
index 00000000..63ae1bab
--- /dev/null
+++ b/src/api/resources/billing/types/ListCompanyBillingProfilesResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface ListCompanyBillingProfilesResponse {
+ data: Schematic.CompanyBillingProfileResponseData[];
+ /** Input parameters */
+ params: Schematic.ListCompanyBillingProfilesParams;
+}
diff --git a/src/api/resources/billing/types/UpdateCompanyBillingProfileResponse.ts b/src/api/resources/billing/types/UpdateCompanyBillingProfileResponse.ts
new file mode 100644
index 00000000..c047c38b
--- /dev/null
+++ b/src/api/resources/billing/types/UpdateCompanyBillingProfileResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface UpdateCompanyBillingProfileResponse {
+ data: Schematic.CompanyBillingProfileResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/billing/types/index.ts b/src/api/resources/billing/types/index.ts
index 7e9332c9..5fa2d7b3 100644
--- a/src/api/resources/billing/types/index.ts
+++ b/src/api/resources/billing/types/index.ts
@@ -14,6 +14,8 @@ export * from "./ListBillingProductPricesParams";
export * from "./ListBillingProductPricesResponse";
export * from "./ListBillingProductsParams";
export * from "./ListBillingProductsResponse";
+export * from "./ListCompanyBillingProfilesParams";
+export * from "./ListCompanyBillingProfilesResponse";
export * from "./ListCouponsParams";
export * from "./ListCouponsResponse";
export * from "./ListCustomersWithSubscriptionsParams";
@@ -24,6 +26,7 @@ export * from "./ListMetersParams";
export * from "./ListMetersResponse";
export * from "./ListPaymentMethodsParams";
export * from "./ListPaymentMethodsResponse";
+export * from "./UpdateCompanyBillingProfileResponse";
export * from "./UpsertBillingCouponResponse";
export * from "./UpsertBillingCustomerResponse";
export * from "./UpsertBillingMeterResponse";
diff --git a/src/api/resources/credits/client/Client.ts b/src/api/resources/credits/client/Client.ts
index 7428e3ad..53f1f50a 100644
--- a/src/api/resources/credits/client/Client.ts
+++ b/src/api/resources/credits/client/Client.ts
@@ -2764,6 +2764,7 @@ export class CreditsClient {
*
* @throws {@link Schematic.BadRequestError}
* @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.PaymentRequiredError}
* @throws {@link Schematic.ForbiddenError}
* @throws {@link Schematic.NotFoundError}
* @throws {@link Schematic.InternalServerError}
@@ -2853,6 +2854,17 @@ export class CreditsClient {
}),
_response.rawResponse,
);
+ case 402:
+ throw new Schematic.PaymentRequiredError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
case 403:
throw new Schematic.ForbiddenError(
serializers.ApiError.parseOrThrow(_response.error.body, {
@@ -2905,6 +2917,7 @@ export class CreditsClient {
*
* @throws {@link Schematic.BadRequestError}
* @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.PaymentRequiredError}
* @throws {@link Schematic.ForbiddenError}
* @throws {@link Schematic.NotFoundError}
* @throws {@link Schematic.InternalServerError}
@@ -2994,6 +3007,17 @@ export class CreditsClient {
}),
_response.rawResponse,
);
+ case 402:
+ throw new Schematic.PaymentRequiredError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
case 403:
throw new Schematic.ForbiddenError(
serializers.ApiError.parseOrThrow(_response.error.body, {
@@ -4073,6 +4097,878 @@ export class CreditsClient {
);
}
+ /**
+ * @param {Schematic.ListCreditSpendPoliciesRequest} request
+ * @param {CreditsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.credits.listCreditSpendPolicies({
+ * billingCreditId: "billing_credit_id",
+ * companyId: "company_id",
+ * scopeType: "company",
+ * userId: "user_id",
+ * userIds: ["user_ids"],
+ * limit: 1000000,
+ * offset: 1000000
+ * })
+ */
+ public listCreditSpendPolicies(
+ request: Schematic.ListCreditSpendPoliciesRequest = {},
+ requestOptions?: CreditsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__listCreditSpendPolicies(request, requestOptions));
+ }
+
+ private async __listCreditSpendPolicies(
+ request: Schematic.ListCreditSpendPoliciesRequest = {},
+ requestOptions?: CreditsClient.RequestOptions,
+ ): Promise> {
+ const { billingCreditId, companyId, scopeType, userId, userIds, limit, offset } = request;
+ const _queryParams: Record = {
+ billing_credit_id: billingCreditId,
+ company_id: companyId,
+ scope_type:
+ scopeType != null
+ ? serializers.CreditSpendPolicyScope.jsonOrThrow(scopeType, { unrecognizedObjectKeys: "strip" })
+ : undefined,
+ user_id: userId,
+ user_ids: userIds,
+ limit,
+ offset,
+ };
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "billing/credits/spend-policies",
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url
+ .queryBuilder()
+ .addMany(_queryParams)
+ .mergeAdditional(requestOptions?.queryParams)
+ .build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.ListCreditSpendPoliciesResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "GET",
+ "/billing/credits/spend-policies",
+ );
+ }
+
+ /**
+ * @param {Schematic.CreateCreditSpendPolicyRequestBody} request
+ * @param {CreditsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.credits.createCreditSpendPolicy({
+ * billingCreditId: "billing_credit_id",
+ * maxPerDraw: 1.1
+ * })
+ */
+ public createCreditSpendPolicy(
+ request: Schematic.CreateCreditSpendPolicyRequestBody,
+ requestOptions?: CreditsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__createCreditSpendPolicy(request, requestOptions));
+ }
+
+ private async __createCreditSpendPolicy(
+ request: Schematic.CreateCreditSpendPolicyRequestBody,
+ requestOptions?: CreditsClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "billing/credits/spend-policies",
+ ),
+ method: "POST",
+ headers: _headers,
+ contentType: "application/json",
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ requestType: "json",
+ body: mergeAdditionalBodyParameters(
+ serializers.CreateCreditSpendPolicyRequestBody.jsonOrThrow(request, {
+ unrecognizedObjectKeys: "strip",
+ }),
+ requestOptions?.additionalBodyParameters,
+ ),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.CreateCreditSpendPolicyResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "POST",
+ "/billing/credits/spend-policies",
+ );
+ }
+
+ /**
+ * @param {string} spend_policy_id - spend_policy_id
+ * @param {CreditsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.credits.getCreditSpendPolicy("spend_policy_id")
+ */
+ public getCreditSpendPolicy(
+ spend_policy_id: string,
+ requestOptions?: CreditsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__getCreditSpendPolicy(spend_policy_id, requestOptions));
+ }
+
+ private async __getCreditSpendPolicy(
+ spend_policy_id: string,
+ requestOptions?: CreditsClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ `billing/credits/spend-policies/${core.url.encodePathParam(spend_policy_id)}`,
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.GetCreditSpendPolicyResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "GET",
+ "/billing/credits/spend-policies/{spend_policy_id}",
+ );
+ }
+
+ /**
+ * @param {string} spend_policy_id - spend_policy_id
+ * @param {Schematic.UpdateCreditSpendPolicyRequestBody} request
+ * @param {CreditsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.credits.updateCreditSpendPolicy("spend_policy_id")
+ */
+ public updateCreditSpendPolicy(
+ spend_policy_id: string,
+ request: Schematic.UpdateCreditSpendPolicyRequestBody = {},
+ requestOptions?: CreditsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(
+ this.__updateCreditSpendPolicy(spend_policy_id, request, requestOptions),
+ );
+ }
+
+ private async __updateCreditSpendPolicy(
+ spend_policy_id: string,
+ request: Schematic.UpdateCreditSpendPolicyRequestBody = {},
+ requestOptions?: CreditsClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ `billing/credits/spend-policies/${core.url.encodePathParam(spend_policy_id)}`,
+ ),
+ method: "PUT",
+ headers: _headers,
+ contentType: "application/json",
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ requestType: "json",
+ body: mergeAdditionalBodyParameters(
+ serializers.UpdateCreditSpendPolicyRequestBody.jsonOrThrow(request, {
+ unrecognizedObjectKeys: "strip",
+ }),
+ requestOptions?.additionalBodyParameters,
+ ),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.UpdateCreditSpendPolicyResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "PUT",
+ "/billing/credits/spend-policies/{spend_policy_id}",
+ );
+ }
+
+ /**
+ * @param {string} spend_policy_id - spend_policy_id
+ * @param {CreditsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.credits.deleteCreditSpendPolicy("spend_policy_id")
+ */
+ public deleteCreditSpendPolicy(
+ spend_policy_id: string,
+ requestOptions?: CreditsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__deleteCreditSpendPolicy(spend_policy_id, requestOptions));
+ }
+
+ private async __deleteCreditSpendPolicy(
+ spend_policy_id: string,
+ requestOptions?: CreditsClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ `billing/credits/spend-policies/${core.url.encodePathParam(spend_policy_id)}`,
+ ),
+ method: "DELETE",
+ headers: _headers,
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.DeleteCreditSpendPolicyResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "DELETE",
+ "/billing/credits/spend-policies/{spend_policy_id}",
+ );
+ }
+
+ /**
+ * @param {Schematic.CountCreditSpendPoliciesRequest} request
+ * @param {CreditsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.credits.countCreditSpendPolicies({
+ * billingCreditId: "billing_credit_id",
+ * companyId: "company_id",
+ * scopeType: "company",
+ * userId: "user_id",
+ * userIds: ["user_ids"],
+ * limit: 1000000,
+ * offset: 1000000
+ * })
+ */
+ public countCreditSpendPolicies(
+ request: Schematic.CountCreditSpendPoliciesRequest = {},
+ requestOptions?: CreditsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__countCreditSpendPolicies(request, requestOptions));
+ }
+
+ private async __countCreditSpendPolicies(
+ request: Schematic.CountCreditSpendPoliciesRequest = {},
+ requestOptions?: CreditsClient.RequestOptions,
+ ): Promise> {
+ const { billingCreditId, companyId, scopeType, userId, userIds, limit, offset } = request;
+ const _queryParams: Record = {
+ billing_credit_id: billingCreditId,
+ company_id: companyId,
+ scope_type:
+ scopeType != null
+ ? serializers.CreditSpendPolicyScope.jsonOrThrow(scopeType, { unrecognizedObjectKeys: "strip" })
+ : undefined,
+ user_id: userId,
+ user_ids: userIds,
+ limit,
+ offset,
+ };
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "billing/credits/spend-policies/count",
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url
+ .queryBuilder()
+ .addMany(_queryParams)
+ .mergeAdditional(requestOptions?.queryParams)
+ .build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.CountCreditSpendPoliciesResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "GET",
+ "/billing/credits/spend-policies/count",
+ );
+ }
+
/**
* @param {Schematic.ListCreditEventLedgerRequest} request
* @param {CreditsClient.RequestOptions} requestOptions - Request-specific configuration.
diff --git a/src/api/resources/credits/client/requests/CountCreditSpendPoliciesRequest.ts b/src/api/resources/credits/client/requests/CountCreditSpendPoliciesRequest.ts
new file mode 100644
index 00000000..82a6de7d
--- /dev/null
+++ b/src/api/resources/credits/client/requests/CountCreditSpendPoliciesRequest.ts
@@ -0,0 +1,27 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../index";
+
+/**
+ * @example
+ * {
+ * billingCreditId: "billing_credit_id",
+ * companyId: "company_id",
+ * scopeType: "company",
+ * userId: "user_id",
+ * userIds: ["user_ids"],
+ * limit: 1000000,
+ * offset: 1000000
+ * }
+ */
+export interface CountCreditSpendPoliciesRequest {
+ billingCreditId?: string;
+ companyId?: string;
+ scopeType?: Schematic.CreditSpendPolicyScope;
+ userId?: string;
+ userIds?: string | string[];
+ /** Page limit (default 100) */
+ limit?: number;
+ /** Page offset (default 0) */
+ offset?: number;
+}
diff --git a/src/api/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts b/src/api/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts
new file mode 100644
index 00000000..60a28c83
--- /dev/null
+++ b/src/api/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts
@@ -0,0 +1,19 @@
+// This file was auto-generated by Fern from our API Definition.
+
+/**
+ * @example
+ * {
+ * billingCreditId: "billing_credit_id",
+ * maxPerDraw: 1.1
+ * }
+ */
+export interface CreateCreditSpendPolicyRequestBody {
+ billingCreditId: string;
+ /** The company the cap applies to. Set exactly one of company_id and user_id. */
+ companyId?: string;
+ label?: string;
+ /** The largest number of credits a single draw may spend. */
+ maxPerDraw: number;
+ /** The user the cap applies to. Set exactly one of company_id and user_id. */
+ userId?: string;
+}
diff --git a/src/api/resources/credits/client/requests/ListCreditSpendPoliciesRequest.ts b/src/api/resources/credits/client/requests/ListCreditSpendPoliciesRequest.ts
new file mode 100644
index 00000000..19f11ae6
--- /dev/null
+++ b/src/api/resources/credits/client/requests/ListCreditSpendPoliciesRequest.ts
@@ -0,0 +1,27 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../index";
+
+/**
+ * @example
+ * {
+ * billingCreditId: "billing_credit_id",
+ * companyId: "company_id",
+ * scopeType: "company",
+ * userId: "user_id",
+ * userIds: ["user_ids"],
+ * limit: 1000000,
+ * offset: 1000000
+ * }
+ */
+export interface ListCreditSpendPoliciesRequest {
+ billingCreditId?: string;
+ companyId?: string;
+ scopeType?: Schematic.CreditSpendPolicyScope;
+ userId?: string;
+ userIds?: string | string[];
+ /** Page limit (default 100) */
+ limit?: number;
+ /** Page offset (default 0) */
+ offset?: number;
+}
diff --git a/src/api/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts b/src/api/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts
new file mode 100644
index 00000000..243af906
--- /dev/null
+++ b/src/api/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts
@@ -0,0 +1,10 @@
+// This file was auto-generated by Fern from our API Definition.
+
+/**
+ * @example
+ * {}
+ */
+export interface UpdateCreditSpendPolicyRequestBody {
+ label?: string;
+ maxPerDraw?: number;
+}
diff --git a/src/api/resources/credits/client/requests/index.ts b/src/api/resources/credits/client/requests/index.ts
index 3c019166..3da0aed6 100644
--- a/src/api/resources/credits/client/requests/index.ts
+++ b/src/api/resources/credits/client/requests/index.ts
@@ -5,9 +5,11 @@ export type { CountBillingPlanCreditGrantsRequest } from "./CountBillingPlanCred
export type { CountCompanyGrantsRequest } from "./CountCompanyGrantsRequest";
export type { CountCreditBundlesRequest } from "./CountCreditBundlesRequest";
export type { CountCreditEventLedgerRequest } from "./CountCreditEventLedgerRequest";
+export type { CountCreditSpendPoliciesRequest } from "./CountCreditSpendPoliciesRequest";
export type { CreateBillingCreditRequestBody } from "./CreateBillingCreditRequestBody";
export type { CreateCompanyCreditGrant } from "./CreateCompanyCreditGrant";
export type { CreateCreditBundleRequestBody } from "./CreateCreditBundleRequestBody";
+export type { CreateCreditSpendPolicyRequestBody } from "./CreateCreditSpendPolicyRequestBody";
export type { DeleteBillingPlanCreditGrantRequest } from "./DeleteBillingPlanCreditGrantRequest";
export type { ExtendCreditLeaseRequestBody } from "./ExtendCreditLeaseRequestBody";
export type { ListBillingCreditsRequest } from "./ListBillingCreditsRequest";
@@ -16,7 +18,9 @@ export type { ListCompanyCreditBalancesRequest } from "./ListCompanyCreditBalanc
export type { ListCompanyGrantsRequest } from "./ListCompanyGrantsRequest";
export type { ListCreditBundlesRequest } from "./ListCreditBundlesRequest";
export type { ListCreditEventLedgerRequest } from "./ListCreditEventLedgerRequest";
+export type { ListCreditSpendPoliciesRequest } from "./ListCreditSpendPoliciesRequest";
export type { ListGrantsForCreditRequest } from "./ListGrantsForCreditRequest";
export type { UpdateBillingCreditRequestBody } from "./UpdateBillingCreditRequestBody";
export type { UpdateCreditBundleDetailsRequestBody } from "./UpdateCreditBundleDetailsRequestBody";
+export type { UpdateCreditSpendPolicyRequestBody } from "./UpdateCreditSpendPolicyRequestBody";
export type { ZeroOutGrantRequestBody } from "./ZeroOutGrantRequestBody";
diff --git a/src/api/resources/credits/types/CountCreditSpendPoliciesParams.ts b/src/api/resources/credits/types/CountCreditSpendPoliciesParams.ts
new file mode 100644
index 00000000..f69267d2
--- /dev/null
+++ b/src/api/resources/credits/types/CountCreditSpendPoliciesParams.ts
@@ -0,0 +1,18 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+/**
+ * Input parameters
+ */
+export interface CountCreditSpendPoliciesParams {
+ billingCreditId?: string;
+ companyId?: string;
+ /** Page limit (default 100) */
+ limit?: number;
+ /** Page offset (default 0) */
+ offset?: number;
+ scopeType?: Schematic.CreditSpendPolicyScope;
+ userId?: string;
+ userIds?: string[];
+}
diff --git a/src/api/resources/credits/types/CountCreditSpendPoliciesResponse.ts b/src/api/resources/credits/types/CountCreditSpendPoliciesResponse.ts
new file mode 100644
index 00000000..7fc50bdc
--- /dev/null
+++ b/src/api/resources/credits/types/CountCreditSpendPoliciesResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface CountCreditSpendPoliciesResponse {
+ data: Schematic.CountResponse;
+ /** Input parameters */
+ params: Schematic.CountCreditSpendPoliciesParams;
+}
diff --git a/src/api/resources/credits/types/CreateCreditSpendPolicyResponse.ts b/src/api/resources/credits/types/CreateCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..f7f21416
--- /dev/null
+++ b/src/api/resources/credits/types/CreateCreditSpendPolicyResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface CreateCreditSpendPolicyResponse {
+ data: Schematic.CreditSpendPolicyResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/credits/types/DeleteCreditSpendPolicyResponse.ts b/src/api/resources/credits/types/DeleteCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..4ae4b8e4
--- /dev/null
+++ b/src/api/resources/credits/types/DeleteCreditSpendPolicyResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface DeleteCreditSpendPolicyResponse {
+ data: Schematic.DeleteResponse;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/credits/types/GetCreditSpendPolicyResponse.ts b/src/api/resources/credits/types/GetCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..f03ff954
--- /dev/null
+++ b/src/api/resources/credits/types/GetCreditSpendPolicyResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface GetCreditSpendPolicyResponse {
+ data: Schematic.CreditSpendPolicyResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/credits/types/ListCreditSpendPoliciesParams.ts b/src/api/resources/credits/types/ListCreditSpendPoliciesParams.ts
new file mode 100644
index 00000000..862184b3
--- /dev/null
+++ b/src/api/resources/credits/types/ListCreditSpendPoliciesParams.ts
@@ -0,0 +1,18 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+/**
+ * Input parameters
+ */
+export interface ListCreditSpendPoliciesParams {
+ billingCreditId?: string;
+ companyId?: string;
+ /** Page limit (default 100) */
+ limit?: number;
+ /** Page offset (default 0) */
+ offset?: number;
+ scopeType?: Schematic.CreditSpendPolicyScope;
+ userId?: string;
+ userIds?: string[];
+}
diff --git a/src/api/resources/credits/types/ListCreditSpendPoliciesResponse.ts b/src/api/resources/credits/types/ListCreditSpendPoliciesResponse.ts
new file mode 100644
index 00000000..2b91160b
--- /dev/null
+++ b/src/api/resources/credits/types/ListCreditSpendPoliciesResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface ListCreditSpendPoliciesResponse {
+ data: Schematic.CreditSpendPolicyResponseData[];
+ /** Input parameters */
+ params: Schematic.ListCreditSpendPoliciesParams;
+}
diff --git a/src/api/resources/credits/types/UpdateCreditSpendPolicyResponse.ts b/src/api/resources/credits/types/UpdateCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..1b3e908c
--- /dev/null
+++ b/src/api/resources/credits/types/UpdateCreditSpendPolicyResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface UpdateCreditSpendPolicyResponse {
+ data: Schematic.CreditSpendPolicyResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/credits/types/index.ts b/src/api/resources/credits/types/index.ts
index 2e92a33a..f55d471c 100644
--- a/src/api/resources/credits/types/index.ts
+++ b/src/api/resources/credits/types/index.ts
@@ -11,14 +11,19 @@ export * from "./CountCreditBundlesParams";
export * from "./CountCreditBundlesResponse";
export * from "./CountCreditEventLedgerParams";
export * from "./CountCreditEventLedgerResponse";
+export * from "./CountCreditSpendPoliciesParams";
+export * from "./CountCreditSpendPoliciesResponse";
export * from "./CreateBillingCreditResponse";
export * from "./CreateBillingPlanCreditGrantResponse";
export * from "./CreateCreditBundleResponse";
+export * from "./CreateCreditSpendPolicyResponse";
export * from "./DeleteBillingPlanCreditGrantParams";
export * from "./DeleteBillingPlanCreditGrantResponse";
export * from "./DeleteCreditBundleResponse";
+export * from "./DeleteCreditSpendPolicyResponse";
export * from "./ExtendCreditLeaseResponse";
export * from "./GetCreditBundleResponse";
+export * from "./GetCreditSpendPolicyResponse";
export * from "./GetSingleBillingCreditResponse";
export * from "./GetSingleBillingPlanCreditGrantResponse";
export * from "./GrantBillingCreditsToCompanyResponse";
@@ -34,6 +39,8 @@ export * from "./ListCreditBundlesParams";
export * from "./ListCreditBundlesResponse";
export * from "./ListCreditEventLedgerParams";
export * from "./ListCreditEventLedgerResponse";
+export * from "./ListCreditSpendPoliciesParams";
+export * from "./ListCreditSpendPoliciesResponse";
export * from "./ListGrantsForCreditParams";
export * from "./ListGrantsForCreditResponse";
export * from "./ReleaseCreditLeaseResponse";
@@ -41,4 +48,5 @@ export * from "./SoftDeleteBillingCreditResponse";
export * from "./UpdateBillingCreditResponse";
export * from "./UpdateBillingPlanCreditGrantResponse";
export * from "./UpdateCreditBundleDetailsResponse";
+export * from "./UpdateCreditSpendPolicyResponse";
export * from "./ZeroOutGrantResponse";
diff --git a/src/api/resources/events/client/Client.ts b/src/api/resources/events/client/Client.ts
index 8ab61512..71a9bccd 100644
--- a/src/api/resources/events/client/Client.ts
+++ b/src/api/resources/events/client/Client.ts
@@ -724,6 +724,388 @@ export class EventsClient {
return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/events/{event_id}");
}
+ /**
+ * @param {EventsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.events.getOtlpEnvironmentSettings()
+ */
+ public getOtlpEnvironmentSettings(
+ requestOptions?: EventsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__getOtlpEnvironmentSettings(requestOptions));
+ }
+
+ private async __getOtlpEnvironmentSettings(
+ requestOptions?: EventsClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "otlp/settings",
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.GetOtlpEnvironmentSettingsResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/otlp/settings");
+ }
+
+ /**
+ * @param {Schematic.UpsertOtlpEnvironmentSettingsRequestBody} request
+ * @param {EventsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.events.upsertOtlpEnvironmentSettings({
+ * toolEventsEnabled: true
+ * })
+ */
+ public upsertOtlpEnvironmentSettings(
+ request: Schematic.UpsertOtlpEnvironmentSettingsRequestBody,
+ requestOptions?: EventsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__upsertOtlpEnvironmentSettings(request, requestOptions));
+ }
+
+ private async __upsertOtlpEnvironmentSettings(
+ request: Schematic.UpsertOtlpEnvironmentSettingsRequestBody,
+ requestOptions?: EventsClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "otlp/settings",
+ ),
+ method: "POST",
+ headers: _headers,
+ contentType: "application/json",
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ requestType: "json",
+ body: mergeAdditionalBodyParameters(
+ serializers.UpsertOtlpEnvironmentSettingsRequestBody.jsonOrThrow(request, {
+ unrecognizedObjectKeys: "strip",
+ }),
+ requestOptions?.additionalBodyParameters,
+ ),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.UpsertOtlpEnvironmentSettingsResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/otlp/settings");
+ }
+
+ /**
+ * @param {EventsClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.events.deleteOtlpEnvironmentSettings()
+ */
+ public deleteOtlpEnvironmentSettings(
+ requestOptions?: EventsClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__deleteOtlpEnvironmentSettings(requestOptions));
+ }
+
+ private async __deleteOtlpEnvironmentSettings(
+ requestOptions?: EventsClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "otlp/settings",
+ ),
+ method: "DELETE",
+ headers: _headers,
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.DeleteOtlpEnvironmentSettingsResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/otlp/settings");
+ }
+
/**
* @param {EventsClient.RequestOptions} requestOptions - Request-specific configuration.
*
diff --git a/src/api/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts b/src/api/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts
new file mode 100644
index 00000000..1e19c220
--- /dev/null
+++ b/src/api/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts
@@ -0,0 +1,15 @@
+// This file was auto-generated by Fern from our API Definition.
+
+/**
+ * @example
+ * {
+ * toolEventsEnabled: true
+ * }
+ */
+export interface UpsertOtlpEnvironmentSettingsRequestBody {
+ companyAttribute?: string;
+ companyKey?: string;
+ toolEventsEnabled: boolean;
+ userAttribute?: string;
+ userKey?: string;
+}
diff --git a/src/api/resources/events/client/requests/index.ts b/src/api/resources/events/client/requests/index.ts
index 5a36c08e..2a53be06 100644
--- a/src/api/resources/events/client/requests/index.ts
+++ b/src/api/resources/events/client/requests/index.ts
@@ -1,3 +1,4 @@
export type { CreateEventBatchRequestBody } from "./CreateEventBatchRequestBody";
export type { GetEventSummariesRequest } from "./GetEventSummariesRequest";
export type { ListEventsRequest } from "./ListEventsRequest";
+export type { UpsertOtlpEnvironmentSettingsRequestBody } from "./UpsertOtlpEnvironmentSettingsRequestBody";
diff --git a/src/api/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts b/src/api/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts
new file mode 100644
index 00000000..329f8016
--- /dev/null
+++ b/src/api/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface DeleteOtlpEnvironmentSettingsResponse {
+ data: Schematic.DeleteResponse;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts b/src/api/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts
new file mode 100644
index 00000000..91c48f48
--- /dev/null
+++ b/src/api/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface GetOtlpEnvironmentSettingsResponse {
+ data: Schematic.OtlpEnvironmentSettingsResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts b/src/api/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts
new file mode 100644
index 00000000..e7b47969
--- /dev/null
+++ b/src/api/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface UpsertOtlpEnvironmentSettingsResponse {
+ data: Schematic.OtlpEnvironmentSettingsResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/events/types/index.ts b/src/api/resources/events/types/index.ts
index 421f16fb..3ed83d82 100644
--- a/src/api/resources/events/types/index.ts
+++ b/src/api/resources/events/types/index.ts
@@ -1,8 +1,11 @@
export * from "./CreateEventBatchResponse";
export * from "./CreateEventResponse";
+export * from "./DeleteOtlpEnvironmentSettingsResponse";
export * from "./GetEventResponse";
export * from "./GetEventSummariesParams";
export * from "./GetEventSummariesResponse";
+export * from "./GetOtlpEnvironmentSettingsResponse";
export * from "./GetSegmentIntegrationStatusResponse";
export * from "./ListEventsParams";
export * from "./ListEventsResponse";
+export * from "./UpsertOtlpEnvironmentSettingsResponse";
diff --git a/src/api/resources/integrationsapi/client/Client.ts b/src/api/resources/integrationsapi/client/Client.ts
index 5143f235..e22d0317 100644
--- a/src/api/resources/integrationsapi/client/Client.ts
+++ b/src/api/resources/integrationsapi/client/Client.ts
@@ -829,6 +829,389 @@ export class IntegrationsapiClient {
);
}
+ /**
+ * @param {IntegrationsapiClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.integrationsapi.getStripeSandboxClaimLink()
+ */
+ public getStripeSandboxClaimLink(
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__getStripeSandboxClaimLink(requestOptions));
+ }
+
+ private async __getStripeSandboxClaimLink(
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "integrations/stripe/sandbox/claim-link",
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.GetStripeSandboxClaimLinkResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "GET",
+ "/integrations/stripe/sandbox/claim-link",
+ );
+ }
+
+ /**
+ * @param {IntegrationsapiClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.integrationsapi.getStripeSandboxKeys()
+ */
+ public getStripeSandboxKeys(
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__getStripeSandboxKeys(requestOptions));
+ }
+
+ private async __getStripeSandboxKeys(
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "integrations/stripe/sandbox/keys",
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.GetStripeSandboxKeysResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "GET",
+ "/integrations/stripe/sandbox/keys",
+ );
+ }
+
+ /**
+ * @param {Schematic.ClaimStripeSandboxKeysRequestBody} request
+ * @param {IntegrationsapiClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.integrationsapi.claimStripeSandboxKeys({
+ * token: "token"
+ * })
+ */
+ public claimStripeSandboxKeys(
+ request: Schematic.ClaimStripeSandboxKeysRequestBody,
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__claimStripeSandboxKeys(request, requestOptions));
+ }
+
+ private async __claimStripeSandboxKeys(
+ request: Schematic.ClaimStripeSandboxKeysRequestBody,
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "integrations/stripe/sandbox/keys/claim",
+ ),
+ method: "POST",
+ headers: _headers,
+ contentType: "application/json",
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ requestType: "json",
+ body: mergeAdditionalBodyParameters(
+ serializers.ClaimStripeSandboxKeysRequestBody.jsonOrThrow(request, { unrecognizedObjectKeys: "strip" }),
+ requestOptions?.additionalBodyParameters,
+ ),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.ClaimStripeSandboxKeysResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "POST",
+ "/integrations/stripe/sandbox/keys/claim",
+ );
+ }
+
/**
* @param {Schematic.InstallIntegrationRequestBody} request
* @param {IntegrationsapiClient.RequestOptions} requestOptions - Request-specific configuration.
@@ -1115,6 +1498,269 @@ export class IntegrationsapiClient {
);
}
+ /**
+ * @param {Schematic.InstallStripeSandboxRequestBody} request
+ * @param {IntegrationsapiClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.BadRequestError}
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.integrationsapi.installStripeClaimableSandbox({
+ * email: "email"
+ * })
+ */
+ public installStripeClaimableSandbox(
+ request: Schematic.InstallStripeSandboxRequestBody,
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__installStripeClaimableSandbox(request, requestOptions));
+ }
+
+ private async __installStripeClaimableSandbox(
+ request: Schematic.InstallStripeSandboxRequestBody,
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "integrations/stripe/v2/sandbox",
+ ),
+ method: "POST",
+ headers: _headers,
+ contentType: "application/json",
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ requestType: "json",
+ body: mergeAdditionalBodyParameters(
+ serializers.InstallStripeSandboxRequestBody.jsonOrThrow(request, { unrecognizedObjectKeys: "strip" }),
+ requestOptions?.additionalBodyParameters,
+ ),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.InstallStripeClaimableSandboxResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 400:
+ throw new Schematic.BadRequestError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "POST",
+ "/integrations/stripe/v2/sandbox",
+ );
+ }
+
+ /**
+ * @param {IntegrationsapiClient.RequestOptions} requestOptions - Request-specific configuration.
+ *
+ * @throws {@link Schematic.UnauthorizedError}
+ * @throws {@link Schematic.ForbiddenError}
+ * @throws {@link Schematic.NotFoundError}
+ * @throws {@link Schematic.InternalServerError}
+ * @throws {@link errors.SchematicError}
+ * @throws {@link errors.SchematicTimeoutError}
+ *
+ * @example
+ * await client.integrationsapi.listStripeSandboxCountries()
+ */
+ public listStripeSandboxCountries(
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): core.HttpResponsePromise {
+ return core.HttpResponsePromise.fromPromise(this.__listStripeSandboxCountries(requestOptions));
+ }
+
+ private async __listStripeSandboxCountries(
+ requestOptions?: IntegrationsapiClient.RequestOptions,
+ ): Promise> {
+ const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
+ const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
+ _authRequest.headers,
+ this._options?.headers,
+ requestOptions?.headers,
+ );
+ const _response = await (this._options.fetcher ?? core.fetcher)({
+ url: core.url.join(
+ (await core.Supplier.get(this._options.baseUrl)) ??
+ (await core.Supplier.get(this._options.environment)) ??
+ environments.SchematicEnvironment.Default,
+ "integrations/stripe/v2/sandbox-countries",
+ ),
+ method: "GET",
+ headers: _headers,
+ queryString: core.url.queryBuilder().mergeAdditional(requestOptions?.queryParams).build(),
+ timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 60) * 1000,
+ maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
+ abortSignal: requestOptions?.abortSignal,
+ fetchFn: this._options?.fetch,
+ logging: this._options.logging,
+ });
+ if (_response.ok) {
+ return {
+ data: serializers.ListStripeSandboxCountriesResponse.parseOrThrow(_response.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ rawResponse: _response.rawResponse,
+ };
+ }
+
+ if (_response.error.reason === "status-code") {
+ switch (_response.error.statusCode) {
+ case 401:
+ throw new Schematic.UnauthorizedError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 403:
+ throw new Schematic.ForbiddenError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 404:
+ throw new Schematic.NotFoundError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ case 500:
+ throw new Schematic.InternalServerError(
+ serializers.ApiError.parseOrThrow(_response.error.body, {
+ unrecognizedObjectKeys: "passthrough",
+ allowUnrecognizedUnionMembers: true,
+ allowUnrecognizedEnumValues: true,
+ skipValidation: true,
+ breadcrumbsPrefix: ["response"],
+ }),
+ _response.rawResponse,
+ );
+ default:
+ throw new errors.SchematicError({
+ statusCode: _response.error.statusCode,
+ body: _response.error.body,
+ rawResponse: _response.rawResponse,
+ });
+ }
+ }
+
+ return handleNonStatusCodeError(
+ _response.error,
+ _response.rawResponse,
+ "GET",
+ "/integrations/stripe/v2/sandbox-countries",
+ );
+ }
+
/**
* @param {string} integration_id - integration_id
* @param {IntegrationsapiClient.RequestOptions} requestOptions - Request-specific configuration.
diff --git a/src/api/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts b/src/api/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts
new file mode 100644
index 00000000..2dbe821d
--- /dev/null
+++ b/src/api/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts
@@ -0,0 +1,11 @@
+// This file was auto-generated by Fern from our API Definition.
+
+/**
+ * @example
+ * {
+ * token: "token"
+ * }
+ */
+export interface ClaimStripeSandboxKeysRequestBody {
+ token: string;
+}
diff --git a/src/api/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts b/src/api/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts
new file mode 100644
index 00000000..7bcde347
--- /dev/null
+++ b/src/api/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts
@@ -0,0 +1,14 @@
+// This file was auto-generated by Fern from our API Definition.
+
+/**
+ * @example
+ * {
+ * email: "email"
+ * }
+ */
+export interface InstallStripeSandboxRequestBody {
+ country?: string;
+ email: string;
+ name?: string;
+ seedSampleData?: boolean;
+}
diff --git a/src/api/resources/integrationsapi/client/requests/index.ts b/src/api/resources/integrationsapi/client/requests/index.ts
index c4031dc4..eba3e6b5 100644
--- a/src/api/resources/integrationsapi/client/requests/index.ts
+++ b/src/api/resources/integrationsapi/client/requests/index.ts
@@ -1,2 +1,4 @@
+export type { ClaimStripeSandboxKeysRequestBody } from "./ClaimStripeSandboxKeysRequestBody";
+export type { InstallStripeSandboxRequestBody } from "./InstallStripeSandboxRequestBody";
export type { ListIntegrationsRequest } from "./ListIntegrationsRequest";
export type { StartDataImportRequestBody } from "./StartDataImportRequestBody";
diff --git a/src/api/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts b/src/api/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts
new file mode 100644
index 00000000..04e8c07f
--- /dev/null
+++ b/src/api/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface ClaimStripeSandboxKeysResponse {
+ data: Schematic.ClaimedStripeSandboxKeysResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts b/src/api/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts
new file mode 100644
index 00000000..b8403e32
--- /dev/null
+++ b/src/api/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface GetStripeSandboxClaimLinkResponse {
+ data: Schematic.StripeSandboxClaimLink;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts b/src/api/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts
new file mode 100644
index 00000000..5a061ef2
--- /dev/null
+++ b/src/api/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface GetStripeSandboxKeysResponse {
+ data: Schematic.ClaimedStripeSandboxKeysResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts b/src/api/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts
new file mode 100644
index 00000000..06dff8dc
--- /dev/null
+++ b/src/api/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface InstallStripeClaimableSandboxResponse {
+ data: Schematic.StripeSandboxInstallResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts b/src/api/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts
new file mode 100644
index 00000000..31739cae
--- /dev/null
+++ b/src/api/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts
@@ -0,0 +1,9 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../index";
+
+export interface ListStripeSandboxCountriesResponse {
+ data: Schematic.StripeSandboxCountriesResponseData;
+ /** Input parameters */
+ params: Record;
+}
diff --git a/src/api/resources/integrationsapi/types/index.ts b/src/api/resources/integrationsapi/types/index.ts
index 3c4b71a4..3835c1ba 100644
--- a/src/api/resources/integrationsapi/types/index.ts
+++ b/src/api/resources/integrationsapi/types/index.ts
@@ -1,9 +1,14 @@
export * from "./AssumeStripeInstalledResponse";
+export * from "./ClaimStripeSandboxKeysResponse";
export * from "./GetIntegrationWebhookUrlResponse";
+export * from "./GetStripeSandboxClaimLinkResponse";
+export * from "./GetStripeSandboxKeysResponse";
export * from "./InstallIntegrationResponse";
+export * from "./InstallStripeClaimableSandboxResponse";
export * from "./InstallStripeResponse";
export * from "./ListIntegrationsParams";
export * from "./ListIntegrationsResponse";
+export * from "./ListStripeSandboxCountriesResponse";
export * from "./LoadSampleDataSetResponse";
export * from "./RunIntegrationResponse";
export * from "./StartDataImportResponse";
diff --git a/src/api/types/ClaimedStripeSandboxKeysResponseData.ts b/src/api/types/ClaimedStripeSandboxKeysResponseData.ts
new file mode 100644
index 00000000..90342d33
--- /dev/null
+++ b/src/api/types/ClaimedStripeSandboxKeysResponseData.ts
@@ -0,0 +1,7 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export interface ClaimedStripeSandboxKeysResponseData {
+ publishable: string;
+ sandboxId: string;
+ secret: string;
+}
diff --git a/src/api/types/CompanyBillingProfileResponseData.ts b/src/api/types/CompanyBillingProfileResponseData.ts
new file mode 100644
index 00000000..61f81774
--- /dev/null
+++ b/src/api/types/CompanyBillingProfileResponseData.ts
@@ -0,0 +1,20 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../index";
+
+export interface CompanyBillingProfileResponseData {
+ accountId: string;
+ billingCustomerId?: string;
+ collectionMethod: Schematic.BillingCollectionMethod;
+ companyId: string;
+ createdAt: Date;
+ daysUntilDue?: number;
+ environmentId: string;
+ id: string;
+ isDefault: boolean;
+ name?: string;
+ paymentMethodId?: string;
+ prorationBehavior?: Schematic.ProrationBehavior;
+ providerType: Schematic.BillingProviderType;
+ updatedAt: Date;
+}
diff --git a/src/api/types/CompanyDetailResponseData.ts b/src/api/types/CompanyDetailResponseData.ts
index aaec8c3d..7c12b495 100644
--- a/src/api/types/CompanyDetailResponseData.ts
+++ b/src/api/types/CompanyDetailResponseData.ts
@@ -5,6 +5,8 @@ import type * as Schematic from "../index";
export interface CompanyDetailResponseData {
addOns: Schematic.CompanyPlanWithBillingSubView[];
billingCreditBalances?: Record;
+ billingProfile?: Schematic.CompanyBillingProfileResponseData;
+ billingProfiles?: Schematic.CompanyBillingProfileResponseData[];
billingSubscription?: Schematic.BillingSubscriptionView;
billingSubscriptions: Schematic.BillingSubscriptionView[];
createdAt: Date;
diff --git a/src/api/types/CompanyOverrideResponseData.ts b/src/api/types/CompanyOverrideResponseData.ts
index ad78e24a..924d4fb0 100644
--- a/src/api/types/CompanyOverrideResponseData.ts
+++ b/src/api/types/CompanyOverrideResponseData.ts
@@ -19,6 +19,8 @@ export interface CompanyOverrideResponseData {
ruleIdUsageExceeded?: string;
updatedAt: Date;
valueBool?: boolean;
+ valueCredit?: Schematic.BillingCreditResponseData;
+ valueCreditId?: string;
valueNumeric?: number;
valueTrait?: Schematic.EntityTraitDefinitionResponseData;
valueTraitId?: string;
diff --git a/src/api/types/CreditSpendPolicyResponseData.ts b/src/api/types/CreditSpendPolicyResponseData.ts
new file mode 100644
index 00000000..b30575a1
--- /dev/null
+++ b/src/api/types/CreditSpendPolicyResponseData.ts
@@ -0,0 +1,15 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../index";
+
+export interface CreditSpendPolicyResponseData {
+ billingCreditId: string;
+ companyId?: string;
+ createdAt: Date;
+ id: string;
+ label?: string;
+ maxPerDraw?: number;
+ scopeType: Schematic.CreditSpendPolicyScope;
+ updatedAt: Date;
+ userId?: string;
+}
diff --git a/src/api/types/CreditSpendPolicyScope.ts b/src/api/types/CreditSpendPolicyScope.ts
new file mode 100644
index 00000000..16ab934d
--- /dev/null
+++ b/src/api/types/CreditSpendPolicyScope.ts
@@ -0,0 +1,8 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export const CreditSpendPolicyScope = {
+ Company: "company",
+ User: "user",
+ Group: "group",
+} as const;
+export type CreditSpendPolicyScope = (typeof CreditSpendPolicyScope)[keyof typeof CreditSpendPolicyScope];
diff --git a/src/api/types/EventBodyInference.ts b/src/api/types/EventBodyInference.ts
index 13546c06..ed70210d 100644
--- a/src/api/types/EventBodyInference.ts
+++ b/src/api/types/EventBodyInference.ts
@@ -1,7 +1,9 @@
// This file was auto-generated by Fern from our API Definition.
export interface EventBodyInference {
- /** Number of input tokens served from cache */
+ /** Number of input tokens written to a prompt cache; a subset of input_tokens */
+ cacheCreationInputTokens?: number;
+ /** Number of input tokens served from cache; a subset of input_tokens */
cachedInputTokens?: number;
/** Key-value pairs to identify the company associated with the inference event */
company: Record;
@@ -11,7 +13,7 @@ export interface EventBodyInference {
currency?: string;
/** Optional track event name to fan out for usage-based billing */
event?: string;
- /** Number of input tokens for the inference request */
+ /** Total number of input tokens for the inference request, including those served from and written to a prompt cache */
inputTokens: number;
/** The inference operation; defaults to 'chat' */
operation?: string;
diff --git a/src/api/types/GetOnboardingStateResp.ts b/src/api/types/GetOnboardingStateResp.ts
index 96aedc54..31249da0 100644
--- a/src/api/types/GetOnboardingStateResp.ts
+++ b/src/api/types/GetOnboardingStateResp.ts
@@ -4,6 +4,7 @@ import type * as Schematic from "../index";
export interface GetOnboardingStateResp {
agentConnectedAt?: Date;
+ country?: string;
dismissedAt?: Date;
environmentId?: string;
milestones: Schematic.OnboardingMilestoneView[];
diff --git a/src/api/types/OtlpEnvironmentSettingsResponseData.ts b/src/api/types/OtlpEnvironmentSettingsResponseData.ts
new file mode 100644
index 00000000..5320255d
--- /dev/null
+++ b/src/api/types/OtlpEnvironmentSettingsResponseData.ts
@@ -0,0 +1,12 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export interface OtlpEnvironmentSettingsResponseData {
+ companyAttribute?: string;
+ companyKey?: string;
+ createdAt: Date;
+ environmentId: string;
+ toolEventsEnabled: boolean;
+ updatedAt: Date;
+ userAttribute?: string;
+ userKey?: string;
+}
diff --git a/src/api/types/RuleConditionDetailResponseData.ts b/src/api/types/RuleConditionDetailResponseData.ts
index 73053ae3..950eb7f5 100644
--- a/src/api/types/RuleConditionDetailResponseData.ts
+++ b/src/api/types/RuleConditionDetailResponseData.ts
@@ -16,6 +16,7 @@ export interface RuleConditionDetailResponseData {
metricPeriodMonthReset?: Schematic.MetricPeriodMonthReset;
metricValue?: number;
operator: Schematic.ComparableOperator;
+ planVersions?: Schematic.RuleConditionPlanVersionResponseData[];
resourceIds: string[];
resources: Schematic.PreviewObjectResponseData[];
ruleId: string;
diff --git a/src/api/types/RuleConditionPlanVersionResponseData.ts b/src/api/types/RuleConditionPlanVersionResponseData.ts
new file mode 100644
index 00000000..bc96054b
--- /dev/null
+++ b/src/api/types/RuleConditionPlanVersionResponseData.ts
@@ -0,0 +1,10 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../index";
+
+export interface RuleConditionPlanVersionResponseData {
+ id: string;
+ name: string;
+ status: Schematic.PlanVersionStatus;
+ version: number;
+}
diff --git a/src/api/types/StripeIntegrationConfig.ts b/src/api/types/StripeIntegrationConfig.ts
index 9092df41..e9a30de9 100644
--- a/src/api/types/StripeIntegrationConfig.ts
+++ b/src/api/types/StripeIntegrationConfig.ts
@@ -5,6 +5,12 @@ export interface StripeIntegrationConfig {
accountId?: string;
/** Display name of the connected Stripe account */
accountName?: string;
+ /** When Stripe deletes the sandbox if nobody claims it, 60 days from creation; absent on sandboxes created before it was recorded */
+ claimableSandboxExpiresAt?: Date;
+ /** Stripe claimable sandbox this connection was provisioned from; absent for an OAuth connect */
+ claimableSandboxId?: string;
+ /** Stripe's claim status for the sandbox: unclaimed, claimed, or live */
+ claimableSandboxStatus?: string;
/** When importing Stripe customers, only update existing companies, do not create new companies */
companyUpdateOnly?: boolean;
/** Whether the integration is connected to a Stripe sandbox account */
diff --git a/src/api/types/StripeSandboxClaimLink.ts b/src/api/types/StripeSandboxClaimLink.ts
new file mode 100644
index 00000000..da3a12fe
--- /dev/null
+++ b/src/api/types/StripeSandboxClaimLink.ts
@@ -0,0 +1,8 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export interface StripeSandboxClaimLink {
+ claimUrl: string;
+ expiresAt?: Date;
+ sandboxId: string;
+ status: string;
+}
diff --git a/src/api/types/StripeSandboxCountriesResponseData.ts b/src/api/types/StripeSandboxCountriesResponseData.ts
new file mode 100644
index 00000000..aceb61f7
--- /dev/null
+++ b/src/api/types/StripeSandboxCountriesResponseData.ts
@@ -0,0 +1,5 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export interface StripeSandboxCountriesResponseData {
+ countries: string[];
+}
diff --git a/src/api/types/StripeSandboxInstallResponseData.ts b/src/api/types/StripeSandboxInstallResponseData.ts
new file mode 100644
index 00000000..5a8d30de
--- /dev/null
+++ b/src/api/types/StripeSandboxInstallResponseData.ts
@@ -0,0 +1,13 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../index";
+
+export interface StripeSandboxInstallResponseData {
+ apiKeys?: Schematic.StripeSandboxKeysResponseData;
+ claimUrl: string;
+ claimUrlExpiresAt?: Date;
+ expiresAt?: Date;
+ install: Schematic.IntegrationInstallResponseData;
+ sandboxId: string;
+ stripeAccountId: string;
+}
diff --git a/src/api/types/StripeSandboxKeysResponseData.ts b/src/api/types/StripeSandboxKeysResponseData.ts
new file mode 100644
index 00000000..da5879e4
--- /dev/null
+++ b/src/api/types/StripeSandboxKeysResponseData.ts
@@ -0,0 +1,7 @@
+// This file was auto-generated by Fern from our API Definition.
+
+export interface StripeSandboxKeysResponseData {
+ mcp: string;
+ publishable: string;
+ secret: string;
+}
diff --git a/src/api/types/index.ts b/src/api/types/index.ts
index 6e7d3cb9..f54b90e5 100644
--- a/src/api/types/index.ts
+++ b/src/api/types/index.ts
@@ -89,6 +89,7 @@ export * from "./CheckoutFieldValue";
export * from "./CheckoutFieldWithValue";
export * from "./CheckoutSettingsResponseData";
export * from "./CheckoutSubscription";
+export * from "./ClaimedStripeSandboxKeysResponseData";
export * from "./ClerkIntegrationConfig";
export * from "./CompanyBillingAddressView";
export * from "./CompanyBillingCheckoutSettings";
@@ -96,6 +97,7 @@ export * from "./CompanyBillingDetailsResponseData";
export * from "./CompanyBillingDetailsView";
export * from "./CompanyBillingEntityResponseData";
export * from "./CompanyBillingEntitySubscriptionResponseData";
+export * from "./CompanyBillingProfileResponseData";
export * from "./CompanyCreditBalance";
export * from "./CompanyCreditBalanceResponseData";
export * from "./CompanyDetailResponseData";
@@ -165,6 +167,8 @@ export * from "./CreditGrantDetail";
export * from "./CreditGrantExpiryRequestBody";
export * from "./CreditGrantSortOrder";
export * from "./CreditLeaseResponseData";
+export * from "./CreditSpendPolicyResponseData";
+export * from "./CreditSpendPolicyScope";
export * from "./CreditsAutoTopupCompanySummary";
export * from "./CreditsAutoTopupCreditSummary";
export * from "./CreditsAutoTopupHardFailure";
@@ -293,6 +297,7 @@ export * from "./OnboardingStripeImport";
export * from "./OnboardingTrack";
export * from "./OrbIntegrationConfig";
export * from "./OrderedPlansInGroup";
+export * from "./OtlpEnvironmentSettingsResponseData";
export * from "./PaymentMethodRequestBody";
export * from "./PaymentMethodResponseData";
export * from "./PendingMigrationResponseData";
@@ -357,6 +362,7 @@ export * from "./Rule";
export * from "./RuleConditionDetailResponseData";
export * from "./RuleConditionGroupDetailResponseData";
export * from "./RuleConditionGroupResponseData";
+export * from "./RuleConditionPlanVersionResponseData";
export * from "./RuleConditionResponseData";
export * from "./RuleDetailResponseData";
export * from "./RuleResponseData";
@@ -394,6 +400,10 @@ export * from "./SkippedEntitlementResponseData";
export * from "./SortDirection";
export * from "./StripeEmbedInfo";
export * from "./StripeIntegrationConfig";
+export * from "./StripeSandboxClaimLink";
+export * from "./StripeSandboxCountriesResponseData";
+export * from "./StripeSandboxInstallResponseData";
+export * from "./StripeSandboxKeysResponseData";
export * from "./SubscriptionStatus";
export * from "./SubscriptionTraitUpdate";
export * from "./SubscriptionType";
diff --git a/src/serialization/resources/accounts/client/requests/UpdateOnboardingStateRequestBody.ts b/src/serialization/resources/accounts/client/requests/UpdateOnboardingStateRequestBody.ts
index abaae39d..fa20843a 100644
--- a/src/serialization/resources/accounts/client/requests/UpdateOnboardingStateRequestBody.ts
+++ b/src/serialization/resources/accounts/client/requests/UpdateOnboardingStateRequestBody.ts
@@ -10,6 +10,7 @@ export const UpdateOnboardingStateRequestBody: core.serialization.Schema<
serializers.UpdateOnboardingStateRequestBody.Raw,
Schematic.UpdateOnboardingStateRequestBody
> = core.serialization.object({
+ country: core.serialization.string().optional(),
dismissed: core.serialization.boolean().optional(),
path: OnboardingPath.optional(),
pricingPageUrl: core.serialization.property("pricing_page_url", core.serialization.string().optional()),
@@ -19,6 +20,7 @@ export const UpdateOnboardingStateRequestBody: core.serialization.Schema<
export declare namespace UpdateOnboardingStateRequestBody {
export interface Raw {
+ country?: string | null;
dismissed?: boolean | null;
path?: OnboardingPath.Raw | null;
pricing_page_url?: string | null;
diff --git a/src/serialization/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts b/src/serialization/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts
new file mode 100644
index 00000000..b11634ec
--- /dev/null
+++ b/src/serialization/resources/billing/client/requests/UpdateCompanyBillingProfileRequestBody.ts
@@ -0,0 +1,30 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../../api/index";
+import * as core from "../../../../../core";
+import type * as serializers from "../../../../index";
+import { BillingCollectionMethod } from "../../../../types/BillingCollectionMethod";
+import { ProrationBehavior } from "../../../../types/ProrationBehavior";
+
+export const UpdateCompanyBillingProfileRequestBody: core.serialization.Schema<
+ serializers.UpdateCompanyBillingProfileRequestBody.Raw,
+ Schematic.UpdateCompanyBillingProfileRequestBody
+> = core.serialization.object({
+ collectionMethod: core.serialization.property("collection_method", BillingCollectionMethod),
+ daysUntilDue: core.serialization.property("days_until_due", core.serialization.number().optional()),
+ isDefault: core.serialization.property("is_default", core.serialization.boolean().optional()),
+ name: core.serialization.string().optional(),
+ paymentMethodId: core.serialization.property("payment_method_id", core.serialization.string().optional()),
+ prorationBehavior: core.serialization.property("proration_behavior", ProrationBehavior.optional()),
+});
+
+export declare namespace UpdateCompanyBillingProfileRequestBody {
+ export interface Raw {
+ collection_method: BillingCollectionMethod.Raw;
+ days_until_due?: number | null;
+ is_default?: boolean | null;
+ name?: string | null;
+ payment_method_id?: string | null;
+ proration_behavior?: ProrationBehavior.Raw | null;
+ }
+}
diff --git a/src/serialization/resources/billing/client/requests/index.ts b/src/serialization/resources/billing/client/requests/index.ts
index ae39129e..2e05f983 100644
--- a/src/serialization/resources/billing/client/requests/index.ts
+++ b/src/serialization/resources/billing/client/requests/index.ts
@@ -6,3 +6,4 @@ export { CreateCouponRequestBody } from "./CreateCouponRequestBody";
export { CreateInvoiceRequestBody } from "./CreateInvoiceRequestBody";
export { CreateMeterRequestBody } from "./CreateMeterRequestBody";
export { CreatePaymentMethodRequestBody } from "./CreatePaymentMethodRequestBody";
+export { UpdateCompanyBillingProfileRequestBody } from "./UpdateCompanyBillingProfileRequestBody";
diff --git a/src/serialization/resources/billing/types/ListCompanyBillingProfilesParams.ts b/src/serialization/resources/billing/types/ListCompanyBillingProfilesParams.ts
new file mode 100644
index 00000000..f4a414ae
--- /dev/null
+++ b/src/serialization/resources/billing/types/ListCompanyBillingProfilesParams.ts
@@ -0,0 +1,27 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { BillingProviderType } from "../../../types/BillingProviderType";
+
+export const ListCompanyBillingProfilesParams: core.serialization.ObjectSchema<
+ serializers.ListCompanyBillingProfilesParams.Raw,
+ Schematic.ListCompanyBillingProfilesParams
+> = core.serialization.object({
+ companyId: core.serialization.property("company_id", core.serialization.string().optional()),
+ isDefault: core.serialization.property("is_default", core.serialization.boolean().optional()),
+ limit: core.serialization.number().optional(),
+ offset: core.serialization.number().optional(),
+ providerType: core.serialization.property("provider_type", BillingProviderType.optional()),
+});
+
+export declare namespace ListCompanyBillingProfilesParams {
+ export interface Raw {
+ company_id?: string | null;
+ is_default?: boolean | null;
+ limit?: number | null;
+ offset?: number | null;
+ provider_type?: BillingProviderType.Raw | null;
+ }
+}
diff --git a/src/serialization/resources/billing/types/ListCompanyBillingProfilesResponse.ts b/src/serialization/resources/billing/types/ListCompanyBillingProfilesResponse.ts
new file mode 100644
index 00000000..eee33642
--- /dev/null
+++ b/src/serialization/resources/billing/types/ListCompanyBillingProfilesResponse.ts
@@ -0,0 +1,22 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CompanyBillingProfileResponseData } from "../../../types/CompanyBillingProfileResponseData";
+import { ListCompanyBillingProfilesParams } from "./ListCompanyBillingProfilesParams";
+
+export const ListCompanyBillingProfilesResponse: core.serialization.ObjectSchema<
+ serializers.ListCompanyBillingProfilesResponse.Raw,
+ Schematic.ListCompanyBillingProfilesResponse
+> = core.serialization.object({
+ data: core.serialization.list(CompanyBillingProfileResponseData),
+ params: ListCompanyBillingProfilesParams,
+});
+
+export declare namespace ListCompanyBillingProfilesResponse {
+ export interface Raw {
+ data: CompanyBillingProfileResponseData.Raw[];
+ params: ListCompanyBillingProfilesParams.Raw;
+ }
+}
diff --git a/src/serialization/resources/billing/types/UpdateCompanyBillingProfileResponse.ts b/src/serialization/resources/billing/types/UpdateCompanyBillingProfileResponse.ts
new file mode 100644
index 00000000..4f8f88fc
--- /dev/null
+++ b/src/serialization/resources/billing/types/UpdateCompanyBillingProfileResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CompanyBillingProfileResponseData } from "../../../types/CompanyBillingProfileResponseData";
+
+export const UpdateCompanyBillingProfileResponse: core.serialization.ObjectSchema<
+ serializers.UpdateCompanyBillingProfileResponse.Raw,
+ Schematic.UpdateCompanyBillingProfileResponse
+> = core.serialization.object({
+ data: CompanyBillingProfileResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace UpdateCompanyBillingProfileResponse {
+ export interface Raw {
+ data: CompanyBillingProfileResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/billing/types/index.ts b/src/serialization/resources/billing/types/index.ts
index 7e9332c9..5fa2d7b3 100644
--- a/src/serialization/resources/billing/types/index.ts
+++ b/src/serialization/resources/billing/types/index.ts
@@ -14,6 +14,8 @@ export * from "./ListBillingProductPricesParams";
export * from "./ListBillingProductPricesResponse";
export * from "./ListBillingProductsParams";
export * from "./ListBillingProductsResponse";
+export * from "./ListCompanyBillingProfilesParams";
+export * from "./ListCompanyBillingProfilesResponse";
export * from "./ListCouponsParams";
export * from "./ListCouponsResponse";
export * from "./ListCustomersWithSubscriptionsParams";
@@ -24,6 +26,7 @@ export * from "./ListMetersParams";
export * from "./ListMetersResponse";
export * from "./ListPaymentMethodsParams";
export * from "./ListPaymentMethodsResponse";
+export * from "./UpdateCompanyBillingProfileResponse";
export * from "./UpsertBillingCouponResponse";
export * from "./UpsertBillingCustomerResponse";
export * from "./UpsertBillingMeterResponse";
diff --git a/src/serialization/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts b/src/serialization/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts
new file mode 100644
index 00000000..1e39f973
--- /dev/null
+++ b/src/serialization/resources/credits/client/requests/CreateCreditSpendPolicyRequestBody.ts
@@ -0,0 +1,26 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../../api/index";
+import * as core from "../../../../../core";
+import type * as serializers from "../../../../index";
+
+export const CreateCreditSpendPolicyRequestBody: core.serialization.Schema<
+ serializers.CreateCreditSpendPolicyRequestBody.Raw,
+ Schematic.CreateCreditSpendPolicyRequestBody
+> = core.serialization.object({
+ billingCreditId: core.serialization.property("billing_credit_id", core.serialization.string()),
+ companyId: core.serialization.property("company_id", core.serialization.string().optional()),
+ label: core.serialization.string().optional(),
+ maxPerDraw: core.serialization.property("max_per_draw", core.serialization.number()),
+ userId: core.serialization.property("user_id", core.serialization.string().optional()),
+});
+
+export declare namespace CreateCreditSpendPolicyRequestBody {
+ export interface Raw {
+ billing_credit_id: string;
+ company_id?: string | null;
+ label?: string | null;
+ max_per_draw: number;
+ user_id?: string | null;
+ }
+}
diff --git a/src/serialization/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts b/src/serialization/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts
new file mode 100644
index 00000000..45d76ca8
--- /dev/null
+++ b/src/serialization/resources/credits/client/requests/UpdateCreditSpendPolicyRequestBody.ts
@@ -0,0 +1,20 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../../api/index";
+import * as core from "../../../../../core";
+import type * as serializers from "../../../../index";
+
+export const UpdateCreditSpendPolicyRequestBody: core.serialization.Schema<
+ serializers.UpdateCreditSpendPolicyRequestBody.Raw,
+ Schematic.UpdateCreditSpendPolicyRequestBody
+> = core.serialization.object({
+ label: core.serialization.string().optional(),
+ maxPerDraw: core.serialization.property("max_per_draw", core.serialization.number().optional()),
+});
+
+export declare namespace UpdateCreditSpendPolicyRequestBody {
+ export interface Raw {
+ label?: string | null;
+ max_per_draw?: number | null;
+ }
+}
diff --git a/src/serialization/resources/credits/client/requests/index.ts b/src/serialization/resources/credits/client/requests/index.ts
index 010270c7..d71ca06d 100644
--- a/src/serialization/resources/credits/client/requests/index.ts
+++ b/src/serialization/resources/credits/client/requests/index.ts
@@ -2,7 +2,9 @@ export { AcquireCreditLeaseRequestBody } from "./AcquireCreditLeaseRequestBody";
export { CreateBillingCreditRequestBody } from "./CreateBillingCreditRequestBody";
export { CreateCompanyCreditGrant } from "./CreateCompanyCreditGrant";
export { CreateCreditBundleRequestBody } from "./CreateCreditBundleRequestBody";
+export { CreateCreditSpendPolicyRequestBody } from "./CreateCreditSpendPolicyRequestBody";
export { ExtendCreditLeaseRequestBody } from "./ExtendCreditLeaseRequestBody";
export { UpdateBillingCreditRequestBody } from "./UpdateBillingCreditRequestBody";
export { UpdateCreditBundleDetailsRequestBody } from "./UpdateCreditBundleDetailsRequestBody";
+export { UpdateCreditSpendPolicyRequestBody } from "./UpdateCreditSpendPolicyRequestBody";
export { ZeroOutGrantRequestBody } from "./ZeroOutGrantRequestBody";
diff --git a/src/serialization/resources/credits/types/CountCreditSpendPoliciesParams.ts b/src/serialization/resources/credits/types/CountCreditSpendPoliciesParams.ts
new file mode 100644
index 00000000..0fee30f2
--- /dev/null
+++ b/src/serialization/resources/credits/types/CountCreditSpendPoliciesParams.ts
@@ -0,0 +1,31 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CreditSpendPolicyScope } from "../../../types/CreditSpendPolicyScope";
+
+export const CountCreditSpendPoliciesParams: core.serialization.ObjectSchema<
+ serializers.CountCreditSpendPoliciesParams.Raw,
+ Schematic.CountCreditSpendPoliciesParams
+> = core.serialization.object({
+ billingCreditId: core.serialization.property("billing_credit_id", core.serialization.string().optional()),
+ companyId: core.serialization.property("company_id", core.serialization.string().optional()),
+ limit: core.serialization.number().optional(),
+ offset: core.serialization.number().optional(),
+ scopeType: core.serialization.property("scope_type", CreditSpendPolicyScope.optional()),
+ userId: core.serialization.property("user_id", core.serialization.string().optional()),
+ userIds: core.serialization.property("user_ids", core.serialization.list(core.serialization.string()).optional()),
+});
+
+export declare namespace CountCreditSpendPoliciesParams {
+ export interface Raw {
+ billing_credit_id?: string | null;
+ company_id?: string | null;
+ limit?: number | null;
+ offset?: number | null;
+ scope_type?: CreditSpendPolicyScope.Raw | null;
+ user_id?: string | null;
+ user_ids?: string[] | null;
+ }
+}
diff --git a/src/serialization/resources/credits/types/CountCreditSpendPoliciesResponse.ts b/src/serialization/resources/credits/types/CountCreditSpendPoliciesResponse.ts
new file mode 100644
index 00000000..1c4acb21
--- /dev/null
+++ b/src/serialization/resources/credits/types/CountCreditSpendPoliciesResponse.ts
@@ -0,0 +1,22 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CountResponse } from "../../../types/CountResponse";
+import { CountCreditSpendPoliciesParams } from "./CountCreditSpendPoliciesParams";
+
+export const CountCreditSpendPoliciesResponse: core.serialization.ObjectSchema<
+ serializers.CountCreditSpendPoliciesResponse.Raw,
+ Schematic.CountCreditSpendPoliciesResponse
+> = core.serialization.object({
+ data: CountResponse,
+ params: CountCreditSpendPoliciesParams,
+});
+
+export declare namespace CountCreditSpendPoliciesResponse {
+ export interface Raw {
+ data: CountResponse.Raw;
+ params: CountCreditSpendPoliciesParams.Raw;
+ }
+}
diff --git a/src/serialization/resources/credits/types/CreateCreditSpendPolicyResponse.ts b/src/serialization/resources/credits/types/CreateCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..ceb25da9
--- /dev/null
+++ b/src/serialization/resources/credits/types/CreateCreditSpendPolicyResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CreditSpendPolicyResponseData } from "../../../types/CreditSpendPolicyResponseData";
+
+export const CreateCreditSpendPolicyResponse: core.serialization.ObjectSchema<
+ serializers.CreateCreditSpendPolicyResponse.Raw,
+ Schematic.CreateCreditSpendPolicyResponse
+> = core.serialization.object({
+ data: CreditSpendPolicyResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace CreateCreditSpendPolicyResponse {
+ export interface Raw {
+ data: CreditSpendPolicyResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/credits/types/DeleteCreditSpendPolicyResponse.ts b/src/serialization/resources/credits/types/DeleteCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..3da848fd
--- /dev/null
+++ b/src/serialization/resources/credits/types/DeleteCreditSpendPolicyResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { DeleteResponse } from "../../../types/DeleteResponse";
+
+export const DeleteCreditSpendPolicyResponse: core.serialization.ObjectSchema<
+ serializers.DeleteCreditSpendPolicyResponse.Raw,
+ Schematic.DeleteCreditSpendPolicyResponse
+> = core.serialization.object({
+ data: DeleteResponse,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace DeleteCreditSpendPolicyResponse {
+ export interface Raw {
+ data: DeleteResponse.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/credits/types/GetCreditSpendPolicyResponse.ts b/src/serialization/resources/credits/types/GetCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..ca226f6b
--- /dev/null
+++ b/src/serialization/resources/credits/types/GetCreditSpendPolicyResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CreditSpendPolicyResponseData } from "../../../types/CreditSpendPolicyResponseData";
+
+export const GetCreditSpendPolicyResponse: core.serialization.ObjectSchema<
+ serializers.GetCreditSpendPolicyResponse.Raw,
+ Schematic.GetCreditSpendPolicyResponse
+> = core.serialization.object({
+ data: CreditSpendPolicyResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace GetCreditSpendPolicyResponse {
+ export interface Raw {
+ data: CreditSpendPolicyResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/credits/types/ListCreditSpendPoliciesParams.ts b/src/serialization/resources/credits/types/ListCreditSpendPoliciesParams.ts
new file mode 100644
index 00000000..d4e3047d
--- /dev/null
+++ b/src/serialization/resources/credits/types/ListCreditSpendPoliciesParams.ts
@@ -0,0 +1,31 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CreditSpendPolicyScope } from "../../../types/CreditSpendPolicyScope";
+
+export const ListCreditSpendPoliciesParams: core.serialization.ObjectSchema<
+ serializers.ListCreditSpendPoliciesParams.Raw,
+ Schematic.ListCreditSpendPoliciesParams
+> = core.serialization.object({
+ billingCreditId: core.serialization.property("billing_credit_id", core.serialization.string().optional()),
+ companyId: core.serialization.property("company_id", core.serialization.string().optional()),
+ limit: core.serialization.number().optional(),
+ offset: core.serialization.number().optional(),
+ scopeType: core.serialization.property("scope_type", CreditSpendPolicyScope.optional()),
+ userId: core.serialization.property("user_id", core.serialization.string().optional()),
+ userIds: core.serialization.property("user_ids", core.serialization.list(core.serialization.string()).optional()),
+});
+
+export declare namespace ListCreditSpendPoliciesParams {
+ export interface Raw {
+ billing_credit_id?: string | null;
+ company_id?: string | null;
+ limit?: number | null;
+ offset?: number | null;
+ scope_type?: CreditSpendPolicyScope.Raw | null;
+ user_id?: string | null;
+ user_ids?: string[] | null;
+ }
+}
diff --git a/src/serialization/resources/credits/types/ListCreditSpendPoliciesResponse.ts b/src/serialization/resources/credits/types/ListCreditSpendPoliciesResponse.ts
new file mode 100644
index 00000000..9fe19495
--- /dev/null
+++ b/src/serialization/resources/credits/types/ListCreditSpendPoliciesResponse.ts
@@ -0,0 +1,22 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CreditSpendPolicyResponseData } from "../../../types/CreditSpendPolicyResponseData";
+import { ListCreditSpendPoliciesParams } from "./ListCreditSpendPoliciesParams";
+
+export const ListCreditSpendPoliciesResponse: core.serialization.ObjectSchema<
+ serializers.ListCreditSpendPoliciesResponse.Raw,
+ Schematic.ListCreditSpendPoliciesResponse
+> = core.serialization.object({
+ data: core.serialization.list(CreditSpendPolicyResponseData),
+ params: ListCreditSpendPoliciesParams,
+});
+
+export declare namespace ListCreditSpendPoliciesResponse {
+ export interface Raw {
+ data: CreditSpendPolicyResponseData.Raw[];
+ params: ListCreditSpendPoliciesParams.Raw;
+ }
+}
diff --git a/src/serialization/resources/credits/types/UpdateCreditSpendPolicyResponse.ts b/src/serialization/resources/credits/types/UpdateCreditSpendPolicyResponse.ts
new file mode 100644
index 00000000..b27c0631
--- /dev/null
+++ b/src/serialization/resources/credits/types/UpdateCreditSpendPolicyResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { CreditSpendPolicyResponseData } from "../../../types/CreditSpendPolicyResponseData";
+
+export const UpdateCreditSpendPolicyResponse: core.serialization.ObjectSchema<
+ serializers.UpdateCreditSpendPolicyResponse.Raw,
+ Schematic.UpdateCreditSpendPolicyResponse
+> = core.serialization.object({
+ data: CreditSpendPolicyResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace UpdateCreditSpendPolicyResponse {
+ export interface Raw {
+ data: CreditSpendPolicyResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/credits/types/index.ts b/src/serialization/resources/credits/types/index.ts
index 2e92a33a..f55d471c 100644
--- a/src/serialization/resources/credits/types/index.ts
+++ b/src/serialization/resources/credits/types/index.ts
@@ -11,14 +11,19 @@ export * from "./CountCreditBundlesParams";
export * from "./CountCreditBundlesResponse";
export * from "./CountCreditEventLedgerParams";
export * from "./CountCreditEventLedgerResponse";
+export * from "./CountCreditSpendPoliciesParams";
+export * from "./CountCreditSpendPoliciesResponse";
export * from "./CreateBillingCreditResponse";
export * from "./CreateBillingPlanCreditGrantResponse";
export * from "./CreateCreditBundleResponse";
+export * from "./CreateCreditSpendPolicyResponse";
export * from "./DeleteBillingPlanCreditGrantParams";
export * from "./DeleteBillingPlanCreditGrantResponse";
export * from "./DeleteCreditBundleResponse";
+export * from "./DeleteCreditSpendPolicyResponse";
export * from "./ExtendCreditLeaseResponse";
export * from "./GetCreditBundleResponse";
+export * from "./GetCreditSpendPolicyResponse";
export * from "./GetSingleBillingCreditResponse";
export * from "./GetSingleBillingPlanCreditGrantResponse";
export * from "./GrantBillingCreditsToCompanyResponse";
@@ -34,6 +39,8 @@ export * from "./ListCreditBundlesParams";
export * from "./ListCreditBundlesResponse";
export * from "./ListCreditEventLedgerParams";
export * from "./ListCreditEventLedgerResponse";
+export * from "./ListCreditSpendPoliciesParams";
+export * from "./ListCreditSpendPoliciesResponse";
export * from "./ListGrantsForCreditParams";
export * from "./ListGrantsForCreditResponse";
export * from "./ReleaseCreditLeaseResponse";
@@ -41,4 +48,5 @@ export * from "./SoftDeleteBillingCreditResponse";
export * from "./UpdateBillingCreditResponse";
export * from "./UpdateBillingPlanCreditGrantResponse";
export * from "./UpdateCreditBundleDetailsResponse";
+export * from "./UpdateCreditSpendPolicyResponse";
export * from "./ZeroOutGrantResponse";
diff --git a/src/serialization/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts b/src/serialization/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts
new file mode 100644
index 00000000..bf0ebc8c
--- /dev/null
+++ b/src/serialization/resources/events/client/requests/UpsertOtlpEnvironmentSettingsRequestBody.ts
@@ -0,0 +1,26 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../../api/index";
+import * as core from "../../../../../core";
+import type * as serializers from "../../../../index";
+
+export const UpsertOtlpEnvironmentSettingsRequestBody: core.serialization.Schema<
+ serializers.UpsertOtlpEnvironmentSettingsRequestBody.Raw,
+ Schematic.UpsertOtlpEnvironmentSettingsRequestBody
+> = core.serialization.object({
+ companyAttribute: core.serialization.property("company_attribute", core.serialization.string().optional()),
+ companyKey: core.serialization.property("company_key", core.serialization.string().optional()),
+ toolEventsEnabled: core.serialization.property("tool_events_enabled", core.serialization.boolean()),
+ userAttribute: core.serialization.property("user_attribute", core.serialization.string().optional()),
+ userKey: core.serialization.property("user_key", core.serialization.string().optional()),
+});
+
+export declare namespace UpsertOtlpEnvironmentSettingsRequestBody {
+ export interface Raw {
+ company_attribute?: string | null;
+ company_key?: string | null;
+ tool_events_enabled: boolean;
+ user_attribute?: string | null;
+ user_key?: string | null;
+ }
+}
diff --git a/src/serialization/resources/events/client/requests/index.ts b/src/serialization/resources/events/client/requests/index.ts
index b63138cc..e8553efa 100644
--- a/src/serialization/resources/events/client/requests/index.ts
+++ b/src/serialization/resources/events/client/requests/index.ts
@@ -1 +1,2 @@
export { CreateEventBatchRequestBody } from "./CreateEventBatchRequestBody";
+export { UpsertOtlpEnvironmentSettingsRequestBody } from "./UpsertOtlpEnvironmentSettingsRequestBody";
diff --git a/src/serialization/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts b/src/serialization/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts
new file mode 100644
index 00000000..355c3ce4
--- /dev/null
+++ b/src/serialization/resources/events/types/DeleteOtlpEnvironmentSettingsResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { DeleteResponse } from "../../../types/DeleteResponse";
+
+export const DeleteOtlpEnvironmentSettingsResponse: core.serialization.ObjectSchema<
+ serializers.DeleteOtlpEnvironmentSettingsResponse.Raw,
+ Schematic.DeleteOtlpEnvironmentSettingsResponse
+> = core.serialization.object({
+ data: DeleteResponse,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace DeleteOtlpEnvironmentSettingsResponse {
+ export interface Raw {
+ data: DeleteResponse.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts b/src/serialization/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts
new file mode 100644
index 00000000..a4463f35
--- /dev/null
+++ b/src/serialization/resources/events/types/GetOtlpEnvironmentSettingsResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { OtlpEnvironmentSettingsResponseData } from "../../../types/OtlpEnvironmentSettingsResponseData";
+
+export const GetOtlpEnvironmentSettingsResponse: core.serialization.ObjectSchema<
+ serializers.GetOtlpEnvironmentSettingsResponse.Raw,
+ Schematic.GetOtlpEnvironmentSettingsResponse
+> = core.serialization.object({
+ data: OtlpEnvironmentSettingsResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace GetOtlpEnvironmentSettingsResponse {
+ export interface Raw {
+ data: OtlpEnvironmentSettingsResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts b/src/serialization/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts
new file mode 100644
index 00000000..510d9573
--- /dev/null
+++ b/src/serialization/resources/events/types/UpsertOtlpEnvironmentSettingsResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { OtlpEnvironmentSettingsResponseData } from "../../../types/OtlpEnvironmentSettingsResponseData";
+
+export const UpsertOtlpEnvironmentSettingsResponse: core.serialization.ObjectSchema<
+ serializers.UpsertOtlpEnvironmentSettingsResponse.Raw,
+ Schematic.UpsertOtlpEnvironmentSettingsResponse
+> = core.serialization.object({
+ data: OtlpEnvironmentSettingsResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace UpsertOtlpEnvironmentSettingsResponse {
+ export interface Raw {
+ data: OtlpEnvironmentSettingsResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/events/types/index.ts b/src/serialization/resources/events/types/index.ts
index 421f16fb..3ed83d82 100644
--- a/src/serialization/resources/events/types/index.ts
+++ b/src/serialization/resources/events/types/index.ts
@@ -1,8 +1,11 @@
export * from "./CreateEventBatchResponse";
export * from "./CreateEventResponse";
+export * from "./DeleteOtlpEnvironmentSettingsResponse";
export * from "./GetEventResponse";
export * from "./GetEventSummariesParams";
export * from "./GetEventSummariesResponse";
+export * from "./GetOtlpEnvironmentSettingsResponse";
export * from "./GetSegmentIntegrationStatusResponse";
export * from "./ListEventsParams";
export * from "./ListEventsResponse";
+export * from "./UpsertOtlpEnvironmentSettingsResponse";
diff --git a/src/serialization/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts b/src/serialization/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts
new file mode 100644
index 00000000..98c493c2
--- /dev/null
+++ b/src/serialization/resources/integrationsapi/client/requests/ClaimStripeSandboxKeysRequestBody.ts
@@ -0,0 +1,18 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../../api/index";
+import * as core from "../../../../../core";
+import type * as serializers from "../../../../index";
+
+export const ClaimStripeSandboxKeysRequestBody: core.serialization.Schema<
+ serializers.ClaimStripeSandboxKeysRequestBody.Raw,
+ Schematic.ClaimStripeSandboxKeysRequestBody
+> = core.serialization.object({
+ token: core.serialization.string(),
+});
+
+export declare namespace ClaimStripeSandboxKeysRequestBody {
+ export interface Raw {
+ token: string;
+ }
+}
diff --git a/src/serialization/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts b/src/serialization/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts
new file mode 100644
index 00000000..563586c8
--- /dev/null
+++ b/src/serialization/resources/integrationsapi/client/requests/InstallStripeSandboxRequestBody.ts
@@ -0,0 +1,24 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../../api/index";
+import * as core from "../../../../../core";
+import type * as serializers from "../../../../index";
+
+export const InstallStripeSandboxRequestBody: core.serialization.Schema<
+ serializers.InstallStripeSandboxRequestBody.Raw,
+ Schematic.InstallStripeSandboxRequestBody
+> = core.serialization.object({
+ country: core.serialization.string().optional(),
+ email: core.serialization.string(),
+ name: core.serialization.string().optional(),
+ seedSampleData: core.serialization.property("seed_sample_data", core.serialization.boolean().optional()),
+});
+
+export declare namespace InstallStripeSandboxRequestBody {
+ export interface Raw {
+ country?: string | null;
+ email: string;
+ name?: string | null;
+ seed_sample_data?: boolean | null;
+ }
+}
diff --git a/src/serialization/resources/integrationsapi/client/requests/index.ts b/src/serialization/resources/integrationsapi/client/requests/index.ts
index 3c15e6ae..aff599c3 100644
--- a/src/serialization/resources/integrationsapi/client/requests/index.ts
+++ b/src/serialization/resources/integrationsapi/client/requests/index.ts
@@ -1 +1,3 @@
+export { ClaimStripeSandboxKeysRequestBody } from "./ClaimStripeSandboxKeysRequestBody";
+export { InstallStripeSandboxRequestBody } from "./InstallStripeSandboxRequestBody";
export { StartDataImportRequestBody } from "./StartDataImportRequestBody";
diff --git a/src/serialization/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts b/src/serialization/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts
new file mode 100644
index 00000000..ced992b4
--- /dev/null
+++ b/src/serialization/resources/integrationsapi/types/ClaimStripeSandboxKeysResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { ClaimedStripeSandboxKeysResponseData } from "../../../types/ClaimedStripeSandboxKeysResponseData";
+
+export const ClaimStripeSandboxKeysResponse: core.serialization.ObjectSchema<
+ serializers.ClaimStripeSandboxKeysResponse.Raw,
+ Schematic.ClaimStripeSandboxKeysResponse
+> = core.serialization.object({
+ data: ClaimedStripeSandboxKeysResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace ClaimStripeSandboxKeysResponse {
+ export interface Raw {
+ data: ClaimedStripeSandboxKeysResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts b/src/serialization/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts
new file mode 100644
index 00000000..57ffffc7
--- /dev/null
+++ b/src/serialization/resources/integrationsapi/types/GetStripeSandboxClaimLinkResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { StripeSandboxClaimLink } from "../../../types/StripeSandboxClaimLink";
+
+export const GetStripeSandboxClaimLinkResponse: core.serialization.ObjectSchema<
+ serializers.GetStripeSandboxClaimLinkResponse.Raw,
+ Schematic.GetStripeSandboxClaimLinkResponse
+> = core.serialization.object({
+ data: StripeSandboxClaimLink,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace GetStripeSandboxClaimLinkResponse {
+ export interface Raw {
+ data: StripeSandboxClaimLink.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts b/src/serialization/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts
new file mode 100644
index 00000000..ef0c212f
--- /dev/null
+++ b/src/serialization/resources/integrationsapi/types/GetStripeSandboxKeysResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { ClaimedStripeSandboxKeysResponseData } from "../../../types/ClaimedStripeSandboxKeysResponseData";
+
+export const GetStripeSandboxKeysResponse: core.serialization.ObjectSchema<
+ serializers.GetStripeSandboxKeysResponse.Raw,
+ Schematic.GetStripeSandboxKeysResponse
+> = core.serialization.object({
+ data: ClaimedStripeSandboxKeysResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace GetStripeSandboxKeysResponse {
+ export interface Raw {
+ data: ClaimedStripeSandboxKeysResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts b/src/serialization/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts
new file mode 100644
index 00000000..a9b5f7d4
--- /dev/null
+++ b/src/serialization/resources/integrationsapi/types/InstallStripeClaimableSandboxResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { StripeSandboxInstallResponseData } from "../../../types/StripeSandboxInstallResponseData";
+
+export const InstallStripeClaimableSandboxResponse: core.serialization.ObjectSchema<
+ serializers.InstallStripeClaimableSandboxResponse.Raw,
+ Schematic.InstallStripeClaimableSandboxResponse
+> = core.serialization.object({
+ data: StripeSandboxInstallResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace InstallStripeClaimableSandboxResponse {
+ export interface Raw {
+ data: StripeSandboxInstallResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts b/src/serialization/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts
new file mode 100644
index 00000000..dacacd18
--- /dev/null
+++ b/src/serialization/resources/integrationsapi/types/ListStripeSandboxCountriesResponse.ts
@@ -0,0 +1,21 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../../../api/index";
+import * as core from "../../../../core";
+import type * as serializers from "../../../index";
+import { StripeSandboxCountriesResponseData } from "../../../types/StripeSandboxCountriesResponseData";
+
+export const ListStripeSandboxCountriesResponse: core.serialization.ObjectSchema<
+ serializers.ListStripeSandboxCountriesResponse.Raw,
+ Schematic.ListStripeSandboxCountriesResponse
+> = core.serialization.object({
+ data: StripeSandboxCountriesResponseData,
+ params: core.serialization.record(core.serialization.string(), core.serialization.unknown()),
+});
+
+export declare namespace ListStripeSandboxCountriesResponse {
+ export interface Raw {
+ data: StripeSandboxCountriesResponseData.Raw;
+ params: Record;
+ }
+}
diff --git a/src/serialization/resources/integrationsapi/types/index.ts b/src/serialization/resources/integrationsapi/types/index.ts
index 3c4b71a4..3835c1ba 100644
--- a/src/serialization/resources/integrationsapi/types/index.ts
+++ b/src/serialization/resources/integrationsapi/types/index.ts
@@ -1,9 +1,14 @@
export * from "./AssumeStripeInstalledResponse";
+export * from "./ClaimStripeSandboxKeysResponse";
export * from "./GetIntegrationWebhookUrlResponse";
+export * from "./GetStripeSandboxClaimLinkResponse";
+export * from "./GetStripeSandboxKeysResponse";
export * from "./InstallIntegrationResponse";
+export * from "./InstallStripeClaimableSandboxResponse";
export * from "./InstallStripeResponse";
export * from "./ListIntegrationsParams";
export * from "./ListIntegrationsResponse";
+export * from "./ListStripeSandboxCountriesResponse";
export * from "./LoadSampleDataSetResponse";
export * from "./RunIntegrationResponse";
export * from "./StartDataImportResponse";
diff --git a/src/serialization/types/ClaimedStripeSandboxKeysResponseData.ts b/src/serialization/types/ClaimedStripeSandboxKeysResponseData.ts
new file mode 100644
index 00000000..83eebeff
--- /dev/null
+++ b/src/serialization/types/ClaimedStripeSandboxKeysResponseData.ts
@@ -0,0 +1,22 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+
+export const ClaimedStripeSandboxKeysResponseData: core.serialization.ObjectSchema<
+ serializers.ClaimedStripeSandboxKeysResponseData.Raw,
+ Schematic.ClaimedStripeSandboxKeysResponseData
+> = core.serialization.object({
+ publishable: core.serialization.string(),
+ sandboxId: core.serialization.property("sandbox_id", core.serialization.string()),
+ secret: core.serialization.string(),
+});
+
+export declare namespace ClaimedStripeSandboxKeysResponseData {
+ export interface Raw {
+ publishable: string;
+ sandbox_id: string;
+ secret: string;
+ }
+}
diff --git a/src/serialization/types/CompanyBillingProfileResponseData.ts b/src/serialization/types/CompanyBillingProfileResponseData.ts
new file mode 100644
index 00000000..0a2e15f4
--- /dev/null
+++ b/src/serialization/types/CompanyBillingProfileResponseData.ts
@@ -0,0 +1,47 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+import { BillingCollectionMethod } from "./BillingCollectionMethod";
+import { BillingProviderType } from "./BillingProviderType";
+import { ProrationBehavior } from "./ProrationBehavior";
+
+export const CompanyBillingProfileResponseData: core.serialization.ObjectSchema<
+ serializers.CompanyBillingProfileResponseData.Raw,
+ Schematic.CompanyBillingProfileResponseData
+> = core.serialization.object({
+ accountId: core.serialization.property("account_id", core.serialization.string()),
+ billingCustomerId: core.serialization.property("billing_customer_id", core.serialization.string().optional()),
+ collectionMethod: core.serialization.property("collection_method", BillingCollectionMethod),
+ companyId: core.serialization.property("company_id", core.serialization.string()),
+ createdAt: core.serialization.property("created_at", core.serialization.date()),
+ daysUntilDue: core.serialization.property("days_until_due", core.serialization.number().optional()),
+ environmentId: core.serialization.property("environment_id", core.serialization.string()),
+ id: core.serialization.string(),
+ isDefault: core.serialization.property("is_default", core.serialization.boolean()),
+ name: core.serialization.string().optional(),
+ paymentMethodId: core.serialization.property("payment_method_id", core.serialization.string().optional()),
+ prorationBehavior: core.serialization.property("proration_behavior", ProrationBehavior.optional()),
+ providerType: core.serialization.property("provider_type", BillingProviderType),
+ updatedAt: core.serialization.property("updated_at", core.serialization.date()),
+});
+
+export declare namespace CompanyBillingProfileResponseData {
+ export interface Raw {
+ account_id: string;
+ billing_customer_id?: string | null;
+ collection_method: BillingCollectionMethod.Raw;
+ company_id: string;
+ created_at: string;
+ days_until_due?: number | null;
+ environment_id: string;
+ id: string;
+ is_default: boolean;
+ name?: string | null;
+ payment_method_id?: string | null;
+ proration_behavior?: ProrationBehavior.Raw | null;
+ provider_type: BillingProviderType.Raw;
+ updated_at: string;
+ }
+}
diff --git a/src/serialization/types/CompanyDetailResponseData.ts b/src/serialization/types/CompanyDetailResponseData.ts
index 5483195e..ab368c46 100644
--- a/src/serialization/types/CompanyDetailResponseData.ts
+++ b/src/serialization/types/CompanyDetailResponseData.ts
@@ -4,6 +4,7 @@ import type * as Schematic from "../../api/index";
import * as core from "../../core";
import type * as serializers from "../index";
import { BillingSubscriptionView } from "./BillingSubscriptionView";
+import { CompanyBillingProfileResponseData } from "./CompanyBillingProfileResponseData";
import { CompanyEventPeriodMetricsResponseData } from "./CompanyEventPeriodMetricsResponseData";
import { CompanyPlanWithBillingSubView } from "./CompanyPlanWithBillingSubView";
import { CustomPlanBillingResponseData } from "./CustomPlanBillingResponseData";
@@ -25,6 +26,11 @@ export const CompanyDetailResponseData: core.serialization.ObjectSchema<
"billing_credit_balances",
core.serialization.record(core.serialization.string(), core.serialization.number()).optional(),
),
+ billingProfile: core.serialization.property("billing_profile", CompanyBillingProfileResponseData.optional()),
+ billingProfiles: core.serialization.property(
+ "billing_profiles",
+ core.serialization.list(CompanyBillingProfileResponseData).optional(),
+ ),
billingSubscription: core.serialization.property("billing_subscription", BillingSubscriptionView.optional()),
billingSubscriptions: core.serialization.property(
"billing_subscriptions",
@@ -60,6 +66,8 @@ export declare namespace CompanyDetailResponseData {
export interface Raw {
add_ons: CompanyPlanWithBillingSubView.Raw[];
billing_credit_balances?: Record | null;
+ billing_profile?: CompanyBillingProfileResponseData.Raw | null;
+ billing_profiles?: CompanyBillingProfileResponseData.Raw[] | null;
billing_subscription?: BillingSubscriptionView.Raw | null;
billing_subscriptions: BillingSubscriptionView.Raw[];
created_at: string;
diff --git a/src/serialization/types/CompanyOverrideResponseData.ts b/src/serialization/types/CompanyOverrideResponseData.ts
index bdc4c395..95856238 100644
--- a/src/serialization/types/CompanyOverrideResponseData.ts
+++ b/src/serialization/types/CompanyOverrideResponseData.ts
@@ -3,6 +3,7 @@
import type * as Schematic from "../../api/index";
import * as core from "../../core";
import type * as serializers from "../index";
+import { BillingCreditResponseData } from "./BillingCreditResponseData";
import { CompanyDetailResponseData } from "./CompanyDetailResponseData";
import { CompanyOverrideNoteResponseData } from "./CompanyOverrideNoteResponseData";
import { EntitlementValueType } from "./EntitlementValueType";
@@ -31,6 +32,8 @@ export const CompanyOverrideResponseData: core.serialization.ObjectSchema<
ruleIdUsageExceeded: core.serialization.property("rule_id_usage_exceeded", core.serialization.string().optional()),
updatedAt: core.serialization.property("updated_at", core.serialization.date()),
valueBool: core.serialization.property("value_bool", core.serialization.boolean().optional()),
+ valueCredit: core.serialization.property("value_credit", BillingCreditResponseData.optional()),
+ valueCreditId: core.serialization.property("value_credit_id", core.serialization.string().optional()),
valueNumeric: core.serialization.property("value_numeric", core.serialization.number().optional()),
valueTrait: core.serialization.property("value_trait", EntityTraitDefinitionResponseData.optional()),
valueTraitId: core.serialization.property("value_trait_id", core.serialization.string().optional()),
@@ -55,6 +58,8 @@ export declare namespace CompanyOverrideResponseData {
rule_id_usage_exceeded?: string | null;
updated_at: string;
value_bool?: boolean | null;
+ value_credit?: BillingCreditResponseData.Raw | null;
+ value_credit_id?: string | null;
value_numeric?: number | null;
value_trait?: EntityTraitDefinitionResponseData.Raw | null;
value_trait_id?: string | null;
diff --git a/src/serialization/types/CreditSpendPolicyResponseData.ts b/src/serialization/types/CreditSpendPolicyResponseData.ts
new file mode 100644
index 00000000..9f1bc294
--- /dev/null
+++ b/src/serialization/types/CreditSpendPolicyResponseData.ts
@@ -0,0 +1,35 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+import { CreditSpendPolicyScope } from "./CreditSpendPolicyScope";
+
+export const CreditSpendPolicyResponseData: core.serialization.ObjectSchema<
+ serializers.CreditSpendPolicyResponseData.Raw,
+ Schematic.CreditSpendPolicyResponseData
+> = core.serialization.object({
+ billingCreditId: core.serialization.property("billing_credit_id", core.serialization.string()),
+ companyId: core.serialization.property("company_id", core.serialization.string().optional()),
+ createdAt: core.serialization.property("created_at", core.serialization.date()),
+ id: core.serialization.string(),
+ label: core.serialization.string().optional(),
+ maxPerDraw: core.serialization.property("max_per_draw", core.serialization.number().optional()),
+ scopeType: core.serialization.property("scope_type", CreditSpendPolicyScope),
+ updatedAt: core.serialization.property("updated_at", core.serialization.date()),
+ userId: core.serialization.property("user_id", core.serialization.string().optional()),
+});
+
+export declare namespace CreditSpendPolicyResponseData {
+ export interface Raw {
+ billing_credit_id: string;
+ company_id?: string | null;
+ created_at: string;
+ id: string;
+ label?: string | null;
+ max_per_draw?: number | null;
+ scope_type: CreditSpendPolicyScope.Raw;
+ updated_at: string;
+ user_id?: string | null;
+ }
+}
diff --git a/src/serialization/types/CreditSpendPolicyScope.ts b/src/serialization/types/CreditSpendPolicyScope.ts
new file mode 100644
index 00000000..4be0f45a
--- /dev/null
+++ b/src/serialization/types/CreditSpendPolicyScope.ts
@@ -0,0 +1,14 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+
+export const CreditSpendPolicyScope: core.serialization.Schema<
+ serializers.CreditSpendPolicyScope.Raw,
+ Schematic.CreditSpendPolicyScope
+> = core.serialization.enum_(["company", "user", "group"]);
+
+export declare namespace CreditSpendPolicyScope {
+ export type Raw = "company" | "user" | "group";
+}
diff --git a/src/serialization/types/EventBodyInference.ts b/src/serialization/types/EventBodyInference.ts
index 898174a7..5ec6b863 100644
--- a/src/serialization/types/EventBodyInference.ts
+++ b/src/serialization/types/EventBodyInference.ts
@@ -8,6 +8,10 @@ export const EventBodyInference: core.serialization.ObjectSchema<
serializers.EventBodyInference.Raw,
Schematic.EventBodyInference
> = core.serialization.object({
+ cacheCreationInputTokens: core.serialization.property(
+ "cache_creation_input_tokens",
+ core.serialization.number().optional(),
+ ),
cachedInputTokens: core.serialization.property("cached_input_tokens", core.serialization.number().optional()),
company: core.serialization.record(core.serialization.string(), core.serialization.string()),
cost: core.serialization.string().optional(),
@@ -26,6 +30,7 @@ export const EventBodyInference: core.serialization.ObjectSchema<
export declare namespace EventBodyInference {
export interface Raw {
+ cache_creation_input_tokens?: number | null;
cached_input_tokens?: number | null;
company: Record;
cost?: string | null;
diff --git a/src/serialization/types/GetOnboardingStateResp.ts b/src/serialization/types/GetOnboardingStateResp.ts
index cae18d26..9c69b39d 100644
--- a/src/serialization/types/GetOnboardingStateResp.ts
+++ b/src/serialization/types/GetOnboardingStateResp.ts
@@ -15,6 +15,7 @@ export const GetOnboardingStateResp: core.serialization.ObjectSchema<
Schematic.GetOnboardingStateResp
> = core.serialization.object({
agentConnectedAt: core.serialization.property("agent_connected_at", core.serialization.date().optional()),
+ country: core.serialization.string().optional(),
dismissedAt: core.serialization.property("dismissed_at", core.serialization.date().optional()),
environmentId: core.serialization.property("environment_id", core.serialization.string().optional()),
milestones: core.serialization.list(OnboardingMilestoneView),
@@ -30,6 +31,7 @@ export const GetOnboardingStateResp: core.serialization.ObjectSchema<
export declare namespace GetOnboardingStateResp {
export interface Raw {
agent_connected_at?: string | null;
+ country?: string | null;
dismissed_at?: string | null;
environment_id?: string | null;
milestones: OnboardingMilestoneView.Raw[];
diff --git a/src/serialization/types/OtlpEnvironmentSettingsResponseData.ts b/src/serialization/types/OtlpEnvironmentSettingsResponseData.ts
new file mode 100644
index 00000000..68645de9
--- /dev/null
+++ b/src/serialization/types/OtlpEnvironmentSettingsResponseData.ts
@@ -0,0 +1,32 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+
+export const OtlpEnvironmentSettingsResponseData: core.serialization.ObjectSchema<
+ serializers.OtlpEnvironmentSettingsResponseData.Raw,
+ Schematic.OtlpEnvironmentSettingsResponseData
+> = core.serialization.object({
+ companyAttribute: core.serialization.property("company_attribute", core.serialization.string().optional()),
+ companyKey: core.serialization.property("company_key", core.serialization.string().optional()),
+ createdAt: core.serialization.property("created_at", core.serialization.date()),
+ environmentId: core.serialization.property("environment_id", core.serialization.string()),
+ toolEventsEnabled: core.serialization.property("tool_events_enabled", core.serialization.boolean()),
+ updatedAt: core.serialization.property("updated_at", core.serialization.date()),
+ userAttribute: core.serialization.property("user_attribute", core.serialization.string().optional()),
+ userKey: core.serialization.property("user_key", core.serialization.string().optional()),
+});
+
+export declare namespace OtlpEnvironmentSettingsResponseData {
+ export interface Raw {
+ company_attribute?: string | null;
+ company_key?: string | null;
+ created_at: string;
+ environment_id: string;
+ tool_events_enabled: boolean;
+ updated_at: string;
+ user_attribute?: string | null;
+ user_key?: string | null;
+ }
+}
diff --git a/src/serialization/types/RuleConditionDetailResponseData.ts b/src/serialization/types/RuleConditionDetailResponseData.ts
index 7424c50a..56d878c0 100644
--- a/src/serialization/types/RuleConditionDetailResponseData.ts
+++ b/src/serialization/types/RuleConditionDetailResponseData.ts
@@ -10,6 +10,7 @@ import { EntityType } from "./EntityType";
import { MetricPeriod } from "./MetricPeriod";
import { MetricPeriodMonthReset } from "./MetricPeriodMonthReset";
import { PreviewObjectResponseData } from "./PreviewObjectResponseData";
+import { RuleConditionPlanVersionResponseData } from "./RuleConditionPlanVersionResponseData";
export const RuleConditionDetailResponseData: core.serialization.ObjectSchema<
serializers.RuleConditionDetailResponseData.Raw,
@@ -28,6 +29,10 @@ export const RuleConditionDetailResponseData: core.serialization.ObjectSchema<
metricPeriodMonthReset: core.serialization.property("metric_period_month_reset", MetricPeriodMonthReset.optional()),
metricValue: core.serialization.property("metric_value", core.serialization.number().optional()),
operator: ComparableOperator,
+ planVersions: core.serialization.property(
+ "plan_versions",
+ core.serialization.list(RuleConditionPlanVersionResponseData).optional(),
+ ),
resourceIds: core.serialization.property("resource_ids", core.serialization.list(core.serialization.string())),
resources: core.serialization.list(PreviewObjectResponseData),
ruleId: core.serialization.property("rule_id", core.serialization.string()),
@@ -53,6 +58,7 @@ export declare namespace RuleConditionDetailResponseData {
metric_period_month_reset?: MetricPeriodMonthReset.Raw | null;
metric_value?: number | null;
operator: ComparableOperator.Raw;
+ plan_versions?: RuleConditionPlanVersionResponseData.Raw[] | null;
resource_ids: string[];
resources: PreviewObjectResponseData.Raw[];
rule_id: string;
diff --git a/src/serialization/types/RuleConditionPlanVersionResponseData.ts b/src/serialization/types/RuleConditionPlanVersionResponseData.ts
new file mode 100644
index 00000000..5bf073f6
--- /dev/null
+++ b/src/serialization/types/RuleConditionPlanVersionResponseData.ts
@@ -0,0 +1,25 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+import { PlanVersionStatus } from "./PlanVersionStatus";
+
+export const RuleConditionPlanVersionResponseData: core.serialization.ObjectSchema<
+ serializers.RuleConditionPlanVersionResponseData.Raw,
+ Schematic.RuleConditionPlanVersionResponseData
+> = core.serialization.object({
+ id: core.serialization.string(),
+ name: core.serialization.string(),
+ status: PlanVersionStatus,
+ version: core.serialization.number(),
+});
+
+export declare namespace RuleConditionPlanVersionResponseData {
+ export interface Raw {
+ id: string;
+ name: string;
+ status: PlanVersionStatus.Raw;
+ version: number;
+ }
+}
diff --git a/src/serialization/types/StripeIntegrationConfig.ts b/src/serialization/types/StripeIntegrationConfig.ts
index 52ae8ce7..ebe29be8 100644
--- a/src/serialization/types/StripeIntegrationConfig.ts
+++ b/src/serialization/types/StripeIntegrationConfig.ts
@@ -10,6 +10,15 @@ export const StripeIntegrationConfig: core.serialization.ObjectSchema<
> = core.serialization.object({
accountId: core.serialization.property("account_id", core.serialization.string().optional()),
accountName: core.serialization.property("account_name", core.serialization.string().optional()),
+ claimableSandboxExpiresAt: core.serialization.property(
+ "claimable_sandbox_expires_at",
+ core.serialization.date().optional(),
+ ),
+ claimableSandboxId: core.serialization.property("claimable_sandbox_id", core.serialization.string().optional()),
+ claimableSandboxStatus: core.serialization.property(
+ "claimable_sandbox_status",
+ core.serialization.string().optional(),
+ ),
companyUpdateOnly: core.serialization.property("company_update_only", core.serialization.boolean().optional()),
isSandbox: core.serialization.property("is_sandbox", core.serialization.boolean()),
liveMode: core.serialization.property("live_mode", core.serialization.boolean()),
@@ -21,6 +30,9 @@ export declare namespace StripeIntegrationConfig {
export interface Raw {
account_id?: string | null;
account_name?: string | null;
+ claimable_sandbox_expires_at?: string | null;
+ claimable_sandbox_id?: string | null;
+ claimable_sandbox_status?: string | null;
company_update_only?: boolean | null;
is_sandbox: boolean;
live_mode: boolean;
diff --git a/src/serialization/types/StripeSandboxClaimLink.ts b/src/serialization/types/StripeSandboxClaimLink.ts
new file mode 100644
index 00000000..13e25639
--- /dev/null
+++ b/src/serialization/types/StripeSandboxClaimLink.ts
@@ -0,0 +1,24 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+
+export const StripeSandboxClaimLink: core.serialization.ObjectSchema<
+ serializers.StripeSandboxClaimLink.Raw,
+ Schematic.StripeSandboxClaimLink
+> = core.serialization.object({
+ claimUrl: core.serialization.property("claim_url", core.serialization.string()),
+ expiresAt: core.serialization.property("expires_at", core.serialization.date().optional()),
+ sandboxId: core.serialization.property("sandbox_id", core.serialization.string()),
+ status: core.serialization.string(),
+});
+
+export declare namespace StripeSandboxClaimLink {
+ export interface Raw {
+ claim_url: string;
+ expires_at?: string | null;
+ sandbox_id: string;
+ status: string;
+ }
+}
diff --git a/src/serialization/types/StripeSandboxCountriesResponseData.ts b/src/serialization/types/StripeSandboxCountriesResponseData.ts
new file mode 100644
index 00000000..7b92e46f
--- /dev/null
+++ b/src/serialization/types/StripeSandboxCountriesResponseData.ts
@@ -0,0 +1,18 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+
+export const StripeSandboxCountriesResponseData: core.serialization.ObjectSchema<
+ serializers.StripeSandboxCountriesResponseData.Raw,
+ Schematic.StripeSandboxCountriesResponseData
+> = core.serialization.object({
+ countries: core.serialization.list(core.serialization.string()),
+});
+
+export declare namespace StripeSandboxCountriesResponseData {
+ export interface Raw {
+ countries: string[];
+ }
+}
diff --git a/src/serialization/types/StripeSandboxInstallResponseData.ts b/src/serialization/types/StripeSandboxInstallResponseData.ts
new file mode 100644
index 00000000..e8cd2a99
--- /dev/null
+++ b/src/serialization/types/StripeSandboxInstallResponseData.ts
@@ -0,0 +1,32 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+import { IntegrationInstallResponseData } from "./IntegrationInstallResponseData";
+import { StripeSandboxKeysResponseData } from "./StripeSandboxKeysResponseData";
+
+export const StripeSandboxInstallResponseData: core.serialization.ObjectSchema<
+ serializers.StripeSandboxInstallResponseData.Raw,
+ Schematic.StripeSandboxInstallResponseData
+> = core.serialization.object({
+ apiKeys: core.serialization.property("api_keys", StripeSandboxKeysResponseData.optional()),
+ claimUrl: core.serialization.property("claim_url", core.serialization.string()),
+ claimUrlExpiresAt: core.serialization.property("claim_url_expires_at", core.serialization.date().optional()),
+ expiresAt: core.serialization.property("expires_at", core.serialization.date().optional()),
+ install: IntegrationInstallResponseData,
+ sandboxId: core.serialization.property("sandbox_id", core.serialization.string()),
+ stripeAccountId: core.serialization.property("stripe_account_id", core.serialization.string()),
+});
+
+export declare namespace StripeSandboxInstallResponseData {
+ export interface Raw {
+ api_keys?: StripeSandboxKeysResponseData.Raw | null;
+ claim_url: string;
+ claim_url_expires_at?: string | null;
+ expires_at?: string | null;
+ install: IntegrationInstallResponseData.Raw;
+ sandbox_id: string;
+ stripe_account_id: string;
+ }
+}
diff --git a/src/serialization/types/StripeSandboxKeysResponseData.ts b/src/serialization/types/StripeSandboxKeysResponseData.ts
new file mode 100644
index 00000000..9bfcd7f7
--- /dev/null
+++ b/src/serialization/types/StripeSandboxKeysResponseData.ts
@@ -0,0 +1,22 @@
+// This file was auto-generated by Fern from our API Definition.
+
+import type * as Schematic from "../../api/index";
+import * as core from "../../core";
+import type * as serializers from "../index";
+
+export const StripeSandboxKeysResponseData: core.serialization.ObjectSchema<
+ serializers.StripeSandboxKeysResponseData.Raw,
+ Schematic.StripeSandboxKeysResponseData
+> = core.serialization.object({
+ mcp: core.serialization.string(),
+ publishable: core.serialization.string(),
+ secret: core.serialization.string(),
+});
+
+export declare namespace StripeSandboxKeysResponseData {
+ export interface Raw {
+ mcp: string;
+ publishable: string;
+ secret: string;
+ }
+}
diff --git a/src/serialization/types/index.ts b/src/serialization/types/index.ts
index 6e7d3cb9..f54b90e5 100644
--- a/src/serialization/types/index.ts
+++ b/src/serialization/types/index.ts
@@ -89,6 +89,7 @@ export * from "./CheckoutFieldValue";
export * from "./CheckoutFieldWithValue";
export * from "./CheckoutSettingsResponseData";
export * from "./CheckoutSubscription";
+export * from "./ClaimedStripeSandboxKeysResponseData";
export * from "./ClerkIntegrationConfig";
export * from "./CompanyBillingAddressView";
export * from "./CompanyBillingCheckoutSettings";
@@ -96,6 +97,7 @@ export * from "./CompanyBillingDetailsResponseData";
export * from "./CompanyBillingDetailsView";
export * from "./CompanyBillingEntityResponseData";
export * from "./CompanyBillingEntitySubscriptionResponseData";
+export * from "./CompanyBillingProfileResponseData";
export * from "./CompanyCreditBalance";
export * from "./CompanyCreditBalanceResponseData";
export * from "./CompanyDetailResponseData";
@@ -165,6 +167,8 @@ export * from "./CreditGrantDetail";
export * from "./CreditGrantExpiryRequestBody";
export * from "./CreditGrantSortOrder";
export * from "./CreditLeaseResponseData";
+export * from "./CreditSpendPolicyResponseData";
+export * from "./CreditSpendPolicyScope";
export * from "./CreditsAutoTopupCompanySummary";
export * from "./CreditsAutoTopupCreditSummary";
export * from "./CreditsAutoTopupHardFailure";
@@ -293,6 +297,7 @@ export * from "./OnboardingStripeImport";
export * from "./OnboardingTrack";
export * from "./OrbIntegrationConfig";
export * from "./OrderedPlansInGroup";
+export * from "./OtlpEnvironmentSettingsResponseData";
export * from "./PaymentMethodRequestBody";
export * from "./PaymentMethodResponseData";
export * from "./PendingMigrationResponseData";
@@ -357,6 +362,7 @@ export * from "./Rule";
export * from "./RuleConditionDetailResponseData";
export * from "./RuleConditionGroupDetailResponseData";
export * from "./RuleConditionGroupResponseData";
+export * from "./RuleConditionPlanVersionResponseData";
export * from "./RuleConditionResponseData";
export * from "./RuleDetailResponseData";
export * from "./RuleResponseData";
@@ -394,6 +400,10 @@ export * from "./SkippedEntitlementResponseData";
export * from "./SortDirection";
export * from "./StripeEmbedInfo";
export * from "./StripeIntegrationConfig";
+export * from "./StripeSandboxClaimLink";
+export * from "./StripeSandboxCountriesResponseData";
+export * from "./StripeSandboxInstallResponseData";
+export * from "./StripeSandboxKeysResponseData";
export * from "./SubscriptionStatus";
export * from "./SubscriptionTraitUpdate";
export * from "./SubscriptionType";
diff --git a/tests/conformance/runner.test.ts b/tests/conformance/runner.test.ts
deleted file mode 100644
index 3a29a886..00000000
--- a/tests/conformance/runner.test.ts
+++ /dev/null
@@ -1,720 +0,0 @@
-/**
- * Executes the language-agnostic conformance vectors in `conformance/vectors/`
- * against the reference implementation, on both store backends. The vector
- * schema and the semantics they pin are documented in `conformance/SPEC.md`;
- * ports of the lease/reservation system reimplement this runner (it is the
- * only language-specific piece) and must pass the same vectors.
- */
-import * as fs from "fs";
-import * as path from "path";
-
-import type * as api from "../../src/api";
-import type { CreditsClient } from "../../src/api/resources/credits/client/Client";
-import { type CreditCheckDeps, checkWithLease } from "../../src/credits/check";
-import { CreditLeaseManager } from "../../src/credits/lease-manager";
-import { type ILeaseStore, LeaseStore } from "../../src/credits/lease-store";
-import { RedisLeaseStore } from "../../src/credits/redis-lease-store";
-import { RedisReservationStore } from "../../src/credits/redis-reservation-store";
-import { type IReservationStore, ReservationStore } from "../../src/credits/reservation-store";
-import { consumeReservationAndBuildEvent } from "../../src/credits/track";
-import type { CheckOptions, CheckResult, OnAcquireFailure, Reservation } from "../../src/credits/types";
-import type { DataStreamClient } from "../../src/datastream";
-import type { Logger } from "../../src/logger";
-import { makeFakeRedis } from "../unit/credits/fake-redis";
-
-// ---------------------------------------------------------------------------
-// Vector schema (see conformance/SPEC.md — keys are snake_case JSON).
-
-interface LeaseSpec {
- lease_id: string;
- company_id: string;
- credit_type_id: string;
- granted_amount: number;
- expires_at_ms: number;
-}
-
-interface ConfigSpec {
- lease_duration_ms?: number;
- reservation_ttl_ms?: number;
- lease_size?: number;
- low_water_mark?: number;
-}
-
-interface ServerLeaseSpec {
- lease_id?: string;
- granted_amount?: number;
- granted_total?: number;
- expires_at_ms: number;
-}
-
-type ServerScript = { lease: ServerLeaseSpec; error?: undefined } | { error: string; lease?: undefined };
-
-interface EngineEntitlementSpec {
- value_type: string;
- credit_id?: string;
- consumption_rate?: number;
- event_subtype?: string;
-}
-
-interface EngineResultSpec {
- value: boolean;
- reason?: string;
- entitlement?: EngineEntitlementSpec;
-}
-
-interface EngineCallExpect {
- credit_balance?: number | "max_safe_integer";
- credit_cost?: number;
- event_usage?: { event_subtype: string; quantity: number };
- usage?: number;
-}
-
-interface OpExpect {
- written?: boolean;
- balance?: number | null;
- consumed?: number | null;
- throws?: boolean;
- exists?: boolean;
- lease_id?: string | null;
- granted_amount?: number;
- local_remaining_credits?: number;
- total?: number;
- count?: number;
- swept?: number;
- wire_acquires?: number;
- last_acquire_requested_amount?: number;
- released_lease_ids?: string[];
- wire_extends?: number;
- last_extend_additional_amount?: number;
- last_extend_lease_id?: string;
- allowed?: boolean;
- reason?: string;
- err?: string;
- has_reservation?: boolean;
- reservation?: {
- lease_id?: string;
- credit_type_id?: string;
- event_subtype?: string;
- quantity_reserved?: number;
- credits_reserved?: number;
- consumption_rate?: number;
- };
- engine_calls?: EngineCallExpect[];
- fallback_called?: boolean;
- settled_locally?: boolean;
- track?: { event?: string; quantity?: number; lease_id?: string };
-}
-
-interface Operation {
- op: string;
- expect?: OpExpect;
- // advance_clock
- ms?: number;
- // lease / reservation store ops
- lease_id?: string;
- company_id?: string;
- credit_type_id?: string;
- granted_amount?: number;
- expires_at_ms?: number;
- credits?: number;
- pin_lease_id?: string;
- granted_total?: number;
- id?: string;
- handle?: string;
- event_subtype?: string;
- quantity_reserved?: number;
- credits_reserved?: number;
- consumption_rate?: number;
- crash_before_refund?: boolean;
- // manager ops
- required_credits?: number;
- server?: ServerScript | { acquire?: ServerScript; extend?: ServerScript };
- install_during_wire?: LeaseSpec;
- // check / track ops
- flag_key?: string;
- company?: { id: string; credit_balances?: Record };
- usage?: number;
- on_acquire_failure?: string;
- engine?: EngineResultSpec[];
- save_reservation_as?: string;
- actual_quantity?: number;
-}
-
-interface Vector {
- name: string;
- description: string;
- backends?: string[];
- given?: { config?: ConfigSpec; leases?: LeaseSpec[] };
- operations: Operation[];
-}
-
-interface VectorDoc {
- category: string;
- vectors: Vector[];
-}
-
-const VECTORS_DIR = path.join(__dirname, "..", "..", "conformance", "vectors");
-const documents: VectorDoc[] = fs
- .readdirSync(VECTORS_DIR)
- .filter((f) => f.endsWith(".json"))
- .sort()
- .map((f) => JSON.parse(fs.readFileSync(path.join(VECTORS_DIR, f), "utf8")) as VectorDoc);
-
-// ---------------------------------------------------------------------------
-// Backends. The crash hook interposes on the lease store the RESERVATION
-// store refunds through (the consume-then-refund window); every other path
-// uses the raw store. One-shot: it disarms itself when it fires.
-
-interface Stores {
- leases: ILeaseStore;
- reservations: IReservationStore;
- armCrash: () => void;
-}
-
-function crashableRefund(target: ILeaseStore): { store: ILeaseStore; arm: () => void } {
- let armed = false;
- return {
- arm: () => {
- armed = true;
- },
- store: {
- get: (companyId, creditTypeId) => target.get(companyId, creditTypeId),
- replace: (entry) => target.replace(entry),
- extend: (companyId, creditTypeId, grantedAmount, newExpiresAt, leaseId) =>
- target.extend(companyId, creditTypeId, grantedAmount, newExpiresAt, leaseId),
- drop: (companyId, creditTypeId) => target.drop(companyId, creditTypeId),
- tryReserve: (companyId, creditTypeId, credits) => target.tryReserve(companyId, creditTypeId, credits),
- refund: (companyId, creditTypeId, credits, leaseId) => {
- if (armed) {
- armed = false;
- throw new Error("simulated crash before refund");
- }
- return target.refund(companyId, creditTypeId, credits, leaseId);
- },
- },
- };
-}
-
-const backends: Array<["in_memory" | "redis", () => Stores]> = [
- [
- "in_memory",
- () => {
- const leases = new LeaseStore();
- const crash = crashableRefund(leases);
- return { leases, reservations: new ReservationStore(crash.store, 60_000), armCrash: crash.arm };
- },
- ],
- [
- "redis",
- () => {
- const client = makeFakeRedis();
- const leases = new RedisLeaseStore({ client });
- const crash = crashableRefund(leases);
- return {
- leases,
- reservations: new RedisReservationStore({ client, leaseStore: crash.store, sweepIntervalMs: 60_000 }),
- armCrash: crash.arm,
- };
- },
- ],
-];
-
-// ---------------------------------------------------------------------------
-// Harness
-
-const T0 = new Date("2026-01-01T00:00:00Z").getTime();
-
-const silentLogger: Logger = { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} };
-
-// Let floating fire-and-forget promise chains (background extend, redundant
-// release) settle. Only microtasks are involved — no timers.
-async function drain(): Promise {
- for (let i = 0; i < 20; i++) {
- await Promise.resolve();
- }
-}
-
-interface RecordedEngineCall {
- creditBalances: Record | undefined;
- creditCost: Record | undefined;
- eventUsage: { eventSubtype: string; quantity: number } | undefined;
- usage: number | undefined;
-}
-
-class Harness {
- readonly handles = new Map();
- readonly acquireResponses: ServerScript[] = [];
- readonly extendResponses: ServerScript[] = [];
- readonly acquireCalls: api.AcquireCreditLeaseRequestBody[] = [];
- readonly extendCalls: Array<{ leaseId: string; body: api.ExtendCreditLeaseRequestBody }> = [];
- readonly releaseCalls: string[] = [];
- installDuringWire: LeaseSpec | undefined;
- readonly manager: CreditLeaseManager;
- private elapsed = 0;
-
- constructor(
- readonly stores: Stores,
- config: ConfigSpec,
- ) {
- const creditsClient = {
- acquireCreditLease: async (body: api.AcquireCreditLeaseRequestBody) => {
- this.acquireCalls.push(body);
- const install = this.installDuringWire;
- if (install) {
- this.installDuringWire = undefined;
- await this.stores.leases.replace({
- leaseId: install.lease_id,
- companyId: install.company_id,
- creditTypeId: install.credit_type_id,
- grantedAmount: install.granted_amount,
- expiresAt: this.atMs(install.expires_at_ms),
- });
- }
- const scripted = this.acquireResponses.shift();
- if (!scripted || scripted.error !== undefined || !scripted.lease) {
- throw new Error(scripted?.error ?? "unscripted acquire wire call");
- }
- const lease = scripted.lease;
- return {
- data: {
- id: lease.lease_id ?? "lse_unnamed",
- companyId: body.companyId,
- creditTypeId: body.creditTypeId,
- grantedAmount: lease.granted_amount ?? 0,
- expiresAt: this.atMs(lease.expires_at_ms),
- createdAt: this.atMs(0),
- updatedAt: this.atMs(0),
- },
- params: {},
- };
- },
- extendCreditLease: async (leaseId: string, body: api.ExtendCreditLeaseRequestBody) => {
- this.extendCalls.push({ leaseId, body });
- const scripted = this.extendResponses.shift();
- if (!scripted || scripted.error !== undefined || !scripted.lease) {
- throw new Error(scripted?.error ?? "unscripted extend wire call");
- }
- const lease = scripted.lease;
- return {
- data: {
- id: leaseId,
- companyId: "co_wire",
- creditTypeId: "ct_wire",
- grantedAmount: lease.granted_total ?? 0,
- expiresAt: this.atMs(lease.expires_at_ms),
- createdAt: this.atMs(0),
- updatedAt: this.atMs(0),
- },
- params: {},
- };
- },
- releaseCreditLease: async (leaseId: string) => {
- this.releaseCalls.push(leaseId);
- return { data: {}, params: {} };
- },
- } as unknown as CreditsClient;
- this.manager = new CreditLeaseManager({
- creditsClient,
- leaseStore: stores.leases,
- logger: silentLogger,
- config: {
- defaultLeaseDuration: config.lease_duration_ms,
- defaultReservationTTL: config.reservation_ttl_ms,
- defaultLeaseSize: config.lease_size,
- lowWaterMark: config.low_water_mark,
- },
- });
- }
-
- atMs(offset: number): Date {
- return new Date(T0 + offset);
- }
-
- advance(ms: number): void {
- this.elapsed += ms;
- jest.setSystemTime(T0 + this.elapsed);
- }
-
- setServer(server: Operation["server"]): void {
- if (!server) return;
- if ("lease" in server || "error" in server) {
- // Manager ops script a single call directly.
- return;
- }
- if (server.acquire) this.acquireResponses.push(server.acquire);
- if (server.extend) this.extendResponses.push(server.extend);
- }
-
- resolveReservation(op: Operation): string {
- if (op.handle !== undefined) {
- const reservation = this.handles.get(op.handle);
- if (!reservation) throw new Error(`unknown reservation handle: ${op.handle}`);
- return reservation.id;
- }
- if (op.id === undefined) throw new Error(`op ${op.op} needs an id or handle`);
- return op.id;
- }
-}
-
-function mapEntitlement(spec: EngineEntitlementSpec, flagKey: string) {
- return {
- featureId: "feat_1",
- featureKey: flagKey,
- valueType: spec.value_type,
- creditId: spec.credit_id,
- consumptionRate: spec.consumption_rate,
- eventSubtype: spec.event_subtype,
- };
-}
-
-async function runCheck(
- h: Harness,
- op: Operation,
-): Promise<{ result: CheckResult; engineCalls: RecordedEngineCall[]; fallbackCalled: boolean }> {
- const flagKey = op.flag_key ?? "flag";
- const company = op.company ?? { id: "co_1" };
- const engineResults = [...(op.engine ?? [])];
- const engineCalls: RecordedEngineCall[] = [];
- const engine = {
- checkFlagWithOptions: async (
- _flag: unknown,
- evalCompany: { creditBalances?: Record },
- _user: unknown,
- options: {
- creditCost?: Record;
- eventUsage?: { eventSubtype: string; quantity: number };
- usage?: number;
- } | null,
- ) => {
- engineCalls.push({
- creditBalances: evalCompany.creditBalances,
- creditCost: options?.creditCost,
- eventUsage: options?.eventUsage,
- usage: options?.usage,
- });
- const scripted = engineResults.shift();
- if (!scripted) throw new Error(`unscripted engine call in check op for flag ${flagKey}`);
- return {
- value: scripted.value,
- reason: scripted.reason,
- flagKey,
- flagId: "flag_1",
- entitlement: scripted.entitlement ? mapEntitlement(scripted.entitlement, flagKey) : undefined,
- };
- },
- };
- const datastream = {
- getFlag: async () => ({ id: "flag_1", key: flagKey }),
- getCompany: async () => ({ id: company.id, creditBalances: company.credit_balances ?? {} }),
- getUser: async () => null,
- getRulesEngine: () => engine,
- } as unknown as DataStreamClient;
-
- h.setServer(op.server);
-
- let fallbackCalled = false;
- const fallback = async (): Promise => {
- fallbackCalled = true;
- return { allowed: true, value: true, reason: "fallback", flagKey };
- };
-
- const deps: CreditCheckDeps = {
- leaseStore: h.stores.leases,
- reservations: h.stores.reservations,
- manager: h.manager,
- datastream,
- logger: silentLogger,
- enqueueFlagCheckEvent: () => {},
- };
- const options: CheckOptions = {
- usage: op.usage,
- eventSubtype: op.event_subtype,
- onAcquireFailure: op.on_acquire_failure as OnAcquireFailure | undefined,
- };
- const result = await checkWithLease(deps, flagKey, { company: { id: company.id } }, options, fallback);
- await drain();
- return { result, engineCalls, fallbackCalled };
-}
-
-function assertEngineCalls(recorded: RecordedEngineCall[], expected: EngineCallExpect[], creditId: string | undefined) {
- expect(recorded).toHaveLength(expected.length);
- expected.forEach((want, i) => {
- const got = recorded[i];
- if (want.credit_balance !== undefined) {
- const wantBalance =
- want.credit_balance === "max_safe_integer" ? Number.MAX_SAFE_INTEGER : want.credit_balance;
- expect(creditId).toBeDefined();
- expect(got.creditBalances?.[creditId as string]).toBe(wantBalance);
- }
- if (want.credit_cost !== undefined) {
- expect(got.creditCost?.[creditId as string]).toBe(want.credit_cost);
- }
- if (want.event_usage !== undefined) {
- expect(got.eventUsage).toEqual({
- eventSubtype: want.event_usage.event_subtype,
- quantity: want.event_usage.quantity,
- });
- }
- if (want.usage !== undefined) {
- expect(got.usage).toBe(want.usage);
- }
- });
-}
-
-async function runVector(vector: Vector, makeStores: () => Stores): Promise {
- const stores = makeStores();
- const h = new Harness(stores, vector.given?.config ?? {});
- try {
- for (const lease of vector.given?.leases ?? []) {
- expect(
- await stores.leases.replace({
- leaseId: lease.lease_id,
- companyId: lease.company_id,
- creditTypeId: lease.credit_type_id,
- grantedAmount: lease.granted_amount,
- expiresAt: h.atMs(lease.expires_at_ms),
- }),
- ).toBe(true);
- }
-
- for (const op of vector.operations) {
- const exp = op.expect ?? {};
- switch (op.op) {
- case "advance_clock": {
- h.advance(op.ms ?? 0);
- break;
- }
- case "replace_lease": {
- const written = await stores.leases.replace({
- leaseId: op.lease_id as string,
- companyId: op.company_id as string,
- creditTypeId: op.credit_type_id as string,
- grantedAmount: op.granted_amount as number,
- expiresAt: h.atMs(op.expires_at_ms as number),
- });
- if (exp.written !== undefined) expect(written).toBe(exp.written);
- break;
- }
- case "drop_lease": {
- await stores.leases.drop(op.company_id as string, op.credit_type_id as string);
- break;
- }
- case "try_reserve": {
- const balance = await stores.leases.tryReserve(
- op.company_id as string,
- op.credit_type_id as string,
- op.credits as number,
- );
- if ("balance" in exp) expect(balance).toBe(exp.balance);
- break;
- }
- case "refund_lease": {
- await stores.leases.refund(
- op.company_id as string,
- op.credit_type_id as string,
- op.credits as number,
- op.pin_lease_id,
- );
- break;
- }
- case "extend_lease": {
- await stores.leases.extend(
- op.company_id as string,
- op.credit_type_id as string,
- op.granted_total as number,
- op.expires_at_ms !== undefined ? h.atMs(op.expires_at_ms) : undefined,
- op.pin_lease_id,
- );
- break;
- }
- case "get_lease": {
- const entry = await stores.leases.get(op.company_id as string, op.credit_type_id as string);
- if (exp.exists !== undefined) expect(entry !== undefined).toBe(exp.exists);
- if (exp.lease_id !== undefined) expect(entry?.leaseId).toBe(exp.lease_id);
- if (exp.granted_amount !== undefined) expect(entry?.grantedAmount).toBe(exp.granted_amount);
- if (exp.local_remaining_credits !== undefined) {
- expect(entry?.localRemainingCredits).toBe(exp.local_remaining_credits);
- }
- break;
- }
- case "add_reservation": {
- await stores.reservations.add({
- id: op.id as string,
- leaseId: op.lease_id as string,
- companyId: op.company_id as string,
- creditTypeId: op.credit_type_id as string,
- eventSubtype: op.event_subtype as string,
- quantityReserved: op.quantity_reserved as number,
- creditsReserved: op.credits_reserved as number,
- consumptionRate: op.consumption_rate as number,
- expiresAt: h.atMs(op.expires_at_ms as number),
- evalCtx: { company: { id: op.company_id as string } },
- });
- break;
- }
- case "consume_reservation": {
- const id = h.resolveReservation(op);
- if (op.crash_before_refund) {
- stores.armCrash();
- await expect(stores.reservations.consume(id, op.credits as number)).rejects.toThrow(
- "simulated crash before refund",
- );
- expect(exp.throws).toBe(true);
- } else {
- const consumed = await stores.reservations.consume(id, op.credits as number);
- if ("consumed" in exp) expect(consumed).toBe(exp.consumed);
- }
- break;
- }
- case "get_reservation": {
- const reservation = await stores.reservations.get(h.resolveReservation(op));
- if (exp.exists !== undefined) expect(reservation !== undefined).toBe(exp.exists);
- break;
- }
- case "reserved_credits": {
- const total = await stores.reservations.reservedCredits(
- op.company_id as string,
- op.credit_type_id as string,
- );
- expect(total).toBe(exp.total);
- break;
- }
- case "reservation_count": {
- expect(await stores.reservations.size()).toBe(exp.count);
- break;
- }
- case "sweep_expired": {
- const swept = await stores.reservations.sweepExpired(new Date());
- if (exp.swept !== undefined) expect(swept).toBe(exp.swept);
- break;
- }
- case "acquire_if_needed": {
- if (op.server) h.acquireResponses.push(op.server as ServerScript);
- if (op.install_during_wire) h.installDuringWire = op.install_during_wire;
- const entry = await h.manager.acquireIfNeeded(op.company_id as string, op.credit_type_id as string);
- await drain();
- if ("lease_id" in exp) expect(entry?.leaseId ?? null).toBe(exp.lease_id);
- if (exp.wire_acquires !== undefined) expect(h.acquireCalls).toHaveLength(exp.wire_acquires);
- if (exp.last_acquire_requested_amount !== undefined) {
- expect(h.acquireCalls[h.acquireCalls.length - 1]?.requestedAmount).toBe(
- exp.last_acquire_requested_amount,
- );
- }
- if (exp.released_lease_ids !== undefined) expect(h.releaseCalls).toEqual(exp.released_lease_ids);
- break;
- }
- case "maybe_extend": {
- if (op.server) h.extendResponses.push(op.server as ServerScript);
- await h.manager.maybeExtendInBackground(
- op.company_id as string,
- op.credit_type_id as string,
- op.required_credits,
- );
- await drain();
- if (exp.wire_extends !== undefined) expect(h.extendCalls).toHaveLength(exp.wire_extends);
- if (exp.last_extend_additional_amount !== undefined) {
- expect(h.extendCalls[h.extendCalls.length - 1]?.body.additionalAmount).toBe(
- exp.last_extend_additional_amount,
- );
- }
- if (exp.last_extend_lease_id !== undefined) {
- expect(h.extendCalls[h.extendCalls.length - 1]?.leaseId).toBe(exp.last_extend_lease_id);
- }
- break;
- }
- case "release_all_local_leases": {
- await h.manager.releaseAllLocalLeases();
- if (exp.released_lease_ids !== undefined) expect(h.releaseCalls).toEqual(exp.released_lease_ids);
- break;
- }
- case "check": {
- const { result, engineCalls, fallbackCalled } = await runCheck(h, op);
- if (exp.allowed !== undefined) expect(result.allowed).toBe(exp.allowed);
- if (exp.reason !== undefined) expect(result.reason).toBe(exp.reason);
- if (exp.err !== undefined) expect(result.err).toBe(exp.err);
- if (exp.has_reservation !== undefined) {
- expect(result.reservation !== undefined).toBe(exp.has_reservation);
- }
- if (exp.fallback_called !== undefined) expect(fallbackCalled).toBe(exp.fallback_called);
- if (exp.reservation) {
- const r = result.reservation;
- expect(r).toBeDefined();
- if (exp.reservation.lease_id !== undefined) expect(r?.leaseId).toBe(exp.reservation.lease_id);
- if (exp.reservation.credit_type_id !== undefined) {
- expect(r?.creditTypeId).toBe(exp.reservation.credit_type_id);
- }
- if (exp.reservation.event_subtype !== undefined) {
- expect(r?.eventSubtype).toBe(exp.reservation.event_subtype);
- }
- if (exp.reservation.quantity_reserved !== undefined) {
- expect(r?.quantityReserved).toBe(exp.reservation.quantity_reserved);
- }
- if (exp.reservation.credits_reserved !== undefined) {
- expect(r?.creditsReserved).toBe(exp.reservation.credits_reserved);
- }
- if (exp.reservation.consumption_rate !== undefined) {
- expect(r?.consumptionRate).toBe(exp.reservation.consumption_rate);
- }
- }
- if (exp.engine_calls !== undefined) {
- const creditId =
- op.engine?.find((e) => e.entitlement?.credit_id)?.entitlement?.credit_id ??
- Object.keys(op.company?.credit_balances ?? {})[0];
- assertEngineCalls(engineCalls, exp.engine_calls, creditId);
- }
- if (exp.wire_extends !== undefined) expect(h.extendCalls).toHaveLength(exp.wire_extends);
- if (exp.last_extend_additional_amount !== undefined) {
- expect(h.extendCalls[h.extendCalls.length - 1]?.body.additionalAmount).toBe(
- exp.last_extend_additional_amount,
- );
- }
- if (op.save_reservation_as && result.reservation) {
- h.handles.set(op.save_reservation_as, result.reservation);
- }
- break;
- }
- case "track": {
- const reservation = h.handles.get(op.handle as string);
- if (!reservation) throw new Error(`unknown reservation handle: ${op.handle}`);
- const { track, settledLocally } = await consumeReservationAndBuildEvent(
- stores.reservations,
- reservation,
- op.actual_quantity as number,
- );
- if (exp.settled_locally !== undefined) expect(settledLocally).toBe(exp.settled_locally);
- if (exp.track) {
- if (exp.track.event !== undefined) expect(track.event).toBe(exp.track.event);
- if (exp.track.quantity !== undefined) expect(track.quantity).toBe(exp.track.quantity);
- if (exp.track.lease_id !== undefined) expect(track.leaseId).toBe(exp.track.lease_id);
- }
- break;
- }
- default:
- throw new Error(`unknown conformance op: ${op.op}`);
- }
- }
- } finally {
- stores.reservations.stop();
- }
-}
-
-describe.each(backends)("credit lease conformance — %s", (backendName, makeStores) => {
- beforeEach(() => {
- jest.useFakeTimers();
- jest.setSystemTime(T0);
- });
- afterEach(() => {
- jest.useRealTimers();
- });
-
- for (const doc of documents) {
- describe(doc.category, () => {
- for (const vector of doc.vectors) {
- if (vector.backends && !vector.backends.includes(backendName)) continue;
- it(vector.name, async () => {
- await runVector(vector, makeStores);
- });
- }
- });
- }
-});
diff --git a/tests/races/harness.ts b/tests/races/harness.ts
deleted file mode 100644
index 14b3d14b..00000000
--- a/tests/races/harness.ts
+++ /dev/null
@@ -1,676 +0,0 @@
-/**
- * Seeded randomized race harness for the lease/reservation stores.
- *
- * The conformance suite pins sequential semantics with deterministic vectors;
- * the truly concurrent interleavings (single-flight, extend-vs-expiry,
- * release-vs-sweeper, replace-vs-reserve) are prose invariants there. This
- * harness exercises exactly those: per seed it spawns N async workers sharing
- * a small set of (company, creditType) slots, each running a randomized op
- * sequence against the store API with seeded micro-yields injected between
- * store calls so the event-loop interleaving varies by seed. At quiescence it
- * asserts the prose invariants (conservation, bounded leak, expiry
- * monotonicity, pinned refunds/extends, exactly-once claims).
- *
- * Determinism: everything (op choice, amounts, yields, virtual-clock
- * advances) draws from PRNGs derived from the seed, ids are counters, and the
- * only awaited primitives are microtasks and `setImmediate` — whose relative
- * ordering Node schedules deterministically — so a seed replays the exact
- * schedule. `RACE_SEED=` re-runs one seed; `RACE_ITERATIONS=` scales the
- * batch.
- */
-import type { ILeaseStore } from "../../src/credits/lease-store";
-import { LeaseStore } from "../../src/credits/lease-store";
-import { RedisLeaseStore } from "../../src/credits/redis-lease-store";
-import { RedisReservationStore } from "../../src/credits/redis-reservation-store";
-import type { IReservationStore } from "../../src/credits/reservation-store";
-import { ReservationStore } from "../../src/credits/reservation-store";
-import type { Reservation } from "../../src/credits/types";
-import { makeFakeRedis } from "../unit/credits/fake-redis";
-import { deriveSeed, Rng } from "./prng";
-
-const EPS = 1e-9;
-
-export interface Slot {
- companyId: string;
- creditTypeId: string;
-}
-
-export function slotKeyOf(slot: Slot): string {
- return `${slot.companyId}:${slot.creditTypeId}`;
-}
-
-// ---------------------------------------------------------------------------
-// Virtual clock
-//
-// Both stores (and fake-redis's TTL eviction) decide expiry via `Date.now()`,
-// so overriding it gives the harness full, deterministic control of the
-// timeline — clock advances are ordinary synchronous ops workers race against
-// reserves/extends/sweeps. (The real Redis store reads the *server* clock via
-// TIME; fake-redis emulates that with `Date.now()`, which this override also
-// controls. The opt-in real-Redis integration suite is where server-clock
-// authority itself is exercised.)
-// ---------------------------------------------------------------------------
-
-export interface VirtualClock {
- now(): number;
- advance(ms: number): void;
- uninstall(): void;
-}
-
-const CLOCK_EPOCH_MS = 1_700_000_000_000;
-
-export function installVirtualClock(): VirtualClock {
- const realNow = Date.now;
- let current = CLOCK_EPOCH_MS;
- Date.now = () => current;
- return {
- now: () => current,
- advance: (ms: number) => {
- current += ms;
- },
- uninstall: () => {
- Date.now = realNow;
- },
- };
-}
-
-// ---------------------------------------------------------------------------
-// Interleaving control
-// ---------------------------------------------------------------------------
-
-/**
- * Seeded micro-yield: 0-3 awaits, each either a microtask or a macrotask
- * (`setImmediate`). Workers call this between store operations so the
- * interleaving of their op sequences varies by seed. `setTimeout(0)` is
- * deliberately excluded — its ordering relative to `setImmediate` is not
- * deterministic in Node, which would break seed replay.
- */
-export async function jitter(rng: Rng): Promise {
- const yields = rng.int(4);
- for (let i = 0; i < yields; i++) {
- if (rng.chance(0.5)) {
- await Promise.resolve();
- } else {
- await new Promise((resolve) => setImmediate(resolve));
- }
- }
-}
-
-/** Drain pending microtasks/immediates (e.g. fire-and-forget releases) before verifying. */
-export async function settle(rounds = 25): Promise {
- for (let i = 0; i < rounds; i++) {
- await new Promise((resolve) => setImmediate(resolve));
- }
-}
-
-/**
- * Credit amounts are multiples of 0.25: fractional (exercising the Redis
- * string-balance encoding) but exactly representable in binary, so the
- * conservation sums below can be compared exactly.
- */
-export function quarters(rng: Rng, maxQuarters: number, minQuarters = 1): number {
- return rng.intBetween(minQuarters, maxQuarters) * 0.25;
-}
-
-// ---------------------------------------------------------------------------
-// Backends
-// ---------------------------------------------------------------------------
-
-export interface StorePair {
- leases: ILeaseStore;
- reservations: IReservationStore;
-}
-
-export interface Backend {
- name: string;
- make(): StorePair;
-}
-
-// The sweep interval is irrelevant here (workers call `sweepExpired`
-// explicitly, racing it against consumes); set it long so a stray
-// `startSweep` could never fire mid-run.
-export const backends: Backend[] = [
- {
- name: "in-memory",
- make: () => {
- const leases = new LeaseStore();
- return { leases, reservations: new ReservationStore(leases, 60_000) };
- },
- },
- {
- name: "redis (fake)",
- make: () => {
- const client = makeFakeRedis();
- const leases = new RedisLeaseStore({ client });
- return {
- leases,
- reservations: new RedisReservationStore({ client, leaseStore: leases, sweepIntervalMs: 60_000 }),
- };
- },
- },
-];
-
-// ---------------------------------------------------------------------------
-// Model: what the harness knows it asked the stores to do
-// ---------------------------------------------------------------------------
-
-export interface OpenReservation {
- slotKey: string;
- leaseId: string;
- credits: number;
-}
-
-export class RaceModel {
- /** Leases whose `replace` returned written=true, keyed by lease id (ids are never reused). */
- installs = new Map();
- /** Every store `extend` issued, with its pin. Pins are only ever ids observed live in the slot. */
- extendsIssued: Array<{ pinLeaseId: string; total: number; expiresAtMs: number }> = [];
- /** Reservations recorded via `add` and not yet claimed by a non-null `consume` this run. */
- open = new Map();
- /** Per-slot credits actually consumed (sum of non-null `consume` returns). */
- consumed = new Map();
- /** Per-slot credits deliberately leaked via simulated window-1 crashes (debit without record). */
- leaked = new Map();
- /** Per-reservation count of non-null `consume` returns (must be <= 1). */
- claims = new Map();
- /** Op-time violations (non-racy assertions checked inline). */
- violations: string[] = [];
-
- addTo(map: Map, key: string, credits: number): void {
- map.set(key, (map.get(key) ?? 0) + credits);
- }
-}
-
-export interface RaceCtx {
- seed: number;
- clock: VirtualClock;
- leases: ILeaseStore;
- reservations: IReservationStore;
- slots: Slot[];
- model: RaceModel;
- nextId(prefix: string): string;
-}
-
-export function makeReservation(
- ctx: RaceCtx,
- slot: Slot,
- leaseId: string,
- credits: number,
- ttlMs: number,
-): Reservation {
- return {
- id: ctx.nextId("res"),
- leaseId,
- companyId: slot.companyId,
- creditTypeId: slot.creditTypeId,
- eventSubtype: "inference_tokens",
- quantityReserved: credits,
- creditsReserved: credits,
- consumptionRate: 1,
- expiresAt: new Date(ctx.clock.now() + ttlMs),
- evalCtx: { company: { id: slot.companyId } },
- };
-}
-
-// ---------------------------------------------------------------------------
-// Shared ops
-// ---------------------------------------------------------------------------
-
-export interface WeightedOp {
- weight: number;
- run(rng: Rng): Promise;
-}
-
-export interface ReserveOpts {
- /** Probability of simulating a window-1 crash (debit lands, record never written). */
- crashChance?: number;
- /** Reservation TTL range [min, max] ms. */
- ttlMs: [number, number];
- /** Max reserve size in quarter-credits. */
- maxQuarters: number;
-}
-
-/**
- * The check-flow shape: observe the lease (skipping expired ones, like the
- * manager does), debit via `try_reserve`, then record the reservation pinned
- * to the OBSERVED lease id — deliberately leaving seeded yield points where
- * expiry, a successor `replace`, or a sweep can interleave.
- */
-export function reserveOp(ctx: RaceCtx, opts: ReserveOpts): WeightedOp {
- return {
- weight: 4,
- run: async (rng) => {
- const slot = rng.pick(ctx.slots);
- const entry = await ctx.leases.get(slot.companyId, slot.creditTypeId);
- if (!entry || entry.expiresAt.getTime() <= ctx.clock.now()) return;
- const credits = quarters(rng, opts.maxQuarters);
- await jitter(rng);
- const post = await ctx.leases.tryReserve(slot.companyId, slot.creditTypeId, credits);
- if (post === null) return;
- if (post < -EPS) {
- ctx.model.violations.push(
- `tryReserve(${credits}) on ${slotKeyOf(slot)} returned a negative balance ${post}`,
- );
- }
- await jitter(rng);
- if (opts.crashChance && rng.chance(opts.crashChance)) {
- // Simulated window-1 crash: the debit landed but the record is
- // never written. The sweeper can never refund it; conservation
- // accounts for it via the leak budget.
- ctx.model.addTo(ctx.model.leaked, slotKeyOf(slot), credits);
- return;
- }
- const reservation = makeReservation(ctx, slot, entry.leaseId, credits, rng.intBetween(...opts.ttlMs));
- await ctx.reservations.add(reservation);
- ctx.model.open.set(reservation.id, { slotKey: slotKeyOf(slot), leaseId: entry.leaseId, credits });
- },
- };
-}
-
-/** Settle a random open reservation — racing other consumers and the sweeper. */
-export function consumeOp(ctx: RaceCtx): WeightedOp {
- return {
- weight: 3,
- run: async (rng) => {
- const ids = Array.from(ctx.model.open.keys());
- if (ids.length === 0) return;
- const id = rng.pick(ids);
- const open = ctx.model.open.get(id);
- if (!open) return;
- const roll = rng.next();
- let requested: number;
- if (roll < 0.15) {
- requested = open.credits + quarters(rng, 20); // over-consume: clamps to reserved
- } else if (roll < 0.25) {
- requested = -quarters(rng, 8); // negative: clamps to 0, full refund
- } else {
- requested = quarters(rng, Math.max(1, Math.round(open.credits * 4)), 0);
- }
- await jitter(rng);
- const consumed = await ctx.reservations.consume(id, requested);
- if (consumed === null) return; // lost the claim race (sweeper or another consumer)
- if (consumed < -EPS || consumed > open.credits + EPS) {
- ctx.model.violations.push(
- `consume(${id}, ${requested}) returned ${consumed}, outside [0, ${open.credits}]`,
- );
- }
- ctx.model.claims.set(id, (ctx.model.claims.get(id) ?? 0) + 1);
- ctx.model.addTo(ctx.model.consumed, open.slotKey, consumed);
- ctx.model.open.delete(id);
- },
- };
-}
-
-/** Run the expired-reservation sweeper — racing settles on the same reservations. */
-export function sweepOp(ctx: RaceCtx): WeightedOp {
- return {
- weight: 2,
- run: async (rng) => {
- await jitter(rng);
- await ctx.reservations.sweepExpired(new Date(ctx.clock.now()));
- },
- };
-}
-
-/**
- * Advance the virtual clock. Bounded to 300ms per op so a run's total advance
- * stays well under the stores' TTL grace windows (30s reservation / 60s
- * lease): rows must never TTL-evict un-swept mid-run, which would look like a
- * lost refund to the conservation check.
- */
-export function advanceOp(ctx: RaceCtx, weight = 2): WeightedOp {
- return {
- weight,
- run: async (rng) => {
- ctx.clock.advance(rng.intBetween(50, 300));
- },
- };
-}
-
-/** Non-finite/negative debits must be rejected without touching the balance. */
-export function invalidReserveOp(ctx: RaceCtx): WeightedOp {
- return {
- weight: 1,
- run: async (rng) => {
- const slot = rng.pick(ctx.slots);
- const bad = rng.pick([Number.NaN, -3, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]);
- const result = await ctx.leases.tryReserve(slot.companyId, slot.creditTypeId, bad);
- if (result !== null) {
- ctx.model.violations.push(`tryReserve(${bad}) on ${slotKeyOf(slot)} returned ${result}, not null`);
- }
- },
- };
-}
-
-/**
- * The manager's extend shape: observe the lease (skipping expired ones),
- * then reconcile the store to a server-authoritative total pinned to the
- * observed lease id — racing expiry and successor installs.
- */
-export function extendObservedOp(ctx: RaceCtx, durationMs: [number, number]): WeightedOp {
- return {
- weight: 3,
- run: async (rng) => {
- const slot = rng.pick(ctx.slots);
- const entry = await ctx.leases.get(slot.companyId, slot.creditTypeId);
- if (!entry || entry.expiresAt.getTime() <= ctx.clock.now()) return;
- // Mix of higher totals (real extends) and stale/lower totals
- // (out-of-order applies that must converge as no-ops).
- const total = entry.grantedAmount + rng.pick([-50, -0.25, 25, 100, 250.5]);
- const expiresAtMs = ctx.clock.now() + rng.intBetween(...durationMs);
- await jitter(rng);
- await ctx.leases.extend(slot.companyId, slot.creditTypeId, total, new Date(expiresAtMs), entry.leaseId);
- ctx.model.extendsIssued.push({ pinLeaseId: entry.leaseId, total, expiresAtMs });
- },
- };
-}
-
-export interface ReplaceOpts {
- /** Lease duration range, or "immortal" for a lease that can never expire mid-run. */
- durationMs: [number, number] | "immortal";
- grantedQuarters: [number, number];
- weight?: number;
- /** Only attempt the replace when the observed slot is empty/expired (the manager's shape). */
- onlyIfDead?: boolean;
-}
-
-/** Install a fresh lease — racing sibling installs (keep-first) and in-flight reserves. */
-export function replaceFreshOp(ctx: RaceCtx, opts: ReplaceOpts): WeightedOp {
- return {
- weight: opts.weight ?? 2,
- run: async (rng) => {
- const slot = rng.pick(ctx.slots);
- if (opts.onlyIfDead) {
- const current = await ctx.leases.get(slot.companyId, slot.creditTypeId);
- if (current && current.expiresAt.getTime() > ctx.clock.now()) return;
- await jitter(rng);
- }
- const granted = quarters(rng, opts.grantedQuarters[1], opts.grantedQuarters[0]);
- const expiresAtMs =
- opts.durationMs === "immortal"
- ? ctx.clock.now() + 10 * 365 * 24 * 60 * 60 * 1000
- : ctx.clock.now() + rng.intBetween(...opts.durationMs);
- const leaseId = ctx.nextId("lse");
- const wrote = await ctx.leases.replace({
- leaseId,
- companyId: slot.companyId,
- creditTypeId: slot.creditTypeId,
- grantedAmount: granted,
- expiresAt: new Date(expiresAtMs),
- });
- if (wrote) {
- ctx.model.installs.set(leaseId, { slotKey: slotKeyOf(slot), granted, expiresAtMs });
- }
- },
- };
-}
-
-/**
- * Prove the expiry guard: observe the lease, synchronously advance the clock
- * just past its expiry, and immediately probe `try_reserve`. The advance and
- * the call have no yield between them, so any debit happens at
- * `clock >= advancedTo`. If the probe succeeds and the slot still holds the
- * SAME lease with an expiry `<= advancedTo`, the debit provably landed on an
- * expired lease (ids are never reused and expiry only moves forward, so a
- * live-at-debit lease would read a later expiry afterwards) — a
- * server-side double-spend the local ledger alone cannot see. A success where
- * the slot moved on to a live successor is legitimate (the debit hit the
- * successor); it is accounted as an unrecorded hold, like a window-1 crash.
- */
-export function expiredProbeOp(ctx: RaceCtx, weight = 2): WeightedOp {
- return {
- weight,
- run: async (rng) => {
- const slot = rng.pick(ctx.slots);
- const before = await ctx.leases.get(slot.companyId, slot.creditTypeId);
- if (!before) return;
- const advancedTo = Math.max(ctx.clock.now(), before.expiresAt.getTime() + 1);
- ctx.clock.advance(advancedTo - ctx.clock.now());
- const credits = 0.25;
- const post = await ctx.leases.tryReserve(slot.companyId, slot.creditTypeId, credits);
- if (post === null) return;
- const after = await ctx.leases.get(slot.companyId, slot.creditTypeId);
- if (after && after.leaseId === before.leaseId && after.expiresAt.getTime() <= advancedTo) {
- ctx.model.violations.push(
- `${slotKeyOf(slot)}: tryReserve succeeded against expired lease ${before.leaseId} ` +
- `(expiry ${after.expiresAt.getTime()} <= clock ${advancedTo}; ` +
- `the server already refunded this balance — serving it double-spends)`,
- );
- return;
- }
- // Legitimate: the debit landed on a live successor. Nothing records
- // this hold, so account it like a window-1 crash leak.
- ctx.model.addTo(ctx.model.leaked, slotKeyOf(slot), credits);
- },
- };
-}
-
-/** Drop the slot (remote release) — racing everything else. */
-export function dropOp(ctx: RaceCtx, weight = 1): WeightedOp {
- return {
- weight,
- run: async (rng) => {
- const slot = rng.pick(ctx.slots);
- await jitter(rng);
- await ctx.leases.drop(slot.companyId, slot.creditTypeId);
- },
- };
-}
-
-// ---------------------------------------------------------------------------
-// Invariant verification (at quiescence)
-// ---------------------------------------------------------------------------
-
-export interface VerifyOpts {
- /**
- * Exact conservation: granted == remaining + open holds + consumed +
- * crash-leaked, per slot. Only sound when the scenario guarantees a single
- * never-expiring lease per slot (attribution of debits is then exact); it
- * catches both double-refunds and lost refunds.
- */
- conservation?: boolean;
- /**
- * Assert the exact final granted/expiry of the surviving lease from the
- * model (install + pinned extends). Sound whenever the harness only pins
- * extends to observed-live lease ids (ids are never reused, so a lease
- * still installed at quiescence was installed continuously since its
- * `replace` — every extend pinned to it applied). Off for manager-driven
- * scenarios where installs happen inside the manager.
- */
- exactLeaseState?: boolean;
- /** Require every slot to still hold a known lease (single-immortal-lease scenarios). */
- requireLease?: boolean;
-}
-
-export async function verifyInvariants(ctx: RaceCtx, opts: VerifyOpts): Promise {
- const violations: string[] = [...ctx.model.violations];
-
- // Reconcile the model's open reservations against the store: ones the
- // sweeper claimed are gone (their hold refunded to the lease); ones still
- // present are open holds.
- const presentBySlot = new Map();
- for (const [id, open] of ctx.model.open) {
- const inStore = await ctx.reservations.get(id);
- if (!inStore) continue; // swept: full hold refunded (pinned), counts as consumed 0
- const list = presentBySlot.get(open.slotKey) ?? [];
- list.push(open);
- presentBySlot.set(open.slotKey, list);
- }
-
- for (const slot of ctx.slots) {
- const key = slotKeyOf(slot);
- const present = presentBySlot.get(key) ?? [];
- const presentSum = present.reduce((sum, r) => sum + r.credits, 0);
-
- // The reserved-credits index (a separate structure in the Redis store)
- // must agree exactly with the reservations actually present.
- const reservedTotal = await ctx.reservations.reservedCredits(slot.companyId, slot.creditTypeId);
- if (Math.abs(reservedTotal - presentSum) > EPS) {
- violations.push(
- `${key}: reservedCredits reports ${reservedTotal} but open reservations sum to ${presentSum}`,
- );
- }
-
- const entry = await ctx.leases.get(slot.companyId, slot.creditTypeId);
- if (!entry) {
- if (opts.requireLease) violations.push(`${key}: expected the immortal lease to survive, slot is empty`);
- continue;
- }
-
- const remaining = entry.localRemainingCredits;
- const granted = entry.grantedAmount;
- if (remaining < -EPS) violations.push(`${key}: negative balance ${remaining} on lease ${entry.leaseId}`);
- if (remaining > granted + EPS) {
- violations.push(`${key}: balance ${remaining} exceeds granted ${granted} on lease ${entry.leaseId}`);
- }
-
- // No double-spend: credits held by open reservations pinned to the
- // live lease were debited from it, so remaining + holds can never
- // exceed granted. A double-refund or a refund crossing lease
- // generations (a broken pin) pushes this over.
- const pinnedOpen = present.filter((r) => r.leaseId === entry.leaseId).reduce((sum, r) => sum + r.credits, 0);
- if (remaining + pinnedOpen > granted + EPS) {
- violations.push(
- `${key}: remaining ${remaining} + pinned open holds ${pinnedOpen} exceeds granted ${granted} ` +
- `on lease ${entry.leaseId} (credits were minted)`,
- );
- }
-
- const install = ctx.model.installs.get(entry.leaseId);
- if (opts.exactLeaseState) {
- if (!install) {
- violations.push(`${key}: slot holds lease ${entry.leaseId} the harness never installed`);
- } else {
- const pinnedExtends = ctx.model.extendsIssued.filter((e) => e.pinLeaseId === entry.leaseId);
- const expectedGranted = Math.max(install.granted, ...pinnedExtends.map((e) => e.total));
- const expectedExpiry = Math.max(install.expiresAtMs, ...pinnedExtends.map((e) => e.expiresAtMs));
- if (Math.abs(granted - expectedGranted) > EPS) {
- violations.push(
- `${key}: lease ${entry.leaseId} granted ${granted}, expected ${expectedGranted} ` +
- `(install ${install.granted} + ${pinnedExtends.length} pinned extends; ` +
- `an unpinned/stale extend leaked through)`,
- );
- }
- if (entry.expiresAt.getTime() !== expectedExpiry) {
- violations.push(
- `${key}: lease ${entry.leaseId} expiry ${entry.expiresAt.getTime()}, expected ${expectedExpiry} ` +
- `(expiry must equal the max of install + pinned extend expiries — it only moves forward)`,
- );
- }
- }
- }
-
- if (opts.conservation) {
- const consumed = ctx.model.consumed.get(key) ?? 0;
- const leaked = ctx.model.leaked.get(key) ?? 0;
- const accounted = remaining + presentSum + consumed + leaked;
- if (Math.abs(accounted - granted) > EPS) {
- violations.push(
- `${key}: conservation broken on lease ${entry.leaseId}: remaining ${remaining} + ` +
- `open holds ${presentSum} + consumed ${consumed} + crash-leaked ${leaked} ` +
- `= ${accounted}, expected granted ${granted} ` +
- `(${accounted > granted ? "double refund" : "lost refund"})`,
- );
- }
- }
- }
-
- for (const [id, count] of ctx.model.claims) {
- if (count > 1) violations.push(`reservation ${id} was claimed ${count} times (consume must be exactly-once)`);
- }
-
- return violations;
-}
-
-// ---------------------------------------------------------------------------
-// Runner
-// ---------------------------------------------------------------------------
-
-export interface ScenarioRun {
- ops: WeightedOp[];
- verify(): Promise;
-}
-
-export interface RaceScenario {
- name: string;
- slots: Slot[];
- build(ctx: RaceCtx): Promise;
-}
-
-function pickWeighted(ops: WeightedOp[], rng: Rng): WeightedOp {
- const total = ops.reduce((sum, op) => sum + op.weight, 0);
- let roll = rng.next() * total;
- for (const op of ops) {
- roll -= op.weight;
- if (roll < 0) return op;
- }
- return ops[ops.length - 1];
-}
-
-export async function runScenario(scenario: RaceScenario, backend: Backend, seed: number): Promise {
- const rng = new Rng(deriveSeed(seed, 0));
- const clock = installVirtualClock();
- try {
- const { leases, reservations } = backend.make();
- let idCounter = 0;
- const ctx: RaceCtx = {
- seed,
- clock,
- leases,
- reservations,
- slots: scenario.slots,
- model: new RaceModel(),
- nextId: (prefix: string) => `${prefix}_${seed}_${++idCounter}`,
- };
- const { ops, verify } = await scenario.build(ctx);
-
- const workerCount = rng.intBetween(3, 6);
- const opsPerWorker = rng.intBetween(6, 12);
- await Promise.all(
- Array.from({ length: workerCount }, (_, workerIndex) => {
- const workerRng = new Rng(deriveSeed(seed, workerIndex + 1));
- return (async () => {
- for (let i = 0; i < opsPerWorker; i++) {
- await jitter(workerRng);
- await pickWeighted(ops, workerRng).run(workerRng);
- }
- })();
- }),
- );
-
- // Quiescence: all workers idle; drain anything fire-and-forget, then
- // run one final sweep. The sweep reconciles reservation rows the
- // backend TTL-evicted after large clock jumps (their per-slot index
- // fields would otherwise read as reserved-credits drift) — the same
- // reconciliation the production sweep loop performs.
- await settle();
- await reservations.sweepExpired(new Date(clock.now()));
-
- const violations = await verify();
- if (violations.length > 0) {
- throw new Error(
- `Race invariant violated (scenario="${scenario.name}", backend="${backend.name}", seed=${seed}, ` +
- `workers=${workerCount}, opsPerWorker=${opsPerWorker})\n` +
- `Replay exactly this schedule with: RACE_SEED=${seed} yarn test tests/races\n` +
- violations.map((v) => ` - ${v}`).join("\n"),
- );
- }
- } finally {
- clock.uninstall();
- }
-}
-
-/** Seeds for this run: `RACE_SEED` replays one; `RACE_ITERATIONS` scales the batch. */
-export function seedBatch(defaultIterations: number): number[] {
- const single = process.env.RACE_SEED;
- if (single !== undefined && single !== "") {
- const seed = Number(single);
- if (!Number.isInteger(seed)) throw new Error(`RACE_SEED must be an integer, got "${single}"`);
- return [seed];
- }
- const iterations = Number(process.env.RACE_ITERATIONS ?? defaultIterations);
- if (!Number.isInteger(iterations) || iterations < 1) {
- throw new Error(`RACE_ITERATIONS must be a positive integer, got "${process.env.RACE_ITERATIONS}"`);
- }
- return Array.from({ length: iterations }, (_, i) => i + 1);
-}
diff --git a/tests/races/prng.ts b/tests/races/prng.ts
deleted file mode 100644
index 666904e2..00000000
--- a/tests/races/prng.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Seeded PRNG (mulberry32) for the race harness. Every random choice in a run
- * — op selection, amounts, TTLs, and the micro-yields that vary event-loop
- * interleaving — draws from an `Rng` derived from the run's seed, so a failing
- * schedule replays exactly under `RACE_SEED=`.
- */
-export class Rng {
- private state: number;
-
- constructor(seed: number) {
- this.state = seed >>> 0;
- // mulberry32 degenerates on a zero state; nudge to a fixed constant so
- // seed 0 is still a valid, distinct stream.
- if (this.state === 0) this.state = 0x9e3779b9;
- }
-
- /** Uniform float in [0, 1). */
- next(): number {
- this.state = (this.state + 0x6d2b79f5) >>> 0;
- let t = this.state;
- t = Math.imul(t ^ (t >>> 15), t | 1);
- t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
- }
-
- /** Uniform integer in [0, maxExclusive). */
- int(maxExclusive: number): number {
- return Math.floor(this.next() * maxExclusive);
- }
-
- /** Uniform integer in [min, max] (inclusive). */
- intBetween(min: number, max: number): number {
- return min + this.int(max - min + 1);
- }
-
- pick(items: readonly T[]): T {
- return items[this.int(items.length)];
- }
-
- chance(probability: number): boolean {
- return this.next() < probability;
- }
-}
-
-/** Deterministically derive a child seed (e.g. per worker) from a run seed. */
-export function deriveSeed(seed: number, salt: number): number {
- let h = (Math.imul(seed, 0x9e3779b1) ^ Math.imul(salt + 1, 0x85ebca6b)) >>> 0;
- h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35) >>> 0;
- return h;
-}
diff --git a/tests/races/races.test.ts b/tests/races/races.test.ts
deleted file mode 100644
index 5a65d7bd..00000000
--- a/tests/races/races.test.ts
+++ /dev/null
@@ -1,311 +0,0 @@
-/**
- * Seeded concurrency race tests for the lease/reservation stores (and the
- * lease manager on top of them). Each scenario targets one of the race pairs
- * the conformance spec can only state as prose invariants:
- *
- * - concurrent acquires (replace) on one slot: keep-first, single live lease
- * - extend racing lease expiry and successor installs: pinned extends never
- * credit a successor; expiry only moves forward
- * - settle (consume) racing the sweeper: exactly-once claims, no double or
- * lost refunds
- * - successor replace racing try_reserve: expired balances are never served
- * - manager acquire/extend single-flight over a shared store: the installed
- * lease is never released out from under siblings; extends never mint
- * phantom credits
- * - mixed chaos across slots: all of the above at once, plus drops and
- * simulated window-1 crashes (bounded leak)
- *
- * Every run is deterministic per seed. A failure prints the seed; replay it
- * with `RACE_SEED= yarn test tests/races`. `RACE_ITERATIONS=` scales
- * the batch (default 40 per scenario/backend).
- */
-import { CreditLeaseManager } from "../../src/credits/lease-manager";
-import type { Logger } from "../../src/logger";
-
-import type { RaceCtx, RaceScenario, Slot, WeightedOp } from "./harness";
-import {
- advanceOp,
- backends,
- consumeOp,
- dropOp,
- expiredProbeOp,
- extendObservedOp,
- invalidReserveOp,
- quarters,
- replaceFreshOp,
- reserveOp,
- runScenario,
- seedBatch,
- slotKeyOf,
- sweepOp,
- verifyInvariants,
-} from "./harness";
-import { deriveSeed, Rng } from "./prng";
-import { ScriptedCreditsServer } from "./scripted-server";
-
-const seeds = seedBatch(40);
-
-jest.setTimeout(600_000);
-
-const oneSlot: Slot[] = [{ companyId: "co_1", creditTypeId: "ct_1" }];
-const twoSlots: Slot[] = [
- { companyId: "co_1", creditTypeId: "ct_1" },
- { companyId: "co_1", creditTypeId: "ct_2" },
-];
-
-const silentLogger: Logger = { error() {}, warn() {}, info() {}, debug() {} };
-
-async function installLease(ctx: RaceCtx, slot: Slot, granted: number, expiresAtMs: number): Promise {
- const leaseId = ctx.nextId("lse");
- const wrote = await ctx.leases.replace({
- leaseId,
- companyId: slot.companyId,
- creditTypeId: slot.creditTypeId,
- grantedAmount: granted,
- expiresAt: new Date(expiresAtMs),
- });
- if (!wrote) throw new Error(`setup: failed to install lease for ${slotKeyOf(slot)}`);
- ctx.model.installs.set(leaseId, { slotKey: slotKeyOf(slot), granted, expiresAtMs });
- return leaseId;
-}
-
-const scenarios: RaceScenario[] = [
- {
- // Documented gap: single-flight / concurrent acquires. All installs
- // use a lease that can never expire, so exactly one concurrent
- // `replace` may win the slot; the losers must keep the winner's
- // already-debited balance intact (conservation stays exact).
- name: "concurrent acquires (replace) on one slot",
- slots: oneSlot,
- async build(ctx) {
- return {
- ops: [
- replaceFreshOp(ctx, { durationMs: "immortal", grantedQuarters: [2000, 4000], weight: 3 }),
- reserveOp(ctx, { ttlMs: [100, 800], maxQuarters: 100 }),
- consumeOp(ctx),
- sweepOp(ctx),
- advanceOp(ctx),
- invalidReserveOp(ctx),
- ],
- verify: async () => {
- const violations = await verifyInvariants(ctx, { conservation: true, exactLeaseState: true });
- if (ctx.model.installs.size > 1) {
- violations.push(
- `${ctx.model.installs.size} concurrent replaces reported written=true for one live slot`,
- );
- }
- return violations;
- },
- };
- },
- },
- {
- // Documented gap: extend racing expiry. A short-lived lease is
- // extended (pinned) while the clock races past its expiry and
- // successors install over it. A pinned extend must never credit a
- // successor, and a lease's final granted/expiry must equal exactly
- // what its install plus its own pinned extends produced.
- name: "extend racing expiry and successor installs",
- slots: oneSlot,
- async build(ctx) {
- const setupRng = new Rng(deriveSeed(ctx.seed, 101));
- await installLease(
- ctx,
- ctx.slots[0],
- quarters(setupRng, 2000, 800),
- ctx.clock.now() + setupRng.intBetween(300, 1200),
- );
- return {
- ops: [
- advanceOp(ctx, 3),
- extendObservedOp(ctx, [300, 1500]),
- replaceFreshOp(ctx, { durationMs: [300, 1500], grantedQuarters: [800, 2000], onlyIfDead: true }),
- reserveOp(ctx, { ttlMs: [100, 700], maxQuarters: 60 }),
- consumeOp(ctx),
- sweepOp(ctx),
- expiredProbeOp(ctx),
- ],
- verify: () => verifyInvariants(ctx, { exactLeaseState: true }),
- };
- },
- },
- {
- // Documented gap: release (settle) racing the sweeper. One immortal
- // lease; short-TTL reservations are settled by racing consumers while
- // sweeps and clock advances fire concurrently, with occasional
- // simulated window-1 crashes (debit without record). Conservation is
- // exact: every credit is remaining, held, consumed, or accounted to
- // the crash-leak budget — a double refund (sweeper + settle both
- // winning a claim) or a lost refund breaks the equality.
- name: "settle (consume) racing the sweeper",
- slots: oneSlot,
- async build(ctx) {
- const setupRng = new Rng(deriveSeed(ctx.seed, 202));
- await installLease(
- ctx,
- ctx.slots[0],
- quarters(setupRng, 1600, 1000),
- ctx.clock.now() + 10 * 365 * 24 * 60 * 60 * 1000,
- );
- return {
- ops: [
- reserveOp(ctx, { ttlMs: [100, 700], maxQuarters: 400, crashChance: 0.1 }),
- { ...consumeOp(ctx), weight: 4 },
- { ...sweepOp(ctx), weight: 3 },
- advanceOp(ctx, 3),
- extendObservedOp(ctx, [300, 1500]),
- invalidReserveOp(ctx),
- ],
- verify: () => verifyInvariants(ctx, { conservation: true, exactLeaseState: true, requireLease: true }),
- };
- },
- },
- {
- // Documented gap: replace racing try_reserve. Leases churn quickly
- // (short durations, aggressive clock advances) while reserves are in
- // flight, so debits race successor installs. A reserve must never be
- // served by an expired balance and never mint credits on a successor.
- name: "successor replace racing try_reserve",
- slots: oneSlot,
- async build(ctx) {
- const setupRng = new Rng(deriveSeed(ctx.seed, 303));
- await installLease(
- ctx,
- ctx.slots[0],
- quarters(setupRng, 1200, 400),
- ctx.clock.now() + setupRng.intBetween(200, 1000),
- );
- return {
- ops: [
- replaceFreshOp(ctx, {
- durationMs: [200, 1000],
- grantedQuarters: [400, 1200],
- onlyIfDead: true,
- weight: 3,
- }),
- { ...reserveOp(ctx, { ttlMs: [100, 600], maxQuarters: 40 }), weight: 5 },
- consumeOp(ctx),
- { ...sweepOp(ctx), weight: 1 },
- advanceOp(ctx, 3),
- expiredProbeOp(ctx),
- ],
- verify: () => verifyInvariants(ctx, { exactLeaseState: true }),
- };
- },
- },
- {
- // Everything at once, across two slots: acquires, pinned extends,
- // reserves, settles, sweeps, drops, clock advances, and window-1
- // crashes, all interleaved by seed.
- name: "mixed chaos across slots",
- slots: twoSlots,
- async build(ctx) {
- return {
- ops: [
- replaceFreshOp(ctx, { durationMs: [200, 1200], grantedQuarters: [400, 1600], weight: 3 }),
- extendObservedOp(ctx, [300, 1500]),
- reserveOp(ctx, { ttlMs: [100, 700], maxQuarters: 60, crashChance: 0.1 }),
- consumeOp(ctx),
- sweepOp(ctx),
- advanceOp(ctx, 3),
- dropOp(ctx),
- invalidReserveOp(ctx),
- expiredProbeOp(ctx, 1),
- ],
- verify: () => verifyInvariants(ctx, { exactLeaseState: true }),
- };
- },
- },
- {
- // Documented gap: per-slot single-flight and the redundant-release
- // rules, driven through the real CreditLeaseManager. Two managers
- // ("pods") share one store and one scripted wire server whose calls
- // carry seeded latency, so acquire responses race sibling installs
- // and extend responses race expiry. The lease actually installed must
- // never be released server-side, and the local view must never exceed
- // the server-authoritative total.
- name: "manager acquire/extend single-flight over a shared store",
- slots: oneSlot,
- async build(ctx) {
- const buildRng = new Rng(deriveSeed(ctx.seed, 404));
- const server = new ScriptedCreditsServer(ctx.clock, new Rng(deriveSeed(ctx.seed, 405)));
- const leaseDuration = buildRng.intBetween(800, 2500);
- const managers = [0, 1].map(
- () =>
- new CreditLeaseManager({
- creditsClient: server.client(),
- leaseStore: ctx.leases,
- logger: silentLogger,
- config: {
- defaultLeaseDuration: leaseDuration,
- defaultReservationTTL: 60_000,
- defaultLeaseSize: 500,
- lowWaterMark: 0.25,
- },
- }),
- );
- const slot = ctx.slots[0];
- const ops: WeightedOp[] = [
- {
- weight: 4,
- run: async (rng) => {
- await managers[rng.int(managers.length)].acquireIfNeeded(slot.companyId, slot.creditTypeId);
- },
- },
- {
- weight: 3,
- run: async (rng) => {
- const required = rng.chance(0.5) ? quarters(rng, 2400) : undefined;
- await managers[rng.int(managers.length)].maybeExtendInBackground(
- slot.companyId,
- slot.creditTypeId,
- required,
- );
- },
- },
- reserveOp(ctx, { ttlMs: [100, 800], maxQuarters: 300 }),
- consumeOp(ctx),
- sweepOp(ctx),
- advanceOp(ctx, 3),
- expiredProbeOp(ctx, 1),
- ];
- return {
- ops,
- verify: async () => {
- const violations = await verifyInvariants(ctx, {});
- const entry = await ctx.leases.get(slot.companyId, slot.creditTypeId);
- if (entry && entry.expiresAt.getTime() > ctx.clock.now()) {
- if (server.released.has(entry.leaseId)) {
- violations.push(
- `live installed lease ${entry.leaseId} was released server-side ` +
- `(a redundant-release pulled the shared lease out from under siblings)`,
- );
- }
- const srv = server.leasesById.get(entry.leaseId);
- if (!srv) {
- violations.push(`installed lease ${entry.leaseId} is unknown to the server`);
- } else if (entry.grantedAmount > srv.granted + 1e-9) {
- violations.push(
- `local granted ${entry.grantedAmount} exceeds server-authoritative total ` +
- `${srv.granted} for ${entry.leaseId} (phantom extend credits)`,
- );
- }
- }
- return violations;
- },
- };
- },
- },
-];
-
-describe("lease/reservation concurrency race harness", () => {
- for (const scenario of scenarios) {
- for (const backend of backends) {
- test(`${scenario.name} [${backend.name}] — ${seeds.length} seeded schedule(s)`, async () => {
- for (const seed of seeds) {
- await runScenario(scenario, backend, seed);
- }
- });
- }
- }
-});
diff --git a/tests/races/scripted-server.ts b/tests/races/scripted-server.ts
deleted file mode 100644
index a4ad2807..00000000
--- a/tests/races/scripted-server.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Deterministic in-process stand-in for the credits wire API, used by the
- * manager-level race scenario. Mirrors the server contract the SDK relies on:
- *
- * - `acquire` is transactional and idempotent for an active slot: while a
- * live, unreleased lease exists for (company, creditType) every acquire is
- * handed that lease back; a fresh lease is minted only when the slot is
- * free. The check-and-mint is atomic (no awaits inside), like the real
- * server's transaction.
- * - `extend` grows the lease's authoritative total and returns it; extending
- * a released/expired lease errors.
- * - `release` marks the lease released and frees the slot.
- *
- * Seeded jitter at the entry and exit of every call simulates wire latency,
- * opening the windows (acquire response racing a sibling's install, extend
- * response landing after expiry) the lease manager has to survive.
- */
-import type { CreditsClient } from "../../src/api/resources/credits/client/Client";
-
-import type { VirtualClock } from "./harness";
-import { jitter } from "./harness";
-import type { Rng } from "./prng";
-
-interface ServerLease {
- id: string;
- companyId: string;
- creditTypeId: string;
- granted: number;
- expiresAtMs: number;
-}
-
-export class ScriptedCreditsServer {
- readonly leasesById = new Map();
- readonly released = new Set();
- private readonly activeBySlot = new Map();
- private seq = 0;
-
- constructor(
- private readonly clock: VirtualClock,
- private readonly rng: Rng,
- ) {}
-
- private activeLease(slotKey: string): ServerLease | undefined {
- const id = this.activeBySlot.get(slotKey);
- if (!id) return undefined;
- const lease = this.leasesById.get(id);
- if (!lease || this.released.has(id) || lease.expiresAtMs <= this.clock.now()) return undefined;
- return lease;
- }
-
- private toData(lease: ServerLease) {
- // Snapshot inside the atomic section so the response carries the state
- // as of the call, then travels through simulated latency.
- return {
- id: lease.id,
- companyId: lease.companyId,
- creditTypeId: lease.creditTypeId,
- grantedAmount: lease.granted,
- expiresAt: new Date(lease.expiresAtMs),
- createdAt: new Date(0),
- updatedAt: new Date(0),
- };
- }
-
- client(): CreditsClient {
- const acquireCreditLease = async (body: {
- companyId: string;
- creditTypeId: string;
- requestedAmount: number;
- expiresAt: Date;
- }) => {
- await jitter(this.rng);
- const slotKey = `${body.companyId}:${body.creditTypeId}`;
- let lease = this.activeLease(slotKey);
- if (!lease) {
- lease = {
- id: `lse_srv_${++this.seq}`,
- companyId: body.companyId,
- creditTypeId: body.creditTypeId,
- granted: body.requestedAmount,
- expiresAtMs: body.expiresAt.getTime(),
- };
- this.leasesById.set(lease.id, lease);
- this.activeBySlot.set(slotKey, lease.id);
- }
- const data = this.toData(lease);
- await jitter(this.rng);
- return { data, params: {} };
- };
-
- const extendCreditLease = async (leaseId: string, body: { additionalAmount: number; expiresAt: Date }) => {
- await jitter(this.rng);
- const lease = this.leasesById.get(leaseId);
- if (!lease || this.released.has(leaseId) || lease.expiresAtMs <= this.clock.now()) {
- throw new Error(`cannot extend inactive lease ${leaseId}`);
- }
- lease.granted += body.additionalAmount;
- lease.expiresAtMs = Math.max(lease.expiresAtMs, body.expiresAt.getTime());
- const data = this.toData(lease);
- await jitter(this.rng);
- return { data, params: {} };
- };
-
- const releaseCreditLease = async (leaseId: string) => {
- await jitter(this.rng);
- this.released.add(leaseId);
- const lease = this.leasesById.get(leaseId);
- if (lease) {
- const slotKey = `${lease.companyId}:${lease.creditTypeId}`;
- if (this.activeBySlot.get(slotKey) === leaseId) this.activeBySlot.delete(slotKey);
- }
- await jitter(this.rng);
- return { data: {}, params: {} };
- };
-
- return { acquireCreditLease, extendCreditLease, releaseCreditLease } as unknown as CreditsClient;
- }
-}
diff --git a/tests/wire/accounts.test.ts b/tests/wire/accounts.test.ts
index 28eebd1f..73ca7e54 100644
--- a/tests/wire/accounts.test.ts
+++ b/tests/wire/accounts.test.ts
@@ -2403,6 +2403,7 @@ describe("AccountsClient", () => {
const rawResponseBody = {
data: {
agent_connected_at: "2024-01-15T09:30:00Z",
+ country: "country",
dismissed_at: "2024-01-15T09:30:00Z",
environment_id: "environment_id",
milestones: [{ id: "evaluated", missing: ["connect_agent"], progress: 1.1 }],
@@ -2423,6 +2424,7 @@ describe("AccountsClient", () => {
expect(response).toEqual({
data: {
agentConnectedAt: new Date("2024-01-15T09:30:00.000Z"),
+ country: "country",
dismissedAt: new Date("2024-01-15T09:30:00.000Z"),
environmentId: "environment_id",
milestones: [
@@ -2510,6 +2512,7 @@ describe("AccountsClient", () => {
const rawResponseBody = {
data: {
agent_connected_at: "2024-01-15T09:30:00Z",
+ country: "country",
dismissed_at: "2024-01-15T09:30:00Z",
environment_id: "environment_id",
milestones: [{ id: "evaluated", missing: ["connect_agent"], progress: 1.1 }],
@@ -2537,6 +2540,7 @@ describe("AccountsClient", () => {
expect(response).toEqual({
data: {
agentConnectedAt: new Date("2024-01-15T09:30:00.000Z"),
+ country: "country",
dismissedAt: new Date("2024-01-15T09:30:00.000Z"),
environmentId: "environment_id",
milestones: [
diff --git a/tests/wire/billing.test.ts b/tests/wire/billing.test.ts
index f7c3b475..12d3b324 100644
--- a/tests/wire/billing.test.ts
+++ b/tests/wire/billing.test.ts
@@ -4005,6 +4005,310 @@ describe("BillingClient", () => {
}).rejects.toThrow(Schematic.InternalServerError);
});
+ test("listCompanyBillingProfiles (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = {
+ data: [
+ {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
+ params: {
+ company_id: "company_id",
+ is_default: true,
+ limit: 1000000,
+ offset: 1000000,
+ provider_type: "metronome",
+ },
+ };
+
+ server.mockEndpoint().get("/billing/profiles").respondWith().statusCode(200).jsonBody(rawResponseBody).build();
+
+ const response = await client.billing.listCompanyBillingProfiles({
+ companyId: "company_id",
+ isDefault: true,
+ providerType: "metronome",
+ limit: 1000000,
+ offset: 1000000,
+ });
+ expect(response).toEqual({
+ data: [
+ {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
+ params: {
+ companyId: "company_id",
+ isDefault: true,
+ limit: 1000000,
+ offset: 1000000,
+ providerType: "metronome",
+ },
+ });
+ });
+
+ test("listCompanyBillingProfiles (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/billing/profiles").respondWith().statusCode(400).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.billing.listCompanyBillingProfiles();
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("listCompanyBillingProfiles (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/billing/profiles").respondWith().statusCode(401).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.billing.listCompanyBillingProfiles();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("listCompanyBillingProfiles (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/billing/profiles").respondWith().statusCode(403).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.billing.listCompanyBillingProfiles();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("listCompanyBillingProfiles (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/billing/profiles").respondWith().statusCode(404).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.billing.listCompanyBillingProfiles();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("listCompanyBillingProfiles (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/billing/profiles").respondWith().statusCode(500).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.billing.listCompanyBillingProfiles();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("updateCompanyBillingProfile (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { collection_method: "charge_automatically" };
+ const rawResponseBody = {
+ data: {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .put("/billing/profiles/billing_profile_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ collectionMethod: "charge_automatically",
+ });
+ expect(response).toEqual({
+ data: {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("updateCompanyBillingProfile (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { collection_method: "charge_automatically" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/profiles/billing_profile_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ collectionMethod: "charge_automatically",
+ });
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("updateCompanyBillingProfile (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { collection_method: "charge_automatically" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/profiles/billing_profile_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ collectionMethod: "charge_automatically",
+ });
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("updateCompanyBillingProfile (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { collection_method: "charge_automatically" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/profiles/billing_profile_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ collectionMethod: "charge_automatically",
+ });
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("updateCompanyBillingProfile (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { collection_method: "charge_automatically" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/profiles/billing_profile_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ collectionMethod: "charge_automatically",
+ });
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("updateCompanyBillingProfile (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { collection_method: "charge_automatically" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/profiles/billing_profile_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.billing.updateCompanyBillingProfile("billing_profile_id", {
+ collectionMethod: "charge_automatically",
+ });
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
test("upsertBillingSubscription (1)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
diff --git a/tests/wire/checkout.test.ts b/tests/wire/checkout.test.ts
index e2699d1c..a0b0b78b 100644
--- a/tests/wire/checkout.test.ts
+++ b/tests/wire/checkout.test.ts
@@ -1039,6 +1039,30 @@ describe("CheckoutClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -2147,6 +2171,30 @@ describe("CheckoutClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -4078,6 +4126,30 @@ describe("CheckoutClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -4407,6 +4479,30 @@ describe("CheckoutClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -5635,6 +5731,30 @@ describe("CheckoutClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -5941,6 +6061,30 @@ describe("CheckoutClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
diff --git a/tests/wire/companies.test.ts b/tests/wire/companies.test.ts
index 3be53d1a..85f63a73 100644
--- a/tests/wire/companies.test.ts
+++ b/tests/wire/companies.test.ts
@@ -38,6 +38,30 @@ describe("CompaniesClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -378,6 +402,30 @@ describe("CompaniesClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -773,6 +821,35 @@ describe("CompaniesClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
application_id: "application_id",
cancel_at: 1000000,
@@ -1134,6 +1211,35 @@ describe("CompaniesClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
applicationId: "application_id",
cancelAt: 1000000,
@@ -1621,6 +1727,35 @@ describe("CompaniesClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
application_id: "application_id",
cancel_at: 1000000,
@@ -1977,6 +2112,35 @@ describe("CompaniesClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
applicationId: "application_id",
cancelAt: 1000000,
@@ -2695,6 +2859,35 @@ describe("CompaniesClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
application_id: "application_id",
cancel_at: 1000000,
@@ -3056,6 +3249,35 @@ describe("CompaniesClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
applicationId: "application_id",
cancelAt: 1000000,
@@ -4079,6 +4301,56 @@ describe("CompaniesClient", () => {
},
],
billing_credit_balances: { billing_credit_balances: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
application_id: "application_id",
cancel_at: 1000000,
@@ -5850,6 +6122,56 @@ describe("CompaniesClient", () => {
billingCreditBalances: {
billing_credit_balances: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
applicationId: "application_id",
cancelAt: 1000000,
@@ -8565,6 +8887,35 @@ describe("CompaniesClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
application_id: "application_id",
cancel_at: 1000000,
@@ -8927,6 +9278,35 @@ describe("CompaniesClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
applicationId: "application_id",
cancelAt: 1000000,
diff --git a/tests/wire/components.test.ts b/tests/wire/components.test.ts
index 9333a457..ee20a5c2 100644
--- a/tests/wire/components.test.ts
+++ b/tests/wire/components.test.ts
@@ -1264,6 +1264,30 @@ describe("ComponentsClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -2660,6 +2684,30 @@ describe("ComponentsClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
diff --git a/tests/wire/credits.test.ts b/tests/wire/credits.test.ts
index 6440ab83..ad33fa07 100644
--- a/tests/wire/credits.test.ts
+++ b/tests/wire/credits.test.ts
@@ -3811,6 +3811,30 @@ describe("CreditsClient", () => {
const rawRequestBody = { company_id: "company_id", credit_type_id: "credit_type_id", requested_amount: 1.1 };
const rawResponseBody = { error: "error" };
+ server
+ .mockEndpoint()
+ .post("/billing/credits/lease")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(402)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.acquireCreditLease({
+ companyId: "company_id",
+ creditTypeId: "credit_type_id",
+ requestedAmount: 1.1,
+ });
+ }).rejects.toThrow(Schematic.PaymentRequiredError);
+ });
+
+ test("acquireCreditLease (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { company_id: "company_id", credit_type_id: "credit_type_id", requested_amount: 1.1 };
+ const rawResponseBody = { error: "error" };
+
server
.mockEndpoint()
.post("/billing/credits/lease")
@@ -3829,7 +3853,7 @@ describe("CreditsClient", () => {
}).rejects.toThrow(Schematic.ForbiddenError);
});
- test("acquireCreditLease (5)", async () => {
+ test("acquireCreditLease (6)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
const rawRequestBody = { company_id: "company_id", credit_type_id: "credit_type_id", requested_amount: 1.1 };
@@ -3853,7 +3877,7 @@ describe("CreditsClient", () => {
}).rejects.toThrow(Schematic.NotFoundError);
});
- test("acquireCreditLease (6)", async () => {
+ test("acquireCreditLease (7)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
const rawRequestBody = { company_id: "company_id", credit_type_id: "credit_type_id", requested_amount: 1.1 };
@@ -3976,6 +4000,28 @@ describe("CreditsClient", () => {
const rawRequestBody = { additional_amount: 1.1 };
const rawResponseBody = { error: "error" };
+ server
+ .mockEndpoint()
+ .put("/billing/credits/lease/lease_id/extend")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(402)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.extendCreditLease("lease_id", {
+ additionalAmount: 1.1,
+ });
+ }).rejects.toThrow(Schematic.PaymentRequiredError);
+ });
+
+ test("extendCreditLease (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { additional_amount: 1.1 };
+ const rawResponseBody = { error: "error" };
+
server
.mockEndpoint()
.put("/billing/credits/lease/lease_id/extend")
@@ -3992,7 +4038,7 @@ describe("CreditsClient", () => {
}).rejects.toThrow(Schematic.ForbiddenError);
});
- test("extendCreditLease (5)", async () => {
+ test("extendCreditLease (6)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
const rawRequestBody = { additional_amount: 1.1 };
@@ -4014,7 +4060,7 @@ describe("CreditsClient", () => {
}).rejects.toThrow(Schematic.NotFoundError);
});
- test("extendCreditLease (6)", async () => {
+ test("extendCreditLease (7)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
const rawRequestBody = { additional_amount: 1.1 };
@@ -5619,6 +5665,872 @@ describe("CreditsClient", () => {
}).rejects.toThrow(Schematic.InternalServerError);
});
+ test("listCreditSpendPolicies (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = {
+ data: [
+ {
+ billing_credit_id: "billing_credit_id",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ id: "id",
+ label: "label",
+ max_per_draw: 1.1,
+ scope_type: "company",
+ updated_at: "2024-01-15T09:30:00Z",
+ user_id: "user_id",
+ },
+ ],
+ params: {
+ billing_credit_id: "billing_credit_id",
+ company_id: "company_id",
+ limit: 1000000,
+ offset: 1000000,
+ scope_type: "company",
+ user_id: "user_id",
+ user_ids: ["user_ids"],
+ },
+ };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies")
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.credits.listCreditSpendPolicies({
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ scopeType: "company",
+ userId: "user_id",
+ userIds: ["user_ids"],
+ limit: 1000000,
+ offset: 1000000,
+ });
+ expect(response).toEqual({
+ data: [
+ {
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ id: "id",
+ label: "label",
+ maxPerDraw: 1.1,
+ scopeType: "company",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ userId: "user_id",
+ },
+ ],
+ params: {
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ limit: 1000000,
+ offset: 1000000,
+ scopeType: "company",
+ userId: "user_id",
+ userIds: ["user_ids"],
+ },
+ });
+ });
+
+ test("listCreditSpendPolicies (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies")
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.listCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("listCreditSpendPolicies (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies")
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.listCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("listCreditSpendPolicies (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies")
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.listCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("listCreditSpendPolicies (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies")
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.listCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("listCreditSpendPolicies (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies")
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.listCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("createCreditSpendPolicy (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { billing_credit_id: "billing_credit_id", max_per_draw: 1.1 };
+ const rawResponseBody = {
+ data: {
+ billing_credit_id: "billing_credit_id",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ id: "id",
+ label: "label",
+ max_per_draw: 1.1,
+ scope_type: "company",
+ updated_at: "2024-01-15T09:30:00Z",
+ user_id: "user_id",
+ },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .post("/billing/credits/spend-policies")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.credits.createCreditSpendPolicy({
+ billingCreditId: "billing_credit_id",
+ maxPerDraw: 1.1,
+ });
+ expect(response).toEqual({
+ data: {
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ id: "id",
+ label: "label",
+ maxPerDraw: 1.1,
+ scopeType: "company",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ userId: "user_id",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("createCreditSpendPolicy (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { billing_credit_id: "billing_credit_id", max_per_draw: 1.1 };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/billing/credits/spend-policies")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.createCreditSpendPolicy({
+ billingCreditId: "billing_credit_id",
+ maxPerDraw: 1.1,
+ });
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("createCreditSpendPolicy (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { billing_credit_id: "billing_credit_id", max_per_draw: 1.1 };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/billing/credits/spend-policies")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.createCreditSpendPolicy({
+ billingCreditId: "billing_credit_id",
+ maxPerDraw: 1.1,
+ });
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("createCreditSpendPolicy (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { billing_credit_id: "billing_credit_id", max_per_draw: 1.1 };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/billing/credits/spend-policies")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.createCreditSpendPolicy({
+ billingCreditId: "billing_credit_id",
+ maxPerDraw: 1.1,
+ });
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("createCreditSpendPolicy (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { billing_credit_id: "billing_credit_id", max_per_draw: 1.1 };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/billing/credits/spend-policies")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.createCreditSpendPolicy({
+ billingCreditId: "billing_credit_id",
+ maxPerDraw: 1.1,
+ });
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("createCreditSpendPolicy (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { billing_credit_id: "billing_credit_id", max_per_draw: 1.1 };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/billing/credits/spend-policies")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.createCreditSpendPolicy({
+ billingCreditId: "billing_credit_id",
+ maxPerDraw: 1.1,
+ });
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("getCreditSpendPolicy (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = {
+ data: {
+ billing_credit_id: "billing_credit_id",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ id: "id",
+ label: "label",
+ max_per_draw: 1.1,
+ scope_type: "company",
+ updated_at: "2024-01-15T09:30:00Z",
+ user_id: "user_id",
+ },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.credits.getCreditSpendPolicy("spend_policy_id");
+ expect(response).toEqual({
+ data: {
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ id: "id",
+ label: "label",
+ maxPerDraw: 1.1,
+ scopeType: "company",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ userId: "user_id",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("getCreditSpendPolicy (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.getCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("getCreditSpendPolicy (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.getCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("getCreditSpendPolicy (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.getCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("getCreditSpendPolicy (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.getCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("updateCreditSpendPolicy (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = {};
+ const rawResponseBody = {
+ data: {
+ billing_credit_id: "billing_credit_id",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ id: "id",
+ label: "label",
+ max_per_draw: 1.1,
+ scope_type: "company",
+ updated_at: "2024-01-15T09:30:00Z",
+ user_id: "user_id",
+ },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .put("/billing/credits/spend-policies/spend_policy_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.credits.updateCreditSpendPolicy("spend_policy_id");
+ expect(response).toEqual({
+ data: {
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ id: "id",
+ label: "label",
+ maxPerDraw: 1.1,
+ scopeType: "company",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ userId: "user_id",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("updateCreditSpendPolicy (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = {};
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/credits/spend-policies/spend_policy_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.updateCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("updateCreditSpendPolicy (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = {};
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/credits/spend-policies/spend_policy_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.updateCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("updateCreditSpendPolicy (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = {};
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/credits/spend-policies/spend_policy_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.updateCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("updateCreditSpendPolicy (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = {};
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/credits/spend-policies/spend_policy_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.updateCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("updateCreditSpendPolicy (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = {};
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .put("/billing/credits/spend-policies/spend_policy_id")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.updateCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("deleteCreditSpendPolicy (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { data: { deleted: true }, params: { key: "value" } };
+
+ server
+ .mockEndpoint()
+ .delete("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.credits.deleteCreditSpendPolicy("spend_policy_id");
+ expect(response).toEqual({
+ data: {
+ deleted: true,
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("deleteCreditSpendPolicy (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .delete("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.deleteCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("deleteCreditSpendPolicy (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .delete("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.deleteCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("deleteCreditSpendPolicy (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .delete("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.deleteCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("deleteCreditSpendPolicy (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .delete("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.deleteCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("deleteCreditSpendPolicy (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .delete("/billing/credits/spend-policies/spend_policy_id")
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.deleteCreditSpendPolicy("spend_policy_id");
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("countCreditSpendPolicies (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = {
+ data: { count: 1000000 },
+ params: {
+ billing_credit_id: "billing_credit_id",
+ company_id: "company_id",
+ limit: 1000000,
+ offset: 1000000,
+ scope_type: "company",
+ user_id: "user_id",
+ user_ids: ["user_ids"],
+ },
+ };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/count")
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.credits.countCreditSpendPolicies({
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ scopeType: "company",
+ userId: "user_id",
+ userIds: ["user_ids"],
+ limit: 1000000,
+ offset: 1000000,
+ });
+ expect(response).toEqual({
+ data: {
+ count: 1000000,
+ },
+ params: {
+ billingCreditId: "billing_credit_id",
+ companyId: "company_id",
+ limit: 1000000,
+ offset: 1000000,
+ scopeType: "company",
+ userId: "user_id",
+ userIds: ["user_ids"],
+ },
+ });
+ });
+
+ test("countCreditSpendPolicies (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/count")
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.countCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("countCreditSpendPolicies (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/count")
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.countCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("countCreditSpendPolicies (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/count")
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.countCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("countCreditSpendPolicies (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/count")
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.countCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("countCreditSpendPolicies (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/billing/credits/spend-policies/count")
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.credits.countCreditSpendPolicies();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
test("listCreditEventLedger (1)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
diff --git a/tests/wire/entitlements.test.ts b/tests/wire/entitlements.test.ts
index b4c3b24d..5edac2be 100644
--- a/tests/wire/entitlements.test.ts
+++ b/tests/wire/entitlements.test.ts
@@ -228,6 +228,19 @@ describe("EntitlementsClient", () => {
rule_id_usage_exceeded: "rule_id_usage_exceeded",
updated_at: "2024-01-15T09:30:00Z",
value_bool: true,
+ value_credit: {
+ burn_strategy: "expiration_priority",
+ cost_editable: true,
+ created_at: "2024-01-15T09:30:00Z",
+ currency_prices: [{ currency: "currency" }],
+ default_expiry_unit: "billing_periods",
+ default_rollover_policy: "expire",
+ description: "description",
+ id: "id",
+ name: "name",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ value_credit_id: "value_credit_id",
value_numeric: 1000000,
value_trait: {
created_at: "2024-01-15T09:30:00Z",
@@ -498,6 +511,23 @@ describe("EntitlementsClient", () => {
ruleIdUsageExceeded: "rule_id_usage_exceeded",
updatedAt: new Date("2024-01-15T09:30:00.000Z"),
valueBool: true,
+ valueCredit: {
+ burnStrategy: "expiration_priority",
+ costEditable: true,
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ currencyPrices: [
+ {
+ currency: "currency",
+ },
+ ],
+ defaultExpiryUnit: "billing_periods",
+ defaultRolloverPolicy: "expire",
+ description: "description",
+ id: "id",
+ name: "name",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ valueCreditId: "value_credit_id",
valueNumeric: 1000000,
valueTrait: {
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -624,6 +654,30 @@ describe("EntitlementsClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -922,6 +976,46 @@ describe("EntitlementsClient", () => {
rule_id_usage_exceeded: "rule_id_usage_exceeded",
updated_at: "2024-01-15T09:30:00Z",
value_bool: true,
+ value_credit: {
+ burn_strategy: "expiration_priority",
+ cost_editable: true,
+ created_at: "2024-01-15T09:30:00Z",
+ currency_prices: [{ currency: "currency" }],
+ default_expiry_unit: "billing_periods",
+ default_expiry_unit_count: 1000000,
+ default_rollover_policy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ plural_name: "plural_name",
+ price: {
+ currency: "currency",
+ external_price_id: "external_price_id",
+ id: "id",
+ interval: "day",
+ interval_count: 1000000,
+ price: 1000000,
+ provider_type: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ account_id: "account_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ external_id: "external_id",
+ is_active: true,
+ name: "name",
+ price: 1.1,
+ product_id: "product_id",
+ provider_type: "metronome",
+ quantity: 1.1,
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ singular_name: "singular_name",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ value_credit_id: "value_credit_id",
value_numeric: 1000000,
value_trait: {
created_at: "2024-01-15T09:30:00Z",
@@ -983,6 +1077,30 @@ describe("EntitlementsClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -1294,6 +1412,50 @@ describe("EntitlementsClient", () => {
ruleIdUsageExceeded: "rule_id_usage_exceeded",
updatedAt: new Date("2024-01-15T09:30:00.000Z"),
valueBool: true,
+ valueCredit: {
+ burnStrategy: "expiration_priority",
+ costEditable: true,
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ currencyPrices: [
+ {
+ currency: "currency",
+ },
+ ],
+ defaultExpiryUnit: "billing_periods",
+ defaultExpiryUnitCount: 1000000,
+ defaultRolloverPolicy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ pluralName: "plural_name",
+ price: {
+ currency: "currency",
+ externalPriceId: "external_price_id",
+ id: "id",
+ interval: "day",
+ intervalCount: 1000000,
+ price: 1000000,
+ providerType: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ accountId: "account_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ externalId: "external_id",
+ isActive: true,
+ name: "name",
+ price: 1.1,
+ productId: "product_id",
+ providerType: "metronome",
+ quantity: 1.1,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ singularName: "singular_name",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ valueCreditId: "value_credit_id",
valueNumeric: 1000000,
valueTrait: {
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -1466,6 +1628,30 @@ describe("EntitlementsClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -1764,6 +1950,46 @@ describe("EntitlementsClient", () => {
rule_id_usage_exceeded: "rule_id_usage_exceeded",
updated_at: "2024-01-15T09:30:00Z",
value_bool: true,
+ value_credit: {
+ burn_strategy: "expiration_priority",
+ cost_editable: true,
+ created_at: "2024-01-15T09:30:00Z",
+ currency_prices: [{ currency: "currency" }],
+ default_expiry_unit: "billing_periods",
+ default_expiry_unit_count: 1000000,
+ default_rollover_policy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ plural_name: "plural_name",
+ price: {
+ currency: "currency",
+ external_price_id: "external_price_id",
+ id: "id",
+ interval: "day",
+ interval_count: 1000000,
+ price: 1000000,
+ provider_type: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ account_id: "account_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ external_id: "external_id",
+ is_active: true,
+ name: "name",
+ price: 1.1,
+ product_id: "product_id",
+ provider_type: "metronome",
+ quantity: 1.1,
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ singular_name: "singular_name",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ value_credit_id: "value_credit_id",
value_numeric: 1000000,
value_trait: {
created_at: "2024-01-15T09:30:00Z",
@@ -1820,6 +2046,30 @@ describe("EntitlementsClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -2131,6 +2381,50 @@ describe("EntitlementsClient", () => {
ruleIdUsageExceeded: "rule_id_usage_exceeded",
updatedAt: new Date("2024-01-15T09:30:00.000Z"),
valueBool: true,
+ valueCredit: {
+ burnStrategy: "expiration_priority",
+ costEditable: true,
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ currencyPrices: [
+ {
+ currency: "currency",
+ },
+ ],
+ defaultExpiryUnit: "billing_periods",
+ defaultExpiryUnitCount: 1000000,
+ defaultRolloverPolicy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ pluralName: "plural_name",
+ price: {
+ currency: "currency",
+ externalPriceId: "external_price_id",
+ id: "id",
+ interval: "day",
+ intervalCount: 1000000,
+ price: 1000000,
+ providerType: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ accountId: "account_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ externalId: "external_id",
+ isActive: true,
+ name: "name",
+ price: 1.1,
+ productId: "product_id",
+ providerType: "metronome",
+ quantity: 1.1,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ singularName: "singular_name",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ valueCreditId: "value_credit_id",
valueNumeric: 1000000,
valueTrait: {
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -2259,6 +2553,30 @@ describe("EntitlementsClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -2557,6 +2875,46 @@ describe("EntitlementsClient", () => {
rule_id_usage_exceeded: "rule_id_usage_exceeded",
updated_at: "2024-01-15T09:30:00Z",
value_bool: true,
+ value_credit: {
+ burn_strategy: "expiration_priority",
+ cost_editable: true,
+ created_at: "2024-01-15T09:30:00Z",
+ currency_prices: [{ currency: "currency" }],
+ default_expiry_unit: "billing_periods",
+ default_expiry_unit_count: 1000000,
+ default_rollover_policy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ plural_name: "plural_name",
+ price: {
+ currency: "currency",
+ external_price_id: "external_price_id",
+ id: "id",
+ interval: "day",
+ interval_count: 1000000,
+ price: 1000000,
+ provider_type: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ account_id: "account_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ external_id: "external_id",
+ is_active: true,
+ name: "name",
+ price: 1.1,
+ product_id: "product_id",
+ provider_type: "metronome",
+ quantity: 1.1,
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ singular_name: "singular_name",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ value_credit_id: "value_credit_id",
value_numeric: 1000000,
value_trait: {
created_at: "2024-01-15T09:30:00Z",
@@ -2613,9 +2971,33 @@ describe("EntitlementsClient", () => {
name: "name",
},
],
- billingCreditBalances: {
- key: 1.1,
- },
+ billingCreditBalances: {
+ key: 1.1,
+ },
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -2927,6 +3309,50 @@ describe("EntitlementsClient", () => {
ruleIdUsageExceeded: "rule_id_usage_exceeded",
updatedAt: new Date("2024-01-15T09:30:00.000Z"),
valueBool: true,
+ valueCredit: {
+ burnStrategy: "expiration_priority",
+ costEditable: true,
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ currencyPrices: [
+ {
+ currency: "currency",
+ },
+ ],
+ defaultExpiryUnit: "billing_periods",
+ defaultExpiryUnitCount: 1000000,
+ defaultRolloverPolicy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ pluralName: "plural_name",
+ price: {
+ currency: "currency",
+ externalPriceId: "external_price_id",
+ id: "id",
+ interval: "day",
+ intervalCount: 1000000,
+ price: 1000000,
+ providerType: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ accountId: "account_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ externalId: "external_id",
+ isActive: true,
+ name: "name",
+ price: 1.1,
+ productId: "product_id",
+ providerType: "metronome",
+ quantity: 1.1,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ singularName: "singular_name",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ valueCreditId: "value_credit_id",
valueNumeric: 1000000,
valueTrait: {
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -9384,6 +9810,18 @@ describe("EntitlementsClient", () => {
{ id: "id", included_credit_grants: [], name: "name" },
],
billing_credit_balances: { billing_credit_balances: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -9668,6 +10106,46 @@ describe("EntitlementsClient", () => {
rule_id_usage_exceeded: "rule_id_usage_exceeded",
updated_at: "2024-01-15T09:30:00Z",
value_bool: true,
+ value_credit: {
+ burn_strategy: "expiration_priority",
+ cost_editable: true,
+ created_at: "2024-01-15T09:30:00Z",
+ currency_prices: [{ currency: "currency" }, { currency: "currency" }],
+ default_expiry_unit: "billing_periods",
+ default_expiry_unit_count: 1000000,
+ default_rollover_policy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ plural_name: "plural_name",
+ price: {
+ currency: "currency",
+ external_price_id: "external_price_id",
+ id: "id",
+ interval: "day",
+ interval_count: 1000000,
+ price: 1000000,
+ provider_type: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ account_id: "account_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ external_id: "external_id",
+ is_active: true,
+ name: "name",
+ price: 1.1,
+ product_id: "product_id",
+ provider_type: "metronome",
+ quantity: 1.1,
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ singular_name: "singular_name",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ value_credit_id: "value_credit_id",
value_numeric: 1000000,
value_trait: {
created_at: "2024-01-15T09:30:00Z",
@@ -10334,6 +10812,18 @@ describe("EntitlementsClient", () => {
{ id: "id", included_credit_grants: [], name: "name" },
],
billing_credit_balances: { billing_credit_balances: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -10618,6 +11108,46 @@ describe("EntitlementsClient", () => {
rule_id_usage_exceeded: "rule_id_usage_exceeded",
updated_at: "2024-01-15T09:30:00Z",
value_bool: true,
+ value_credit: {
+ burn_strategy: "expiration_priority",
+ cost_editable: true,
+ created_at: "2024-01-15T09:30:00Z",
+ currency_prices: [{ currency: "currency" }, { currency: "currency" }],
+ default_expiry_unit: "billing_periods",
+ default_expiry_unit_count: 1000000,
+ default_rollover_policy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ plural_name: "plural_name",
+ price: {
+ currency: "currency",
+ external_price_id: "external_price_id",
+ id: "id",
+ interval: "day",
+ interval_count: 1000000,
+ price: 1000000,
+ provider_type: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ account_id: "account_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ external_id: "external_id",
+ is_active: true,
+ name: "name",
+ price: 1.1,
+ product_id: "product_id",
+ provider_type: "metronome",
+ quantity: 1.1,
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ singular_name: "singular_name",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ value_credit_id: "value_credit_id",
value_numeric: 1000000,
value_trait: {
created_at: "2024-01-15T09:30:00Z",
@@ -11309,6 +11839,18 @@ describe("EntitlementsClient", () => {
billingCreditBalances: {
billing_credit_balances: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -11615,6 +12157,53 @@ describe("EntitlementsClient", () => {
ruleIdUsageExceeded: "rule_id_usage_exceeded",
updatedAt: new Date("2024-01-15T09:30:00.000Z"),
valueBool: true,
+ valueCredit: {
+ burnStrategy: "expiration_priority",
+ costEditable: true,
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ currencyPrices: [
+ {
+ currency: "currency",
+ },
+ {
+ currency: "currency",
+ },
+ ],
+ defaultExpiryUnit: "billing_periods",
+ defaultExpiryUnitCount: 1000000,
+ defaultRolloverPolicy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ pluralName: "plural_name",
+ price: {
+ currency: "currency",
+ externalPriceId: "external_price_id",
+ id: "id",
+ interval: "day",
+ intervalCount: 1000000,
+ price: 1000000,
+ providerType: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ accountId: "account_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ externalId: "external_id",
+ isActive: true,
+ name: "name",
+ price: 1.1,
+ productId: "product_id",
+ providerType: "metronome",
+ quantity: 1.1,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ singularName: "singular_name",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ valueCreditId: "value_credit_id",
valueNumeric: 1000000,
valueTrait: {
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -12318,6 +12907,18 @@ describe("EntitlementsClient", () => {
billingCreditBalances: {
billing_credit_balances: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
@@ -12624,6 +13225,53 @@ describe("EntitlementsClient", () => {
ruleIdUsageExceeded: "rule_id_usage_exceeded",
updatedAt: new Date("2024-01-15T09:30:00.000Z"),
valueBool: true,
+ valueCredit: {
+ burnStrategy: "expiration_priority",
+ costEditable: true,
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ currencyPrices: [
+ {
+ currency: "currency",
+ },
+ {
+ currency: "currency",
+ },
+ ],
+ defaultExpiryUnit: "billing_periods",
+ defaultExpiryUnitCount: 1000000,
+ defaultRolloverPolicy: "expire",
+ description: "description",
+ icon: "icon",
+ id: "id",
+ name: "name",
+ pluralName: "plural_name",
+ price: {
+ currency: "currency",
+ externalPriceId: "external_price_id",
+ id: "id",
+ interval: "day",
+ intervalCount: 1000000,
+ price: 1000000,
+ providerType: "metronome",
+ scheme: "per_unit",
+ },
+ product: {
+ accountId: "account_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ externalId: "external_id",
+ isActive: true,
+ name: "name",
+ price: 1.1,
+ productId: "product_id",
+ providerType: "metronome",
+ quantity: 1.1,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ singularName: "singular_name",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ valueCreditId: "value_credit_id",
valueNumeric: 1000000,
valueTrait: {
createdAt: new Date("2024-01-15T09:30:00.000Z"),
diff --git a/tests/wire/events.test.ts b/tests/wire/events.test.ts
index f412ef88..695d502a 100644
--- a/tests/wire/events.test.ts
+++ b/tests/wire/events.test.ts
@@ -819,6 +819,337 @@ describe("EventsClient", () => {
}).rejects.toThrow(Schematic.InternalServerError);
});
+ test("getOTLPEnvironmentSettings (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = {
+ data: {
+ company_attribute: "company_attribute",
+ company_key: "company_key",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ tool_events_enabled: true,
+ updated_at: "2024-01-15T09:30:00Z",
+ user_attribute: "user_attribute",
+ user_key: "user_key",
+ },
+ params: { key: "value" },
+ };
+
+ server.mockEndpoint().get("/otlp/settings").respondWith().statusCode(200).jsonBody(rawResponseBody).build();
+
+ const response = await client.events.getOtlpEnvironmentSettings();
+ expect(response).toEqual({
+ data: {
+ companyAttribute: "company_attribute",
+ companyKey: "company_key",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ toolEventsEnabled: true,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ userAttribute: "user_attribute",
+ userKey: "user_key",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("getOTLPEnvironmentSettings (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/otlp/settings").respondWith().statusCode(401).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.getOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("getOTLPEnvironmentSettings (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/otlp/settings").respondWith().statusCode(403).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.getOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("getOTLPEnvironmentSettings (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/otlp/settings").respondWith().statusCode(404).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.getOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("getOTLPEnvironmentSettings (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().get("/otlp/settings").respondWith().statusCode(500).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.getOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("upsertOTLPEnvironmentSettings (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { tool_events_enabled: true };
+ const rawResponseBody = {
+ data: {
+ company_attribute: "company_attribute",
+ company_key: "company_key",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ tool_events_enabled: true,
+ updated_at: "2024-01-15T09:30:00Z",
+ user_attribute: "user_attribute",
+ user_key: "user_key",
+ },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .post("/otlp/settings")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.events.upsertOtlpEnvironmentSettings({
+ toolEventsEnabled: true,
+ });
+ expect(response).toEqual({
+ data: {
+ companyAttribute: "company_attribute",
+ companyKey: "company_key",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ toolEventsEnabled: true,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ userAttribute: "user_attribute",
+ userKey: "user_key",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("upsertOTLPEnvironmentSettings (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { tool_events_enabled: true };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/otlp/settings")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.events.upsertOtlpEnvironmentSettings({
+ toolEventsEnabled: true,
+ });
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("upsertOTLPEnvironmentSettings (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { tool_events_enabled: true };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/otlp/settings")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.events.upsertOtlpEnvironmentSettings({
+ toolEventsEnabled: true,
+ });
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("upsertOTLPEnvironmentSettings (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { tool_events_enabled: true };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/otlp/settings")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.events.upsertOtlpEnvironmentSettings({
+ toolEventsEnabled: true,
+ });
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("upsertOTLPEnvironmentSettings (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { tool_events_enabled: true };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/otlp/settings")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.events.upsertOtlpEnvironmentSettings({
+ toolEventsEnabled: true,
+ });
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("upsertOTLPEnvironmentSettings (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { tool_events_enabled: true };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/otlp/settings")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.events.upsertOtlpEnvironmentSettings({
+ toolEventsEnabled: true,
+ });
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("deleteOTLPEnvironmentSettings (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { data: { deleted: true }, params: { key: "value" } };
+
+ server.mockEndpoint().delete("/otlp/settings").respondWith().statusCode(200).jsonBody(rawResponseBody).build();
+
+ const response = await client.events.deleteOtlpEnvironmentSettings();
+ expect(response).toEqual({
+ data: {
+ deleted: true,
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("deleteOTLPEnvironmentSettings (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().delete("/otlp/settings").respondWith().statusCode(400).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.deleteOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("deleteOTLPEnvironmentSettings (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().delete("/otlp/settings").respondWith().statusCode(401).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.deleteOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("deleteOTLPEnvironmentSettings (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().delete("/otlp/settings").respondWith().statusCode(403).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.deleteOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("deleteOTLPEnvironmentSettings (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().delete("/otlp/settings").respondWith().statusCode(404).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.deleteOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("deleteOTLPEnvironmentSettings (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server.mockEndpoint().delete("/otlp/settings").respondWith().statusCode(500).jsonBody(rawResponseBody).build();
+
+ await expect(async () => {
+ return await client.events.deleteOtlpEnvironmentSettings();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
test("getSegmentIntegrationStatus (1)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
diff --git a/tests/wire/integrationsapi.test.ts b/tests/wire/integrationsapi.test.ts
index 2d9d820a..cb2e33b8 100644
--- a/tests/wire/integrationsapi.test.ts
+++ b/tests/wire/integrationsapi.test.ts
@@ -795,6 +795,367 @@ describe("IntegrationsapiClient", () => {
}).rejects.toThrow(Schematic.InternalServerError);
});
+ test("getStripeSandboxClaimLink (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = {
+ data: {
+ claim_url: "claim_url",
+ expires_at: "2024-01-15T09:30:00Z",
+ sandbox_id: "sandbox_id",
+ status: "status",
+ },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/claim-link")
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.integrationsapi.getStripeSandboxClaimLink();
+ expect(response).toEqual({
+ data: {
+ claimUrl: "claim_url",
+ expiresAt: new Date("2024-01-15T09:30:00.000Z"),
+ sandboxId: "sandbox_id",
+ status: "status",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("getStripeSandboxClaimLink (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/claim-link")
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxClaimLink();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("getStripeSandboxClaimLink (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/claim-link")
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxClaimLink();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("getStripeSandboxClaimLink (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/claim-link")
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxClaimLink();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("getStripeSandboxClaimLink (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/claim-link")
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxClaimLink();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("getStripeSandboxKeys (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = {
+ data: { publishable: "publishable", sandbox_id: "sandbox_id", secret: "secret" },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/keys")
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.integrationsapi.getStripeSandboxKeys();
+ expect(response).toEqual({
+ data: {
+ publishable: "publishable",
+ sandboxId: "sandbox_id",
+ secret: "secret",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("getStripeSandboxKeys (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/keys")
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxKeys();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("getStripeSandboxKeys (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/keys")
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxKeys();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("getStripeSandboxKeys (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/keys")
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxKeys();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("getStripeSandboxKeys (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/sandbox/keys")
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.getStripeSandboxKeys();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("claimStripeSandboxKeys (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { token: "token" };
+ const rawResponseBody = {
+ data: { publishable: "publishable", sandbox_id: "sandbox_id", secret: "secret" },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/sandbox/keys/claim")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.integrationsapi.claimStripeSandboxKeys({
+ token: "token",
+ });
+ expect(response).toEqual({
+ data: {
+ publishable: "publishable",
+ sandboxId: "sandbox_id",
+ secret: "secret",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("claimStripeSandboxKeys (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { token: "x" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/sandbox/keys/claim")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.claimStripeSandboxKeys({
+ token: "x",
+ });
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("claimStripeSandboxKeys (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { token: "x" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/sandbox/keys/claim")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.claimStripeSandboxKeys({
+ token: "x",
+ });
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("claimStripeSandboxKeys (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { token: "x" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/sandbox/keys/claim")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.claimStripeSandboxKeys({
+ token: "x",
+ });
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("claimStripeSandboxKeys (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { token: "x" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/sandbox/keys/claim")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.claimStripeSandboxKeys({
+ token: "x",
+ });
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("claimStripeSandboxKeys (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { token: "x" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/sandbox/keys/claim")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.claimStripeSandboxKeys({
+ token: "x",
+ });
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
test("assumeStripeInstalled (1)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
@@ -1169,6 +1530,306 @@ describe("IntegrationsapiClient", () => {
}).rejects.toThrow(Schematic.InternalServerError);
});
+ test("installStripeClaimableSandbox (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { email: "email" };
+ const rawResponseBody = {
+ data: {
+ api_keys: { mcp: "mcp", publishable: "publishable", secret: "secret" },
+ claim_url: "claim_url",
+ claim_url_expires_at: "2024-01-15T09:30:00Z",
+ expires_at: "2024-01-15T09:30:00Z",
+ install: {
+ capabilities: { author_plans: true, checkout: true, edit_billing: true },
+ config: {
+ created_at: "2024-01-15T09:30:00Z",
+ id: "id",
+ integration_id: "integration_id",
+ is_app_install: true,
+ is_connect_install: true,
+ live_mode: true,
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ integration: {
+ created_at: "2024-01-15T09:30:00Z",
+ id: "id",
+ state: "active",
+ type: "clerk",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ },
+ sandbox_id: "sandbox_id",
+ stripe_account_id: "stripe_account_id",
+ },
+ params: { key: "value" },
+ };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/v2/sandbox")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.integrationsapi.installStripeClaimableSandbox({
+ email: "email",
+ });
+ expect(response).toEqual({
+ data: {
+ apiKeys: {
+ mcp: "mcp",
+ publishable: "publishable",
+ secret: "secret",
+ },
+ claimUrl: "claim_url",
+ claimUrlExpiresAt: new Date("2024-01-15T09:30:00.000Z"),
+ expiresAt: new Date("2024-01-15T09:30:00.000Z"),
+ install: {
+ capabilities: {
+ authorPlans: true,
+ checkout: true,
+ editBilling: true,
+ },
+ config: {
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ id: "id",
+ integrationId: "integration_id",
+ isAppInstall: true,
+ isConnectInstall: true,
+ liveMode: true,
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ integration: {
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ id: "id",
+ state: "active",
+ type: "clerk",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ },
+ sandboxId: "sandbox_id",
+ stripeAccountId: "stripe_account_id",
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("installStripeClaimableSandbox (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { email: "email" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/v2/sandbox")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(400)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.installStripeClaimableSandbox({
+ email: "email",
+ });
+ }).rejects.toThrow(Schematic.BadRequestError);
+ });
+
+ test("installStripeClaimableSandbox (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { email: "email" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/v2/sandbox")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.installStripeClaimableSandbox({
+ email: "email",
+ });
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("installStripeClaimableSandbox (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { email: "email" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/v2/sandbox")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.installStripeClaimableSandbox({
+ email: "email",
+ });
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("installStripeClaimableSandbox (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { email: "email" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/v2/sandbox")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.installStripeClaimableSandbox({
+ email: "email",
+ });
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("installStripeClaimableSandbox (6)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+ const rawRequestBody = { email: "email" };
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .post("/integrations/stripe/v2/sandbox")
+ .jsonBody(rawRequestBody)
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.installStripeClaimableSandbox({
+ email: "email",
+ });
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
+ test("listStripeSandboxCountries (1)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { data: { countries: ["countries"] }, params: { key: "value" } };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/v2/sandbox-countries")
+ .respondWith()
+ .statusCode(200)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ const response = await client.integrationsapi.listStripeSandboxCountries();
+ expect(response).toEqual({
+ data: {
+ countries: ["countries"],
+ },
+ params: {
+ key: "value",
+ },
+ });
+ });
+
+ test("listStripeSandboxCountries (2)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/v2/sandbox-countries")
+ .respondWith()
+ .statusCode(401)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.listStripeSandboxCountries();
+ }).rejects.toThrow(Schematic.UnauthorizedError);
+ });
+
+ test("listStripeSandboxCountries (3)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/v2/sandbox-countries")
+ .respondWith()
+ .statusCode(403)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.listStripeSandboxCountries();
+ }).rejects.toThrow(Schematic.ForbiddenError);
+ });
+
+ test("listStripeSandboxCountries (4)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/v2/sandbox-countries")
+ .respondWith()
+ .statusCode(404)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.listStripeSandboxCountries();
+ }).rejects.toThrow(Schematic.NotFoundError);
+ });
+
+ test("listStripeSandboxCountries (5)", async () => {
+ const server = mockServerPool.createServer();
+ const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
+
+ const rawResponseBody = { error: "error" };
+
+ server
+ .mockEndpoint()
+ .get("/integrations/stripe/v2/sandbox-countries")
+ .respondWith()
+ .statusCode(500)
+ .jsonBody(rawResponseBody)
+ .build();
+
+ await expect(async () => {
+ return await client.integrationsapi.listStripeSandboxCountries();
+ }).rejects.toThrow(Schematic.InternalServerError);
+ });
+
test("uninstallIntegration (1)", async () => {
const server = mockServerPool.createServer();
const client = new SchematicClient({ maxRetries: 0, apiKey: "test", environment: server.baseUrl });
diff --git a/tests/wire/plans.test.ts b/tests/wire/plans.test.ts
index e654e745..feca3e4a 100644
--- a/tests/wire/plans.test.ts
+++ b/tests/wire/plans.test.ts
@@ -37,6 +37,35 @@ describe("PlansClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ billing_customer_id: "billing_customer_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ days_until_due: 1000000,
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ name: "name",
+ payment_method_id: "payment_method_id",
+ proration_behavior: "create_prorations",
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
application_id: "application_id",
cancel_at: 1000000,
@@ -396,6 +425,35 @@ describe("PlansClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ billingCustomerId: "billing_customer_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ daysUntilDue: 1000000,
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ name: "name",
+ paymentMethodId: "payment_method_id",
+ prorationBehavior: "create_prorations",
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
applicationId: "application_id",
cancelAt: 1000000,
@@ -5835,6 +5893,30 @@ describe("PlansClient", () => {
},
],
billing_credit_balances: { key: 1.1 },
+ billing_profile: {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ billing_profiles: [
+ {
+ account_id: "account_id",
+ collection_method: "charge_automatically",
+ company_id: "company_id",
+ created_at: "2024-01-15T09:30:00Z",
+ environment_id: "environment_id",
+ id: "id",
+ is_default: true,
+ provider_type: "metronome",
+ updated_at: "2024-01-15T09:30:00Z",
+ },
+ ],
billing_subscription: {
cancel_at_period_end: true,
created_at: "2024-01-15T09:30:00Z",
@@ -6142,6 +6224,30 @@ describe("PlansClient", () => {
billingCreditBalances: {
key: 1.1,
},
+ billingProfile: {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ billingProfiles: [
+ {
+ accountId: "account_id",
+ collectionMethod: "charge_automatically",
+ companyId: "company_id",
+ createdAt: new Date("2024-01-15T09:30:00.000Z"),
+ environmentId: "environment_id",
+ id: "id",
+ isDefault: true,
+ providerType: "metronome",
+ updatedAt: new Date("2024-01-15T09:30:00.000Z"),
+ },
+ ],
billingSubscription: {
cancelAtPeriodEnd: true,
createdAt: new Date("2024-01-15T09:30:00.000Z"),
diff --git a/yarn.lock b/yarn.lock
index e80853df..182558b7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1182,9 +1182,9 @@
form-data "^4.0.4"
"@types/node@*":
- version "26.4.0"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-26.4.0.tgz#4c4ca071c42241fe602741d02999f16b4e64c468"
- integrity sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ==
+ version "26.4.1"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-26.4.1.tgz#3d8dc80515894958448ee266cf5d6bc3e5205bd5"
+ integrity sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==
dependencies:
undici-types "~8.3.0"
@@ -1547,10 +1547,10 @@ base64-js@^1.3.1:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-baseline-browser-mapping@^2.11.12:
- version "2.11.20"
- resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.20.tgz#26078c7a4b08299656ea7ddceaebec955dc44303"
- integrity sha512-H0ulySigv6icDJ1F7SjtdCD6PrhTpdYCmP0CactWy1+ekh0AFd0o1Wn5T8b+hnTmdBx19u9yhL6wvCylXMY7zw==
+baseline-browser-mapping@^2.11.20:
+ version "2.11.21"
+ resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.21.tgz#99af73cb8e54007e4f5345e132278e26c2662f2c"
+ integrity sha512-uh8vpY/1/YyFkunIDFH/12p7/7VdPKA1hejMVEbdkEaWnUz0Hesvx5EbiU6XxjyHZIOju+ZMbQJkRh+es3/spQ==
brace-expansion@^1.1.7:
version "1.1.18"
@@ -1568,15 +1568,15 @@ braces@^3.0.3:
fill-range "^7.1.1"
browserslist@^4.24.0, browserslist@^4.28.1:
- version "4.28.8"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.8.tgz#a3c79ceb70028527e5da7dafc887f3200b5168c0"
- integrity sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==
+ version "4.28.9"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.9.tgz#07ce6b449b90af880eb9bfb7cd39372cc4f71c8c"
+ integrity sha512-EWazOblFYUvlGZcfGhPUPmYh3nikUxBVb+y9MJun5f3hBi812X+8MSQTujLBtgK3cf51fJWbWfOjyeO954d+Eg==
dependencies:
- baseline-browser-mapping "^2.11.12"
- caniuse-lite "^1.0.30001809"
- electron-to-chromium "^1.5.402"
- node-releases "^2.0.53"
- update-browserslist-db "^1.3.0"
+ baseline-browser-mapping "^2.11.20"
+ caniuse-lite "^1.0.30001810"
+ electron-to-chromium "^1.5.420"
+ node-releases "^2.0.54"
+ update-browserslist-db "^1.3.2"
bs-logger@^0.2.6:
version "0.2.6"
@@ -1628,7 +1628,7 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
-caniuse-lite@^1.0.30001809:
+caniuse-lite@^1.0.30001810:
version "1.0.30001810"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz#4970b477dea3278374de9bc43aa8f5d39fc3cda2"
integrity sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==
@@ -1840,10 +1840,10 @@ dunder-proto@^1.0.1:
es-errors "^1.3.0"
gopd "^1.2.0"
-electron-to-chromium@^1.5.402:
- version "1.5.417"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.417.tgz#5c2feb4670edfadf88c86c51886675802f584975"
- integrity sha512-4T+DTDWuMPM4aHlHwWdAVCVWwp7LDilnhzkj+c/Lbj91XSQrLuOmZSLtS9Q4iIqjlPUbPOnC624zDVVHCHaolQ==
+electron-to-chromium@^1.5.420:
+ version "1.5.422"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.422.tgz#e27fb1ca0e6bef612a647022e1469701fea9ee1f"
+ integrity sha512-UvA/32XqrLDdZSn7Jllo1AYNcWji/G0d5M0GTViE7KoGBiMunw3a34Sb2KO4ZZyrSEhqsxFoVhWWJshdyfKqJA==
emittery@^0.13.1:
version "0.13.1"
@@ -2032,9 +2032,9 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0:
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-uri@^3.0.1:
- version "3.1.6"
- resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.6.tgz#bfdd308ef763f835fed059f3c6c925f708e33e3a"
- integrity sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==
+ version "3.1.7"
+ resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.7.tgz#743157d957f3cbb4c65310e033dc2ad4ad7dc60a"
+ integrity sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==
fb-watchman@^2.0.0:
version "2.0.2"
@@ -2947,9 +2947,9 @@ minimist@^1.2.5:
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
minimizer-webpack-plugin@^5.7.0:
- version "5.8.0"
- resolved "https://registry.yarnpkg.com/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.8.0.tgz#744f0e28da888aa1708e2be32b4ddcf2eeb09e58"
- integrity sha512-2cT9+goJfBhtMz+gJqejSf09ClgmYhPhccRb/fb0ztVbixt0BkO8mRuI26FoPPuUNkRk6iEDryWAIouc5W8eJA==
+ version "5.9.0"
+ resolved "https://registry.yarnpkg.com/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.9.0.tgz#06c5ade7d028f3ff63321eab87f9c8c20bfa5ee8"
+ integrity sha512-OASqv+dewv8vjkOBjqMOHvxUaXhtGBLZAXq7JbmYE8TSzBvOswiGq5JcBdc8ypuLL/8YUT1OEyupga6/iqdyTA==
dependencies:
"@jridgewell/trace-mapping" "^0.3.31"
jest-worker "^27.4.5"
@@ -3013,7 +3013,7 @@ node-int64@^0.4.0:
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
-node-releases@^2.0.53:
+node-releases@^2.0.54:
version "2.0.54"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.54.tgz#09af17d5647aa9f221ec5cf2becb95b68a981afe"
integrity sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==
@@ -3636,17 +3636,17 @@ undici-types@~8.3.0:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-8.3.0.tgz#44e9fc9f3244648cdea35e4f9bb2d681e9410809"
integrity sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==
-undici@7.28.0, undici@7.29.0:
- version "7.29.0"
- resolved "https://registry.yarnpkg.com/undici/-/undici-7.29.0.tgz#ae0f6f62e06e057a9cbb7b2b5fde2bb74f791b8f"
- integrity sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==
+undici@7.28.0:
+ version "7.28.0"
+ resolved "https://registry.yarnpkg.com/undici/-/undici-7.28.0.tgz#97d64564198b285bc281f0e8e29597e3d11fe7ec"
+ integrity sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==
universalify@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
-update-browserslist-db@^1.3.0:
+update-browserslist-db@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.3.2.tgz#9d99fbff56c50bb11ba5fd35cece5916da595836"
integrity sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==
@@ -3708,9 +3708,9 @@ webpack-sources@^3.5.1:
integrity sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==
webpack@^5.105.4:
- version "5.110.2"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.110.2.tgz#ef23a0e62fe5e1ba71b033e3505b7f005d8d5c6e"
- integrity sha512-TciLrfM7zgEjqGdY851HkirDsSPQgTFsWQpl9oHqMAMYsHhEC0bKjscvjpnz+pzx10hLC8qISApGrsnrCP4UtQ==
+ version "5.110.3"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.110.3.tgz#e122b66f6226b7af8f209b6102cd13238c4813a8"
+ integrity sha512-GuizBzRvo9YPpyoNMf3ag7AzxbaW85qrRSqTha345KyJbAFPt3/cMzBM0h+RWg7SK/7DdzRLINP3LvQ0hvr4hg==
dependencies:
"@types/estree" "^1.0.8"
"@types/json-schema" "^7.0.15"
From b83080140c6a303d1e67155d556a101cfb013dcf Mon Sep 17 00:00:00 2001
From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com>
Date: Sat, 5 Sep 2026 06:37:36 +0000
Subject: [PATCH 2/2] [fern-replay] Applied customizations
Patches applied (1):
- patch-7a37bae5: chore(deps): resolve dependabot security alerts (#156)
---
.fern/replay.lock | 78 +++++++++++++++++++++++++----------------------
package.json | 3 ++
yarn.lock | 8 ++---
3 files changed, 49 insertions(+), 40 deletions(-)
diff --git a/.fern/replay.lock b/.fern/replay.lock
index 3264e8cb..8c837454 100644
--- a/.fern/replay.lock
+++ b/.fern/replay.lock
@@ -60,20 +60,26 @@ generations:
cli_version: unknown
generator_versions:
fernapi/fern-typescript-node-sdk: 3.88.3
-current_generation: 1ddbfa34c9d81f17bce913c7f1633cc61befa9c8
+ - commit_sha: a723439c1cfc640f590bb2140cf318040c7a3a4e
+ tree_hash: abc4284d81d318150972967e01fa5a0d99c8c207
+ timestamp: 2026-09-05T06:37:33.288Z
+ cli_version: unknown
+ generator_versions:
+ fernapi/fern-typescript-node-sdk: 3.90.0
+current_generation: a723439c1cfc640f590bb2140cf318040c7a3a4e
patches:
- id: patch-7a37bae5
content_hash: sha256:d668134d32b63ddb680e8e6c5c499b6e6871061c050e7aad130e876c514bc8ef
original_commit: 7a37bae547cd7e3acf4123558f38a67e8de1449b
original_message: "chore(deps): resolve dependabot security alerts (#156)"
original_author: Orbit
- base_generation: 1ddbfa34c9d81f17bce913c7f1633cc61befa9c8
+ base_generation: a723439c1cfc640f590bb2140cf318040c7a3a4e
files:
- package.json
- yarn.lock
patch_content: |
diff --git a/package.json b/package.json
- index e9dd4f5..84df190 100644
+ index d779590..e6c1d02 100644
--- a/package.json
+++ b/package.json
@@ -57,6 +57,9 @@
@@ -87,7 +93,7 @@ patches:
"engines": {
"node": ">=18.0.0"
diff --git a/yarn.lock b/yarn.lock
- index 88ec73a..e80853d 100644
+ index 182558b..ec63c7c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3636,10 +3636,10 @@ undici-types@~8.3.0:
@@ -109,7 +115,7 @@ patches:
package.json: |
{
"name": "@schematichq/schematic-typescript-node",
- "version": "1.5.11",
+ "version": "1.5.12",
"private": false,
"repository": {
"type": "git",
@@ -1369,9 +1375,9 @@ patches:
form-data "^4.0.4"
"@types/node@*":
- version "26.4.0"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-26.4.0.tgz#4c4ca071c42241fe602741d02999f16b4e64c468"
- integrity sha512-faiGnoIrLH/V8cibOMEAZ8pMw6oXqSukl29ra4mN8GdaB2ZewzeaLj+INpV5N+Z1eKWzY+IzaIZH2EIR6YZRNQ==
+ version "26.4.1"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-26.4.1.tgz#3d8dc80515894958448ee266cf5d6bc3e5205bd5"
+ integrity sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==
dependencies:
undici-types "~8.3.0"
@@ -1734,10 +1740,10 @@ patches:
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
- baseline-browser-mapping@^2.11.12:
- version "2.11.20"
- resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.20.tgz#26078c7a4b08299656ea7ddceaebec955dc44303"
- integrity sha512-H0ulySigv6icDJ1F7SjtdCD6PrhTpdYCmP0CactWy1+ekh0AFd0o1Wn5T8b+hnTmdBx19u9yhL6wvCylXMY7zw==
+ baseline-browser-mapping@^2.11.20:
+ version "2.11.21"
+ resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.21.tgz#99af73cb8e54007e4f5345e132278e26c2662f2c"
+ integrity sha512-uh8vpY/1/YyFkunIDFH/12p7/7VdPKA1hejMVEbdkEaWnUz0Hesvx5EbiU6XxjyHZIOju+ZMbQJkRh+es3/spQ==
brace-expansion@^1.1.7:
version "1.1.18"
@@ -1755,15 +1761,15 @@ patches:
fill-range "^7.1.1"
browserslist@^4.24.0, browserslist@^4.28.1:
- version "4.28.8"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.8.tgz#a3c79ceb70028527e5da7dafc887f3200b5168c0"
- integrity sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==
+ version "4.28.9"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.9.tgz#07ce6b449b90af880eb9bfb7cd39372cc4f71c8c"
+ integrity sha512-EWazOblFYUvlGZcfGhPUPmYh3nikUxBVb+y9MJun5f3hBi812X+8MSQTujLBtgK3cf51fJWbWfOjyeO954d+Eg==
dependencies:
- baseline-browser-mapping "^2.11.12"
- caniuse-lite "^1.0.30001809"
- electron-to-chromium "^1.5.402"
- node-releases "^2.0.53"
- update-browserslist-db "^1.3.0"
+ baseline-browser-mapping "^2.11.20"
+ caniuse-lite "^1.0.30001810"
+ electron-to-chromium "^1.5.420"
+ node-releases "^2.0.54"
+ update-browserslist-db "^1.3.2"
bs-logger@^0.2.6:
version "0.2.6"
@@ -1815,7 +1821,7 @@ patches:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
- caniuse-lite@^1.0.30001809:
+ caniuse-lite@^1.0.30001810:
version "1.0.30001810"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz#4970b477dea3278374de9bc43aa8f5d39fc3cda2"
integrity sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==
@@ -2027,10 +2033,10 @@ patches:
es-errors "^1.3.0"
gopd "^1.2.0"
- electron-to-chromium@^1.5.402:
- version "1.5.417"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.417.tgz#5c2feb4670edfadf88c86c51886675802f584975"
- integrity sha512-4T+DTDWuMPM4aHlHwWdAVCVWwp7LDilnhzkj+c/Lbj91XSQrLuOmZSLtS9Q4iIqjlPUbPOnC624zDVVHCHaolQ==
+ electron-to-chromium@^1.5.420:
+ version "1.5.422"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.422.tgz#e27fb1ca0e6bef612a647022e1469701fea9ee1f"
+ integrity sha512-UvA/32XqrLDdZSn7Jllo1AYNcWji/G0d5M0GTViE7KoGBiMunw3a34Sb2KO4ZZyrSEhqsxFoVhWWJshdyfKqJA==
emittery@^0.13.1:
version "0.13.1"
@@ -2219,9 +2225,9 @@ patches:
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-uri@^3.0.1:
- version "3.1.6"
- resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.6.tgz#bfdd308ef763f835fed059f3c6c925f708e33e3a"
- integrity sha512-7Ical1vFEMr0onbVzEDIreM22I4khW+fzyQPwvAFWBp1iwdshSZRsL4jjRvPG9JP1uiqMHRto+YU6R2/CzDz5Q==
+ version "3.1.7"
+ resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.7.tgz#743157d957f3cbb4c65310e033dc2ad4ad7dc60a"
+ integrity sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==
fb-watchman@^2.0.0:
version "2.0.2"
@@ -3134,9 +3140,9 @@ patches:
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
minimizer-webpack-plugin@^5.7.0:
- version "5.8.0"
- resolved "https://registry.yarnpkg.com/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.8.0.tgz#744f0e28da888aa1708e2be32b4ddcf2eeb09e58"
- integrity sha512-2cT9+goJfBhtMz+gJqejSf09ClgmYhPhccRb/fb0ztVbixt0BkO8mRuI26FoPPuUNkRk6iEDryWAIouc5W8eJA==
+ version "5.9.0"
+ resolved "https://registry.yarnpkg.com/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.9.0.tgz#06c5ade7d028f3ff63321eab87f9c8c20bfa5ee8"
+ integrity sha512-OASqv+dewv8vjkOBjqMOHvxUaXhtGBLZAXq7JbmYE8TSzBvOswiGq5JcBdc8ypuLL/8YUT1OEyupga6/iqdyTA==
dependencies:
"@jridgewell/trace-mapping" "^0.3.31"
jest-worker "^27.4.5"
@@ -3200,7 +3206,7 @@ patches:
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
- node-releases@^2.0.53:
+ node-releases@^2.0.54:
version "2.0.54"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.54.tgz#09af17d5647aa9f221ec5cf2becb95b68a981afe"
integrity sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==
@@ -3833,7 +3839,7 @@ patches:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
- update-browserslist-db@^1.3.0:
+ update-browserslist-db@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.3.2.tgz#9d99fbff56c50bb11ba5fd35cece5916da595836"
integrity sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==
@@ -3895,9 +3901,9 @@ patches:
integrity sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==
webpack@^5.105.4:
- version "5.110.2"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.110.2.tgz#ef23a0e62fe5e1ba71b033e3505b7f005d8d5c6e"
- integrity sha512-TciLrfM7zgEjqGdY851HkirDsSPQgTFsWQpl9oHqMAMYsHhEC0bKjscvjpnz+pzx10hLC8qISApGrsnrCP4UtQ==
+ version "5.110.3"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.110.3.tgz#e122b66f6226b7af8f209b6102cd13238c4813a8"
+ integrity sha512-GuizBzRvo9YPpyoNMf3ag7AzxbaW85qrRSqTha345KyJbAFPt3/cMzBM0h+RWg7SK/7DdzRLINP3LvQ0hvr4hg==
dependencies:
"@types/estree" "^1.0.8"
"@types/json-schema" "^7.0.15"
diff --git a/package.json b/package.json
index d779590c..e6c1d02e 100644
--- a/package.json
+++ b/package.json
@@ -57,6 +57,9 @@
"crypto": false,
"timers": false
},
+ "resolutions": {
+ "undici": "7.29.0"
+ },
"packageManager": "yarn@1.22.22",
"engines": {
"node": ">=18.0.0"
diff --git a/yarn.lock b/yarn.lock
index 182558b7..ec63c7cc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3636,10 +3636,10 @@ undici-types@~8.3.0:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-8.3.0.tgz#44e9fc9f3244648cdea35e4f9bb2d681e9410809"
integrity sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==
-undici@7.28.0:
- version "7.28.0"
- resolved "https://registry.yarnpkg.com/undici/-/undici-7.28.0.tgz#97d64564198b285bc281f0e8e29597e3d11fe7ec"
- integrity sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==
+undici@7.28.0, undici@7.29.0:
+ version "7.29.0"
+ resolved "https://registry.yarnpkg.com/undici/-/undici-7.29.0.tgz#ae0f6f62e06e057a9cbb7b2b5fde2bb74f791b8f"
+ integrity sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==
universalify@^0.2.0:
version "0.2.0"