diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index c766a1b1..08ebb64c 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.18.2"
+ ".": "3.19.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 1e64c91b..88277273 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 103
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-95a3d7780935a38e0cf076d4ad2d68bd1a5641bced8398d972db2e92751d364a.yml
-openapi_spec_hash: 9ebe818c4ad4f2d9c4e473b5192d7544
-config_hash: 54edf41f0377bc235f622fdaa7405f22
+configured_endpoints: 106
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-e8dad7eee5621fe2ba948dfd00dabf170d9d92ce615a9f04b0f546f4d8bf39ba.yml
+openapi_spec_hash: 3f6a98e3a1b3a47acebd67a960090ebf
+config_hash: 7e523cf79552b8936bd772f2e1025e5f
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a915617c..050ce307 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## 3.19.0 (2025-04-08)
+
+Full Changelog: [v3.18.2...v3.19.0](https://github.com/orbcorp/orb-python/compare/v3.18.2...v3.19.0)
+
+### Features
+
+* **api:** api update ([#614](https://github.com/orbcorp/orb-python/issues/614)) ([900d258](https://github.com/orbcorp/orb-python/commit/900d258b7af45e1c777b20b561373b9438e42abb))
+
+
+### Chores
+
+* **internal:** slight transform perf improvement ([#616](https://github.com/orbcorp/orb-python/issues/616)) ([de565f2](https://github.com/orbcorp/orb-python/commit/de565f252353fa7f951ad8cc10574f82919e35aa))
+* **tests:** improve enum examples ([#617](https://github.com/orbcorp/orb-python/issues/617)) ([a0d4366](https://github.com/orbcorp/orb-python/commit/a0d4366a82d86555d6ac41a912ce22414b74dd50))
+
## 3.18.2 (2025-04-07)
Full Changelog: [v3.18.1...v3.18.2](https://github.com/orbcorp/orb-python/compare/v3.18.1...v3.18.2)
diff --git a/api.md b/api.md
index da2a7bc1..2a1498a9 100644
--- a/api.md
+++ b/api.md
@@ -410,3 +410,21 @@ Methods:
Methods:
- client.dimensional_price_groups.external_dimensional_price_group_id.retrieve(external_dimensional_price_group_id) -> DimensionalPriceGroup
+
+# SubscriptionChanges
+
+Types:
+
+```python
+from orb.types import (
+ SubscriptionChangeRetrieveResponse,
+ SubscriptionChangeApplyResponse,
+ SubscriptionChangeCancelResponse,
+)
+```
+
+Methods:
+
+- client.subscription_changes.retrieve(subscription_change_id) -> SubscriptionChangeRetrieveResponse
+- client.subscription_changes.apply(subscription_change_id, \*\*params) -> SubscriptionChangeApplyResponse
+- client.subscription_changes.cancel(subscription_change_id) -> SubscriptionChangeCancelResponse
diff --git a/pyproject.toml b/pyproject.toml
index e4fc5098..8c6f97d7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "orb-billing"
-version = "3.18.2"
+version = "3.19.0"
description = "The official Python library for the orb API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/orb/_client.py b/src/orb/_client.py
index d9737190..c4b5d59c 100644
--- a/src/orb/_client.py
+++ b/src/orb/_client.py
@@ -35,6 +35,7 @@
credit_notes,
subscriptions,
invoice_line_items,
+ subscription_changes,
)
from ._streaming import Stream as Stream, AsyncStream as AsyncStream
from ._exceptions import OrbError, APIStatusError
@@ -69,6 +70,7 @@ class Orb(SyncAPIClient):
webhooks: webhooks.Webhooks
alerts: alerts.Alerts
dimensional_price_groups: dimensional_price_groups.DimensionalPriceGroups
+ subscription_changes: subscription_changes.SubscriptionChanges
with_raw_response: OrbWithRawResponse
with_streaming_response: OrbWithStreamedResponse
@@ -151,6 +153,7 @@ def __init__(
self.webhooks = webhooks.Webhooks(self)
self.alerts = alerts.Alerts(self)
self.dimensional_price_groups = dimensional_price_groups.DimensionalPriceGroups(self)
+ self.subscription_changes = subscription_changes.SubscriptionChanges(self)
self.with_raw_response = OrbWithRawResponse(self)
self.with_streaming_response = OrbWithStreamedResponse(self)
@@ -325,6 +328,7 @@ class AsyncOrb(AsyncAPIClient):
webhooks: webhooks.AsyncWebhooks
alerts: alerts.AsyncAlerts
dimensional_price_groups: dimensional_price_groups.AsyncDimensionalPriceGroups
+ subscription_changes: subscription_changes.AsyncSubscriptionChanges
with_raw_response: AsyncOrbWithRawResponse
with_streaming_response: AsyncOrbWithStreamedResponse
@@ -407,6 +411,7 @@ def __init__(
self.webhooks = webhooks.AsyncWebhooks(self)
self.alerts = alerts.AsyncAlerts(self)
self.dimensional_price_groups = dimensional_price_groups.AsyncDimensionalPriceGroups(self)
+ self.subscription_changes = subscription_changes.AsyncSubscriptionChanges(self)
self.with_raw_response = AsyncOrbWithRawResponse(self)
self.with_streaming_response = AsyncOrbWithStreamedResponse(self)
@@ -583,6 +588,7 @@ def __init__(self, client: Orb) -> None:
self.dimensional_price_groups = dimensional_price_groups.DimensionalPriceGroupsWithRawResponse(
client.dimensional_price_groups
)
+ self.subscription_changes = subscription_changes.SubscriptionChangesWithRawResponse(client.subscription_changes)
class AsyncOrbWithRawResponse:
@@ -603,6 +609,9 @@ def __init__(self, client: AsyncOrb) -> None:
self.dimensional_price_groups = dimensional_price_groups.AsyncDimensionalPriceGroupsWithRawResponse(
client.dimensional_price_groups
)
+ self.subscription_changes = subscription_changes.AsyncSubscriptionChangesWithRawResponse(
+ client.subscription_changes
+ )
class OrbWithStreamedResponse:
@@ -623,6 +632,9 @@ def __init__(self, client: Orb) -> None:
self.dimensional_price_groups = dimensional_price_groups.DimensionalPriceGroupsWithStreamingResponse(
client.dimensional_price_groups
)
+ self.subscription_changes = subscription_changes.SubscriptionChangesWithStreamingResponse(
+ client.subscription_changes
+ )
class AsyncOrbWithStreamedResponse:
@@ -645,6 +657,9 @@ def __init__(self, client: AsyncOrb) -> None:
self.dimensional_price_groups = dimensional_price_groups.AsyncDimensionalPriceGroupsWithStreamingResponse(
client.dimensional_price_groups
)
+ self.subscription_changes = subscription_changes.AsyncSubscriptionChangesWithStreamingResponse(
+ client.subscription_changes
+ )
Client = Orb
diff --git a/src/orb/_utils/_transform.py b/src/orb/_utils/_transform.py
index 7ac2e17f..3ec62081 100644
--- a/src/orb/_utils/_transform.py
+++ b/src/orb/_utils/_transform.py
@@ -142,6 +142,10 @@ def _maybe_transform_key(key: str, type_: type) -> str:
return key
+def _no_transform_needed(annotation: type) -> bool:
+ return annotation == float or annotation == int
+
+
def _transform_recursive(
data: object,
*,
@@ -184,6 +188,15 @@ def _transform_recursive(
return cast(object, data)
inner_type = extract_type_arg(stripped_type, 0)
+ if _no_transform_needed(inner_type):
+ # for some types there is no need to transform anything, so we can get a small
+ # perf boost from skipping that work.
+ #
+ # but we still need to convert to a list to ensure the data is json-serializable
+ if is_list(data):
+ return data
+ return list(data)
+
return [_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
if is_union_type(stripped_type):
@@ -332,6 +345,15 @@ async def _async_transform_recursive(
return cast(object, data)
inner_type = extract_type_arg(stripped_type, 0)
+ if _no_transform_needed(inner_type):
+ # for some types there is no need to transform anything, so we can get a small
+ # perf boost from skipping that work.
+ #
+ # but we still need to convert to a list to ensure the data is json-serializable
+ if is_list(data):
+ return data
+ return list(data)
+
return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
if is_union_type(stripped_type):
diff --git a/src/orb/_version.py b/src/orb/_version.py
index fe3ad45f..f4c31f1c 100644
--- a/src/orb/_version.py
+++ b/src/orb/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "orb"
-__version__ = "3.18.2" # x-release-please-version
+__version__ = "3.19.0" # x-release-please-version
diff --git a/src/orb/resources/__init__.py b/src/orb/resources/__init__.py
index ccb3f489..80634301 100644
--- a/src/orb/resources/__init__.py
+++ b/src/orb/resources/__init__.py
@@ -108,6 +108,14 @@
InvoiceLineItemsWithStreamingResponse,
AsyncInvoiceLineItemsWithStreamingResponse,
)
+from .subscription_changes import (
+ SubscriptionChanges,
+ AsyncSubscriptionChanges,
+ SubscriptionChangesWithRawResponse,
+ AsyncSubscriptionChangesWithRawResponse,
+ SubscriptionChangesWithStreamingResponse,
+ AsyncSubscriptionChangesWithStreamingResponse,
+)
from .dimensional_price_groups import (
DimensionalPriceGroups,
AsyncDimensionalPriceGroups,
@@ -204,4 +212,10 @@
"AsyncDimensionalPriceGroupsWithRawResponse",
"DimensionalPriceGroupsWithStreamingResponse",
"AsyncDimensionalPriceGroupsWithStreamingResponse",
+ "SubscriptionChanges",
+ "AsyncSubscriptionChanges",
+ "SubscriptionChangesWithRawResponse",
+ "AsyncSubscriptionChangesWithRawResponse",
+ "SubscriptionChangesWithStreamingResponse",
+ "AsyncSubscriptionChangesWithStreamingResponse",
]
diff --git a/src/orb/resources/invoices.py b/src/orb/resources/invoices.py
index 22c82be0..eff301a9 100644
--- a/src/orb/resources/invoices.py
+++ b/src/orb/resources/invoices.py
@@ -104,8 +104,9 @@ def create(
by setting the value to `null`, and the entire metadata mapping can be cleared
by setting `metadata` to `null`.
- will_auto_issue: When true, this invoice will automatically be issued upon creation. When false,
- the resulting invoice will require manual review to issue. Defaulted to false.
+ will_auto_issue: When true, this invoice will be submitted for issuance upon creation. When
+ false, the resulting invoice will require manual review to issue. Defaulted to
+ false.
extra_headers: Send extra headers
@@ -643,8 +644,9 @@ async def create(
by setting the value to `null`, and the entire metadata mapping can be cleared
by setting `metadata` to `null`.
- will_auto_issue: When true, this invoice will automatically be issued upon creation. When false,
- the resulting invoice will require manual review to issue. Defaulted to false.
+ will_auto_issue: When true, this invoice will be submitted for issuance upon creation. When
+ false, the resulting invoice will require manual review to issue. Defaulted to
+ false.
extra_headers: Send extra headers
diff --git a/src/orb/resources/subscription_changes.py b/src/orb/resources/subscription_changes.py
new file mode 100644
index 00000000..645b12dd
--- /dev/null
+++ b/src/orb/resources/subscription_changes.py
@@ -0,0 +1,418 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+
+import httpx
+
+from .. import _legacy_response
+from ..types import subscription_change_apply_params
+from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
+from .._utils import (
+ maybe_transform,
+ async_maybe_transform,
+)
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import to_streamed_response_wrapper, async_to_streamed_response_wrapper
+from .._base_client import make_request_options
+from ..types.subscription_change_apply_response import SubscriptionChangeApplyResponse
+from ..types.subscription_change_cancel_response import SubscriptionChangeCancelResponse
+from ..types.subscription_change_retrieve_response import SubscriptionChangeRetrieveResponse
+
+__all__ = ["SubscriptionChanges", "AsyncSubscriptionChanges"]
+
+
+class SubscriptionChanges(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> SubscriptionChangesWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/orbcorp/orb-python#accessing-raw-response-data-eg-headers
+ """
+ return SubscriptionChangesWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> SubscriptionChangesWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/orbcorp/orb-python#with_streaming_response
+ """
+ return SubscriptionChangesWithStreamingResponse(self)
+
+ def retrieve(
+ self,
+ subscription_change_id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> SubscriptionChangeRetrieveResponse:
+ """
+ This endpoint returns a subscription change given an identifier.
+
+ A subscription change is created by including
+ `Create-Pending-Subscription-Change: True` in the header of a subscription
+ mutation API call (e.g.
+ [create subscription endpoint](/api-reference/subscription/create-subscription),
+ [schedule plan change endpoint](/api-reference/subscription/schedule-plan-change),
+ ...). The subscription change will be referenced by the
+ `pending_subscription_change` field in the response.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not subscription_change_id:
+ raise ValueError(
+ f"Expected a non-empty value for `subscription_change_id` but received {subscription_change_id!r}"
+ )
+ return self._get(
+ f"/subscription_changes/{subscription_change_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SubscriptionChangeRetrieveResponse,
+ )
+
+ def apply(
+ self,
+ subscription_change_id: str,
+ *,
+ description: Optional[str] | NotGiven = NOT_GIVEN,
+ previously_collected_amount: Optional[str] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> SubscriptionChangeApplyResponse:
+ """Apply a subscription change to perform the intended action.
+
+ If a positive amount
+ is passed with a request to this endpoint, any eligible invoices that were
+ created will be issued immediately if they only contain in-advance fees.
+
+ Args:
+ description: Description to apply to the balance transaction representing this credit.
+
+ previously_collected_amount: Amount already collected to apply to the customer's balance.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not subscription_change_id:
+ raise ValueError(
+ f"Expected a non-empty value for `subscription_change_id` but received {subscription_change_id!r}"
+ )
+ return self._post(
+ f"/subscription_changes/{subscription_change_id}/apply",
+ body=maybe_transform(
+ {
+ "description": description,
+ "previously_collected_amount": previously_collected_amount,
+ },
+ subscription_change_apply_params.SubscriptionChangeApplyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=SubscriptionChangeApplyResponse,
+ )
+
+ def cancel(
+ self,
+ subscription_change_id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> SubscriptionChangeCancelResponse:
+ """Cancel a subscription change.
+
+ The change can no longer be applied. A
+ subscription can only have one "pending" change at a time - use this endpoint to
+ cancel an existing change before creating a new one.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not subscription_change_id:
+ raise ValueError(
+ f"Expected a non-empty value for `subscription_change_id` but received {subscription_change_id!r}"
+ )
+ return self._post(
+ f"/subscription_changes/{subscription_change_id}/cancel",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=SubscriptionChangeCancelResponse,
+ )
+
+
+class AsyncSubscriptionChanges(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncSubscriptionChangesWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
+
+ For more information, see https://www.github.com/orbcorp/orb-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncSubscriptionChangesWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncSubscriptionChangesWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/orbcorp/orb-python#with_streaming_response
+ """
+ return AsyncSubscriptionChangesWithStreamingResponse(self)
+
+ async def retrieve(
+ self,
+ subscription_change_id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ ) -> SubscriptionChangeRetrieveResponse:
+ """
+ This endpoint returns a subscription change given an identifier.
+
+ A subscription change is created by including
+ `Create-Pending-Subscription-Change: True` in the header of a subscription
+ mutation API call (e.g.
+ [create subscription endpoint](/api-reference/subscription/create-subscription),
+ [schedule plan change endpoint](/api-reference/subscription/schedule-plan-change),
+ ...). The subscription change will be referenced by the
+ `pending_subscription_change` field in the response.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not subscription_change_id:
+ raise ValueError(
+ f"Expected a non-empty value for `subscription_change_id` but received {subscription_change_id!r}"
+ )
+ return await self._get(
+ f"/subscription_changes/{subscription_change_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SubscriptionChangeRetrieveResponse,
+ )
+
+ async def apply(
+ self,
+ subscription_change_id: str,
+ *,
+ description: Optional[str] | NotGiven = NOT_GIVEN,
+ previously_collected_amount: Optional[str] | NotGiven = NOT_GIVEN,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> SubscriptionChangeApplyResponse:
+ """Apply a subscription change to perform the intended action.
+
+ If a positive amount
+ is passed with a request to this endpoint, any eligible invoices that were
+ created will be issued immediately if they only contain in-advance fees.
+
+ Args:
+ description: Description to apply to the balance transaction representing this credit.
+
+ previously_collected_amount: Amount already collected to apply to the customer's balance.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not subscription_change_id:
+ raise ValueError(
+ f"Expected a non-empty value for `subscription_change_id` but received {subscription_change_id!r}"
+ )
+ return await self._post(
+ f"/subscription_changes/{subscription_change_id}/apply",
+ body=await async_maybe_transform(
+ {
+ "description": description,
+ "previously_collected_amount": previously_collected_amount,
+ },
+ subscription_change_apply_params.SubscriptionChangeApplyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=SubscriptionChangeApplyResponse,
+ )
+
+ async def cancel(
+ self,
+ subscription_change_id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
+ idempotency_key: str | None = None,
+ ) -> SubscriptionChangeCancelResponse:
+ """Cancel a subscription change.
+
+ The change can no longer be applied. A
+ subscription can only have one "pending" change at a time - use this endpoint to
+ cancel an existing change before creating a new one.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+
+ idempotency_key: Specify a custom idempotency key for this request
+ """
+ if not subscription_change_id:
+ raise ValueError(
+ f"Expected a non-empty value for `subscription_change_id` but received {subscription_change_id!r}"
+ )
+ return await self._post(
+ f"/subscription_changes/{subscription_change_id}/cancel",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ idempotency_key=idempotency_key,
+ ),
+ cast_to=SubscriptionChangeCancelResponse,
+ )
+
+
+class SubscriptionChangesWithRawResponse:
+ def __init__(self, subscription_changes: SubscriptionChanges) -> None:
+ self._subscription_changes = subscription_changes
+
+ self.retrieve = _legacy_response.to_raw_response_wrapper(
+ subscription_changes.retrieve,
+ )
+ self.apply = _legacy_response.to_raw_response_wrapper(
+ subscription_changes.apply,
+ )
+ self.cancel = _legacy_response.to_raw_response_wrapper(
+ subscription_changes.cancel,
+ )
+
+
+class AsyncSubscriptionChangesWithRawResponse:
+ def __init__(self, subscription_changes: AsyncSubscriptionChanges) -> None:
+ self._subscription_changes = subscription_changes
+
+ self.retrieve = _legacy_response.async_to_raw_response_wrapper(
+ subscription_changes.retrieve,
+ )
+ self.apply = _legacy_response.async_to_raw_response_wrapper(
+ subscription_changes.apply,
+ )
+ self.cancel = _legacy_response.async_to_raw_response_wrapper(
+ subscription_changes.cancel,
+ )
+
+
+class SubscriptionChangesWithStreamingResponse:
+ def __init__(self, subscription_changes: SubscriptionChanges) -> None:
+ self._subscription_changes = subscription_changes
+
+ self.retrieve = to_streamed_response_wrapper(
+ subscription_changes.retrieve,
+ )
+ self.apply = to_streamed_response_wrapper(
+ subscription_changes.apply,
+ )
+ self.cancel = to_streamed_response_wrapper(
+ subscription_changes.cancel,
+ )
+
+
+class AsyncSubscriptionChangesWithStreamingResponse:
+ def __init__(self, subscription_changes: AsyncSubscriptionChanges) -> None:
+ self._subscription_changes = subscription_changes
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ subscription_changes.retrieve,
+ )
+ self.apply = async_to_streamed_response_wrapper(
+ subscription_changes.apply,
+ )
+ self.cancel = async_to_streamed_response_wrapper(
+ subscription_changes.cancel,
+ )
diff --git a/src/orb/types/__init__.py b/src/orb/types/__init__.py
index 74c64801..42bb839f 100644
--- a/src/orb/types/__init__.py
+++ b/src/orb/types/__init__.py
@@ -77,13 +77,16 @@
from .subscription_fetch_costs_params import SubscriptionFetchCostsParams as SubscriptionFetchCostsParams
from .subscription_fetch_usage_params import SubscriptionFetchUsageParams as SubscriptionFetchUsageParams
from .alert_create_for_customer_params import AlertCreateForCustomerParams as AlertCreateForCustomerParams
+from .subscription_change_apply_params import SubscriptionChangeApplyParams as SubscriptionChangeApplyParams
from .subscription_update_trial_params import SubscriptionUpdateTrialParams as SubscriptionUpdateTrialParams
from .invoice_line_item_create_response import InvoiceLineItemCreateResponse as InvoiceLineItemCreateResponse
from .subscription_fetch_costs_response import SubscriptionFetchCostsResponse as SubscriptionFetchCostsResponse
from .subscription_trigger_phase_params import SubscriptionTriggerPhaseParams as SubscriptionTriggerPhaseParams
+from .subscription_change_apply_response import SubscriptionChangeApplyResponse as SubscriptionChangeApplyResponse
from .subscription_fetch_schedule_params import SubscriptionFetchScheduleParams as SubscriptionFetchScheduleParams
from .subscription_update_trial_response import SubscriptionUpdateTrialResponse as SubscriptionUpdateTrialResponse
from .dimensional_price_group_list_params import DimensionalPriceGroupListParams as DimensionalPriceGroupListParams
+from .subscription_change_cancel_response import SubscriptionChangeCancelResponse as SubscriptionChangeCancelResponse
from .subscription_price_intervals_params import SubscriptionPriceIntervalsParams as SubscriptionPriceIntervalsParams
from .subscription_trigger_phase_response import SubscriptionTriggerPhaseResponse as SubscriptionTriggerPhaseResponse
from .alert_create_for_subscription_params import AlertCreateForSubscriptionParams as AlertCreateForSubscriptionParams
@@ -92,6 +95,9 @@
from .dimensional_price_group_create_params import (
DimensionalPriceGroupCreateParams as DimensionalPriceGroupCreateParams,
)
+from .subscription_change_retrieve_response import (
+ SubscriptionChangeRetrieveResponse as SubscriptionChangeRetrieveResponse,
+)
from .subscription_price_intervals_response import (
SubscriptionPriceIntervalsResponse as SubscriptionPriceIntervalsResponse,
)
diff --git a/src/orb/types/invoice_create_params.py b/src/orb/types/invoice_create_params.py
index 78e22ea8..c8e55475 100644
--- a/src/orb/types/invoice_create_params.py
+++ b/src/orb/types/invoice_create_params.py
@@ -62,7 +62,7 @@ class InvoiceCreateParams(TypedDict, total=False):
"""
will_auto_issue: bool
- """When true, this invoice will automatically be issued upon creation.
+ """When true, this invoice will be submitted for issuance upon creation.
When false, the resulting invoice will require manual review to issue. Defaulted
to false.
diff --git a/src/orb/types/plan_create_params.py b/src/orb/types/plan_create_params.py
index 817ea7f3..ae82aaf8 100644
--- a/src/orb/types/plan_create_params.py
+++ b/src/orb/types/plan_create_params.py
@@ -433,13 +433,13 @@ class PriceNewPlanMatrixPrice(TypedDict, total=False):
class PriceNewPlanTieredPriceTieredConfigTier(TypedDict, total=False):
first_unit: Required[float]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: Required[str]
"""Amount per unit"""
last_unit: Optional[float]
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class PriceNewPlanTieredPriceTieredConfig(TypedDict, total=False):
@@ -535,10 +535,10 @@ class PriceNewPlanTieredBpsPriceTieredBpsConfigTier(TypedDict, total=False):
"""Per-event basis point rate"""
minimum_amount: Required[str]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str]
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str]
"""Per unit maximum to charge"""
diff --git a/src/orb/types/price.py b/src/orb/types/price.py
index f04b2874..a53d02c4 100644
--- a/src/orb/types/price.py
+++ b/src/orb/types/price.py
@@ -710,13 +710,13 @@ class TieredPriceMinimum(BaseModel):
class TieredPriceTieredConfigTier(BaseModel):
first_unit: float
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: str
"""Amount per unit"""
last_unit: Optional[float] = None
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class TieredPriceTieredConfig(BaseModel):
@@ -841,10 +841,10 @@ class TieredBpsPriceTieredBpsConfigTier(BaseModel):
"""Per-event basis point rate"""
minimum_amount: str
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str] = None
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str] = None
"""Per unit maximum to charge"""
diff --git a/src/orb/types/price_create_params.py b/src/orb/types/price_create_params.py
index 3c41a7db..9116a686 100644
--- a/src/orb/types/price_create_params.py
+++ b/src/orb/types/price_create_params.py
@@ -561,13 +561,13 @@ class NewFloatingTieredPrice(TypedDict, total=False):
class NewFloatingTieredPriceTieredConfigTier(TypedDict, total=False):
first_unit: Required[float]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: Required[str]
"""Amount per unit"""
last_unit: Optional[float]
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class NewFloatingTieredPriceTieredConfig(TypedDict, total=False):
@@ -660,10 +660,10 @@ class NewFloatingTieredBpsPriceTieredBpsConfigTier(TypedDict, total=False):
"""Per-event basis point rate"""
minimum_amount: Required[str]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str]
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str]
"""Per unit maximum to charge"""
diff --git a/src/orb/types/subscription.py b/src/orb/types/subscription.py
index 85454c04..51911875 100644
--- a/src/orb/types/subscription.py
+++ b/src/orb/types/subscription.py
@@ -27,6 +27,7 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
@@ -346,6 +347,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -537,6 +542,9 @@ class Subscription(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
diff --git a/src/orb/types/subscription_cancel_response.py b/src/orb/types/subscription_cancel_response.py
index 700b020c..7481099d 100644
--- a/src/orb/types/subscription_cancel_response.py
+++ b/src/orb/types/subscription_cancel_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionCancelResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionCancelResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionCancelResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionCancelResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_change_apply_params.py b/src/orb/types/subscription_change_apply_params.py
new file mode 100644
index 00000000..a0f098fd
--- /dev/null
+++ b/src/orb/types/subscription_change_apply_params.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import TypedDict
+
+__all__ = ["SubscriptionChangeApplyParams"]
+
+
+class SubscriptionChangeApplyParams(TypedDict, total=False):
+ description: Optional[str]
+ """Description to apply to the balance transaction representing this credit."""
+
+ previously_collected_amount: Optional[str]
+ """Amount already collected to apply to the customer's balance."""
diff --git a/src/orb/types/subscription_change_apply_response.py b/src/orb/types/subscription_change_apply_response.py
new file mode 100644
index 00000000..625a60a7
--- /dev/null
+++ b/src/orb/types/subscription_change_apply_response.py
@@ -0,0 +1,610 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .plan import Plan
+from .price import Price
+from .._utils import PropertyInfo
+from .invoice import Invoice
+from .._models import BaseModel
+from .customer import Customer
+from .credit_note import CreditNote
+
+__all__ = [
+ "SubscriptionChangeApplyResponse",
+ "Subscription",
+ "SubscriptionAdjustmentInterval",
+ "SubscriptionAdjustmentIntervalAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment",
+ "SubscriptionBillingCycleAnchorConfiguration",
+ "SubscriptionDiscountInterval",
+ "SubscriptionDiscountIntervalAmountDiscountInterval",
+ "SubscriptionDiscountIntervalPercentageDiscountInterval",
+ "SubscriptionDiscountIntervalUsageDiscountInterval",
+ "SubscriptionFixedFeeQuantitySchedule",
+ "SubscriptionMaximumInterval",
+ "SubscriptionMinimumInterval",
+ "SubscriptionPendingSubscriptionChange",
+ "SubscriptionPriceInterval",
+ "SubscriptionPriceIntervalFixedFeeQuantityTransition",
+ "SubscriptionRedeemedCoupon",
+ "SubscriptionTrialInfo",
+ "SubscriptionChangedResources",
+]
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["usage_discount"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+ usage_discount: float
+ """
+ The number of usage units by which to discount the price this adjustment applies
+ to in a given billing period.
+ """
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["amount_discount"]
+
+ amount_discount: str
+ """
+ The amount by which to discount the prices this adjustment applies to in a given
+ billing period.
+ """
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["percentage_discount"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ percentage_discount: float
+ """
+ The percentage (as a value between 0 and 1) by which to discount the price
+ intervals this adjustment applies to in a given billing period.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["minimum"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ item_id: str
+ """The item ID that revenue from this minimum will be attributed to."""
+
+ minimum_amount: str
+ """
+ The minimum amount to charge in a given billing period for the prices this
+ adjustment applies to.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["maximum"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ maximum_amount: str
+ """
+ The maximum amount to charge in a given billing period for the prices this
+ adjustment applies to.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+SubscriptionAdjustmentIntervalAdjustment: TypeAlias = Annotated[
+ Union[
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment,
+ ],
+ PropertyInfo(discriminator="adjustment_type"),
+]
+
+
+class SubscriptionAdjustmentInterval(BaseModel):
+ id: str
+
+ adjustment: SubscriptionAdjustmentIntervalAdjustment
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval IDs that this adjustment applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the adjustment interval."""
+
+ start_date: datetime
+ """The start date of the adjustment interval."""
+
+
+class SubscriptionBillingCycleAnchorConfiguration(BaseModel):
+ day: int
+ """The day of the month on which the billing cycle is anchored.
+
+ If the maximum number of days in a month is greater than this value, the last
+ day of the month is the billing cycle day (e.g. billing_cycle_day=31 for April
+ means the billing period begins on the 30th.
+ """
+
+ month: Optional[int] = None
+ """The month on which the billing cycle is anchored (e.g.
+
+ a quarterly price anchored in February would have cycles starting February, May,
+ August, and November).
+ """
+
+ year: Optional[int] = None
+ """The year on which the billing cycle is anchored (e.g.
+
+ a 2 year billing cycle anchored on 2021 would have cycles starting on 2021,
+ 2023, 2025, etc.).
+ """
+
+
+class SubscriptionDiscountIntervalAmountDiscountInterval(BaseModel):
+ amount_discount: str
+ """Only available if discount_type is `amount`."""
+
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["amount"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+
+class SubscriptionDiscountIntervalPercentageDiscountInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["percentage"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ percentage_discount: float
+ """
+ Only available if discount_type is `percentage`.This is a number between 0
+ and 1.
+ """
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+
+class SubscriptionDiscountIntervalUsageDiscountInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["usage"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+ usage_discount: float
+ """Only available if discount_type is `usage`.
+
+ Number of usage units that this discount is for
+ """
+
+
+SubscriptionDiscountInterval: TypeAlias = Annotated[
+ Union[
+ SubscriptionDiscountIntervalAmountDiscountInterval,
+ SubscriptionDiscountIntervalPercentageDiscountInterval,
+ SubscriptionDiscountIntervalUsageDiscountInterval,
+ ],
+ PropertyInfo(discriminator="discount_type"),
+]
+
+
+class SubscriptionFixedFeeQuantitySchedule(BaseModel):
+ end_date: Optional[datetime] = None
+
+ price_id: str
+
+ quantity: float
+
+ start_date: datetime
+
+
+class SubscriptionMaximumInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this maximum interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this maximum interval applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the maximum interval."""
+
+ maximum_amount: str
+ """
+ The maximum amount to charge in a given billing period for the price intervals
+ this transform applies to.
+ """
+
+ start_date: datetime
+ """The start date of the maximum interval."""
+
+
+class SubscriptionMinimumInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this minimum interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this minimum interval applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the minimum interval."""
+
+ minimum_amount: str
+ """
+ The minimum amount to charge in a given billing period for the price intervals
+ this minimum applies to.
+ """
+
+ start_date: datetime
+ """The start date of the minimum interval."""
+
+
+class SubscriptionPendingSubscriptionChange(BaseModel):
+ id: str
+
+
+class SubscriptionPriceIntervalFixedFeeQuantityTransition(BaseModel):
+ effective_date: datetime
+
+ price_id: str
+
+ quantity: int
+
+
+class SubscriptionPriceInterval(BaseModel):
+ id: str
+
+ billing_cycle_day: int
+ """The day of the month that Orb bills for this price"""
+
+ current_billing_period_end_date: Optional[datetime] = None
+ """The end of the current billing period.
+
+ This is an exclusive timestamp, such that the instant returned is exactly the
+ end of the billing period. Set to null if this price interval is not currently
+ active.
+ """
+
+ current_billing_period_start_date: Optional[datetime] = None
+ """The start date of the current billing period.
+
+ This is an inclusive timestamp; the instant returned is exactly the beginning of
+ the billing period. Set to null if this price interval is not currently active.
+ """
+
+ end_date: Optional[datetime] = None
+ """The end date of the price interval.
+
+ This is the date that Orb stops billing for this price.
+ """
+
+ filter: Optional[str] = None
+ """An additional filter to apply to usage queries."""
+
+ fixed_fee_quantity_transitions: Optional[List[SubscriptionPriceIntervalFixedFeeQuantityTransition]] = None
+ """The fixed fee quantity transitions for this price interval.
+
+ This is only relevant for fixed fees.
+ """
+
+ price: Price
+ """
+ The Price resource represents a price that can be billed on a subscription,
+ resulting in a charge on an invoice in the form of an invoice line item. Prices
+ take a quantity and determine an amount to bill.
+
+ Orb supports a few different pricing models out of the box. Each of these models
+ is serialized differently in a given Price object. The model_type field
+ determines the key for the configuration object that is present.
+
+ For more on the types of prices, see
+ [the core concepts documentation](/core-concepts#plan-and-price)
+ """
+
+ start_date: datetime
+ """The start date of the price interval.
+
+ This is the date that Orb starts billing for this price.
+ """
+
+ usage_customer_ids: Optional[List[str]] = None
+ """
+ A list of customer IDs whose usage events will be aggregated and billed under
+ this price interval.
+ """
+
+
+class SubscriptionRedeemedCoupon(BaseModel):
+ coupon_id: str
+
+ end_date: Optional[datetime] = None
+
+ start_date: datetime
+
+
+class SubscriptionTrialInfo(BaseModel):
+ end_date: Optional[datetime] = None
+
+
+class SubscriptionChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
+class Subscription(BaseModel):
+ id: str
+
+ active_plan_phase_order: Optional[int] = None
+ """
+ The current plan phase that is active, only if the subscription's plan has
+ phases.
+ """
+
+ adjustment_intervals: List[SubscriptionAdjustmentInterval]
+ """
+ The adjustment intervals for this subscription sorted by the start_date of the
+ adjustment interval.
+ """
+
+ auto_collection: Optional[bool] = None
+ """
+ Determines whether issued invoices for this subscription will automatically be
+ charged with the saved payment method on the due date. This property defaults to
+ the plan's behavior. If null, defaults to the customer's setting.
+ """
+
+ billing_cycle_anchor_configuration: SubscriptionBillingCycleAnchorConfiguration
+
+ billing_cycle_day: int
+ """The day of the month on which the billing cycle is anchored.
+
+ If the maximum number of days in a month is greater than this value, the last
+ day of the month is the billing cycle day (e.g. billing_cycle_day=31 for April
+ means the billing period begins on the 30th.
+ """
+
+ created_at: datetime
+
+ current_billing_period_end_date: Optional[datetime] = None
+ """The end of the current billing period.
+
+ This is an exclusive timestamp, such that the instant returned is not part of
+ the billing period. Set to null for subscriptions that are not currently active.
+ """
+
+ current_billing_period_start_date: Optional[datetime] = None
+ """The start date of the current billing period.
+
+ This is an inclusive timestamp; the instant returned is exactly the beginning of
+ the billing period. Set to null if the subscription is not currently active.
+ """
+
+ customer: Customer
+ """
+ A customer is a buyer of your products, and the other party to the billing
+ relationship.
+
+ In Orb, customers are assigned system generated identifiers automatically, but
+ it's often desirable to have these match existing identifiers in your system. To
+ avoid having to denormalize Orb ID information, you can pass in an
+ `external_customer_id` with your own identifier. See
+ [Customer ID Aliases](/events-and-metrics/customer-aliases) for further
+ information about how these aliases work in Orb.
+
+ In addition to having an identifier in your system, a customer may exist in a
+ payment provider solution like Stripe. Use the `payment_provider_id` and the
+ `payment_provider` enum field to express this mapping.
+
+ A customer also has a timezone (from the standard
+ [IANA timezone database](https://www.iana.org/time-zones)), which defaults to
+ your account's timezone. See [Timezone localization](/essentials/timezones) for
+ information on what this timezone parameter influences within Orb.
+ """
+
+ default_invoice_memo: Optional[str] = None
+ """Determines the default memo on this subscriptions' invoices.
+
+ Note that if this is not provided, it is determined by the plan configuration.
+ """
+
+ discount_intervals: List[SubscriptionDiscountInterval]
+ """The discount intervals for this subscription sorted by the start_date."""
+
+ end_date: Optional[datetime] = None
+ """The date Orb stops billing for this subscription."""
+
+ fixed_fee_quantity_schedule: List[SubscriptionFixedFeeQuantitySchedule]
+
+ invoicing_threshold: Optional[str] = None
+
+ maximum_intervals: List[SubscriptionMaximumInterval]
+ """The maximum intervals for this subscription sorted by the start_date."""
+
+ metadata: Dict[str, str]
+ """User specified key-value pairs for the resource.
+
+ If not present, this defaults to an empty dictionary. Individual keys can be
+ removed by setting the value to `null`, and the entire metadata mapping can be
+ cleared by setting `metadata` to `null`.
+ """
+
+ minimum_intervals: List[SubscriptionMinimumInterval]
+ """The minimum intervals for this subscription sorted by the start_date."""
+
+ net_terms: int
+ """
+ Determines the difference between the invoice issue date for subscription
+ invoices as the date that they are due. A value of `0` here represents that the
+ invoice is due on issue, whereas a value of `30` represents that the customer
+ has a month to pay the invoice.
+ """
+
+ pending_subscription_change: Optional[SubscriptionPendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
+ plan: Plan
+ """
+ The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
+ subscribed to by a customer. Plans define the billing behavior of the
+ subscription. You can see more about how to configure prices in the
+ [Price resource](/reference/price).
+ """
+
+ price_intervals: List[SubscriptionPriceInterval]
+ """The price intervals for this subscription."""
+
+ redeemed_coupon: Optional[SubscriptionRedeemedCoupon] = None
+
+ start_date: datetime
+ """The date Orb starts billing for this subscription."""
+
+ status: Literal["active", "ended", "upcoming"]
+
+ trial_info: SubscriptionTrialInfo
+
+ changed_resources: Optional[SubscriptionChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
+
+
+class SubscriptionChangeApplyResponse(BaseModel):
+ id: str
+
+ expiration_time: datetime
+ """
+ Subscription change will be cancelled at this time and can no longer be applied.
+ """
+
+ status: Literal["pending", "applied", "cancelled"]
+
+ subscription: Optional[Subscription] = None
+
+ applied_at: Optional[datetime] = None
+ """When this change was applied."""
+
+ cancelled_at: Optional[datetime] = None
+ """When this change was cancelled."""
diff --git a/src/orb/types/subscription_change_cancel_response.py b/src/orb/types/subscription_change_cancel_response.py
new file mode 100644
index 00000000..4bb41909
--- /dev/null
+++ b/src/orb/types/subscription_change_cancel_response.py
@@ -0,0 +1,610 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .plan import Plan
+from .price import Price
+from .._utils import PropertyInfo
+from .invoice import Invoice
+from .._models import BaseModel
+from .customer import Customer
+from .credit_note import CreditNote
+
+__all__ = [
+ "SubscriptionChangeCancelResponse",
+ "Subscription",
+ "SubscriptionAdjustmentInterval",
+ "SubscriptionAdjustmentIntervalAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment",
+ "SubscriptionBillingCycleAnchorConfiguration",
+ "SubscriptionDiscountInterval",
+ "SubscriptionDiscountIntervalAmountDiscountInterval",
+ "SubscriptionDiscountIntervalPercentageDiscountInterval",
+ "SubscriptionDiscountIntervalUsageDiscountInterval",
+ "SubscriptionFixedFeeQuantitySchedule",
+ "SubscriptionMaximumInterval",
+ "SubscriptionMinimumInterval",
+ "SubscriptionPendingSubscriptionChange",
+ "SubscriptionPriceInterval",
+ "SubscriptionPriceIntervalFixedFeeQuantityTransition",
+ "SubscriptionRedeemedCoupon",
+ "SubscriptionTrialInfo",
+ "SubscriptionChangedResources",
+]
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["usage_discount"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+ usage_discount: float
+ """
+ The number of usage units by which to discount the price this adjustment applies
+ to in a given billing period.
+ """
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["amount_discount"]
+
+ amount_discount: str
+ """
+ The amount by which to discount the prices this adjustment applies to in a given
+ billing period.
+ """
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["percentage_discount"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ percentage_discount: float
+ """
+ The percentage (as a value between 0 and 1) by which to discount the price
+ intervals this adjustment applies to in a given billing period.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["minimum"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ item_id: str
+ """The item ID that revenue from this minimum will be attributed to."""
+
+ minimum_amount: str
+ """
+ The minimum amount to charge in a given billing period for the prices this
+ adjustment applies to.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["maximum"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ maximum_amount: str
+ """
+ The maximum amount to charge in a given billing period for the prices this
+ adjustment applies to.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+SubscriptionAdjustmentIntervalAdjustment: TypeAlias = Annotated[
+ Union[
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment,
+ ],
+ PropertyInfo(discriminator="adjustment_type"),
+]
+
+
+class SubscriptionAdjustmentInterval(BaseModel):
+ id: str
+
+ adjustment: SubscriptionAdjustmentIntervalAdjustment
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval IDs that this adjustment applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the adjustment interval."""
+
+ start_date: datetime
+ """The start date of the adjustment interval."""
+
+
+class SubscriptionBillingCycleAnchorConfiguration(BaseModel):
+ day: int
+ """The day of the month on which the billing cycle is anchored.
+
+ If the maximum number of days in a month is greater than this value, the last
+ day of the month is the billing cycle day (e.g. billing_cycle_day=31 for April
+ means the billing period begins on the 30th.
+ """
+
+ month: Optional[int] = None
+ """The month on which the billing cycle is anchored (e.g.
+
+ a quarterly price anchored in February would have cycles starting February, May,
+ August, and November).
+ """
+
+ year: Optional[int] = None
+ """The year on which the billing cycle is anchored (e.g.
+
+ a 2 year billing cycle anchored on 2021 would have cycles starting on 2021,
+ 2023, 2025, etc.).
+ """
+
+
+class SubscriptionDiscountIntervalAmountDiscountInterval(BaseModel):
+ amount_discount: str
+ """Only available if discount_type is `amount`."""
+
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["amount"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+
+class SubscriptionDiscountIntervalPercentageDiscountInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["percentage"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ percentage_discount: float
+ """
+ Only available if discount_type is `percentage`.This is a number between 0
+ and 1.
+ """
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+
+class SubscriptionDiscountIntervalUsageDiscountInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["usage"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+ usage_discount: float
+ """Only available if discount_type is `usage`.
+
+ Number of usage units that this discount is for
+ """
+
+
+SubscriptionDiscountInterval: TypeAlias = Annotated[
+ Union[
+ SubscriptionDiscountIntervalAmountDiscountInterval,
+ SubscriptionDiscountIntervalPercentageDiscountInterval,
+ SubscriptionDiscountIntervalUsageDiscountInterval,
+ ],
+ PropertyInfo(discriminator="discount_type"),
+]
+
+
+class SubscriptionFixedFeeQuantitySchedule(BaseModel):
+ end_date: Optional[datetime] = None
+
+ price_id: str
+
+ quantity: float
+
+ start_date: datetime
+
+
+class SubscriptionMaximumInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this maximum interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this maximum interval applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the maximum interval."""
+
+ maximum_amount: str
+ """
+ The maximum amount to charge in a given billing period for the price intervals
+ this transform applies to.
+ """
+
+ start_date: datetime
+ """The start date of the maximum interval."""
+
+
+class SubscriptionMinimumInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this minimum interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this minimum interval applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the minimum interval."""
+
+ minimum_amount: str
+ """
+ The minimum amount to charge in a given billing period for the price intervals
+ this minimum applies to.
+ """
+
+ start_date: datetime
+ """The start date of the minimum interval."""
+
+
+class SubscriptionPendingSubscriptionChange(BaseModel):
+ id: str
+
+
+class SubscriptionPriceIntervalFixedFeeQuantityTransition(BaseModel):
+ effective_date: datetime
+
+ price_id: str
+
+ quantity: int
+
+
+class SubscriptionPriceInterval(BaseModel):
+ id: str
+
+ billing_cycle_day: int
+ """The day of the month that Orb bills for this price"""
+
+ current_billing_period_end_date: Optional[datetime] = None
+ """The end of the current billing period.
+
+ This is an exclusive timestamp, such that the instant returned is exactly the
+ end of the billing period. Set to null if this price interval is not currently
+ active.
+ """
+
+ current_billing_period_start_date: Optional[datetime] = None
+ """The start date of the current billing period.
+
+ This is an inclusive timestamp; the instant returned is exactly the beginning of
+ the billing period. Set to null if this price interval is not currently active.
+ """
+
+ end_date: Optional[datetime] = None
+ """The end date of the price interval.
+
+ This is the date that Orb stops billing for this price.
+ """
+
+ filter: Optional[str] = None
+ """An additional filter to apply to usage queries."""
+
+ fixed_fee_quantity_transitions: Optional[List[SubscriptionPriceIntervalFixedFeeQuantityTransition]] = None
+ """The fixed fee quantity transitions for this price interval.
+
+ This is only relevant for fixed fees.
+ """
+
+ price: Price
+ """
+ The Price resource represents a price that can be billed on a subscription,
+ resulting in a charge on an invoice in the form of an invoice line item. Prices
+ take a quantity and determine an amount to bill.
+
+ Orb supports a few different pricing models out of the box. Each of these models
+ is serialized differently in a given Price object. The model_type field
+ determines the key for the configuration object that is present.
+
+ For more on the types of prices, see
+ [the core concepts documentation](/core-concepts#plan-and-price)
+ """
+
+ start_date: datetime
+ """The start date of the price interval.
+
+ This is the date that Orb starts billing for this price.
+ """
+
+ usage_customer_ids: Optional[List[str]] = None
+ """
+ A list of customer IDs whose usage events will be aggregated and billed under
+ this price interval.
+ """
+
+
+class SubscriptionRedeemedCoupon(BaseModel):
+ coupon_id: str
+
+ end_date: Optional[datetime] = None
+
+ start_date: datetime
+
+
+class SubscriptionTrialInfo(BaseModel):
+ end_date: Optional[datetime] = None
+
+
+class SubscriptionChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
+class Subscription(BaseModel):
+ id: str
+
+ active_plan_phase_order: Optional[int] = None
+ """
+ The current plan phase that is active, only if the subscription's plan has
+ phases.
+ """
+
+ adjustment_intervals: List[SubscriptionAdjustmentInterval]
+ """
+ The adjustment intervals for this subscription sorted by the start_date of the
+ adjustment interval.
+ """
+
+ auto_collection: Optional[bool] = None
+ """
+ Determines whether issued invoices for this subscription will automatically be
+ charged with the saved payment method on the due date. This property defaults to
+ the plan's behavior. If null, defaults to the customer's setting.
+ """
+
+ billing_cycle_anchor_configuration: SubscriptionBillingCycleAnchorConfiguration
+
+ billing_cycle_day: int
+ """The day of the month on which the billing cycle is anchored.
+
+ If the maximum number of days in a month is greater than this value, the last
+ day of the month is the billing cycle day (e.g. billing_cycle_day=31 for April
+ means the billing period begins on the 30th.
+ """
+
+ created_at: datetime
+
+ current_billing_period_end_date: Optional[datetime] = None
+ """The end of the current billing period.
+
+ This is an exclusive timestamp, such that the instant returned is not part of
+ the billing period. Set to null for subscriptions that are not currently active.
+ """
+
+ current_billing_period_start_date: Optional[datetime] = None
+ """The start date of the current billing period.
+
+ This is an inclusive timestamp; the instant returned is exactly the beginning of
+ the billing period. Set to null if the subscription is not currently active.
+ """
+
+ customer: Customer
+ """
+ A customer is a buyer of your products, and the other party to the billing
+ relationship.
+
+ In Orb, customers are assigned system generated identifiers automatically, but
+ it's often desirable to have these match existing identifiers in your system. To
+ avoid having to denormalize Orb ID information, you can pass in an
+ `external_customer_id` with your own identifier. See
+ [Customer ID Aliases](/events-and-metrics/customer-aliases) for further
+ information about how these aliases work in Orb.
+
+ In addition to having an identifier in your system, a customer may exist in a
+ payment provider solution like Stripe. Use the `payment_provider_id` and the
+ `payment_provider` enum field to express this mapping.
+
+ A customer also has a timezone (from the standard
+ [IANA timezone database](https://www.iana.org/time-zones)), which defaults to
+ your account's timezone. See [Timezone localization](/essentials/timezones) for
+ information on what this timezone parameter influences within Orb.
+ """
+
+ default_invoice_memo: Optional[str] = None
+ """Determines the default memo on this subscriptions' invoices.
+
+ Note that if this is not provided, it is determined by the plan configuration.
+ """
+
+ discount_intervals: List[SubscriptionDiscountInterval]
+ """The discount intervals for this subscription sorted by the start_date."""
+
+ end_date: Optional[datetime] = None
+ """The date Orb stops billing for this subscription."""
+
+ fixed_fee_quantity_schedule: List[SubscriptionFixedFeeQuantitySchedule]
+
+ invoicing_threshold: Optional[str] = None
+
+ maximum_intervals: List[SubscriptionMaximumInterval]
+ """The maximum intervals for this subscription sorted by the start_date."""
+
+ metadata: Dict[str, str]
+ """User specified key-value pairs for the resource.
+
+ If not present, this defaults to an empty dictionary. Individual keys can be
+ removed by setting the value to `null`, and the entire metadata mapping can be
+ cleared by setting `metadata` to `null`.
+ """
+
+ minimum_intervals: List[SubscriptionMinimumInterval]
+ """The minimum intervals for this subscription sorted by the start_date."""
+
+ net_terms: int
+ """
+ Determines the difference between the invoice issue date for subscription
+ invoices as the date that they are due. A value of `0` here represents that the
+ invoice is due on issue, whereas a value of `30` represents that the customer
+ has a month to pay the invoice.
+ """
+
+ pending_subscription_change: Optional[SubscriptionPendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
+ plan: Plan
+ """
+ The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
+ subscribed to by a customer. Plans define the billing behavior of the
+ subscription. You can see more about how to configure prices in the
+ [Price resource](/reference/price).
+ """
+
+ price_intervals: List[SubscriptionPriceInterval]
+ """The price intervals for this subscription."""
+
+ redeemed_coupon: Optional[SubscriptionRedeemedCoupon] = None
+
+ start_date: datetime
+ """The date Orb starts billing for this subscription."""
+
+ status: Literal["active", "ended", "upcoming"]
+
+ trial_info: SubscriptionTrialInfo
+
+ changed_resources: Optional[SubscriptionChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
+
+
+class SubscriptionChangeCancelResponse(BaseModel):
+ id: str
+
+ expiration_time: datetime
+ """
+ Subscription change will be cancelled at this time and can no longer be applied.
+ """
+
+ status: Literal["pending", "applied", "cancelled"]
+
+ subscription: Optional[Subscription] = None
+
+ applied_at: Optional[datetime] = None
+ """When this change was applied."""
+
+ cancelled_at: Optional[datetime] = None
+ """When this change was cancelled."""
diff --git a/src/orb/types/subscription_change_retrieve_response.py b/src/orb/types/subscription_change_retrieve_response.py
new file mode 100644
index 00000000..04068bf2
--- /dev/null
+++ b/src/orb/types/subscription_change_retrieve_response.py
@@ -0,0 +1,610 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .plan import Plan
+from .price import Price
+from .._utils import PropertyInfo
+from .invoice import Invoice
+from .._models import BaseModel
+from .customer import Customer
+from .credit_note import CreditNote
+
+__all__ = [
+ "SubscriptionChangeRetrieveResponse",
+ "Subscription",
+ "SubscriptionAdjustmentInterval",
+ "SubscriptionAdjustmentIntervalAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment",
+ "SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment",
+ "SubscriptionBillingCycleAnchorConfiguration",
+ "SubscriptionDiscountInterval",
+ "SubscriptionDiscountIntervalAmountDiscountInterval",
+ "SubscriptionDiscountIntervalPercentageDiscountInterval",
+ "SubscriptionDiscountIntervalUsageDiscountInterval",
+ "SubscriptionFixedFeeQuantitySchedule",
+ "SubscriptionMaximumInterval",
+ "SubscriptionMinimumInterval",
+ "SubscriptionPendingSubscriptionChange",
+ "SubscriptionPriceInterval",
+ "SubscriptionPriceIntervalFixedFeeQuantityTransition",
+ "SubscriptionRedeemedCoupon",
+ "SubscriptionTrialInfo",
+ "SubscriptionChangedResources",
+]
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["usage_discount"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+ usage_discount: float
+ """
+ The number of usage units by which to discount the price this adjustment applies
+ to in a given billing period.
+ """
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["amount_discount"]
+
+ amount_discount: str
+ """
+ The amount by which to discount the prices this adjustment applies to in a given
+ billing period.
+ """
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["percentage_discount"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ percentage_discount: float
+ """
+ The percentage (as a value between 0 and 1) by which to discount the price
+ intervals this adjustment applies to in a given billing period.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["minimum"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ item_id: str
+ """The item ID that revenue from this minimum will be attributed to."""
+
+ minimum_amount: str
+ """
+ The minimum amount to charge in a given billing period for the prices this
+ adjustment applies to.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+class SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment(BaseModel):
+ id: str
+
+ adjustment_type: Literal["maximum"]
+
+ applies_to_price_ids: List[str]
+ """The price IDs that this adjustment applies to."""
+
+ is_invoice_level: bool
+ """
+ True for adjustments that apply to an entire invocice, false for adjustments
+ that apply to only one price.
+ """
+
+ maximum_amount: str
+ """
+ The maximum amount to charge in a given billing period for the prices this
+ adjustment applies to.
+ """
+
+ plan_phase_order: Optional[int] = None
+ """The plan phase in which this adjustment is active."""
+
+ reason: Optional[str] = None
+ """The reason for the adjustment."""
+
+
+SubscriptionAdjustmentIntervalAdjustment: TypeAlias = Annotated[
+ Union[
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseUsageDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseAmountDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhasePercentageDiscountAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMinimumAdjustment,
+ SubscriptionAdjustmentIntervalAdjustmentPlanPhaseMaximumAdjustment,
+ ],
+ PropertyInfo(discriminator="adjustment_type"),
+]
+
+
+class SubscriptionAdjustmentInterval(BaseModel):
+ id: str
+
+ adjustment: SubscriptionAdjustmentIntervalAdjustment
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval IDs that this adjustment applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the adjustment interval."""
+
+ start_date: datetime
+ """The start date of the adjustment interval."""
+
+
+class SubscriptionBillingCycleAnchorConfiguration(BaseModel):
+ day: int
+ """The day of the month on which the billing cycle is anchored.
+
+ If the maximum number of days in a month is greater than this value, the last
+ day of the month is the billing cycle day (e.g. billing_cycle_day=31 for April
+ means the billing period begins on the 30th.
+ """
+
+ month: Optional[int] = None
+ """The month on which the billing cycle is anchored (e.g.
+
+ a quarterly price anchored in February would have cycles starting February, May,
+ August, and November).
+ """
+
+ year: Optional[int] = None
+ """The year on which the billing cycle is anchored (e.g.
+
+ a 2 year billing cycle anchored on 2021 would have cycles starting on 2021,
+ 2023, 2025, etc.).
+ """
+
+
+class SubscriptionDiscountIntervalAmountDiscountInterval(BaseModel):
+ amount_discount: str
+ """Only available if discount_type is `amount`."""
+
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["amount"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+
+class SubscriptionDiscountIntervalPercentageDiscountInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["percentage"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ percentage_discount: float
+ """
+ Only available if discount_type is `percentage`.This is a number between 0
+ and 1.
+ """
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+
+class SubscriptionDiscountIntervalUsageDiscountInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this discount interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this discount interval applies to."""
+
+ discount_type: Literal["usage"]
+
+ end_date: Optional[datetime] = None
+ """The end date of the discount interval."""
+
+ start_date: datetime
+ """The start date of the discount interval."""
+
+ usage_discount: float
+ """Only available if discount_type is `usage`.
+
+ Number of usage units that this discount is for
+ """
+
+
+SubscriptionDiscountInterval: TypeAlias = Annotated[
+ Union[
+ SubscriptionDiscountIntervalAmountDiscountInterval,
+ SubscriptionDiscountIntervalPercentageDiscountInterval,
+ SubscriptionDiscountIntervalUsageDiscountInterval,
+ ],
+ PropertyInfo(discriminator="discount_type"),
+]
+
+
+class SubscriptionFixedFeeQuantitySchedule(BaseModel):
+ end_date: Optional[datetime] = None
+
+ price_id: str
+
+ quantity: float
+
+ start_date: datetime
+
+
+class SubscriptionMaximumInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this maximum interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this maximum interval applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the maximum interval."""
+
+ maximum_amount: str
+ """
+ The maximum amount to charge in a given billing period for the price intervals
+ this transform applies to.
+ """
+
+ start_date: datetime
+ """The start date of the maximum interval."""
+
+
+class SubscriptionMinimumInterval(BaseModel):
+ applies_to_price_ids: List[str]
+ """The price ids that this minimum interval applies to."""
+
+ applies_to_price_interval_ids: List[str]
+ """The price interval ids that this minimum interval applies to."""
+
+ end_date: Optional[datetime] = None
+ """The end date of the minimum interval."""
+
+ minimum_amount: str
+ """
+ The minimum amount to charge in a given billing period for the price intervals
+ this minimum applies to.
+ """
+
+ start_date: datetime
+ """The start date of the minimum interval."""
+
+
+class SubscriptionPendingSubscriptionChange(BaseModel):
+ id: str
+
+
+class SubscriptionPriceIntervalFixedFeeQuantityTransition(BaseModel):
+ effective_date: datetime
+
+ price_id: str
+
+ quantity: int
+
+
+class SubscriptionPriceInterval(BaseModel):
+ id: str
+
+ billing_cycle_day: int
+ """The day of the month that Orb bills for this price"""
+
+ current_billing_period_end_date: Optional[datetime] = None
+ """The end of the current billing period.
+
+ This is an exclusive timestamp, such that the instant returned is exactly the
+ end of the billing period. Set to null if this price interval is not currently
+ active.
+ """
+
+ current_billing_period_start_date: Optional[datetime] = None
+ """The start date of the current billing period.
+
+ This is an inclusive timestamp; the instant returned is exactly the beginning of
+ the billing period. Set to null if this price interval is not currently active.
+ """
+
+ end_date: Optional[datetime] = None
+ """The end date of the price interval.
+
+ This is the date that Orb stops billing for this price.
+ """
+
+ filter: Optional[str] = None
+ """An additional filter to apply to usage queries."""
+
+ fixed_fee_quantity_transitions: Optional[List[SubscriptionPriceIntervalFixedFeeQuantityTransition]] = None
+ """The fixed fee quantity transitions for this price interval.
+
+ This is only relevant for fixed fees.
+ """
+
+ price: Price
+ """
+ The Price resource represents a price that can be billed on a subscription,
+ resulting in a charge on an invoice in the form of an invoice line item. Prices
+ take a quantity and determine an amount to bill.
+
+ Orb supports a few different pricing models out of the box. Each of these models
+ is serialized differently in a given Price object. The model_type field
+ determines the key for the configuration object that is present.
+
+ For more on the types of prices, see
+ [the core concepts documentation](/core-concepts#plan-and-price)
+ """
+
+ start_date: datetime
+ """The start date of the price interval.
+
+ This is the date that Orb starts billing for this price.
+ """
+
+ usage_customer_ids: Optional[List[str]] = None
+ """
+ A list of customer IDs whose usage events will be aggregated and billed under
+ this price interval.
+ """
+
+
+class SubscriptionRedeemedCoupon(BaseModel):
+ coupon_id: str
+
+ end_date: Optional[datetime] = None
+
+ start_date: datetime
+
+
+class SubscriptionTrialInfo(BaseModel):
+ end_date: Optional[datetime] = None
+
+
+class SubscriptionChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
+class Subscription(BaseModel):
+ id: str
+
+ active_plan_phase_order: Optional[int] = None
+ """
+ The current plan phase that is active, only if the subscription's plan has
+ phases.
+ """
+
+ adjustment_intervals: List[SubscriptionAdjustmentInterval]
+ """
+ The adjustment intervals for this subscription sorted by the start_date of the
+ adjustment interval.
+ """
+
+ auto_collection: Optional[bool] = None
+ """
+ Determines whether issued invoices for this subscription will automatically be
+ charged with the saved payment method on the due date. This property defaults to
+ the plan's behavior. If null, defaults to the customer's setting.
+ """
+
+ billing_cycle_anchor_configuration: SubscriptionBillingCycleAnchorConfiguration
+
+ billing_cycle_day: int
+ """The day of the month on which the billing cycle is anchored.
+
+ If the maximum number of days in a month is greater than this value, the last
+ day of the month is the billing cycle day (e.g. billing_cycle_day=31 for April
+ means the billing period begins on the 30th.
+ """
+
+ created_at: datetime
+
+ current_billing_period_end_date: Optional[datetime] = None
+ """The end of the current billing period.
+
+ This is an exclusive timestamp, such that the instant returned is not part of
+ the billing period. Set to null for subscriptions that are not currently active.
+ """
+
+ current_billing_period_start_date: Optional[datetime] = None
+ """The start date of the current billing period.
+
+ This is an inclusive timestamp; the instant returned is exactly the beginning of
+ the billing period. Set to null if the subscription is not currently active.
+ """
+
+ customer: Customer
+ """
+ A customer is a buyer of your products, and the other party to the billing
+ relationship.
+
+ In Orb, customers are assigned system generated identifiers automatically, but
+ it's often desirable to have these match existing identifiers in your system. To
+ avoid having to denormalize Orb ID information, you can pass in an
+ `external_customer_id` with your own identifier. See
+ [Customer ID Aliases](/events-and-metrics/customer-aliases) for further
+ information about how these aliases work in Orb.
+
+ In addition to having an identifier in your system, a customer may exist in a
+ payment provider solution like Stripe. Use the `payment_provider_id` and the
+ `payment_provider` enum field to express this mapping.
+
+ A customer also has a timezone (from the standard
+ [IANA timezone database](https://www.iana.org/time-zones)), which defaults to
+ your account's timezone. See [Timezone localization](/essentials/timezones) for
+ information on what this timezone parameter influences within Orb.
+ """
+
+ default_invoice_memo: Optional[str] = None
+ """Determines the default memo on this subscriptions' invoices.
+
+ Note that if this is not provided, it is determined by the plan configuration.
+ """
+
+ discount_intervals: List[SubscriptionDiscountInterval]
+ """The discount intervals for this subscription sorted by the start_date."""
+
+ end_date: Optional[datetime] = None
+ """The date Orb stops billing for this subscription."""
+
+ fixed_fee_quantity_schedule: List[SubscriptionFixedFeeQuantitySchedule]
+
+ invoicing_threshold: Optional[str] = None
+
+ maximum_intervals: List[SubscriptionMaximumInterval]
+ """The maximum intervals for this subscription sorted by the start_date."""
+
+ metadata: Dict[str, str]
+ """User specified key-value pairs for the resource.
+
+ If not present, this defaults to an empty dictionary. Individual keys can be
+ removed by setting the value to `null`, and the entire metadata mapping can be
+ cleared by setting `metadata` to `null`.
+ """
+
+ minimum_intervals: List[SubscriptionMinimumInterval]
+ """The minimum intervals for this subscription sorted by the start_date."""
+
+ net_terms: int
+ """
+ Determines the difference between the invoice issue date for subscription
+ invoices as the date that they are due. A value of `0` here represents that the
+ invoice is due on issue, whereas a value of `30` represents that the customer
+ has a month to pay the invoice.
+ """
+
+ pending_subscription_change: Optional[SubscriptionPendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
+ plan: Plan
+ """
+ The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
+ subscribed to by a customer. Plans define the billing behavior of the
+ subscription. You can see more about how to configure prices in the
+ [Price resource](/reference/price).
+ """
+
+ price_intervals: List[SubscriptionPriceInterval]
+ """The price intervals for this subscription."""
+
+ redeemed_coupon: Optional[SubscriptionRedeemedCoupon] = None
+
+ start_date: datetime
+ """The date Orb starts billing for this subscription."""
+
+ status: Literal["active", "ended", "upcoming"]
+
+ trial_info: SubscriptionTrialInfo
+
+ changed_resources: Optional[SubscriptionChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
+
+
+class SubscriptionChangeRetrieveResponse(BaseModel):
+ id: str
+
+ expiration_time: datetime
+ """
+ Subscription change will be cancelled at this time and can no longer be applied.
+ """
+
+ status: Literal["pending", "applied", "cancelled"]
+
+ subscription: Optional[Subscription] = None
+
+ applied_at: Optional[datetime] = None
+ """When this change was applied."""
+
+ cancelled_at: Optional[datetime] = None
+ """When this change was cancelled."""
diff --git a/src/orb/types/subscription_create_params.py b/src/orb/types/subscription_create_params.py
index 1caf93ce..cf34ff18 100644
--- a/src/orb/types/subscription_create_params.py
+++ b/src/orb/types/subscription_create_params.py
@@ -829,13 +829,13 @@ class AddPricePriceNewSubscriptionMatrixPrice(TypedDict, total=False):
class AddPricePriceNewSubscriptionTieredPriceTieredConfigTier(TypedDict, total=False):
first_unit: Required[float]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: Required[str]
"""Amount per unit"""
last_unit: Optional[float]
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class AddPricePriceNewSubscriptionTieredPriceTieredConfig(TypedDict, total=False):
@@ -937,10 +937,10 @@ class AddPricePriceNewSubscriptionTieredBpsPriceTieredBpsConfigTier(TypedDict, t
"""Per-event basis point rate"""
minimum_amount: Required[str]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str]
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str]
"""Per unit maximum to charge"""
@@ -3473,13 +3473,13 @@ class ReplacePricePriceNewSubscriptionMatrixPrice(TypedDict, total=False):
class ReplacePricePriceNewSubscriptionTieredPriceTieredConfigTier(TypedDict, total=False):
first_unit: Required[float]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: Required[str]
"""Amount per unit"""
last_unit: Optional[float]
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class ReplacePricePriceNewSubscriptionTieredPriceTieredConfig(TypedDict, total=False):
@@ -3581,10 +3581,10 @@ class ReplacePricePriceNewSubscriptionTieredBpsPriceTieredBpsConfigTier(TypedDic
"""Per-event basis point rate"""
minimum_amount: Required[str]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str]
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str]
"""Per unit maximum to charge"""
diff --git a/src/orb/types/subscription_create_response.py b/src/orb/types/subscription_create_response.py
index ab422df8..485dae87 100644
--- a/src/orb/types/subscription_create_response.py
+++ b/src/orb/types/subscription_create_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionCreateResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionCreateResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionCreateResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionCreateResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_price_intervals_params.py b/src/orb/types/subscription_price_intervals_params.py
index ce28d218..b2b29880 100644
--- a/src/orb/types/subscription_price_intervals_params.py
+++ b/src/orb/types/subscription_price_intervals_params.py
@@ -602,13 +602,13 @@ class AddPriceNewFloatingMatrixWithAllocationPrice(TypedDict, total=False):
class AddPriceNewFloatingTieredPriceTieredConfigTier(TypedDict, total=False):
first_unit: Required[float]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: Required[str]
"""Amount per unit"""
last_unit: Optional[float]
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class AddPriceNewFloatingTieredPriceTieredConfig(TypedDict, total=False):
@@ -701,10 +701,10 @@ class AddPriceNewFloatingTieredBpsPriceTieredBpsConfigTier(TypedDict, total=Fals
"""Per-event basis point rate"""
minimum_amount: Required[str]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str]
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str]
"""Per unit maximum to charge"""
diff --git a/src/orb/types/subscription_price_intervals_response.py b/src/orb/types/subscription_price_intervals_response.py
index b2652d91..0cea78b4 100644
--- a/src/orb/types/subscription_price_intervals_response.py
+++ b/src/orb/types/subscription_price_intervals_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionPriceIntervalsResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionPriceIntervalsResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionPriceIntervalsResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionPriceIntervalsResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_schedule_plan_change_params.py b/src/orb/types/subscription_schedule_plan_change_params.py
index 2961e733..ef1afbc4 100644
--- a/src/orb/types/subscription_schedule_plan_change_params.py
+++ b/src/orb/types/subscription_schedule_plan_change_params.py
@@ -829,13 +829,13 @@ class AddPricePriceNewSubscriptionMatrixPrice(TypedDict, total=False):
class AddPricePriceNewSubscriptionTieredPriceTieredConfigTier(TypedDict, total=False):
first_unit: Required[float]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: Required[str]
"""Amount per unit"""
last_unit: Optional[float]
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class AddPricePriceNewSubscriptionTieredPriceTieredConfig(TypedDict, total=False):
@@ -937,10 +937,10 @@ class AddPricePriceNewSubscriptionTieredBpsPriceTieredBpsConfigTier(TypedDict, t
"""Per-event basis point rate"""
minimum_amount: Required[str]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str]
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str]
"""Per unit maximum to charge"""
@@ -3473,13 +3473,13 @@ class ReplacePricePriceNewSubscriptionMatrixPrice(TypedDict, total=False):
class ReplacePricePriceNewSubscriptionTieredPriceTieredConfigTier(TypedDict, total=False):
first_unit: Required[float]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
unit_amount: Required[str]
"""Amount per unit"""
last_unit: Optional[float]
- """Exclusive tier ending value. If null, this is treated as the last tier"""
+ """Inclusive tier ending value. If null, this is treated as the last tier"""
class ReplacePricePriceNewSubscriptionTieredPriceTieredConfig(TypedDict, total=False):
@@ -3581,10 +3581,10 @@ class ReplacePricePriceNewSubscriptionTieredBpsPriceTieredBpsConfigTier(TypedDic
"""Per-event basis point rate"""
minimum_amount: Required[str]
- """Inclusive tier starting value"""
+ """Exclusive tier starting value"""
maximum_amount: Optional[str]
- """Exclusive tier ending value"""
+ """Inclusive tier ending value"""
per_unit_maximum: Optional[str]
"""Per unit maximum to charge"""
diff --git a/src/orb/types/subscription_schedule_plan_change_response.py b/src/orb/types/subscription_schedule_plan_change_response.py
index 669fe675..5bcadf14 100644
--- a/src/orb/types/subscription_schedule_plan_change_response.py
+++ b/src/orb/types/subscription_schedule_plan_change_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionSchedulePlanChangeResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionSchedulePlanChangeResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionSchedulePlanChangeResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionSchedulePlanChangeResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_trigger_phase_response.py b/src/orb/types/subscription_trigger_phase_response.py
index 55c038c5..bab4f432 100644
--- a/src/orb/types/subscription_trigger_phase_response.py
+++ b/src/orb/types/subscription_trigger_phase_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionTriggerPhaseResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionTriggerPhaseResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionTriggerPhaseResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionTriggerPhaseResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_unschedule_cancellation_response.py b/src/orb/types/subscription_unschedule_cancellation_response.py
index a6629fd9..beca6a53 100644
--- a/src/orb/types/subscription_unschedule_cancellation_response.py
+++ b/src/orb/types/subscription_unschedule_cancellation_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionUnscheduleCancellationResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionUnscheduleCancellationResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionUnscheduleCancellationResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionUnscheduleCancellationResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_unschedule_fixed_fee_quantity_updates_response.py b/src/orb/types/subscription_unschedule_fixed_fee_quantity_updates_response.py
index 910e45d4..d17a4423 100644
--- a/src/orb/types/subscription_unschedule_fixed_fee_quantity_updates_response.py
+++ b/src/orb/types/subscription_unschedule_fixed_fee_quantity_updates_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionUnscheduleFixedFeeQuantityUpdatesResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionUnscheduleFixedFeeQuantityUpdatesResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionUnscheduleFixedFeeQuantityUpdatesResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionUnscheduleFixedFeeQuantityUpdatesResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_unschedule_pending_plan_changes_response.py b/src/orb/types/subscription_unschedule_pending_plan_changes_response.py
index 9d7342a9..96a76755 100644
--- a/src/orb/types/subscription_unschedule_pending_plan_changes_response.py
+++ b/src/orb/types/subscription_unschedule_pending_plan_changes_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionUnschedulePendingPlanChangesResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionUnschedulePendingPlanChangesResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionUnschedulePendingPlanChangesResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionUnschedulePendingPlanChangesResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_update_fixed_fee_quantity_response.py b/src/orb/types/subscription_update_fixed_fee_quantity_response.py
index 74110564..2b86b5c4 100644
--- a/src/orb/types/subscription_update_fixed_fee_quantity_response.py
+++ b/src/orb/types/subscription_update_fixed_fee_quantity_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionUpdateFixedFeeQuantityResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionUpdateFixedFeeQuantityResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionUpdateFixedFeeQuantityResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionUpdateFixedFeeQuantityResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/src/orb/types/subscription_update_trial_response.py b/src/orb/types/subscription_update_trial_response.py
index 2b8ae20e..53e38304 100644
--- a/src/orb/types/subscription_update_trial_response.py
+++ b/src/orb/types/subscription_update_trial_response.py
@@ -7,8 +7,10 @@
from .plan import Plan
from .price import Price
from .._utils import PropertyInfo
+from .invoice import Invoice
from .._models import BaseModel
from .customer import Customer
+from .credit_note import CreditNote
__all__ = [
"SubscriptionUpdateTrialResponse",
@@ -27,10 +29,12 @@
"FixedFeeQuantitySchedule",
"MaximumInterval",
"MinimumInterval",
+ "PendingSubscriptionChange",
"PriceInterval",
"PriceIntervalFixedFeeQuantityTransition",
"RedeemedCoupon",
"TrialInfo",
+ "ChangedResources",
]
@@ -346,6 +350,10 @@ class MinimumInterval(BaseModel):
"""The start date of the minimum interval."""
+class PendingSubscriptionChange(BaseModel):
+ id: str
+
+
class PriceIntervalFixedFeeQuantityTransition(BaseModel):
effective_date: datetime
@@ -429,6 +437,20 @@ class TrialInfo(BaseModel):
end_date: Optional[datetime] = None
+class ChangedResources(BaseModel):
+ created_credit_notes: List[CreditNote]
+ """The credit notes that were created as part of this operation."""
+
+ created_invoices: List[Invoice]
+ """The invoices that were created as part of this operation."""
+
+ voided_credit_notes: List[CreditNote]
+ """The credit notes that were voided as part of this operation."""
+
+ voided_invoices: List[Invoice]
+ """The invoices that were voided as part of this operation."""
+
+
class SubscriptionUpdateTrialResponse(BaseModel):
id: str
@@ -537,6 +559,9 @@ class SubscriptionUpdateTrialResponse(BaseModel):
has a month to pay the invoice.
"""
+ pending_subscription_change: Optional[PendingSubscriptionChange] = None
+ """A pending subscription change if one exists on this subscription."""
+
plan: Plan
"""
The [Plan](/core-concepts#plan-and-price) resource represents a plan that can be
@@ -556,3 +581,10 @@ class SubscriptionUpdateTrialResponse(BaseModel):
status: Literal["active", "ended", "upcoming"]
trial_info: TrialInfo
+
+ changed_resources: Optional[ChangedResources] = None
+ """The resources that were changed as part of this operation.
+
+ Only present when fetched through the subscription changes API or if the
+ `include_changed_resources` parameter was passed in the request.
+ """
diff --git a/tests/api_resources/test_subscription_changes.py b/tests/api_resources/test_subscription_changes.py
new file mode 100644
index 00000000..c362679e
--- /dev/null
+++ b/tests/api_resources/test_subscription_changes.py
@@ -0,0 +1,284 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, cast
+
+import pytest
+
+from orb import Orb, AsyncOrb
+from orb.types import (
+ SubscriptionChangeApplyResponse,
+ SubscriptionChangeCancelResponse,
+ SubscriptionChangeRetrieveResponse,
+)
+from tests.utils import assert_matches_type
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestSubscriptionChanges:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_retrieve(self, client: Orb) -> None:
+ subscription_change = client.subscription_changes.retrieve(
+ "subscription_change_id",
+ )
+ assert_matches_type(SubscriptionChangeRetrieveResponse, subscription_change, path=["response"])
+
+ @parametrize
+ def test_raw_response_retrieve(self, client: Orb) -> None:
+ response = client.subscription_changes.with_raw_response.retrieve(
+ "subscription_change_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeRetrieveResponse, subscription_change, path=["response"])
+
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Orb) -> None:
+ with client.subscription_changes.with_streaming_response.retrieve(
+ "subscription_change_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeRetrieveResponse, subscription_change, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_retrieve(self, client: Orb) -> None:
+ with pytest.raises(
+ ValueError, match=r"Expected a non-empty value for `subscription_change_id` but received ''"
+ ):
+ client.subscription_changes.with_raw_response.retrieve(
+ "",
+ )
+
+ @parametrize
+ def test_method_apply(self, client: Orb) -> None:
+ subscription_change = client.subscription_changes.apply(
+ subscription_change_id="subscription_change_id",
+ )
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ @parametrize
+ def test_method_apply_with_all_params(self, client: Orb) -> None:
+ subscription_change = client.subscription_changes.apply(
+ subscription_change_id="subscription_change_id",
+ description="description",
+ previously_collected_amount="previously_collected_amount",
+ )
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ @parametrize
+ def test_raw_response_apply(self, client: Orb) -> None:
+ response = client.subscription_changes.with_raw_response.apply(
+ subscription_change_id="subscription_change_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ @parametrize
+ def test_streaming_response_apply(self, client: Orb) -> None:
+ with client.subscription_changes.with_streaming_response.apply(
+ subscription_change_id="subscription_change_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_apply(self, client: Orb) -> None:
+ with pytest.raises(
+ ValueError, match=r"Expected a non-empty value for `subscription_change_id` but received ''"
+ ):
+ client.subscription_changes.with_raw_response.apply(
+ subscription_change_id="",
+ )
+
+ @parametrize
+ def test_method_cancel(self, client: Orb) -> None:
+ subscription_change = client.subscription_changes.cancel(
+ "subscription_change_id",
+ )
+ assert_matches_type(SubscriptionChangeCancelResponse, subscription_change, path=["response"])
+
+ @parametrize
+ def test_raw_response_cancel(self, client: Orb) -> None:
+ response = client.subscription_changes.with_raw_response.cancel(
+ "subscription_change_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeCancelResponse, subscription_change, path=["response"])
+
+ @parametrize
+ def test_streaming_response_cancel(self, client: Orb) -> None:
+ with client.subscription_changes.with_streaming_response.cancel(
+ "subscription_change_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeCancelResponse, subscription_change, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_cancel(self, client: Orb) -> None:
+ with pytest.raises(
+ ValueError, match=r"Expected a non-empty value for `subscription_change_id` but received ''"
+ ):
+ client.subscription_changes.with_raw_response.cancel(
+ "",
+ )
+
+
+class TestAsyncSubscriptionChanges:
+ parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncOrb) -> None:
+ subscription_change = await async_client.subscription_changes.retrieve(
+ "subscription_change_id",
+ )
+ assert_matches_type(SubscriptionChangeRetrieveResponse, subscription_change, path=["response"])
+
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncOrb) -> None:
+ response = await async_client.subscription_changes.with_raw_response.retrieve(
+ "subscription_change_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeRetrieveResponse, subscription_change, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncOrb) -> None:
+ async with async_client.subscription_changes.with_streaming_response.retrieve(
+ "subscription_change_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ subscription_change = await response.parse()
+ assert_matches_type(SubscriptionChangeRetrieveResponse, subscription_change, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncOrb) -> None:
+ with pytest.raises(
+ ValueError, match=r"Expected a non-empty value for `subscription_change_id` but received ''"
+ ):
+ await async_client.subscription_changes.with_raw_response.retrieve(
+ "",
+ )
+
+ @parametrize
+ async def test_method_apply(self, async_client: AsyncOrb) -> None:
+ subscription_change = await async_client.subscription_changes.apply(
+ subscription_change_id="subscription_change_id",
+ )
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ @parametrize
+ async def test_method_apply_with_all_params(self, async_client: AsyncOrb) -> None:
+ subscription_change = await async_client.subscription_changes.apply(
+ subscription_change_id="subscription_change_id",
+ description="description",
+ previously_collected_amount="previously_collected_amount",
+ )
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ @parametrize
+ async def test_raw_response_apply(self, async_client: AsyncOrb) -> None:
+ response = await async_client.subscription_changes.with_raw_response.apply(
+ subscription_change_id="subscription_change_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_apply(self, async_client: AsyncOrb) -> None:
+ async with async_client.subscription_changes.with_streaming_response.apply(
+ subscription_change_id="subscription_change_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ subscription_change = await response.parse()
+ assert_matches_type(SubscriptionChangeApplyResponse, subscription_change, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_apply(self, async_client: AsyncOrb) -> None:
+ with pytest.raises(
+ ValueError, match=r"Expected a non-empty value for `subscription_change_id` but received ''"
+ ):
+ await async_client.subscription_changes.with_raw_response.apply(
+ subscription_change_id="",
+ )
+
+ @parametrize
+ async def test_method_cancel(self, async_client: AsyncOrb) -> None:
+ subscription_change = await async_client.subscription_changes.cancel(
+ "subscription_change_id",
+ )
+ assert_matches_type(SubscriptionChangeCancelResponse, subscription_change, path=["response"])
+
+ @parametrize
+ async def test_raw_response_cancel(self, async_client: AsyncOrb) -> None:
+ response = await async_client.subscription_changes.with_raw_response.cancel(
+ "subscription_change_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ subscription_change = response.parse()
+ assert_matches_type(SubscriptionChangeCancelResponse, subscription_change, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_cancel(self, async_client: AsyncOrb) -> None:
+ async with async_client.subscription_changes.with_streaming_response.cancel(
+ "subscription_change_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ subscription_change = await response.parse()
+ assert_matches_type(SubscriptionChangeCancelResponse, subscription_change, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_cancel(self, async_client: AsyncOrb) -> None:
+ with pytest.raises(
+ ValueError, match=r"Expected a non-empty value for `subscription_change_id` but received ''"
+ ):
+ await async_client.subscription_changes.with_raw_response.cancel(
+ "",
+ )
diff --git a/tests/api_resources/test_subscriptions.py b/tests/api_resources/test_subscriptions.py
index dbd2dc56..1235356b 100644
--- a/tests/api_resources/test_subscriptions.py
+++ b/tests/api_resources/test_subscriptions.py
@@ -59,7 +59,7 @@ def test_method_create_with_all_params(self, client: Orb) -> None:
{
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -153,7 +153,7 @@ def test_method_create_with_all_params(self, client: Orb) -> None:
"replaces_price_id": "replaces_price_id",
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -580,7 +580,7 @@ def test_method_price_intervals_with_all_params(self, client: Orb) -> None:
"start_date": parse_datetime("2019-12-27T18:11:19.117Z"),
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -731,7 +731,7 @@ def test_method_schedule_plan_change_with_all_params(self, client: Orb) -> None:
{
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -820,7 +820,7 @@ def test_method_schedule_plan_change_with_all_params(self, client: Orb) -> None:
"replaces_price_id": "replaces_price_id",
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -1205,7 +1205,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOrb) -> No
{
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -1299,7 +1299,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncOrb) -> No
"replaces_price_id": "replaces_price_id",
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -1726,7 +1726,7 @@ async def test_method_price_intervals_with_all_params(self, async_client: AsyncO
"start_date": parse_datetime("2019-12-27T18:11:19.117Z"),
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -1877,7 +1877,7 @@ async def test_method_schedule_plan_change_with_all_params(self, async_client: A
{
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
@@ -1966,7 +1966,7 @@ async def test_method_schedule_plan_change_with_all_params(self, async_client: A
"replaces_price_id": "replaces_price_id",
"allocation_price": {
"amount": "10.00",
- "cadence": "one_time",
+ "cadence": "monthly",
"currency": "USD",
"expires_at_end_of_cadence": True,
},
diff --git a/tests/test_transform.py b/tests/test_transform.py
index dd25243b..c505b930 100644
--- a/tests/test_transform.py
+++ b/tests/test_transform.py
@@ -432,3 +432,15 @@ async def test_base64_file_input(use_async: bool) -> None:
assert await transform({"foo": io.BytesIO(b"Hello, world!")}, TypedDictBase64Input, use_async) == {
"foo": "SGVsbG8sIHdvcmxkIQ=="
} # type: ignore[comparison-overlap]
+
+
+@parametrize
+@pytest.mark.asyncio
+async def test_transform_skipping(use_async: bool) -> None:
+ # lists of ints are left as-is
+ data = [1, 2, 3]
+ assert await transform(data, List[int], use_async) is data
+
+ # iterables of ints are converted to a list
+ data = iter([1, 2, 3])
+ assert await transform(data, Iterable[int], use_async) == [1, 2, 3]