diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eefc48e..7234cce 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,12 +1,14 @@
name: CI
on:
push:
- branches-ignore:
- - 'generated'
- - 'codegen/**'
- - 'integrated/**'
- - 'stl-preview-head/**'
- - 'stl-preview-base/**'
+ branches:
+ - '**'
+ - '!integrated/**'
+ - '!stl-preview-head/**'
+ - '!stl-preview-base/**'
+ - '!generated'
+ - '!codegen/**'
+ - 'codegen/stl/**'
pull_request:
branches-ignore:
- 'stl-preview-head/**'
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 09a565d..9682ed8 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.0.34"
+ ".": "0.0.35"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index d46615a..c2e464b 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 181
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-b6e1387ac58f903f887eae989de30273824663a9a752e7834b82b1036950c3d2.yml
-openapi_spec_hash: 0bea29a304f3d57c44cc186478bef054
-config_hash: 7e9d4f2abf58b7918a0e103387d2a2e9
+configured_endpoints: 191
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-97e920db587b07c064bef1bf31de5e110a3750ddfddc8fca26642e79e6b827f8.yml
+openapi_spec_hash: 97ca16cc55271602443a4329d1e02895
+config_hash: 1a836d20bb988f001cc66d1526f71306
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 763b2f1..0c02743 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,27 @@
# Changelog
+## 0.0.35 (2026-03-18)
+
+Full Changelog: [v0.0.34...v0.0.35](https://github.com/whopio/whopsdk-python/compare/v0.0.34...v0.0.35)
+
+### Features
+
+* **api:** api update ([8a74bd2](https://github.com/whopio/whopsdk-python/commit/8a74bd28a45ae766a17d696a405ec2dcd5f4918a))
+* **api:** api update ([c9dd73f](https://github.com/whopio/whopsdk-python/commit/c9dd73fece709c673b37575a2e1e82ca9643f7d9))
+* **api:** api update ([41811c0](https://github.com/whopio/whopsdk-python/commit/41811c0aec1d7d07b0e7450c810a2b2e5ca03fcb))
+* **api:** manual updates ([9506c84](https://github.com/whopio/whopsdk-python/commit/9506c84dd2836cf9b150e999840b79d82517046f))
+
+
+### Bug Fixes
+
+* **deps:** bump minimum typing-extensions version ([52face0](https://github.com/whopio/whopsdk-python/commit/52face04bba526f4c009caa1dcc390d84da60840))
+* **pydantic:** do not pass `by_alias` unless set ([23cb493](https://github.com/whopio/whopsdk-python/commit/23cb4936ab4f00829d98f0a910e26f2ae26e5398))
+
+
+### Chores
+
+* **internal:** tweak CI branches ([ca6b4cd](https://github.com/whopio/whopsdk-python/commit/ca6b4cd8b46e7de115b37c833da3c40f87ca779a))
+
## 0.0.34 (2026-03-13)
Full Changelog: [v0.0.33...v0.0.34](https://github.com/whopio/whopsdk-python/compare/v0.0.33...v0.0.34)
diff --git a/api.md b/api.md
index bf78cc0..60f2181 100644
--- a/api.md
+++ b/api.md
@@ -849,7 +849,7 @@ Methods:
Types:
```python
-from whop_sdk.types import AIChat, AIChatListResponse, AIChatDeleteResponse
+from whop_sdk.types import AIChat, NotificationPreferences, AIChatListResponse, AIChatDeleteResponse
```
Methods:
@@ -921,3 +921,52 @@ from whop_sdk.types import PayoutAccountCalculatedStatuses, PayoutAccountRetriev
Methods:
- client.payout_accounts.retrieve(id) -> PayoutAccountRetrieveResponse
+
+# Affiliates
+
+Types:
+
+```python
+from whop_sdk.types import (
+ Affiliate,
+ Status,
+ AffiliateListResponse,
+ AffiliateArchiveResponse,
+ AffiliateUnarchiveResponse,
+)
+```
+
+Methods:
+
+- client.affiliates.create(\*\*params) -> Affiliate
+- client.affiliates.retrieve(id) -> Affiliate
+- client.affiliates.list(\*\*params) -> SyncCursorPage[AffiliateListResponse]
+- client.affiliates.archive(id) -> AffiliateArchiveResponse
+- client.affiliates.unarchive(id) -> AffiliateUnarchiveResponse
+
+## Overrides
+
+Types:
+
+```python
+from whop_sdk.types.affiliates import (
+ AffiliateAppliesToPayments,
+ AffiliateAppliesToProducts,
+ AffiliateOverrideRoles,
+ AffiliatePayoutTypes,
+ AffiliateRevenueBases,
+ OverrideCreateResponse,
+ OverrideRetrieveResponse,
+ OverrideUpdateResponse,
+ OverrideListResponse,
+ OverrideDeleteResponse,
+)
+```
+
+Methods:
+
+- client.affiliates.overrides.create(path_id, \*\*params) -> OverrideCreateResponse
+- client.affiliates.overrides.retrieve(override_id, \*, id) -> OverrideRetrieveResponse
+- client.affiliates.overrides.update(override_id, \*, id, \*\*params) -> OverrideUpdateResponse
+- client.affiliates.overrides.list(id, \*\*params) -> SyncCursorPage[OverrideListResponse]
+- client.affiliates.overrides.delete(override_id, \*, id) -> OverrideDeleteResponse
diff --git a/pyproject.toml b/pyproject.toml
index 6d34f6e..062c3d4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "whop-sdk"
-version = "0.0.34"
+version = "0.0.35"
description = "The official Python library for the Whop API"
dynamic = ["readme"]
license = "Apache-2.0"
@@ -11,7 +11,7 @@ authors = [
dependencies = [
"httpx>=0.23.0, <1",
"pydantic>=1.9.0, <3",
- "typing-extensions>=4.10, <5",
+ "typing-extensions>=4.14, <5",
"anyio>=3.5.0, <5",
"distro>=1.7.0, <2",
"sniffio",
diff --git a/src/whop_sdk/_client.py b/src/whop_sdk/_client.py
index 0f28664..98fa7ac 100644
--- a/src/whop_sdk/_client.py
+++ b/src/whop_sdk/_client.py
@@ -55,6 +55,7 @@
reactions,
shipments,
transfers,
+ affiliates,
app_builds,
dm_members,
dm_channels,
@@ -133,6 +134,7 @@
from .resources.payout_accounts import PayoutAccountsResource, AsyncPayoutAccountsResource
from .resources.authorized_users import AuthorizedUsersResource, AsyncAuthorizedUsersResource
from .resources.support_channels import SupportChannelsResource, AsyncSupportChannelsResource
+ from .resources.affiliates.affiliates import AffiliatesResource, AsyncAffiliatesResource
from .resources.checkout_configurations import CheckoutConfigurationsResource, AsyncCheckoutConfigurationsResource
from .resources.resolution_center_cases import ResolutionCenterCasesResource, AsyncResolutionCenterCasesResource
from .resources.company_token_transactions import (
@@ -531,6 +533,13 @@ def payout_accounts(self) -> PayoutAccountsResource:
return PayoutAccountsResource(self)
+ @cached_property
+ def affiliates(self) -> AffiliatesResource:
+ """Affiliates"""
+ from .resources.affiliates import AffiliatesResource
+
+ return AffiliatesResource(self)
+
@cached_property
def with_raw_response(self) -> WhopWithRawResponse:
return WhopWithRawResponse(self)
@@ -1033,6 +1042,13 @@ def payout_accounts(self) -> AsyncPayoutAccountsResource:
return AsyncPayoutAccountsResource(self)
+ @cached_property
+ def affiliates(self) -> AsyncAffiliatesResource:
+ """Affiliates"""
+ from .resources.affiliates import AsyncAffiliatesResource
+
+ return AsyncAffiliatesResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncWhopWithRawResponse:
return AsyncWhopWithRawResponse(self)
@@ -1471,6 +1487,13 @@ def payout_accounts(self) -> payout_accounts.PayoutAccountsResourceWithRawRespon
return PayoutAccountsResourceWithRawResponse(self._client.payout_accounts)
+ @cached_property
+ def affiliates(self) -> affiliates.AffiliatesResourceWithRawResponse:
+ """Affiliates"""
+ from .resources.affiliates import AffiliatesResourceWithRawResponse
+
+ return AffiliatesResourceWithRawResponse(self._client.affiliates)
+
class AsyncWhopWithRawResponse:
_client: AsyncWhop
@@ -1796,6 +1819,13 @@ def payout_accounts(self) -> payout_accounts.AsyncPayoutAccountsResourceWithRawR
return AsyncPayoutAccountsResourceWithRawResponse(self._client.payout_accounts)
+ @cached_property
+ def affiliates(self) -> affiliates.AsyncAffiliatesResourceWithRawResponse:
+ """Affiliates"""
+ from .resources.affiliates import AsyncAffiliatesResourceWithRawResponse
+
+ return AsyncAffiliatesResourceWithRawResponse(self._client.affiliates)
+
class WhopWithStreamedResponse:
_client: Whop
@@ -2121,6 +2151,13 @@ def payout_accounts(self) -> payout_accounts.PayoutAccountsResourceWithStreaming
return PayoutAccountsResourceWithStreamingResponse(self._client.payout_accounts)
+ @cached_property
+ def affiliates(self) -> affiliates.AffiliatesResourceWithStreamingResponse:
+ """Affiliates"""
+ from .resources.affiliates import AffiliatesResourceWithStreamingResponse
+
+ return AffiliatesResourceWithStreamingResponse(self._client.affiliates)
+
class AsyncWhopWithStreamedResponse:
_client: AsyncWhop
@@ -2450,6 +2487,13 @@ def payout_accounts(self) -> payout_accounts.AsyncPayoutAccountsResourceWithStre
return AsyncPayoutAccountsResourceWithStreamingResponse(self._client.payout_accounts)
+ @cached_property
+ def affiliates(self) -> affiliates.AsyncAffiliatesResourceWithStreamingResponse:
+ """Affiliates"""
+ from .resources.affiliates import AsyncAffiliatesResourceWithStreamingResponse
+
+ return AsyncAffiliatesResourceWithStreamingResponse(self._client.affiliates)
+
Client = Whop
diff --git a/src/whop_sdk/_compat.py b/src/whop_sdk/_compat.py
index 786ff42..e6690a4 100644
--- a/src/whop_sdk/_compat.py
+++ b/src/whop_sdk/_compat.py
@@ -2,7 +2,7 @@
from typing import TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, cast, overload
from datetime import date, datetime
-from typing_extensions import Self, Literal
+from typing_extensions import Self, Literal, TypedDict
import pydantic
from pydantic.fields import FieldInfo
@@ -131,6 +131,10 @@ def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str:
return model.model_dump_json(indent=indent)
+class _ModelDumpKwargs(TypedDict, total=False):
+ by_alias: bool
+
+
def model_dump(
model: pydantic.BaseModel,
*,
@@ -142,6 +146,9 @@ def model_dump(
by_alias: bool | None = None,
) -> dict[str, Any]:
if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
+ kwargs: _ModelDumpKwargs = {}
+ if by_alias is not None:
+ kwargs["by_alias"] = by_alias
return model.model_dump(
mode=mode,
exclude=exclude,
@@ -149,7 +156,7 @@ def model_dump(
exclude_defaults=exclude_defaults,
# warnings are not supported in Pydantic v1
warnings=True if PYDANTIC_V1 else warnings,
- by_alias=by_alias,
+ **kwargs,
)
return cast(
"dict[str, Any]",
diff --git a/src/whop_sdk/_version.py b/src/whop_sdk/_version.py
index 75c990c..057036e 100644
--- a/src/whop_sdk/_version.py
+++ b/src/whop_sdk/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "whop_sdk"
-__version__ = "0.0.34" # x-release-please-version
+__version__ = "0.0.35" # x-release-please-version
diff --git a/src/whop_sdk/resources/__init__.py b/src/whop_sdk/resources/__init__.py
index 9d6f232..e95bf53 100644
--- a/src/whop_sdk/resources/__init__.py
+++ b/src/whop_sdk/resources/__init__.py
@@ -184,6 +184,14 @@
TransfersResourceWithStreamingResponse,
AsyncTransfersResourceWithStreamingResponse,
)
+from .affiliates import (
+ AffiliatesResource,
+ AsyncAffiliatesResource,
+ AffiliatesResourceWithRawResponse,
+ AsyncAffiliatesResourceWithRawResponse,
+ AffiliatesResourceWithStreamingResponse,
+ AsyncAffiliatesResourceWithStreamingResponse,
+)
from .app_builds import (
AppBuildsResource,
AsyncAppBuildsResource,
@@ -730,4 +738,10 @@
"AsyncPayoutAccountsResourceWithRawResponse",
"PayoutAccountsResourceWithStreamingResponse",
"AsyncPayoutAccountsResourceWithStreamingResponse",
+ "AffiliatesResource",
+ "AsyncAffiliatesResource",
+ "AffiliatesResourceWithRawResponse",
+ "AsyncAffiliatesResourceWithRawResponse",
+ "AffiliatesResourceWithStreamingResponse",
+ "AsyncAffiliatesResourceWithStreamingResponse",
]
diff --git a/src/whop_sdk/resources/affiliates/__init__.py b/src/whop_sdk/resources/affiliates/__init__.py
new file mode 100644
index 0000000..b533807
--- /dev/null
+++ b/src/whop_sdk/resources/affiliates/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .overrides import (
+ OverridesResource,
+ AsyncOverridesResource,
+ OverridesResourceWithRawResponse,
+ AsyncOverridesResourceWithRawResponse,
+ OverridesResourceWithStreamingResponse,
+ AsyncOverridesResourceWithStreamingResponse,
+)
+from .affiliates import (
+ AffiliatesResource,
+ AsyncAffiliatesResource,
+ AffiliatesResourceWithRawResponse,
+ AsyncAffiliatesResourceWithRawResponse,
+ AffiliatesResourceWithStreamingResponse,
+ AsyncAffiliatesResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "OverridesResource",
+ "AsyncOverridesResource",
+ "OverridesResourceWithRawResponse",
+ "AsyncOverridesResourceWithRawResponse",
+ "OverridesResourceWithStreamingResponse",
+ "AsyncOverridesResourceWithStreamingResponse",
+ "AffiliatesResource",
+ "AsyncAffiliatesResource",
+ "AffiliatesResourceWithRawResponse",
+ "AsyncAffiliatesResourceWithRawResponse",
+ "AffiliatesResourceWithStreamingResponse",
+ "AsyncAffiliatesResourceWithStreamingResponse",
+]
diff --git a/src/whop_sdk/resources/affiliates/affiliates.py b/src/whop_sdk/resources/affiliates/affiliates.py
new file mode 100644
index 0000000..2c184de
--- /dev/null
+++ b/src/whop_sdk/resources/affiliates/affiliates.py
@@ -0,0 +1,674 @@
+# 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 Literal
+
+import httpx
+
+from ...types import Status, affiliate_list_params, affiliate_create_params
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from .overrides import (
+ OverridesResource,
+ AsyncOverridesResource,
+ OverridesResourceWithRawResponse,
+ AsyncOverridesResourceWithRawResponse,
+ OverridesResourceWithStreamingResponse,
+ AsyncOverridesResourceWithStreamingResponse,
+)
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...pagination import SyncCursorPage, AsyncCursorPage
+from ..._base_client import AsyncPaginator, make_request_options
+from ...types.status import Status
+from ...types.affiliate import Affiliate
+from ...types.shared.direction import Direction
+from ...types.affiliate_list_response import AffiliateListResponse
+from ...types.affiliate_archive_response import AffiliateArchiveResponse
+from ...types.affiliate_unarchive_response import AffiliateUnarchiveResponse
+
+__all__ = ["AffiliatesResource", "AsyncAffiliatesResource"]
+
+
+class AffiliatesResource(SyncAPIResource):
+ """Affiliates"""
+
+ @cached_property
+ def overrides(self) -> OverridesResource:
+ """Affiliates"""
+ return OverridesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AffiliatesResourceWithRawResponse:
+ """
+ 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/whopio/whopsdk-python#accessing-raw-response-data-eg-headers
+ """
+ return AffiliatesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AffiliatesResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response
+ """
+ return AffiliatesResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ company_id: str,
+ user_identifier: 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,
+ ) -> Affiliate:
+ """
+ Creates or finds an affiliate for a company and user.
+
+ Required permissions:
+
+ - `affiliate:create`
+
+ Args:
+ company_id: The ID of the company to create the affiliate for.
+
+ user_identifier: The user identifier (username, email, user ID, or Discord ID).
+
+ 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
+ """
+ return self._post(
+ "/affiliates",
+ body=maybe_transform(
+ {
+ "company_id": company_id,
+ "user_identifier": user_identifier,
+ },
+ affiliate_create_params.AffiliateCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Affiliate,
+ )
+
+ def retrieve(
+ self,
+ 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,
+ ) -> Affiliate:
+ """
+ Retrieves the details of an existing affiliate.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._get(
+ f"/affiliates/{id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Affiliate,
+ )
+
+ def list(
+ self,
+ *,
+ company_id: str,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
+ first: Optional[int] | Omit = omit,
+ last: Optional[int] | Omit = omit,
+ order: Optional[Literal["id", "created_at", "cached_total_referrals", "cached_total_rewards"]] | Omit = omit,
+ query: Optional[str] | Omit = omit,
+ status: Optional[Status] | Omit = omit,
+ # 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,
+ ) -> SyncCursorPage[AffiliateListResponse]:
+ """
+ Returns a paginated list of affiliates for the actor in context, with optional
+ filtering by status, search, and sorting.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ Args:
+ company_id: The unique identifier of the company to list affiliates for.
+
+ after: Returns the elements in the list that come after the specified cursor.
+
+ before: Returns the elements in the list that come before the specified cursor.
+
+ direction: The direction of the sort.
+
+ first: Returns the first _n_ elements from the list.
+
+ last: Returns the last _n_ elements from the list.
+
+ order: Which columns can be used to sort.
+
+ query: Search affiliates by username.
+
+ status: Statuses for resources
+
+ 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
+ """
+ return self._get_api_list(
+ "/affiliates",
+ page=SyncCursorPage[AffiliateListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "company_id": company_id,
+ "after": after,
+ "before": before,
+ "direction": direction,
+ "first": first,
+ "last": last,
+ "order": order,
+ "query": query,
+ "status": status,
+ },
+ affiliate_list_params.AffiliateListParams,
+ ),
+ ),
+ model=AffiliateListResponse,
+ )
+
+ def archive(
+ self,
+ 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,
+ ) -> AffiliateArchiveResponse:
+ """
+ Archives an existing Affiliate
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ f"/affiliates/{id}/archive",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AffiliateArchiveResponse,
+ )
+
+ def unarchive(
+ self,
+ 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,
+ ) -> AffiliateUnarchiveResponse:
+ """
+ Unarchives an existing Affiliate
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._post(
+ f"/affiliates/{id}/unarchive",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AffiliateUnarchiveResponse,
+ )
+
+
+class AsyncAffiliatesResource(AsyncAPIResource):
+ """Affiliates"""
+
+ @cached_property
+ def overrides(self) -> AsyncOverridesResource:
+ """Affiliates"""
+ return AsyncOverridesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncAffiliatesResourceWithRawResponse:
+ """
+ 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/whopio/whopsdk-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncAffiliatesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncAffiliatesResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response
+ """
+ return AsyncAffiliatesResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ company_id: str,
+ user_identifier: 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,
+ ) -> Affiliate:
+ """
+ Creates or finds an affiliate for a company and user.
+
+ Required permissions:
+
+ - `affiliate:create`
+
+ Args:
+ company_id: The ID of the company to create the affiliate for.
+
+ user_identifier: The user identifier (username, email, user ID, or Discord ID).
+
+ 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
+ """
+ return await self._post(
+ "/affiliates",
+ body=await async_maybe_transform(
+ {
+ "company_id": company_id,
+ "user_identifier": user_identifier,
+ },
+ affiliate_create_params.AffiliateCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Affiliate,
+ )
+
+ async def retrieve(
+ self,
+ 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,
+ ) -> Affiliate:
+ """
+ Retrieves the details of an existing affiliate.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._get(
+ f"/affiliates/{id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Affiliate,
+ )
+
+ def list(
+ self,
+ *,
+ company_id: str,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
+ first: Optional[int] | Omit = omit,
+ last: Optional[int] | Omit = omit,
+ order: Optional[Literal["id", "created_at", "cached_total_referrals", "cached_total_rewards"]] | Omit = omit,
+ query: Optional[str] | Omit = omit,
+ status: Optional[Status] | Omit = omit,
+ # 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,
+ ) -> AsyncPaginator[AffiliateListResponse, AsyncCursorPage[AffiliateListResponse]]:
+ """
+ Returns a paginated list of affiliates for the actor in context, with optional
+ filtering by status, search, and sorting.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ Args:
+ company_id: The unique identifier of the company to list affiliates for.
+
+ after: Returns the elements in the list that come after the specified cursor.
+
+ before: Returns the elements in the list that come before the specified cursor.
+
+ direction: The direction of the sort.
+
+ first: Returns the first _n_ elements from the list.
+
+ last: Returns the last _n_ elements from the list.
+
+ order: Which columns can be used to sort.
+
+ query: Search affiliates by username.
+
+ status: Statuses for resources
+
+ 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
+ """
+ return self._get_api_list(
+ "/affiliates",
+ page=AsyncCursorPage[AffiliateListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "company_id": company_id,
+ "after": after,
+ "before": before,
+ "direction": direction,
+ "first": first,
+ "last": last,
+ "order": order,
+ "query": query,
+ "status": status,
+ },
+ affiliate_list_params.AffiliateListParams,
+ ),
+ ),
+ model=AffiliateListResponse,
+ )
+
+ async def archive(
+ self,
+ 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,
+ ) -> AffiliateArchiveResponse:
+ """
+ Archives an existing Affiliate
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ f"/affiliates/{id}/archive",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AffiliateArchiveResponse,
+ )
+
+ async def unarchive(
+ self,
+ 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,
+ ) -> AffiliateUnarchiveResponse:
+ """
+ Unarchives an existing Affiliate
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._post(
+ f"/affiliates/{id}/unarchive",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AffiliateUnarchiveResponse,
+ )
+
+
+class AffiliatesResourceWithRawResponse:
+ def __init__(self, affiliates: AffiliatesResource) -> None:
+ self._affiliates = affiliates
+
+ self.create = to_raw_response_wrapper(
+ affiliates.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ affiliates.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ affiliates.list,
+ )
+ self.archive = to_raw_response_wrapper(
+ affiliates.archive,
+ )
+ self.unarchive = to_raw_response_wrapper(
+ affiliates.unarchive,
+ )
+
+ @cached_property
+ def overrides(self) -> OverridesResourceWithRawResponse:
+ """Affiliates"""
+ return OverridesResourceWithRawResponse(self._affiliates.overrides)
+
+
+class AsyncAffiliatesResourceWithRawResponse:
+ def __init__(self, affiliates: AsyncAffiliatesResource) -> None:
+ self._affiliates = affiliates
+
+ self.create = async_to_raw_response_wrapper(
+ affiliates.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ affiliates.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ affiliates.list,
+ )
+ self.archive = async_to_raw_response_wrapper(
+ affiliates.archive,
+ )
+ self.unarchive = async_to_raw_response_wrapper(
+ affiliates.unarchive,
+ )
+
+ @cached_property
+ def overrides(self) -> AsyncOverridesResourceWithRawResponse:
+ """Affiliates"""
+ return AsyncOverridesResourceWithRawResponse(self._affiliates.overrides)
+
+
+class AffiliatesResourceWithStreamingResponse:
+ def __init__(self, affiliates: AffiliatesResource) -> None:
+ self._affiliates = affiliates
+
+ self.create = to_streamed_response_wrapper(
+ affiliates.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ affiliates.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ affiliates.list,
+ )
+ self.archive = to_streamed_response_wrapper(
+ affiliates.archive,
+ )
+ self.unarchive = to_streamed_response_wrapper(
+ affiliates.unarchive,
+ )
+
+ @cached_property
+ def overrides(self) -> OverridesResourceWithStreamingResponse:
+ """Affiliates"""
+ return OverridesResourceWithStreamingResponse(self._affiliates.overrides)
+
+
+class AsyncAffiliatesResourceWithStreamingResponse:
+ def __init__(self, affiliates: AsyncAffiliatesResource) -> None:
+ self._affiliates = affiliates
+
+ self.create = async_to_streamed_response_wrapper(
+ affiliates.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ affiliates.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ affiliates.list,
+ )
+ self.archive = async_to_streamed_response_wrapper(
+ affiliates.archive,
+ )
+ self.unarchive = async_to_streamed_response_wrapper(
+ affiliates.unarchive,
+ )
+
+ @cached_property
+ def overrides(self) -> AsyncOverridesResourceWithStreamingResponse:
+ """Affiliates"""
+ return AsyncOverridesResourceWithStreamingResponse(self._affiliates.overrides)
diff --git a/src/whop_sdk/resources/affiliates/overrides.py b/src/whop_sdk/resources/affiliates/overrides.py
new file mode 100644
index 0000000..a3158a1
--- /dev/null
+++ b/src/whop_sdk/resources/affiliates/overrides.py
@@ -0,0 +1,859 @@
+# 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 Literal, overload
+
+import httpx
+
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._utils import required_args, maybe_transform, async_maybe_transform
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from ..._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...pagination import SyncCursorPage, AsyncCursorPage
+from ..._base_client import AsyncPaginator, make_request_options
+from ...types.affiliates import (
+ AffiliatePayoutTypes,
+ AffiliateRevenueBases,
+ AffiliateOverrideRoles,
+ AffiliateAppliesToPayments,
+ override_list_params,
+ override_create_params,
+ override_update_params,
+)
+from ...types.affiliates.affiliate_payout_types import AffiliatePayoutTypes
+from ...types.affiliates.override_list_response import OverrideListResponse
+from ...types.affiliates.affiliate_revenue_bases import AffiliateRevenueBases
+from ...types.affiliates.affiliate_override_roles import AffiliateOverrideRoles
+from ...types.affiliates.override_create_response import OverrideCreateResponse
+from ...types.affiliates.override_delete_response import OverrideDeleteResponse
+from ...types.affiliates.override_update_response import OverrideUpdateResponse
+from ...types.affiliates.override_retrieve_response import OverrideRetrieveResponse
+from ...types.affiliates.affiliate_applies_to_payments import AffiliateAppliesToPayments
+
+__all__ = ["OverridesResource", "AsyncOverridesResource"]
+
+
+class OverridesResource(SyncAPIResource):
+ """Affiliates"""
+
+ @cached_property
+ def with_raw_response(self) -> OverridesResourceWithRawResponse:
+ """
+ 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/whopio/whopsdk-python#accessing-raw-response-data-eg-headers
+ """
+ return OverridesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> OverridesResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response
+ """
+ return OverridesResourceWithStreamingResponse(self)
+
+ @overload
+ def create(
+ self,
+ path_id: str,
+ *,
+ body_id: str,
+ commission_value: float,
+ override_type: Literal["standard"],
+ plan_id: str,
+ applies_to_payments: Optional[AffiliateAppliesToPayments] | Omit = omit,
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ # 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,
+ ) -> OverrideCreateResponse:
+ """
+ Creates a commission override for an affiliate.
+
+ Required permissions:
+
+ - `affiliate:create`
+
+ Args:
+ body_id: The affiliate ID.
+
+ commission_value: The commission value (percentage 1-100 or flat fee).
+
+ plan_id: The plan ID (required for standard overrides).
+
+ applies_to_payments: Whether the affiliate commission applies to the first payment or all payments
+
+ commission_type: The types of payouts an affiliate can have
+
+ 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
+ """
+ ...
+
+ @overload
+ def create(
+ self,
+ path_id: str,
+ *,
+ body_id: str,
+ commission_value: float,
+ override_type: Literal["rev_share"],
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ product_id: Optional[str] | Omit = omit,
+ revenue_basis: Optional[AffiliateRevenueBases] | Omit = omit,
+ # 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,
+ ) -> OverrideCreateResponse:
+ """
+ Creates a commission override for an affiliate.
+
+ Required permissions:
+
+ - `affiliate:create`
+
+ Args:
+ body_id: The affiliate ID.
+
+ commission_value: The commission value (percentage 1-100 or flat fee).
+
+ commission_type: The types of payouts an affiliate can have
+
+ product_id: The product ID (for rev-share overrides, omit for company-wide).
+
+ revenue_basis: The calculation method for affiliate rev-share percentages
+
+ 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
+ """
+ ...
+
+ @required_args(
+ ["body_id", "commission_value", "override_type", "plan_id"], ["body_id", "commission_value", "override_type"]
+ )
+ def create(
+ self,
+ path_id: str,
+ *,
+ body_id: str,
+ commission_value: float,
+ override_type: Literal["standard"] | Literal["rev_share"],
+ plan_id: str | Omit = omit,
+ applies_to_payments: Optional[AffiliateAppliesToPayments] | Omit = omit,
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ product_id: Optional[str] | Omit = omit,
+ revenue_basis: Optional[AffiliateRevenueBases] | Omit = omit,
+ # 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,
+ ) -> OverrideCreateResponse:
+ if not path_id:
+ raise ValueError(f"Expected a non-empty value for `path_id` but received {path_id!r}")
+ return self._post(
+ f"/affiliates/{path_id}/overrides",
+ body=maybe_transform(
+ {
+ "body_id": body_id,
+ "commission_value": commission_value,
+ "override_type": override_type,
+ "plan_id": plan_id,
+ "applies_to_payments": applies_to_payments,
+ "commission_type": commission_type,
+ "product_id": product_id,
+ "revenue_basis": revenue_basis,
+ },
+ override_create_params.OverrideCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ override_id: str,
+ *,
+ 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,
+ ) -> OverrideRetrieveResponse:
+ """
+ Retrieves the details of a specific affiliate override.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ if not override_id:
+ raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}")
+ return self._get(
+ f"/affiliates/{id}/overrides/{override_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideRetrieveResponse,
+ )
+
+ def update(
+ self,
+ override_id: str,
+ *,
+ id: str,
+ applies_to_payments: Optional[AffiliateAppliesToPayments] | Omit = omit,
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ commission_value: Optional[float] | Omit = omit,
+ revenue_basis: Optional[AffiliateRevenueBases] | Omit = omit,
+ # 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,
+ ) -> OverrideUpdateResponse:
+ """
+ Updates an existing affiliate override.
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ Args:
+ applies_to_payments: Whether the affiliate commission applies to the first payment or all payments
+
+ commission_type: The types of payouts an affiliate can have
+
+ commission_value: The commission value (percentage 1-100 or flat fee in dollars).
+
+ revenue_basis: The calculation method for affiliate rev-share percentages
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ if not override_id:
+ raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}")
+ return self._patch(
+ f"/affiliates/{id}/overrides/{override_id}",
+ body=maybe_transform(
+ {
+ "applies_to_payments": applies_to_payments,
+ "commission_type": commission_type,
+ "commission_value": commission_value,
+ "revenue_basis": revenue_basis,
+ },
+ override_update_params.OverrideUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideUpdateResponse,
+ )
+
+ def list(
+ self,
+ id: str,
+ *,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ first: Optional[int] | Omit = omit,
+ last: Optional[int] | Omit = omit,
+ override_type: Optional[AffiliateOverrideRoles] | Omit = omit,
+ # 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,
+ ) -> SyncCursorPage[OverrideListResponse]:
+ """
+ Returns a paginated list of overrides for an affiliate.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ Args:
+ after: Returns the elements in the list that come after the specified cursor.
+
+ before: Returns the elements in the list that come before the specified cursor.
+
+ first: Returns the first _n_ elements from the list.
+
+ last: Returns the last _n_ elements from the list.
+
+ override_type: The role of an affiliate override (standard or rev_share)
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._get_api_list(
+ f"/affiliates/{id}/overrides",
+ page=SyncCursorPage[OverrideListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "after": after,
+ "before": before,
+ "first": first,
+ "last": last,
+ "override_type": override_type,
+ },
+ override_list_params.OverrideListParams,
+ ),
+ ),
+ model=OverrideListResponse,
+ )
+
+ def delete(
+ self,
+ override_id: str,
+ *,
+ 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,
+ ) -> OverrideDeleteResponse:
+ """
+ Deletes an affiliate override.
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ if not override_id:
+ raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}")
+ return self._delete(
+ f"/affiliates/{id}/overrides/{override_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideDeleteResponse,
+ )
+
+
+class AsyncOverridesResource(AsyncAPIResource):
+ """Affiliates"""
+
+ @cached_property
+ def with_raw_response(self) -> AsyncOverridesResourceWithRawResponse:
+ """
+ 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/whopio/whopsdk-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncOverridesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncOverridesResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response
+ """
+ return AsyncOverridesResourceWithStreamingResponse(self)
+
+ @overload
+ async def create(
+ self,
+ path_id: str,
+ *,
+ body_id: str,
+ commission_value: float,
+ override_type: Literal["standard"],
+ plan_id: str,
+ applies_to_payments: Optional[AffiliateAppliesToPayments] | Omit = omit,
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ # 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,
+ ) -> OverrideCreateResponse:
+ """
+ Creates a commission override for an affiliate.
+
+ Required permissions:
+
+ - `affiliate:create`
+
+ Args:
+ body_id: The affiliate ID.
+
+ commission_value: The commission value (percentage 1-100 or flat fee).
+
+ plan_id: The plan ID (required for standard overrides).
+
+ applies_to_payments: Whether the affiliate commission applies to the first payment or all payments
+
+ commission_type: The types of payouts an affiliate can have
+
+ 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
+ """
+ ...
+
+ @overload
+ async def create(
+ self,
+ path_id: str,
+ *,
+ body_id: str,
+ commission_value: float,
+ override_type: Literal["rev_share"],
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ product_id: Optional[str] | Omit = omit,
+ revenue_basis: Optional[AffiliateRevenueBases] | Omit = omit,
+ # 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,
+ ) -> OverrideCreateResponse:
+ """
+ Creates a commission override for an affiliate.
+
+ Required permissions:
+
+ - `affiliate:create`
+
+ Args:
+ body_id: The affiliate ID.
+
+ commission_value: The commission value (percentage 1-100 or flat fee).
+
+ commission_type: The types of payouts an affiliate can have
+
+ product_id: The product ID (for rev-share overrides, omit for company-wide).
+
+ revenue_basis: The calculation method for affiliate rev-share percentages
+
+ 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
+ """
+ ...
+
+ @required_args(
+ ["body_id", "commission_value", "override_type", "plan_id"], ["body_id", "commission_value", "override_type"]
+ )
+ async def create(
+ self,
+ path_id: str,
+ *,
+ body_id: str,
+ commission_value: float,
+ override_type: Literal["standard"] | Literal["rev_share"],
+ plan_id: str | Omit = omit,
+ applies_to_payments: Optional[AffiliateAppliesToPayments] | Omit = omit,
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ product_id: Optional[str] | Omit = omit,
+ revenue_basis: Optional[AffiliateRevenueBases] | Omit = omit,
+ # 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,
+ ) -> OverrideCreateResponse:
+ if not path_id:
+ raise ValueError(f"Expected a non-empty value for `path_id` but received {path_id!r}")
+ return await self._post(
+ f"/affiliates/{path_id}/overrides",
+ body=await async_maybe_transform(
+ {
+ "body_id": body_id,
+ "commission_value": commission_value,
+ "override_type": override_type,
+ "plan_id": plan_id,
+ "applies_to_payments": applies_to_payments,
+ "commission_type": commission_type,
+ "product_id": product_id,
+ "revenue_basis": revenue_basis,
+ },
+ override_create_params.OverrideCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ override_id: str,
+ *,
+ 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,
+ ) -> OverrideRetrieveResponse:
+ """
+ Retrieves the details of a specific affiliate override.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ if not override_id:
+ raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}")
+ return await self._get(
+ f"/affiliates/{id}/overrides/{override_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideRetrieveResponse,
+ )
+
+ async def update(
+ self,
+ override_id: str,
+ *,
+ id: str,
+ applies_to_payments: Optional[AffiliateAppliesToPayments] | Omit = omit,
+ commission_type: Optional[AffiliatePayoutTypes] | Omit = omit,
+ commission_value: Optional[float] | Omit = omit,
+ revenue_basis: Optional[AffiliateRevenueBases] | Omit = omit,
+ # 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,
+ ) -> OverrideUpdateResponse:
+ """
+ Updates an existing affiliate override.
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ Args:
+ applies_to_payments: Whether the affiliate commission applies to the first payment or all payments
+
+ commission_type: The types of payouts an affiliate can have
+
+ commission_value: The commission value (percentage 1-100 or flat fee in dollars).
+
+ revenue_basis: The calculation method for affiliate rev-share percentages
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ if not override_id:
+ raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}")
+ return await self._patch(
+ f"/affiliates/{id}/overrides/{override_id}",
+ body=await async_maybe_transform(
+ {
+ "applies_to_payments": applies_to_payments,
+ "commission_type": commission_type,
+ "commission_value": commission_value,
+ "revenue_basis": revenue_basis,
+ },
+ override_update_params.OverrideUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideUpdateResponse,
+ )
+
+ def list(
+ self,
+ id: str,
+ *,
+ after: Optional[str] | Omit = omit,
+ before: Optional[str] | Omit = omit,
+ first: Optional[int] | Omit = omit,
+ last: Optional[int] | Omit = omit,
+ override_type: Optional[AffiliateOverrideRoles] | Omit = omit,
+ # 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,
+ ) -> AsyncPaginator[OverrideListResponse, AsyncCursorPage[OverrideListResponse]]:
+ """
+ Returns a paginated list of overrides for an affiliate.
+
+ Required permissions:
+
+ - `affiliate:basic:read`
+
+ Args:
+ after: Returns the elements in the list that come after the specified cursor.
+
+ before: Returns the elements in the list that come before the specified cursor.
+
+ first: Returns the first _n_ elements from the list.
+
+ last: Returns the last _n_ elements from the list.
+
+ override_type: The role of an affiliate override (standard or rev_share)
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._get_api_list(
+ f"/affiliates/{id}/overrides",
+ page=AsyncCursorPage[OverrideListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "after": after,
+ "before": before,
+ "first": first,
+ "last": last,
+ "override_type": override_type,
+ },
+ override_list_params.OverrideListParams,
+ ),
+ ),
+ model=OverrideListResponse,
+ )
+
+ async def delete(
+ self,
+ override_id: str,
+ *,
+ 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,
+ ) -> OverrideDeleteResponse:
+ """
+ Deletes an affiliate override.
+
+ Required permissions:
+
+ - `affiliate:update`
+
+ 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 id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ if not override_id:
+ raise ValueError(f"Expected a non-empty value for `override_id` but received {override_id!r}")
+ return await self._delete(
+ f"/affiliates/{id}/overrides/{override_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=OverrideDeleteResponse,
+ )
+
+
+class OverridesResourceWithRawResponse:
+ def __init__(self, overrides: OverridesResource) -> None:
+ self._overrides = overrides
+
+ self.create = to_raw_response_wrapper(
+ overrides.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ overrides.retrieve,
+ )
+ self.update = to_raw_response_wrapper(
+ overrides.update,
+ )
+ self.list = to_raw_response_wrapper(
+ overrides.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ overrides.delete,
+ )
+
+
+class AsyncOverridesResourceWithRawResponse:
+ def __init__(self, overrides: AsyncOverridesResource) -> None:
+ self._overrides = overrides
+
+ self.create = async_to_raw_response_wrapper(
+ overrides.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ overrides.retrieve,
+ )
+ self.update = async_to_raw_response_wrapper(
+ overrides.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ overrides.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ overrides.delete,
+ )
+
+
+class OverridesResourceWithStreamingResponse:
+ def __init__(self, overrides: OverridesResource) -> None:
+ self._overrides = overrides
+
+ self.create = to_streamed_response_wrapper(
+ overrides.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ overrides.retrieve,
+ )
+ self.update = to_streamed_response_wrapper(
+ overrides.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ overrides.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ overrides.delete,
+ )
+
+
+class AsyncOverridesResourceWithStreamingResponse:
+ def __init__(self, overrides: AsyncOverridesResource) -> None:
+ self._overrides = overrides
+
+ self.create = async_to_streamed_response_wrapper(
+ overrides.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ overrides.retrieve,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ overrides.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ overrides.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ overrides.delete,
+ )
diff --git a/src/whop_sdk/resources/ai_chats.py b/src/whop_sdk/resources/ai_chats.py
index 4eff698..6c9f4a1 100644
--- a/src/whop_sdk/resources/ai_chats.py
+++ b/src/whop_sdk/resources/ai_chats.py
@@ -7,7 +7,7 @@
import httpx
-from ..types import ai_chat_list_params, ai_chat_create_params, ai_chat_update_params
+from ..types import NotificationPreferences, ai_chat_list_params, ai_chat_create_params, ai_chat_update_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -23,6 +23,7 @@
from ..types.ai_chat import AIChat
from ..types.ai_chat_list_response import AIChatListResponse
from ..types.ai_chat_delete_response import AIChatDeleteResponse
+from ..types.notification_preferences import NotificationPreferences
__all__ = ["AIChatsResource", "AsyncAIChatsResource"]
@@ -146,6 +147,7 @@ def update(
id: str,
*,
current_company_id: Optional[str] | Omit = omit,
+ notification_preference: Optional[NotificationPreferences] | Omit = omit,
title: Optional[str] | Omit = omit,
# 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.
@@ -155,7 +157,8 @@ def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AIChat:
"""
- Update an AI chat's title or associated company context.
+ Update an AI chat's title, notification preferences, or associated company
+ context.
Required permissions:
@@ -165,6 +168,8 @@ def update(
current_company_id: The unique identifier of the company to set as context for the AI chat (e.g.,
"biz_XXXXX").
+ notification_preference: The notification preference for an AI chat
+
title: The new display title for the AI chat thread (e.g., "Help with billing").
extra_headers: Send extra headers
@@ -182,6 +187,7 @@ def update(
body=maybe_transform(
{
"current_company_id": current_company_id,
+ "notification_preference": notification_preference,
"title": title,
},
ai_chat_update_params.AIChatUpdateParams,
@@ -408,6 +414,7 @@ async def update(
id: str,
*,
current_company_id: Optional[str] | Omit = omit,
+ notification_preference: Optional[NotificationPreferences] | Omit = omit,
title: Optional[str] | Omit = omit,
# 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.
@@ -417,7 +424,8 @@ async def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AIChat:
"""
- Update an AI chat's title or associated company context.
+ Update an AI chat's title, notification preferences, or associated company
+ context.
Required permissions:
@@ -427,6 +435,8 @@ async def update(
current_company_id: The unique identifier of the company to set as context for the AI chat (e.g.,
"biz_XXXXX").
+ notification_preference: The notification preference for an AI chat
+
title: The new display title for the AI chat thread (e.g., "Help with billing").
extra_headers: Send extra headers
@@ -444,6 +454,7 @@ async def update(
body=await async_maybe_transform(
{
"current_company_id": current_company_id,
+ "notification_preference": notification_preference,
"title": title,
},
ai_chat_update_params.AIChatUpdateParams,
diff --git a/src/whop_sdk/types/__init__.py b/src/whop_sdk/types/__init__.py
index 0cadc48..c4684b3 100644
--- a/src/whop_sdk/types/__init__.py
+++ b/src/whop_sdk/types/__init__.py
@@ -66,10 +66,12 @@
EmailNotificationPreferences as EmailNotificationPreferences,
CourseLessonInteractionListItem as CourseLessonInteractionListItem,
)
+from .status import Status as Status
from .ai_chat import AIChat as AIChat
from .dispute import Dispute as Dispute
from .webhook import Webhook as Webhook
from .app_type import AppType as AppType
+from .affiliate import Affiliate as Affiliate
from .dm_member import DmMember as DmMember
from .languages import Languages as Languages
from .dm_channel import DmChannel as DmChannel
@@ -150,6 +152,7 @@
from .transfer_list_params import TransferListParams as TransferListParams
from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent
from .withdrawal_fee_types import WithdrawalFeeTypes as WithdrawalFeeTypes
+from .affiliate_list_params import AffiliateListParams as AffiliateListParams
from .ai_chat_create_params import AIChatCreateParams as AIChatCreateParams
from .ai_chat_list_response import AIChatListResponse as AIChatListResponse
from .ai_chat_update_params import AIChatUpdateParams as AIChatUpdateParams
@@ -191,6 +194,8 @@
from .transfer_create_params import TransferCreateParams as TransferCreateParams
from .transfer_list_response import TransferListResponse as TransferListResponse
from .withdrawal_list_params import WithdrawalListParams as WithdrawalListParams
+from .affiliate_create_params import AffiliateCreateParams as AffiliateCreateParams
+from .affiliate_list_response import AffiliateListResponse as AffiliateListResponse
from .ai_chat_delete_response import AIChatDeleteResponse as AIChatDeleteResponse
from .app_build_create_params import AppBuildCreateParams as AppBuildCreateParams
from .app_build_list_response import AppBuildListResponse as AppBuildListResponse
@@ -223,6 +228,7 @@
from .membership_cancel_params import MembershipCancelParams as MembershipCancelParams
from .membership_list_response import MembershipListResponse as MembershipListResponse
from .membership_update_params import MembershipUpdateParams as MembershipUpdateParams
+from .notification_preferences import NotificationPreferences as NotificationPreferences
from .payment_list_fees_params import PaymentListFeesParams as PaymentListFeesParams
from .promo_code_create_params import PromoCodeCreateParams as PromoCodeCreateParams
from .promo_code_list_response import PromoCodeListResponse as PromoCodeListResponse
@@ -241,6 +247,7 @@
from .payout_method_list_params import PayoutMethodListParams as PayoutMethodListParams
from .access_token_create_params import AccessTokenCreateParams as AccessTokenCreateParams
from .account_link_create_params import AccountLinkCreateParams as AccountLinkCreateParams
+from .affiliate_archive_response import AffiliateArchiveResponse as AffiliateArchiveResponse
from .chat_channel_list_response import ChatChannelListResponse as ChatChannelListResponse
from .chat_channel_update_params import ChatChannelUpdateParams as ChatChannelUpdateParams
from .course_chapter_list_params import CourseChapterListParams as CourseChapterListParams
@@ -273,6 +280,7 @@
from .support_channel_list_params import SupportChannelListParams as SupportChannelListParams
from .access_token_create_response import AccessTokenCreateResponse as AccessTokenCreateResponse
from .account_link_create_response import AccountLinkCreateResponse as AccountLinkCreateResponse
+from .affiliate_unarchive_response import AffiliateUnarchiveResponse as AffiliateUnarchiveResponse
from .course_chapter_create_params import CourseChapterCreateParams as CourseChapterCreateParams
from .course_chapter_list_response import CourseChapterListResponse as CourseChapterListResponse
from .course_chapter_update_params import CourseChapterUpdateParams as CourseChapterUpdateParams
diff --git a/src/whop_sdk/types/affiliate.py b/src/whop_sdk/types/affiliate.py
new file mode 100644
index 0000000..26de2b8
--- /dev/null
+++ b/src/whop_sdk/types/affiliate.py
@@ -0,0 +1,84 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from .status import Status
+from .._models import BaseModel
+
+__all__ = ["Affiliate", "Company", "User"]
+
+
+class Company(BaseModel):
+ """The company attached to this affiliate"""
+
+ id: str
+ """The unique identifier for the company."""
+
+ title: str
+ """The written name of the company."""
+
+
+class User(BaseModel):
+ """The user attached to this affiliate"""
+
+ id: str
+ """The unique identifier for the user."""
+
+ name: Optional[str] = None
+ """The display name set on the user's Whop profile.
+
+ Null if the user has not set a name.
+ """
+
+ username: Optional[str] = None
+ """The unique username chosen by the user for their Whop profile.
+
+ Null if the user has not set a username.
+ """
+
+
+class Affiliate(BaseModel):
+ """An affiliate of a company or a global affiliate"""
+
+ id: str
+ """The unique identifier for the affiliate."""
+
+ active_members_count: int
+ """The total active members of the affiliate"""
+
+ company: Company
+ """The company attached to this affiliate"""
+
+ created_at: datetime
+ """The datetime the affiliate was created."""
+
+ customer_retention_rate: str
+ """How many referrals have remained since they joined as members"""
+
+ customer_retention_rate_ninety_days: str
+ """A rolling 90-day retention rate for this affiliate"""
+
+ monthly_recurring_revenue_usd: str
+ """The total MRR of the affiliate"""
+
+ status: Optional[Status] = None
+ """Statuses for resources"""
+
+ total_overrides_count: int
+ """The total count of all overrides for this affiliate"""
+
+ total_referral_earnings_usd: str
+ """The total earnings of the affiliate from the users they referred"""
+
+ total_referrals_count: int
+ """The total referrals of the affiliate"""
+
+ total_revenue_usd: str
+ """The total revenue of the affiliate from their referrals"""
+
+ updated_at: datetime
+ """The datetime the affiliate was last updated."""
+
+ user: User
+ """The user attached to this affiliate"""
diff --git a/src/whop_sdk/types/affiliate_archive_response.py b/src/whop_sdk/types/affiliate_archive_response.py
new file mode 100644
index 0000000..ea8a705
--- /dev/null
+++ b/src/whop_sdk/types/affiliate_archive_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["AffiliateArchiveResponse"]
+
+AffiliateArchiveResponse: TypeAlias = bool
diff --git a/src/whop_sdk/types/affiliate_create_params.py b/src/whop_sdk/types/affiliate_create_params.py
new file mode 100644
index 0000000..59ea1cb
--- /dev/null
+++ b/src/whop_sdk/types/affiliate_create_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["AffiliateCreateParams"]
+
+
+class AffiliateCreateParams(TypedDict, total=False):
+ company_id: Required[str]
+ """The ID of the company to create the affiliate for."""
+
+ user_identifier: Required[str]
+ """The user identifier (username, email, user ID, or Discord ID)."""
diff --git a/src/whop_sdk/types/affiliate_list_params.py b/src/whop_sdk/types/affiliate_list_params.py
new file mode 100644
index 0000000..e2baeee
--- /dev/null
+++ b/src/whop_sdk/types/affiliate_list_params.py
@@ -0,0 +1,40 @@
+# 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 Literal, Required, TypedDict
+
+from .status import Status
+from .shared.direction import Direction
+
+__all__ = ["AffiliateListParams"]
+
+
+class AffiliateListParams(TypedDict, total=False):
+ company_id: Required[str]
+ """The unique identifier of the company to list affiliates for."""
+
+ after: Optional[str]
+ """Returns the elements in the list that come after the specified cursor."""
+
+ before: Optional[str]
+ """Returns the elements in the list that come before the specified cursor."""
+
+ direction: Optional[Direction]
+ """The direction of the sort."""
+
+ first: Optional[int]
+ """Returns the first _n_ elements from the list."""
+
+ last: Optional[int]
+ """Returns the last _n_ elements from the list."""
+
+ order: Optional[Literal["id", "created_at", "cached_total_referrals", "cached_total_rewards"]]
+ """Which columns can be used to sort."""
+
+ query: Optional[str]
+ """Search affiliates by username."""
+
+ status: Optional[Status]
+ """Statuses for resources"""
diff --git a/src/whop_sdk/types/affiliate_list_response.py b/src/whop_sdk/types/affiliate_list_response.py
new file mode 100644
index 0000000..9e24c35
--- /dev/null
+++ b/src/whop_sdk/types/affiliate_list_response.py
@@ -0,0 +1,84 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from .status import Status
+from .._models import BaseModel
+
+__all__ = ["AffiliateListResponse", "Company", "User"]
+
+
+class Company(BaseModel):
+ """The company attached to this affiliate"""
+
+ id: str
+ """The unique identifier for the company."""
+
+ title: str
+ """The written name of the company."""
+
+
+class User(BaseModel):
+ """The user attached to this affiliate"""
+
+ id: str
+ """The unique identifier for the user."""
+
+ name: Optional[str] = None
+ """The display name set on the user's Whop profile.
+
+ Null if the user has not set a name.
+ """
+
+ username: Optional[str] = None
+ """The unique username chosen by the user for their Whop profile.
+
+ Null if the user has not set a username.
+ """
+
+
+class AffiliateListResponse(BaseModel):
+ """An affiliate of a company or a global affiliate"""
+
+ id: str
+ """The unique identifier for the affiliate."""
+
+ active_members_count: int
+ """The total active members of the affiliate"""
+
+ company: Company
+ """The company attached to this affiliate"""
+
+ created_at: datetime
+ """The datetime the affiliate was created."""
+
+ customer_retention_rate: str
+ """How many referrals have remained since they joined as members"""
+
+ customer_retention_rate_ninety_days: str
+ """A rolling 90-day retention rate for this affiliate"""
+
+ monthly_recurring_revenue_usd: str
+ """The total MRR of the affiliate"""
+
+ status: Optional[Status] = None
+ """Statuses for resources"""
+
+ total_overrides_count: int
+ """The total count of all overrides for this affiliate"""
+
+ total_referral_earnings_usd: str
+ """The total earnings of the affiliate from the users they referred"""
+
+ total_referrals_count: int
+ """The total referrals of the affiliate"""
+
+ total_revenue_usd: str
+ """The total revenue of the affiliate from their referrals"""
+
+ updated_at: datetime
+ """The datetime the affiliate was last updated."""
+
+ user: User
+ """The user attached to this affiliate"""
diff --git a/src/whop_sdk/types/affiliate_unarchive_response.py b/src/whop_sdk/types/affiliate_unarchive_response.py
new file mode 100644
index 0000000..34c8c2a
--- /dev/null
+++ b/src/whop_sdk/types/affiliate_unarchive_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["AffiliateUnarchiveResponse"]
+
+AffiliateUnarchiveResponse: TypeAlias = bool
diff --git a/src/whop_sdk/types/affiliates/__init__.py b/src/whop_sdk/types/affiliates/__init__.py
new file mode 100644
index 0000000..c072b83
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/__init__.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .override_list_params import OverrideListParams as OverrideListParams
+from .affiliate_payout_types import AffiliatePayoutTypes as AffiliatePayoutTypes
+from .override_create_params import OverrideCreateParams as OverrideCreateParams
+from .override_list_response import OverrideListResponse as OverrideListResponse
+from .override_update_params import OverrideUpdateParams as OverrideUpdateParams
+from .affiliate_revenue_bases import AffiliateRevenueBases as AffiliateRevenueBases
+from .affiliate_override_roles import AffiliateOverrideRoles as AffiliateOverrideRoles
+from .override_create_response import OverrideCreateResponse as OverrideCreateResponse
+from .override_delete_response import OverrideDeleteResponse as OverrideDeleteResponse
+from .override_update_response import OverrideUpdateResponse as OverrideUpdateResponse
+from .override_retrieve_response import OverrideRetrieveResponse as OverrideRetrieveResponse
+from .affiliate_applies_to_payments import AffiliateAppliesToPayments as AffiliateAppliesToPayments
+from .affiliate_applies_to_products import AffiliateAppliesToProducts as AffiliateAppliesToProducts
diff --git a/src/whop_sdk/types/affiliates/affiliate_applies_to_payments.py b/src/whop_sdk/types/affiliates/affiliate_applies_to_payments.py
new file mode 100644
index 0000000..e25a592
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/affiliate_applies_to_payments.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["AffiliateAppliesToPayments"]
+
+AffiliateAppliesToPayments: TypeAlias = Literal["first_payment", "all_payments"]
diff --git a/src/whop_sdk/types/affiliates/affiliate_applies_to_products.py b/src/whop_sdk/types/affiliates/affiliate_applies_to_products.py
new file mode 100644
index 0000000..2e7e21d
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/affiliate_applies_to_products.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["AffiliateAppliesToProducts"]
+
+AffiliateAppliesToProducts: TypeAlias = Literal["single_product", "all_products"]
diff --git a/src/whop_sdk/types/affiliates/affiliate_override_roles.py b/src/whop_sdk/types/affiliates/affiliate_override_roles.py
new file mode 100644
index 0000000..a123816
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/affiliate_override_roles.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["AffiliateOverrideRoles"]
+
+AffiliateOverrideRoles: TypeAlias = Literal["standard", "rev_share"]
diff --git a/src/whop_sdk/types/affiliates/affiliate_payout_types.py b/src/whop_sdk/types/affiliates/affiliate_payout_types.py
new file mode 100644
index 0000000..2bc6e63
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/affiliate_payout_types.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["AffiliatePayoutTypes"]
+
+AffiliatePayoutTypes: TypeAlias = Literal["percentage", "flat_fee"]
diff --git a/src/whop_sdk/types/affiliates/affiliate_revenue_bases.py b/src/whop_sdk/types/affiliates/affiliate_revenue_bases.py
new file mode 100644
index 0000000..0d8f781
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/affiliate_revenue_bases.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["AffiliateRevenueBases"]
+
+AffiliateRevenueBases: TypeAlias = Literal["pre_fees", "post_fees"]
diff --git a/src/whop_sdk/types/affiliates/override_create_params.py b/src/whop_sdk/types/affiliates/override_create_params.py
new file mode 100644
index 0000000..b136a4f
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_create_params.py
@@ -0,0 +1,60 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union, Optional
+from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
+
+from ..._utils import PropertyInfo
+from .affiliate_payout_types import AffiliatePayoutTypes
+from .affiliate_revenue_bases import AffiliateRevenueBases
+from .affiliate_applies_to_payments import AffiliateAppliesToPayments
+
+__all__ = [
+ "OverrideCreateParams",
+ "CreateAffiliateOverrideInputOverrideTypeStandard",
+ "CreateAffiliateOverrideInputOverrideTypeRevShare",
+]
+
+
+class CreateAffiliateOverrideInputOverrideTypeStandard(TypedDict, total=False):
+ body_id: Required[Annotated[str, PropertyInfo(alias="id")]]
+ """The affiliate ID."""
+
+ commission_value: Required[float]
+ """The commission value (percentage 1-100 or flat fee)."""
+
+ override_type: Required[Literal["standard"]]
+
+ plan_id: Required[str]
+ """The plan ID (required for standard overrides)."""
+
+ applies_to_payments: Optional[AffiliateAppliesToPayments]
+ """Whether the affiliate commission applies to the first payment or all payments"""
+
+ commission_type: Optional[AffiliatePayoutTypes]
+ """The types of payouts an affiliate can have"""
+
+
+class CreateAffiliateOverrideInputOverrideTypeRevShare(TypedDict, total=False):
+ body_id: Required[Annotated[str, PropertyInfo(alias="id")]]
+ """The affiliate ID."""
+
+ commission_value: Required[float]
+ """The commission value (percentage 1-100 or flat fee)."""
+
+ override_type: Required[Literal["rev_share"]]
+
+ commission_type: Optional[AffiliatePayoutTypes]
+ """The types of payouts an affiliate can have"""
+
+ product_id: Optional[str]
+ """The product ID (for rev-share overrides, omit for company-wide)."""
+
+ revenue_basis: Optional[AffiliateRevenueBases]
+ """The calculation method for affiliate rev-share percentages"""
+
+
+OverrideCreateParams: TypeAlias = Union[
+ CreateAffiliateOverrideInputOverrideTypeStandard, CreateAffiliateOverrideInputOverrideTypeRevShare
+]
diff --git a/src/whop_sdk/types/affiliates/override_create_response.py b/src/whop_sdk/types/affiliates/override_create_response.py
new file mode 100644
index 0000000..b7c63d4
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_create_response.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+from .affiliate_payout_types import AffiliatePayoutTypes
+from .affiliate_revenue_bases import AffiliateRevenueBases
+from .affiliate_override_roles import AffiliateOverrideRoles
+from .affiliate_applies_to_payments import AffiliateAppliesToPayments
+from .affiliate_applies_to_products import AffiliateAppliesToProducts
+
+__all__ = ["OverrideCreateResponse"]
+
+
+class OverrideCreateResponse(BaseModel):
+ """An object storing information about the affiliate"""
+
+ id: str
+ """The unique identifier for the affiliate override."""
+
+ applies_to_payments: Optional[AffiliateAppliesToPayments] = None
+ """Whether the affiliate commission applies to the first payment or all payments"""
+
+ applies_to_products: Optional[AffiliateAppliesToProducts] = None
+ """Whether a rev-share override applies to a single product or all products"""
+
+ checkout_direct_link: Optional[str] = None
+ """The checkout direct link for referrals (standard overrides only)."""
+
+ commission_type: AffiliatePayoutTypes
+ """The type of commission (percentage or flat_fee)."""
+
+ commission_value: float
+ """The commission value (percentage 1-100 or flat fee in dollars)."""
+
+ override_type: AffiliateOverrideRoles
+ """The type of override (standard or rev_share)."""
+
+ plan_id: Optional[str] = None
+ """The plan ID (for standard overrides)."""
+
+ product_direct_link: Optional[str] = None
+ """The product page direct link for referrals (standard overrides only)."""
+
+ product_id: Optional[str] = None
+ """The product ID (for rev-share overrides)."""
+
+ revenue_basis: Optional[AffiliateRevenueBases] = None
+ """The calculation method for affiliate rev-share percentages"""
+
+ total_referral_earnings_usd: float
+ """
+ The total earnings paid to this affiliate for referrals to this specific plan,
+ in USD.
+ """
diff --git a/src/whop_sdk/types/affiliates/override_delete_response.py b/src/whop_sdk/types/affiliates/override_delete_response.py
new file mode 100644
index 0000000..0cb553b
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_delete_response.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import TypeAlias
+
+__all__ = ["OverrideDeleteResponse"]
+
+OverrideDeleteResponse: TypeAlias = bool
diff --git a/src/whop_sdk/types/affiliates/override_list_params.py b/src/whop_sdk/types/affiliates/override_list_params.py
new file mode 100644
index 0000000..76f82be
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_list_params.py
@@ -0,0 +1,27 @@
+# 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
+
+from .affiliate_override_roles import AffiliateOverrideRoles
+
+__all__ = ["OverrideListParams"]
+
+
+class OverrideListParams(TypedDict, total=False):
+ after: Optional[str]
+ """Returns the elements in the list that come after the specified cursor."""
+
+ before: Optional[str]
+ """Returns the elements in the list that come before the specified cursor."""
+
+ first: Optional[int]
+ """Returns the first _n_ elements from the list."""
+
+ last: Optional[int]
+ """Returns the last _n_ elements from the list."""
+
+ override_type: Optional[AffiliateOverrideRoles]
+ """The role of an affiliate override (standard or rev_share)"""
diff --git a/src/whop_sdk/types/affiliates/override_list_response.py b/src/whop_sdk/types/affiliates/override_list_response.py
new file mode 100644
index 0000000..09ce176
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_list_response.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+from .affiliate_payout_types import AffiliatePayoutTypes
+from .affiliate_revenue_bases import AffiliateRevenueBases
+from .affiliate_override_roles import AffiliateOverrideRoles
+from .affiliate_applies_to_payments import AffiliateAppliesToPayments
+from .affiliate_applies_to_products import AffiliateAppliesToProducts
+
+__all__ = ["OverrideListResponse"]
+
+
+class OverrideListResponse(BaseModel):
+ """An object storing information about the affiliate"""
+
+ id: str
+ """The unique identifier for the affiliate override."""
+
+ applies_to_payments: Optional[AffiliateAppliesToPayments] = None
+ """Whether the affiliate commission applies to the first payment or all payments"""
+
+ applies_to_products: Optional[AffiliateAppliesToProducts] = None
+ """Whether a rev-share override applies to a single product or all products"""
+
+ checkout_direct_link: Optional[str] = None
+ """The checkout direct link for referrals (standard overrides only)."""
+
+ commission_type: AffiliatePayoutTypes
+ """The type of commission (percentage or flat_fee)."""
+
+ commission_value: float
+ """The commission value (percentage 1-100 or flat fee in dollars)."""
+
+ override_type: AffiliateOverrideRoles
+ """The type of override (standard or rev_share)."""
+
+ plan_id: Optional[str] = None
+ """The plan ID (for standard overrides)."""
+
+ product_direct_link: Optional[str] = None
+ """The product page direct link for referrals (standard overrides only)."""
+
+ product_id: Optional[str] = None
+ """The product ID (for rev-share overrides)."""
+
+ revenue_basis: Optional[AffiliateRevenueBases] = None
+ """The calculation method for affiliate rev-share percentages"""
+
+ total_referral_earnings_usd: float
+ """
+ The total earnings paid to this affiliate for referrals to this specific plan,
+ in USD.
+ """
diff --git a/src/whop_sdk/types/affiliates/override_retrieve_response.py b/src/whop_sdk/types/affiliates/override_retrieve_response.py
new file mode 100644
index 0000000..4e54c0f
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_retrieve_response.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+from .affiliate_payout_types import AffiliatePayoutTypes
+from .affiliate_revenue_bases import AffiliateRevenueBases
+from .affiliate_override_roles import AffiliateOverrideRoles
+from .affiliate_applies_to_payments import AffiliateAppliesToPayments
+from .affiliate_applies_to_products import AffiliateAppliesToProducts
+
+__all__ = ["OverrideRetrieveResponse"]
+
+
+class OverrideRetrieveResponse(BaseModel):
+ """An object storing information about the affiliate"""
+
+ id: str
+ """The unique identifier for the affiliate override."""
+
+ applies_to_payments: Optional[AffiliateAppliesToPayments] = None
+ """Whether the affiliate commission applies to the first payment or all payments"""
+
+ applies_to_products: Optional[AffiliateAppliesToProducts] = None
+ """Whether a rev-share override applies to a single product or all products"""
+
+ checkout_direct_link: Optional[str] = None
+ """The checkout direct link for referrals (standard overrides only)."""
+
+ commission_type: AffiliatePayoutTypes
+ """The type of commission (percentage or flat_fee)."""
+
+ commission_value: float
+ """The commission value (percentage 1-100 or flat fee in dollars)."""
+
+ override_type: AffiliateOverrideRoles
+ """The type of override (standard or rev_share)."""
+
+ plan_id: Optional[str] = None
+ """The plan ID (for standard overrides)."""
+
+ product_direct_link: Optional[str] = None
+ """The product page direct link for referrals (standard overrides only)."""
+
+ product_id: Optional[str] = None
+ """The product ID (for rev-share overrides)."""
+
+ revenue_basis: Optional[AffiliateRevenueBases] = None
+ """The calculation method for affiliate rev-share percentages"""
+
+ total_referral_earnings_usd: float
+ """
+ The total earnings paid to this affiliate for referrals to this specific plan,
+ in USD.
+ """
diff --git a/src/whop_sdk/types/affiliates/override_update_params.py b/src/whop_sdk/types/affiliates/override_update_params.py
new file mode 100644
index 0000000..fa1ab86
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_update_params.py
@@ -0,0 +1,28 @@
+# 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 Required, TypedDict
+
+from .affiliate_payout_types import AffiliatePayoutTypes
+from .affiliate_revenue_bases import AffiliateRevenueBases
+from .affiliate_applies_to_payments import AffiliateAppliesToPayments
+
+__all__ = ["OverrideUpdateParams"]
+
+
+class OverrideUpdateParams(TypedDict, total=False):
+ id: Required[str]
+
+ applies_to_payments: Optional[AffiliateAppliesToPayments]
+ """Whether the affiliate commission applies to the first payment or all payments"""
+
+ commission_type: Optional[AffiliatePayoutTypes]
+ """The types of payouts an affiliate can have"""
+
+ commission_value: Optional[float]
+ """The commission value (percentage 1-100 or flat fee in dollars)."""
+
+ revenue_basis: Optional[AffiliateRevenueBases]
+ """The calculation method for affiliate rev-share percentages"""
diff --git a/src/whop_sdk/types/affiliates/override_update_response.py b/src/whop_sdk/types/affiliates/override_update_response.py
new file mode 100644
index 0000000..b9ed5c9
--- /dev/null
+++ b/src/whop_sdk/types/affiliates/override_update_response.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from ..._models import BaseModel
+from .affiliate_payout_types import AffiliatePayoutTypes
+from .affiliate_revenue_bases import AffiliateRevenueBases
+from .affiliate_override_roles import AffiliateOverrideRoles
+from .affiliate_applies_to_payments import AffiliateAppliesToPayments
+from .affiliate_applies_to_products import AffiliateAppliesToProducts
+
+__all__ = ["OverrideUpdateResponse"]
+
+
+class OverrideUpdateResponse(BaseModel):
+ """An object storing information about the affiliate"""
+
+ id: str
+ """The unique identifier for the affiliate override."""
+
+ applies_to_payments: Optional[AffiliateAppliesToPayments] = None
+ """Whether the affiliate commission applies to the first payment or all payments"""
+
+ applies_to_products: Optional[AffiliateAppliesToProducts] = None
+ """Whether a rev-share override applies to a single product or all products"""
+
+ checkout_direct_link: Optional[str] = None
+ """The checkout direct link for referrals (standard overrides only)."""
+
+ commission_type: AffiliatePayoutTypes
+ """The type of commission (percentage or flat_fee)."""
+
+ commission_value: float
+ """The commission value (percentage 1-100 or flat fee in dollars)."""
+
+ override_type: AffiliateOverrideRoles
+ """The type of override (standard or rev_share)."""
+
+ plan_id: Optional[str] = None
+ """The plan ID (for standard overrides)."""
+
+ product_direct_link: Optional[str] = None
+ """The product page direct link for referrals (standard overrides only)."""
+
+ product_id: Optional[str] = None
+ """The product ID (for rev-share overrides)."""
+
+ revenue_basis: Optional[AffiliateRevenueBases] = None
+ """The calculation method for affiliate rev-share percentages"""
+
+ total_referral_earnings_usd: float
+ """
+ The total earnings paid to this affiliate for referrals to this specific plan,
+ in USD.
+ """
diff --git a/src/whop_sdk/types/ai_chat.py b/src/whop_sdk/types/ai_chat.py
index 2ddbc6e..cf370c2 100644
--- a/src/whop_sdk/types/ai_chat.py
+++ b/src/whop_sdk/types/ai_chat.py
@@ -4,6 +4,7 @@
from datetime import datetime
from .._models import BaseModel
+from .notification_preferences import NotificationPreferences
__all__ = ["AIChat", "User"]
@@ -38,6 +39,12 @@ class AIChat(BaseModel):
message_count: int
"""The total number of messages exchanged in this conversation."""
+ notification_preference: NotificationPreferences
+ """The notification preference for this AI chat.
+
+ `all` delivers AI chat notifications and badges, while `none` mutes them.
+ """
+
title: Optional[str] = None
"""A short descriptive title for this AI chat conversation.
diff --git a/src/whop_sdk/types/ai_chat_list_response.py b/src/whop_sdk/types/ai_chat_list_response.py
index af211b4..3b67653 100644
--- a/src/whop_sdk/types/ai_chat_list_response.py
+++ b/src/whop_sdk/types/ai_chat_list_response.py
@@ -4,6 +4,7 @@
from datetime import datetime
from .._models import BaseModel
+from .notification_preferences import NotificationPreferences
__all__ = ["AIChatListResponse", "User"]
@@ -38,6 +39,12 @@ class AIChatListResponse(BaseModel):
message_count: int
"""The total number of messages exchanged in this conversation."""
+ notification_preference: NotificationPreferences
+ """The notification preference for this AI chat.
+
+ `all` delivers AI chat notifications and badges, while `none` mutes them.
+ """
+
title: Optional[str] = None
"""A short descriptive title for this AI chat conversation.
diff --git a/src/whop_sdk/types/ai_chat_update_params.py b/src/whop_sdk/types/ai_chat_update_params.py
index f3fc9bc..7a4773d 100644
--- a/src/whop_sdk/types/ai_chat_update_params.py
+++ b/src/whop_sdk/types/ai_chat_update_params.py
@@ -5,6 +5,8 @@
from typing import Optional
from typing_extensions import TypedDict
+from .notification_preferences import NotificationPreferences
+
__all__ = ["AIChatUpdateParams"]
@@ -15,5 +17,8 @@ class AIChatUpdateParams(TypedDict, total=False):
"biz_XXXXX").
"""
+ notification_preference: Optional[NotificationPreferences]
+ """The notification preference for an AI chat"""
+
title: Optional[str]
"""The new display title for the AI chat thread (e.g., "Help with billing")."""
diff --git a/src/whop_sdk/types/card_brands.py b/src/whop_sdk/types/card_brands.py
index 9d8c7c1..1243eea 100644
--- a/src/whop_sdk/types/card_brands.py
+++ b/src/whop_sdk/types/card_brands.py
@@ -42,5 +42,6 @@
"codensa",
"cabal",
"hipercard",
+ "jcblankapay",
"unknown",
]
diff --git a/src/whop_sdk/types/notification_preferences.py b/src/whop_sdk/types/notification_preferences.py
new file mode 100644
index 0000000..e3cf22f
--- /dev/null
+++ b/src/whop_sdk/types/notification_preferences.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["NotificationPreferences"]
+
+NotificationPreferences: TypeAlias = Literal["all", "none"]
diff --git a/src/whop_sdk/types/setup_intent.py b/src/whop_sdk/types/setup_intent.py
index 6c3f3ac..a79a2b7 100644
--- a/src/whop_sdk/types/setup_intent.py
+++ b/src/whop_sdk/types/setup_intent.py
@@ -16,6 +16,7 @@
"MemberUser",
"PaymentMethod",
"PaymentMethodCard",
+ "PaymentMethodMailingAddress",
]
@@ -89,6 +90,31 @@ class PaymentMethodCard(BaseModel):
"""The last four digits of the card number. Null if not available."""
+class PaymentMethodMailingAddress(BaseModel):
+ """The mailing address associated with the payment method's user"""
+
+ city: Optional[str] = None
+ """The city of the address."""
+
+ country: Optional[str] = None
+ """The country of the address."""
+
+ line1: Optional[str] = None
+ """The line 1 of the address."""
+
+ line2: Optional[str] = None
+ """The line 2 of the address."""
+
+ name: Optional[str] = None
+ """The name of the customer."""
+
+ postal_code: Optional[str] = None
+ """The postal code of the address."""
+
+ state: Optional[str] = None
+ """The state of the address."""
+
+
class PaymentMethod(BaseModel):
"""The saved payment method created by this setup intent.
@@ -106,6 +132,9 @@ class PaymentMethod(BaseModel):
created_at: datetime
"""The datetime the payment token was created."""
+ mailing_address: Optional[PaymentMethodMailingAddress] = None
+ """The mailing address associated with the payment method's user"""
+
payment_method_type: PaymentMethodTypes
"""The payment method type of the payment method"""
diff --git a/src/whop_sdk/types/setup_intent_list_response.py b/src/whop_sdk/types/setup_intent_list_response.py
index cd30204..93d409a 100644
--- a/src/whop_sdk/types/setup_intent_list_response.py
+++ b/src/whop_sdk/types/setup_intent_list_response.py
@@ -16,6 +16,7 @@
"MemberUser",
"PaymentMethod",
"PaymentMethodCard",
+ "PaymentMethodMailingAddress",
]
@@ -89,6 +90,31 @@ class PaymentMethodCard(BaseModel):
"""The last four digits of the card number. Null if not available."""
+class PaymentMethodMailingAddress(BaseModel):
+ """The mailing address associated with the payment method's user"""
+
+ city: Optional[str] = None
+ """The city of the address."""
+
+ country: Optional[str] = None
+ """The country of the address."""
+
+ line1: Optional[str] = None
+ """The line 1 of the address."""
+
+ line2: Optional[str] = None
+ """The line 2 of the address."""
+
+ name: Optional[str] = None
+ """The name of the customer."""
+
+ postal_code: Optional[str] = None
+ """The postal code of the address."""
+
+ state: Optional[str] = None
+ """The state of the address."""
+
+
class PaymentMethod(BaseModel):
"""The saved payment method created by this setup intent.
@@ -106,6 +132,9 @@ class PaymentMethod(BaseModel):
created_at: datetime
"""The datetime the payment token was created."""
+ mailing_address: Optional[PaymentMethodMailingAddress] = None
+ """The mailing address associated with the payment method's user"""
+
payment_method_type: PaymentMethodTypes
"""The payment method type of the payment method"""
diff --git a/src/whop_sdk/types/shared/payment.py b/src/whop_sdk/types/shared/payment.py
index c9403c4..009f035 100644
--- a/src/whop_sdk/types/shared/payment.py
+++ b/src/whop_sdk/types/shared/payment.py
@@ -166,6 +166,7 @@ class FinancingTransaction(BaseModel):
"cancel",
"verify",
"chargeback",
+ "pre_chargeback",
"three_d_secure",
"fraud_screening",
"authorization",
diff --git a/src/whop_sdk/types/status.py b/src/whop_sdk/types/status.py
new file mode 100644
index 0000000..eff0ae9
--- /dev/null
+++ b/src/whop_sdk/types/status.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["Status"]
+
+Status: TypeAlias = Literal["active", "archived", "deleted"]
diff --git a/tests/api_resources/affiliates/__init__.py b/tests/api_resources/affiliates/__init__.py
new file mode 100644
index 0000000..fd8019a
--- /dev/null
+++ b/tests/api_resources/affiliates/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/affiliates/test_overrides.py b/tests/api_resources/affiliates/test_overrides.py
new file mode 100644
index 0000000..4a9d7f4
--- /dev/null
+++ b/tests/api_resources/affiliates/test_overrides.py
@@ -0,0 +1,759 @@
+# 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 whop_sdk import Whop, AsyncWhop
+from tests.utils import assert_matches_type
+from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
+from whop_sdk.types.affiliates import (
+ OverrideListResponse,
+ OverrideCreateResponse,
+ OverrideDeleteResponse,
+ OverrideUpdateResponse,
+ OverrideRetrieveResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestOverrides:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_overload_1(self, client: Whop) -> None:
+ override = client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params_overload_1(self, client: Whop) -> None:
+ override = client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ applies_to_payments="first_payment",
+ commission_type="percentage",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create_overload_1(self, client: Whop) -> None:
+ response = client.affiliates.overrides.with_raw_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create_overload_1(self, client: Whop) -> None:
+ with client.affiliates.overrides.with_streaming_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_create_overload_1(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_id` but received ''"):
+ client.affiliates.overrides.with_raw_response.create(
+ path_id="",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_overload_2(self, client: Whop) -> None:
+ override = client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None:
+ override = client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ commission_type="percentage",
+ product_id="prod_xxxxxxxxxxxxx",
+ revenue_basis="pre_fees",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create_overload_2(self, client: Whop) -> None:
+ response = client.affiliates.overrides.with_raw_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create_overload_2(self, client: Whop) -> None:
+ with client.affiliates.overrides.with_streaming_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_create_overload_2(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_id` but received ''"):
+ client.affiliates.overrides.with_raw_response.create(
+ path_id="",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Whop) -> None:
+ override = client.affiliates.overrides.retrieve(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideRetrieveResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Whop) -> None:
+ response = client.affiliates.overrides.with_raw_response.retrieve(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = response.parse()
+ assert_matches_type(OverrideRetrieveResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Whop) -> None:
+ with client.affiliates.overrides.with_streaming_response.retrieve(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = response.parse()
+ assert_matches_type(OverrideRetrieveResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.affiliates.overrides.with_raw_response.retrieve(
+ override_id="override_id",
+ id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `override_id` but received ''"):
+ client.affiliates.overrides.with_raw_response.retrieve(
+ override_id="",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update(self, client: Whop) -> None:
+ override = client.affiliates.overrides.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Whop) -> None:
+ override = client.affiliates.overrides.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ applies_to_payments="first_payment",
+ commission_type="percentage",
+ commission_value=6.9,
+ revenue_basis="pre_fees",
+ )
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Whop) -> None:
+ response = client.affiliates.overrides.with_raw_response.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = response.parse()
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Whop) -> None:
+ with client.affiliates.overrides.with_streaming_response.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = response.parse()
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_update(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.affiliates.overrides.with_raw_response.update(
+ override_id="override_id",
+ id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `override_id` but received ''"):
+ client.affiliates.overrides.with_raw_response.update(
+ override_id="",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Whop) -> None:
+ override = client.affiliates.overrides.list(
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(SyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Whop) -> None:
+ override = client.affiliates.overrides.list(
+ id="aff_xxxxxxxxxxxxxx",
+ after="after",
+ before="before",
+ first=42,
+ last=42,
+ override_type="standard",
+ )
+ assert_matches_type(SyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.affiliates.overrides.with_raw_response.list(
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = response.parse()
+ assert_matches_type(SyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.affiliates.overrides.with_streaming_response.list(
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = response.parse()
+ assert_matches_type(SyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_list(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.affiliates.overrides.with_raw_response.list(
+ id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_delete(self, client: Whop) -> None:
+ override = client.affiliates.overrides.delete(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideDeleteResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Whop) -> None:
+ response = client.affiliates.overrides.with_raw_response.delete(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = response.parse()
+ assert_matches_type(OverrideDeleteResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Whop) -> None:
+ with client.affiliates.overrides.with_streaming_response.delete(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = response.parse()
+ assert_matches_type(OverrideDeleteResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_delete(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.affiliates.overrides.with_raw_response.delete(
+ override_id="override_id",
+ id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `override_id` but received ''"):
+ client.affiliates.overrides.with_raw_response.delete(
+ override_id="",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+
+class TestAsyncOverrides:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_overload_1(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params_overload_1(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ applies_to_payments="first_payment",
+ commission_type="percentage",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_create_overload_1(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.overrides.with_raw_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = await response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_create_overload_1(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.overrides.with_streaming_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = await response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_create_overload_1(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.create(
+ path_id="",
+ body_id="id",
+ commission_value=6.9,
+ override_type="standard",
+ plan_id="plan_xxxxxxxxxxxxx",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_overload_2(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params_overload_2(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ commission_type="percentage",
+ product_id="prod_xxxxxxxxxxxxx",
+ revenue_basis="pre_fees",
+ )
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_create_overload_2(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.overrides.with_raw_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = await response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_create_overload_2(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.overrides.with_streaming_response.create(
+ path_id="aff_xxxxxxxxxxxxxx",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = await response.parse()
+ assert_matches_type(OverrideCreateResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_create_overload_2(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.create(
+ path_id="",
+ body_id="id",
+ commission_value=6.9,
+ override_type="rev_share",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.retrieve(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideRetrieveResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.overrides.with_raw_response.retrieve(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = await response.parse()
+ assert_matches_type(OverrideRetrieveResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.overrides.with_streaming_response.retrieve(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = await response.parse()
+ assert_matches_type(OverrideRetrieveResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.retrieve(
+ override_id="override_id",
+ id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `override_id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.retrieve(
+ override_id="",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ applies_to_payments="first_payment",
+ commission_type="percentage",
+ commission_value=6.9,
+ revenue_basis="pre_fees",
+ )
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_update(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.overrides.with_raw_response.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = await response.parse()
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_update(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.overrides.with_streaming_response.update(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = await response.parse()
+ assert_matches_type(OverrideUpdateResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_update(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.update(
+ override_id="override_id",
+ id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `override_id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.update(
+ override_id="",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.list(
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(AsyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.list(
+ id="aff_xxxxxxxxxxxxxx",
+ after="after",
+ before="before",
+ first=42,
+ last=42,
+ override_type="standard",
+ )
+ assert_matches_type(AsyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.overrides.with_raw_response.list(
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = await response.parse()
+ assert_matches_type(AsyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.overrides.with_streaming_response.list(
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = await response.parse()
+ assert_matches_type(AsyncCursorPage[OverrideListResponse], override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_list(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.list(
+ id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncWhop) -> None:
+ override = await async_client.affiliates.overrides.delete(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(OverrideDeleteResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.overrides.with_raw_response.delete(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ override = await response.parse()
+ assert_matches_type(OverrideDeleteResponse, override, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.overrides.with_streaming_response.delete(
+ override_id="override_id",
+ id="aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ override = await response.parse()
+ assert_matches_type(OverrideDeleteResponse, override, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_delete(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.delete(
+ override_id="override_id",
+ id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `override_id` but received ''"):
+ await async_client.affiliates.overrides.with_raw_response.delete(
+ override_id="",
+ id="aff_xxxxxxxxxxxxxx",
+ )
diff --git a/tests/api_resources/test_affiliates.py b/tests/api_resources/test_affiliates.py
new file mode 100644
index 0000000..b4c8041
--- /dev/null
+++ b/tests/api_resources/test_affiliates.py
@@ -0,0 +1,456 @@
+# 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 whop_sdk import Whop, AsyncWhop
+from tests.utils import assert_matches_type
+from whop_sdk.types import (
+ Affiliate,
+ AffiliateListResponse,
+ AffiliateArchiveResponse,
+ AffiliateUnarchiveResponse,
+)
+from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestAffiliates:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create(self, client: Whop) -> None:
+ affiliate = client.affiliates.create(
+ company_id="biz_xxxxxxxxxxxxxx",
+ user_identifier="user_identifier",
+ )
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Whop) -> None:
+ response = client.affiliates.with_raw_response.create(
+ company_id="biz_xxxxxxxxxxxxxx",
+ user_identifier="user_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Whop) -> None:
+ with client.affiliates.with_streaming_response.create(
+ company_id="biz_xxxxxxxxxxxxxx",
+ user_identifier="user_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve(self, client: Whop) -> None:
+ affiliate = client.affiliates.retrieve(
+ "aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Whop) -> None:
+ response = client.affiliates.with_raw_response.retrieve(
+ "aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Whop) -> None:
+ with client.affiliates.with_streaming_response.retrieve(
+ "aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_retrieve(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.affiliates.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Whop) -> None:
+ affiliate = client.affiliates.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(SyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Whop) -> None:
+ affiliate = client.affiliates.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ after="after",
+ before="before",
+ direction="asc",
+ first=42,
+ last=42,
+ order="id",
+ query="query",
+ status="active",
+ )
+ assert_matches_type(SyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.affiliates.with_raw_response.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = response.parse()
+ assert_matches_type(SyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.affiliates.with_streaming_response.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = response.parse()
+ assert_matches_type(SyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_archive(self, client: Whop) -> None:
+ affiliate = client.affiliates.archive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(AffiliateArchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_archive(self, client: Whop) -> None:
+ response = client.affiliates.with_raw_response.archive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = response.parse()
+ assert_matches_type(AffiliateArchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_archive(self, client: Whop) -> None:
+ with client.affiliates.with_streaming_response.archive(
+ "aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = response.parse()
+ assert_matches_type(AffiliateArchiveResponse, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_archive(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.affiliates.with_raw_response.archive(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_unarchive(self, client: Whop) -> None:
+ affiliate = client.affiliates.unarchive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(AffiliateUnarchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_unarchive(self, client: Whop) -> None:
+ response = client.affiliates.with_raw_response.unarchive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = response.parse()
+ assert_matches_type(AffiliateUnarchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_unarchive(self, client: Whop) -> None:
+ with client.affiliates.with_streaming_response.unarchive(
+ "aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = response.parse()
+ assert_matches_type(AffiliateUnarchiveResponse, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_unarchive(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.affiliates.with_raw_response.unarchive(
+ "",
+ )
+
+
+class TestAsyncAffiliates:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create(self, async_client: AsyncWhop) -> None:
+ affiliate = await async_client.affiliates.create(
+ company_id="biz_xxxxxxxxxxxxxx",
+ user_identifier="user_identifier",
+ )
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.with_raw_response.create(
+ company_id="biz_xxxxxxxxxxxxxx",
+ user_identifier="user_identifier",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = await response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.with_streaming_response.create(
+ company_id="biz_xxxxxxxxxxxxxx",
+ user_identifier="user_identifier",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = await response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
+ affiliate = await async_client.affiliates.retrieve(
+ "aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.with_raw_response.retrieve(
+ "aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = await response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.with_streaming_response.retrieve(
+ "aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = await response.parse()
+ assert_matches_type(Affiliate, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.affiliates.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncWhop) -> None:
+ affiliate = await async_client.affiliates.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(AsyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
+ affiliate = await async_client.affiliates.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ after="after",
+ before="before",
+ direction="asc",
+ first=42,
+ last=42,
+ order="id",
+ query="query",
+ status="active",
+ )
+ assert_matches_type(AsyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.with_raw_response.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = await response.parse()
+ assert_matches_type(AsyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.with_streaming_response.list(
+ company_id="biz_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = await response.parse()
+ assert_matches_type(AsyncCursorPage[AffiliateListResponse], affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_archive(self, async_client: AsyncWhop) -> None:
+ affiliate = await async_client.affiliates.archive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(AffiliateArchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_archive(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.with_raw_response.archive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = await response.parse()
+ assert_matches_type(AffiliateArchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_archive(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.with_streaming_response.archive(
+ "aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = await response.parse()
+ assert_matches_type(AffiliateArchiveResponse, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_archive(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.affiliates.with_raw_response.archive(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_unarchive(self, async_client: AsyncWhop) -> None:
+ affiliate = await async_client.affiliates.unarchive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+ assert_matches_type(AffiliateUnarchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_unarchive(self, async_client: AsyncWhop) -> None:
+ response = await async_client.affiliates.with_raw_response.unarchive(
+ "aff_xxxxxxxxxxxxxx",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ affiliate = await response.parse()
+ assert_matches_type(AffiliateUnarchiveResponse, affiliate, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_unarchive(self, async_client: AsyncWhop) -> None:
+ async with async_client.affiliates.with_streaming_response.unarchive(
+ "aff_xxxxxxxxxxxxxx",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ affiliate = await response.parse()
+ assert_matches_type(AffiliateUnarchiveResponse, affiliate, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_unarchive(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.affiliates.with_raw_response.unarchive(
+ "",
+ )
diff --git a/tests/api_resources/test_ai_chats.py b/tests/api_resources/test_ai_chats.py
index 6de8558..d4d6bc2 100644
--- a/tests/api_resources/test_ai_chats.py
+++ b/tests/api_resources/test_ai_chats.py
@@ -124,6 +124,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
ai_chat = client.ai_chats.update(
id="aich_xxxxxxxxxxxxx",
current_company_id="current_company_id",
+ notification_preference="all",
title="title",
)
assert_matches_type(AIChat, ai_chat, path=["response"])
@@ -352,6 +353,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
ai_chat = await async_client.ai_chats.update(
id="aich_xxxxxxxxxxxxx",
current_company_id="current_company_id",
+ notification_preference="all",
title="title",
)
assert_matches_type(AIChat, ai_chat, path=["response"])