diff --git a/.stats.yml b/.stats.yml
index a5722ed0..1b7187f8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 226
+configured_endpoints: 242
diff --git a/README.md b/README.md
index f695ea0b..c1218d8e 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,8 @@ It is generated with [Stainless](https://www.stainless.com/).
Use the Whop MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.
-[](https://cursor.com/en-US/install-mcp?name=%40whop%2Fmcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB3aG9wL21jcCJdLCJlbnYiOnsiV0hPUF9BUElfS0VZIjoiTXkgQVBJIEtleSIsIldIT1BfV0VCSE9PS19TRUNSRVQiOiJNeSBXZWJob29rIEtleSIsIldIT1BfQVBQX0lEIjoiYXBwX3h4eHh4eHh4eHh4eHh4In19)
-[](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40whop%2Fmcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40whop%2Fmcp%22%5D%2C%22env%22%3A%7B%22WHOP_API_KEY%22%3A%22My%20API%20Key%22%2C%22WHOP_WEBHOOK_SECRET%22%3A%22My%20Webhook%20Key%22%2C%22WHOP_APP_ID%22%3A%22app_xxxxxxxxxxxxxx%22%7D%7D)
+[](https://cursor.com/en-US/install-mcp?name=%40whop%2Fmcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB3aG9wL21jcCJdLCJlbnYiOnsiV0hPUF9BUElfS0VZIjoiTXkgQVBJIEtleSIsIldIT1BfV0VCSE9PS19TRUNSRVQiOiJNeSBXZWJob29rIEtleSIsIldIT1BfQVBQX0lEIjoiYXBwX3h4eHh4eHh4eHh4eHh4IiwiV0hPUF9BUElfVkVSU0lPTiI6IjIwMjYtMDYtMDkifX0)
+[](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40whop%2Fmcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40whop%2Fmcp%22%5D%2C%22env%22%3A%7B%22WHOP_API_KEY%22%3A%22My%20API%20Key%22%2C%22WHOP_WEBHOOK_SECRET%22%3A%22My%20Webhook%20Key%22%2C%22WHOP_APP_ID%22%3A%22app_xxxxxxxxxxxxxx%22%2C%22WHOP_API_VERSION%22%3A%222026-06-09%22%7D%7D)
> Note: You may need to set environment variables in your MCP client.
diff --git a/api.md b/api.md
index 8c7ec82d..08fab0da 100644
--- a/api.md
+++ b/api.md
@@ -53,7 +53,6 @@ from whop_sdk.types import (
ShipmentSubstatus,
SupportChannel,
TaxType,
- Transfer,
Visibility,
VisibilityFilter,
WhoCanCommentTypes,
@@ -154,6 +153,8 @@ from whop_sdk.types import (
WebhookCreateResponse,
WebhookListResponse,
WebhookDeleteResponse,
+ ChatMessageCreatedWebhookEvent,
+ ChatReactionCreatedWebhookEvent,
CourseLessonInteractionCompletedWebhookEvent,
DisputeCreatedWebhookEvent,
DisputeUpdatedWebhookEvent,
@@ -171,9 +172,11 @@ from whop_sdk.types import (
InvoicePaidWebhookEvent,
InvoicePastDueWebhookEvent,
InvoiceVoidedWebhookEvent,
+ LedgerAccountFundsAvailableWebhookEvent,
MembershipActivatedWebhookEvent,
MembershipCancelAtPeriodEndChangedWebhookEvent,
MembershipDeactivatedWebhookEvent,
+ MembershipTrialEndingSoonWebhookEvent,
PaymentCreatedWebhookEvent,
PaymentFailedWebhookEvent,
PaymentPendingWebhookEvent,
@@ -208,7 +211,13 @@ Methods:
Types:
```python
-from whop_sdk.types import CheckoutFont, CheckoutShape, PlanListResponse, PlanDeleteResponse
+from whop_sdk.types import (
+ CheckoutFont,
+ CheckoutShape,
+ PlanListResponse,
+ PlanDeleteResponse,
+ PlanCalculateTaxResponse,
+)
```
Methods:
@@ -218,6 +227,7 @@ Methods:
- client.plans.update(id, \*\*params) -> Plan
- client.plans.list(\*\*params) -> SyncCursorPage[PlanListResponse]
- client.plans.delete(id) -> PlanDeleteResponse
+- client.plans.calculate_tax(id, \*\*params) -> PlanCalculateTaxResponse
# Entries
@@ -254,13 +264,13 @@ Methods:
Types:
```python
-from whop_sdk.types import TransferListResponse
+from whop_sdk.types import TransferCreateResponse, TransferRetrieveResponse, TransferListResponse
```
Methods:
-- client.transfers.create(\*\*params) -> Transfer
-- client.transfers.retrieve(id) -> Transfer
+- client.transfers.create(\*\*params) -> TransferCreateResponse
+- client.transfers.retrieve(id) -> TransferRetrieveResponse
- client.transfers.list(\*\*params) -> SyncCursorPage[TransferListResponse]
# LedgerAccounts
@@ -343,14 +353,20 @@ Methods:
Types:
```python
-from whop_sdk.types import CheckoutModes, CheckoutConfigurationListResponse
+from whop_sdk.types import (
+ CheckoutModes,
+ CheckoutConfigurationCreateResponse,
+ CheckoutConfigurationRetrieveResponse,
+ CheckoutConfigurationListResponse,
+)
```
Methods:
-- client.checkout_configurations.create(\*\*params) -> CheckoutConfiguration
-- client.checkout_configurations.retrieve(id) -> CheckoutConfiguration
+- client.checkout_configurations.create(\*\*params) -> CheckoutConfigurationCreateResponse
+- client.checkout_configurations.retrieve(id) -> CheckoutConfigurationRetrieveResponse
- client.checkout_configurations.list(\*\*params) -> SyncCursorPage[CheckoutConfigurationListResponse]
+- client.checkout_configurations.delete(id) -> None
# Messages
@@ -387,15 +403,16 @@ Methods:
Types:
```python
-from whop_sdk.types import User, UserListResponse, UserCheckAccessResponse
+from whop_sdk.types import User, UserCheckAccessResponse
```
Methods:
- client.users.retrieve(id, \*\*params) -> User
- client.users.update(id, \*\*params) -> User
-- client.users.list(\*\*params) -> SyncCursorPage[UserListResponse]
+- client.users.list(\*\*params) -> SyncCursorPage[User]
- client.users.check_access(resource_id, \*, id) -> UserCheckAccessResponse
+- client.users.update_me(\*\*params) -> User
# Payments
@@ -708,7 +725,7 @@ Methods:
Types:
```python
-from whop_sdk.types import Account, AccountSocialLink, AccountListResponse
+from whop_sdk.types import Account, AccountSocialLink
```
Methods:
@@ -716,38 +733,97 @@ Methods:
- client.accounts.create(\*\*params) -> Account
- client.accounts.retrieve(account_id) -> Account
- client.accounts.update(account_id, \*\*params) -> Account
-- client.accounts.list(\*\*params) -> AccountListResponse
+- client.accounts.list(\*\*params) -> SyncCursorPage[Account]
- client.accounts.me() -> Account
-# Wallets
+# FinancialActivity
Types:
```python
-from whop_sdk.types import (
- AccountWallet,
- WalletListResponse,
- WalletBalanceResponse,
- WalletSendResponse,
+from whop_sdk.types import FinancialActivityListResponse
+```
+
+Methods:
+
+- client.financial_activity.list(\*\*params) -> FinancialActivityListResponse
+
+# Payouts
+
+Types:
+
+```python
+from whop_sdk.types import PayoutListResponse
+```
+
+Methods:
+
+- client.payouts.list(\*\*params) -> SyncCursorPage[PayoutListResponse]
+
+# Referrals
+
+## Businesses
+
+Types:
+
+```python
+from whop_sdk.types.referrals import (
+ BusinessRetrieveResponse,
+ BusinessListResponse,
+ BusinessListEarningsResponse,
)
```
Methods:
-- client.wallets.list() -> WalletListResponse
-- client.wallets.balance(account_id) -> WalletBalanceResponse
-- client.wallets.send(account_id, \*\*params) -> WalletSendResponse
+- client.referrals.businesses.retrieve(id) -> BusinessRetrieveResponse
+- client.referrals.businesses.list(\*\*params) -> SyncCursorPage[BusinessListResponse]
+- client.referrals.businesses.list_earnings(\*\*params) -> SyncCursorPage[BusinessListEarningsResponse]
+
+### Earnings
+
+Types:
+
+```python
+from whop_sdk.types.referrals.businesses import EarningListResponse
+```
+
+Methods:
+
+- client.referrals.businesses.earnings.list(id, \*\*params) -> SyncCursorPage[EarningListResponse]
+
+# Cards
+
+Types:
+
+```python
+from whop_sdk.types import CardCreateResponse, CardRetrieveResponse, CardListResponse
+```
+
+Methods:
+
+- client.cards.create(\*\*params) -> CardCreateResponse
+- client.cards.retrieve(card_id, \*\*params) -> CardRetrieveResponse
+- client.cards.list(\*\*params) -> CardListResponse
# Swaps
Types:
```python
-from whop_sdk.types import SwapCreateQuoteResponse
+from whop_sdk.types import (
+ SwapCreateResponse,
+ SwapRetrieveResponse,
+ SwapListResponse,
+ SwapCreateQuoteResponse,
+)
```
Methods:
+- client.swaps.create(\*\*params) -> SwapCreateResponse
+- client.swaps.retrieve(id) -> SwapRetrieveResponse
+- client.swaps.list(\*\*params) -> SwapListResponse
- client.swaps.create_quote(\*\*params) -> SwapCreateQuoteResponse
# Deposits
@@ -755,12 +831,13 @@ Methods:
Types:
```python
-from whop_sdk.types import DepositCreateResponse
+from whop_sdk.types import DepositCreateResponse, DepositListResponse
```
Methods:
- client.deposits.create(\*\*params) -> DepositCreateResponse
+- client.deposits.list(\*\*params) -> DepositListResponse
# SetupIntents
@@ -832,15 +909,21 @@ Types:
from whop_sdk.types import (
VerificationErrorCode,
VerificationStatus,
+ VerificationCreateResponse,
VerificationRetrieveResponse,
+ VerificationUpdateResponse,
VerificationListResponse,
+ VerificationDeleteResponse,
)
```
Methods:
-- client.verifications.retrieve(id) -> VerificationRetrieveResponse
-- client.verifications.list(\*\*params) -> SyncCursorPage[VerificationListResponse]
+- client.verifications.create(\*\*params) -> VerificationCreateResponse
+- client.verifications.retrieve(verification_id) -> VerificationRetrieveResponse
+- client.verifications.update(verification_id, \*\*params) -> VerificationUpdateResponse
+- client.verifications.list(\*\*params) -> VerificationListResponse
+- client.verifications.delete(verification_id) -> VerificationDeleteResponse
# Leads
@@ -1073,7 +1156,7 @@ from whop_sdk.types import AdCampaign, AdCampaignPlatform, AdCampaignStatus, AdC
Methods:
-- client.ad_campaigns.retrieve(id) -> AdCampaign
+- client.ad_campaigns.retrieve(id, \*\*params) -> AdCampaign
- client.ad_campaigns.update(id, \*\*params) -> AdCampaign
- client.ad_campaigns.list(\*\*params) -> SyncCursorPage[AdCampaignListResponse]
- client.ad_campaigns.pause(id) -> AdCampaign
@@ -1095,7 +1178,7 @@ from whop_sdk.types import (
Methods:
-- client.ad_groups.retrieve(id) -> AdGroup
+- client.ad_groups.retrieve(id, \*\*params) -> AdGroup
- client.ad_groups.update(id, \*\*params) -> AdGroup
- client.ad_groups.list(\*\*params) -> SyncCursorPage[AdGroupListResponse]
- client.ad_groups.delete(id) -> AdGroupDeleteResponse
@@ -1112,7 +1195,7 @@ from whop_sdk.types import Ad, ExternalAdStatus, AdListResponse
Methods:
-- client.ads.retrieve(id) -> Ad
+- client.ads.retrieve(id, \*\*params) -> Ad
- client.ads.list(\*\*params) -> SyncCursorPage[AdListResponse]
- client.ads.pause(id) -> Ad
- client.ads.unpause(id) -> Ad
diff --git a/src/whop_sdk/_client.py b/src/whop_sdk/_client.py
index 81df0bfb..f7b08806 100644
--- a/src/whop_sdk/_client.py
+++ b/src/whop_sdk/_client.py
@@ -38,6 +38,7 @@
from .resources import (
ads,
apps,
+ cards,
files,
leads,
plans,
@@ -48,9 +49,9 @@
courses,
entries,
members,
+ payouts,
refunds,
reviews,
- wallets,
accounts,
ai_chats,
bounties,
@@ -64,6 +65,7 @@
ad_groups,
companies,
reactions,
+ referrals,
shipments,
transfers,
ad_reports,
@@ -95,6 +97,7 @@
payout_accounts,
authorized_users,
support_channels,
+ financial_activity,
checkout_configurations,
resolution_center_cases,
company_token_transactions,
@@ -102,6 +105,7 @@
)
from .resources.ads import AdsResource, AsyncAdsResource
from .resources.apps import AppsResource, AsyncAppsResource
+ from .resources.cards import CardsResource, AsyncCardsResource
from .resources.files import FilesResource, AsyncFilesResource
from .resources.leads import LeadsResource, AsyncLeadsResource
from .resources.plans import PlansResource, AsyncPlansResource
@@ -112,9 +116,9 @@
from .resources.courses import CoursesResource, AsyncCoursesResource
from .resources.entries import EntriesResource, AsyncEntriesResource
from .resources.members import MembersResource, AsyncMembersResource
+ from .resources.payouts import PayoutsResource, AsyncPayoutsResource
from .resources.refunds import RefundsResource, AsyncRefundsResource
from .resources.reviews import ReviewsResource, AsyncReviewsResource
- from .resources.wallets import WalletsResource, AsyncWalletsResource
from .resources.accounts import AccountsResource, AsyncAccountsResource
from .resources.ai_chats import AIChatsResource, AsyncAIChatsResource
from .resources.bounties import BountiesResource, AsyncBountiesResource
@@ -158,6 +162,8 @@
from .resources.payout_accounts import PayoutAccountsResource, AsyncPayoutAccountsResource
from .resources.authorized_users import AuthorizedUsersResource, AsyncAuthorizedUsersResource
from .resources.support_channels import SupportChannelsResource, AsyncSupportChannelsResource
+ from .resources.financial_activity import FinancialActivityResource, AsyncFinancialActivityResource
+ from .resources.referrals.referrals import ReferralsResource, AsyncReferralsResource
from .resources.affiliates.affiliates import AffiliatesResource, AsyncAffiliatesResource
from .resources.checkout_configurations import CheckoutConfigurationsResource, AsyncCheckoutConfigurationsResource
from .resources.resolution_center_cases import ResolutionCenterCasesResource, AsyncResolutionCenterCasesResource
@@ -178,6 +184,7 @@ class Whop(SyncAPIClient):
api_key: str
webhook_key: str | None
app_id: str | None
+ version: str | None
def __init__(
self,
@@ -185,6 +192,7 @@ def __init__(
api_key: str | None = None,
webhook_key: str | None = None,
app_id: str | None = None,
+ version: str | None = None,
base_url: str | httpx.URL | None = None,
timeout: float | Timeout | None | NotGiven = not_given,
max_retries: int = DEFAULT_MAX_RETRIES,
@@ -210,6 +218,7 @@ def __init__(
- `api_key` from `WHOP_API_KEY`
- `webhook_key` from `WHOP_WEBHOOK_SECRET`
- `app_id` from `WHOP_APP_ID`
+ - `version` from `WHOP_API_VERSION`
"""
if api_key is None:
api_key = os.environ.get("WHOP_API_KEY")
@@ -227,6 +236,10 @@ def __init__(
app_id = os.environ.get("WHOP_APP_ID")
self.app_id = app_id
+ if version is None:
+ version = os.environ.get("WHOP_API_VERSION") or "2026-06-09"
+ self.version = version
+
if base_url is None:
base_url = os.environ.get("WHOP_BASE_URL")
if base_url is None:
@@ -296,7 +309,6 @@ def webhooks(self) -> WebhooksResource:
@cached_property
def plans(self) -> PlansResource:
- """Plans"""
from .resources.plans import PlansResource
return PlansResource(self)
@@ -317,7 +329,6 @@ def forum_posts(self) -> ForumPostsResource:
@cached_property
def transfers(self) -> TransfersResource:
- """Transfers"""
from .resources.transfers import TransfersResource
return TransfersResource(self)
@@ -359,7 +370,6 @@ def shipments(self) -> ShipmentsResource:
@cached_property
def checkout_configurations(self) -> CheckoutConfigurationsResource:
- """Checkout configurations"""
from .resources.checkout_configurations import CheckoutConfigurationsResource
return CheckoutConfigurationsResource(self)
@@ -380,7 +390,6 @@ def chat_channels(self) -> ChatChannelsResource:
@cached_property
def users(self) -> UsersResource:
- """Users"""
from .resources.users import UsersResource
return UsersResource(self)
@@ -518,10 +527,28 @@ def accounts(self) -> AccountsResource:
return AccountsResource(self)
@cached_property
- def wallets(self) -> WalletsResource:
- from .resources.wallets import WalletsResource
+ def financial_activity(self) -> FinancialActivityResource:
+ from .resources.financial_activity import FinancialActivityResource
+
+ return FinancialActivityResource(self)
+
+ @cached_property
+ def payouts(self) -> PayoutsResource:
+ from .resources.payouts import PayoutsResource
+
+ return PayoutsResource(self)
+
+ @cached_property
+ def referrals(self) -> ReferralsResource:
+ from .resources.referrals import ReferralsResource
- return WalletsResource(self)
+ return ReferralsResource(self)
+
+ @cached_property
+ def cards(self) -> CardsResource:
+ from .resources.cards import CardsResource
+
+ return CardsResource(self)
@cached_property
def swaps(self) -> SwapsResource:
@@ -715,6 +742,7 @@ def default_headers(self) -> dict[str, str | Omit]:
**super().default_headers,
"X-Stainless-Async": "false",
"X-Whop-App-Id": self.app_id if self.app_id is not None else Omit(),
+ "Api-Version-Date": self.version if self.version is not None else Omit(),
**self._custom_headers,
}
@@ -724,6 +752,7 @@ def copy(
api_key: str | None = None,
webhook_key: str | None = None,
app_id: str | None = None,
+ version: str | None = None,
base_url: str | httpx.URL | None = None,
timeout: float | Timeout | None | NotGiven = not_given,
http_client: httpx.Client | None = None,
@@ -760,6 +789,7 @@ def copy(
api_key=api_key or self.api_key,
webhook_key=webhook_key or self.webhook_key,
app_id=app_id or self.app_id,
+ version=version or self.version,
base_url=base_url or self.base_url,
timeout=self.timeout if isinstance(timeout, NotGiven) else timeout,
http_client=http_client,
@@ -812,6 +842,7 @@ class AsyncWhop(AsyncAPIClient):
api_key: str
webhook_key: str | None
app_id: str | None
+ version: str | None
def __init__(
self,
@@ -819,6 +850,7 @@ def __init__(
api_key: str | None = None,
webhook_key: str | None = None,
app_id: str | None = None,
+ version: str | None = None,
base_url: str | httpx.URL | None = None,
timeout: float | Timeout | None | NotGiven = not_given,
max_retries: int = DEFAULT_MAX_RETRIES,
@@ -844,6 +876,7 @@ def __init__(
- `api_key` from `WHOP_API_KEY`
- `webhook_key` from `WHOP_WEBHOOK_SECRET`
- `app_id` from `WHOP_APP_ID`
+ - `version` from `WHOP_API_VERSION`
"""
if api_key is None:
api_key = os.environ.get("WHOP_API_KEY")
@@ -861,6 +894,10 @@ def __init__(
app_id = os.environ.get("WHOP_APP_ID")
self.app_id = app_id
+ if version is None:
+ version = os.environ.get("WHOP_API_VERSION") or "2026-06-09"
+ self.version = version
+
if base_url is None:
base_url = os.environ.get("WHOP_BASE_URL")
if base_url is None:
@@ -930,7 +967,6 @@ def webhooks(self) -> AsyncWebhooksResource:
@cached_property
def plans(self) -> AsyncPlansResource:
- """Plans"""
from .resources.plans import AsyncPlansResource
return AsyncPlansResource(self)
@@ -951,7 +987,6 @@ def forum_posts(self) -> AsyncForumPostsResource:
@cached_property
def transfers(self) -> AsyncTransfersResource:
- """Transfers"""
from .resources.transfers import AsyncTransfersResource
return AsyncTransfersResource(self)
@@ -993,7 +1028,6 @@ def shipments(self) -> AsyncShipmentsResource:
@cached_property
def checkout_configurations(self) -> AsyncCheckoutConfigurationsResource:
- """Checkout configurations"""
from .resources.checkout_configurations import AsyncCheckoutConfigurationsResource
return AsyncCheckoutConfigurationsResource(self)
@@ -1014,7 +1048,6 @@ def chat_channels(self) -> AsyncChatChannelsResource:
@cached_property
def users(self) -> AsyncUsersResource:
- """Users"""
from .resources.users import AsyncUsersResource
return AsyncUsersResource(self)
@@ -1152,10 +1185,28 @@ def accounts(self) -> AsyncAccountsResource:
return AsyncAccountsResource(self)
@cached_property
- def wallets(self) -> AsyncWalletsResource:
- from .resources.wallets import AsyncWalletsResource
+ def financial_activity(self) -> AsyncFinancialActivityResource:
+ from .resources.financial_activity import AsyncFinancialActivityResource
+
+ return AsyncFinancialActivityResource(self)
+
+ @cached_property
+ def payouts(self) -> AsyncPayoutsResource:
+ from .resources.payouts import AsyncPayoutsResource
- return AsyncWalletsResource(self)
+ return AsyncPayoutsResource(self)
+
+ @cached_property
+ def referrals(self) -> AsyncReferralsResource:
+ from .resources.referrals import AsyncReferralsResource
+
+ return AsyncReferralsResource(self)
+
+ @cached_property
+ def cards(self) -> AsyncCardsResource:
+ from .resources.cards import AsyncCardsResource
+
+ return AsyncCardsResource(self)
@cached_property
def swaps(self) -> AsyncSwapsResource:
@@ -1349,6 +1400,7 @@ def default_headers(self) -> dict[str, str | Omit]:
**super().default_headers,
"X-Stainless-Async": f"async:{get_async_library()}",
"X-Whop-App-Id": self.app_id if self.app_id is not None else Omit(),
+ "Api-Version-Date": self.version if self.version is not None else Omit(),
**self._custom_headers,
}
@@ -1358,6 +1410,7 @@ def copy(
api_key: str | None = None,
webhook_key: str | None = None,
app_id: str | None = None,
+ version: str | None = None,
base_url: str | httpx.URL | None = None,
timeout: float | Timeout | None | NotGiven = not_given,
http_client: httpx.AsyncClient | None = None,
@@ -1394,6 +1447,7 @@ def copy(
api_key=api_key or self.api_key,
webhook_key=webhook_key or self.webhook_key,
app_id=app_id or self.app_id,
+ version=version or self.version,
base_url=base_url or self.base_url,
timeout=self.timeout if isinstance(timeout, NotGiven) else timeout,
http_client=http_client,
@@ -1491,7 +1545,6 @@ def webhooks(self) -> webhooks.WebhooksResourceWithRawResponse:
@cached_property
def plans(self) -> plans.PlansResourceWithRawResponse:
- """Plans"""
from .resources.plans import PlansResourceWithRawResponse
return PlansResourceWithRawResponse(self._client.plans)
@@ -1512,7 +1565,6 @@ def forum_posts(self) -> forum_posts.ForumPostsResourceWithRawResponse:
@cached_property
def transfers(self) -> transfers.TransfersResourceWithRawResponse:
- """Transfers"""
from .resources.transfers import TransfersResourceWithRawResponse
return TransfersResourceWithRawResponse(self._client.transfers)
@@ -1554,7 +1606,6 @@ def shipments(self) -> shipments.ShipmentsResourceWithRawResponse:
@cached_property
def checkout_configurations(self) -> checkout_configurations.CheckoutConfigurationsResourceWithRawResponse:
- """Checkout configurations"""
from .resources.checkout_configurations import CheckoutConfigurationsResourceWithRawResponse
return CheckoutConfigurationsResourceWithRawResponse(self._client.checkout_configurations)
@@ -1575,7 +1626,6 @@ def chat_channels(self) -> chat_channels.ChatChannelsResourceWithRawResponse:
@cached_property
def users(self) -> users.UsersResourceWithRawResponse:
- """Users"""
from .resources.users import UsersResourceWithRawResponse
return UsersResourceWithRawResponse(self._client.users)
@@ -1713,10 +1763,28 @@ def accounts(self) -> accounts.AccountsResourceWithRawResponse:
return AccountsResourceWithRawResponse(self._client.accounts)
@cached_property
- def wallets(self) -> wallets.WalletsResourceWithRawResponse:
- from .resources.wallets import WalletsResourceWithRawResponse
+ def financial_activity(self) -> financial_activity.FinancialActivityResourceWithRawResponse:
+ from .resources.financial_activity import FinancialActivityResourceWithRawResponse
+
+ return FinancialActivityResourceWithRawResponse(self._client.financial_activity)
+
+ @cached_property
+ def payouts(self) -> payouts.PayoutsResourceWithRawResponse:
+ from .resources.payouts import PayoutsResourceWithRawResponse
+
+ return PayoutsResourceWithRawResponse(self._client.payouts)
+
+ @cached_property
+ def referrals(self) -> referrals.ReferralsResourceWithRawResponse:
+ from .resources.referrals import ReferralsResourceWithRawResponse
+
+ return ReferralsResourceWithRawResponse(self._client.referrals)
+
+ @cached_property
+ def cards(self) -> cards.CardsResourceWithRawResponse:
+ from .resources.cards import CardsResourceWithRawResponse
- return WalletsResourceWithRawResponse(self._client.wallets)
+ return CardsResourceWithRawResponse(self._client.cards)
@cached_property
def swaps(self) -> swaps.SwapsResourceWithRawResponse:
@@ -1937,7 +2005,6 @@ def webhooks(self) -> webhooks.AsyncWebhooksResourceWithRawResponse:
@cached_property
def plans(self) -> plans.AsyncPlansResourceWithRawResponse:
- """Plans"""
from .resources.plans import AsyncPlansResourceWithRawResponse
return AsyncPlansResourceWithRawResponse(self._client.plans)
@@ -1958,7 +2025,6 @@ def forum_posts(self) -> forum_posts.AsyncForumPostsResourceWithRawResponse:
@cached_property
def transfers(self) -> transfers.AsyncTransfersResourceWithRawResponse:
- """Transfers"""
from .resources.transfers import AsyncTransfersResourceWithRawResponse
return AsyncTransfersResourceWithRawResponse(self._client.transfers)
@@ -2000,7 +2066,6 @@ def shipments(self) -> shipments.AsyncShipmentsResourceWithRawResponse:
@cached_property
def checkout_configurations(self) -> checkout_configurations.AsyncCheckoutConfigurationsResourceWithRawResponse:
- """Checkout configurations"""
from .resources.checkout_configurations import AsyncCheckoutConfigurationsResourceWithRawResponse
return AsyncCheckoutConfigurationsResourceWithRawResponse(self._client.checkout_configurations)
@@ -2021,7 +2086,6 @@ def chat_channels(self) -> chat_channels.AsyncChatChannelsResourceWithRawRespons
@cached_property
def users(self) -> users.AsyncUsersResourceWithRawResponse:
- """Users"""
from .resources.users import AsyncUsersResourceWithRawResponse
return AsyncUsersResourceWithRawResponse(self._client.users)
@@ -2159,10 +2223,28 @@ def accounts(self) -> accounts.AsyncAccountsResourceWithRawResponse:
return AsyncAccountsResourceWithRawResponse(self._client.accounts)
@cached_property
- def wallets(self) -> wallets.AsyncWalletsResourceWithRawResponse:
- from .resources.wallets import AsyncWalletsResourceWithRawResponse
+ def financial_activity(self) -> financial_activity.AsyncFinancialActivityResourceWithRawResponse:
+ from .resources.financial_activity import AsyncFinancialActivityResourceWithRawResponse
+
+ return AsyncFinancialActivityResourceWithRawResponse(self._client.financial_activity)
+
+ @cached_property
+ def payouts(self) -> payouts.AsyncPayoutsResourceWithRawResponse:
+ from .resources.payouts import AsyncPayoutsResourceWithRawResponse
+
+ return AsyncPayoutsResourceWithRawResponse(self._client.payouts)
+
+ @cached_property
+ def referrals(self) -> referrals.AsyncReferralsResourceWithRawResponse:
+ from .resources.referrals import AsyncReferralsResourceWithRawResponse
- return AsyncWalletsResourceWithRawResponse(self._client.wallets)
+ return AsyncReferralsResourceWithRawResponse(self._client.referrals)
+
+ @cached_property
+ def cards(self) -> cards.AsyncCardsResourceWithRawResponse:
+ from .resources.cards import AsyncCardsResourceWithRawResponse
+
+ return AsyncCardsResourceWithRawResponse(self._client.cards)
@cached_property
def swaps(self) -> swaps.AsyncSwapsResourceWithRawResponse:
@@ -2385,7 +2467,6 @@ def webhooks(self) -> webhooks.WebhooksResourceWithStreamingResponse:
@cached_property
def plans(self) -> plans.PlansResourceWithStreamingResponse:
- """Plans"""
from .resources.plans import PlansResourceWithStreamingResponse
return PlansResourceWithStreamingResponse(self._client.plans)
@@ -2406,7 +2487,6 @@ def forum_posts(self) -> forum_posts.ForumPostsResourceWithStreamingResponse:
@cached_property
def transfers(self) -> transfers.TransfersResourceWithStreamingResponse:
- """Transfers"""
from .resources.transfers import TransfersResourceWithStreamingResponse
return TransfersResourceWithStreamingResponse(self._client.transfers)
@@ -2448,7 +2528,6 @@ def shipments(self) -> shipments.ShipmentsResourceWithStreamingResponse:
@cached_property
def checkout_configurations(self) -> checkout_configurations.CheckoutConfigurationsResourceWithStreamingResponse:
- """Checkout configurations"""
from .resources.checkout_configurations import CheckoutConfigurationsResourceWithStreamingResponse
return CheckoutConfigurationsResourceWithStreamingResponse(self._client.checkout_configurations)
@@ -2469,7 +2548,6 @@ def chat_channels(self) -> chat_channels.ChatChannelsResourceWithStreamingRespon
@cached_property
def users(self) -> users.UsersResourceWithStreamingResponse:
- """Users"""
from .resources.users import UsersResourceWithStreamingResponse
return UsersResourceWithStreamingResponse(self._client.users)
@@ -2607,10 +2685,28 @@ def accounts(self) -> accounts.AccountsResourceWithStreamingResponse:
return AccountsResourceWithStreamingResponse(self._client.accounts)
@cached_property
- def wallets(self) -> wallets.WalletsResourceWithStreamingResponse:
- from .resources.wallets import WalletsResourceWithStreamingResponse
+ def financial_activity(self) -> financial_activity.FinancialActivityResourceWithStreamingResponse:
+ from .resources.financial_activity import FinancialActivityResourceWithStreamingResponse
+
+ return FinancialActivityResourceWithStreamingResponse(self._client.financial_activity)
+
+ @cached_property
+ def payouts(self) -> payouts.PayoutsResourceWithStreamingResponse:
+ from .resources.payouts import PayoutsResourceWithStreamingResponse
+
+ return PayoutsResourceWithStreamingResponse(self._client.payouts)
+
+ @cached_property
+ def referrals(self) -> referrals.ReferralsResourceWithStreamingResponse:
+ from .resources.referrals import ReferralsResourceWithStreamingResponse
- return WalletsResourceWithStreamingResponse(self._client.wallets)
+ return ReferralsResourceWithStreamingResponse(self._client.referrals)
+
+ @cached_property
+ def cards(self) -> cards.CardsResourceWithStreamingResponse:
+ from .resources.cards import CardsResourceWithStreamingResponse
+
+ return CardsResourceWithStreamingResponse(self._client.cards)
@cached_property
def swaps(self) -> swaps.SwapsResourceWithStreamingResponse:
@@ -2833,7 +2929,6 @@ def webhooks(self) -> webhooks.AsyncWebhooksResourceWithStreamingResponse:
@cached_property
def plans(self) -> plans.AsyncPlansResourceWithStreamingResponse:
- """Plans"""
from .resources.plans import AsyncPlansResourceWithStreamingResponse
return AsyncPlansResourceWithStreamingResponse(self._client.plans)
@@ -2854,7 +2949,6 @@ def forum_posts(self) -> forum_posts.AsyncForumPostsResourceWithStreamingRespons
@cached_property
def transfers(self) -> transfers.AsyncTransfersResourceWithStreamingResponse:
- """Transfers"""
from .resources.transfers import AsyncTransfersResourceWithStreamingResponse
return AsyncTransfersResourceWithStreamingResponse(self._client.transfers)
@@ -2898,7 +2992,6 @@ def shipments(self) -> shipments.AsyncShipmentsResourceWithStreamingResponse:
def checkout_configurations(
self,
) -> checkout_configurations.AsyncCheckoutConfigurationsResourceWithStreamingResponse:
- """Checkout configurations"""
from .resources.checkout_configurations import AsyncCheckoutConfigurationsResourceWithStreamingResponse
return AsyncCheckoutConfigurationsResourceWithStreamingResponse(self._client.checkout_configurations)
@@ -2919,7 +3012,6 @@ def chat_channels(self) -> chat_channels.AsyncChatChannelsResourceWithStreamingR
@cached_property
def users(self) -> users.AsyncUsersResourceWithStreamingResponse:
- """Users"""
from .resources.users import AsyncUsersResourceWithStreamingResponse
return AsyncUsersResourceWithStreamingResponse(self._client.users)
@@ -3057,10 +3149,28 @@ def accounts(self) -> accounts.AsyncAccountsResourceWithStreamingResponse:
return AsyncAccountsResourceWithStreamingResponse(self._client.accounts)
@cached_property
- def wallets(self) -> wallets.AsyncWalletsResourceWithStreamingResponse:
- from .resources.wallets import AsyncWalletsResourceWithStreamingResponse
+ def financial_activity(self) -> financial_activity.AsyncFinancialActivityResourceWithStreamingResponse:
+ from .resources.financial_activity import AsyncFinancialActivityResourceWithStreamingResponse
+
+ return AsyncFinancialActivityResourceWithStreamingResponse(self._client.financial_activity)
+
+ @cached_property
+ def payouts(self) -> payouts.AsyncPayoutsResourceWithStreamingResponse:
+ from .resources.payouts import AsyncPayoutsResourceWithStreamingResponse
+
+ return AsyncPayoutsResourceWithStreamingResponse(self._client.payouts)
+
+ @cached_property
+ def referrals(self) -> referrals.AsyncReferralsResourceWithStreamingResponse:
+ from .resources.referrals import AsyncReferralsResourceWithStreamingResponse
+
+ return AsyncReferralsResourceWithStreamingResponse(self._client.referrals)
+
+ @cached_property
+ def cards(self) -> cards.AsyncCardsResourceWithStreamingResponse:
+ from .resources.cards import AsyncCardsResourceWithStreamingResponse
- return AsyncWalletsResourceWithStreamingResponse(self._client.wallets)
+ return AsyncCardsResourceWithStreamingResponse(self._client.cards)
@cached_property
def swaps(self) -> swaps.AsyncSwapsResourceWithStreamingResponse:
diff --git a/src/whop_sdk/resources/__init__.py b/src/whop_sdk/resources/__init__.py
index 6cd6f052..492cd7c6 100644
--- a/src/whop_sdk/resources/__init__.py
+++ b/src/whop_sdk/resources/__init__.py
@@ -16,6 +16,14 @@
AppsResourceWithStreamingResponse,
AsyncAppsResourceWithStreamingResponse,
)
+from .cards import (
+ CardsResource,
+ AsyncCardsResource,
+ CardsResourceWithRawResponse,
+ AsyncCardsResourceWithRawResponse,
+ CardsResourceWithStreamingResponse,
+ AsyncCardsResourceWithStreamingResponse,
+)
from .files import (
FilesResource,
AsyncFilesResource,
@@ -96,6 +104,14 @@
MembersResourceWithStreamingResponse,
AsyncMembersResourceWithStreamingResponse,
)
+from .payouts import (
+ PayoutsResource,
+ AsyncPayoutsResource,
+ PayoutsResourceWithRawResponse,
+ AsyncPayoutsResourceWithRawResponse,
+ PayoutsResourceWithStreamingResponse,
+ AsyncPayoutsResourceWithStreamingResponse,
+)
from .refunds import (
RefundsResource,
AsyncRefundsResource,
@@ -112,14 +128,6 @@
ReviewsResourceWithStreamingResponse,
AsyncReviewsResourceWithStreamingResponse,
)
-from .wallets import (
- WalletsResource,
- AsyncWalletsResource,
- WalletsResourceWithRawResponse,
- AsyncWalletsResourceWithRawResponse,
- WalletsResourceWithStreamingResponse,
- AsyncWalletsResourceWithStreamingResponse,
-)
from .accounts import (
AccountsResource,
AsyncAccountsResource,
@@ -224,6 +232,14 @@
ReactionsResourceWithStreamingResponse,
AsyncReactionsResourceWithStreamingResponse,
)
+from .referrals import (
+ ReferralsResource,
+ AsyncReferralsResource,
+ ReferralsResourceWithRawResponse,
+ AsyncReferralsResourceWithRawResponse,
+ ReferralsResourceWithStreamingResponse,
+ AsyncReferralsResourceWithStreamingResponse,
+)
from .shipments import (
ShipmentsResource,
AsyncShipmentsResource,
@@ -472,6 +488,14 @@
SupportChannelsResourceWithStreamingResponse,
AsyncSupportChannelsResourceWithStreamingResponse,
)
+from .financial_activity import (
+ FinancialActivityResource,
+ AsyncFinancialActivityResource,
+ FinancialActivityResourceWithRawResponse,
+ AsyncFinancialActivityResourceWithRawResponse,
+ FinancialActivityResourceWithStreamingResponse,
+ AsyncFinancialActivityResourceWithStreamingResponse,
+)
from .checkout_configurations import (
CheckoutConfigurationsResource,
AsyncCheckoutConfigurationsResource,
@@ -734,12 +758,30 @@
"AsyncAccountsResourceWithRawResponse",
"AccountsResourceWithStreamingResponse",
"AsyncAccountsResourceWithStreamingResponse",
- "WalletsResource",
- "AsyncWalletsResource",
- "WalletsResourceWithRawResponse",
- "AsyncWalletsResourceWithRawResponse",
- "WalletsResourceWithStreamingResponse",
- "AsyncWalletsResourceWithStreamingResponse",
+ "FinancialActivityResource",
+ "AsyncFinancialActivityResource",
+ "FinancialActivityResourceWithRawResponse",
+ "AsyncFinancialActivityResourceWithRawResponse",
+ "FinancialActivityResourceWithStreamingResponse",
+ "AsyncFinancialActivityResourceWithStreamingResponse",
+ "PayoutsResource",
+ "AsyncPayoutsResource",
+ "PayoutsResourceWithRawResponse",
+ "AsyncPayoutsResourceWithRawResponse",
+ "PayoutsResourceWithStreamingResponse",
+ "AsyncPayoutsResourceWithStreamingResponse",
+ "ReferralsResource",
+ "AsyncReferralsResource",
+ "ReferralsResourceWithRawResponse",
+ "AsyncReferralsResourceWithRawResponse",
+ "ReferralsResourceWithStreamingResponse",
+ "AsyncReferralsResourceWithStreamingResponse",
+ "CardsResource",
+ "AsyncCardsResource",
+ "CardsResourceWithRawResponse",
+ "AsyncCardsResourceWithRawResponse",
+ "CardsResourceWithStreamingResponse",
+ "AsyncCardsResourceWithStreamingResponse",
"SwapsResource",
"AsyncSwapsResource",
"SwapsResourceWithRawResponse",
diff --git a/src/whop_sdk/resources/accounts.py b/src/whop_sdk/resources/accounts.py
index 16264fbd..4f8189cb 100644
--- a/src/whop_sdk/resources/accounts.py
+++ b/src/whop_sdk/resources/accounts.py
@@ -7,7 +7,7 @@
import httpx
from ..types import account_list_params, account_create_params, account_update_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -17,9 +17,9 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from .._base_client import make_request_options
+from ..pagination import SyncCursorPage, AsyncCursorPage
+from .._base_client import AsyncPaginator, make_request_options
from ..types.account import Account
-from ..types.account_list_response import AccountListResponse
__all__ = ["AccountsResource", "AsyncAccountsResource"]
@@ -132,17 +132,31 @@ def update(
affiliate_instructions: Optional[str] | Omit = omit,
banner_image: Optional[Dict[str, object]] | Omit = omit,
business_type: Optional[str] | Omit = omit,
+ country: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
featured_affiliate_product_id: Optional[str] | Omit = omit,
+ home_preferences: SequenceNotStr[str] | Omit = omit,
industry_group: Optional[str] | Omit = omit,
industry_type: Optional[str] | Omit = omit,
+ invoice_prefix: Optional[str] | Omit = omit,
logo: Optional[Dict[str, object]] | Omit = omit,
metadata: Dict[str, object] | Omit = omit,
+ onboarding_type: Optional[str] | Omit = omit,
+ opengraph_image: Optional[Dict[str, object]] | Omit = omit,
+ opengraph_image_variant: Optional[str] | Omit = omit,
+ other_business_description: Optional[str] | Omit = omit,
+ other_industry_description: Optional[str] | Omit = omit,
+ require_2fa: bool | Omit = omit,
route: Optional[str] | Omit = omit,
send_customer_emails: bool | Omit = omit,
+ show_joined_whops: bool | Omit = omit,
+ show_reviews_dtc: bool | Omit = omit,
+ show_user_directory: bool | Omit = omit,
social_links: Iterable[Dict[str, object]] | Omit = omit,
+ store_page_config: Optional[Dict[str, object]] | Omit = omit,
target_audience: Optional[str] | Omit = omit,
title: Optional[str] | Omit = omit,
+ use_logo_as_opengraph_image_fallback: bool | 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,
@@ -165,28 +179,57 @@ def update(
business_type: The high-level business category for the account.
+ country: The country the account is located in.
+
description: A promotional description for the account.
featured_affiliate_product_id: The ID of the product to feature for affiliates. Pass null to clear.
+ home_preferences: Preferences for the public business home page.
+
industry_group: The industry group the account belongs to.
industry_type: The specific industry vertical the account operates in.
+ invoice_prefix: The prefix to use for account invoices.
+
logo: Attachment input for the account logo.
metadata: Arbitrary key/value metadata to store on the account.
+ onboarding_type: The type of onboarding the account has completed.
+
+ opengraph_image: Attachment input for the account Open Graph image.
+
+ opengraph_image_variant: The account Open Graph image variant.
+
+ other_business_description: The description of the business type when business_type is other.
+
+ other_industry_description: The description of the industry type when industry_type is other.
+
+ require_2fa: Whether the account requires authorized users to have two-factor authentication
+ enabled.
+
route: The unique URL slug for the account.
send_customer_emails: Whether Whop sends transactional emails to customers on behalf of this account.
+ show_joined_whops: Whether the account appears in joined whops on other accounts.
+
+ show_reviews_dtc: Whether reviews are displayed on direct-to-consumer product pages.
+
+ show_user_directory: Whether the account shows users in the user directory.
+
social_links: The full list of social links to display for the account.
+ store_page_config: Store page display configuration for the account.
+
target_audience: The target audience for this account.
title: The display name of the account.
+ use_logo_as_opengraph_image_fallback: Whether the account uses its logo as the fallback Open Graph image.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -205,17 +248,31 @@ def update(
"affiliate_instructions": affiliate_instructions,
"banner_image": banner_image,
"business_type": business_type,
+ "country": country,
"description": description,
"featured_affiliate_product_id": featured_affiliate_product_id,
+ "home_preferences": home_preferences,
"industry_group": industry_group,
"industry_type": industry_type,
+ "invoice_prefix": invoice_prefix,
"logo": logo,
"metadata": metadata,
+ "onboarding_type": onboarding_type,
+ "opengraph_image": opengraph_image,
+ "opengraph_image_variant": opengraph_image_variant,
+ "other_business_description": other_business_description,
+ "other_industry_description": other_industry_description,
+ "require_2fa": require_2fa,
"route": route,
"send_customer_emails": send_customer_emails,
+ "show_joined_whops": show_joined_whops,
+ "show_reviews_dtc": show_reviews_dtc,
+ "show_user_directory": show_user_directory,
"social_links": social_links,
+ "store_page_config": store_page_config,
"target_audience": target_audience,
"title": title,
+ "use_logo_as_opengraph_image_fallback": use_logo_as_opengraph_image_fallback,
},
account_update_params.AccountUpdateParams,
),
@@ -228,15 +285,17 @@ def update(
def list(
self,
*,
- page: int | Omit = omit,
- per: int | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ last: int | 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,
- ) -> AccountListResponse:
+ ) -> SyncCursorPage[Account]:
"""Lists accounts visible to the credential.
User tokens return the user's business
@@ -244,10 +303,13 @@ def list(
its connected accounts.
Args:
- page: The page number to retrieve
+ after: A cursor; returns accounts after this position.
- per: The number of resources to return per page. There is a limit of 50 results per
- page.
+ before: A cursor; returns accounts before this position.
+
+ first: The number of accounts to return (default 10, max 50).
+
+ last: The number of accounts to return from the end of the range.
extra_headers: Send extra headers
@@ -257,8 +319,9 @@ def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return self._get(
+ return self._get_api_list(
"/accounts",
+ page=SyncCursorPage[Account],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -266,13 +329,15 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "page": page,
- "per": per,
+ "after": after,
+ "before": before,
+ "first": first,
+ "last": last,
},
account_list_params.AccountListParams,
),
),
- cast_to=AccountListResponse,
+ model=Account,
)
def me(
@@ -406,17 +471,31 @@ async def update(
affiliate_instructions: Optional[str] | Omit = omit,
banner_image: Optional[Dict[str, object]] | Omit = omit,
business_type: Optional[str] | Omit = omit,
+ country: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
featured_affiliate_product_id: Optional[str] | Omit = omit,
+ home_preferences: SequenceNotStr[str] | Omit = omit,
industry_group: Optional[str] | Omit = omit,
industry_type: Optional[str] | Omit = omit,
+ invoice_prefix: Optional[str] | Omit = omit,
logo: Optional[Dict[str, object]] | Omit = omit,
metadata: Dict[str, object] | Omit = omit,
+ onboarding_type: Optional[str] | Omit = omit,
+ opengraph_image: Optional[Dict[str, object]] | Omit = omit,
+ opengraph_image_variant: Optional[str] | Omit = omit,
+ other_business_description: Optional[str] | Omit = omit,
+ other_industry_description: Optional[str] | Omit = omit,
+ require_2fa: bool | Omit = omit,
route: Optional[str] | Omit = omit,
send_customer_emails: bool | Omit = omit,
+ show_joined_whops: bool | Omit = omit,
+ show_reviews_dtc: bool | Omit = omit,
+ show_user_directory: bool | Omit = omit,
social_links: Iterable[Dict[str, object]] | Omit = omit,
+ store_page_config: Optional[Dict[str, object]] | Omit = omit,
target_audience: Optional[str] | Omit = omit,
title: Optional[str] | Omit = omit,
+ use_logo_as_opengraph_image_fallback: bool | 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,
@@ -439,28 +518,57 @@ async def update(
business_type: The high-level business category for the account.
+ country: The country the account is located in.
+
description: A promotional description for the account.
featured_affiliate_product_id: The ID of the product to feature for affiliates. Pass null to clear.
+ home_preferences: Preferences for the public business home page.
+
industry_group: The industry group the account belongs to.
industry_type: The specific industry vertical the account operates in.
+ invoice_prefix: The prefix to use for account invoices.
+
logo: Attachment input for the account logo.
metadata: Arbitrary key/value metadata to store on the account.
+ onboarding_type: The type of onboarding the account has completed.
+
+ opengraph_image: Attachment input for the account Open Graph image.
+
+ opengraph_image_variant: The account Open Graph image variant.
+
+ other_business_description: The description of the business type when business_type is other.
+
+ other_industry_description: The description of the industry type when industry_type is other.
+
+ require_2fa: Whether the account requires authorized users to have two-factor authentication
+ enabled.
+
route: The unique URL slug for the account.
send_customer_emails: Whether Whop sends transactional emails to customers on behalf of this account.
+ show_joined_whops: Whether the account appears in joined whops on other accounts.
+
+ show_reviews_dtc: Whether reviews are displayed on direct-to-consumer product pages.
+
+ show_user_directory: Whether the account shows users in the user directory.
+
social_links: The full list of social links to display for the account.
+ store_page_config: Store page display configuration for the account.
+
target_audience: The target audience for this account.
title: The display name of the account.
+ use_logo_as_opengraph_image_fallback: Whether the account uses its logo as the fallback Open Graph image.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -479,17 +587,31 @@ async def update(
"affiliate_instructions": affiliate_instructions,
"banner_image": banner_image,
"business_type": business_type,
+ "country": country,
"description": description,
"featured_affiliate_product_id": featured_affiliate_product_id,
+ "home_preferences": home_preferences,
"industry_group": industry_group,
"industry_type": industry_type,
+ "invoice_prefix": invoice_prefix,
"logo": logo,
"metadata": metadata,
+ "onboarding_type": onboarding_type,
+ "opengraph_image": opengraph_image,
+ "opengraph_image_variant": opengraph_image_variant,
+ "other_business_description": other_business_description,
+ "other_industry_description": other_industry_description,
+ "require_2fa": require_2fa,
"route": route,
"send_customer_emails": send_customer_emails,
+ "show_joined_whops": show_joined_whops,
+ "show_reviews_dtc": show_reviews_dtc,
+ "show_user_directory": show_user_directory,
"social_links": social_links,
+ "store_page_config": store_page_config,
"target_audience": target_audience,
"title": title,
+ "use_logo_as_opengraph_image_fallback": use_logo_as_opengraph_image_fallback,
},
account_update_params.AccountUpdateParams,
),
@@ -499,18 +621,20 @@ async def update(
cast_to=Account,
)
- async def list(
+ def list(
self,
*,
- page: int | Omit = omit,
- per: int | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ last: int | 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,
- ) -> AccountListResponse:
+ ) -> AsyncPaginator[Account, AsyncCursorPage[Account]]:
"""Lists accounts visible to the credential.
User tokens return the user's business
@@ -518,10 +642,13 @@ async def list(
its connected accounts.
Args:
- page: The page number to retrieve
+ after: A cursor; returns accounts after this position.
- per: The number of resources to return per page. There is a limit of 50 results per
- page.
+ before: A cursor; returns accounts before this position.
+
+ first: The number of accounts to return (default 10, max 50).
+
+ last: The number of accounts to return from the end of the range.
extra_headers: Send extra headers
@@ -531,22 +658,25 @@ async def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return await self._get(
+ return self._get_api_list(
"/accounts",
+ page=AsyncCursorPage[Account],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=await async_maybe_transform(
+ query=maybe_transform(
{
- "page": page,
- "per": per,
+ "after": after,
+ "before": before,
+ "first": first,
+ "last": last,
},
account_list_params.AccountListParams,
),
),
- cast_to=AccountListResponse,
+ model=Account,
)
async def me(
diff --git a/src/whop_sdk/resources/ad_campaigns.py b/src/whop_sdk/resources/ad_campaigns.py
index 3cbade58..f166f0ce 100644
--- a/src/whop_sdk/resources/ad_campaigns.py
+++ b/src/whop_sdk/resources/ad_campaigns.py
@@ -4,10 +4,16 @@
from typing import Union, Optional
from datetime import datetime
+from typing_extensions import Literal
import httpx
-from ..types import AdCampaignStatus, ad_campaign_list_params, ad_campaign_update_params
+from ..types import (
+ AdCampaignStatus,
+ ad_campaign_list_params,
+ ad_campaign_update_params,
+ ad_campaign_retrieve_params,
+)
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -21,6 +27,7 @@
from ..pagination import SyncCursorPage, AsyncCursorPage
from .._base_client import AsyncPaginator, make_request_options
from ..types.ad_campaign import AdCampaign
+from ..types.shared.direction import Direction
from ..types.ad_campaign_status import AdCampaignStatus
from ..types.ad_campaign_list_response import AdCampaignListResponse
@@ -53,6 +60,8 @@ def retrieve(
self,
id: str,
*,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | 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,
@@ -68,6 +77,12 @@ def retrieve(
- `ad_campaign:basic:read`
Args:
+ stats_from: Inclusive start of the window for the campaign's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for the campaign's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -81,7 +96,17 @@ def retrieve(
return self._get(
path_template("/ad_campaigns/{id}", id=id),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "stats_from": stats_from,
+ "stats_to": stats_to,
+ },
+ ad_campaign_retrieve_params.AdCampaignRetrieveParams,
+ ),
),
cast_to=AdCampaign,
)
@@ -91,6 +116,7 @@ def update(
id: str,
*,
budget: Optional[float] | Omit = omit,
+ desired_cpr: Optional[float] | 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,
@@ -99,7 +125,8 @@ def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AdCampaign:
"""
- Updates an ad campaign synchronously.
+ Updates an ad campaign synchronously and returns it immediately (local-first).
+ The platform push runs in the background; any errors surface on the dashboard.
Required permissions:
@@ -109,6 +136,8 @@ def update(
budget: The campaign budget in dollars. The interpretation (daily or lifetime) follows
the campaign's existing budget type.
+ desired_cpr: The advertiser's desired cost per result in dollars.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -121,7 +150,13 @@ def update(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return self._patch(
path_template("/ad_campaigns/{id}", id=id),
- body=maybe_transform({"budget": budget}, ad_campaign_update_params.AdCampaignUpdateParams),
+ body=maybe_transform(
+ {
+ "budget": budget,
+ "desired_cpr": desired_cpr,
+ },
+ ad_campaign_update_params.AdCampaignUpdateParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -136,9 +171,30 @@ def list(
company_id: Optional[str] | Omit = omit,
created_after: Union[str, datetime, None] | Omit = omit,
created_before: Union[str, datetime, None] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
first: Optional[int] | Omit = omit,
last: Optional[int] | Omit = omit,
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ | Omit = omit,
query: Optional[str] | Omit = omit,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | Omit = omit,
status: Optional[AdCampaignStatus] | 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.
@@ -166,11 +222,22 @@ def list(
created_before: Only return ad campaigns created before this timestamp.
+ direction: The direction of the sort.
+
first: Returns the first _n_ elements from the list.
last: Returns the last _n_ elements from the list.
- query: Case-insensitive substring match against the campaign title.
+ order: The fields the ads dashboard lists (campaigns, ad sets) can be ordered by. Stat
+ columns are computed over the provided stats date range.
+
+ query: Case-insensitive substring match against the campaign title or ID.
+
+ stats_from: Inclusive start of the window for each campaign's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for each campaign's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
status: The status of an ad campaign.
@@ -197,9 +264,13 @@ def list(
"company_id": company_id,
"created_after": created_after,
"created_before": created_before,
+ "direction": direction,
"first": first,
"last": last,
+ "order": order,
"query": query,
+ "stats_from": stats_from,
+ "stats_to": stats_to,
"status": status,
},
ad_campaign_list_params.AdCampaignListParams,
@@ -309,6 +380,8 @@ async def retrieve(
self,
id: str,
*,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | 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,
@@ -324,6 +397,12 @@ async def retrieve(
- `ad_campaign:basic:read`
Args:
+ stats_from: Inclusive start of the window for the campaign's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for the campaign's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -337,7 +416,17 @@ async def retrieve(
return await self._get(
path_template("/ad_campaigns/{id}", id=id),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "stats_from": stats_from,
+ "stats_to": stats_to,
+ },
+ ad_campaign_retrieve_params.AdCampaignRetrieveParams,
+ ),
),
cast_to=AdCampaign,
)
@@ -347,6 +436,7 @@ async def update(
id: str,
*,
budget: Optional[float] | Omit = omit,
+ desired_cpr: Optional[float] | 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,
@@ -355,7 +445,8 @@ async def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AdCampaign:
"""
- Updates an ad campaign synchronously.
+ Updates an ad campaign synchronously and returns it immediately (local-first).
+ The platform push runs in the background; any errors surface on the dashboard.
Required permissions:
@@ -365,6 +456,8 @@ async def update(
budget: The campaign budget in dollars. The interpretation (daily or lifetime) follows
the campaign's existing budget type.
+ desired_cpr: The advertiser's desired cost per result in dollars.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -377,7 +470,13 @@ async def update(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return await self._patch(
path_template("/ad_campaigns/{id}", id=id),
- body=await async_maybe_transform({"budget": budget}, ad_campaign_update_params.AdCampaignUpdateParams),
+ body=await async_maybe_transform(
+ {
+ "budget": budget,
+ "desired_cpr": desired_cpr,
+ },
+ ad_campaign_update_params.AdCampaignUpdateParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -392,9 +491,30 @@ def list(
company_id: Optional[str] | Omit = omit,
created_after: Union[str, datetime, None] | Omit = omit,
created_before: Union[str, datetime, None] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
first: Optional[int] | Omit = omit,
last: Optional[int] | Omit = omit,
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ | Omit = omit,
query: Optional[str] | Omit = omit,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | Omit = omit,
status: Optional[AdCampaignStatus] | 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.
@@ -422,11 +542,22 @@ def list(
created_before: Only return ad campaigns created before this timestamp.
+ direction: The direction of the sort.
+
first: Returns the first _n_ elements from the list.
last: Returns the last _n_ elements from the list.
- query: Case-insensitive substring match against the campaign title.
+ order: The fields the ads dashboard lists (campaigns, ad sets) can be ordered by. Stat
+ columns are computed over the provided stats date range.
+
+ query: Case-insensitive substring match against the campaign title or ID.
+
+ stats_from: Inclusive start of the window for each campaign's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for each campaign's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
status: The status of an ad campaign.
@@ -453,9 +584,13 @@ def list(
"company_id": company_id,
"created_after": created_after,
"created_before": created_before,
+ "direction": direction,
"first": first,
"last": last,
+ "order": order,
"query": query,
+ "stats_from": stats_from,
+ "stats_to": stats_to,
"status": status,
},
ad_campaign_list_params.AdCampaignListParams,
diff --git a/src/whop_sdk/resources/ad_groups.py b/src/whop_sdk/resources/ad_groups.py
index 25cdded6..73bb01cf 100644
--- a/src/whop_sdk/resources/ad_groups.py
+++ b/src/whop_sdk/resources/ad_groups.py
@@ -4,11 +4,12 @@
from typing import Union, Optional
from datetime import datetime
+from typing_extensions import Literal
import httpx
-from ..types import AdBudgetType, AdGroupStatus, ad_group_list_params, ad_group_update_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..types import AdGroupStatus, ad_group_list_params, ad_group_update_params, ad_group_retrieve_params
+from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -21,8 +22,8 @@
from ..pagination import SyncCursorPage, AsyncCursorPage
from .._base_client import AsyncPaginator, make_request_options
from ..types.ad_group import AdGroup
-from ..types.ad_budget_type import AdBudgetType
from ..types.ad_group_status import AdGroupStatus
+from ..types.shared.direction import Direction
from ..types.ad_group_list_response import AdGroupListResponse
from ..types.ad_group_delete_response import AdGroupDeleteResponse
@@ -55,6 +56,8 @@ def retrieve(
self,
id: str,
*,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | 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,
@@ -70,6 +73,12 @@ def retrieve(
- `ad_campaign:basic:read`
Args:
+ stats_from: Inclusive start of the window for the ad group's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for the ad group's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -83,7 +92,17 @@ def retrieve(
return self._get(
path_template("/ad_groups/{id}", id=id),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "stats_from": stats_from,
+ "stats_to": stats_to,
+ },
+ ad_group_retrieve_params.AdGroupRetrieveParams,
+ ),
),
cast_to=AdGroup,
)
@@ -93,12 +112,7 @@ def update(
id: str,
*,
budget: Optional[float] | Omit = omit,
- budget_type: Optional[AdBudgetType] | Omit = omit,
- config: Optional[ad_group_update_params.Config] | Omit = omit,
- daily_budget: Optional[float] | Omit = omit,
- name: Optional[str] | Omit = omit,
- platform_config: Optional[ad_group_update_params.PlatformConfig] | Omit = omit,
- status: Optional[AdGroupStatus] | 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.
extra_headers: Headers | None = None,
@@ -106,8 +120,10 @@ def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AdGroup:
- """
- Updates an existing ad group.
+ """Updates an ad group synchronously and returns it immediately (local-first).
+
+ The
+ platform push runs in the background; any errors surface on the dashboard.
Required permissions:
@@ -115,19 +131,10 @@ def update(
- `ad_campaign:basic:read`
Args:
- budget: Budget amount in dollars.
+ budget: Budget amount in dollars. The interpretation (daily or lifetime) follows the ad
+ group's existing budget type.
- budget_type: The budget type for an ad campaign or ad group.
-
- config: Unified ad group configuration (bidding, optimization, targeting).
-
- daily_budget: Daily budget in dollars.
-
- name: Human-readable ad group name.
-
- platform_config: Platform-specific ad group configuration.
-
- status: The status of an external ad group.
+ title: Human-readable ad group title. Max 255 characters.
extra_headers: Send extra headers
@@ -144,12 +151,7 @@ def update(
body=maybe_transform(
{
"budget": budget,
- "budget_type": budget_type,
- "config": config,
- "daily_budget": daily_budget,
- "name": name,
- "platform_config": platform_config,
- "status": status,
+ "title": title,
},
ad_group_update_params.AdGroupUpdateParams,
),
@@ -162,16 +164,38 @@ def update(
def list(
self,
*,
+ ad_campaign_id: Optional[str] | Omit = omit,
+ ad_campaign_ids: Optional[SequenceNotStr[str]] | Omit = omit,
after: Optional[str] | Omit = omit,
before: Optional[str] | Omit = omit,
campaign_id: Optional[str] | Omit = omit,
company_id: Optional[str] | Omit = omit,
created_after: Union[str, datetime, None] | Omit = omit,
created_before: Union[str, datetime, None] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
first: Optional[int] | Omit = omit,
- include_paused: Optional[bool] | Omit = omit,
last: Optional[int] | Omit = omit,
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ | Omit = omit,
query: Optional[str] | Omit = omit,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | Omit = omit,
status: Optional[AdGroupStatus] | 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.
@@ -189,26 +213,39 @@ def list(
- `ad_campaign:basic:read`
Args:
+ ad_campaign_id: Filter by ad campaign. Provide exactly one of ad_campaign_id or company_id.
+
+ ad_campaign_ids: Only return ad groups belonging to these ad campaigns (max 100). Can be combined
+ with companyId or used on its own.
+
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.
- campaign_id: Filter by campaign. Provide exactly one of campaign_id or company_id.
+ campaign_id: Filter by campaign.
- company_id: Filter by company. Provide exactly one of campaign_id or company_id.
+ company_id: Filter by company. Provide companyId or adCampaignIds.
created_after: Only return ad groups created after this timestamp.
created_before: Only return ad groups created before this timestamp.
- first: Returns the first _n_ elements from the list.
+ direction: The direction of the sort.
- include_paused: When false, excludes paused ad groups so pagination matches the dashboard's
- hide-paused toggle.
+ first: Returns the first _n_ elements from the list.
last: Returns the last _n_ elements from the list.
- query: Case-insensitive substring match against the ad group name.
+ order: The fields the ads dashboard lists (campaigns, ad sets) can be ordered by. Stat
+ columns are computed over the provided stats date range.
+
+ query: Case-insensitive substring match against the ad group name or ID.
+
+ stats_from: Inclusive start of the window for each ad group's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for each ad group's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
status: The status of an external ad group.
@@ -230,16 +267,21 @@ def list(
timeout=timeout,
query=maybe_transform(
{
+ "ad_campaign_id": ad_campaign_id,
+ "ad_campaign_ids": ad_campaign_ids,
"after": after,
"before": before,
"campaign_id": campaign_id,
"company_id": company_id,
"created_after": created_after,
"created_before": created_before,
+ "direction": direction,
"first": first,
- "include_paused": include_paused,
"last": last,
+ "order": order,
"query": query,
+ "stats_from": stats_from,
+ "stats_to": stats_to,
"status": status,
},
ad_group_list_params.AdGroupListParams,
@@ -388,6 +430,8 @@ async def retrieve(
self,
id: str,
*,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | 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,
@@ -403,6 +447,12 @@ async def retrieve(
- `ad_campaign:basic:read`
Args:
+ stats_from: Inclusive start of the window for the ad group's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for the ad group's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -416,7 +466,17 @@ async def retrieve(
return await self._get(
path_template("/ad_groups/{id}", id=id),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "stats_from": stats_from,
+ "stats_to": stats_to,
+ },
+ ad_group_retrieve_params.AdGroupRetrieveParams,
+ ),
),
cast_to=AdGroup,
)
@@ -426,12 +486,7 @@ async def update(
id: str,
*,
budget: Optional[float] | Omit = omit,
- budget_type: Optional[AdBudgetType] | Omit = omit,
- config: Optional[ad_group_update_params.Config] | Omit = omit,
- daily_budget: Optional[float] | Omit = omit,
- name: Optional[str] | Omit = omit,
- platform_config: Optional[ad_group_update_params.PlatformConfig] | Omit = omit,
- status: Optional[AdGroupStatus] | 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.
extra_headers: Headers | None = None,
@@ -439,8 +494,10 @@ async def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AdGroup:
- """
- Updates an existing ad group.
+ """Updates an ad group synchronously and returns it immediately (local-first).
+
+ The
+ platform push runs in the background; any errors surface on the dashboard.
Required permissions:
@@ -448,19 +505,10 @@ async def update(
- `ad_campaign:basic:read`
Args:
- budget: Budget amount in dollars.
+ budget: Budget amount in dollars. The interpretation (daily or lifetime) follows the ad
+ group's existing budget type.
- budget_type: The budget type for an ad campaign or ad group.
-
- config: Unified ad group configuration (bidding, optimization, targeting).
-
- daily_budget: Daily budget in dollars.
-
- name: Human-readable ad group name.
-
- platform_config: Platform-specific ad group configuration.
-
- status: The status of an external ad group.
+ title: Human-readable ad group title. Max 255 characters.
extra_headers: Send extra headers
@@ -477,12 +525,7 @@ async def update(
body=await async_maybe_transform(
{
"budget": budget,
- "budget_type": budget_type,
- "config": config,
- "daily_budget": daily_budget,
- "name": name,
- "platform_config": platform_config,
- "status": status,
+ "title": title,
},
ad_group_update_params.AdGroupUpdateParams,
),
@@ -495,16 +538,38 @@ async def update(
def list(
self,
*,
+ ad_campaign_id: Optional[str] | Omit = omit,
+ ad_campaign_ids: Optional[SequenceNotStr[str]] | Omit = omit,
after: Optional[str] | Omit = omit,
before: Optional[str] | Omit = omit,
campaign_id: Optional[str] | Omit = omit,
company_id: Optional[str] | Omit = omit,
created_after: Union[str, datetime, None] | Omit = omit,
created_before: Union[str, datetime, None] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
first: Optional[int] | Omit = omit,
- include_paused: Optional[bool] | Omit = omit,
last: Optional[int] | Omit = omit,
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ | Omit = omit,
query: Optional[str] | Omit = omit,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | Omit = omit,
status: Optional[AdGroupStatus] | 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.
@@ -522,26 +587,39 @@ def list(
- `ad_campaign:basic:read`
Args:
+ ad_campaign_id: Filter by ad campaign. Provide exactly one of ad_campaign_id or company_id.
+
+ ad_campaign_ids: Only return ad groups belonging to these ad campaigns (max 100). Can be combined
+ with companyId or used on its own.
+
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.
- campaign_id: Filter by campaign. Provide exactly one of campaign_id or company_id.
+ campaign_id: Filter by campaign.
- company_id: Filter by company. Provide exactly one of campaign_id or company_id.
+ company_id: Filter by company. Provide companyId or adCampaignIds.
created_after: Only return ad groups created after this timestamp.
created_before: Only return ad groups created before this timestamp.
- first: Returns the first _n_ elements from the list.
+ direction: The direction of the sort.
- include_paused: When false, excludes paused ad groups so pagination matches the dashboard's
- hide-paused toggle.
+ first: Returns the first _n_ elements from the list.
last: Returns the last _n_ elements from the list.
- query: Case-insensitive substring match against the ad group name.
+ order: The fields the ads dashboard lists (campaigns, ad sets) can be ordered by. Stat
+ columns are computed over the provided stats date range.
+
+ query: Case-insensitive substring match against the ad group name or ID.
+
+ stats_from: Inclusive start of the window for each ad group's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for each ad group's metric fields. Omit both
+ statsFrom and statsTo for all-time stats.
status: The status of an external ad group.
@@ -563,16 +641,21 @@ def list(
timeout=timeout,
query=maybe_transform(
{
+ "ad_campaign_id": ad_campaign_id,
+ "ad_campaign_ids": ad_campaign_ids,
"after": after,
"before": before,
"campaign_id": campaign_id,
"company_id": company_id,
"created_after": created_after,
"created_before": created_before,
+ "direction": direction,
"first": first,
- "include_paused": include_paused,
"last": last,
+ "order": order,
"query": query,
+ "stats_from": stats_from,
+ "stats_to": stats_to,
"status": status,
},
ad_group_list_params.AdGroupListParams,
diff --git a/src/whop_sdk/resources/ad_reports.py b/src/whop_sdk/resources/ad_reports.py
index 1c8cbd81..232bd119 100644
--- a/src/whop_sdk/resources/ad_reports.py
+++ b/src/whop_sdk/resources/ad_reports.py
@@ -9,7 +9,7 @@
import httpx
from ..types import Granularities, ad_report_retrieve_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -53,9 +53,9 @@ def retrieve(
*,
from_: Union[str, datetime],
to: Union[str, datetime],
- ad_campaign_id: Optional[str] | Omit = omit,
- ad_group_id: Optional[str] | Omit = omit,
- ad_id: Optional[str] | Omit = omit,
+ ad_campaign_ids: Optional[SequenceNotStr[str]] | Omit = omit,
+ ad_group_ids: Optional[SequenceNotStr[str]] | Omit = omit,
+ ad_ids: Optional[SequenceNotStr[str]] | Omit = omit,
breakdown: Optional[Literal["campaign", "ad_group", "ad"]] | Omit = omit,
company_id: Optional[str] | Omit = omit,
currency: Optional[str] | Omit = omit,
@@ -67,13 +67,13 @@ def retrieve(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AdReportRetrieveResponse:
- """Performance report for a company, ad campaign, ad group, or ad.
+ """Performance report for a company, ad campaigns, ad groups, or ads.
- Always returns
- aggregate `summary` totals. Set `granularity` (`daily`/`hourly`) to additionally
- get a time series, or set `breakdown` (`campaign`/`ad_group`/`ad`) to
- additionally get per-entity rows inside the requested scope. Exactly one of
- `companyId`, `adCampaignId`, `adGroupId`, or `adId` must be provided.
+ Always
+ returns aggregate `summary` totals summed across the scope. Set `granularity` to
+ additionally get a time series, or set `breakdown` (`campaign`/`ad_group`/`ad`)
+ to additionally get per-entity rows inside the requested scope. Exactly one of
+ `companyId`, `adCampaignIds`, `adGroupIds`, or `adIds` must be provided.
Required permissions:
@@ -84,20 +84,20 @@ def retrieve(
to: Inclusive end of the reporting window.
- ad_campaign_id: The unique identifier of an ad campaign. Mutually exclusive with `companyId`,
- `adGroupId`, and `adId`.
+ ad_campaign_ids: Scope the report to these ad campaigns (max 100); stats are summed across them.
+ Mutually exclusive with `companyId`, `adGroupIds`, and `adIds`.
- ad_group_id: The unique identifier of an ad group. Mutually exclusive with `companyId`,
- `adCampaignId`, and `adId`.
+ ad_group_ids: Scope the report to these ad groups (max 100); stats are summed across them.
+ Mutually exclusive with `companyId`, `adCampaignIds`, and `adIds`.
- ad_id: The unique identifier of an ad. Mutually exclusive with `companyId`,
- `adCampaignId`, and `adGroupId`.
+ ad_ids: Scope the report to these ads (max 100); stats are summed across them. Mutually
+ exclusive with `companyId`, `adCampaignIds`, and `adGroupIds`.
breakdown: Entity level to group an ad report by.
- company_id: The unique identifier of a company. Mutually exclusive with `adCampaignId`,
- `adGroupId`, and `adId`. Use with `breakdown` to fan out across every campaign,
- ad group, or ad in the company without paging.
+ company_id: The unique identifier of a company. Mutually exclusive with `adCampaignIds`,
+ `adGroupIds`, and `adIds`. Use with `breakdown` to fan out across every
+ campaign, ad group, or ad in the company without paging.
currency: ISO 4217 currency code to report `spend` in. Defaults to the company's ads
reporting currency.
@@ -123,9 +123,9 @@ def retrieve(
{
"from_": from_,
"to": to,
- "ad_campaign_id": ad_campaign_id,
- "ad_group_id": ad_group_id,
- "ad_id": ad_id,
+ "ad_campaign_ids": ad_campaign_ids,
+ "ad_group_ids": ad_group_ids,
+ "ad_ids": ad_ids,
"breakdown": breakdown,
"company_id": company_id,
"currency": currency,
@@ -165,9 +165,9 @@ async def retrieve(
*,
from_: Union[str, datetime],
to: Union[str, datetime],
- ad_campaign_id: Optional[str] | Omit = omit,
- ad_group_id: Optional[str] | Omit = omit,
- ad_id: Optional[str] | Omit = omit,
+ ad_campaign_ids: Optional[SequenceNotStr[str]] | Omit = omit,
+ ad_group_ids: Optional[SequenceNotStr[str]] | Omit = omit,
+ ad_ids: Optional[SequenceNotStr[str]] | Omit = omit,
breakdown: Optional[Literal["campaign", "ad_group", "ad"]] | Omit = omit,
company_id: Optional[str] | Omit = omit,
currency: Optional[str] | Omit = omit,
@@ -179,13 +179,13 @@ async def retrieve(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AdReportRetrieveResponse:
- """Performance report for a company, ad campaign, ad group, or ad.
+ """Performance report for a company, ad campaigns, ad groups, or ads.
- Always returns
- aggregate `summary` totals. Set `granularity` (`daily`/`hourly`) to additionally
- get a time series, or set `breakdown` (`campaign`/`ad_group`/`ad`) to
- additionally get per-entity rows inside the requested scope. Exactly one of
- `companyId`, `adCampaignId`, `adGroupId`, or `adId` must be provided.
+ Always
+ returns aggregate `summary` totals summed across the scope. Set `granularity` to
+ additionally get a time series, or set `breakdown` (`campaign`/`ad_group`/`ad`)
+ to additionally get per-entity rows inside the requested scope. Exactly one of
+ `companyId`, `adCampaignIds`, `adGroupIds`, or `adIds` must be provided.
Required permissions:
@@ -196,20 +196,20 @@ async def retrieve(
to: Inclusive end of the reporting window.
- ad_campaign_id: The unique identifier of an ad campaign. Mutually exclusive with `companyId`,
- `adGroupId`, and `adId`.
+ ad_campaign_ids: Scope the report to these ad campaigns (max 100); stats are summed across them.
+ Mutually exclusive with `companyId`, `adGroupIds`, and `adIds`.
- ad_group_id: The unique identifier of an ad group. Mutually exclusive with `companyId`,
- `adCampaignId`, and `adId`.
+ ad_group_ids: Scope the report to these ad groups (max 100); stats are summed across them.
+ Mutually exclusive with `companyId`, `adCampaignIds`, and `adIds`.
- ad_id: The unique identifier of an ad. Mutually exclusive with `companyId`,
- `adCampaignId`, and `adGroupId`.
+ ad_ids: Scope the report to these ads (max 100); stats are summed across them. Mutually
+ exclusive with `companyId`, `adCampaignIds`, and `adGroupIds`.
breakdown: Entity level to group an ad report by.
- company_id: The unique identifier of a company. Mutually exclusive with `adCampaignId`,
- `adGroupId`, and `adId`. Use with `breakdown` to fan out across every campaign,
- ad group, or ad in the company without paging.
+ company_id: The unique identifier of a company. Mutually exclusive with `adCampaignIds`,
+ `adGroupIds`, and `adIds`. Use with `breakdown` to fan out across every
+ campaign, ad group, or ad in the company without paging.
currency: ISO 4217 currency code to report `spend` in. Defaults to the company's ads
reporting currency.
@@ -235,9 +235,9 @@ async def retrieve(
{
"from_": from_,
"to": to,
- "ad_campaign_id": ad_campaign_id,
- "ad_group_id": ad_group_id,
- "ad_id": ad_id,
+ "ad_campaign_ids": ad_campaign_ids,
+ "ad_group_ids": ad_group_ids,
+ "ad_ids": ad_ids,
"breakdown": breakdown,
"company_id": company_id,
"currency": currency,
diff --git a/src/whop_sdk/resources/ads.py b/src/whop_sdk/resources/ads.py
index fc6351c6..7304fe6d 100644
--- a/src/whop_sdk/resources/ads.py
+++ b/src/whop_sdk/resources/ads.py
@@ -8,9 +8,9 @@
import httpx
-from ..types import ExternalAdStatus, ad_list_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import path_template, maybe_transform
+from ..types import ExternalAdStatus, ad_list_params, ad_retrieve_params
+from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from ..types.ad import Ad
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -55,6 +55,8 @@ def retrieve(
self,
id: str,
*,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | 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,
@@ -70,6 +72,12 @@ def retrieve(
- `ad_campaign:basic:read`
Args:
+ stats_from: Inclusive start of the window for the ad's metric fields (spend, impressions,
+ …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for the ad's metric fields. Omit both statsFrom and
+ statsTo for all-time stats.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -83,7 +91,17 @@ def retrieve(
return self._get(
path_template("/ads/{id}", id=id),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "stats_from": stats_from,
+ "stats_to": stats_to,
+ },
+ ad_retrieve_params.AdRetrieveParams,
+ ),
),
cast_to=Ad,
)
@@ -91,17 +109,38 @@ def retrieve(
def list(
self,
*,
+ ad_campaign_id: Optional[str] | Omit = omit,
+ ad_campaign_ids: Optional[SequenceNotStr[str]] | Omit = omit,
ad_group_id: Optional[str] | Omit = omit,
+ ad_group_ids: Optional[SequenceNotStr[str]] | Omit = omit,
after: Optional[str] | Omit = omit,
before: Optional[str] | Omit = omit,
campaign_id: Optional[str] | Omit = omit,
company_id: Optional[str] | Omit = omit,
created_after: Union[str, datetime, None] | Omit = omit,
created_before: Union[str, datetime, None] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
first: Optional[int] | Omit = omit,
- include_paused: Optional[bool] | Omit = omit,
last: Optional[int] | Omit = omit,
- order_by: Optional[Literal["spend", "roas"]] | Omit = omit,
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ | Omit = omit,
+ order_by: Optional[Literal["spend", "return_on_ad_spend", "roas"]] | Omit = omit,
order_direction: Optional[Direction] | Omit = omit,
query: Optional[str] | Omit = omit,
stats_from: Union[str, datetime, None] | Omit = omit,
@@ -122,39 +161,52 @@ def list(
- `ad_campaign:basic:read`
Args:
- ad_group_id: Filter by ad group. Provide exactly one of ad_group_id, campaign_id, or
+ ad_campaign_id: Filter by ad campaign. Provide exactly one of ad_group_id, ad_campaign_id, or
+ company_id.
+
+ ad_campaign_ids: Only return ads belonging to these ad campaigns (max 100). Can be combined with
+ companyId or used on its own.
+
+ ad_group_id: Filter by ad group. Provide exactly one of ad_group_id, ad_campaign_id, or
company_id.
+ ad_group_ids: Only return ads belonging to these ad groups (max 100). Can be combined with
+ companyId or used on its own.
+
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.
- campaign_id: Filter by campaign. Provide exactly one of ad_group_id, campaign_id, or
- company_id.
+ campaign_id: Filter by campaign.
- company_id: Filter by company. Provide exactly one of ad_group_id, campaign_id, or
+ company_id: Filter by company. Provide exactly one of ad_group_id, ad_campaign_id, or
company_id.
created_after: Only return ads created after this timestamp.
created_before: Only return ads created before this timestamp.
- first: Returns the first _n_ elements from the list.
+ direction: The direction of the sort.
- include_paused: When false, excludes paused ads so pagination matches the dashboard's
- hide-paused toggle.
+ first: Returns the first _n_ elements from the list.
last: Returns the last _n_ elements from the list.
- order_by: Columns that the listAds query can sort by.
+ order: The fields the ads dashboard lists (campaigns, ad sets) can be ordered by. Stat
+ columns are computed over the provided stats date range.
+
+ order_by: Columns that the listAds query can sort by. Deprecated — use AdStatOrder.
order_direction: The direction of the sort.
- query: Case-insensitive substring match against the ad title or tag.
+ query: Case-insensitive substring match against the ad title or ID.
- stats_from: Start of the stats date range used when order_by is a stats column.
+ stats_from: Inclusive start of the window for each ad's metric fields (spend, impressions,
+ …) and for stats-column sorting. Omit both statsFrom and statsTo for all-time
+ stats.
- stats_to: End of the stats date range used when order_by is a stats column.
+ stats_to: Inclusive end of the window for each ad's metric fields and for stats-column
+ sorting. Omit both statsFrom and statsTo for all-time stats.
status: The status of an external ad.
@@ -176,16 +228,20 @@ def list(
timeout=timeout,
query=maybe_transform(
{
+ "ad_campaign_id": ad_campaign_id,
+ "ad_campaign_ids": ad_campaign_ids,
"ad_group_id": ad_group_id,
+ "ad_group_ids": ad_group_ids,
"after": after,
"before": before,
"campaign_id": campaign_id,
"company_id": company_id,
"created_after": created_after,
"created_before": created_before,
+ "direction": direction,
"first": first,
- "include_paused": include_paused,
"last": last,
+ "order": order,
"order_by": order_by,
"order_direction": order_direction,
"query": query,
@@ -302,6 +358,8 @@ async def retrieve(
self,
id: str,
*,
+ stats_from: Union[str, datetime, None] | Omit = omit,
+ stats_to: Union[str, datetime, None] | 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,
@@ -317,6 +375,12 @@ async def retrieve(
- `ad_campaign:basic:read`
Args:
+ stats_from: Inclusive start of the window for the ad's metric fields (spend, impressions,
+ …). Omit both statsFrom and statsTo for all-time stats.
+
+ stats_to: Inclusive end of the window for the ad's metric fields. Omit both statsFrom and
+ statsTo for all-time stats.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -330,7 +394,17 @@ async def retrieve(
return await self._get(
path_template("/ads/{id}", id=id),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "stats_from": stats_from,
+ "stats_to": stats_to,
+ },
+ ad_retrieve_params.AdRetrieveParams,
+ ),
),
cast_to=Ad,
)
@@ -338,17 +412,38 @@ async def retrieve(
def list(
self,
*,
+ ad_campaign_id: Optional[str] | Omit = omit,
+ ad_campaign_ids: Optional[SequenceNotStr[str]] | Omit = omit,
ad_group_id: Optional[str] | Omit = omit,
+ ad_group_ids: Optional[SequenceNotStr[str]] | Omit = omit,
after: Optional[str] | Omit = omit,
before: Optional[str] | Omit = omit,
campaign_id: Optional[str] | Omit = omit,
company_id: Optional[str] | Omit = omit,
created_after: Union[str, datetime, None] | Omit = omit,
created_before: Union[str, datetime, None] | Omit = omit,
+ direction: Optional[Direction] | Omit = omit,
first: Optional[int] | Omit = omit,
- include_paused: Optional[bool] | Omit = omit,
last: Optional[int] | Omit = omit,
- order_by: Optional[Literal["spend", "roas"]] | Omit = omit,
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ | Omit = omit,
+ order_by: Optional[Literal["spend", "return_on_ad_spend", "roas"]] | Omit = omit,
order_direction: Optional[Direction] | Omit = omit,
query: Optional[str] | Omit = omit,
stats_from: Union[str, datetime, None] | Omit = omit,
@@ -369,39 +464,52 @@ def list(
- `ad_campaign:basic:read`
Args:
- ad_group_id: Filter by ad group. Provide exactly one of ad_group_id, campaign_id, or
+ ad_campaign_id: Filter by ad campaign. Provide exactly one of ad_group_id, ad_campaign_id, or
+ company_id.
+
+ ad_campaign_ids: Only return ads belonging to these ad campaigns (max 100). Can be combined with
+ companyId or used on its own.
+
+ ad_group_id: Filter by ad group. Provide exactly one of ad_group_id, ad_campaign_id, or
company_id.
+ ad_group_ids: Only return ads belonging to these ad groups (max 100). Can be combined with
+ companyId or used on its own.
+
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.
- campaign_id: Filter by campaign. Provide exactly one of ad_group_id, campaign_id, or
- company_id.
+ campaign_id: Filter by campaign.
- company_id: Filter by company. Provide exactly one of ad_group_id, campaign_id, or
+ company_id: Filter by company. Provide exactly one of ad_group_id, ad_campaign_id, or
company_id.
created_after: Only return ads created after this timestamp.
created_before: Only return ads created before this timestamp.
- first: Returns the first _n_ elements from the list.
+ direction: The direction of the sort.
- include_paused: When false, excludes paused ads so pagination matches the dashboard's
- hide-paused toggle.
+ first: Returns the first _n_ elements from the list.
last: Returns the last _n_ elements from the list.
- order_by: Columns that the listAds query can sort by.
+ order: The fields the ads dashboard lists (campaigns, ad sets) can be ordered by. Stat
+ columns are computed over the provided stats date range.
+
+ order_by: Columns that the listAds query can sort by. Deprecated — use AdStatOrder.
order_direction: The direction of the sort.
- query: Case-insensitive substring match against the ad title or tag.
+ query: Case-insensitive substring match against the ad title or ID.
- stats_from: Start of the stats date range used when order_by is a stats column.
+ stats_from: Inclusive start of the window for each ad's metric fields (spend, impressions,
+ …) and for stats-column sorting. Omit both statsFrom and statsTo for all-time
+ stats.
- stats_to: End of the stats date range used when order_by is a stats column.
+ stats_to: Inclusive end of the window for each ad's metric fields and for stats-column
+ sorting. Omit both statsFrom and statsTo for all-time stats.
status: The status of an external ad.
@@ -423,16 +531,20 @@ def list(
timeout=timeout,
query=maybe_transform(
{
+ "ad_campaign_id": ad_campaign_id,
+ "ad_campaign_ids": ad_campaign_ids,
"ad_group_id": ad_group_id,
+ "ad_group_ids": ad_group_ids,
"after": after,
"before": before,
"campaign_id": campaign_id,
"company_id": company_id,
"created_after": created_after,
"created_before": created_before,
+ "direction": direction,
"first": first,
- "include_paused": include_paused,
"last": last,
+ "order": order,
"order_by": order_by,
"order_direction": order_direction,
"query": query,
diff --git a/src/whop_sdk/resources/authorized_users.py b/src/whop_sdk/resources/authorized_users.py
index 0519e3e2..90c75893 100644
--- a/src/whop_sdk/resources/authorized_users.py
+++ b/src/whop_sdk/resources/authorized_users.py
@@ -56,6 +56,7 @@ def create(
company_id: str,
role: AuthorizedUserRoles,
user_id: str,
+ elevation: Optional[authorized_user_create_params.Elevation] | Omit = omit,
send_emails: Optional[bool] | 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.
@@ -81,6 +82,8 @@ def create(
user_id: The ID of the user to add as an authorized user.
+ elevation: Re-authentication proof required to perform this sensitive action.
+
send_emails: Whether to send notification emails to the user on creation.
extra_headers: Send extra headers
@@ -98,6 +101,7 @@ def create(
"company_id": company_id,
"role": role,
"user_id": user_id,
+ "elevation": elevation,
"send_emails": send_emails,
},
authorized_user_create_params.AuthorizedUserCreateParams,
@@ -304,6 +308,7 @@ async def create(
company_id: str,
role: AuthorizedUserRoles,
user_id: str,
+ elevation: Optional[authorized_user_create_params.Elevation] | Omit = omit,
send_emails: Optional[bool] | 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.
@@ -329,6 +334,8 @@ async def create(
user_id: The ID of the user to add as an authorized user.
+ elevation: Re-authentication proof required to perform this sensitive action.
+
send_emails: Whether to send notification emails to the user on creation.
extra_headers: Send extra headers
@@ -346,6 +353,7 @@ async def create(
"company_id": company_id,
"role": role,
"user_id": user_id,
+ "elevation": elevation,
"send_emails": send_emails,
},
authorized_user_create_params.AuthorizedUserCreateParams,
diff --git a/src/whop_sdk/resources/bounties.py b/src/whop_sdk/resources/bounties.py
index ea396695..7f2a1f46 100644
--- a/src/whop_sdk/resources/bounties.py
+++ b/src/whop_sdk/resources/bounties.py
@@ -2,7 +2,8 @@
from __future__ import annotations
-from typing import Optional
+from typing import Union, Optional
+from datetime import datetime
from typing_extensions import Literal
import httpx
@@ -60,10 +61,17 @@ def create(
title: str,
accepted_submissions_limit: Optional[int] | Omit = omit,
allowed_country_codes: Optional[SequenceNotStr[str]] | Omit = omit,
+ business_goal_type: Optional[
+ Literal["clipping", "post_engagement", "owned_account_growth", "ugc_content", "local_activation", "other"]
+ ]
+ | Omit = omit,
experience_id: Optional[str] | Omit = omit,
origin_account_id: Optional[str] | Omit = omit,
post_markdown_content: Optional[str] | Omit = omit,
post_title: Optional[str] | Omit = omit,
+ scheduled_frequency: Optional[Literal["once", "hourly", "daily", "weekly", "monthly"]] | Omit = omit,
+ scheduled_publish_at: Union[str, datetime, None] | Omit = omit,
+ scheduled_timezone: 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.
extra_headers: Headers | None = None,
@@ -94,6 +102,9 @@ def create(
allowed_country_codes: The ISO3166 country codes where this bounty should be visible. Empty means
globally visible.
+ business_goal_type: What the poster is trying to accomplish with a workforce bounty. Used for
+ product taxonomy and analytics, separate from the bounty's implementation type.
+
experience_id: An optional experience to scope the bounty to.
origin_account_id: The user (user*\\**) or company (biz*\\**) tag whose balance funds this bounty pool.
@@ -106,6 +117,14 @@ def create(
post_title: Optional title for the anchor forum post. Falls back to the bounty title when
omitted.
+ scheduled_frequency: How often a scheduled bounty republishes a new bounty.
+
+ scheduled_publish_at: When to publish the bounty. When provided, the bounty is created as a hidden
+ draft and published at this time instead of immediately. Must be in the future.
+
+ scheduled_timezone: The IANA timezone used for recurring occurrences. Required when
+ scheduled_publish_at is provided.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -124,10 +143,14 @@ def create(
"title": title,
"accepted_submissions_limit": accepted_submissions_limit,
"allowed_country_codes": allowed_country_codes,
+ "business_goal_type": business_goal_type,
"experience_id": experience_id,
"origin_account_id": origin_account_id,
"post_markdown_content": post_markdown_content,
"post_title": post_title,
+ "scheduled_frequency": scheduled_frequency,
+ "scheduled_publish_at": scheduled_publish_at,
+ "scheduled_timezone": scheduled_timezone,
},
bounty_create_params.BountyCreateParams,
),
@@ -179,7 +202,7 @@ def list(
experience_id: Optional[str] | Omit = omit,
first: Optional[int] | Omit = omit,
last: Optional[int] | Omit = omit,
- status: Optional[Literal["published", "archived"]] | Omit = omit,
+ status: Optional[Literal["published", "archived", "scheduled"]] | 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,
@@ -273,10 +296,17 @@ async def create(
title: str,
accepted_submissions_limit: Optional[int] | Omit = omit,
allowed_country_codes: Optional[SequenceNotStr[str]] | Omit = omit,
+ business_goal_type: Optional[
+ Literal["clipping", "post_engagement", "owned_account_growth", "ugc_content", "local_activation", "other"]
+ ]
+ | Omit = omit,
experience_id: Optional[str] | Omit = omit,
origin_account_id: Optional[str] | Omit = omit,
post_markdown_content: Optional[str] | Omit = omit,
post_title: Optional[str] | Omit = omit,
+ scheduled_frequency: Optional[Literal["once", "hourly", "daily", "weekly", "monthly"]] | Omit = omit,
+ scheduled_publish_at: Union[str, datetime, None] | Omit = omit,
+ scheduled_timezone: 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.
extra_headers: Headers | None = None,
@@ -307,6 +337,9 @@ async def create(
allowed_country_codes: The ISO3166 country codes where this bounty should be visible. Empty means
globally visible.
+ business_goal_type: What the poster is trying to accomplish with a workforce bounty. Used for
+ product taxonomy and analytics, separate from the bounty's implementation type.
+
experience_id: An optional experience to scope the bounty to.
origin_account_id: The user (user*\\**) or company (biz*\\**) tag whose balance funds this bounty pool.
@@ -319,6 +352,14 @@ async def create(
post_title: Optional title for the anchor forum post. Falls back to the bounty title when
omitted.
+ scheduled_frequency: How often a scheduled bounty republishes a new bounty.
+
+ scheduled_publish_at: When to publish the bounty. When provided, the bounty is created as a hidden
+ draft and published at this time instead of immediately. Must be in the future.
+
+ scheduled_timezone: The IANA timezone used for recurring occurrences. Required when
+ scheduled_publish_at is provided.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -337,10 +378,14 @@ async def create(
"title": title,
"accepted_submissions_limit": accepted_submissions_limit,
"allowed_country_codes": allowed_country_codes,
+ "business_goal_type": business_goal_type,
"experience_id": experience_id,
"origin_account_id": origin_account_id,
"post_markdown_content": post_markdown_content,
"post_title": post_title,
+ "scheduled_frequency": scheduled_frequency,
+ "scheduled_publish_at": scheduled_publish_at,
+ "scheduled_timezone": scheduled_timezone,
},
bounty_create_params.BountyCreateParams,
),
@@ -392,7 +437,7 @@ def list(
experience_id: Optional[str] | Omit = omit,
first: Optional[int] | Omit = omit,
last: Optional[int] | Omit = omit,
- status: Optional[Literal["published", "archived"]] | Omit = omit,
+ status: Optional[Literal["published", "archived", "scheduled"]] | 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,
diff --git a/src/whop_sdk/resources/cards.py b/src/whop_sdk/resources/cards.py
new file mode 100644
index 00000000..1bdb27f9
--- /dev/null
+++ b/src/whop_sdk/resources/cards.py
@@ -0,0 +1,455 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ..types import card_list_params, card_create_params, card_retrieve_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import path_template, 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 .._base_client import make_request_options
+from ..types.card_list_response import CardListResponse
+from ..types.card_create_response import CardCreateResponse
+from ..types.card_retrieve_response import CardRetrieveResponse
+
+__all__ = ["CardsResource", "AsyncCardsResource"]
+
+
+class CardsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> CardsResourceWithRawResponse:
+ """
+ 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 CardsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> CardsResourceWithStreamingResponse:
+ """
+ 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 CardsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ name: str | Omit = omit,
+ spend_limit: float | Omit = omit,
+ spend_limit_frequency: Literal["daily", "weekly", "monthly", "one_time"] | Omit = omit,
+ transaction_limit: float | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> CardCreateResponse:
+ """Issues a virtual card for an individual (consumer) card issuing account.
+
+ The
+ ledger's owner is passed as exactly one of account*id (a biz* identifier) or
+ user*id (a user* identifier). Returns the newly created card resource.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ name: A display name for the card.
+
+ spend_limit: Spending limit amount, in dollars.
+
+ spend_limit_frequency: The spending limit window.
+
+ transaction_limit: Per-transaction limit amount, in dollars.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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(
+ "/cards",
+ body=maybe_transform(
+ {
+ "account_id": account_id,
+ "name": name,
+ "spend_limit": spend_limit,
+ "spend_limit_frequency": spend_limit_frequency,
+ "transaction_limit": transaction_limit,
+ "user_id": user_id,
+ },
+ card_create_params.CardCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CardCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ card_id: str,
+ *,
+ account_id: str | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> CardRetrieveResponse:
+ """
+ Retrieves a single card by its icrd\\__ identifier, including its secrets (full
+ card number, CVC, and cardholder name) for active cards.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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
+ """
+ if not card_id:
+ raise ValueError(f"Expected a non-empty value for `card_id` but received {card_id!r}")
+ return self._get(
+ path_template("/cards/{card_id}", card_id=card_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "account_id": account_id,
+ "user_id": user_id,
+ },
+ card_retrieve_params.CardRetrieveParams,
+ ),
+ ),
+ cast_to=CardRetrieveResponse,
+ )
+
+ def list(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> CardListResponse:
+ """
+ Lists the issued (Whop Card) virtual and physical cards for a ledger account,
+ including pending invitation cards that have not been issued by the card
+ provider yet. The ledger's owner is passed as exactly one of account*id (a biz*
+ identifier) or user*id (a user* identifier). Non-owner team members only see
+ cards assigned to them. Users without the payout:account:read scope can still
+ list cards assigned to them (for example moderators or external cardholders).
+ Use GET /cards/:card_id to retrieve a single card with its secrets.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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._get(
+ "/cards",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "account_id": account_id,
+ "user_id": user_id,
+ },
+ card_list_params.CardListParams,
+ ),
+ ),
+ cast_to=CardListResponse,
+ )
+
+
+class AsyncCardsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncCardsResourceWithRawResponse:
+ """
+ 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 AsyncCardsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncCardsResourceWithStreamingResponse:
+ """
+ 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 AsyncCardsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ name: str | Omit = omit,
+ spend_limit: float | Omit = omit,
+ spend_limit_frequency: Literal["daily", "weekly", "monthly", "one_time"] | Omit = omit,
+ transaction_limit: float | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> CardCreateResponse:
+ """Issues a virtual card for an individual (consumer) card issuing account.
+
+ The
+ ledger's owner is passed as exactly one of account*id (a biz* identifier) or
+ user*id (a user* identifier). Returns the newly created card resource.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ name: A display name for the card.
+
+ spend_limit: Spending limit amount, in dollars.
+
+ spend_limit_frequency: The spending limit window.
+
+ transaction_limit: Per-transaction limit amount, in dollars.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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(
+ "/cards",
+ body=await async_maybe_transform(
+ {
+ "account_id": account_id,
+ "name": name,
+ "spend_limit": spend_limit,
+ "spend_limit_frequency": spend_limit_frequency,
+ "transaction_limit": transaction_limit,
+ "user_id": user_id,
+ },
+ card_create_params.CardCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CardCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ card_id: str,
+ *,
+ account_id: str | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> CardRetrieveResponse:
+ """
+ Retrieves a single card by its icrd\\__ identifier, including its secrets (full
+ card number, CVC, and cardholder name) for active cards.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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
+ """
+ if not card_id:
+ raise ValueError(f"Expected a non-empty value for `card_id` but received {card_id!r}")
+ return await self._get(
+ path_template("/cards/{card_id}", card_id=card_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "account_id": account_id,
+ "user_id": user_id,
+ },
+ card_retrieve_params.CardRetrieveParams,
+ ),
+ ),
+ cast_to=CardRetrieveResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> CardListResponse:
+ """
+ Lists the issued (Whop Card) virtual and physical cards for a ledger account,
+ including pending invitation cards that have not been issued by the card
+ provider yet. The ledger's owner is passed as exactly one of account*id (a biz*
+ identifier) or user*id (a user* identifier). Non-owner team members only see
+ cards assigned to them. Users without the payout:account:read scope can still
+ list cards assigned to them (for example moderators or external cardholders).
+ Use GET /cards/:card_id to retrieve a single card with its secrets.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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._get(
+ "/cards",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "account_id": account_id,
+ "user_id": user_id,
+ },
+ card_list_params.CardListParams,
+ ),
+ ),
+ cast_to=CardListResponse,
+ )
+
+
+class CardsResourceWithRawResponse:
+ def __init__(self, cards: CardsResource) -> None:
+ self._cards = cards
+
+ self.create = to_raw_response_wrapper(
+ cards.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ cards.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ cards.list,
+ )
+
+
+class AsyncCardsResourceWithRawResponse:
+ def __init__(self, cards: AsyncCardsResource) -> None:
+ self._cards = cards
+
+ self.create = async_to_raw_response_wrapper(
+ cards.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ cards.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ cards.list,
+ )
+
+
+class CardsResourceWithStreamingResponse:
+ def __init__(self, cards: CardsResource) -> None:
+ self._cards = cards
+
+ self.create = to_streamed_response_wrapper(
+ cards.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ cards.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ cards.list,
+ )
+
+
+class AsyncCardsResourceWithStreamingResponse:
+ def __init__(self, cards: AsyncCardsResource) -> None:
+ self._cards = cards
+
+ self.create = async_to_streamed_response_wrapper(
+ cards.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ cards.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ cards.list,
+ )
diff --git a/src/whop_sdk/resources/checkout_configurations.py b/src/whop_sdk/resources/checkout_configurations.py
index b2e70eeb..7a15580f 100644
--- a/src/whop_sdk/resources/checkout_configurations.py
+++ b/src/whop_sdk/resources/checkout_configurations.py
@@ -2,15 +2,14 @@
from __future__ import annotations
-from typing import Dict, Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, overload
+from typing import Optional
+from typing_extensions import Literal
import httpx
from ..types import checkout_configuration_list_params, checkout_configuration_create_params
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import path_template, required_args, maybe_transform, async_maybe_transform
+from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -21,17 +20,14 @@
)
from ..pagination import SyncCursorPage, AsyncCursorPage
from .._base_client import AsyncPaginator, make_request_options
-from ..types.shared.currency import Currency
-from ..types.shared.direction import Direction
-from ..types.shared.checkout_configuration import CheckoutConfiguration
from ..types.checkout_configuration_list_response import CheckoutConfigurationListResponse
+from ..types.checkout_configuration_create_response import CheckoutConfigurationCreateResponse
+from ..types.checkout_configuration_retrieve_response import CheckoutConfigurationRetrieveResponse
__all__ = ["CheckoutConfigurationsResource", "AsyncCheckoutConfigurationsResource"]
class CheckoutConfigurationsResource(SyncAPIResource):
- """Checkout configurations"""
-
@cached_property
def with_raw_response(self) -> CheckoutConfigurationsResourceWithRawResponse:
"""
@@ -51,207 +47,50 @@ def with_streaming_response(self) -> CheckoutConfigurationsResourceWithStreaming
"""
return CheckoutConfigurationsResourceWithStreamingResponse(self)
- @overload
def create(
self,
*,
- plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan,
affiliate_code: Optional[str] | Omit = omit,
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling
- ]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- mode: Literal["payment"] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration
- ]
- | Omit = omit,
- redirect_url: Optional[str] | Omit = omit,
- source_url: 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
- """
- Creates a new checkout configuration
-
- Required permissions:
-
- - `checkout_configuration:create`
- - `plan:create`
- - `access_pass:create`
- - `access_pass:update`
- - `checkout_configuration:basic:read`
-
- Args:
- plan: The plan attributes to create a new plan inline for this checkout configuration.
-
- affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate.
-
- allow_promo_codes: Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
-
- checkout_styling: Checkout styling overrides for this session. Overrides plan and company
- defaults.
-
- currency: The available currencies on the platform
-
- metadata: Custom key-value metadata to attach to the checkout configuration.
-
- payment_method_configuration: The explicit payment method configuration for the checkout session. Only applies
- to setup mode. If not provided, the platform or company defaults will apply.
-
- redirect_url: The URL to redirect the user to after checkout is completed.
-
- source_url: The URL of the page where the checkout is being initiated from.
-
- 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,
- *,
- plan_id: str,
- affiliate_code: Optional[str] | Omit = omit,
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling
- ]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- mode: Literal["payment"] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration
- ]
- | Omit = omit,
- redirect_url: Optional[str] | Omit = omit,
- source_url: 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
- """
- Creates a new checkout configuration
-
- Required permissions:
-
- - `checkout_configuration:create`
- - `plan:create`
- - `access_pass:create`
- - `access_pass:update`
- - `checkout_configuration:basic:read`
-
- Args:
- plan_id: The unique identifier of an existing plan to use for this checkout
- configuration.
-
- affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate.
-
- allow_promo_codes: Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
-
- checkout_styling: Checkout styling overrides for this session. Overrides plan and company
- defaults.
-
- currency: The available currencies on the platform
-
- metadata: Custom key-value metadata to attach to the checkout configuration.
-
- payment_method_configuration: The explicit payment method configuration for the checkout session. Only applies
- to setup mode. If not provided, the platform or company defaults will apply.
-
- redirect_url: The URL to redirect the user to after checkout is completed.
-
- source_url: The URL of the page where the checkout is being initiated from.
-
- 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,
- *,
- company_id: str,
- mode: Literal["setup"],
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling
- ]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration
- ]
+ company_id: str | Omit = omit,
+ currency: Optional[str] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
+ mode: Literal["payment", "setup"] | Omit = omit,
+ payment_method_configuration: Optional[checkout_configuration_create_params.PaymentMethodConfiguration]
| Omit = omit,
+ plan: Optional[checkout_configuration_create_params.Plan] | Omit = omit,
+ plan_id: Optional[str] | Omit = omit,
redirect_url: Optional[str] | Omit = omit,
- source_url: Optional[str] | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | Omit = omit,
+ three_ds_level: 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.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
- """
- Creates a new checkout configuration
-
- Required permissions:
+ ) -> CheckoutConfigurationCreateResponse:
+ """Creates a checkout configuration for a plan.
- - `checkout_configuration:create`
- - `plan:create`
- - `access_pass:create`
- - `access_pass:update`
- - `checkout_configuration:basic:read`
+ Mode defaults to 'payment'.
Args:
- company_id: The unique identifier of the company to create the checkout configuration for.
- Only required in setup mode.
+ affiliate_code: An affiliate code to apply.
- allow_promo_codes: Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
+ company_id: The ID of the company.
- checkout_styling: Checkout styling overrides for this session. Overrides plan and company
- defaults.
+ currency: The currency code.
- currency: The available currencies on the platform
+ metadata: Arbitrary key-value metadata.
- metadata: Custom key-value metadata to attach to the checkout configuration.
+ mode: Checkout mode. Defaults to 'payment'.
- payment_method_configuration: The explicit payment method configuration for the checkout session. Only applies
- to setup mode. If not provided, the platform or company defaults will apply.
+ plan: Plan attributes to create a new plan inline for this checkout configuration.
+ Mutually exclusive with plan_id.
- redirect_url: The URL to redirect the user to after checkout is completed.
+ plan_id: The ID of an existing plan to attach.
- source_url: The URL of the page where the checkout is being initiated from.
+ redirect_url: URL to redirect after checkout.
- three_ds_level: The 3D Secure behavior for a plan.
+ three_ds_level: 3D Secure enforcement level.
extra_headers: Send extra headers
@@ -261,60 +100,19 @@ def create(
timeout: Override the client-level default timeout for this request, in seconds
"""
- ...
-
- @required_args(["plan"], ["plan_id"], ["company_id", "mode"])
- def create(
- self,
- *,
- plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan | Omit = omit,
- affiliate_code: Optional[str] | Omit = omit,
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling
- ]
- | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling]
- | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- mode: Literal["payment"] | Literal["setup"] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration
- ]
- | Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration
- ]
- | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration]
- | Omit = omit,
- redirect_url: Optional[str] | Omit = omit,
- source_url: Optional[str] | Omit = omit,
- plan_id: str | Omit = omit,
- company_id: str | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | 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,
- ) -> CheckoutConfiguration:
return self._post(
"/checkout_configurations",
body=maybe_transform(
{
- "plan": plan,
"affiliate_code": affiliate_code,
- "allow_promo_codes": allow_promo_codes,
- "checkout_styling": checkout_styling,
+ "company_id": company_id,
"currency": currency,
"metadata": metadata,
"mode": mode,
"payment_method_configuration": payment_method_configuration,
- "redirect_url": redirect_url,
- "source_url": source_url,
+ "plan": plan,
"plan_id": plan_id,
- "company_id": company_id,
+ "redirect_url": redirect_url,
"three_ds_level": three_ds_level,
},
checkout_configuration_create_params.CheckoutConfigurationCreateParams,
@@ -322,7 +120,7 @@ def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=CheckoutConfiguration,
+ cast_to=CheckoutConfigurationCreateResponse,
)
def retrieve(
@@ -335,13 +133,10 @@ def retrieve(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
- """
- Retrieves the details of an existing checkout configuration.
+ ) -> CheckoutConfigurationRetrieveResponse:
+ """Retrieves a checkout configuration by ID.
- Required permissions:
-
- - `checkout_configuration:basic:read`
+ No authentication required.
Args:
extra_headers: Send extra headers
@@ -359,21 +154,19 @@ def retrieve(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=CheckoutConfiguration,
+ cast_to=CheckoutConfigurationRetrieveResponse,
)
def list(
self,
*,
company_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- plan_id: Optional[str] | Omit = omit,
+ after: str | Omit = omit,
+ created_after: int | Omit = omit,
+ created_before: int | Omit = omit,
+ direction: str | Omit = omit,
+ first: int | Omit = omit,
+ plan_id: 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.
extra_headers: Headers | None = None,
@@ -382,32 +175,22 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> SyncCursorPage[CheckoutConfigurationListResponse]:
"""
- Returns a paginated list of checkout configurations for a company, with optional
- filtering by plan and creation date.
-
- Required permissions:
-
- - `checkout_configuration:basic:read`
+ Returns a paginated list of checkout configurations for a company.
Args:
- company_id: The unique identifier of the company to list checkout configurations for.
+ company_id: The ID of the company to list checkout configurations for.
- after: Returns the elements in the list that come after the specified cursor.
+ after: Cursor for forward pagination.
- before: Returns the elements in the list that come before the specified cursor.
+ created_after: Filter to configurations created after this Unix timestamp.
- created_after: Only return checkout configurations created after this timestamp.
+ created_before: Filter to configurations created before this Unix timestamp.
- created_before: Only return checkout configurations created before this timestamp.
+ direction: Sort direction: asc or desc. Defaults to desc.
- direction: The direction of the sort.
+ first: Number of results to return (forward pagination).
- first: Returns the first _n_ elements from the list.
-
- last: Returns the last _n_ elements from the list.
-
- plan_id: Filter checkout configurations to only those associated with this plan
- identifier.
+ plan_id: Filter by plan ID.
extra_headers: Send extra headers
@@ -429,12 +212,10 @@ def list(
{
"company_id": company_id,
"after": after,
- "before": before,
"created_after": created_after,
"created_before": created_before,
"direction": direction,
"first": first,
- "last": last,
"plan_id": plan_id,
},
checkout_configuration_list_params.CheckoutConfigurationListParams,
@@ -443,89 +224,21 @@ def list(
model=CheckoutConfigurationListResponse,
)
-
-class AsyncCheckoutConfigurationsResource(AsyncAPIResource):
- """Checkout configurations"""
-
- @cached_property
- def with_raw_response(self) -> AsyncCheckoutConfigurationsResourceWithRawResponse:
- """
- 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 AsyncCheckoutConfigurationsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncCheckoutConfigurationsResourceWithStreamingResponse:
- """
- 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 AsyncCheckoutConfigurationsResourceWithStreamingResponse(self)
-
- @overload
- async def create(
+ def delete(
self,
+ id: str,
*,
- plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan,
- affiliate_code: Optional[str] | Omit = omit,
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling
- ]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- mode: Literal["payment"] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration
- ]
- | Omit = omit,
- redirect_url: Optional[str] | Omit = omit,
- source_url: 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.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
+ ) -> None:
"""
- Creates a new checkout configuration
-
- Required permissions:
-
- - `checkout_configuration:create`
- - `plan:create`
- - `access_pass:create`
- - `access_pass:update`
- - `checkout_configuration:basic:read`
+ Deletes a checkout configuration.
Args:
- plan: The plan attributes to create a new plan inline for this checkout configuration.
-
- affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate.
-
- allow_promo_codes: Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
-
- checkout_styling: Checkout styling overrides for this session. Overrides plan and company
- defaults.
-
- currency: The available currencies on the platform
-
- metadata: Custom key-value metadata to attach to the checkout configuration.
-
- payment_method_configuration: The explicit payment method configuration for the checkout session. Only applies
- to setup mode. If not provided, the platform or company defaults will apply.
-
- redirect_url: The URL to redirect the user to after checkout is completed.
-
- source_url: The URL of the page where the checkout is being initiated from.
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -534,139 +247,82 @@ async def create(
timeout: Override the client-level default timeout for this request, in seconds
"""
- ...
-
- @overload
- async def create(
- self,
- *,
- plan_id: str,
- affiliate_code: Optional[str] | Omit = omit,
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling
- ]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- mode: Literal["payment"] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration
- ]
- | Omit = omit,
- redirect_url: Optional[str] | Omit = omit,
- source_url: 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.
- extra_headers: Headers | None = None,
- extra_query: Query | None = None,
- extra_body: Body | None = None,
- timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
- """
- Creates a new checkout configuration
-
- Required permissions:
-
- - `checkout_configuration:create`
- - `plan:create`
- - `access_pass:create`
- - `access_pass:update`
- - `checkout_configuration:basic:read`
-
- Args:
- plan_id: The unique identifier of an existing plan to use for this checkout
- configuration.
-
- affiliate_code: An affiliate tracking code to attribute the checkout to a specific affiliate.
-
- allow_promo_codes: Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
-
- checkout_styling: Checkout styling overrides for this session. Overrides plan and company
- defaults.
-
- currency: The available currencies on the platform
-
- metadata: Custom key-value metadata to attach to the checkout configuration.
-
- payment_method_configuration: The explicit payment method configuration for the checkout session. Only applies
- to setup mode. If not provided, the platform or company defaults will apply.
-
- redirect_url: The URL to redirect the user to after checkout is completed.
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._delete(
+ path_template("/checkout_configurations/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
- source_url: The URL of the page where the checkout is being initiated from.
- extra_headers: Send extra headers
+class AsyncCheckoutConfigurationsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncCheckoutConfigurationsResourceWithRawResponse:
+ """
+ This property can be used as a prefix for any HTTP method call to return
+ the raw response object instead of the parsed content.
- extra_query: Add additional query parameters to the request
+ For more information, see https://www.github.com/whopio/whopsdk-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncCheckoutConfigurationsResourceWithRawResponse(self)
- extra_body: Add additional JSON properties to the request
+ @cached_property
+ def with_streaming_response(self) -> AsyncCheckoutConfigurationsResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
- timeout: Override the client-level default timeout for this request, in seconds
+ For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response
"""
- ...
+ return AsyncCheckoutConfigurationsResourceWithStreamingResponse(self)
- @overload
async def create(
self,
*,
- company_id: str,
- mode: Literal["setup"],
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling
- ]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration
- ]
+ affiliate_code: Optional[str] | Omit = omit,
+ company_id: str | Omit = omit,
+ currency: Optional[str] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
+ mode: Literal["payment", "setup"] | Omit = omit,
+ payment_method_configuration: Optional[checkout_configuration_create_params.PaymentMethodConfiguration]
| Omit = omit,
+ plan: Optional[checkout_configuration_create_params.Plan] | Omit = omit,
+ plan_id: Optional[str] | Omit = omit,
redirect_url: Optional[str] | Omit = omit,
- source_url: Optional[str] | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | Omit = omit,
+ three_ds_level: 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.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
- """
- Creates a new checkout configuration
-
- Required permissions:
+ ) -> CheckoutConfigurationCreateResponse:
+ """Creates a checkout configuration for a plan.
- - `checkout_configuration:create`
- - `plan:create`
- - `access_pass:create`
- - `access_pass:update`
- - `checkout_configuration:basic:read`
+ Mode defaults to 'payment'.
Args:
- company_id: The unique identifier of the company to create the checkout configuration for.
- Only required in setup mode.
+ affiliate_code: An affiliate code to apply.
- allow_promo_codes: Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
+ company_id: The ID of the company.
- checkout_styling: Checkout styling overrides for this session. Overrides plan and company
- defaults.
+ currency: The currency code.
- currency: The available currencies on the platform
+ metadata: Arbitrary key-value metadata.
- metadata: Custom key-value metadata to attach to the checkout configuration.
+ mode: Checkout mode. Defaults to 'payment'.
- payment_method_configuration: The explicit payment method configuration for the checkout session. Only applies
- to setup mode. If not provided, the platform or company defaults will apply.
+ plan: Plan attributes to create a new plan inline for this checkout configuration.
+ Mutually exclusive with plan_id.
- redirect_url: The URL to redirect the user to after checkout is completed.
+ plan_id: The ID of an existing plan to attach.
- source_url: The URL of the page where the checkout is being initiated from.
+ redirect_url: URL to redirect after checkout.
- three_ds_level: The 3D Secure behavior for a plan.
+ three_ds_level: 3D Secure enforcement level.
extra_headers: Send extra headers
@@ -676,60 +332,19 @@ async def create(
timeout: Override the client-level default timeout for this request, in seconds
"""
- ...
-
- @required_args(["plan"], ["plan_id"], ["company_id", "mode"])
- async def create(
- self,
- *,
- plan: checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPlan | Omit = omit,
- affiliate_code: Optional[str] | Omit = omit,
- allow_promo_codes: Optional[bool] | Omit = omit,
- checkout_styling: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling
- ]
- | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling]
- | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupCheckoutStyling]
- | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- mode: Literal["payment"] | Literal["setup"] | Omit = omit,
- payment_method_configuration: Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration
- ]
- | Optional[
- checkout_configuration_create_params.CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration
- ]
- | Optional[checkout_configuration_create_params.CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration]
- | Omit = omit,
- redirect_url: Optional[str] | Omit = omit,
- source_url: Optional[str] | Omit = omit,
- plan_id: str | Omit = omit,
- company_id: str | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | 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,
- ) -> CheckoutConfiguration:
return await self._post(
"/checkout_configurations",
body=await async_maybe_transform(
{
- "plan": plan,
"affiliate_code": affiliate_code,
- "allow_promo_codes": allow_promo_codes,
- "checkout_styling": checkout_styling,
+ "company_id": company_id,
"currency": currency,
"metadata": metadata,
"mode": mode,
"payment_method_configuration": payment_method_configuration,
- "redirect_url": redirect_url,
- "source_url": source_url,
+ "plan": plan,
"plan_id": plan_id,
- "company_id": company_id,
+ "redirect_url": redirect_url,
"three_ds_level": three_ds_level,
},
checkout_configuration_create_params.CheckoutConfigurationCreateParams,
@@ -737,7 +352,7 @@ async def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=CheckoutConfiguration,
+ cast_to=CheckoutConfigurationCreateResponse,
)
async def retrieve(
@@ -750,13 +365,10 @@ async def retrieve(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CheckoutConfiguration:
- """
- Retrieves the details of an existing checkout configuration.
+ ) -> CheckoutConfigurationRetrieveResponse:
+ """Retrieves a checkout configuration by ID.
- Required permissions:
-
- - `checkout_configuration:basic:read`
+ No authentication required.
Args:
extra_headers: Send extra headers
@@ -774,21 +386,19 @@ async def retrieve(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=CheckoutConfiguration,
+ cast_to=CheckoutConfigurationRetrieveResponse,
)
def list(
self,
*,
company_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- plan_id: Optional[str] | Omit = omit,
+ after: str | Omit = omit,
+ created_after: int | Omit = omit,
+ created_before: int | Omit = omit,
+ direction: str | Omit = omit,
+ first: int | Omit = omit,
+ plan_id: 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.
extra_headers: Headers | None = None,
@@ -797,32 +407,22 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AsyncPaginator[CheckoutConfigurationListResponse, AsyncCursorPage[CheckoutConfigurationListResponse]]:
"""
- Returns a paginated list of checkout configurations for a company, with optional
- filtering by plan and creation date.
-
- Required permissions:
-
- - `checkout_configuration:basic:read`
+ Returns a paginated list of checkout configurations for a company.
Args:
- company_id: The unique identifier of the company to list checkout configurations for.
-
- after: Returns the elements in the list that come after the specified cursor.
+ company_id: The ID of the company to list checkout configurations for.
- before: Returns the elements in the list that come before the specified cursor.
+ after: Cursor for forward pagination.
- created_after: Only return checkout configurations created after this timestamp.
+ created_after: Filter to configurations created after this Unix timestamp.
- created_before: Only return checkout configurations created before this timestamp.
+ created_before: Filter to configurations created before this Unix timestamp.
- direction: The direction of the sort.
+ direction: Sort direction: asc or desc. Defaults to desc.
- first: Returns the first _n_ elements from the list.
+ first: Number of results to return (forward pagination).
- last: Returns the last _n_ elements from the list.
-
- plan_id: Filter checkout configurations to only those associated with this plan
- identifier.
+ plan_id: Filter by plan ID.
extra_headers: Send extra headers
@@ -844,12 +444,10 @@ def list(
{
"company_id": company_id,
"after": after,
- "before": before,
"created_after": created_after,
"created_before": created_before,
"direction": direction,
"first": first,
- "last": last,
"plan_id": plan_id,
},
checkout_configuration_list_params.CheckoutConfigurationListParams,
@@ -858,6 +456,40 @@ def list(
model=CheckoutConfigurationListResponse,
)
+ async def delete(
+ 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,
+ ) -> None:
+ """
+ Deletes a checkout configuration.
+
+ 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}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._delete(
+ path_template("/checkout_configurations/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class CheckoutConfigurationsResourceWithRawResponse:
def __init__(self, checkout_configurations: CheckoutConfigurationsResource) -> None:
@@ -872,6 +504,9 @@ def __init__(self, checkout_configurations: CheckoutConfigurationsResource) -> N
self.list = to_raw_response_wrapper(
checkout_configurations.list,
)
+ self.delete = to_raw_response_wrapper(
+ checkout_configurations.delete,
+ )
class AsyncCheckoutConfigurationsResourceWithRawResponse:
@@ -887,6 +522,9 @@ def __init__(self, checkout_configurations: AsyncCheckoutConfigurationsResource)
self.list = async_to_raw_response_wrapper(
checkout_configurations.list,
)
+ self.delete = async_to_raw_response_wrapper(
+ checkout_configurations.delete,
+ )
class CheckoutConfigurationsResourceWithStreamingResponse:
@@ -902,6 +540,9 @@ def __init__(self, checkout_configurations: CheckoutConfigurationsResource) -> N
self.list = to_streamed_response_wrapper(
checkout_configurations.list,
)
+ self.delete = to_streamed_response_wrapper(
+ checkout_configurations.delete,
+ )
class AsyncCheckoutConfigurationsResourceWithStreamingResponse:
@@ -917,3 +558,6 @@ def __init__(self, checkout_configurations: AsyncCheckoutConfigurationsResource)
self.list = async_to_streamed_response_wrapper(
checkout_configurations.list,
)
+ self.delete = async_to_streamed_response_wrapper(
+ checkout_configurations.delete,
+ )
diff --git a/src/whop_sdk/resources/conversions.py b/src/whop_sdk/resources/conversions.py
index a3dd6259..4f70d949 100644
--- a/src/whop_sdk/resources/conversions.py
+++ b/src/whop_sdk/resources/conversions.py
@@ -52,7 +52,17 @@ def create(
self,
*,
company_id: str,
- event_name: Literal["lead", "submit_application", "contact", "complete_registration", "schedule", "custom"],
+ event_name: Literal[
+ "lead",
+ "submit_application",
+ "contact",
+ "complete_registration",
+ "schedule",
+ "view_content",
+ "add_to_cart",
+ "custom",
+ "page",
+ ],
action_source: Optional[
Literal[
"email",
@@ -70,11 +80,15 @@ def create(
context: Optional[conversion_create_params.Context] | Omit = omit,
currency: Optional[Currency] | Omit = omit,
custom_name: Optional[str] | Omit = omit,
+ duration: Optional[int] | Omit = omit,
event_id: Optional[str] | Omit = omit,
event_time: Union[str, datetime, None] | Omit = omit,
plan_id: Optional[str] | Omit = omit,
product_id: Optional[str] | Omit = omit,
referrer_url: Optional[str] | Omit = omit,
+ resumed: Optional[bool] | Omit = omit,
+ source: Optional[str] | Omit = omit,
+ title: Optional[str] | Omit = omit,
url: Optional[str] | Omit = omit,
user: Optional[conversion_create_params.User] | Omit = omit,
value: Optional[float] | Omit = omit,
@@ -103,7 +117,9 @@ def create(
currency: The available currencies on the platform
- custom_name: Custom event name when event_name is 'custom'.
+ custom_name: Custom event name when event_name is 'custom'. Maximum 35 chars for this value.
+
+ duration: For 'leave' events: milliseconds the visitor spent on the page.
event_id: Client-provided identifier for deduplication. Generated if omitted.
@@ -115,6 +131,13 @@ def create(
referrer_url: The referring URL.
+ resumed: For 'page' events: true when the page was restored from the back/forward cache.
+
+ source: For 'identify' events: where the identity was captured (url, form, manual,
+ iframe).
+
+ title: For 'page' events: the document title.
+
url: The URL where the event occurred.
user: User identity and profile data.
@@ -139,11 +162,15 @@ def create(
"context": context,
"currency": currency,
"custom_name": custom_name,
+ "duration": duration,
"event_id": event_id,
"event_time": event_time,
"plan_id": plan_id,
"product_id": product_id,
"referrer_url": referrer_url,
+ "resumed": resumed,
+ "source": source,
+ "title": title,
"url": url,
"user": user,
"value": value,
@@ -183,7 +210,17 @@ async def create(
self,
*,
company_id: str,
- event_name: Literal["lead", "submit_application", "contact", "complete_registration", "schedule", "custom"],
+ event_name: Literal[
+ "lead",
+ "submit_application",
+ "contact",
+ "complete_registration",
+ "schedule",
+ "view_content",
+ "add_to_cart",
+ "custom",
+ "page",
+ ],
action_source: Optional[
Literal[
"email",
@@ -201,11 +238,15 @@ async def create(
context: Optional[conversion_create_params.Context] | Omit = omit,
currency: Optional[Currency] | Omit = omit,
custom_name: Optional[str] | Omit = omit,
+ duration: Optional[int] | Omit = omit,
event_id: Optional[str] | Omit = omit,
event_time: Union[str, datetime, None] | Omit = omit,
plan_id: Optional[str] | Omit = omit,
product_id: Optional[str] | Omit = omit,
referrer_url: Optional[str] | Omit = omit,
+ resumed: Optional[bool] | Omit = omit,
+ source: Optional[str] | Omit = omit,
+ title: Optional[str] | Omit = omit,
url: Optional[str] | Omit = omit,
user: Optional[conversion_create_params.User] | Omit = omit,
value: Optional[float] | Omit = omit,
@@ -234,7 +275,9 @@ async def create(
currency: The available currencies on the platform
- custom_name: Custom event name when event_name is 'custom'.
+ custom_name: Custom event name when event_name is 'custom'. Maximum 35 chars for this value.
+
+ duration: For 'leave' events: milliseconds the visitor spent on the page.
event_id: Client-provided identifier for deduplication. Generated if omitted.
@@ -246,6 +289,13 @@ async def create(
referrer_url: The referring URL.
+ resumed: For 'page' events: true when the page was restored from the back/forward cache.
+
+ source: For 'identify' events: where the identity was captured (url, form, manual,
+ iframe).
+
+ title: For 'page' events: the document title.
+
url: The URL where the event occurred.
user: User identity and profile data.
@@ -270,11 +320,15 @@ async def create(
"context": context,
"currency": currency,
"custom_name": custom_name,
+ "duration": duration,
"event_id": event_id,
"event_time": event_time,
"plan_id": plan_id,
"product_id": product_id,
"referrer_url": referrer_url,
+ "resumed": resumed,
+ "source": source,
+ "title": title,
"url": url,
"user": user,
"value": value,
diff --git a/src/whop_sdk/resources/deposits.py b/src/whop_sdk/resources/deposits.py
index 9d32c93d..82ceb67d 100644
--- a/src/whop_sdk/resources/deposits.py
+++ b/src/whop_sdk/resources/deposits.py
@@ -6,7 +6,7 @@
import httpx
-from ..types import deposit_create_params
+from ..types import deposit_list_params, deposit_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
@@ -18,6 +18,7 @@
async_to_streamed_response_wrapper,
)
from .._base_client import make_request_options
+from ..types.deposit_list_response import DepositListResponse
from ..types.deposit_create_response import DepositCreateResponse
__all__ = ["DepositsResource", "AsyncDepositsResource"]
@@ -46,8 +47,8 @@ def with_streaming_response(self) -> DepositsResourceWithStreamingResponse:
def create(
self,
*,
- amount: float,
destination: deposit_create_params.Destination,
+ amount: float | Omit = omit,
metadata: Dict[str, object] | Omit = omit,
network: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -59,14 +60,15 @@ def create(
) -> DepositCreateResponse:
"""
Resolves a deposit destination and returns the on-chain addresses that can fund
- it.
+ it. No authentication is required; any business can be resolved by its account
+ ID.
Args:
- amount: Amount to deposit.
-
destination: Destination account ID or wallet address. Object form is supported for
compatibility.
+ amount: Optional amount to deposit.
+
metadata: Arbitrary metadata echoed in the response.
network: Optional destination network override.
@@ -83,8 +85,8 @@ def create(
"/deposits",
body=maybe_transform(
{
- "amount": amount,
"destination": destination,
+ "amount": amount,
"metadata": metadata,
"network": network,
},
@@ -96,6 +98,45 @@ def create(
cast_to=DepositCreateResponse,
)
+ def list(
+ self,
+ *,
+ account_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,
+ ) -> DepositListResponse:
+ """Returns deposit transactions for a business account.
+
+ Bank deposit transactions
+ are nested under the bank field.
+
+ Args:
+ account_id: Business account ID (biz\\__\\**).
+
+ 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(
+ "/deposits",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"account_id": account_id}, deposit_list_params.DepositListParams),
+ ),
+ cast_to=DepositListResponse,
+ )
+
class AsyncDepositsResource(AsyncAPIResource):
@cached_property
@@ -120,8 +161,8 @@ def with_streaming_response(self) -> AsyncDepositsResourceWithStreamingResponse:
async def create(
self,
*,
- amount: float,
destination: deposit_create_params.Destination,
+ amount: float | Omit = omit,
metadata: Dict[str, object] | Omit = omit,
network: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -133,14 +174,15 @@ async def create(
) -> DepositCreateResponse:
"""
Resolves a deposit destination and returns the on-chain addresses that can fund
- it.
+ it. No authentication is required; any business can be resolved by its account
+ ID.
Args:
- amount: Amount to deposit.
-
destination: Destination account ID or wallet address. Object form is supported for
compatibility.
+ amount: Optional amount to deposit.
+
metadata: Arbitrary metadata echoed in the response.
network: Optional destination network override.
@@ -157,8 +199,8 @@ async def create(
"/deposits",
body=await async_maybe_transform(
{
- "amount": amount,
"destination": destination,
+ "amount": amount,
"metadata": metadata,
"network": network,
},
@@ -170,6 +212,45 @@ async def create(
cast_to=DepositCreateResponse,
)
+ async def list(
+ self,
+ *,
+ account_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,
+ ) -> DepositListResponse:
+ """Returns deposit transactions for a business account.
+
+ Bank deposit transactions
+ are nested under the bank field.
+
+ Args:
+ account_id: Business account ID (biz\\__\\**).
+
+ 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._get(
+ "/deposits",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform({"account_id": account_id}, deposit_list_params.DepositListParams),
+ ),
+ cast_to=DepositListResponse,
+ )
+
class DepositsResourceWithRawResponse:
def __init__(self, deposits: DepositsResource) -> None:
@@ -178,6 +259,9 @@ def __init__(self, deposits: DepositsResource) -> None:
self.create = to_raw_response_wrapper(
deposits.create,
)
+ self.list = to_raw_response_wrapper(
+ deposits.list,
+ )
class AsyncDepositsResourceWithRawResponse:
@@ -187,6 +271,9 @@ def __init__(self, deposits: AsyncDepositsResource) -> None:
self.create = async_to_raw_response_wrapper(
deposits.create,
)
+ self.list = async_to_raw_response_wrapper(
+ deposits.list,
+ )
class DepositsResourceWithStreamingResponse:
@@ -196,6 +283,9 @@ def __init__(self, deposits: DepositsResource) -> None:
self.create = to_streamed_response_wrapper(
deposits.create,
)
+ self.list = to_streamed_response_wrapper(
+ deposits.list,
+ )
class AsyncDepositsResourceWithStreamingResponse:
@@ -205,3 +295,6 @@ def __init__(self, deposits: AsyncDepositsResource) -> None:
self.create = async_to_streamed_response_wrapper(
deposits.create,
)
+ self.list = async_to_streamed_response_wrapper(
+ deposits.list,
+ )
diff --git a/src/whop_sdk/resources/financial_activity.py b/src/whop_sdk/resources/financial_activity.py
new file mode 100644
index 00000000..90a4e652
--- /dev/null
+++ b/src/whop_sdk/resources/financial_activity.py
@@ -0,0 +1,276 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import date, datetime
+
+import httpx
+
+from ..types import financial_activity_list_params
+from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
+from .._utils import 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 .._base_client import make_request_options
+from ..types.financial_activity_list_response import FinancialActivityListResponse
+
+__all__ = ["FinancialActivityResource", "AsyncFinancialActivityResource"]
+
+
+class FinancialActivityResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> FinancialActivityResourceWithRawResponse:
+ """
+ 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 FinancialActivityResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> FinancialActivityResourceWithStreamingResponse:
+ """
+ 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 FinancialActivityResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ available_after: Union[str, date] | Omit = omit,
+ available_before: Union[str, date] | Omit = omit,
+ currency: str | Omit = omit,
+ cursor: str | Omit = omit,
+ limit: int | Omit = omit,
+ line_types: SequenceNotStr[str] | Omit = omit,
+ posted_after: Union[str, datetime] | Omit = omit,
+ posted_before: Union[str, datetime] | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> FinancialActivityListResponse:
+ """Lists financial activity rows for a ledger account.
+
+ Rows are derived from ledger
+ lines and include typed resource and source objects that clients can use for
+ presentation and navigation. The ledger's owner is passed as exactly one of
+ account*id (a biz* identifier) or user*id (a user* identifier).
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ available_after: Only include rows whose funds became withdrawable on or after this YYYY-MM-DD
+ settlement date (UTC), distinct from posted_at. Requires currency.
+
+ available_before: Only include rows whose funds became withdrawable on or before this YYYY-MM-DD
+ settlement date (UTC). Set equal to available_after for a single day. Requires
+ currency.
+
+ currency: Optional currency code filter, for example usd.
+
+ cursor: Cursor returned by the previous page.
+
+ limit: Maximum number of rows to return.
+
+ line_types: Optional ledger line categories to include. Some categories (for example
+ onchain_deposit, which covers inbound crypto deposits such as MoonPay onramps)
+ are only returned when explicitly requested here.
+
+ posted_after: Only include rows posted after this ISO 8601 timestamp.
+
+ posted_before: Only include rows posted before this ISO 8601 timestamp.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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._get(
+ "/financial-activity",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "account_id": account_id,
+ "available_after": available_after,
+ "available_before": available_before,
+ "currency": currency,
+ "cursor": cursor,
+ "limit": limit,
+ "line_types": line_types,
+ "posted_after": posted_after,
+ "posted_before": posted_before,
+ "user_id": user_id,
+ },
+ financial_activity_list_params.FinancialActivityListParams,
+ ),
+ ),
+ cast_to=FinancialActivityListResponse,
+ )
+
+
+class AsyncFinancialActivityResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncFinancialActivityResourceWithRawResponse:
+ """
+ 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 AsyncFinancialActivityResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncFinancialActivityResourceWithStreamingResponse:
+ """
+ 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 AsyncFinancialActivityResourceWithStreamingResponse(self)
+
+ async def list(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ available_after: Union[str, date] | Omit = omit,
+ available_before: Union[str, date] | Omit = omit,
+ currency: str | Omit = omit,
+ cursor: str | Omit = omit,
+ limit: int | Omit = omit,
+ line_types: SequenceNotStr[str] | Omit = omit,
+ posted_after: Union[str, datetime] | Omit = omit,
+ posted_before: Union[str, datetime] | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> FinancialActivityListResponse:
+ """Lists financial activity rows for a ledger account.
+
+ Rows are derived from ledger
+ lines and include typed resource and source objects that clients can use for
+ presentation and navigation. The ledger's owner is passed as exactly one of
+ account*id (a biz* identifier) or user*id (a user* identifier).
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ available_after: Only include rows whose funds became withdrawable on or after this YYYY-MM-DD
+ settlement date (UTC), distinct from posted_at. Requires currency.
+
+ available_before: Only include rows whose funds became withdrawable on or before this YYYY-MM-DD
+ settlement date (UTC). Set equal to available_after for a single day. Requires
+ currency.
+
+ currency: Optional currency code filter, for example usd.
+
+ cursor: Cursor returned by the previous page.
+
+ limit: Maximum number of rows to return.
+
+ line_types: Optional ledger line categories to include. Some categories (for example
+ onchain_deposit, which covers inbound crypto deposits such as MoonPay onramps)
+ are only returned when explicitly requested here.
+
+ posted_after: Only include rows posted after this ISO 8601 timestamp.
+
+ posted_before: Only include rows posted before this ISO 8601 timestamp.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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._get(
+ "/financial-activity",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "account_id": account_id,
+ "available_after": available_after,
+ "available_before": available_before,
+ "currency": currency,
+ "cursor": cursor,
+ "limit": limit,
+ "line_types": line_types,
+ "posted_after": posted_after,
+ "posted_before": posted_before,
+ "user_id": user_id,
+ },
+ financial_activity_list_params.FinancialActivityListParams,
+ ),
+ ),
+ cast_to=FinancialActivityListResponse,
+ )
+
+
+class FinancialActivityResourceWithRawResponse:
+ def __init__(self, financial_activity: FinancialActivityResource) -> None:
+ self._financial_activity = financial_activity
+
+ self.list = to_raw_response_wrapper(
+ financial_activity.list,
+ )
+
+
+class AsyncFinancialActivityResourceWithRawResponse:
+ def __init__(self, financial_activity: AsyncFinancialActivityResource) -> None:
+ self._financial_activity = financial_activity
+
+ self.list = async_to_raw_response_wrapper(
+ financial_activity.list,
+ )
+
+
+class FinancialActivityResourceWithStreamingResponse:
+ def __init__(self, financial_activity: FinancialActivityResource) -> None:
+ self._financial_activity = financial_activity
+
+ self.list = to_streamed_response_wrapper(
+ financial_activity.list,
+ )
+
+
+class AsyncFinancialActivityResourceWithStreamingResponse:
+ def __init__(self, financial_activity: AsyncFinancialActivityResource) -> None:
+ self._financial_activity = financial_activity
+
+ self.list = async_to_streamed_response_wrapper(
+ financial_activity.list,
+ )
diff --git a/src/whop_sdk/resources/payouts.py b/src/whop_sdk/resources/payouts.py
new file mode 100644
index 00000000..4394b6ea
--- /dev/null
+++ b/src/whop_sdk/resources/payouts.py
@@ -0,0 +1,242 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ..types import payout_list_params
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import 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.payout_list_response import PayoutListResponse
+
+__all__ = ["PayoutsResource", "AsyncPayoutsResource"]
+
+
+class PayoutsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> PayoutsResourceWithRawResponse:
+ """
+ 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 PayoutsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> PayoutsResourceWithStreamingResponse:
+ """
+ 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 PayoutsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ currency: str | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> SyncCursorPage[PayoutListResponse]:
+ """Lists payouts (withdrawal requests) for a ledger account, most recent first.
+
+ The
+ ledger's owner is passed as exactly one of account*id (a biz* identifier) or
+ user*id (a user* identifier). The saved payout method on each payout
+ additionally requires the payout:destination:read scope and is null without it.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ after: Cursor to fetch the page after (from page_info.end_cursor).
+
+ before: Cursor to fetch the page before (from page_info.start_cursor).
+
+ currency: Optional currency code filter, for example usd.
+
+ first: Number of payouts to return from the start of the window.
+
+ last: Number of payouts to return from the end of the window.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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._get_api_list(
+ "/payouts",
+ page=SyncCursorPage[PayoutListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "account_id": account_id,
+ "after": after,
+ "before": before,
+ "currency": currency,
+ "first": first,
+ "last": last,
+ "user_id": user_id,
+ },
+ payout_list_params.PayoutListParams,
+ ),
+ ),
+ model=PayoutListResponse,
+ )
+
+
+class AsyncPayoutsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncPayoutsResourceWithRawResponse:
+ """
+ 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 AsyncPayoutsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncPayoutsResourceWithStreamingResponse:
+ """
+ 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 AsyncPayoutsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ currency: str | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ user_id: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> AsyncPaginator[PayoutListResponse, AsyncCursorPage[PayoutListResponse]]:
+ """Lists payouts (withdrawal requests) for a ledger account, most recent first.
+
+ The
+ ledger's owner is passed as exactly one of account*id (a biz* identifier) or
+ user*id (a user* identifier). The saved payout method on each payout
+ additionally requires the payout:destination:read scope and is null without it.
+
+ Args:
+ account_id: The owning account ID (a biz\\__ identifier). Provide this or user_id.
+
+ after: Cursor to fetch the page after (from page_info.end_cursor).
+
+ before: Cursor to fetch the page before (from page_info.start_cursor).
+
+ currency: Optional currency code filter, for example usd.
+
+ first: Number of payouts to return from the start of the window.
+
+ last: Number of payouts to return from the end of the window.
+
+ user_id: The owning user ID (a user\\__ identifier). Provide this or account_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._get_api_list(
+ "/payouts",
+ page=AsyncCursorPage[PayoutListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "account_id": account_id,
+ "after": after,
+ "before": before,
+ "currency": currency,
+ "first": first,
+ "last": last,
+ "user_id": user_id,
+ },
+ payout_list_params.PayoutListParams,
+ ),
+ ),
+ model=PayoutListResponse,
+ )
+
+
+class PayoutsResourceWithRawResponse:
+ def __init__(self, payouts: PayoutsResource) -> None:
+ self._payouts = payouts
+
+ self.list = to_raw_response_wrapper(
+ payouts.list,
+ )
+
+
+class AsyncPayoutsResourceWithRawResponse:
+ def __init__(self, payouts: AsyncPayoutsResource) -> None:
+ self._payouts = payouts
+
+ self.list = async_to_raw_response_wrapper(
+ payouts.list,
+ )
+
+
+class PayoutsResourceWithStreamingResponse:
+ def __init__(self, payouts: PayoutsResource) -> None:
+ self._payouts = payouts
+
+ self.list = to_streamed_response_wrapper(
+ payouts.list,
+ )
+
+
+class AsyncPayoutsResourceWithStreamingResponse:
+ def __init__(self, payouts: AsyncPayoutsResource) -> None:
+ self._payouts = payouts
+
+ self.list = async_to_streamed_response_wrapper(
+ payouts.list,
+ )
diff --git a/src/whop_sdk/resources/plans.py b/src/whop_sdk/resources/plans.py
index e351bc6f..59c15215 100644
--- a/src/whop_sdk/resources/plans.py
+++ b/src/whop_sdk/resources/plans.py
@@ -2,13 +2,12 @@
from __future__ import annotations
-from typing import Dict, List, Union, Iterable, Optional
-from datetime import datetime
+from typing import Iterable, Optional
from typing_extensions import Literal
import httpx
-from ..types import plan_list_params, plan_create_params, plan_update_params
+from ..types import plan_list_params, plan_create_params, plan_update_params, plan_calculate_tax_params
from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -22,22 +21,14 @@
from ..pagination import SyncCursorPage, AsyncCursorPage
from .._base_client import AsyncPaginator, make_request_options
from ..types.shared.plan import Plan
-from ..types.shared.currency import Currency
-from ..types.shared.tax_type import TaxType
-from ..types.shared.direction import Direction
-from ..types.shared.plan_type import PlanType
-from ..types.shared.visibility import Visibility
from ..types.plan_list_response import PlanListResponse
from ..types.plan_delete_response import PlanDeleteResponse
-from ..types.shared.release_method import ReleaseMethod
-from ..types.shared.visibility_filter import VisibilityFilter
+from ..types.plan_calculate_tax_response import PlanCalculateTaxResponse
__all__ = ["PlansResource", "AsyncPlansResource"]
class PlansResource(SyncAPIResource):
- """Plans"""
-
@cached_property
def with_raw_response(self) -> PlansResourceWithRawResponse:
"""
@@ -60,12 +51,11 @@ def with_streaming_response(self) -> PlansResourceWithStreamingResponse:
def create(
self,
*,
- company_id: str,
- product_id: str,
+ account_id: str | Omit = omit,
adaptive_pricing_enabled: Optional[bool] | Omit = omit,
billing_period: Optional[int] | Omit = omit,
- checkout_styling: Optional[plan_create_params.CheckoutStyling] | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
+ checkout_styling: Optional[object] | Omit = omit,
+ currency: str | Omit = omit,
custom_fields: Optional[Iterable[plan_create_params.CustomField]] | Omit = omit,
description: Optional[str] | Omit = omit,
expiration_days: Optional[int] | Omit = omit,
@@ -73,19 +63,20 @@ def create(
initial_price: Optional[float] | Omit = omit,
internal_notes: Optional[str] | Omit = omit,
legacy_payment_method_controls: Optional[bool] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- override_tax_type: Optional[TaxType] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
+ override_tax_type: str | Omit = omit,
payment_method_configuration: Optional[plan_create_params.PaymentMethodConfiguration] | Omit = omit,
- plan_type: Optional[PlanType] | Omit = omit,
- release_method: Optional[ReleaseMethod] | Omit = omit,
+ plan_type: str | Omit = omit,
+ product_id: str | Omit = omit,
+ release_method: str | Omit = omit,
renewal_price: Optional[float] | Omit = omit,
split_pay_required_payments: Optional[int] | Omit = omit,
stock: Optional[int] | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | Omit = omit,
+ three_ds_level: Literal["mandate_challenge", "frictionless"] | Omit = omit,
title: Optional[str] | Omit = omit,
trial_period_days: Optional[int] | Omit = omit,
unlimited_stock: Optional[bool] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -98,76 +89,67 @@ def create(
The plan defines the billing interval,
price, and availability for customers.
- Required permissions:
-
- - `plan:create`
- - `access_pass:basic:read`
- - `plan:basic:read`
-
Args:
- company_id: The unique identifier of the company to create this plan for.
-
- product_id: The unique identifier of the product to attach this plan to.
+ account_id: The unique identifier of the account to create this plan for. Defaults to the
+ caller's account.
adaptive_pricing_enabled: Whether this plan accepts local currency payments via adaptive pricing.
billing_period: The number of days between recurring charges. For example, 30 for monthly or 365
for yearly.
- checkout_styling: Checkout styling overrides for this plan. Pass null to inherit from the company
- default.
+ checkout_styling: Checkout styling overrides for this plan.
- currency: The available currencies on the platform
+ currency: The three-letter ISO currency code for the plan's pricing. Defaults to USD.
custom_fields: An array of custom field definitions to collect from customers at checkout.
+ Omitting this field clears existing custom fields.
description: A text description of the plan displayed to customers on the product page.
- expiration_days: The number of days until the membership expires and access is revoked. Used for
- expiration-based plans.
+ expiration_days: The number of days until the membership expires and access is revoked.
image: An image displayed on the product page to represent this plan.
- initial_price: The amount charged on the first purchase. For one-time plans, this is the full
- price. For recurring plans, this is an additional charge on top of the renewal
- price. Provided in the plan's currency (e.g., 10.43 for $10.43).
+ initial_price: The amount charged on the first purchase, in the plan's currency (e.g., 10.43
+ for $10.43).
internal_notes: Private notes visible only to the business owner. Not shown to customers.
legacy_payment_method_controls: Whether this plan uses legacy payment method controls.
metadata: Custom key-value pairs to store on the plan. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
+ payment and membership events. Max 50 keys, 100 chars per key, 500 chars per
+ string value.
- override_tax_type: Whether or not the tax is included in a plan's price (or if it hasn't been set
- up)
+ override_tax_type: Override the default tax classification for this specific plan.
payment_method_configuration: Explicit payment method configuration for the plan. When not provided, the
- company's defaults apply.
+ account's defaults apply.
+
+ plan_type: The billing type of the plan, such as one_time or renewal.
- plan_type: The type of plan that can be attached to a product
+ product_id: The unique identifier of the product to attach this plan to.
- release_method: The methods of how a plan can be released.
+ release_method: The method used to sell this plan (e.g., buy_now, waitlist).
- renewal_price: The amount charged each billing period for recurring plans. Provided in the
- plan's currency (e.g., 10.43 for $10.43).
+ renewal_price: The amount charged each billing period for recurring plans, in the plan's
+ currency.
split_pay_required_payments: The number of installment payments required before the subscription pauses.
stock: The maximum number of units available for purchase. Ignored when unlimited_stock
is true.
- three_ds_level: The 3D Secure behavior for a plan.
+ three_ds_level: The 3D Secure behavior for this plan. Send null to inherit the account default.
title: The display name of the plan shown to customers on the product page.
trial_period_days: The number of free trial days before the first charge on a recurring plan.
unlimited_stock: Whether the plan has unlimited stock. When true, the stock field is ignored.
- Defaults to true.
- visibility: Visibility of a resource
+ visibility: Whether the plan is visible to customers or hidden from public view.
extra_headers: Send extra headers
@@ -181,8 +163,7 @@ def create(
"/plans",
body=maybe_transform(
{
- "company_id": company_id,
- "product_id": product_id,
+ "account_id": account_id,
"adaptive_pricing_enabled": adaptive_pricing_enabled,
"billing_period": billing_period,
"checkout_styling": checkout_styling,
@@ -198,6 +179,7 @@ def create(
"override_tax_type": override_tax_type,
"payment_method_configuration": payment_method_configuration,
"plan_type": plan_type,
+ "product_id": product_id,
"release_method": release_method,
"renewal_price": renewal_price,
"split_pay_required_payments": split_pay_required_payments,
@@ -230,10 +212,6 @@ def retrieve(
"""
Retrieves the details of an existing plan.
- Required permissions:
-
- - `plan:basic:read`
-
Args:
extra_headers: Send extra headers
@@ -259,8 +237,8 @@ def update(
*,
adaptive_pricing_enabled: Optional[bool] | Omit = omit,
billing_period: Optional[int] | Omit = omit,
- checkout_styling: Optional[plan_update_params.CheckoutStyling] | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
+ checkout_styling: Optional[object] | Omit = omit,
+ currency: str | Omit = omit,
custom_fields: Optional[Iterable[plan_update_params.CustomField]] | Omit = omit,
description: Optional[str] | Omit = omit,
expiration_days: Optional[int] | Omit = omit,
@@ -268,19 +246,19 @@ def update(
initial_price: Optional[float] | Omit = omit,
internal_notes: Optional[str] | Omit = omit,
legacy_payment_method_controls: Optional[bool] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
offer_cancel_discount: Optional[bool] | Omit = omit,
- override_tax_type: Optional[TaxType] | Omit = omit,
+ override_tax_type: str | Omit = omit,
payment_method_configuration: Optional[plan_update_params.PaymentMethodConfiguration] | Omit = omit,
renewal_price: Optional[float] | Omit = omit,
stock: Optional[int] | Omit = omit,
strike_through_initial_price: Optional[float] | Omit = omit,
strike_through_renewal_price: Optional[float] | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | Omit = omit,
+ three_ds_level: Literal["mandate_challenge", "frictionless"] | Omit = omit,
title: Optional[str] | Omit = omit,
trial_period_days: Optional[int] | Omit = omit,
unlimited_stock: Optional[bool] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -292,64 +270,54 @@ def update(
Update a plan's pricing, billing interval, visibility, stock, and other
settings.
- Required permissions:
-
- - `plan:update`
- - `access_pass:basic:read`
- - `plan:basic:read`
-
Args:
adaptive_pricing_enabled: Whether this plan accepts local currency payments via adaptive pricing.
billing_period: The number of days between recurring charges. For example, 30 for monthly or 365
for yearly.
- checkout_styling: Checkout styling overrides for this plan. Pass null to remove all overrides and
- inherit from the company default.
+ checkout_styling: Checkout styling overrides for this plan.
- currency: The available currencies on the platform
+ currency: The three-letter ISO currency code for the plan's pricing. Defaults to USD.
custom_fields: An array of custom field definitions to collect from customers at checkout.
+ Omitting this field clears existing custom fields.
description: A text description of the plan displayed to customers on the product page.
- expiration_days: The number of days until the membership expires and access is revoked. For
- example, 365 for one-year access.
+ expiration_days: The number of days until the membership expires and access is revoked.
image: An image displayed on the product page to represent this plan.
- initial_price: The amount charged on the first purchase. Provided in the plan's currency (e.g.,
- 10.43 for $10.43).
+ initial_price: The amount charged on the first purchase, in the plan's currency (e.g., 10.43
+ for $10.43).
internal_notes: Private notes visible only to the business owner. Not shown to customers.
legacy_payment_method_controls: Whether this plan uses legacy payment method controls.
metadata: Custom key-value pairs to store on the plan. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
+ payment and membership events. Max 50 keys, 100 chars per key, 500 chars per
+ string value.
offer_cancel_discount: Whether to offer a retention discount when a customer attempts to cancel.
- override_tax_type: Whether or not the tax is included in a plan's price (or if it hasn't been set
- up)
+ override_tax_type: Override the default tax classification for this specific plan.
- payment_method_configuration: Explicit payment method configuration for the plan. Sending null removes any
- custom configuration.
+ payment_method_configuration: Explicit payment method configuration for the plan. When not provided, the
+ account's defaults apply.
- renewal_price: The amount charged each billing period for recurring plans. Provided in the
- plan's currency (e.g., 10.43 for $10.43).
+ renewal_price: The amount charged each billing period for recurring plans, in the plan's
+ currency.
stock: The maximum number of units available for purchase. Ignored when unlimited_stock
is true.
strike_through_initial_price: A comparison price displayed with a strikethrough for the initial price.
- Provided in the plan's currency (e.g., 19.99 for $19.99).
strike_through_renewal_price: A comparison price displayed with a strikethrough for the renewal price.
- Provided in the plan's currency (e.g., 19.99 for $19.99).
- three_ds_level: The 3D Secure behavior for a plan.
+ three_ds_level: The 3D Secure behavior for this plan. Send null to inherit the account default.
title: The display name of the plan shown to customers on the product page.
@@ -357,7 +325,7 @@ def update(
unlimited_stock: Whether the plan has unlimited stock. When true, the stock field is ignored.
- visibility: Visibility of a resource
+ visibility: Whether the plan is visible to customers or hidden from public view.
extra_headers: Send extra headers
@@ -409,20 +377,19 @@ def update(
def list(
self,
*,
- company_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- order: Optional[Literal["id", "active_members_count", "created_at", "internal_notes", "expires_at"]]
- | Omit = omit,
- plan_types: Optional[List[PlanType]] | Omit = omit,
- product_ids: Optional[SequenceNotStr[str]] | Omit = omit,
- release_methods: Optional[List[ReleaseMethod]] | Omit = omit,
- visibilities: Optional[List[VisibilityFilter]] | Omit = omit,
+ account_id: str,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ created_after: str | Omit = omit,
+ created_before: str | Omit = omit,
+ direction: Literal["asc", "desc"] | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["id", "active_members_count", "created_at", "internal_notes", "expires_at"] | Omit = omit,
+ plan_types: SequenceNotStr[str] | Omit = omit,
+ product_ids: SequenceNotStr[str] | Omit = omit,
+ release_methods: SequenceNotStr[str] | Omit = omit,
+ visibilities: SequenceNotStr[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.
extra_headers: Headers | None = None,
@@ -431,31 +398,27 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> SyncCursorPage[PlanListResponse]:
"""
- Returns a paginated list of plans belonging to a company, with optional
+ Returns a paginated list of plans belonging to an account, with optional
filtering by visibility, type, release method, and product.
- Required permissions:
-
- - `plan:basic:read`
-
Args:
- company_id: The unique identifier of the company to list plans for.
+ account_id: The unique identifier of the account to list plans for.
- after: Returns the elements in the list that come after the specified cursor.
+ after: A cursor; returns plans after this position.
- before: Returns the elements in the list that come before the specified cursor.
+ before: A cursor; returns plans before this position.
created_after: Only return plans created after this timestamp.
created_before: Only return plans created before this timestamp.
- direction: The direction of the sort.
+ direction: The sort direction for results. Defaults to descending.
- first: Returns the first _n_ elements from the list.
+ first: The number of plans to return (default and max 100).
- last: Returns the last _n_ elements from the list.
+ last: The number of plans to return from the end of the range.
- order: The ways a relation of Plans can be ordered
+ order: The field to sort results by. Defaults to created_at.
plan_types: Filter to only plans matching these billing types.
@@ -483,7 +446,7 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "company_id": company_id,
+ "account_id": account_id,
"after": after,
"before": before,
"created_after": created_after,
@@ -519,10 +482,6 @@ def delete(
Existing memberships on this plan will
not be affected.
- Required permissions:
-
- - `plan:delete`
-
Args:
extra_headers: Send extra headers
@@ -542,10 +501,60 @@ def delete(
cast_to=PlanDeleteResponse,
)
+ def calculate_tax(
+ self,
+ id: str,
+ *,
+ address: Optional[plan_calculate_tax_params.Address] | Omit = omit,
+ ip_address: str | Omit = omit,
+ tax_ids: Optional[Iterable[plan_calculate_tax_params.TaxID]] | 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,
+ ) -> PlanCalculateTaxResponse:
+ """
+ Calculates the tax owed on a plan based on the buyer's location.
-class AsyncPlansResource(AsyncAPIResource):
- """Plans"""
+ Args:
+ address: The buyer's billing address. Provide this or ip_address.
+
+ ip_address: The buyer's IP address, used to resolve their location when no address is
+ provided.
+
+ tax_ids: The buyer's tax IDs, such as a VAT number, used to apply B2B reverse-charge
+ exemptions.
+
+ 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(
+ path_template("/plans/{id}/calculate_tax", id=id),
+ body=maybe_transform(
+ {
+ "address": address,
+ "ip_address": ip_address,
+ "tax_ids": tax_ids,
+ },
+ plan_calculate_tax_params.PlanCalculateTaxParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=PlanCalculateTaxResponse,
+ )
+
+
+class AsyncPlansResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncPlansResourceWithRawResponse:
"""
@@ -568,12 +577,11 @@ def with_streaming_response(self) -> AsyncPlansResourceWithStreamingResponse:
async def create(
self,
*,
- company_id: str,
- product_id: str,
+ account_id: str | Omit = omit,
adaptive_pricing_enabled: Optional[bool] | Omit = omit,
billing_period: Optional[int] | Omit = omit,
- checkout_styling: Optional[plan_create_params.CheckoutStyling] | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
+ checkout_styling: Optional[object] | Omit = omit,
+ currency: str | Omit = omit,
custom_fields: Optional[Iterable[plan_create_params.CustomField]] | Omit = omit,
description: Optional[str] | Omit = omit,
expiration_days: Optional[int] | Omit = omit,
@@ -581,19 +589,20 @@ async def create(
initial_price: Optional[float] | Omit = omit,
internal_notes: Optional[str] | Omit = omit,
legacy_payment_method_controls: Optional[bool] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- override_tax_type: Optional[TaxType] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
+ override_tax_type: str | Omit = omit,
payment_method_configuration: Optional[plan_create_params.PaymentMethodConfiguration] | Omit = omit,
- plan_type: Optional[PlanType] | Omit = omit,
- release_method: Optional[ReleaseMethod] | Omit = omit,
+ plan_type: str | Omit = omit,
+ product_id: str | Omit = omit,
+ release_method: str | Omit = omit,
renewal_price: Optional[float] | Omit = omit,
split_pay_required_payments: Optional[int] | Omit = omit,
stock: Optional[int] | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | Omit = omit,
+ three_ds_level: Literal["mandate_challenge", "frictionless"] | Omit = omit,
title: Optional[str] | Omit = omit,
trial_period_days: Optional[int] | Omit = omit,
unlimited_stock: Optional[bool] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -606,76 +615,67 @@ async def create(
The plan defines the billing interval,
price, and availability for customers.
- Required permissions:
-
- - `plan:create`
- - `access_pass:basic:read`
- - `plan:basic:read`
-
Args:
- company_id: The unique identifier of the company to create this plan for.
-
- product_id: The unique identifier of the product to attach this plan to.
+ account_id: The unique identifier of the account to create this plan for. Defaults to the
+ caller's account.
adaptive_pricing_enabled: Whether this plan accepts local currency payments via adaptive pricing.
billing_period: The number of days between recurring charges. For example, 30 for monthly or 365
for yearly.
- checkout_styling: Checkout styling overrides for this plan. Pass null to inherit from the company
- default.
+ checkout_styling: Checkout styling overrides for this plan.
- currency: The available currencies on the platform
+ currency: The three-letter ISO currency code for the plan's pricing. Defaults to USD.
custom_fields: An array of custom field definitions to collect from customers at checkout.
+ Omitting this field clears existing custom fields.
description: A text description of the plan displayed to customers on the product page.
- expiration_days: The number of days until the membership expires and access is revoked. Used for
- expiration-based plans.
+ expiration_days: The number of days until the membership expires and access is revoked.
image: An image displayed on the product page to represent this plan.
- initial_price: The amount charged on the first purchase. For one-time plans, this is the full
- price. For recurring plans, this is an additional charge on top of the renewal
- price. Provided in the plan's currency (e.g., 10.43 for $10.43).
+ initial_price: The amount charged on the first purchase, in the plan's currency (e.g., 10.43
+ for $10.43).
internal_notes: Private notes visible only to the business owner. Not shown to customers.
legacy_payment_method_controls: Whether this plan uses legacy payment method controls.
metadata: Custom key-value pairs to store on the plan. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
+ payment and membership events. Max 50 keys, 100 chars per key, 500 chars per
+ string value.
- override_tax_type: Whether or not the tax is included in a plan's price (or if it hasn't been set
- up)
+ override_tax_type: Override the default tax classification for this specific plan.
payment_method_configuration: Explicit payment method configuration for the plan. When not provided, the
- company's defaults apply.
+ account's defaults apply.
- plan_type: The type of plan that can be attached to a product
+ plan_type: The billing type of the plan, such as one_time or renewal.
- release_method: The methods of how a plan can be released.
+ product_id: The unique identifier of the product to attach this plan to.
- renewal_price: The amount charged each billing period for recurring plans. Provided in the
- plan's currency (e.g., 10.43 for $10.43).
+ release_method: The method used to sell this plan (e.g., buy_now, waitlist).
+
+ renewal_price: The amount charged each billing period for recurring plans, in the plan's
+ currency.
split_pay_required_payments: The number of installment payments required before the subscription pauses.
stock: The maximum number of units available for purchase. Ignored when unlimited_stock
is true.
- three_ds_level: The 3D Secure behavior for a plan.
+ three_ds_level: The 3D Secure behavior for this plan. Send null to inherit the account default.
title: The display name of the plan shown to customers on the product page.
trial_period_days: The number of free trial days before the first charge on a recurring plan.
unlimited_stock: Whether the plan has unlimited stock. When true, the stock field is ignored.
- Defaults to true.
- visibility: Visibility of a resource
+ visibility: Whether the plan is visible to customers or hidden from public view.
extra_headers: Send extra headers
@@ -689,8 +689,7 @@ async def create(
"/plans",
body=await async_maybe_transform(
{
- "company_id": company_id,
- "product_id": product_id,
+ "account_id": account_id,
"adaptive_pricing_enabled": adaptive_pricing_enabled,
"billing_period": billing_period,
"checkout_styling": checkout_styling,
@@ -706,6 +705,7 @@ async def create(
"override_tax_type": override_tax_type,
"payment_method_configuration": payment_method_configuration,
"plan_type": plan_type,
+ "product_id": product_id,
"release_method": release_method,
"renewal_price": renewal_price,
"split_pay_required_payments": split_pay_required_payments,
@@ -738,10 +738,6 @@ async def retrieve(
"""
Retrieves the details of an existing plan.
- Required permissions:
-
- - `plan:basic:read`
-
Args:
extra_headers: Send extra headers
@@ -767,8 +763,8 @@ async def update(
*,
adaptive_pricing_enabled: Optional[bool] | Omit = omit,
billing_period: Optional[int] | Omit = omit,
- checkout_styling: Optional[plan_update_params.CheckoutStyling] | Omit = omit,
- currency: Optional[Currency] | Omit = omit,
+ checkout_styling: Optional[object] | Omit = omit,
+ currency: str | Omit = omit,
custom_fields: Optional[Iterable[plan_update_params.CustomField]] | Omit = omit,
description: Optional[str] | Omit = omit,
expiration_days: Optional[int] | Omit = omit,
@@ -776,19 +772,19 @@ async def update(
initial_price: Optional[float] | Omit = omit,
internal_notes: Optional[str] | Omit = omit,
legacy_payment_method_controls: Optional[bool] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
offer_cancel_discount: Optional[bool] | Omit = omit,
- override_tax_type: Optional[TaxType] | Omit = omit,
+ override_tax_type: str | Omit = omit,
payment_method_configuration: Optional[plan_update_params.PaymentMethodConfiguration] | Omit = omit,
renewal_price: Optional[float] | Omit = omit,
stock: Optional[int] | Omit = omit,
strike_through_initial_price: Optional[float] | Omit = omit,
strike_through_renewal_price: Optional[float] | Omit = omit,
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] | Omit = omit,
+ three_ds_level: Literal["mandate_challenge", "frictionless"] | Omit = omit,
title: Optional[str] | Omit = omit,
trial_period_days: Optional[int] | Omit = omit,
unlimited_stock: Optional[bool] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -800,64 +796,54 @@ async def update(
Update a plan's pricing, billing interval, visibility, stock, and other
settings.
- Required permissions:
-
- - `plan:update`
- - `access_pass:basic:read`
- - `plan:basic:read`
-
Args:
adaptive_pricing_enabled: Whether this plan accepts local currency payments via adaptive pricing.
billing_period: The number of days between recurring charges. For example, 30 for monthly or 365
for yearly.
- checkout_styling: Checkout styling overrides for this plan. Pass null to remove all overrides and
- inherit from the company default.
+ checkout_styling: Checkout styling overrides for this plan.
- currency: The available currencies on the platform
+ currency: The three-letter ISO currency code for the plan's pricing. Defaults to USD.
custom_fields: An array of custom field definitions to collect from customers at checkout.
+ Omitting this field clears existing custom fields.
description: A text description of the plan displayed to customers on the product page.
- expiration_days: The number of days until the membership expires and access is revoked. For
- example, 365 for one-year access.
+ expiration_days: The number of days until the membership expires and access is revoked.
image: An image displayed on the product page to represent this plan.
- initial_price: The amount charged on the first purchase. Provided in the plan's currency (e.g.,
- 10.43 for $10.43).
+ initial_price: The amount charged on the first purchase, in the plan's currency (e.g., 10.43
+ for $10.43).
internal_notes: Private notes visible only to the business owner. Not shown to customers.
legacy_payment_method_controls: Whether this plan uses legacy payment method controls.
metadata: Custom key-value pairs to store on the plan. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
+ payment and membership events. Max 50 keys, 100 chars per key, 500 chars per
+ string value.
offer_cancel_discount: Whether to offer a retention discount when a customer attempts to cancel.
- override_tax_type: Whether or not the tax is included in a plan's price (or if it hasn't been set
- up)
+ override_tax_type: Override the default tax classification for this specific plan.
- payment_method_configuration: Explicit payment method configuration for the plan. Sending null removes any
- custom configuration.
+ payment_method_configuration: Explicit payment method configuration for the plan. When not provided, the
+ account's defaults apply.
- renewal_price: The amount charged each billing period for recurring plans. Provided in the
- plan's currency (e.g., 10.43 for $10.43).
+ renewal_price: The amount charged each billing period for recurring plans, in the plan's
+ currency.
stock: The maximum number of units available for purchase. Ignored when unlimited_stock
is true.
strike_through_initial_price: A comparison price displayed with a strikethrough for the initial price.
- Provided in the plan's currency (e.g., 19.99 for $19.99).
strike_through_renewal_price: A comparison price displayed with a strikethrough for the renewal price.
- Provided in the plan's currency (e.g., 19.99 for $19.99).
- three_ds_level: The 3D Secure behavior for a plan.
+ three_ds_level: The 3D Secure behavior for this plan. Send null to inherit the account default.
title: The display name of the plan shown to customers on the product page.
@@ -865,7 +851,7 @@ async def update(
unlimited_stock: Whether the plan has unlimited stock. When true, the stock field is ignored.
- visibility: Visibility of a resource
+ visibility: Whether the plan is visible to customers or hidden from public view.
extra_headers: Send extra headers
@@ -917,20 +903,19 @@ async def update(
def list(
self,
*,
- company_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- order: Optional[Literal["id", "active_members_count", "created_at", "internal_notes", "expires_at"]]
- | Omit = omit,
- plan_types: Optional[List[PlanType]] | Omit = omit,
- product_ids: Optional[SequenceNotStr[str]] | Omit = omit,
- release_methods: Optional[List[ReleaseMethod]] | Omit = omit,
- visibilities: Optional[List[VisibilityFilter]] | Omit = omit,
+ account_id: str,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ created_after: str | Omit = omit,
+ created_before: str | Omit = omit,
+ direction: Literal["asc", "desc"] | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["id", "active_members_count", "created_at", "internal_notes", "expires_at"] | Omit = omit,
+ plan_types: SequenceNotStr[str] | Omit = omit,
+ product_ids: SequenceNotStr[str] | Omit = omit,
+ release_methods: SequenceNotStr[str] | Omit = omit,
+ visibilities: SequenceNotStr[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.
extra_headers: Headers | None = None,
@@ -939,31 +924,27 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AsyncPaginator[PlanListResponse, AsyncCursorPage[PlanListResponse]]:
"""
- Returns a paginated list of plans belonging to a company, with optional
+ Returns a paginated list of plans belonging to an account, with optional
filtering by visibility, type, release method, and product.
- Required permissions:
-
- - `plan:basic:read`
-
Args:
- company_id: The unique identifier of the company to list plans for.
+ account_id: The unique identifier of the account to list plans for.
- after: Returns the elements in the list that come after the specified cursor.
+ after: A cursor; returns plans after this position.
- before: Returns the elements in the list that come before the specified cursor.
+ before: A cursor; returns plans before this position.
created_after: Only return plans created after this timestamp.
created_before: Only return plans created before this timestamp.
- direction: The direction of the sort.
+ direction: The sort direction for results. Defaults to descending.
- first: Returns the first _n_ elements from the list.
+ first: The number of plans to return (default and max 100).
- last: Returns the last _n_ elements from the list.
+ last: The number of plans to return from the end of the range.
- order: The ways a relation of Plans can be ordered
+ order: The field to sort results by. Defaults to created_at.
plan_types: Filter to only plans matching these billing types.
@@ -991,7 +972,7 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "company_id": company_id,
+ "account_id": account_id,
"after": after,
"before": before,
"created_after": created_after,
@@ -1027,10 +1008,6 @@ async def delete(
Existing memberships on this plan will
not be affected.
- Required permissions:
-
- - `plan:delete`
-
Args:
extra_headers: Send extra headers
@@ -1050,6 +1027,58 @@ async def delete(
cast_to=PlanDeleteResponse,
)
+ async def calculate_tax(
+ self,
+ id: str,
+ *,
+ address: Optional[plan_calculate_tax_params.Address] | Omit = omit,
+ ip_address: str | Omit = omit,
+ tax_ids: Optional[Iterable[plan_calculate_tax_params.TaxID]] | 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,
+ ) -> PlanCalculateTaxResponse:
+ """
+ Calculates the tax owed on a plan based on the buyer's location.
+
+ Args:
+ address: The buyer's billing address. Provide this or ip_address.
+
+ ip_address: The buyer's IP address, used to resolve their location when no address is
+ provided.
+
+ tax_ids: The buyer's tax IDs, such as a VAT number, used to apply B2B reverse-charge
+ exemptions.
+
+ 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(
+ path_template("/plans/{id}/calculate_tax", id=id),
+ body=await async_maybe_transform(
+ {
+ "address": address,
+ "ip_address": ip_address,
+ "tax_ids": tax_ids,
+ },
+ plan_calculate_tax_params.PlanCalculateTaxParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=PlanCalculateTaxResponse,
+ )
+
class PlansResourceWithRawResponse:
def __init__(self, plans: PlansResource) -> None:
@@ -1070,6 +1099,9 @@ def __init__(self, plans: PlansResource) -> None:
self.delete = to_raw_response_wrapper(
plans.delete,
)
+ self.calculate_tax = to_raw_response_wrapper(
+ plans.calculate_tax,
+ )
class AsyncPlansResourceWithRawResponse:
@@ -1091,6 +1123,9 @@ def __init__(self, plans: AsyncPlansResource) -> None:
self.delete = async_to_raw_response_wrapper(
plans.delete,
)
+ self.calculate_tax = async_to_raw_response_wrapper(
+ plans.calculate_tax,
+ )
class PlansResourceWithStreamingResponse:
@@ -1112,6 +1147,9 @@ def __init__(self, plans: PlansResource) -> None:
self.delete = to_streamed_response_wrapper(
plans.delete,
)
+ self.calculate_tax = to_streamed_response_wrapper(
+ plans.calculate_tax,
+ )
class AsyncPlansResourceWithStreamingResponse:
@@ -1133,3 +1171,6 @@ def __init__(self, plans: AsyncPlansResource) -> None:
self.delete = async_to_streamed_response_wrapper(
plans.delete,
)
+ self.calculate_tax = async_to_streamed_response_wrapper(
+ plans.calculate_tax,
+ )
diff --git a/src/whop_sdk/resources/products.py b/src/whop_sdk/resources/products.py
index 505de8e1..5bb4f3b4 100644
--- a/src/whop_sdk/resources/products.py
+++ b/src/whop_sdk/resources/products.py
@@ -2,8 +2,7 @@
from __future__ import annotations
-from typing import Dict, List, Union, Iterable, Optional
-from datetime import datetime
+from typing import Optional
from typing_extensions import Literal
import httpx
@@ -22,14 +21,8 @@
from ..pagination import SyncCursorPage, AsyncCursorPage
from .._base_client import AsyncPaginator, make_request_options
from ..types.shared.product import Product
-from ..types.shared.direction import Direction
-from ..types.shared.custom_cta import CustomCta
-from ..types.shared.visibility import Visibility
from ..types.product_delete_response import ProductDeleteResponse
-from ..types.shared.access_pass_type import AccessPassType
from ..types.shared.product_list_item import ProductListItem
-from ..types.shared.visibility_filter import VisibilityFilter
-from ..types.shared.global_affiliate_status import GlobalAffiliateStatus
__all__ = ["ProductsResource", "AsyncProductsResource"]
@@ -59,26 +52,23 @@ def with_streaming_response(self) -> ProductsResourceWithStreamingResponse:
def create(
self,
*,
- company_id: str,
title: str,
collect_shipping_address: Optional[bool] | Omit = omit,
- custom_cta: Optional[CustomCta] | Omit = omit,
+ company_id: str | Omit = omit,
+ custom_cta: Optional[str] | Omit = omit,
custom_cta_url: Optional[str] | Omit = omit,
custom_statement_descriptor: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
- experience_ids: Optional[SequenceNotStr[str]] | Omit = omit,
global_affiliate_percentage: Optional[float] | Omit = omit,
- global_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
+ global_affiliate_status: str | Omit = omit,
headline: Optional[str] | Omit = omit,
member_affiliate_percentage: Optional[float] | Omit = omit,
- member_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- plan_options: Optional[product_create_params.PlanOptions] | Omit = omit,
+ member_affiliate_status: str | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
product_tax_code_id: Optional[str] | Omit = omit,
redirect_purchase_url: Optional[str] | Omit = omit,
route: Optional[str] | Omit = omit,
- send_welcome_message: Optional[bool] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -86,64 +76,43 @@ def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Product:
- """Create a new product for a company.
-
- The product serves as the top-level
- container for plans and experiences.
-
- Required permissions:
-
- - `access_pass:create`
- - `access_pass:basic:read`
+ """
+ Creates a new product for a company.
Args:
- company_id: The unique identifier of the company to create this product for.
-
title: The display name of the product. Maximum 80 characters.
- collect_shipping_address: Whether the checkout flow collects a shipping address from the customer.
-
- custom_cta: The different types of custom CTAs that can be selected.
+ collect_shipping_address: Whether to collect a shipping address at checkout.
- custom_cta_url: A URL that the call-to-action button links to instead of the default checkout
- flow.
+ company_id: The unique identifier of the company to create this product for.
- custom_statement_descriptor: A custom text label that appears on the customer's bank statement. Must be 5-22
- characters, contain at least one letter, and not contain <, >, \\,, ', or "
- characters.
+ custom_cta: The call-to-action button label.
- description: A written description of the product displayed on its product page.
+ custom_cta_url: A URL the call-to-action button links to.
- experience_ids: The unique identifiers of experiences to connect to this product.
+ custom_statement_descriptor: Custom bank statement descriptor. Must start with WHOP\\**.
- global_affiliate_percentage: The commission rate as a percentage that affiliates earn through the global
- affiliate program.
+ description: A written description displayed on the product page.
- global_affiliate_status: The different statuses of the global affiliate program for a product.
+ global_affiliate_percentage: The commission rate affiliates earn.
- headline: A short marketing headline displayed prominently on the product page.
+ global_affiliate_status: The enrollment status in the global affiliate program.
- member_affiliate_percentage: The commission rate as a percentage that members earn through the member
- affiliate program.
+ headline: A short marketing headline for the product page.
- member_affiliate_status: The different statuses of the global affiliate program for a product.
+ member_affiliate_percentage: The commission rate members earn.
- metadata: Custom key-value pairs to store on the product. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
+ member_affiliate_status: The enrollment status in the member affiliate program.
- plan_options: Configuration for an automatically generated plan to attach to this product.
+ metadata: Custom key-value pairs to store on the product.
- product_tax_code_id: The unique identifier of the tax classification code to apply to this product.
+ product_tax_code_id: The unique identifier of the tax classification code.
- redirect_purchase_url: A URL to redirect the customer to after completing a purchase.
+ redirect_purchase_url: A URL to redirect the customer to after purchase.
route: The URL slug for the product's public link.
- send_welcome_message: Whether to send an automated welcome message via support chat when a user joins
- this product. Defaults to true.
-
- visibility: Visibility of a resource
+ visibility: Whether the product is visible to customers.
extra_headers: Send extra headers
@@ -157,25 +126,22 @@ def create(
"/products",
body=maybe_transform(
{
- "company_id": company_id,
"title": title,
"collect_shipping_address": collect_shipping_address,
+ "company_id": company_id,
"custom_cta": custom_cta,
"custom_cta_url": custom_cta_url,
"custom_statement_descriptor": custom_statement_descriptor,
"description": description,
- "experience_ids": experience_ids,
"global_affiliate_percentage": global_affiliate_percentage,
"global_affiliate_status": global_affiliate_status,
"headline": headline,
"member_affiliate_percentage": member_affiliate_percentage,
"member_affiliate_status": member_affiliate_status,
"metadata": metadata,
- "plan_options": plan_options,
"product_tax_code_id": product_tax_code_id,
"redirect_purchase_url": redirect_purchase_url,
"route": route,
- "send_welcome_message": send_welcome_message,
"visibility": visibility,
},
product_create_params.ProductCreateParams,
@@ -197,12 +163,10 @@ def retrieve(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Product:
- """
- Retrieves the details of an existing product.
-
- Required permissions:
+ """Retrieves the details of an existing product.
- - `access_pass:basic:read`
+ This endpoint is publicly
+ accessible.
Args:
extra_headers: Send extra headers
@@ -227,25 +191,11 @@ def update(
self,
id: str,
*,
- collect_shipping_address: Optional[bool] | Omit = omit,
- custom_cta: Optional[CustomCta] | Omit = omit,
- custom_cta_url: Optional[str] | Omit = omit,
- custom_statement_descriptor: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
- gallery_images: Optional[Iterable[product_update_params.GalleryImage]] | Omit = omit,
- global_affiliate_percentage: Optional[float] | Omit = omit,
- global_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
headline: Optional[str] | Omit = omit,
- member_affiliate_percentage: Optional[float] | Omit = omit,
- member_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- product_tax_code_id: Optional[str] | Omit = omit,
- redirect_purchase_url: Optional[str] | Omit = omit,
- route: Optional[str] | Omit = omit,
- send_welcome_message: Optional[bool] | Omit = omit,
- store_page_config: Optional[product_update_params.StorePageConfig] | Omit = omit,
- title: Optional[str] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
+ title: str | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -254,59 +204,18 @@ def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Product:
"""
- Update a product's title, description, visibility, and other settings.
-
- Required permissions:
-
- - `access_pass:update`
- - `access_pass:basic:read`
+ Updates an existing product.
Args:
- collect_shipping_address: Whether the checkout flow collects a shipping address from the customer.
-
- custom_cta: The different types of custom CTAs that can be selected.
-
- custom_cta_url: A URL that the call-to-action button links to instead of the default checkout
- flow.
-
- custom_statement_descriptor: A custom text label that appears on the customer's bank statement. Must be 5-22
- characters, contain at least one letter, and not contain <, >, \\,, ', or "
- characters.
-
- description: A written description of the product displayed on its product page.
-
- gallery_images: The gallery images for the product.
+ description: A written description displayed on the product page.
- global_affiliate_percentage: The commission rate as a percentage that affiliates earn through the global
- affiliate program.
+ headline: A short marketing headline for the product page.
- global_affiliate_status: The different statuses of the global affiliate program for a product.
+ metadata: Custom key-value pairs to store on the product.
- headline: A short marketing headline displayed prominently on the product page.
+ title: The display name of the product.
- member_affiliate_percentage: The commission rate as a percentage that members earn through the member
- affiliate program.
-
- member_affiliate_status: The different statuses of the global affiliate program for a product.
-
- metadata: Custom key-value pairs to store on the product. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
-
- product_tax_code_id: The unique identifier of the tax classification code to apply to this product.
-
- redirect_purchase_url: A URL to redirect the customer to after completing a purchase.
-
- route: The URL slug for the product's public link.
-
- send_welcome_message: Whether to send an automated welcome message via support chat when a user joins
- this product.
-
- store_page_config: Layout and display configuration for this product on the company's store page.
-
- title: The display name of the product. Maximum 80 characters.
-
- visibility: Visibility of a resource
+ visibility: Whether the product is visible to customers.
extra_headers: Send extra headers
@@ -322,23 +231,9 @@ def update(
path_template("/products/{id}", id=id),
body=maybe_transform(
{
- "collect_shipping_address": collect_shipping_address,
- "custom_cta": custom_cta,
- "custom_cta_url": custom_cta_url,
- "custom_statement_descriptor": custom_statement_descriptor,
"description": description,
- "gallery_images": gallery_images,
- "global_affiliate_percentage": global_affiliate_percentage,
- "global_affiliate_status": global_affiliate_status,
"headline": headline,
- "member_affiliate_percentage": member_affiliate_percentage,
- "member_affiliate_status": member_affiliate_status,
"metadata": metadata,
- "product_tax_code_id": product_tax_code_id,
- "redirect_purchase_url": redirect_purchase_url,
- "route": route,
- "send_welcome_message": send_welcome_message,
- "store_page_config": store_page_config,
"title": title,
"visibility": visibility,
},
@@ -354,16 +249,14 @@ def list(
self,
*,
company_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- order: Optional[Literal["active_memberships_count", "created_at", "usd_gmv", "usd_gmv_30_days"]] | Omit = omit,
- product_types: Optional[List[AccessPassType]] | Omit = omit,
- visibilities: Optional[List[VisibilityFilter]] | Omit = omit,
+ access_pass_types: SequenceNotStr[str] | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ direction: Literal["asc", "desc"] | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ order: str | Omit = omit,
+ visibilities: SequenceNotStr[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.
extra_headers: Headers | None = None,
@@ -372,33 +265,24 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> SyncCursorPage[ProductListItem]:
"""
- Returns a paginated list of products belonging to a company, with optional
- filtering by type, visibility, and creation date.
-
- Required permissions:
-
- - `access_pass:basic:read`
+ Returns a paginated list of products belonging to a company.
Args:
company_id: The unique identifier of the company to list products 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.
+ access_pass_types: Filter to only products matching these types.
- created_after: Only return products created after this timestamp.
+ after: A cursor; returns products after this position.
- created_before: Only return products created before this timestamp.
+ before: A cursor; returns products before this position.
- direction: The direction of the sort.
+ direction: The sort direction for results. Defaults to descending.
- first: Returns the first _n_ elements from the list.
+ first: The number of products to return (default and max 100).
- last: Returns the last _n_ elements from the list.
+ last: The number of products to return from the end of the range.
- order: The ways a relation of AccessPasses can be ordered
-
- product_types: Filter to only products matching these type classifications.
+ order: The field to sort results by. Defaults to created_at.
visibilities: Filter to only products matching these visibility states.
@@ -421,15 +305,13 @@ def list(
query=maybe_transform(
{
"company_id": company_id,
+ "access_pass_types": access_pass_types,
"after": after,
"before": before,
- "created_after": created_after,
- "created_before": created_before,
"direction": direction,
"first": first,
"last": last,
"order": order,
- "product_types": product_types,
"visibilities": visibilities,
},
product_list_params.ProductListParams,
@@ -449,12 +331,10 @@ def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ProductDeleteResponse:
- """
- Permanently delete a product and remove it from the company's catalog.
-
- Required permissions:
+ """Deletes a product.
- - `access_pass:delete`
+ Only products with no memberships, entries, reviews, or
+ invoices can be deleted.
Args:
extra_headers: Send extra headers
@@ -501,26 +381,23 @@ def with_streaming_response(self) -> AsyncProductsResourceWithStreamingResponse:
async def create(
self,
*,
- company_id: str,
title: str,
collect_shipping_address: Optional[bool] | Omit = omit,
- custom_cta: Optional[CustomCta] | Omit = omit,
+ company_id: str | Omit = omit,
+ custom_cta: Optional[str] | Omit = omit,
custom_cta_url: Optional[str] | Omit = omit,
custom_statement_descriptor: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
- experience_ids: Optional[SequenceNotStr[str]] | Omit = omit,
global_affiliate_percentage: Optional[float] | Omit = omit,
- global_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
+ global_affiliate_status: str | Omit = omit,
headline: Optional[str] | Omit = omit,
member_affiliate_percentage: Optional[float] | Omit = omit,
- member_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- plan_options: Optional[product_create_params.PlanOptions] | Omit = omit,
+ member_affiliate_status: str | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
product_tax_code_id: Optional[str] | Omit = omit,
redirect_purchase_url: Optional[str] | Omit = omit,
route: Optional[str] | Omit = omit,
- send_welcome_message: Optional[bool] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -528,64 +405,43 @@ async def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Product:
- """Create a new product for a company.
-
- The product serves as the top-level
- container for plans and experiences.
-
- Required permissions:
-
- - `access_pass:create`
- - `access_pass:basic:read`
+ """
+ Creates a new product for a company.
Args:
- company_id: The unique identifier of the company to create this product for.
-
title: The display name of the product. Maximum 80 characters.
- collect_shipping_address: Whether the checkout flow collects a shipping address from the customer.
-
- custom_cta: The different types of custom CTAs that can be selected.
+ collect_shipping_address: Whether to collect a shipping address at checkout.
- custom_cta_url: A URL that the call-to-action button links to instead of the default checkout
- flow.
+ company_id: The unique identifier of the company to create this product for.
- custom_statement_descriptor: A custom text label that appears on the customer's bank statement. Must be 5-22
- characters, contain at least one letter, and not contain <, >, \\,, ', or "
- characters.
+ custom_cta: The call-to-action button label.
- description: A written description of the product displayed on its product page.
+ custom_cta_url: A URL the call-to-action button links to.
- experience_ids: The unique identifiers of experiences to connect to this product.
+ custom_statement_descriptor: Custom bank statement descriptor. Must start with WHOP\\**.
- global_affiliate_percentage: The commission rate as a percentage that affiliates earn through the global
- affiliate program.
+ description: A written description displayed on the product page.
- global_affiliate_status: The different statuses of the global affiliate program for a product.
+ global_affiliate_percentage: The commission rate affiliates earn.
- headline: A short marketing headline displayed prominently on the product page.
+ global_affiliate_status: The enrollment status in the global affiliate program.
- member_affiliate_percentage: The commission rate as a percentage that members earn through the member
- affiliate program.
+ headline: A short marketing headline for the product page.
- member_affiliate_status: The different statuses of the global affiliate program for a product.
+ member_affiliate_percentage: The commission rate members earn.
- metadata: Custom key-value pairs to store on the product. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
+ member_affiliate_status: The enrollment status in the member affiliate program.
- plan_options: Configuration for an automatically generated plan to attach to this product.
+ metadata: Custom key-value pairs to store on the product.
- product_tax_code_id: The unique identifier of the tax classification code to apply to this product.
+ product_tax_code_id: The unique identifier of the tax classification code.
- redirect_purchase_url: A URL to redirect the customer to after completing a purchase.
+ redirect_purchase_url: A URL to redirect the customer to after purchase.
route: The URL slug for the product's public link.
- send_welcome_message: Whether to send an automated welcome message via support chat when a user joins
- this product. Defaults to true.
-
- visibility: Visibility of a resource
+ visibility: Whether the product is visible to customers.
extra_headers: Send extra headers
@@ -599,25 +455,22 @@ async def create(
"/products",
body=await async_maybe_transform(
{
- "company_id": company_id,
"title": title,
"collect_shipping_address": collect_shipping_address,
+ "company_id": company_id,
"custom_cta": custom_cta,
"custom_cta_url": custom_cta_url,
"custom_statement_descriptor": custom_statement_descriptor,
"description": description,
- "experience_ids": experience_ids,
"global_affiliate_percentage": global_affiliate_percentage,
"global_affiliate_status": global_affiliate_status,
"headline": headline,
"member_affiliate_percentage": member_affiliate_percentage,
"member_affiliate_status": member_affiliate_status,
"metadata": metadata,
- "plan_options": plan_options,
"product_tax_code_id": product_tax_code_id,
"redirect_purchase_url": redirect_purchase_url,
"route": route,
- "send_welcome_message": send_welcome_message,
"visibility": visibility,
},
product_create_params.ProductCreateParams,
@@ -639,12 +492,10 @@ async def retrieve(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Product:
- """
- Retrieves the details of an existing product.
-
- Required permissions:
+ """Retrieves the details of an existing product.
- - `access_pass:basic:read`
+ This endpoint is publicly
+ accessible.
Args:
extra_headers: Send extra headers
@@ -669,25 +520,11 @@ async def update(
self,
id: str,
*,
- collect_shipping_address: Optional[bool] | Omit = omit,
- custom_cta: Optional[CustomCta] | Omit = omit,
- custom_cta_url: Optional[str] | Omit = omit,
- custom_statement_descriptor: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
- gallery_images: Optional[Iterable[product_update_params.GalleryImage]] | Omit = omit,
- global_affiliate_percentage: Optional[float] | Omit = omit,
- global_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
headline: Optional[str] | Omit = omit,
- member_affiliate_percentage: Optional[float] | Omit = omit,
- member_affiliate_status: Optional[GlobalAffiliateStatus] | Omit = omit,
- metadata: Optional[Dict[str, object]] | Omit = omit,
- product_tax_code_id: Optional[str] | Omit = omit,
- redirect_purchase_url: Optional[str] | Omit = omit,
- route: Optional[str] | Omit = omit,
- send_welcome_message: Optional[bool] | Omit = omit,
- store_page_config: Optional[product_update_params.StorePageConfig] | Omit = omit,
- title: Optional[str] | Omit = omit,
- visibility: Optional[Visibility] | Omit = omit,
+ metadata: Optional[object] | Omit = omit,
+ title: str | Omit = omit,
+ visibility: 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.
extra_headers: Headers | None = None,
@@ -696,59 +533,18 @@ async def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> Product:
"""
- Update a product's title, description, visibility, and other settings.
-
- Required permissions:
-
- - `access_pass:update`
- - `access_pass:basic:read`
+ Updates an existing product.
Args:
- collect_shipping_address: Whether the checkout flow collects a shipping address from the customer.
-
- custom_cta: The different types of custom CTAs that can be selected.
-
- custom_cta_url: A URL that the call-to-action button links to instead of the default checkout
- flow.
-
- custom_statement_descriptor: A custom text label that appears on the customer's bank statement. Must be 5-22
- characters, contain at least one letter, and not contain <, >, \\,, ', or "
- characters.
-
- description: A written description of the product displayed on its product page.
-
- gallery_images: The gallery images for the product.
+ description: A written description displayed on the product page.
- global_affiliate_percentage: The commission rate as a percentage that affiliates earn through the global
- affiliate program.
+ headline: A short marketing headline for the product page.
- global_affiliate_status: The different statuses of the global affiliate program for a product.
+ metadata: Custom key-value pairs to store on the product.
- headline: A short marketing headline displayed prominently on the product page.
+ title: The display name of the product.
- member_affiliate_percentage: The commission rate as a percentage that members earn through the member
- affiliate program.
-
- member_affiliate_status: The different statuses of the global affiliate program for a product.
-
- metadata: Custom key-value pairs to store on the product. Included in webhook payloads for
- payment and membership events. Max 50 keys, 500 chars per key, 5000 chars per
- value.
-
- product_tax_code_id: The unique identifier of the tax classification code to apply to this product.
-
- redirect_purchase_url: A URL to redirect the customer to after completing a purchase.
-
- route: The URL slug for the product's public link.
-
- send_welcome_message: Whether to send an automated welcome message via support chat when a user joins
- this product.
-
- store_page_config: Layout and display configuration for this product on the company's store page.
-
- title: The display name of the product. Maximum 80 characters.
-
- visibility: Visibility of a resource
+ visibility: Whether the product is visible to customers.
extra_headers: Send extra headers
@@ -764,23 +560,9 @@ async def update(
path_template("/products/{id}", id=id),
body=await async_maybe_transform(
{
- "collect_shipping_address": collect_shipping_address,
- "custom_cta": custom_cta,
- "custom_cta_url": custom_cta_url,
- "custom_statement_descriptor": custom_statement_descriptor,
"description": description,
- "gallery_images": gallery_images,
- "global_affiliate_percentage": global_affiliate_percentage,
- "global_affiliate_status": global_affiliate_status,
"headline": headline,
- "member_affiliate_percentage": member_affiliate_percentage,
- "member_affiliate_status": member_affiliate_status,
"metadata": metadata,
- "product_tax_code_id": product_tax_code_id,
- "redirect_purchase_url": redirect_purchase_url,
- "route": route,
- "send_welcome_message": send_welcome_message,
- "store_page_config": store_page_config,
"title": title,
"visibility": visibility,
},
@@ -796,16 +578,14 @@ def list(
self,
*,
company_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- order: Optional[Literal["active_memberships_count", "created_at", "usd_gmv", "usd_gmv_30_days"]] | Omit = omit,
- product_types: Optional[List[AccessPassType]] | Omit = omit,
- visibilities: Optional[List[VisibilityFilter]] | Omit = omit,
+ access_pass_types: SequenceNotStr[str] | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ direction: Literal["asc", "desc"] | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ order: str | Omit = omit,
+ visibilities: SequenceNotStr[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.
extra_headers: Headers | None = None,
@@ -814,33 +594,24 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AsyncPaginator[ProductListItem, AsyncCursorPage[ProductListItem]]:
"""
- Returns a paginated list of products belonging to a company, with optional
- filtering by type, visibility, and creation date.
-
- Required permissions:
-
- - `access_pass:basic:read`
+ Returns a paginated list of products belonging to a company.
Args:
company_id: The unique identifier of the company to list products 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.
+ access_pass_types: Filter to only products matching these types.
- created_after: Only return products created after this timestamp.
+ after: A cursor; returns products after this position.
- created_before: Only return products created before this timestamp.
+ before: A cursor; returns products before this position.
- direction: The direction of the sort.
+ direction: The sort direction for results. Defaults to descending.
- first: Returns the first _n_ elements from the list.
+ first: The number of products to return (default and max 100).
- last: Returns the last _n_ elements from the list.
+ last: The number of products to return from the end of the range.
- order: The ways a relation of AccessPasses can be ordered
-
- product_types: Filter to only products matching these type classifications.
+ order: The field to sort results by. Defaults to created_at.
visibilities: Filter to only products matching these visibility states.
@@ -863,15 +634,13 @@ def list(
query=maybe_transform(
{
"company_id": company_id,
+ "access_pass_types": access_pass_types,
"after": after,
"before": before,
- "created_after": created_after,
- "created_before": created_before,
"direction": direction,
"first": first,
"last": last,
"order": order,
- "product_types": product_types,
"visibilities": visibilities,
},
product_list_params.ProductListParams,
@@ -891,12 +660,10 @@ async def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ProductDeleteResponse:
- """
- Permanently delete a product and remove it from the company's catalog.
-
- Required permissions:
+ """Deletes a product.
- - `access_pass:delete`
+ Only products with no memberships, entries, reviews, or
+ invoices can be deleted.
Args:
extra_headers: Send extra headers
diff --git a/src/whop_sdk/resources/referrals/__init__.py b/src/whop_sdk/resources/referrals/__init__.py
new file mode 100644
index 00000000..9d40a31a
--- /dev/null
+++ b/src/whop_sdk/resources/referrals/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .referrals import (
+ ReferralsResource,
+ AsyncReferralsResource,
+ ReferralsResourceWithRawResponse,
+ AsyncReferralsResourceWithRawResponse,
+ ReferralsResourceWithStreamingResponse,
+ AsyncReferralsResourceWithStreamingResponse,
+)
+from .businesses import (
+ BusinessesResource,
+ AsyncBusinessesResource,
+ BusinessesResourceWithRawResponse,
+ AsyncBusinessesResourceWithRawResponse,
+ BusinessesResourceWithStreamingResponse,
+ AsyncBusinessesResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "BusinessesResource",
+ "AsyncBusinessesResource",
+ "BusinessesResourceWithRawResponse",
+ "AsyncBusinessesResourceWithRawResponse",
+ "BusinessesResourceWithStreamingResponse",
+ "AsyncBusinessesResourceWithStreamingResponse",
+ "ReferralsResource",
+ "AsyncReferralsResource",
+ "ReferralsResourceWithRawResponse",
+ "AsyncReferralsResourceWithRawResponse",
+ "ReferralsResourceWithStreamingResponse",
+ "AsyncReferralsResourceWithStreamingResponse",
+]
diff --git a/src/whop_sdk/resources/referrals/businesses/__init__.py b/src/whop_sdk/resources/referrals/businesses/__init__.py
new file mode 100644
index 00000000..bd5fa65b
--- /dev/null
+++ b/src/whop_sdk/resources/referrals/businesses/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .earnings import (
+ EarningsResource,
+ AsyncEarningsResource,
+ EarningsResourceWithRawResponse,
+ AsyncEarningsResourceWithRawResponse,
+ EarningsResourceWithStreamingResponse,
+ AsyncEarningsResourceWithStreamingResponse,
+)
+from .businesses import (
+ BusinessesResource,
+ AsyncBusinessesResource,
+ BusinessesResourceWithRawResponse,
+ AsyncBusinessesResourceWithRawResponse,
+ BusinessesResourceWithStreamingResponse,
+ AsyncBusinessesResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "EarningsResource",
+ "AsyncEarningsResource",
+ "EarningsResourceWithRawResponse",
+ "AsyncEarningsResourceWithRawResponse",
+ "EarningsResourceWithStreamingResponse",
+ "AsyncEarningsResourceWithStreamingResponse",
+ "BusinessesResource",
+ "AsyncBusinessesResource",
+ "BusinessesResourceWithRawResponse",
+ "AsyncBusinessesResourceWithRawResponse",
+ "BusinessesResourceWithStreamingResponse",
+ "AsyncBusinessesResourceWithStreamingResponse",
+]
diff --git a/src/whop_sdk/resources/referrals/businesses/businesses.py b/src/whop_sdk/resources/referrals/businesses/businesses.py
new file mode 100644
index 00000000..fbe717b0
--- /dev/null
+++ b/src/whop_sdk/resources/referrals/businesses/businesses.py
@@ -0,0 +1,486 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from .earnings import (
+ EarningsResource,
+ AsyncEarningsResource,
+ EarningsResourceWithRawResponse,
+ AsyncEarningsResourceWithRawResponse,
+ EarningsResourceWithStreamingResponse,
+ AsyncEarningsResourceWithStreamingResponse,
+)
+from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ...._utils import path_template, 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.referrals import business_list_params, business_list_earnings_params
+from ....types.referrals.business_list_response import BusinessListResponse
+from ....types.referrals.business_retrieve_response import BusinessRetrieveResponse
+from ....types.referrals.business_list_earnings_response import BusinessListEarningsResponse
+
+__all__ = ["BusinessesResource", "AsyncBusinessesResource"]
+
+
+class BusinessesResource(SyncAPIResource):
+ @cached_property
+ def earnings(self) -> EarningsResource:
+ return EarningsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> BusinessesResourceWithRawResponse:
+ """
+ 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 BusinessesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> BusinessesResourceWithStreamingResponse:
+ """
+ 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 BusinessesResourceWithStreamingResponse(self)
+
+ 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,
+ ) -> BusinessRetrieveResponse:
+ """
+ Retrieves a single referred business and its referral terms.
+
+ 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(
+ path_template("/referrals/businesses/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BusinessRetrieveResponse,
+ )
+
+ def list(
+ self,
+ *,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ has_earnings: bool | Omit = omit,
+ last: int | Omit = omit,
+ status: Literal["active", "removed"] | 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[BusinessListResponse]:
+ """
+ Lists the businesses the authenticated user referred onto Whop, most recent
+ first.
+
+ Args:
+ after: Cursor to fetch the page after (from page_info.end_cursor).
+
+ before: Cursor to fetch the page before (from page_info.start_cursor).
+
+ first: Number of business referrals to return from the start of the window.
+
+ has_earnings: When true, only businesses that have paid out at least one earning to the
+ caller.
+
+ last: Number of business referrals to return from the end of the window.
+
+ status: Filter by referral status.
+
+ 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(
+ "/referrals/businesses",
+ page=SyncCursorPage[BusinessListResponse],
+ 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,
+ "has_earnings": has_earnings,
+ "last": last,
+ "status": status,
+ },
+ business_list_params.BusinessListParams,
+ ),
+ ),
+ model=BusinessListResponse,
+ )
+
+ def list_earnings(
+ self,
+ *,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ include: Literal["receipt_fees"] | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ sort: Literal["created_at", "amount", "payout_at"] | Omit = omit,
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"] | 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[BusinessListEarningsResponse]:
+ """
+ Lists every business referral earning the authenticated user has, most recent
+ first.
+
+ Args:
+ include: Comma-separated extras to embed. Supported: receipt_fees (adds amount_after_fees
+ and the receipt_fees breakdown).
+
+ order: Sort direction.
+
+ sort: Field to sort earnings by.
+
+ status: Filter by earning status.
+
+ 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(
+ "/referrals/businesses/earnings",
+ page=SyncCursorPage[BusinessListEarningsResponse],
+ 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,
+ "include": include,
+ "last": last,
+ "order": order,
+ "sort": sort,
+ "status": status,
+ },
+ business_list_earnings_params.BusinessListEarningsParams,
+ ),
+ ),
+ model=BusinessListEarningsResponse,
+ )
+
+
+class AsyncBusinessesResource(AsyncAPIResource):
+ @cached_property
+ def earnings(self) -> AsyncEarningsResource:
+ return AsyncEarningsResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncBusinessesResourceWithRawResponse:
+ """
+ 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 AsyncBusinessesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncBusinessesResourceWithStreamingResponse:
+ """
+ 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 AsyncBusinessesResourceWithStreamingResponse(self)
+
+ 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,
+ ) -> BusinessRetrieveResponse:
+ """
+ Retrieves a single referred business and its referral terms.
+
+ 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(
+ path_template("/referrals/businesses/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BusinessRetrieveResponse,
+ )
+
+ def list(
+ self,
+ *,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ has_earnings: bool | Omit = omit,
+ last: int | Omit = omit,
+ status: Literal["active", "removed"] | 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[BusinessListResponse, AsyncCursorPage[BusinessListResponse]]:
+ """
+ Lists the businesses the authenticated user referred onto Whop, most recent
+ first.
+
+ Args:
+ after: Cursor to fetch the page after (from page_info.end_cursor).
+
+ before: Cursor to fetch the page before (from page_info.start_cursor).
+
+ first: Number of business referrals to return from the start of the window.
+
+ has_earnings: When true, only businesses that have paid out at least one earning to the
+ caller.
+
+ last: Number of business referrals to return from the end of the window.
+
+ status: Filter by referral status.
+
+ 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(
+ "/referrals/businesses",
+ page=AsyncCursorPage[BusinessListResponse],
+ 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,
+ "has_earnings": has_earnings,
+ "last": last,
+ "status": status,
+ },
+ business_list_params.BusinessListParams,
+ ),
+ ),
+ model=BusinessListResponse,
+ )
+
+ def list_earnings(
+ self,
+ *,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ include: Literal["receipt_fees"] | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ sort: Literal["created_at", "amount", "payout_at"] | Omit = omit,
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"] | 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[BusinessListEarningsResponse, AsyncCursorPage[BusinessListEarningsResponse]]:
+ """
+ Lists every business referral earning the authenticated user has, most recent
+ first.
+
+ Args:
+ include: Comma-separated extras to embed. Supported: receipt_fees (adds amount_after_fees
+ and the receipt_fees breakdown).
+
+ order: Sort direction.
+
+ sort: Field to sort earnings by.
+
+ status: Filter by earning status.
+
+ 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(
+ "/referrals/businesses/earnings",
+ page=AsyncCursorPage[BusinessListEarningsResponse],
+ 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,
+ "include": include,
+ "last": last,
+ "order": order,
+ "sort": sort,
+ "status": status,
+ },
+ business_list_earnings_params.BusinessListEarningsParams,
+ ),
+ ),
+ model=BusinessListEarningsResponse,
+ )
+
+
+class BusinessesResourceWithRawResponse:
+ def __init__(self, businesses: BusinessesResource) -> None:
+ self._businesses = businesses
+
+ self.retrieve = to_raw_response_wrapper(
+ businesses.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ businesses.list,
+ )
+ self.list_earnings = to_raw_response_wrapper(
+ businesses.list_earnings,
+ )
+
+ @cached_property
+ def earnings(self) -> EarningsResourceWithRawResponse:
+ return EarningsResourceWithRawResponse(self._businesses.earnings)
+
+
+class AsyncBusinessesResourceWithRawResponse:
+ def __init__(self, businesses: AsyncBusinessesResource) -> None:
+ self._businesses = businesses
+
+ self.retrieve = async_to_raw_response_wrapper(
+ businesses.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ businesses.list,
+ )
+ self.list_earnings = async_to_raw_response_wrapper(
+ businesses.list_earnings,
+ )
+
+ @cached_property
+ def earnings(self) -> AsyncEarningsResourceWithRawResponse:
+ return AsyncEarningsResourceWithRawResponse(self._businesses.earnings)
+
+
+class BusinessesResourceWithStreamingResponse:
+ def __init__(self, businesses: BusinessesResource) -> None:
+ self._businesses = businesses
+
+ self.retrieve = to_streamed_response_wrapper(
+ businesses.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ businesses.list,
+ )
+ self.list_earnings = to_streamed_response_wrapper(
+ businesses.list_earnings,
+ )
+
+ @cached_property
+ def earnings(self) -> EarningsResourceWithStreamingResponse:
+ return EarningsResourceWithStreamingResponse(self._businesses.earnings)
+
+
+class AsyncBusinessesResourceWithStreamingResponse:
+ def __init__(self, businesses: AsyncBusinessesResource) -> None:
+ self._businesses = businesses
+
+ self.retrieve = async_to_streamed_response_wrapper(
+ businesses.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ businesses.list,
+ )
+ self.list_earnings = async_to_streamed_response_wrapper(
+ businesses.list_earnings,
+ )
+
+ @cached_property
+ def earnings(self) -> AsyncEarningsResourceWithStreamingResponse:
+ return AsyncEarningsResourceWithStreamingResponse(self._businesses.earnings)
diff --git a/src/whop_sdk/resources/referrals/businesses/earnings.py b/src/whop_sdk/resources/referrals/businesses/earnings.py
new file mode 100644
index 00000000..61c264bb
--- /dev/null
+++ b/src/whop_sdk/resources/referrals/businesses/earnings.py
@@ -0,0 +1,238 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal
+
+import httpx
+
+from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ...._utils import path_template, 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.referrals.businesses import earning_list_params
+from ....types.referrals.businesses.earning_list_response import EarningListResponse
+
+__all__ = ["EarningsResource", "AsyncEarningsResource"]
+
+
+class EarningsResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> EarningsResourceWithRawResponse:
+ """
+ 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 EarningsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> EarningsResourceWithStreamingResponse:
+ """
+ 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 EarningsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ id: str,
+ *,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ include: Literal["receipt_fees"] | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ sort: Literal["created_at", "amount", "payout_at"] | Omit = omit,
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"] | 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[EarningListResponse]:
+ """
+ Lists the earnings Whop pays out for one referred business's activity, most
+ recent first.
+
+ Args:
+ include: Comma-separated extras to embed. Supported: receipt_fees (adds amount_after_fees
+ and the receipt_fees breakdown).
+
+ order: Sort direction.
+
+ sort: Field to sort earnings by.
+
+ status: Filter by earning status.
+
+ 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(
+ path_template("/referrals/businesses/{id}/earnings", id=id),
+ page=SyncCursorPage[EarningListResponse],
+ 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,
+ "include": include,
+ "last": last,
+ "order": order,
+ "sort": sort,
+ "status": status,
+ },
+ earning_list_params.EarningListParams,
+ ),
+ ),
+ model=EarningListResponse,
+ )
+
+
+class AsyncEarningsResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncEarningsResourceWithRawResponse:
+ """
+ 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 AsyncEarningsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncEarningsResourceWithStreamingResponse:
+ """
+ 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 AsyncEarningsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ id: str,
+ *,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ include: Literal["receipt_fees"] | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["asc", "desc"] | Omit = omit,
+ sort: Literal["created_at", "amount", "payout_at"] | Omit = omit,
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"] | 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[EarningListResponse, AsyncCursorPage[EarningListResponse]]:
+ """
+ Lists the earnings Whop pays out for one referred business's activity, most
+ recent first.
+
+ Args:
+ include: Comma-separated extras to embed. Supported: receipt_fees (adds amount_after_fees
+ and the receipt_fees breakdown).
+
+ order: Sort direction.
+
+ sort: Field to sort earnings by.
+
+ status: Filter by earning status.
+
+ 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(
+ path_template("/referrals/businesses/{id}/earnings", id=id),
+ page=AsyncCursorPage[EarningListResponse],
+ 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,
+ "include": include,
+ "last": last,
+ "order": order,
+ "sort": sort,
+ "status": status,
+ },
+ earning_list_params.EarningListParams,
+ ),
+ ),
+ model=EarningListResponse,
+ )
+
+
+class EarningsResourceWithRawResponse:
+ def __init__(self, earnings: EarningsResource) -> None:
+ self._earnings = earnings
+
+ self.list = to_raw_response_wrapper(
+ earnings.list,
+ )
+
+
+class AsyncEarningsResourceWithRawResponse:
+ def __init__(self, earnings: AsyncEarningsResource) -> None:
+ self._earnings = earnings
+
+ self.list = async_to_raw_response_wrapper(
+ earnings.list,
+ )
+
+
+class EarningsResourceWithStreamingResponse:
+ def __init__(self, earnings: EarningsResource) -> None:
+ self._earnings = earnings
+
+ self.list = to_streamed_response_wrapper(
+ earnings.list,
+ )
+
+
+class AsyncEarningsResourceWithStreamingResponse:
+ def __init__(self, earnings: AsyncEarningsResource) -> None:
+ self._earnings = earnings
+
+ self.list = async_to_streamed_response_wrapper(
+ earnings.list,
+ )
diff --git a/src/whop_sdk/resources/referrals/referrals.py b/src/whop_sdk/resources/referrals/referrals.py
new file mode 100644
index 00000000..949735f3
--- /dev/null
+++ b/src/whop_sdk/resources/referrals/referrals.py
@@ -0,0 +1,102 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from .businesses.businesses import (
+ BusinessesResource,
+ AsyncBusinessesResource,
+ BusinessesResourceWithRawResponse,
+ AsyncBusinessesResourceWithRawResponse,
+ BusinessesResourceWithStreamingResponse,
+ AsyncBusinessesResourceWithStreamingResponse,
+)
+
+__all__ = ["ReferralsResource", "AsyncReferralsResource"]
+
+
+class ReferralsResource(SyncAPIResource):
+ @cached_property
+ def businesses(self) -> BusinessesResource:
+ return BusinessesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> ReferralsResourceWithRawResponse:
+ """
+ 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 ReferralsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ReferralsResourceWithStreamingResponse:
+ """
+ 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 ReferralsResourceWithStreamingResponse(self)
+
+
+class AsyncReferralsResource(AsyncAPIResource):
+ @cached_property
+ def businesses(self) -> AsyncBusinessesResource:
+ return AsyncBusinessesResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncReferralsResourceWithRawResponse:
+ """
+ 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 AsyncReferralsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncReferralsResourceWithStreamingResponse:
+ """
+ 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 AsyncReferralsResourceWithStreamingResponse(self)
+
+
+class ReferralsResourceWithRawResponse:
+ def __init__(self, referrals: ReferralsResource) -> None:
+ self._referrals = referrals
+
+ @cached_property
+ def businesses(self) -> BusinessesResourceWithRawResponse:
+ return BusinessesResourceWithRawResponse(self._referrals.businesses)
+
+
+class AsyncReferralsResourceWithRawResponse:
+ def __init__(self, referrals: AsyncReferralsResource) -> None:
+ self._referrals = referrals
+
+ @cached_property
+ def businesses(self) -> AsyncBusinessesResourceWithRawResponse:
+ return AsyncBusinessesResourceWithRawResponse(self._referrals.businesses)
+
+
+class ReferralsResourceWithStreamingResponse:
+ def __init__(self, referrals: ReferralsResource) -> None:
+ self._referrals = referrals
+
+ @cached_property
+ def businesses(self) -> BusinessesResourceWithStreamingResponse:
+ return BusinessesResourceWithStreamingResponse(self._referrals.businesses)
+
+
+class AsyncReferralsResourceWithStreamingResponse:
+ def __init__(self, referrals: AsyncReferralsResource) -> None:
+ self._referrals = referrals
+
+ @cached_property
+ def businesses(self) -> AsyncBusinessesResourceWithStreamingResponse:
+ return AsyncBusinessesResourceWithStreamingResponse(self._referrals.businesses)
diff --git a/src/whop_sdk/resources/swaps.py b/src/whop_sdk/resources/swaps.py
index a79eabbe..858cdb6c 100644
--- a/src/whop_sdk/resources/swaps.py
+++ b/src/whop_sdk/resources/swaps.py
@@ -6,9 +6,9 @@
import httpx
-from ..types import swap_create_quote_params
+from ..types import swap_list_params, swap_create_params, swap_create_quote_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -18,6 +18,9 @@
async_to_streamed_response_wrapper,
)
from .._base_client import make_request_options
+from ..types.swap_list_response import SwapListResponse
+from ..types.swap_create_response import SwapCreateResponse
+from ..types.swap_retrieve_response import SwapRetrieveResponse
from ..types.swap_create_quote_response import SwapCreateQuoteResponse
__all__ = ["SwapsResource", "AsyncSwapsResource"]
@@ -43,6 +46,136 @@ def with_streaming_response(self) -> SwapsResourceWithStreamingResponse:
"""
return SwapsResourceWithStreamingResponse(self)
+ def create(
+ self,
+ *,
+ account_id: str,
+ amount: str,
+ from_token: str,
+ to_token: str,
+ from_chain: Union[str, int, None] | Omit = omit,
+ slippage_bps: Optional[int] | Omit = omit,
+ to_chain: Union[str, int, None] | 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,
+ ) -> SwapCreateResponse:
+ """Executes a swap from the account's wallet.
+
+ Runs asynchronously — poll GET
+ /swaps/{id} for status.
+
+ Args:
+ account_id: Business or user account ID (biz*\\** / user*\\**).
+
+ amount: Input token amount.
+
+ from_token: Source token, by contract address or ticker symbol (e.g. "USDT").
+
+ to_token: Destination token, by contract address or ticker symbol (e.g. "XAUT").
+
+ 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(
+ "/swaps",
+ body=maybe_transform(
+ {
+ "account_id": account_id,
+ "amount": amount,
+ "from_token": from_token,
+ "to_token": to_token,
+ "from_chain": from_chain,
+ "slippage_bps": slippage_bps,
+ "to_chain": to_chain,
+ },
+ swap_create_params.SwapCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SwapCreateResponse,
+ )
+
+ 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,
+ ) -> SwapRetrieveResponse:
+ """
+ Returns the status of a specific swap, by the id returned from POST /swaps.
+
+ 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(
+ path_template("/swaps/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SwapRetrieveResponse,
+ )
+
+ def list(
+ self,
+ *,
+ account_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,
+ ) -> SwapListResponse:
+ """
+ Lists the account's swaps — currently its in-flight or most recent swap, so zero
+ or one rows.
+
+ Args:
+ account_id: Business or user account ID (biz*\\** / user*\\**).
+
+ 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(
+ "/swaps",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"account_id": account_id}, swap_list_params.SwapListParams),
+ ),
+ cast_to=SwapListResponse,
+ )
+
def create_quote(
self,
*,
@@ -69,9 +202,9 @@ def create_quote(
Args:
amount: Input token amount.
- from_token: Source token contract address.
+ from_token: Source token, by contract address or ticker symbol (e.g. "USDT").
- to_token: Destination token contract address.
+ to_token: Destination token, by contract address or ticker symbol (e.g. "XAUT").
extra_headers: Send extra headers
@@ -124,6 +257,136 @@ def with_streaming_response(self) -> AsyncSwapsResourceWithStreamingResponse:
"""
return AsyncSwapsResourceWithStreamingResponse(self)
+ async def create(
+ self,
+ *,
+ account_id: str,
+ amount: str,
+ from_token: str,
+ to_token: str,
+ from_chain: Union[str, int, None] | Omit = omit,
+ slippage_bps: Optional[int] | Omit = omit,
+ to_chain: Union[str, int, None] | 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,
+ ) -> SwapCreateResponse:
+ """Executes a swap from the account's wallet.
+
+ Runs asynchronously — poll GET
+ /swaps/{id} for status.
+
+ Args:
+ account_id: Business or user account ID (biz*\\** / user*\\**).
+
+ amount: Input token amount.
+
+ from_token: Source token, by contract address or ticker symbol (e.g. "USDT").
+
+ to_token: Destination token, by contract address or ticker symbol (e.g. "XAUT").
+
+ 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(
+ "/swaps",
+ body=await async_maybe_transform(
+ {
+ "account_id": account_id,
+ "amount": amount,
+ "from_token": from_token,
+ "to_token": to_token,
+ "from_chain": from_chain,
+ "slippage_bps": slippage_bps,
+ "to_chain": to_chain,
+ },
+ swap_create_params.SwapCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SwapCreateResponse,
+ )
+
+ 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,
+ ) -> SwapRetrieveResponse:
+ """
+ Returns the status of a specific swap, by the id returned from POST /swaps.
+
+ 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(
+ path_template("/swaps/{id}", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SwapRetrieveResponse,
+ )
+
+ async def list(
+ self,
+ *,
+ account_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,
+ ) -> SwapListResponse:
+ """
+ Lists the account's swaps — currently its in-flight or most recent swap, so zero
+ or one rows.
+
+ Args:
+ account_id: Business or user account ID (biz*\\** / user*\\**).
+
+ 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._get(
+ "/swaps",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform({"account_id": account_id}, swap_list_params.SwapListParams),
+ ),
+ cast_to=SwapListResponse,
+ )
+
async def create_quote(
self,
*,
@@ -150,9 +413,9 @@ async def create_quote(
Args:
amount: Input token amount.
- from_token: Source token contract address.
+ from_token: Source token, by contract address or ticker symbol (e.g. "USDT").
- to_token: Destination token contract address.
+ to_token: Destination token, by contract address or ticker symbol (e.g. "XAUT").
extra_headers: Send extra headers
@@ -189,6 +452,15 @@ class SwapsResourceWithRawResponse:
def __init__(self, swaps: SwapsResource) -> None:
self._swaps = swaps
+ self.create = to_raw_response_wrapper(
+ swaps.create,
+ )
+ self.retrieve = to_raw_response_wrapper(
+ swaps.retrieve,
+ )
+ self.list = to_raw_response_wrapper(
+ swaps.list,
+ )
self.create_quote = to_raw_response_wrapper(
swaps.create_quote,
)
@@ -198,6 +470,15 @@ class AsyncSwapsResourceWithRawResponse:
def __init__(self, swaps: AsyncSwapsResource) -> None:
self._swaps = swaps
+ self.create = async_to_raw_response_wrapper(
+ swaps.create,
+ )
+ self.retrieve = async_to_raw_response_wrapper(
+ swaps.retrieve,
+ )
+ self.list = async_to_raw_response_wrapper(
+ swaps.list,
+ )
self.create_quote = async_to_raw_response_wrapper(
swaps.create_quote,
)
@@ -207,6 +488,15 @@ class SwapsResourceWithStreamingResponse:
def __init__(self, swaps: SwapsResource) -> None:
self._swaps = swaps
+ self.create = to_streamed_response_wrapper(
+ swaps.create,
+ )
+ self.retrieve = to_streamed_response_wrapper(
+ swaps.retrieve,
+ )
+ self.list = to_streamed_response_wrapper(
+ swaps.list,
+ )
self.create_quote = to_streamed_response_wrapper(
swaps.create_quote,
)
@@ -216,6 +506,15 @@ class AsyncSwapsResourceWithStreamingResponse:
def __init__(self, swaps: AsyncSwapsResource) -> None:
self._swaps = swaps
+ self.create = async_to_streamed_response_wrapper(
+ swaps.create,
+ )
+ self.retrieve = async_to_streamed_response_wrapper(
+ swaps.retrieve,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ swaps.list,
+ )
self.create_quote = async_to_streamed_response_wrapper(
swaps.create_quote,
)
diff --git a/src/whop_sdk/resources/transfers.py b/src/whop_sdk/resources/transfers.py
index 806984ba..4472c431 100644
--- a/src/whop_sdk/resources/transfers.py
+++ b/src/whop_sdk/resources/transfers.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Dict, Union, Optional
+from typing import Any, Dict, Union, Optional, cast
from datetime import datetime
from typing_extensions import Literal
@@ -21,17 +21,14 @@
)
from ..pagination import SyncCursorPage, AsyncCursorPage
from .._base_client import AsyncPaginator, make_request_options
-from ..types.shared.currency import Currency
-from ..types.shared.transfer import Transfer
-from ..types.shared.direction import Direction
from ..types.transfer_list_response import TransferListResponse
+from ..types.transfer_create_response import TransferCreateResponse
+from ..types.transfer_retrieve_response import TransferRetrieveResponse
__all__ = ["TransfersResource", "AsyncTransfersResource"]
class TransfersResource(SyncAPIResource):
- """Transfers"""
-
@cached_property
def with_raw_response(self) -> TransfersResourceWithRawResponse:
"""
@@ -55,48 +52,54 @@ def create(
self,
*,
amount: float,
- currency: Currency,
- destination_id: str,
origin_id: str,
+ currency: str | Omit = omit,
+ destination_id: str | Omit = omit,
+ expires_at: Union[str, datetime, None] | Omit = omit,
idempotence_key: Optional[str] | Omit = omit,
metadata: Optional[Dict[str, object]] | Omit = omit,
notes: Optional[str] | Omit = omit,
+ redeemable_count: int | Omit = omit,
+ type: Literal["ledger", "wallet_send", "claim_link"] | 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,
- ) -> Transfer:
- """
- Transfer funds between two ledger accounts, such as from a company balance to a
- user balance.
-
- Required permissions:
+ ) -> TransferCreateResponse:
+ """Moves funds out of an account.
- - `payout:transfer_funds`
+ `type` selects the kind of movement (default
+ `ledger`): `ledger` transfers credit between two ledger accounts and returns a
+ Transfer; `wallet_send` sends USDT from the origin account's Ethereum wallet to
+ a recipient; `claim_link` funds a shareable claim link anyone with the URL can
+ redeem.
Args:
- amount: The amount to transfer in the specified currency. For example, 25.00 for $25.00
- USD.
+ amount: The amount to move, in the transfer currency. For example 25.00.
+
+ origin_id: The account sending the funds. A user ID (user_xxx), account ID (biz_xxx), or
+ ledger account ID (ldgr_xxx).
+
+ currency: The currency, such as usd. Required for ledger transfers.
- currency: The currency of the transfer amount, such as 'usd'.
+ destination_id: The recipient. Required for ledger and wallet*send (a user*/biz*/ldgr* ID, or —
+ for sends — an email). Omit for claim_link.
- destination_id: The identifier of the account receiving the funds. Accepts a user ID
- ('user_xxx'), company ID ('biz_xxx'), ledger account ID ('ldgr_xxx'), or an
- email address — emails without an existing Whop user trigger a placeholder-user
- signup.
+ expires_at: claim_link only. Link expiry as an ISO 8601 timestamp. Defaults to 24 hours from
+ creation.
- origin_id: The identifier of the account sending the funds. Accepts a user ID ('user_xxx'),
- company ID ('biz_xxx'), or ledger account ID ('ldgr_xxx').
+ idempotence_key: Ledger transfers only. A unique key to prevent duplicate transfers.
- idempotence_key: A unique key to prevent duplicate transfers. Use a UUID or similar unique
- string.
+ metadata: Ledger transfers only. Custom key-value pairs attached to the transfer. Max 50
+ keys, 100 chars per key, 500 chars per string value.
- metadata: A JSON object of custom metadata to attach to the transfer for tracking
- purposes.
+ notes: Ledger transfers only. A short note describing the transfer.
- notes: A short note describing the transfer, up to 50 characters.
+ redeemable_count: claim_link only. How many different users can claim the link. Defaults to 1.
+
+ type: The kind of money movement. Defaults to ledger.
extra_headers: Send extra headers
@@ -106,24 +109,32 @@ def create(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return self._post(
- "/transfers",
- body=maybe_transform(
- {
- "amount": amount,
- "currency": currency,
- "destination_id": destination_id,
- "origin_id": origin_id,
- "idempotence_key": idempotence_key,
- "metadata": metadata,
- "notes": notes,
- },
- transfer_create_params.TransferCreateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ return cast(
+ TransferCreateResponse,
+ self._post(
+ "/transfers",
+ body=maybe_transform(
+ {
+ "amount": amount,
+ "origin_id": origin_id,
+ "currency": currency,
+ "destination_id": destination_id,
+ "expires_at": expires_at,
+ "idempotence_key": idempotence_key,
+ "metadata": metadata,
+ "notes": notes,
+ "redeemable_count": redeemable_count,
+ "type": type,
+ },
+ transfer_create_params.TransferCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(
+ Any, TransferCreateResponse
+ ), # Union types cannot be passed in as arguments in the type system
),
- cast_to=Transfer,
)
def retrieve(
@@ -136,13 +147,9 @@ def retrieve(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Transfer:
+ ) -> TransferRetrieveResponse:
"""
- Retrieves the details of an existing transfer.
-
- Required permissions:
-
- - `payout:transfer:read`
+ Retrieves a ledger transfer by ID.
Args:
extra_headers: Send extra headers
@@ -160,22 +167,22 @@ def retrieve(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=Transfer,
+ cast_to=TransferRetrieveResponse,
)
def list(
self,
*,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- destination_id: Optional[str] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- order: Optional[Literal["amount", "created_at"]] | Omit = omit,
- origin_id: Optional[str] | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ created_after: str | Omit = omit,
+ created_before: str | Omit = omit,
+ destination_id: str | Omit = omit,
+ direction: Literal["asc", "desc"] | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["created_at", "amount"] | Omit = omit,
+ origin_id: 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.
extra_headers: Headers | None = None,
@@ -183,36 +190,31 @@ def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> SyncCursorPage[TransferListResponse]:
- """
- Returns a paginated list of fund transfers, filtered by origin or destination
- account, with optional sorting and date filtering.
-
- Required permissions:
+ """Lists ledger transfers for an account.
- - `payout:transfer:read`
+ You must specify an origin_id or a
+ destination_id.
Args:
- after: Returns the elements in the list that come after the specified cursor.
+ after: Cursor to fetch the page after (from page_info.end_cursor).
- before: Returns the elements in the list that come before the specified cursor.
+ before: Cursor to fetch the page before (from page_info.start_cursor).
- created_after: Only return transfers created after this timestamp.
+ created_after: Only transfers created strictly after this ISO 8601 timestamp.
- created_before: Only return transfers created before this timestamp.
+ created_before: Only transfers created strictly before this ISO 8601 timestamp.
- destination_id: Filter to transfers received by this account. Accepts a user, company, or ledger
- account ID.
+ destination_id: Filter to transfers received by this account.
- direction: The direction of the sort.
+ direction: Sort direction. Defaults to desc.
- first: Returns the first _n_ elements from the list.
+ first: Number of transfers to return from the start of the window.
- last: Returns the last _n_ elements from the list.
+ last: Number of transfers to return from the end of the window.
- order: Which columns can be used to sort.
+ order: Sort column. Defaults to created_at.
- origin_id: Filter to transfers sent from this account. Accepts a user, company, or ledger
- account ID.
+ origin_id: Filter to transfers sent from this account.
extra_headers: Send extra headers
@@ -251,8 +253,6 @@ def list(
class AsyncTransfersResource(AsyncAPIResource):
- """Transfers"""
-
@cached_property
def with_raw_response(self) -> AsyncTransfersResourceWithRawResponse:
"""
@@ -276,48 +276,54 @@ async def create(
self,
*,
amount: float,
- currency: Currency,
- destination_id: str,
origin_id: str,
+ currency: str | Omit = omit,
+ destination_id: str | Omit = omit,
+ expires_at: Union[str, datetime, None] | Omit = omit,
idempotence_key: Optional[str] | Omit = omit,
metadata: Optional[Dict[str, object]] | Omit = omit,
notes: Optional[str] | Omit = omit,
+ redeemable_count: int | Omit = omit,
+ type: Literal["ledger", "wallet_send", "claim_link"] | 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,
- ) -> Transfer:
- """
- Transfer funds between two ledger accounts, such as from a company balance to a
- user balance.
-
- Required permissions:
+ ) -> TransferCreateResponse:
+ """Moves funds out of an account.
- - `payout:transfer_funds`
+ `type` selects the kind of movement (default
+ `ledger`): `ledger` transfers credit between two ledger accounts and returns a
+ Transfer; `wallet_send` sends USDT from the origin account's Ethereum wallet to
+ a recipient; `claim_link` funds a shareable claim link anyone with the URL can
+ redeem.
Args:
- amount: The amount to transfer in the specified currency. For example, 25.00 for $25.00
- USD.
+ amount: The amount to move, in the transfer currency. For example 25.00.
+
+ origin_id: The account sending the funds. A user ID (user_xxx), account ID (biz_xxx), or
+ ledger account ID (ldgr_xxx).
+
+ currency: The currency, such as usd. Required for ledger transfers.
- currency: The currency of the transfer amount, such as 'usd'.
+ destination_id: The recipient. Required for ledger and wallet*send (a user*/biz*/ldgr* ID, or —
+ for sends — an email). Omit for claim_link.
- destination_id: The identifier of the account receiving the funds. Accepts a user ID
- ('user_xxx'), company ID ('biz_xxx'), ledger account ID ('ldgr_xxx'), or an
- email address — emails without an existing Whop user trigger a placeholder-user
- signup.
+ expires_at: claim_link only. Link expiry as an ISO 8601 timestamp. Defaults to 24 hours from
+ creation.
- origin_id: The identifier of the account sending the funds. Accepts a user ID ('user_xxx'),
- company ID ('biz_xxx'), or ledger account ID ('ldgr_xxx').
+ idempotence_key: Ledger transfers only. A unique key to prevent duplicate transfers.
- idempotence_key: A unique key to prevent duplicate transfers. Use a UUID or similar unique
- string.
+ metadata: Ledger transfers only. Custom key-value pairs attached to the transfer. Max 50
+ keys, 100 chars per key, 500 chars per string value.
- metadata: A JSON object of custom metadata to attach to the transfer for tracking
- purposes.
+ notes: Ledger transfers only. A short note describing the transfer.
- notes: A short note describing the transfer, up to 50 characters.
+ redeemable_count: claim_link only. How many different users can claim the link. Defaults to 1.
+
+ type: The kind of money movement. Defaults to ledger.
extra_headers: Send extra headers
@@ -327,24 +333,32 @@ async def create(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return await self._post(
- "/transfers",
- body=await async_maybe_transform(
- {
- "amount": amount,
- "currency": currency,
- "destination_id": destination_id,
- "origin_id": origin_id,
- "idempotence_key": idempotence_key,
- "metadata": metadata,
- "notes": notes,
- },
- transfer_create_params.TransferCreateParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ return cast(
+ TransferCreateResponse,
+ await self._post(
+ "/transfers",
+ body=await async_maybe_transform(
+ {
+ "amount": amount,
+ "origin_id": origin_id,
+ "currency": currency,
+ "destination_id": destination_id,
+ "expires_at": expires_at,
+ "idempotence_key": idempotence_key,
+ "metadata": metadata,
+ "notes": notes,
+ "redeemable_count": redeemable_count,
+ "type": type,
+ },
+ transfer_create_params.TransferCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=cast(
+ Any, TransferCreateResponse
+ ), # Union types cannot be passed in as arguments in the type system
),
- cast_to=Transfer,
)
async def retrieve(
@@ -357,13 +371,9 @@ async def retrieve(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Transfer:
+ ) -> TransferRetrieveResponse:
"""
- Retrieves the details of an existing transfer.
-
- Required permissions:
-
- - `payout:transfer:read`
+ Retrieves a ledger transfer by ID.
Args:
extra_headers: Send extra headers
@@ -381,22 +391,22 @@ async def retrieve(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=Transfer,
+ cast_to=TransferRetrieveResponse,
)
def list(
self,
*,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- created_after: Union[str, datetime, None] | Omit = omit,
- created_before: Union[str, datetime, None] | Omit = omit,
- destination_id: Optional[str] | Omit = omit,
- direction: Optional[Direction] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- order: Optional[Literal["amount", "created_at"]] | Omit = omit,
- origin_id: Optional[str] | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ created_after: str | Omit = omit,
+ created_before: str | Omit = omit,
+ destination_id: str | Omit = omit,
+ direction: Literal["asc", "desc"] | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ order: Literal["created_at", "amount"] | Omit = omit,
+ origin_id: 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.
extra_headers: Headers | None = None,
@@ -404,36 +414,31 @@ def list(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> AsyncPaginator[TransferListResponse, AsyncCursorPage[TransferListResponse]]:
- """
- Returns a paginated list of fund transfers, filtered by origin or destination
- account, with optional sorting and date filtering.
-
- Required permissions:
+ """Lists ledger transfers for an account.
- - `payout:transfer:read`
+ You must specify an origin_id or a
+ destination_id.
Args:
- after: Returns the elements in the list that come after the specified cursor.
+ after: Cursor to fetch the page after (from page_info.end_cursor).
- before: Returns the elements in the list that come before the specified cursor.
+ before: Cursor to fetch the page before (from page_info.start_cursor).
- created_after: Only return transfers created after this timestamp.
+ created_after: Only transfers created strictly after this ISO 8601 timestamp.
- created_before: Only return transfers created before this timestamp.
+ created_before: Only transfers created strictly before this ISO 8601 timestamp.
- destination_id: Filter to transfers received by this account. Accepts a user, company, or ledger
- account ID.
+ destination_id: Filter to transfers received by this account.
- direction: The direction of the sort.
+ direction: Sort direction. Defaults to desc.
- first: Returns the first _n_ elements from the list.
+ first: Number of transfers to return from the start of the window.
- last: Returns the last _n_ elements from the list.
+ last: Number of transfers to return from the end of the window.
- order: Which columns can be used to sort.
+ order: Sort column. Defaults to created_at.
- origin_id: Filter to transfers sent from this account. Accepts a user, company, or ledger
- account ID.
+ origin_id: Filter to transfers sent from this account.
extra_headers: Send extra headers
diff --git a/src/whop_sdk/resources/users.py b/src/whop_sdk/resources/users.py
index e0ce27c0..0393836e 100644
--- a/src/whop_sdk/resources/users.py
+++ b/src/whop_sdk/resources/users.py
@@ -2,11 +2,9 @@
from __future__ import annotations
-from typing import Optional
-
import httpx
-from ..types import user_list_params, user_update_params, user_retrieve_params
+from ..types import user_list_params, user_update_params, user_retrieve_params, user_update_me_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -20,15 +18,12 @@
from ..pagination import SyncCursorPage, AsyncCursorPage
from ..types.user import User
from .._base_client import AsyncPaginator, make_request_options
-from ..types.user_list_response import UserListResponse
from ..types.user_check_access_response import UserCheckAccessResponse
__all__ = ["UsersResource", "AsyncUsersResource"]
class UsersResource(SyncAPIResource):
- """Users"""
-
@cached_property
def with_raw_response(self) -> UsersResourceWithRawResponse:
"""
@@ -52,7 +47,7 @@ def retrieve(
self,
id: str,
*,
- company_id: Optional[str] | Omit = omit,
+ account_id: 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.
extra_headers: Headers | None = None,
@@ -61,11 +56,11 @@ def retrieve(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> User:
"""
- Retrieves the details of an existing user.
+ Retrieves a user's public profile by user\\__ tag, username, or 'me'.
Args:
- company_id: When provided, returns the user's company-specific profile overrides (name,
- profile picture) instead of their global profile.
+ account_id: When set, returns the user's account-specific profile overrides for this
+ account.
extra_headers: Send extra headers
@@ -84,7 +79,7 @@ def retrieve(
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=maybe_transform({"company_id": company_id}, user_retrieve_params.UserRetrieveParams),
+ query=maybe_transform({"account_id": account_id}, user_retrieve_params.UserRetrieveParams),
),
cast_to=User,
)
@@ -93,11 +88,11 @@ def update(
self,
id: str,
*,
- bio: Optional[str] | Omit = omit,
- company_id: Optional[str] | Omit = omit,
- name: Optional[str] | Omit = omit,
- profile_picture: Optional[user_update_params.ProfilePicture] | Omit = omit,
- username: Optional[str] | Omit = omit,
+ account_id: str | Omit = omit,
+ bio: str | Omit = omit,
+ name: str | Omit = omit,
+ profile_picture: user_update_params.ProfilePicture | Omit = omit,
+ username: 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.
extra_headers: Headers | None = None,
@@ -105,26 +100,13 @@ def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> User:
- """
- Update a user's profile by their ID.
-
- Required permissions:
+ """Updates a user.
- - `user:profile:update`
+ A user token updates their own global profile; an API key
+ updates the user's account-specific profile override (account_id required).
Args:
- bio: A short biography displayed on the user's public profile.
-
- company_id: When provided, updates the user's profile overrides for this company instead of
- the global profile. Pass name and profile_picture to set overrides, or null to
- clear them.
-
- name: The user's display name shown on their public profile. Maximum 100 characters.
-
- profile_picture: The user's profile picture image attachment.
-
- username: The user's unique username. Alphanumeric characters and hyphens only. Maximum 42
- characters.
+ account_id: The account whose profile override to update. Required for API key callers.
extra_headers: Send extra headers
@@ -141,7 +123,6 @@ def update(
body=maybe_transform(
{
"bio": bio,
- "company_id": company_id,
"name": name,
"profile_picture": profile_picture,
"username": username,
@@ -149,7 +130,11 @@ def update(
user_update_params.UserUpdateParams,
),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"account_id": account_id}, user_update_params.UserUpdateParams),
),
cast_to=User,
)
@@ -157,32 +142,33 @@ def update(
def list(
self,
*,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- query: Optional[str] | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ query: 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.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> SyncCursorPage[UserListResponse]:
+ ) -> SyncCursorPage[User]:
"""
Search for users by name or username, ranked by social proximity to the
- authenticated user.
+ authenticated user. Returns the user's most recently followed users when no
+ query is given.
Args:
- after: Returns the elements in the list that come after the specified cursor.
+ after: A cursor; returns users after this position.
- before: Returns the elements in the list that come before the specified cursor.
+ before: A cursor; returns users before this position.
- first: Returns the first _n_ elements from the list.
+ first: The number of users to return (max 50).
- last: Returns the last _n_ elements from the list.
+ last: The number of users to return from the end of the range.
- query: Search term to filter by name or username.
+ query: A search term to filter users by name or username.
extra_headers: Send extra headers
@@ -194,7 +180,7 @@ def list(
"""
return self._get_api_list(
"/users",
- page=SyncCursorPage[UserListResponse],
+ page=SyncCursorPage[User],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -211,7 +197,7 @@ def list(
user_list_params.UserListParams,
),
),
- model=UserListResponse,
+ model=User,
)
def check_access(
@@ -227,8 +213,8 @@ def check_access(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> UserCheckAccessResponse:
"""
- Check whether a user has access to a specific resource, and return their access
- level.
+ Checks whether a user has access to an account, product, or experience the
+ caller can reach.
Args:
extra_headers: Send extra headers
@@ -251,10 +237,60 @@ def check_access(
cast_to=UserCheckAccessResponse,
)
+ def update_me(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ bio: str | Omit = omit,
+ name: str | Omit = omit,
+ profile_picture: user_update_me_params.ProfilePicture | Omit = omit,
+ username: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> User:
+ """
+ Updates the authenticated user's global profile, or their profile override for
+ an account when account_id is given. Not available to API keys.
-class AsyncUsersResource(AsyncAPIResource):
- """Users"""
+ Args:
+ account_id: When set, updates the authenticated user's profile override for this account
+ instead of their global profile.
+
+ 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._patch(
+ "/users/me",
+ body=maybe_transform(
+ {
+ "bio": bio,
+ "name": name,
+ "profile_picture": profile_picture,
+ "username": username,
+ },
+ user_update_me_params.UserUpdateMeParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"account_id": account_id}, user_update_me_params.UserUpdateMeParams),
+ ),
+ cast_to=User,
+ )
+
+
+class AsyncUsersResource(AsyncAPIResource):
@cached_property
def with_raw_response(self) -> AsyncUsersResourceWithRawResponse:
"""
@@ -278,7 +314,7 @@ async def retrieve(
self,
id: str,
*,
- company_id: Optional[str] | Omit = omit,
+ account_id: 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.
extra_headers: Headers | None = None,
@@ -287,11 +323,11 @@ async def retrieve(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> User:
"""
- Retrieves the details of an existing user.
+ Retrieves a user's public profile by user\\__ tag, username, or 'me'.
Args:
- company_id: When provided, returns the user's company-specific profile overrides (name,
- profile picture) instead of their global profile.
+ account_id: When set, returns the user's account-specific profile overrides for this
+ account.
extra_headers: Send extra headers
@@ -310,7 +346,7 @@ async def retrieve(
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=await async_maybe_transform({"company_id": company_id}, user_retrieve_params.UserRetrieveParams),
+ query=await async_maybe_transform({"account_id": account_id}, user_retrieve_params.UserRetrieveParams),
),
cast_to=User,
)
@@ -319,11 +355,11 @@ async def update(
self,
id: str,
*,
- bio: Optional[str] | Omit = omit,
- company_id: Optional[str] | Omit = omit,
- name: Optional[str] | Omit = omit,
- profile_picture: Optional[user_update_params.ProfilePicture] | Omit = omit,
- username: Optional[str] | Omit = omit,
+ account_id: str | Omit = omit,
+ bio: str | Omit = omit,
+ name: str | Omit = omit,
+ profile_picture: user_update_params.ProfilePicture | Omit = omit,
+ username: 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.
extra_headers: Headers | None = None,
@@ -331,26 +367,13 @@ async def update(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> User:
- """
- Update a user's profile by their ID.
+ """Updates a user.
- Required permissions:
-
- - `user:profile:update`
+ A user token updates their own global profile; an API key
+ updates the user's account-specific profile override (account_id required).
Args:
- bio: A short biography displayed on the user's public profile.
-
- company_id: When provided, updates the user's profile overrides for this company instead of
- the global profile. Pass name and profile_picture to set overrides, or null to
- clear them.
-
- name: The user's display name shown on their public profile. Maximum 100 characters.
-
- profile_picture: The user's profile picture image attachment.
-
- username: The user's unique username. Alphanumeric characters and hyphens only. Maximum 42
- characters.
+ account_id: The account whose profile override to update. Required for API key callers.
extra_headers: Send extra headers
@@ -367,7 +390,6 @@ async def update(
body=await async_maybe_transform(
{
"bio": bio,
- "company_id": company_id,
"name": name,
"profile_picture": profile_picture,
"username": username,
@@ -375,7 +397,11 @@ async def update(
user_update_params.UserUpdateParams,
),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform({"account_id": account_id}, user_update_params.UserUpdateParams),
),
cast_to=User,
)
@@ -383,32 +409,33 @@ async def update(
def list(
self,
*,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
- query: Optional[str] | Omit = omit,
+ after: str | Omit = omit,
+ before: str | Omit = omit,
+ first: int | Omit = omit,
+ last: int | Omit = omit,
+ query: 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.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncPaginator[UserListResponse, AsyncCursorPage[UserListResponse]]:
+ ) -> AsyncPaginator[User, AsyncCursorPage[User]]:
"""
Search for users by name or username, ranked by social proximity to the
- authenticated user.
+ authenticated user. Returns the user's most recently followed users when no
+ query is given.
Args:
- after: Returns the elements in the list that come after the specified cursor.
+ after: A cursor; returns users after this position.
- before: Returns the elements in the list that come before the specified cursor.
+ before: A cursor; returns users before this position.
- first: Returns the first _n_ elements from the list.
+ first: The number of users to return (max 50).
- last: Returns the last _n_ elements from the list.
+ last: The number of users to return from the end of the range.
- query: Search term to filter by name or username.
+ query: A search term to filter users by name or username.
extra_headers: Send extra headers
@@ -420,7 +447,7 @@ def list(
"""
return self._get_api_list(
"/users",
- page=AsyncCursorPage[UserListResponse],
+ page=AsyncCursorPage[User],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -437,7 +464,7 @@ def list(
user_list_params.UserListParams,
),
),
- model=UserListResponse,
+ model=User,
)
async def check_access(
@@ -453,8 +480,8 @@ async def check_access(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> UserCheckAccessResponse:
"""
- Check whether a user has access to a specific resource, and return their access
- level.
+ Checks whether a user has access to an account, product, or experience the
+ caller can reach.
Args:
extra_headers: Send extra headers
@@ -477,6 +504,58 @@ async def check_access(
cast_to=UserCheckAccessResponse,
)
+ async def update_me(
+ self,
+ *,
+ account_id: str | Omit = omit,
+ bio: str | Omit = omit,
+ name: str | Omit = omit,
+ profile_picture: user_update_me_params.ProfilePicture | Omit = omit,
+ username: 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.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> User:
+ """
+ Updates the authenticated user's global profile, or their profile override for
+ an account when account_id is given. Not available to API keys.
+
+ Args:
+ account_id: When set, updates the authenticated user's profile override for this account
+ instead of their global profile.
+
+ 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._patch(
+ "/users/me",
+ body=await async_maybe_transform(
+ {
+ "bio": bio,
+ "name": name,
+ "profile_picture": profile_picture,
+ "username": username,
+ },
+ user_update_me_params.UserUpdateMeParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform({"account_id": account_id}, user_update_me_params.UserUpdateMeParams),
+ ),
+ cast_to=User,
+ )
+
class UsersResourceWithRawResponse:
def __init__(self, users: UsersResource) -> None:
@@ -494,6 +573,9 @@ def __init__(self, users: UsersResource) -> None:
self.check_access = to_raw_response_wrapper(
users.check_access,
)
+ self.update_me = to_raw_response_wrapper(
+ users.update_me,
+ )
class AsyncUsersResourceWithRawResponse:
@@ -512,6 +594,9 @@ def __init__(self, users: AsyncUsersResource) -> None:
self.check_access = async_to_raw_response_wrapper(
users.check_access,
)
+ self.update_me = async_to_raw_response_wrapper(
+ users.update_me,
+ )
class UsersResourceWithStreamingResponse:
@@ -530,6 +615,9 @@ def __init__(self, users: UsersResource) -> None:
self.check_access = to_streamed_response_wrapper(
users.check_access,
)
+ self.update_me = to_streamed_response_wrapper(
+ users.update_me,
+ )
class AsyncUsersResourceWithStreamingResponse:
@@ -548,3 +636,6 @@ def __init__(self, users: AsyncUsersResource) -> None:
self.check_access = async_to_streamed_response_wrapper(
users.check_access,
)
+ self.update_me = async_to_streamed_response_wrapper(
+ users.update_me,
+ )
diff --git a/src/whop_sdk/resources/verifications.py b/src/whop_sdk/resources/verifications.py
index 4fce0869..3403ff34 100644
--- a/src/whop_sdk/resources/verifications.py
+++ b/src/whop_sdk/resources/verifications.py
@@ -2,13 +2,14 @@
from __future__ import annotations
-from typing import Optional
+from typing import Dict, Iterable
+from typing_extensions import Literal
import httpx
-from ..types import verification_list_params
+from ..types import verification_list_params, verification_create_params, verification_update_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import path_template, maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -17,9 +18,11 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ..pagination import SyncCursorPage, AsyncCursorPage
-from .._base_client import AsyncPaginator, make_request_options
+from .._base_client import make_request_options
from ..types.verification_list_response import VerificationListResponse
+from ..types.verification_create_response import VerificationCreateResponse
+from ..types.verification_delete_response import VerificationDeleteResponse
+from ..types.verification_update_response import VerificationUpdateResponse
from ..types.verification_retrieve_response import VerificationRetrieveResponse
__all__ = ["VerificationsResource", "AsyncVerificationsResource"]
@@ -47,23 +50,122 @@ def with_streaming_response(self) -> VerificationsResourceWithStreamingResponse:
"""
return VerificationsResourceWithStreamingResponse(self)
- def retrieve(
+ def create(
self,
- id: str,
*,
+ account_id: str,
+ address: Dict[str, object] | Omit = omit,
+ business_name: str | Omit = omit,
+ business_structure: str | Omit = omit,
+ business_website: str | Omit = omit,
+ country: str | Omit = omit,
+ date_of_birth: str | Omit = omit,
+ first_name: str | Omit = omit,
+ kind: Literal["individual", "business"] | Omit = omit,
+ last_name: str | Omit = omit,
+ phone: str | Omit = omit,
+ place_of_incorporation: str | Omit = omit,
+ restart: bool | Omit = omit,
+ tax_identification_number: 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.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> VerificationRetrieveResponse:
+ ) -> VerificationCreateResponse:
"""
- Retrieves the details of an existing verification.
+ Creates or resumes a verification session for an account.
+
+ Args:
+ account_id: The account ID to verify (biz\\__ tag).
+
+ address: Optional pre-fill claim. Address (line1, city, state, postal_code).
+
+ business_name: Optional pre-fill claim for businesses.
+
+ business_structure: Optional. Business structure (e.g. llc, corporation).
+
+ business_website: Optional. Business website URL. Accepted for both individual and business
+ verifications on company accounts; persisted to the account's metadata and used
+ to provision the payout account on approval. Whop store pages are rejected.
+
+ country: Optional pre-fill claim. Country code; for businesses, the country of
+ incorporation.
+
+ date_of_birth: Optional pre-fill claim. Seeds the Sumsub session; attested values come from
+ Sumsub on approval.
+
+ first_name: Optional pre-fill claim. Seeds the Sumsub session; attested values come from
+ Sumsub on approval.
+
+ kind: The verification type. Defaults to individual.
+
+ last_name: Optional pre-fill claim. Seeds the Sumsub session; attested values come from
+ Sumsub on approval.
+
+ phone: Optional pre-fill claim — phone number.
- Required permissions:
+ place_of_incorporation: Optional. Place of incorporation (state/region); maps to the business address
+ state.
- - `payout:account:read`
+ restart: Whether to restart an in-flight verification.
+
+ tax_identification_number: Optional. Tax identification number — SSN for individuals, EIN for businesses.
+ Tokenized in transit, never stored raw; stored on the profile so the payout
+ account, provisioned on approval, doesn't raise a tax-id RFI.
+
+ 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(
+ "/verifications",
+ body=maybe_transform(
+ {
+ "address": address,
+ "business_name": business_name,
+ "business_structure": business_structure,
+ "business_website": business_website,
+ "country": country,
+ "date_of_birth": date_of_birth,
+ "first_name": first_name,
+ "kind": kind,
+ "last_name": last_name,
+ "phone": phone,
+ "place_of_incorporation": place_of_incorporation,
+ "restart": restart,
+ "tax_identification_number": tax_identification_number,
+ },
+ verification_create_params.VerificationCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"account_id": account_id}, verification_create_params.VerificationCreateParams),
+ ),
+ cast_to=VerificationCreateResponse,
+ )
+
+ def retrieve(
+ self,
+ verification_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,
+ ) -> VerificationRetrieveResponse:
+ """
+ Retrieves a single identity verification profile by its idpf\\__ tag.
Args:
extra_headers: Send extra headers
@@ -74,49 +176,59 @@ def retrieve(
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 verification_id:
+ raise ValueError(f"Expected a non-empty value for `verification_id` but received {verification_id!r}")
return self._get(
- path_template("/verifications/{id}", id=id),
+ path_template("/verifications/{verification_id}", verification_id=verification_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=VerificationRetrieveResponse,
)
- def list(
+ def update(
self,
+ verification_id: str,
*,
- payout_account_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
+ business_address: Dict[str, object] | Omit = omit,
+ business_name: str | Omit = omit,
+ business_structure: str | Omit = omit,
+ country: str | Omit = omit,
+ date_of_birth: str | Omit = omit,
+ first_name: str | Omit = omit,
+ last_name: str | Omit = omit,
+ personal_address: Dict[str, object] | Omit = omit,
+ rfis: Iterable[verification_update_params.Rfi] | 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[VerificationListResponse]:
+ ) -> VerificationUpdateResponse:
"""
- Returns a list of identity verifications for a payout account, ordered by most
- recent first.
+ Updates fields on an identity verification profile, or responds to outstanding
+ RFIs.
- Required permissions:
+ Args:
+ business_address: The business address.
- - `payout:account:read`
+ business_name: The business name.
- Args:
- payout_account_id: The unique identifier of the payout account to list verifications for.
+ business_structure: The business structure.
+
+ country: The country code.
- after: Returns the elements in the list that come after the specified cursor.
+ date_of_birth: The date of birth.
- before: Returns the elements in the list that come before the specified cursor.
+ first_name: The first name on the verification.
- first: Returns the first _n_ elements from the list.
+ last_name: The last name on the verification.
- last: Returns the last _n_ elements from the list.
+ personal_address: The personal address.
+
+ rfis: RFI responses. Each entry must include id and a value, address, or files
+ payload.
extra_headers: Send extra headers
@@ -126,26 +238,98 @@ def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return self._get_api_list(
+ if not verification_id:
+ raise ValueError(f"Expected a non-empty value for `verification_id` but received {verification_id!r}")
+ return self._patch(
+ path_template("/verifications/{verification_id}", verification_id=verification_id),
+ body=maybe_transform(
+ {
+ "business_address": business_address,
+ "business_name": business_name,
+ "business_structure": business_structure,
+ "country": country,
+ "date_of_birth": date_of_birth,
+ "first_name": first_name,
+ "last_name": last_name,
+ "personal_address": personal_address,
+ "rfis": rfis,
+ },
+ verification_update_params.VerificationUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=VerificationUpdateResponse,
+ )
+
+ def list(
+ self,
+ *,
+ account_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,
+ ) -> VerificationListResponse:
+ """
+ Lists identity verification profiles for an account.
+
+ Args:
+ account_id: The account ID to list verifications for (biz\\__ tag).
+
+ 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(
"/verifications",
- page=SyncCursorPage[VerificationListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=maybe_transform(
- {
- "payout_account_id": payout_account_id,
- "after": after,
- "before": before,
- "first": first,
- "last": last,
- },
- verification_list_params.VerificationListParams,
- ),
+ query=maybe_transform({"account_id": account_id}, verification_list_params.VerificationListParams),
+ ),
+ cast_to=VerificationListResponse,
+ )
+
+ def delete(
+ self,
+ verification_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,
+ ) -> VerificationDeleteResponse:
+ """
+ Unlinks a verification from the caller's accounts.
+
+ 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 verification_id:
+ raise ValueError(f"Expected a non-empty value for `verification_id` but received {verification_id!r}")
+ return self._delete(
+ path_template("/verifications/{verification_id}", verification_id=verification_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- model=VerificationListResponse,
+ cast_to=VerificationDeleteResponse,
)
@@ -171,23 +355,124 @@ def with_streaming_response(self) -> AsyncVerificationsResourceWithStreamingResp
"""
return AsyncVerificationsResourceWithStreamingResponse(self)
- async def retrieve(
+ async def create(
self,
- id: str,
*,
+ account_id: str,
+ address: Dict[str, object] | Omit = omit,
+ business_name: str | Omit = omit,
+ business_structure: str | Omit = omit,
+ business_website: str | Omit = omit,
+ country: str | Omit = omit,
+ date_of_birth: str | Omit = omit,
+ first_name: str | Omit = omit,
+ kind: Literal["individual", "business"] | Omit = omit,
+ last_name: str | Omit = omit,
+ phone: str | Omit = omit,
+ place_of_incorporation: str | Omit = omit,
+ restart: bool | Omit = omit,
+ tax_identification_number: 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.
extra_headers: Headers | None = None,
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> VerificationRetrieveResponse:
+ ) -> VerificationCreateResponse:
"""
- Retrieves the details of an existing verification.
+ Creates or resumes a verification session for an account.
+
+ Args:
+ account_id: The account ID to verify (biz\\__ tag).
+
+ address: Optional pre-fill claim. Address (line1, city, state, postal_code).
+
+ business_name: Optional pre-fill claim for businesses.
- Required permissions:
+ business_structure: Optional. Business structure (e.g. llc, corporation).
- - `payout:account:read`
+ business_website: Optional. Business website URL. Accepted for both individual and business
+ verifications on company accounts; persisted to the account's metadata and used
+ to provision the payout account on approval. Whop store pages are rejected.
+
+ country: Optional pre-fill claim. Country code; for businesses, the country of
+ incorporation.
+
+ date_of_birth: Optional pre-fill claim. Seeds the Sumsub session; attested values come from
+ Sumsub on approval.
+
+ first_name: Optional pre-fill claim. Seeds the Sumsub session; attested values come from
+ Sumsub on approval.
+
+ kind: The verification type. Defaults to individual.
+
+ last_name: Optional pre-fill claim. Seeds the Sumsub session; attested values come from
+ Sumsub on approval.
+
+ phone: Optional pre-fill claim — phone number.
+
+ place_of_incorporation: Optional. Place of incorporation (state/region); maps to the business address
+ state.
+
+ restart: Whether to restart an in-flight verification.
+
+ tax_identification_number: Optional. Tax identification number — SSN for individuals, EIN for businesses.
+ Tokenized in transit, never stored raw; stored on the profile so the payout
+ account, provisioned on approval, doesn't raise a tax-id RFI.
+
+ 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(
+ "/verifications",
+ body=await async_maybe_transform(
+ {
+ "address": address,
+ "business_name": business_name,
+ "business_structure": business_structure,
+ "business_website": business_website,
+ "country": country,
+ "date_of_birth": date_of_birth,
+ "first_name": first_name,
+ "kind": kind,
+ "last_name": last_name,
+ "phone": phone,
+ "place_of_incorporation": place_of_incorporation,
+ "restart": restart,
+ "tax_identification_number": tax_identification_number,
+ },
+ verification_create_params.VerificationCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"account_id": account_id}, verification_create_params.VerificationCreateParams
+ ),
+ ),
+ cast_to=VerificationCreateResponse,
+ )
+
+ async def retrieve(
+ self,
+ verification_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,
+ ) -> VerificationRetrieveResponse:
+ """
+ Retrieves a single identity verification profile by its idpf\\__ tag.
Args:
extra_headers: Send extra headers
@@ -198,49 +483,108 @@ async def retrieve(
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 verification_id:
+ raise ValueError(f"Expected a non-empty value for `verification_id` but received {verification_id!r}")
return await self._get(
- path_template("/verifications/{id}", id=id),
+ path_template("/verifications/{verification_id}", verification_id=verification_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=VerificationRetrieveResponse,
)
- def list(
+ async def update(
self,
+ verification_id: str,
*,
- payout_account_id: str,
- after: Optional[str] | Omit = omit,
- before: Optional[str] | Omit = omit,
- first: Optional[int] | Omit = omit,
- last: Optional[int] | Omit = omit,
+ business_address: Dict[str, object] | Omit = omit,
+ business_name: str | Omit = omit,
+ business_structure: str | Omit = omit,
+ country: str | Omit = omit,
+ date_of_birth: str | Omit = omit,
+ first_name: str | Omit = omit,
+ last_name: str | Omit = omit,
+ personal_address: Dict[str, object] | Omit = omit,
+ rfis: Iterable[verification_update_params.Rfi] | 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[VerificationListResponse, AsyncCursorPage[VerificationListResponse]]:
+ ) -> VerificationUpdateResponse:
"""
- Returns a list of identity verifications for a payout account, ordered by most
- recent first.
+ Updates fields on an identity verification profile, or responds to outstanding
+ RFIs.
- Required permissions:
+ Args:
+ business_address: The business address.
- - `payout:account:read`
+ business_name: The business name.
- Args:
- payout_account_id: The unique identifier of the payout account to list verifications for.
+ business_structure: The business structure.
+
+ country: The country code.
+
+ date_of_birth: The date of birth.
+
+ first_name: The first name on the verification.
+
+ last_name: The last name on the verification.
+
+ personal_address: The personal address.
- after: Returns the elements in the list that come after the specified cursor.
+ rfis: RFI responses. Each entry must include id and a value, address, or files
+ payload.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
- before: Returns the elements in the list that come before the specified cursor.
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not verification_id:
+ raise ValueError(f"Expected a non-empty value for `verification_id` but received {verification_id!r}")
+ return await self._patch(
+ path_template("/verifications/{verification_id}", verification_id=verification_id),
+ body=await async_maybe_transform(
+ {
+ "business_address": business_address,
+ "business_name": business_name,
+ "business_structure": business_structure,
+ "country": country,
+ "date_of_birth": date_of_birth,
+ "first_name": first_name,
+ "last_name": last_name,
+ "personal_address": personal_address,
+ "rfis": rfis,
+ },
+ verification_update_params.VerificationUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=VerificationUpdateResponse,
+ )
- first: Returns the first _n_ elements from the list.
+ async def list(
+ self,
+ *,
+ account_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,
+ ) -> VerificationListResponse:
+ """
+ Lists identity verification profiles for an account.
- last: Returns the last _n_ elements from the list.
+ Args:
+ account_id: The account ID to list verifications for (biz\\__ tag).
extra_headers: Send extra headers
@@ -250,26 +594,51 @@ def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return self._get_api_list(
+ return await self._get(
"/verifications",
- page=AsyncCursorPage[VerificationListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=maybe_transform(
- {
- "payout_account_id": payout_account_id,
- "after": after,
- "before": before,
- "first": first,
- "last": last,
- },
- verification_list_params.VerificationListParams,
+ query=await async_maybe_transform(
+ {"account_id": account_id}, verification_list_params.VerificationListParams
),
),
- model=VerificationListResponse,
+ cast_to=VerificationListResponse,
+ )
+
+ async def delete(
+ self,
+ verification_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,
+ ) -> VerificationDeleteResponse:
+ """
+ Unlinks a verification from the caller's accounts.
+
+ 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 verification_id:
+ raise ValueError(f"Expected a non-empty value for `verification_id` but received {verification_id!r}")
+ return await self._delete(
+ path_template("/verifications/{verification_id}", verification_id=verification_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=VerificationDeleteResponse,
)
@@ -277,45 +646,81 @@ class VerificationsResourceWithRawResponse:
def __init__(self, verifications: VerificationsResource) -> None:
self._verifications = verifications
+ self.create = to_raw_response_wrapper(
+ verifications.create,
+ )
self.retrieve = to_raw_response_wrapper(
verifications.retrieve,
)
+ self.update = to_raw_response_wrapper(
+ verifications.update,
+ )
self.list = to_raw_response_wrapper(
verifications.list,
)
+ self.delete = to_raw_response_wrapper(
+ verifications.delete,
+ )
class AsyncVerificationsResourceWithRawResponse:
def __init__(self, verifications: AsyncVerificationsResource) -> None:
self._verifications = verifications
+ self.create = async_to_raw_response_wrapper(
+ verifications.create,
+ )
self.retrieve = async_to_raw_response_wrapper(
verifications.retrieve,
)
+ self.update = async_to_raw_response_wrapper(
+ verifications.update,
+ )
self.list = async_to_raw_response_wrapper(
verifications.list,
)
+ self.delete = async_to_raw_response_wrapper(
+ verifications.delete,
+ )
class VerificationsResourceWithStreamingResponse:
def __init__(self, verifications: VerificationsResource) -> None:
self._verifications = verifications
+ self.create = to_streamed_response_wrapper(
+ verifications.create,
+ )
self.retrieve = to_streamed_response_wrapper(
verifications.retrieve,
)
+ self.update = to_streamed_response_wrapper(
+ verifications.update,
+ )
self.list = to_streamed_response_wrapper(
verifications.list,
)
+ self.delete = to_streamed_response_wrapper(
+ verifications.delete,
+ )
class AsyncVerificationsResourceWithStreamingResponse:
def __init__(self, verifications: AsyncVerificationsResource) -> None:
self._verifications = verifications
+ self.create = async_to_streamed_response_wrapper(
+ verifications.create,
+ )
self.retrieve = async_to_streamed_response_wrapper(
verifications.retrieve,
)
+ self.update = async_to_streamed_response_wrapper(
+ verifications.update,
+ )
self.list = async_to_streamed_response_wrapper(
verifications.list,
)
+ self.delete = async_to_streamed_response_wrapper(
+ verifications.delete,
+ )
diff --git a/src/whop_sdk/resources/wallets.py b/src/whop_sdk/resources/wallets.py
deleted file mode 100644
index 42e8018d..00000000
--- a/src/whop_sdk/resources/wallets.py
+++ /dev/null
@@ -1,321 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-import httpx
-
-from ..types import wallet_send_params
-from .._types import Body, Query, Headers, NotGiven, not_given
-from .._utils import path_template, 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 .._base_client import make_request_options
-from ..types.wallet_list_response import WalletListResponse
-from ..types.wallet_send_response import WalletSendResponse
-from ..types.wallet_balance_response import WalletBalanceResponse
-
-__all__ = ["WalletsResource", "AsyncWalletsResource"]
-
-
-class WalletsResource(SyncAPIResource):
- @cached_property
- def with_raw_response(self) -> WalletsResourceWithRawResponse:
- """
- 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 WalletsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> WalletsResourceWithStreamingResponse:
- """
- 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 WalletsResourceWithStreamingResponse(self)
-
- def list(
- self,
- *,
- # 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,
- ) -> WalletListResponse:
- """Lists every crypto wallet linked to the authenticated resource."""
- return self._get(
- "/wallets",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WalletListResponse,
- )
-
- def balance(
- self,
- account_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,
- ) -> WalletBalanceResponse:
- """
- Returns per-token balances held in an account's wallet.
-
- 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 account_id:
- raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
- return self._get(
- path_template("/wallets/{account_id}/balance", account_id=account_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WalletBalanceResponse,
- )
-
- def send(
- self,
- account_id: str,
- *,
- amount: str,
- to: 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,
- ) -> WalletSendResponse:
- """
- Sends USDT from an account's wallet to another Whop user or business.
-
- Args:
- amount: USDT amount to send.
-
- to: Recipient user ID, business account ID, ledger account ID, or email.
-
- 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 account_id:
- raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
- return self._post(
- path_template("/wallets/{account_id}/sends", account_id=account_id),
- body=maybe_transform(
- {
- "amount": amount,
- "to": to,
- },
- wallet_send_params.WalletSendParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WalletSendResponse,
- )
-
-
-class AsyncWalletsResource(AsyncAPIResource):
- @cached_property
- def with_raw_response(self) -> AsyncWalletsResourceWithRawResponse:
- """
- 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 AsyncWalletsResourceWithRawResponse(self)
-
- @cached_property
- def with_streaming_response(self) -> AsyncWalletsResourceWithStreamingResponse:
- """
- 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 AsyncWalletsResourceWithStreamingResponse(self)
-
- async def list(
- self,
- *,
- # 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,
- ) -> WalletListResponse:
- """Lists every crypto wallet linked to the authenticated resource."""
- return await self._get(
- "/wallets",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WalletListResponse,
- )
-
- async def balance(
- self,
- account_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,
- ) -> WalletBalanceResponse:
- """
- Returns per-token balances held in an account's wallet.
-
- 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 account_id:
- raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
- return await self._get(
- path_template("/wallets/{account_id}/balance", account_id=account_id),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WalletBalanceResponse,
- )
-
- async def send(
- self,
- account_id: str,
- *,
- amount: str,
- to: 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,
- ) -> WalletSendResponse:
- """
- Sends USDT from an account's wallet to another Whop user or business.
-
- Args:
- amount: USDT amount to send.
-
- to: Recipient user ID, business account ID, ledger account ID, or email.
-
- 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 account_id:
- raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
- return await self._post(
- path_template("/wallets/{account_id}/sends", account_id=account_id),
- body=await async_maybe_transform(
- {
- "amount": amount,
- "to": to,
- },
- wallet_send_params.WalletSendParams,
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WalletSendResponse,
- )
-
-
-class WalletsResourceWithRawResponse:
- def __init__(self, wallets: WalletsResource) -> None:
- self._wallets = wallets
-
- self.list = to_raw_response_wrapper(
- wallets.list,
- )
- self.balance = to_raw_response_wrapper(
- wallets.balance,
- )
- self.send = to_raw_response_wrapper(
- wallets.send,
- )
-
-
-class AsyncWalletsResourceWithRawResponse:
- def __init__(self, wallets: AsyncWalletsResource) -> None:
- self._wallets = wallets
-
- self.list = async_to_raw_response_wrapper(
- wallets.list,
- )
- self.balance = async_to_raw_response_wrapper(
- wallets.balance,
- )
- self.send = async_to_raw_response_wrapper(
- wallets.send,
- )
-
-
-class WalletsResourceWithStreamingResponse:
- def __init__(self, wallets: WalletsResource) -> None:
- self._wallets = wallets
-
- self.list = to_streamed_response_wrapper(
- wallets.list,
- )
- self.balance = to_streamed_response_wrapper(
- wallets.balance,
- )
- self.send = to_streamed_response_wrapper(
- wallets.send,
- )
-
-
-class AsyncWalletsResourceWithStreamingResponse:
- def __init__(self, wallets: AsyncWalletsResource) -> None:
- self._wallets = wallets
-
- self.list = async_to_streamed_response_wrapper(
- wallets.list,
- )
- self.balance = async_to_streamed_response_wrapper(
- wallets.balance,
- )
- self.send = async_to_streamed_response_wrapper(
- wallets.send,
- )
diff --git a/src/whop_sdk/resources/withdrawals.py b/src/whop_sdk/resources/withdrawals.py
index 0eb7bde9..78a2336c 100644
--- a/src/whop_sdk/resources/withdrawals.py
+++ b/src/whop_sdk/resources/withdrawals.py
@@ -83,7 +83,7 @@ def create(
payout_method_id: The ID of the payout method to use for the withdrawal.
- platform_covers_fees: Whether the platform covers the payout fees instead of the connected account.
+ platform_covers_fees: Whether the platform covers the payout fees.
statement_descriptor: Custom statement descriptor for the withdrawal. Must be between 5 and 22
characters and contain only alphanumeric characters.
@@ -285,7 +285,7 @@ async def create(
payout_method_id: The ID of the payout method to use for the withdrawal.
- platform_covers_fees: Whether the platform covers the payout fees instead of the connected account.
+ platform_covers_fees: Whether the platform covers the payout fees.
statement_descriptor: Custom statement descriptor for the withdrawal. Must be between 5 and 22
characters and contain only alphanumeric characters.
diff --git a/src/whop_sdk/types/__init__.py b/src/whop_sdk/types/__init__.py
index c41c9b9b..90baf49b 100644
--- a/src/whop_sdk/types/__init__.py
+++ b/src/whop_sdk/types/__init__.py
@@ -24,7 +24,6 @@
PlanType as PlanType,
Reaction as Reaction,
Shipment as Shipment,
- Transfer as Transfer,
CustomCta as CustomCta,
Direction as Direction,
ForumPost as ForumPost,
@@ -92,7 +91,6 @@
from .review_status import ReviewStatus as ReviewStatus
from .upload_status import UploadStatus as UploadStatus
from .webhook_event import WebhookEvent as WebhookEvent
-from .account_wallet import AccountWallet as AccountWallet
from .ad_budget_type import AdBudgetType as AdBudgetType
from .ad_list_params import AdListParams as AdListParams
from .cancel_options import CancelOptions as CancelOptions
@@ -107,10 +105,12 @@
from .fee_markup_type import FeeMarkupType as FeeMarkupType
from .file_visibility import FileVisibility as FileVisibility
from .ad_list_response import AdListResponse as AdListResponse
+from .card_list_params import CardListParams as CardListParams
from .dispute_statuses import DisputeStatuses as DisputeStatuses
from .lead_list_params import LeadListParams as LeadListParams
from .payment_provider import PaymentProvider as PaymentProvider
from .plan_list_params import PlanListParams as PlanListParams
+from .swap_list_params import SwapListParams as SwapListParams
from .user_list_params import UserListParams as UserListParams
from .app_create_params import AppCreateParams as AppCreateParams
from .app_list_response import AppListResponse as AppListResponse
@@ -122,7 +122,10 @@
from .withdrawal_speeds import WithdrawalSpeeds as WithdrawalSpeeds
from .withdrawal_status import WithdrawalStatus as WithdrawalStatus
from .ad_campaign_status import AdCampaignStatus as AdCampaignStatus
+from .ad_retrieve_params import AdRetrieveParams as AdRetrieveParams
from .bounty_list_params import BountyListParams as BountyListParams
+from .card_create_params import CardCreateParams as CardCreateParams
+from .card_list_response import CardListResponse as CardListResponse
from .course_list_params import CourseListParams as CourseListParams
from .dispute_alert_type import DisputeAlertType as DisputeAlertType
from .external_ad_status import ExternalAdStatus as ExternalAdStatus
@@ -131,19 +134,21 @@
from .lead_list_response import LeadListResponse as LeadListResponse
from .lead_update_params import LeadUpdateParams as LeadUpdateParams
from .member_list_params import MemberListParams as MemberListParams
+from .payout_list_params import PayoutListParams as PayoutListParams
from .plan_create_params import PlanCreateParams as PlanCreateParams
from .plan_list_response import PlanListResponse as PlanListResponse
from .plan_update_params import PlanUpdateParams as PlanUpdateParams
from .refund_list_params import RefundListParams as RefundListParams
from .review_list_params import ReviewListParams as ReviewListParams
-from .user_list_response import UserListResponse as UserListResponse
+from .swap_create_params import SwapCreateParams as SwapCreateParams
+from .swap_list_response import SwapListResponse as SwapListResponse
from .user_update_params import UserUpdateParams as UserUpdateParams
-from .wallet_send_params import WalletSendParams as WalletSendParams
from .account_list_params import AccountListParams as AccountListParams
from .account_social_link import AccountSocialLink as AccountSocialLink
from .ai_chat_list_params import AIChatListParams as AIChatListParams
from .company_list_params import CompanyListParams as CompanyListParams
from .course_visibilities import CourseVisibilities as CourseVisibilities
+from .deposit_list_params import DepositListParams as DepositListParams
from .dispute_list_params import DisputeListParams as DisputeListParams
from .entry_list_response import EntryListResponse as EntryListResponse
from .forum_list_response import ForumListResponse as ForumListResponse
@@ -162,12 +167,15 @@
from .ad_group_list_params import AdGroupListParams as AdGroupListParams
from .bounty_create_params import BountyCreateParams as BountyCreateParams
from .bounty_list_response import BountyListResponse as BountyListResponse
+from .card_create_response import CardCreateResponse as CardCreateResponse
+from .card_retrieve_params import CardRetrieveParams as CardRetrieveParams
from .course_create_params import CourseCreateParams as CourseCreateParams
from .course_list_response import CourseListResponse as CourseListResponse
from .course_update_params import CourseUpdateParams as CourseUpdateParams
from .file_create_response import FileCreateResponse as FileCreateResponse
from .member_list_response import MemberListResponse as MemberListResponse
from .payment_method_types import PaymentMethodTypes as PaymentMethodTypes
+from .payout_list_response import PayoutListResponse as PayoutListResponse
from .plan_delete_response import PlanDeleteResponse as PlanDeleteResponse
from .reaction_list_params import ReactionListParams as ReactionListParams
from .receipt_tax_behavior import ReceiptTaxBehavior as ReceiptTaxBehavior
@@ -175,14 +183,12 @@
from .review_list_response import ReviewListResponse as ReviewListResponse
from .shipment_list_params import ShipmentListParams as ShipmentListParams
from .social_link_websites import SocialLinkWebsites as SocialLinkWebsites
+from .swap_create_response import SwapCreateResponse as SwapCreateResponse
from .transfer_list_params import TransferListParams as TransferListParams
from .unwrap_webhook_event import UnwrapWebhookEvent as UnwrapWebhookEvent
from .user_retrieve_params import UserRetrieveParams as UserRetrieveParams
-from .wallet_list_response import WalletListResponse as WalletListResponse
-from .wallet_send_response import WalletSendResponse as WalletSendResponse
from .withdrawal_fee_types import WithdrawalFeeTypes as WithdrawalFeeTypes
from .account_create_params import AccountCreateParams as AccountCreateParams
-from .account_list_response import AccountListResponse as AccountListResponse
from .account_update_params import AccountUpdateParams as AccountUpdateParams
from .affiliate_list_params import AffiliateListParams as AffiliateListParams
from .ai_chat_create_params import AIChatCreateParams as AIChatCreateParams
@@ -193,6 +199,7 @@
from .company_list_response import CompanyListResponse as CompanyListResponse
from .company_update_params import CompanyUpdateParams as CompanyUpdateParams
from .deposit_create_params import DepositCreateParams as DepositCreateParams
+from .deposit_list_response import DepositListResponse as DepositListResponse
from .dispute_list_response import DisputeListResponse as DisputeListResponse
from .dm_member_list_params import DmMemberListParams as DmMemberListParams
from .invoice_create_params import InvoiceCreateParams as InvoiceCreateParams
@@ -208,12 +215,14 @@
from .product_update_params import ProductUpdateParams as ProductUpdateParams
from .refund_reference_type import RefundReferenceType as RefundReferenceType
from .topup_create_response import TopupCreateResponse as TopupCreateResponse
+from .user_update_me_params import UserUpdateMeParams as UserUpdateMeParams
from .webhook_create_params import WebhookCreateParams as WebhookCreateParams
from .webhook_list_response import WebhookListResponse as WebhookListResponse
from .webhook_update_params import WebhookUpdateParams as WebhookUpdateParams
from .ad_group_list_response import AdGroupListResponse as AdGroupListResponse
from .ad_group_update_params import AdGroupUpdateParams as AdGroupUpdateParams
from .bounty_create_response import BountyCreateResponse as BountyCreateResponse
+from .card_retrieve_response import CardRetrieveResponse as CardRetrieveResponse
from .course_delete_response import CourseDeleteResponse as CourseDeleteResponse
from .dm_channel_list_params import DmChannelListParams as DmChannelListParams
from .entry_approve_response import EntryApproveResponse as EntryApproveResponse
@@ -228,6 +237,7 @@
from .reaction_list_response import ReactionListResponse as ReactionListResponse
from .shipment_create_params import ShipmentCreateParams as ShipmentCreateParams
from .shipment_list_response import ShipmentListResponse as ShipmentListResponse
+from .swap_retrieve_response import SwapRetrieveResponse as SwapRetrieveResponse
from .transfer_create_params import TransferCreateParams as TransferCreateParams
from .transfer_list_response import TransferListResponse as TransferListResponse
from .withdrawal_list_params import WithdrawalListParams as WithdrawalListParams
@@ -248,10 +258,10 @@
from .product_delete_response import ProductDeleteResponse as ProductDeleteResponse
from .refund_reference_status import RefundReferenceStatus as RefundReferenceStatus
from .verification_error_code import VerificationErrorCode as VerificationErrorCode
-from .wallet_balance_response import WalletBalanceResponse as WalletBalanceResponse
from .webhook_create_response import WebhookCreateResponse as WebhookCreateResponse
from .webhook_delete_response import WebhookDeleteResponse as WebhookDeleteResponse
from .ad_group_delete_response import AdGroupDeleteResponse as AdGroupDeleteResponse
+from .ad_group_retrieve_params import AdGroupRetrieveParams as AdGroupRetrieveParams
from .bounty_retrieve_response import BountyRetrieveResponse as BountyRetrieveResponse
from .chat_channel_list_params import ChatChannelListParams as ChatChannelListParams
from .conversion_create_params import ConversionCreateParams as ConversionCreateParams
@@ -281,6 +291,7 @@
from .review_retrieve_response import ReviewRetrieveResponse as ReviewRetrieveResponse
from .setup_intent_list_params import SetupIntentListParams as SetupIntentListParams
from .swap_create_quote_params import SwapCreateQuoteParams as SwapCreateQuoteParams
+from .transfer_create_response import TransferCreateResponse as TransferCreateResponse
from .verification_list_params import VerificationListParams as VerificationListParams
from .withdrawal_create_params import WithdrawalCreateParams as WithdrawalCreateParams
from .withdrawal_list_response import WithdrawalListResponse as WithdrawalListResponse
@@ -293,6 +304,7 @@
from .dispute_alert_list_params import DisputeAlertListParams as DisputeAlertListParams
from .dm_member_delete_response import DmMemberDeleteResponse as DmMemberDeleteResponse
from .payout_method_list_params import PayoutMethodListParams as PayoutMethodListParams
+from .plan_calculate_tax_params import PlanCalculateTaxParams as PlanCalculateTaxParams
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
@@ -315,8 +327,12 @@
from .promo_code_delete_response import PromoCodeDeleteResponse as PromoCodeDeleteResponse
from .setup_intent_list_response import SetupIntentListResponse as SetupIntentListResponse
from .swap_create_quote_response import SwapCreateQuoteResponse as SwapCreateQuoteResponse
+from .transfer_retrieve_response import TransferRetrieveResponse as TransferRetrieveResponse
from .user_check_access_response import UserCheckAccessResponse as UserCheckAccessResponse
+from .verification_create_params import VerificationCreateParams as VerificationCreateParams
from .verification_list_response import VerificationListResponse as VerificationListResponse
+from .verification_update_params import VerificationUpdateParams as VerificationUpdateParams
+from .ad_campaign_retrieve_params import AdCampaignRetrieveParams as AdCampaignRetrieveParams
from .ad_report_retrieve_response import AdReportRetrieveResponse as AdReportRetrieveResponse
from .authorized_user_list_params import AuthorizedUserListParams as AuthorizedUserListParams
from .course_lesson_create_params import CourseLessonCreateParams as CourseLessonCreateParams
@@ -328,6 +344,7 @@
from .experience_duplicate_params import ExperienceDuplicateParams as ExperienceDuplicateParams
from .payout_destination_category import PayoutDestinationCategory as PayoutDestinationCategory
from .payout_method_list_response import PayoutMethodListResponse as PayoutMethodListResponse
+from .plan_calculate_tax_response import PlanCalculateTaxResponse as PlanCalculateTaxResponse
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
@@ -344,6 +361,9 @@
from .payment_method_list_response import PaymentMethodListResponse as PaymentMethodListResponse
from .refund_created_webhook_event import RefundCreatedWebhookEvent as RefundCreatedWebhookEvent
from .refund_updated_webhook_event import RefundUpdatedWebhookEvent as RefundUpdatedWebhookEvent
+from .verification_create_response import VerificationCreateResponse as VerificationCreateResponse
+from .verification_delete_response import VerificationDeleteResponse as VerificationDeleteResponse
+from .verification_update_response import VerificationUpdateResponse as VerificationUpdateResponse
from .authorized_user_create_params import AuthorizedUserCreateParams as AuthorizedUserCreateParams
from .authorized_user_delete_params import AuthorizedUserDeleteParams as AuthorizedUserDeleteParams
from .authorized_user_list_response import AuthorizedUserListResponse as AuthorizedUserListResponse
@@ -360,6 +380,7 @@
from .company_token_transaction_type import CompanyTokenTransactionType as CompanyTokenTransactionType
from .course_chapter_delete_response import CourseChapterDeleteResponse as CourseChapterDeleteResponse
from .dispute_update_evidence_params import DisputeUpdateEvidenceParams as DisputeUpdateEvidenceParams
+from .financial_activity_list_params import FinancialActivityListParams as FinancialActivityListParams
from .invoice_past_due_webhook_event import InvoicePastDueWebhookEvent as InvoicePastDueWebhookEvent
from .payment_method_retrieve_params import PaymentMethodRetrieveParams as PaymentMethodRetrieveParams
from .verification_retrieve_response import VerificationRetrieveResponse as VerificationRetrieveResponse
@@ -370,16 +391,19 @@
from .payment_succeeded_webhook_event import PaymentSucceededWebhookEvent as PaymentSucceededWebhookEvent
from .payout_method_retrieve_response import PayoutMethodRetrieveResponse as PayoutMethodRetrieveResponse
from .course_student_retrieve_response import CourseStudentRetrieveResponse as CourseStudentRetrieveResponse
+from .financial_activity_list_response import FinancialActivityListResponse as FinancialActivityListResponse
from .ledger_account_retrieve_response import LedgerAccountRetrieveResponse as LedgerAccountRetrieveResponse
from .payment_method_retrieve_response import PaymentMethodRetrieveResponse as PaymentMethodRetrieveResponse
from .payout_account_retrieve_response import PayoutAccountRetrieveResponse as PayoutAccountRetrieveResponse
from .withdrawal_created_webhook_event import WithdrawalCreatedWebhookEvent as WithdrawalCreatedWebhookEvent
from .withdrawal_updated_webhook_event import WithdrawalUpdatedWebhookEvent as WithdrawalUpdatedWebhookEvent
from .resolution_center_case_issue_type import ResolutionCenterCaseIssueType as ResolutionCenterCaseIssueType
+from .chat_message_created_webhook_event import ChatMessageCreatedWebhookEvent as ChatMessageCreatedWebhookEvent
from .checkout_configuration_list_params import CheckoutConfigurationListParams as CheckoutConfigurationListParams
from .membership_activated_webhook_event import MembershipActivatedWebhookEvent as MembershipActivatedWebhookEvent
from .payout_account_calculated_statuses import PayoutAccountCalculatedStatuses as PayoutAccountCalculatedStatuses
from .resolution_center_case_list_params import ResolutionCenterCaseListParams as ResolutionCenterCaseListParams
+from .chat_reaction_created_webhook_event import ChatReactionCreatedWebhookEvent as ChatReactionCreatedWebhookEvent
from .dispute_alert_created_webhook_event import DisputeAlertCreatedWebhookEvent as DisputeAlertCreatedWebhookEvent
from .invoice_mark_uncollectible_response import InvoiceMarkUncollectibleResponse as InvoiceMarkUncollectibleResponse
from .payout_method_created_webhook_event import PayoutMethodCreatedWebhookEvent as PayoutMethodCreatedWebhookEvent
@@ -396,6 +420,9 @@
from .course_lesson_interaction_list_params import (
CourseLessonInteractionListParams as CourseLessonInteractionListParams,
)
+from .checkout_configuration_create_response import (
+ CheckoutConfigurationCreateResponse as CheckoutConfigurationCreateResponse,
+)
from .course_lesson_submit_assessment_params import (
CourseLessonSubmitAssessmentParams as CourseLessonSubmitAssessmentParams,
)
@@ -417,6 +444,9 @@
from .identity_profile_rejected_webhook_event import (
IdentityProfileRejectedWebhookEvent as IdentityProfileRejectedWebhookEvent,
)
+from .checkout_configuration_retrieve_response import (
+ CheckoutConfigurationRetrieveResponse as CheckoutConfigurationRetrieveResponse,
+)
from .course_lesson_mark_as_completed_response import (
CourseLessonMarkAsCompletedResponse as CourseLessonMarkAsCompletedResponse,
)
@@ -438,6 +468,9 @@
from .invoice_marked_uncollectible_webhook_event import (
InvoiceMarkedUncollectibleWebhookEvent as InvoiceMarkedUncollectibleWebhookEvent,
)
+from .membership_trial_ending_soon_webhook_event import (
+ MembershipTrialEndingSoonWebhookEvent as MembershipTrialEndingSoonWebhookEvent,
+)
from .setup_intent_requires_action_webhook_event import (
SetupIntentRequiresActionWebhookEvent as SetupIntentRequiresActionWebhookEvent,
)
@@ -447,6 +480,9 @@
from .payout_account_status_updated_webhook_event import (
PayoutAccountStatusUpdatedWebhookEvent as PayoutAccountStatusUpdatedWebhookEvent,
)
+from .ledger_account_funds_available_webhook_event import (
+ LedgerAccountFundsAvailableWebhookEvent as LedgerAccountFundsAvailableWebhookEvent,
+)
from .resolution_center_case_created_webhook_event import (
ResolutionCenterCaseCreatedWebhookEvent as ResolutionCenterCaseCreatedWebhookEvent,
)
diff --git a/src/whop_sdk/types/account.py b/src/whop_sdk/types/account.py
index 6a1d0063..29809554 100644
--- a/src/whop_sdk/types/account.py
+++ b/src/whop_sdk/types/account.py
@@ -1,24 +1,187 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import List, Optional
+from typing_extensions import Literal
from .._models import BaseModel
-from .account_wallet import AccountWallet
from .account_social_link import AccountSocialLink
-__all__ = ["Account"]
+__all__ = ["Account", "Balance", "Capabilities", "RecommendedAction", "RequiredAction", "Wallet"]
+
+
+class Balance(BaseModel):
+ """The account's holdings (crypto and fiat), each with its USD value.
+
+ Empty when total_usd is null (not computed)
+ """
+
+ balance: str
+ """The total amount held in native units, as a decimal string"""
+
+ breakdown: object
+ """
+ The holding split into available, pending, and reserve amounts (native-unit
+ decimal strings). On-chain crypto is entirely available; good_funds and fiat
+ cash can have pending/reserve portions
+ """
+
+ icon_url: Optional[str] = None
+ """The URL of the holding's icon, when available"""
+
+ name: str
+ """The holding's display name"""
+
+ price_usd: Optional[float] = None
+ """The USD price per unit, or null when no exchange rate is available"""
+
+ symbol: str
+ """The holding's display symbol, e.g. USDT, cbBTC, or EUR"""
+
+ value_usd: Optional[str] = None
+ """The total USD value of the holding, or null when no exchange rate is available"""
+
+
+class Capabilities(BaseModel):
+ """Payment rails enabled for this account (active, inactive, or pending).
+
+ pending means onboarding or review is in progress. Only computed on retrieve and me for callers with the company:balance:read scope; null otherwise
+ """
+
+ accept_bank_payments: Literal["active", "inactive", "pending"]
+ """Bank payins: debits, transfers, and local bank rails"""
+
+ accept_bnpl_payments: Literal["active", "inactive", "pending"]
+ """Buy-now-pay-later payins; requires approval"""
+
+ accept_card_payments: Literal["active", "inactive", "pending"]
+ """Card payins, including Apple Pay and Google Pay"""
+
+ bank_deposit: Literal["active", "inactive", "pending"]
+ """Deposits by bank wire or ACH to the account's virtual bank account"""
+
+ card_deposit: Literal["active", "inactive", "pending"]
+ """Balance top-ups by charging a stored payment method"""
+
+ card_issuing: Literal["active", "inactive", "pending"]
+ """Issuing Whop cards; requires card application approval"""
+
+ crypto_deposit: Literal["active", "inactive", "pending"]
+ """On-chain deposits to the account's crypto wallet"""
+
+ crypto_payout: Literal["active", "inactive", "pending"]
+ """On-chain payouts to a crypto wallet"""
+
+ instant_payout: Literal["active", "inactive", "pending"]
+ """Instant payouts to an eligible payout destination"""
+
+ standard_payout: Literal["active", "inactive", "pending"]
+ """Standard payouts to an external payout destination"""
+
+ transfer: Literal["active", "inactive", "pending"]
+ """Transfers to other accounts"""
+
+
+class RecommendedAction(BaseModel):
+ """Optional actions that unlock capabilities or grow the account.
+
+ Same shape as required_actions. Only computed on retrieve and me; null otherwise
+ """
+
+ action: Literal["apply_for_financing", "migrate_from_stripe", "accept_first_payment", "join_whop_university"]
+ """
+ The recommendation; new values may be added, so handle unknown actions
+ gracefully
+ """
+
+ blocked_capabilities: List[str]
+
+ cta: str
+ """The URL the call-to-action links to"""
+
+ cta_label: str
+ """Button label"""
+
+ description: str
+ """Supporting copy, or empty"""
+
+ icon_url: Optional[str] = None
+ """Illustration icon URL, or null"""
+
+ status: Literal["optional"]
+ """Always optional — never blocking"""
+
+ title: str
+ """Headline for the recommendation"""
+
+
+class RequiredAction(BaseModel):
+ """Obligations the account holder must resolve, ordered by display priority.
+
+ Only computed on retrieve and me for callers with the company:balance:read scope; null otherwise
+ """
+
+ action: Literal["deposit_funds", "submit_information_request", "verify_identity", "connect_fulfillment_tracker"]
+ """
+ What the holder must do; new values may be added, so handle unknown actions
+ gracefully
+ """
+
+ blocked_capabilities: List[str]
+
+ cta: Optional[str] = None
+ """The URL the call-to-action links to, or null when there is no button"""
+
+ cta_label: str
+ """Button label, or empty when there is no button"""
+
+ description: str
+ """Supporting copy, or empty"""
+
+ icon_url: Optional[str] = None
+ """The URL of the action's illustration icon, or null if it has none"""
+
+ status: Literal["required", "pending"]
+ """required (act now) or pending (under review)"""
+
+ title: str
+ """Headline for the action"""
+
+
+class Wallet(BaseModel):
+ """The account's primary crypto wallet, or null if none has been provisioned"""
+
+ id: str
+ """The ID of the wallet, which will look like wallet\\__******\\********"""
+
+ address: str
+ """The on-chain address of the wallet"""
+
+ network: Literal["solana", "ethereum", "bitcoin"]
+ """The blockchain network the wallet lives on"""
class Account(BaseModel):
id: str
"""The ID of the account, which will look like biz\\__******\\********"""
+ balances: List[Balance]
+
banner_image_url: Optional[str] = None
"""The URL of the account banner image"""
business_type: Optional[str] = None
"""The high-level business category for the account"""
+ capabilities: Optional[Capabilities] = None
+ """Payment rails enabled for this account (active, inactive, or pending).
+
+ pending means onboarding or review is in progress. Only computed on retrieve and
+ me for callers with the company:balance:read scope; null otherwise
+ """
+
+ country: Optional[str] = None
+ """The country the account is located in"""
+
created_at: str
"""When the account was created, as an ISO 8601 timestamp"""
@@ -28,34 +191,108 @@ class Account(BaseModel):
email: Optional[str] = None
"""The email address of the account owner"""
+ home_preferences: List[str]
+
industry_group: Optional[str] = None
"""The industry group the account belongs to"""
industry_type: Optional[str] = None
"""The specific industry vertical the account operates in"""
+ invoice_prefix: Optional[str] = None
+ """The prefix used for account invoices"""
+
logo_url: Optional[str] = None
"""The URL of the account logo image"""
metadata: object
"""Arbitrary key/value metadata supplied when the account was created"""
+ onboarding_type: Optional[str] = None
+ """The type of onboarding the account has completed"""
+
+ opengraph_image_url: Optional[str] = None
+ """The URL of the account Open Graph image"""
+
+ opengraph_image_variant: Optional[str] = None
+ """The account Open Graph image variant"""
+
+ other_business_description: Optional[str] = None
+ """The description of the business type when business_type is other"""
+
+ other_industry_description: Optional[str] = None
+ """The description of the industry type when industry_type is other"""
+
parent_account_id: Optional[str] = None
"""The parent account ID for connected accounts"""
+ recommended_actions: Optional[List[RecommendedAction]] = None
+
+ require_2fa: bool
+ """
+ Whether the account requires authorized users to have two-factor authentication
+ enabled
+ """
+
+ required_actions: Optional[List[RequiredAction]] = None
+
route: str
"""The account's public route identifier"""
send_customer_emails: bool
"""Whether Whop sends transactional emails to customers on behalf of this account"""
+ show_joined_whops: bool
+ """Whether the account appears in joined whops on other accounts"""
+
+ show_reviews_dtc: bool
+ """Whether reviews are displayed on direct-to-consumer product pages"""
+
+ show_user_directory: bool
+ """Whether the account shows users in the user directory"""
+
social_links: List[AccountSocialLink]
+ status: Optional[str] = None
+ """Whether the account can operate on Whop: active or suspended.
+
+ Only computed on retrieve and me; null otherwise
+ """
+
+ store_page_config: object
+ """Store page display configuration for the account"""
+
target_audience: Optional[str] = None
"""The target audience for this account"""
title: str
"""The display name of the account"""
- wallet: Optional[AccountWallet] = None
+ total_earned_usd: Optional[float] = None
+ """Lifetime sales for the account, normalized to USD.
+
+ Only computed on retrieve and me for callers with the stats:read scope; null
+ otherwise
+ """
+
+ total_usd: Optional[str] = None
+ """Total USD value across all balances with a known exchange rate.
+
+ Only computed on single-account reads (retrieve and me); null (with an empty
+ balances array) on list responses, on writes, when the caller's token lacks the
+ balance-read permission, and when the balance source is unavailable
+ """
+
+ use_logo_as_opengraph_image_fallback: bool
+ """Whether the account uses its logo as the fallback Open Graph image"""
+
+ verification: object
+ """The account's identity-verification status.
+
+ `individual` is KYC, `business` is KYB; each is null when that profile has not
+ been created, otherwise { status } where status is one of not_started, pending,
+ approved, rejected
+ """
+
+ wallet: Optional[Wallet] = None
"""The account's primary crypto wallet, or null if none has been provisioned"""
diff --git a/src/whop_sdk/types/account_list_params.py b/src/whop_sdk/types/account_list_params.py
index 3462edca..92d86bd4 100644
--- a/src/whop_sdk/types/account_list_params.py
+++ b/src/whop_sdk/types/account_list_params.py
@@ -8,11 +8,14 @@
class AccountListParams(TypedDict, total=False):
- page: int
- """The page number to retrieve"""
+ after: str
+ """A cursor; returns accounts after this position."""
- per: int
- """The number of resources to return per page.
+ before: str
+ """A cursor; returns accounts before this position."""
- There is a limit of 50 results per page.
- """
+ first: int
+ """The number of accounts to return (default 10, max 50)."""
+
+ last: int
+ """The number of accounts to return from the end of the range."""
diff --git a/src/whop_sdk/types/account_list_response.py b/src/whop_sdk/types/account_list_response.py
deleted file mode 100644
index d4250efb..00000000
--- a/src/whop_sdk/types/account_list_response.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from .account import Account
-from .._models import BaseModel
-
-__all__ = ["AccountListResponse", "Pagination"]
-
-
-class Pagination(BaseModel):
- current_page: float
- """Current page number"""
-
- next_page: Optional[float] = None
- """Next page number"""
-
- prev_page: Optional[float] = None
- """Previous page number"""
-
- total_count: float
- """Total number of records"""
-
- total_pages: float
- """Total number of pages"""
-
-
-class AccountListResponse(BaseModel):
- accounts: List[Account]
-
- pagination: Pagination
diff --git a/src/whop_sdk/types/account_update_params.py b/src/whop_sdk/types/account_update_params.py
index 1efb814c..f5014c18 100644
--- a/src/whop_sdk/types/account_update_params.py
+++ b/src/whop_sdk/types/account_update_params.py
@@ -5,6 +5,8 @@
from typing import Dict, Iterable, Optional
from typing_extensions import TypedDict
+from .._types import SequenceNotStr
+
__all__ = ["AccountUpdateParams"]
@@ -24,35 +26,80 @@ class AccountUpdateParams(TypedDict, total=False):
business_type: Optional[str]
"""The high-level business category for the account."""
+ country: Optional[str]
+ """The country the account is located in."""
+
description: Optional[str]
"""A promotional description for the account."""
featured_affiliate_product_id: Optional[str]
"""The ID of the product to feature for affiliates. Pass null to clear."""
+ home_preferences: SequenceNotStr[str]
+ """Preferences for the public business home page."""
+
industry_group: Optional[str]
"""The industry group the account belongs to."""
industry_type: Optional[str]
"""The specific industry vertical the account operates in."""
+ invoice_prefix: Optional[str]
+ """The prefix to use for account invoices."""
+
logo: Optional[Dict[str, object]]
"""Attachment input for the account logo."""
metadata: Dict[str, object]
"""Arbitrary key/value metadata to store on the account."""
+ onboarding_type: Optional[str]
+ """The type of onboarding the account has completed."""
+
+ opengraph_image: Optional[Dict[str, object]]
+ """Attachment input for the account Open Graph image."""
+
+ opengraph_image_variant: Optional[str]
+ """The account Open Graph image variant."""
+
+ other_business_description: Optional[str]
+ """The description of the business type when business_type is other."""
+
+ other_industry_description: Optional[str]
+ """The description of the industry type when industry_type is other."""
+
+ require_2fa: bool
+ """
+ Whether the account requires authorized users to have two-factor authentication
+ enabled.
+ """
+
route: Optional[str]
"""The unique URL slug for the account."""
send_customer_emails: bool
"""Whether Whop sends transactional emails to customers on behalf of this account."""
+ show_joined_whops: bool
+ """Whether the account appears in joined whops on other accounts."""
+
+ show_reviews_dtc: bool
+ """Whether reviews are displayed on direct-to-consumer product pages."""
+
+ show_user_directory: bool
+ """Whether the account shows users in the user directory."""
+
social_links: Iterable[Dict[str, object]]
"""The full list of social links to display for the account."""
+ store_page_config: Optional[Dict[str, object]]
+ """Store page display configuration for the account."""
+
target_audience: Optional[str]
"""The target audience for this account."""
title: Optional[str]
"""The display name of the account."""
+
+ use_logo_as_opengraph_image_fallback: bool
+ """Whether the account uses its logo as the fallback Open Graph image."""
diff --git a/src/whop_sdk/types/account_wallet.py b/src/whop_sdk/types/account_wallet.py
deleted file mode 100644
index 0f32e70d..00000000
--- a/src/whop_sdk/types/account_wallet.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal
-
-from .._models import BaseModel
-
-__all__ = ["AccountWallet"]
-
-
-class AccountWallet(BaseModel):
- id: str
- """The ID of the wallet, which will look like wallet\\__******\\********"""
-
- address: str
- """The on-chain address of the wallet"""
-
- network: Literal["solana", "ethereum", "bitcoin"]
- """The blockchain network the wallet lives on"""
diff --git a/src/whop_sdk/types/ad.py b/src/whop_sdk/types/ad.py
index e2a1a0bd..9c405ea6 100644
--- a/src/whop_sdk/types/ad.py
+++ b/src/whop_sdk/types/ad.py
@@ -1,13 +1,15 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
+from .shared.currency import Currency
from .external_ad_status import ExternalAdStatus
from .ad_campaign_platform import AdCampaignPlatform
-__all__ = ["Ad", "AdCampaign", "AdGroup"]
+__all__ = ["Ad", "AdCampaign", "AdGroup", "Issue"]
class AdCampaign(BaseModel):
@@ -24,6 +26,37 @@ class AdGroup(BaseModel):
"""The unique identifier for this ad group."""
+class Issue(BaseModel):
+ """A platform-reported issue on an ad object (rejection, policy flag, etc.)."""
+
+ category: Optional[Literal["policy_rejection", "creative_media", "audience_targeting", "ad_volume_limit"]] = None
+ """Whop's canonical category that a raw platform issue is bucketed into."""
+
+ created_at: datetime
+ """When the issue was first reported."""
+
+ resolution_status: Literal["open", "resolved", "acknowledged"]
+ """Current resolution status."""
+
+ resource_id: Optional[str] = None
+ """The Whop ID of the ad object this issue is on (the ad, ad group, or campaign).
+
+ Null when the issue isn't tied to a local object.
+ """
+
+ resource_type: str
+ """The kind of ad object this issue is on: `ad`, `ad_group`, or `ad_campaign`.
+
+ Pairs with `resourceId`.
+ """
+
+ subtype: Optional[str] = None
+ """Finer-grained sub-bucket within the category (e.g.
+
+ the specific Meta policy for a rejection).
+ """
+
+
class Ad(BaseModel):
"""An ad belonging to an ad group."""
@@ -36,17 +69,101 @@ class Ad(BaseModel):
ad_group: AdGroup
"""The parent ad group this ad belongs to."""
+ click_through_rate: float
+ """Click-through rate as a fraction of impressions (clicks / impressions, 0–1)."""
+
+ clicks: int
+ """Total clicks on this ad in the stats window."""
+
+ cost_per_click: float
+ """Cost per click in dollars (spend / clicks). 0 when there are no clicks."""
+
+ cost_per_lead: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed lead (spend / leads).
+
+ 0 when leads are tracked but none happened yet; null when leads are not a goal
+ and none were attributed.
+ """
+
+ cost_per_mille: float
+ """Cost per 1,000 impressions in dollars (spend / impressions × 1000).
+
+ 0 when there are no impressions.
+ """
+
+ cost_per_purchase: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed purchase (spend / purchases).
+
+ 0 when purchases are tracked but none happened yet; null when purchases are not
+ a goal and none were attributed.
+ """
+
+ cost_per_result: Optional[float] = None
+ """Cost in dollars per optimization result (spend / results).
+
+ 0 when a result is being optimized for but none happened yet; null when nothing
+ is being optimized for.
+ """
+
created_at: datetime
"""When the ad was created."""
+ frequency: Optional[float] = None
+ """
+ Average number of times each person saw an ad (impressions / reach), as reported
+ by the platform.
+ """
+
+ impressions: int
+ """Total impressions (views) on this ad in the stats window."""
+
+ issues: List[Issue]
+ """Open platform issues affecting this ad, deduplicated per object.
+
+ Empty when there are none.
+ """
+
+ leads: int
+ """Number of Whop pixel-attributed leads (last-click) in the stats window."""
+
platform: AdCampaignPlatform
"""The external ad platform this ad is running on (e.g., meta, tiktok)."""
+ purchase_value: float
+ """Total USD value of Whop pixel-attributed purchases in the stats window."""
+
+ purchases: int
+ """Number of Whop pixel-attributed purchases (last-click) in the stats window."""
+
+ reach: int
+ """Unique users reached in the stats window (deduplicated by the platform)."""
+
+ return_on_ad_spend: float
+ """
+ Return on ad spend as a ratio (purchaseValue / spend) — 2.5 means $2.50 of
+ attributed purchase value per $1 spent. 0 when there is no spend.
+ """
+
+ spend: float
+ """Amount charged in dollars in the stats window."""
+
+ spend_currency: Optional[Currency] = None
+ """The available currencies on the platform"""
+
status: ExternalAdStatus
"""Current delivery status of the ad."""
title: Optional[str] = None
"""The display title of the ad. Falls back to the creative set caption when unset."""
+ unique_click_through_rate: Optional[float] = None
+ """
+ Unique click-through rate as a fraction of impressions (unique clicks /
+ impressions, 0–1).
+ """
+
+ unique_clicks: int
+ """Unique clicks (deduplicated by the platform) in the stats window."""
+
updated_at: datetime
"""When the ad was last updated."""
diff --git a/src/whop_sdk/types/ad_campaign.py b/src/whop_sdk/types/ad_campaign.py
index 6d201157..80f875e1 100644
--- a/src/whop_sdk/types/ad_campaign.py
+++ b/src/whop_sdk/types/ad_campaign.py
@@ -6,66 +6,42 @@
from .._models import BaseModel
from .ad_budget_type import AdBudgetType
+from .shared.currency import Currency
from .ad_campaign_status import AdCampaignStatus
from .ad_campaign_platform import AdCampaignPlatform
-__all__ = ["AdCampaign", "CreatedByUser", "MetaConfig"]
+__all__ = ["AdCampaign", "Issue"]
-class CreatedByUser(BaseModel):
- """The user who created this ad campaign."""
+class Issue(BaseModel):
+ """A platform-reported issue on an ad object (rejection, policy flag, etc.)."""
- id: str
- """The unique identifier for the user."""
-
- name: Optional[str] = None
- """The user's display name shown on their public profile."""
+ category: Optional[Literal["policy_rejection", "creative_media", "audience_targeting", "ad_volume_limit"]] = None
+ """Whop's canonical category that a raw platform issue is bucketed into."""
- username: str
- """The user's unique username shown on their public profile."""
+ created_at: datetime
+ """When the issue was first reported."""
+ resolution_status: Literal["open", "resolved", "acknowledged"]
+ """Current resolution status."""
-class MetaConfig(BaseModel):
- """Meta-specific campaign configuration (objective, budget mode, etc.).
+ resource_id: Optional[str] = None
+ """The Whop ID of the ad object this issue is on (the ad, ad group, or campaign).
- Null for non-Meta campaigns.
+ Null when the issue isn't tied to a local object.
"""
- bid_amount: Optional[int] = None
- """Bid cap amount in cents. Only used when bid_strategy is bid_cap."""
+ resource_type: str
+ """The kind of ad object this issue is on: `ad`, `ad_group`, or `ad_campaign`.
- bid_strategy: Optional[Literal["lowest_cost", "bid_cap", "cost_cap"]] = None
- """The bidding strategy used to optimize spend for this campaign."""
-
- budget_optimization: Optional[bool] = None
- """
- Whether campaign budget optimization (CBO) is enabled, allowing the platform to
- distribute budget across ad groups.
+ Pairs with `resourceId`.
"""
- effective_status: Optional[Literal["active", "paused", "deleted", "in_review", "rejected", "with_issues"]] = None
- """
- The actual delivery status, accounting for platform overrides (e.g., in_review,
- rejected).
- """
-
- end_time: Optional[str] = None
- """The scheduled end time of the campaign (ISO8601)."""
-
- objective: Optional[Literal["awareness", "traffic", "engagement", "leads", "sales"]] = None
- """The campaign objective that determines how Meta optimizes delivery."""
+ subtype: Optional[str] = None
+ """Finer-grained sub-bucket within the category (e.g.
- special_categories: Optional[List[str]] = None
+ the specific Meta policy for a rejection).
"""
- Special ad categories required by the platform (e.g., housing, employment,
- credit).
- """
-
- start_time: Optional[str] = None
- """The scheduled start time of the campaign (ISO8601)."""
-
- status: Optional[Literal["active", "paused"]] = None
- """The campaign status as set by the advertiser (active or paused)."""
class AdCampaign(BaseModel):
@@ -80,29 +56,101 @@ class AdCampaign(BaseModel):
budget_type: Optional[AdBudgetType] = None
"""The budget type for an ad campaign or ad group."""
+ click_through_rate: float
+ """Click-through rate as a fraction of impressions (clicks / impressions, 0–1)."""
+
+ clicks: int
+ """Total clicks on the campaign's ads in the stats window."""
+
+ cost_per_click: float
+ """Cost per click in dollars (spend / clicks). 0 when there are no clicks."""
+
+ cost_per_lead: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed lead (spend / leads).
+
+ 0 when leads are tracked but none happened yet; null when leads are not a goal
+ and none were attributed.
+ """
+
+ cost_per_mille: float
+ """Cost per 1,000 impressions in dollars (spend / impressions × 1000).
+
+ 0 when there are no impressions.
+ """
+
+ cost_per_purchase: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed purchase (spend / purchases).
+
+ 0 when purchases are tracked but none happened yet; null when purchases are not
+ a goal and none were attributed.
+ """
+
+ cost_per_result: Optional[float] = None
+ """Cost in dollars per optimization result (spend / results).
+
+ 0 when a result is being optimized for but none happened yet; null when nothing
+ is being optimized for.
+ """
+
created_at: datetime
"""When the ad campaign was created."""
- created_by_user: CreatedByUser
- """The user who created this ad campaign."""
+ frequency: Optional[float] = None
+ """
+ Average number of times each person saw an ad (impressions / reach), as reported
+ by the platform.
+ """
- meta_config: Optional[MetaConfig] = None
- """Meta-specific campaign configuration (objective, budget mode, etc.).
+ impressions: int
+ """Total impressions (views) on the campaign's ads in the stats window."""
- Null for non-Meta campaigns.
+ issues: List[Issue]
+ """
+ Open platform issues affecting this campaign and its descendant ad groups and
+ ads, deduplicated per object. Empty when there are none.
"""
+ leads: int
+ """Number of Whop pixel-attributed leads (last-click) in the stats window."""
+
platform: AdCampaignPlatform
"""The external ad platform this campaign is running on (e.g., meta, tiktok)."""
+ purchase_value: float
+ """Total USD value of Whop pixel-attributed purchases in the stats window."""
+
+ purchases: int
+ """Number of Whop pixel-attributed purchases (last-click) in the stats window."""
+
+ reach: int
+ """Unique users reached in the stats window (deduplicated by the platform)."""
+
+ return_on_ad_spend: float
+ """
+ Return on ad spend as a ratio (purchaseValue / spend) — 2.5 means $2.50 of
+ attributed purchase value per $1 spent. 0 when there is no spend.
+ """
+
+ spend: float
+ """Amount charged in dollars in the stats window."""
+
+ spend_currency: Optional[Currency] = None
+ """The available currencies on the platform"""
+
status: AdCampaignStatus
- """Current status of the campaign (active, paused, or inactive)."""
+ """Current status of the campaign."""
title: str
"""The campaign name shown in the Whop dashboard."""
- total_spend: float
- """Total amount spent in dollars."""
+ unique_click_through_rate: Optional[float] = None
+ """
+ Unique click-through rate as a fraction of impressions (unique clicks /
+ impressions, 0–1).
+ """
+
+ unique_clicks: int
+ """Unique clicks (deduplicated by the platform) in the stats window."""
updated_at: datetime
"""When the ad campaign was last updated."""
diff --git a/src/whop_sdk/types/ad_campaign_list_params.py b/src/whop_sdk/types/ad_campaign_list_params.py
index ab696839..526ecf84 100644
--- a/src/whop_sdk/types/ad_campaign_list_params.py
+++ b/src/whop_sdk/types/ad_campaign_list_params.py
@@ -4,9 +4,10 @@
from typing import Union, Optional
from datetime import datetime
-from typing_extensions import Annotated, TypedDict
+from typing_extensions import Literal, Annotated, TypedDict
from .._utils import PropertyInfo
+from .shared.direction import Direction
from .ad_campaign_status import AdCampaignStatus
__all__ = ["AdCampaignListParams"]
@@ -28,14 +29,51 @@ class AdCampaignListParams(TypedDict, total=False):
created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""Only return ad campaigns created before this timestamp."""
+ 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[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ """The fields the ads dashboard lists (campaigns, ad sets) can be ordered by.
+
+ Stat columns are computed over the provided stats date range.
+ """
+
query: Optional[str]
- """Case-insensitive substring match against the campaign title."""
+ """Case-insensitive substring match against the campaign title or ID."""
+
+ stats_from: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """
+ Inclusive start of the window for each campaign's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+ """
+
+ stats_to: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """Inclusive end of the window for each campaign's metric fields.
+
+ Omit both statsFrom and statsTo for all-time stats.
+ """
status: Optional[AdCampaignStatus]
"""The status of an ad campaign."""
diff --git a/src/whop_sdk/types/ad_campaign_list_response.py b/src/whop_sdk/types/ad_campaign_list_response.py
index 7123408d..731878bf 100644
--- a/src/whop_sdk/types/ad_campaign_list_response.py
+++ b/src/whop_sdk/types/ad_campaign_list_response.py
@@ -1,14 +1,47 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
from .ad_budget_type import AdBudgetType
+from .shared.currency import Currency
from .ad_campaign_status import AdCampaignStatus
from .ad_campaign_platform import AdCampaignPlatform
-__all__ = ["AdCampaignListResponse"]
+__all__ = ["AdCampaignListResponse", "Issue"]
+
+
+class Issue(BaseModel):
+ """A platform-reported issue on an ad object (rejection, policy flag, etc.)."""
+
+ category: Optional[Literal["policy_rejection", "creative_media", "audience_targeting", "ad_volume_limit"]] = None
+ """Whop's canonical category that a raw platform issue is bucketed into."""
+
+ created_at: datetime
+ """When the issue was first reported."""
+
+ resolution_status: Literal["open", "resolved", "acknowledged"]
+ """Current resolution status."""
+
+ resource_id: Optional[str] = None
+ """The Whop ID of the ad object this issue is on (the ad, ad group, or campaign).
+
+ Null when the issue isn't tied to a local object.
+ """
+
+ resource_type: str
+ """The kind of ad object this issue is on: `ad`, `ad_group`, or `ad_campaign`.
+
+ Pairs with `resourceId`.
+ """
+
+ subtype: Optional[str] = None
+ """Finer-grained sub-bucket within the category (e.g.
+
+ the specific Meta policy for a rejection).
+ """
class AdCampaignListResponse(BaseModel):
@@ -23,20 +56,101 @@ class AdCampaignListResponse(BaseModel):
budget_type: Optional[AdBudgetType] = None
"""The budget type for an ad campaign or ad group."""
+ click_through_rate: float
+ """Click-through rate as a fraction of impressions (clicks / impressions, 0–1)."""
+
+ clicks: int
+ """Total clicks on the campaign's ads in the stats window."""
+
+ cost_per_click: float
+ """Cost per click in dollars (spend / clicks). 0 when there are no clicks."""
+
+ cost_per_lead: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed lead (spend / leads).
+
+ 0 when leads are tracked but none happened yet; null when leads are not a goal
+ and none were attributed.
+ """
+
+ cost_per_mille: float
+ """Cost per 1,000 impressions in dollars (spend / impressions × 1000).
+
+ 0 when there are no impressions.
+ """
+
+ cost_per_purchase: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed purchase (spend / purchases).
+
+ 0 when purchases are tracked but none happened yet; null when purchases are not
+ a goal and none were attributed.
+ """
+
+ cost_per_result: Optional[float] = None
+ """Cost in dollars per optimization result (spend / results).
+
+ 0 when a result is being optimized for but none happened yet; null when nothing
+ is being optimized for.
+ """
+
created_at: datetime
"""When the ad campaign was created."""
+ frequency: Optional[float] = None
+ """
+ Average number of times each person saw an ad (impressions / reach), as reported
+ by the platform.
+ """
+
+ impressions: int
+ """Total impressions (views) on the campaign's ads in the stats window."""
+
+ issues: List[Issue]
+ """
+ Open platform issues affecting this campaign and its descendant ad groups and
+ ads, deduplicated per object. Empty when there are none.
+ """
+
+ leads: int
+ """Number of Whop pixel-attributed leads (last-click) in the stats window."""
+
platform: AdCampaignPlatform
"""The external ad platform this campaign is running on (e.g., meta, tiktok)."""
+ purchase_value: float
+ """Total USD value of Whop pixel-attributed purchases in the stats window."""
+
+ purchases: int
+ """Number of Whop pixel-attributed purchases (last-click) in the stats window."""
+
+ reach: int
+ """Unique users reached in the stats window (deduplicated by the platform)."""
+
+ return_on_ad_spend: float
+ """
+ Return on ad spend as a ratio (purchaseValue / spend) — 2.5 means $2.50 of
+ attributed purchase value per $1 spent. 0 when there is no spend.
+ """
+
+ spend: float
+ """Amount charged in dollars in the stats window."""
+
+ spend_currency: Optional[Currency] = None
+ """The available currencies on the platform"""
+
status: AdCampaignStatus
- """Current status of the campaign (active, paused, or inactive)."""
+ """Current status of the campaign."""
title: str
"""The campaign name shown in the Whop dashboard."""
- total_spend: float
- """Total amount spent in dollars."""
+ unique_click_through_rate: Optional[float] = None
+ """
+ Unique click-through rate as a fraction of impressions (unique clicks /
+ impressions, 0–1).
+ """
+
+ unique_clicks: int
+ """Unique clicks (deduplicated by the platform) in the stats window."""
updated_at: datetime
"""When the ad campaign was last updated."""
diff --git a/src/whop_sdk/types/ad_campaign_retrieve_params.py b/src/whop_sdk/types/ad_campaign_retrieve_params.py
new file mode 100644
index 00000000..4bd49c3b
--- /dev/null
+++ b/src/whop_sdk/types/ad_campaign_retrieve_params.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["AdCampaignRetrieveParams"]
+
+
+class AdCampaignRetrieveParams(TypedDict, total=False):
+ stats_from: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """
+ Inclusive start of the window for the campaign's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+ """
+
+ stats_to: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """Inclusive end of the window for the campaign's metric fields.
+
+ Omit both statsFrom and statsTo for all-time stats.
+ """
diff --git a/src/whop_sdk/types/ad_campaign_update_params.py b/src/whop_sdk/types/ad_campaign_update_params.py
index 7c476aea..63afb37f 100644
--- a/src/whop_sdk/types/ad_campaign_update_params.py
+++ b/src/whop_sdk/types/ad_campaign_update_params.py
@@ -15,3 +15,6 @@ class AdCampaignUpdateParams(TypedDict, total=False):
The interpretation (daily or lifetime) follows the campaign's existing budget
type.
"""
+
+ desired_cpr: Optional[float]
+ """The advertiser's desired cost per result in dollars."""
diff --git a/src/whop_sdk/types/ad_group.py b/src/whop_sdk/types/ad_group.py
index 384dbf5f..de67e0bb 100644
--- a/src/whop_sdk/types/ad_group.py
+++ b/src/whop_sdk/types/ad_group.py
@@ -1,14 +1,16 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
from .ad_budget_type import AdBudgetType
from .ad_group_status import AdGroupStatus
+from .shared.currency import Currency
from .ad_campaign_platform import AdCampaignPlatform
-__all__ = ["AdGroup", "AdCampaign"]
+__all__ = ["AdGroup", "AdCampaign", "Issue"]
class AdCampaign(BaseModel):
@@ -18,8 +20,39 @@ class AdCampaign(BaseModel):
"""The unique identifier for this ad campaign."""
+class Issue(BaseModel):
+ """A platform-reported issue on an ad object (rejection, policy flag, etc.)."""
+
+ category: Optional[Literal["policy_rejection", "creative_media", "audience_targeting", "ad_volume_limit"]] = None
+ """Whop's canonical category that a raw platform issue is bucketed into."""
+
+ created_at: datetime
+ """When the issue was first reported."""
+
+ resolution_status: Literal["open", "resolved", "acknowledged"]
+ """Current resolution status."""
+
+ resource_id: Optional[str] = None
+ """The Whop ID of the ad object this issue is on (the ad, ad group, or campaign).
+
+ Null when the issue isn't tied to a local object.
+ """
+
+ resource_type: str
+ """The kind of ad object this issue is on: `ad`, `ad_group`, or `ad_campaign`.
+
+ Pairs with `resourceId`.
+ """
+
+ subtype: Optional[str] = None
+ """Finer-grained sub-bucket within the category (e.g.
+
+ the specific Meta policy for a rejection).
+ """
+
+
class AdGroup(BaseModel):
- """An ad group (ad set) belonging to an ad campaign."""
+ """An ad group belonging to an ad campaign."""
id: str
"""The unique identifier for this ad group."""
@@ -33,17 +66,101 @@ class AdGroup(BaseModel):
budget_type: Optional[AdBudgetType] = None
"""The budget type for an ad campaign or ad group."""
+ click_through_rate: float
+ """Click-through rate as a fraction of impressions (clicks / impressions, 0–1)."""
+
+ clicks: int
+ """Total clicks on this ad group's ads in the stats window."""
+
+ cost_per_click: float
+ """Cost per click in dollars (spend / clicks). 0 when there are no clicks."""
+
+ cost_per_lead: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed lead (spend / leads).
+
+ 0 when leads are tracked but none happened yet; null when leads are not a goal
+ and none were attributed.
+ """
+
+ cost_per_mille: float
+ """Cost per 1,000 impressions in dollars (spend / impressions × 1000).
+
+ 0 when there are no impressions.
+ """
+
+ cost_per_purchase: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed purchase (spend / purchases).
+
+ 0 when purchases are tracked but none happened yet; null when purchases are not
+ a goal and none were attributed.
+ """
+
+ cost_per_result: Optional[float] = None
+ """Cost in dollars per optimization result (spend / results).
+
+ 0 when a result is being optimized for but none happened yet; null when nothing
+ is being optimized for.
+ """
+
created_at: datetime
"""When the ad group was created."""
+ frequency: Optional[float] = None
+ """
+ Average number of times each person saw an ad (impressions / reach), as reported
+ by the platform.
+ """
+
+ impressions: int
+ """Total impressions (views) on this ad group's ads in the stats window."""
+
+ issues: List[Issue]
+ """
+ Open platform issues affecting this ad group and its descendant ads,
+ deduplicated per object. Empty when there are none.
+ """
+
+ leads: int
+ """Number of Whop pixel-attributed leads (last-click) in the stats window."""
+
platform: AdCampaignPlatform
"""The external ad platform this ad group is running on (e.g., meta, tiktok)."""
+ purchase_value: float
+ """Total USD value of Whop pixel-attributed purchases in the stats window."""
+
+ purchases: int
+ """Number of Whop pixel-attributed purchases (last-click) in the stats window."""
+
+ reach: int
+ """Unique users reached in the stats window (deduplicated by the platform)."""
+
+ return_on_ad_spend: float
+ """
+ Return on ad spend as a ratio (purchaseValue / spend) — 2.5 means $2.50 of
+ attributed purchase value per $1 spent. 0 when there is no spend.
+ """
+
+ spend: float
+ """Amount charged in dollars in the stats window."""
+
+ spend_currency: Optional[Currency] = None
+ """The available currencies on the platform"""
+
status: AdGroupStatus
"""Current operational status of the ad group."""
title: Optional[str] = None
- """Human-readable name shown on the external platform."""
+ """The ad group name shown in the Whop dashboard."""
+
+ unique_click_through_rate: Optional[float] = None
+ """
+ Unique click-through rate as a fraction of impressions (unique clicks /
+ impressions, 0–1).
+ """
+
+ unique_clicks: int
+ """Unique clicks (deduplicated by the platform) in the stats window."""
updated_at: datetime
"""When the ad group was last updated."""
diff --git a/src/whop_sdk/types/ad_group_list_params.py b/src/whop_sdk/types/ad_group_list_params.py
index 9bda52fb..9ddc929c 100644
--- a/src/whop_sdk/types/ad_group_list_params.py
+++ b/src/whop_sdk/types/ad_group_list_params.py
@@ -4,15 +4,26 @@
from typing import Union, Optional
from datetime import datetime
-from typing_extensions import Annotated, TypedDict
+from typing_extensions import Literal, Annotated, TypedDict
+from .._types import SequenceNotStr
from .._utils import PropertyInfo
from .ad_group_status import AdGroupStatus
+from .shared.direction import Direction
__all__ = ["AdGroupListParams"]
class AdGroupListParams(TypedDict, total=False):
+ ad_campaign_id: Optional[str]
+ """Filter by ad campaign. Provide exactly one of ad_campaign_id or company_id."""
+
+ ad_campaign_ids: Optional[SequenceNotStr[str]]
+ """Only return ad groups belonging to these ad campaigns (max 100).
+
+ Can be combined with companyId or used on its own.
+ """
+
after: Optional[str]
"""Returns the elements in the list that come after the specified cursor."""
@@ -20,10 +31,10 @@ class AdGroupListParams(TypedDict, total=False):
"""Returns the elements in the list that come before the specified cursor."""
campaign_id: Optional[str]
- """Filter by campaign. Provide exactly one of campaign_id or company_id."""
+ """Filter by campaign."""
company_id: Optional[str]
- """Filter by company. Provide exactly one of campaign_id or company_id."""
+ """Filter by company. Provide companyId or adCampaignIds."""
created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""Only return ad groups created after this timestamp."""
@@ -31,20 +42,51 @@ class AdGroupListParams(TypedDict, total=False):
created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""Only return ad groups created before this timestamp."""
+ direction: Optional[Direction]
+ """The direction of the sort."""
+
first: Optional[int]
"""Returns the first _n_ elements from the list."""
- include_paused: Optional[bool]
- """
- When false, excludes paused ad groups so pagination matches the dashboard's
- hide-paused toggle.
- """
-
last: Optional[int]
"""Returns the last _n_ elements from the list."""
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ """The fields the ads dashboard lists (campaigns, ad sets) can be ordered by.
+
+ Stat columns are computed over the provided stats date range.
+ """
+
query: Optional[str]
- """Case-insensitive substring match against the ad group name."""
+ """Case-insensitive substring match against the ad group name or ID."""
+
+ stats_from: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """
+ Inclusive start of the window for each ad group's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+ """
+
+ stats_to: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """Inclusive end of the window for each ad group's metric fields.
+
+ Omit both statsFrom and statsTo for all-time stats.
+ """
status: Optional[AdGroupStatus]
"""The status of an external ad group."""
diff --git a/src/whop_sdk/types/ad_group_list_response.py b/src/whop_sdk/types/ad_group_list_response.py
index dac01854..4345765a 100644
--- a/src/whop_sdk/types/ad_group_list_response.py
+++ b/src/whop_sdk/types/ad_group_list_response.py
@@ -1,14 +1,16 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
from .ad_budget_type import AdBudgetType
from .ad_group_status import AdGroupStatus
+from .shared.currency import Currency
from .ad_campaign_platform import AdCampaignPlatform
-__all__ = ["AdGroupListResponse", "AdCampaign"]
+__all__ = ["AdGroupListResponse", "AdCampaign", "Issue"]
class AdCampaign(BaseModel):
@@ -18,8 +20,39 @@ class AdCampaign(BaseModel):
"""The unique identifier for this ad campaign."""
+class Issue(BaseModel):
+ """A platform-reported issue on an ad object (rejection, policy flag, etc.)."""
+
+ category: Optional[Literal["policy_rejection", "creative_media", "audience_targeting", "ad_volume_limit"]] = None
+ """Whop's canonical category that a raw platform issue is bucketed into."""
+
+ created_at: datetime
+ """When the issue was first reported."""
+
+ resolution_status: Literal["open", "resolved", "acknowledged"]
+ """Current resolution status."""
+
+ resource_id: Optional[str] = None
+ """The Whop ID of the ad object this issue is on (the ad, ad group, or campaign).
+
+ Null when the issue isn't tied to a local object.
+ """
+
+ resource_type: str
+ """The kind of ad object this issue is on: `ad`, `ad_group`, or `ad_campaign`.
+
+ Pairs with `resourceId`.
+ """
+
+ subtype: Optional[str] = None
+ """Finer-grained sub-bucket within the category (e.g.
+
+ the specific Meta policy for a rejection).
+ """
+
+
class AdGroupListResponse(BaseModel):
- """An ad group (ad set) belonging to an ad campaign."""
+ """An ad group belonging to an ad campaign."""
id: str
"""The unique identifier for this ad group."""
@@ -33,17 +66,101 @@ class AdGroupListResponse(BaseModel):
budget_type: Optional[AdBudgetType] = None
"""The budget type for an ad campaign or ad group."""
+ click_through_rate: float
+ """Click-through rate as a fraction of impressions (clicks / impressions, 0–1)."""
+
+ clicks: int
+ """Total clicks on this ad group's ads in the stats window."""
+
+ cost_per_click: float
+ """Cost per click in dollars (spend / clicks). 0 when there are no clicks."""
+
+ cost_per_lead: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed lead (spend / leads).
+
+ 0 when leads are tracked but none happened yet; null when leads are not a goal
+ and none were attributed.
+ """
+
+ cost_per_mille: float
+ """Cost per 1,000 impressions in dollars (spend / impressions × 1000).
+
+ 0 when there are no impressions.
+ """
+
+ cost_per_purchase: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed purchase (spend / purchases).
+
+ 0 when purchases are tracked but none happened yet; null when purchases are not
+ a goal and none were attributed.
+ """
+
+ cost_per_result: Optional[float] = None
+ """Cost in dollars per optimization result (spend / results).
+
+ 0 when a result is being optimized for but none happened yet; null when nothing
+ is being optimized for.
+ """
+
created_at: datetime
"""When the ad group was created."""
+ frequency: Optional[float] = None
+ """
+ Average number of times each person saw an ad (impressions / reach), as reported
+ by the platform.
+ """
+
+ impressions: int
+ """Total impressions (views) on this ad group's ads in the stats window."""
+
+ issues: List[Issue]
+ """
+ Open platform issues affecting this ad group and its descendant ads,
+ deduplicated per object. Empty when there are none.
+ """
+
+ leads: int
+ """Number of Whop pixel-attributed leads (last-click) in the stats window."""
+
platform: AdCampaignPlatform
"""The external ad platform this ad group is running on (e.g., meta, tiktok)."""
+ purchase_value: float
+ """Total USD value of Whop pixel-attributed purchases in the stats window."""
+
+ purchases: int
+ """Number of Whop pixel-attributed purchases (last-click) in the stats window."""
+
+ reach: int
+ """Unique users reached in the stats window (deduplicated by the platform)."""
+
+ return_on_ad_spend: float
+ """
+ Return on ad spend as a ratio (purchaseValue / spend) — 2.5 means $2.50 of
+ attributed purchase value per $1 spent. 0 when there is no spend.
+ """
+
+ spend: float
+ """Amount charged in dollars in the stats window."""
+
+ spend_currency: Optional[Currency] = None
+ """The available currencies on the platform"""
+
status: AdGroupStatus
"""Current operational status of the ad group."""
title: Optional[str] = None
- """Human-readable name shown on the external platform."""
+ """The ad group name shown in the Whop dashboard."""
+
+ unique_click_through_rate: Optional[float] = None
+ """
+ Unique click-through rate as a fraction of impressions (unique clicks /
+ impressions, 0–1).
+ """
+
+ unique_clicks: int
+ """Unique clicks (deduplicated by the platform) in the stats window."""
updated_at: datetime
"""When the ad group was last updated."""
diff --git a/src/whop_sdk/types/ad_group_retrieve_params.py b/src/whop_sdk/types/ad_group_retrieve_params.py
new file mode 100644
index 00000000..54c57f2c
--- /dev/null
+++ b/src/whop_sdk/types/ad_group_retrieve_params.py
@@ -0,0 +1,25 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["AdGroupRetrieveParams"]
+
+
+class AdGroupRetrieveParams(TypedDict, total=False):
+ stats_from: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """
+ Inclusive start of the window for the ad group's metric fields (spend,
+ impressions, …). Omit both statsFrom and statsTo for all-time stats.
+ """
+
+ stats_to: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """Inclusive end of the window for the ad group's metric fields.
+
+ Omit both statsFrom and statsTo for all-time stats.
+ """
diff --git a/src/whop_sdk/types/ad_group_update_params.py b/src/whop_sdk/types/ad_group_update_params.py
index 97f6403e..71db1f9b 100644
--- a/src/whop_sdk/types/ad_group_update_params.py
+++ b/src/whop_sdk/types/ad_group_update_params.py
@@ -2,1220 +2,19 @@
from __future__ import annotations
-from typing import Dict, List, Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing import Optional
+from typing_extensions import TypedDict
-from .._types import SequenceNotStr
-from .ad_budget_type import AdBudgetType
-from .ad_group_status import AdGroupStatus
-
-__all__ = [
- "AdGroupUpdateParams",
- "Config",
- "ConfigTargeting",
- "PlatformConfig",
- "PlatformConfigMeta",
- "PlatformConfigMetaAttributionSpec",
- "PlatformConfigMetaExcludedGeoLocations",
- "PlatformConfigMetaExcludedGeoLocationsCity",
- "PlatformConfigMetaExcludedGeoLocationsRegion",
- "PlatformConfigMetaExcludedGeoLocationsZip",
- "PlatformConfigMetaGeoCity",
- "PlatformConfigMetaGeoLocations",
- "PlatformConfigMetaGeoLocationsCity",
- "PlatformConfigMetaGeoLocationsRegion",
- "PlatformConfigMetaGeoLocationsZip",
- "PlatformConfigMetaGeoRegion",
- "PlatformConfigMetaLeadFormConfig",
- "PlatformConfigMetaLeadFormConfigQuestion",
- "PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestion",
- "PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestionOption",
- "PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestionOptionLogic",
- "PlatformConfigMetaLeadFormConfigQuestionOption",
- "PlatformConfigMetaLeadFormConfigQuestionOptionLogic",
- "PlatformConfigMetaLeadFormConfigCustomDisclaimerCheckbox",
- "PlatformConfigMetaLeadFormConfigThankYouPage",
- "PlatformConfigMetaPromotedObject",
- "PlatformConfigMetaTargetingAutomation",
- "PlatformConfigTiktok",
- "PlatformConfigTiktokAction",
- "PlatformConfigTiktokInstantFormConfig",
- "PlatformConfigTiktokInstantFormConfigQuestion",
-]
+__all__ = ["AdGroupUpdateParams"]
class AdGroupUpdateParams(TypedDict, total=False):
budget: Optional[float]
- """Budget amount in dollars."""
-
- budget_type: Optional[AdBudgetType]
- """The budget type for an ad campaign or ad group."""
-
- config: Optional[Config]
- """Unified ad group configuration (bidding, optimization, targeting)."""
-
- daily_budget: Optional[float]
- """Daily budget in dollars."""
-
- name: Optional[str]
- """Human-readable ad group name."""
-
- platform_config: Optional[PlatformConfig]
- """Platform-specific ad group configuration."""
-
- status: Optional[AdGroupStatus]
- """The status of an external ad group."""
-
-
-class ConfigTargeting(TypedDict, total=False):
- """Audience targeting settings (demographics, geo, interests, audiences, devices)."""
-
- age_max: Optional[int]
- """Maximum age for demographic targeting."""
-
- age_min: Optional[int]
- """Minimum age for demographic targeting."""
-
- countries: Optional[SequenceNotStr[str]]
- """ISO 3166-1 alpha-2 country codes to target."""
-
- device_platforms: Optional[List[Literal["mobile", "desktop"]]]
- """Device platforms to target."""
-
- exclude_audience_ids: Optional[SequenceNotStr[str]]
- """Platform audience IDs to exclude."""
-
- genders: Optional[List[Literal["male", "female", "all"]]]
- """Genders to target."""
-
- include_audience_ids: Optional[SequenceNotStr[str]]
- """Platform audience IDs to include."""
-
- interest_ids: Optional[SequenceNotStr[str]]
- """Platform-specific interest IDs to target."""
-
- languages: Optional[SequenceNotStr[str]]
- """Language codes to target."""
-
- placement_type: Optional[Literal["automatic", "manual"]]
- """Placement strategy for ad delivery."""
-
-
-class Config(TypedDict, total=False):
- """Unified ad group configuration (bidding, optimization, targeting)."""
-
- bid_amount: Optional[int]
- """Bid cap amount in cents. Used when bid_strategy is bid_cap or cost_cap."""
-
- bid_strategy: Optional[Literal["lowest_cost", "bid_cap", "cost_cap"]]
- """Bid strategy: lowest_cost, bid_cap, or cost_cap."""
-
- billing_event: Optional[Literal["impressions", "clicks", "optimized_cpm", "video_views"]]
- """How you are billed (e.g., impressions, clicks)."""
-
- end_time: Optional[str]
- """Scheduled end time (ISO8601). Required for lifetime budgets."""
-
- frequency_cap: Optional[int]
- """Maximum number of times to show ads to each person in the frequency interval."""
-
- frequency_cap_interval_days: Optional[int]
- """Number of days for the frequency cap interval."""
-
- optimization_goal: Optional[
- Literal[
- "conversions",
- "link_clicks",
- "landing_page_views",
- "reach",
- "impressions",
- "app_installs",
- "video_views",
- "lead_generation",
- "value",
- "page_likes",
- "conversations",
- "ad_recall_lift",
- "two_second_continuous_video_views",
- "post_engagement",
- "event_responses",
- "reminders_set",
- "quality_lead",
- ]
- ]
- """What the ad group optimizes for (e.g., conversions, link_clicks, reach)."""
-
- pacing: Optional[Literal["standard", "accelerated"]]
- """Budget pacing: standard (even) or accelerated (fast)."""
-
- start_time: Optional[str]
- """Scheduled start time (ISO8601)."""
-
- targeting: Optional[ConfigTargeting]
- """Audience targeting settings (demographics, geo, interests, audiences, devices)."""
-
-
-class PlatformConfigMetaAttributionSpec(TypedDict, total=False):
- """Meta conversion attribution window."""
-
- event_type: Required[str]
- """Attribution event type (e.g., CLICK_THROUGH, VIEW_THROUGH)."""
-
- window_days: Required[int]
- """Attribution window in days (1, 7, 28)."""
-
-
-class PlatformConfigMetaExcludedGeoLocationsCity(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaExcludedGeoLocationsRegion(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaExcludedGeoLocationsZip(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaExcludedGeoLocations(TypedDict, total=False):
- """Geo locations to exclude."""
-
- cities: Optional[Iterable[PlatformConfigMetaExcludedGeoLocationsCity]]
- """City targets."""
-
- countries: Optional[SequenceNotStr[str]]
- """ISO 3166-1 alpha-2 country codes."""
-
- location_types: Optional[SequenceNotStr[str]]
- """Location types (home, recent, travel_in)."""
-
- regions: Optional[Iterable[PlatformConfigMetaExcludedGeoLocationsRegion]]
- """Region/state targets."""
-
- zips: Optional[Iterable[PlatformConfigMetaExcludedGeoLocationsZip]]
- """Zip/postal code targets."""
-
-
-class PlatformConfigMetaGeoCity(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaGeoLocationsCity(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaGeoLocationsRegion(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaGeoLocationsZip(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaGeoLocations(TypedDict, total=False):
- """Geo targeting (countries, regions, cities, zips)."""
-
- cities: Optional[Iterable[PlatformConfigMetaGeoLocationsCity]]
- """City targets."""
-
- countries: Optional[SequenceNotStr[str]]
- """ISO 3166-1 alpha-2 country codes."""
-
- location_types: Optional[SequenceNotStr[str]]
- """Location types (home, recent, travel_in)."""
-
- regions: Optional[Iterable[PlatformConfigMetaGeoLocationsRegion]]
- """Region/state targets."""
-
- zips: Optional[Iterable[PlatformConfigMetaGeoLocationsZip]]
- """Zip/postal code targets."""
-
-
-class PlatformConfigMetaGeoRegion(TypedDict, total=False):
- """A Meta geo target entry (region, city, or zip)."""
-
- key: Required[str]
- """Meta geo target key/ID."""
-
- country: Optional[str]
- """Country code for this entry."""
-
- name: Optional[str]
- """Display name."""
-
- radius: Optional[int]
- """Radius in miles (cities only)."""
-
-
-class PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestionOptionLogic(TypedDict, total=False):
- """Conditional logic routing for this answer option."""
-
- type: Required[str]
- """Logic type: go_to_question, submit_form, or close_form."""
-
- target_end_page_index: Optional[int]
- """Index of the end page to route to (for submit_form type)."""
-
- target_question_index: Optional[int]
- """Index of the question to route to (for go_to_question type)."""
-
-
-class PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestionOption(TypedDict, total=False):
- """An answer option for a multiple choice lead form question."""
-
- key: Required[str]
- """Unique key for this option."""
-
- value: Required[str]
- """Display text for this option."""
-
- logic: Optional[PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestionOptionLogic]
- """Conditional logic routing for this answer option."""
-
-
-class PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestion(TypedDict, total=False):
- """A dependent conditional question (non-recursive to avoid schema recursion)."""
-
- type: Required[str]
- """Question type (EMAIL, FULL_NAME, PHONE, CUSTOM, DATE_TIME, etc.)."""
-
- inline_context: Optional[str]
- """Helper text shown below the question."""
-
- key: Optional[str]
- """Unique key for this question."""
-
- label: Optional[str]
- """Custom label for CUSTOM questions."""
-
- options: Optional[Iterable[PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestionOption]]
- """Answer options for multiple choice questions."""
-
-
-class PlatformConfigMetaLeadFormConfigQuestionOptionLogic(TypedDict, total=False):
- """Conditional logic routing for this answer option."""
-
- type: Required[str]
- """Logic type: go_to_question, submit_form, or close_form."""
-
- target_end_page_index: Optional[int]
- """Index of the end page to route to (for submit_form type)."""
-
- target_question_index: Optional[int]
- """Index of the question to route to (for go_to_question type)."""
-
-
-class PlatformConfigMetaLeadFormConfigQuestionOption(TypedDict, total=False):
- """An answer option for a multiple choice lead form question."""
-
- key: Required[str]
- """Unique key for this option."""
-
- value: Required[str]
- """Display text for this option."""
-
- logic: Optional[PlatformConfigMetaLeadFormConfigQuestionOptionLogic]
- """Conditional logic routing for this answer option."""
-
-
-class PlatformConfigMetaLeadFormConfigQuestion(TypedDict, total=False):
- """A question on a Meta lead gen form."""
-
- type: Required[str]
- """Question type (EMAIL, FULL_NAME, PHONE, CUSTOM, DATE_TIME, etc.)."""
-
- conditional_questions_group_id: Optional[str]
- """Group ID for conditional question routing."""
-
- dependent_conditional_questions: Optional[
- Iterable[PlatformConfigMetaLeadFormConfigQuestionDependentConditionalQuestion]
- ]
- """Questions shown conditionally based on this question's answer."""
-
- inline_context: Optional[str]
- """Helper text shown below the question."""
-
- key: Optional[str]
- """Unique key for this question."""
-
- label: Optional[str]
- """Custom label for CUSTOM questions."""
-
- options: Optional[Iterable[PlatformConfigMetaLeadFormConfigQuestionOption]]
- """Answer options for multiple choice CUSTOM questions."""
-
- question_format: Optional[str]
- """UI hint: short_answer, multiple_choice, or appointment."""
-
-
-class PlatformConfigMetaLeadFormConfigCustomDisclaimerCheckbox(TypedDict, total=False):
- """A consent checkbox for the custom disclaimer section."""
-
- key: Required[str]
- """Unique key for this checkbox."""
-
- text: Required[str]
- """Label text for the checkbox."""
-
- is_checked_by_default: Optional[bool]
- """Whether the checkbox is checked by default."""
-
- is_required: Optional[bool]
- """Whether the checkbox must be checked to submit."""
-
-
-class PlatformConfigMetaLeadFormConfigThankYouPage(TypedDict, total=False):
- """A thank-you / ending page for a Meta lead gen form."""
-
- body: Optional[str]
- """Body text for this ending page."""
-
- business_phone: Optional[str]
- """Business phone number for call CTA."""
-
- button_text: Optional[str]
- """Custom button text."""
-
- button_type: Optional[str]
- """CTA button type: VIEW_WEBSITE, CALL_BUSINESS, DOWNLOAD."""
-
- conditional_question_group_id: Optional[str]
- """Question group ID for conditional routing to this page."""
-
- enable_messenger: Optional[bool]
- """Enable Messenger follow-up."""
-
- gated_file_url: Optional[str]
- """Uploaded file URL for gated content download."""
-
- link: Optional[str]
- """URL the button links to."""
-
- name: Optional[str]
- """Internal name for this ending page."""
-
- title: Optional[str]
- """Headline for this ending page."""
-
-
-class PlatformConfigMetaLeadFormConfig(TypedDict, total=False):
- """Configuration for a Meta lead gen instant form."""
-
- name: Required[str]
- """Name of the lead form."""
-
- privacy_policy_url: Required[str]
- """URL to your privacy policy. Required by Meta."""
-
- questions: Required[Iterable[PlatformConfigMetaLeadFormConfigQuestion]]
- """Questions to ask on the form."""
-
- background_image_source: Optional[str]
- """Background image source: from_ad or custom."""
-
- background_image_url: Optional[str]
- """URL of custom background image."""
-
- conditional_logic_enabled: Optional[bool]
- """Whether conditional logic is enabled for questions."""
-
- context_card_button_text: Optional[str]
- """CTA button text on the greeting card."""
-
- context_card_content: Optional[SequenceNotStr[str]]
- """Optional greeting card bullet points."""
-
- context_card_style: Optional[str]
- """Greeting layout: PARAGRAPH_STYLE or LIST_STYLE."""
-
- context_card_title: Optional[str]
- """Optional greeting card title."""
-
- custom_disclaimer_body: Optional[str]
- """Custom disclaimer body text."""
-
- custom_disclaimer_checkboxes: Optional[Iterable[PlatformConfigMetaLeadFormConfigCustomDisclaimerCheckbox]]
- """Consent checkboxes for the custom disclaimer."""
-
- custom_disclaimer_title: Optional[str]
- """Custom disclaimer section title."""
-
- form_type: Optional[str]
- """Form type: more_volume, higher_intent, or rich_creative."""
-
- messenger_enabled: Optional[bool]
- """Enable Messenger follow-up after form submission."""
-
- phone_verification_enabled: Optional[bool]
- """Require phone number verification via OTP (higher_intent only)."""
-
- privacy_policy_link_text: Optional[str]
- """Custom link text for privacy policy (max 70 chars)."""
-
- question_page_custom_headline: Optional[str]
- """Custom headline for the questions page."""
-
- rich_creative_headline: Optional[str]
- """Headline for rich creative form intro."""
-
- rich_creative_overview: Optional[str]
- """Overview description for rich creative form intro."""
-
- rich_creative_url: Optional[str]
- """Uploaded image URL for rich creative form type."""
-
- thank_you_pages: Optional[Iterable[PlatformConfigMetaLeadFormConfigThankYouPage]]
- """Thank you / ending pages (supports multiple for conditional routing)."""
-
-
-class PlatformConfigMetaPromotedObject(TypedDict, total=False):
- """The object this ad set promotes (pixel, page, etc.)."""
-
- custom_conversion_id: Optional[str]
- """Custom conversion rule ID (numeric, from Meta Events Manager)."""
-
- custom_event_str: Optional[str]
- """Pixel event name, used when custom_event_type is OTHER."""
-
- custom_event_type: Optional[str]
- """Custom event type (e.g., PURCHASE, COMPLETE_REGISTRATION, OTHER)."""
-
- page_id: Optional[str]
- """Facebook Page ID."""
-
- pixel_id: Optional[str]
- """Meta Pixel ID for conversion tracking."""
-
- whatsapp_phone_number: Optional[str]
- """WhatsApp phone number for messaging campaigns."""
-
-
-class PlatformConfigMetaTargetingAutomation(TypedDict, total=False):
- """Advantage+ audience expansion settings."""
-
- advantage_audience: Optional[int]
- """0 = off (use exact targeting), 1 = on (let Meta expand audience)."""
-
-
-class PlatformConfigMeta(TypedDict, total=False):
- """Meta (Facebook/Instagram) ad set configuration."""
-
- android_devices: Optional[SequenceNotStr[str]]
-
- attribution_setting: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- attribution_spec: Optional[Iterable[PlatformConfigMetaAttributionSpec]]
- """Conversion attribution windows."""
-
- audience_network_positions: Optional[SequenceNotStr[str]]
-
- audience_type: Optional[str]
- """Audience type for retargeting."""
-
- bid_amount: Optional[int]
- """Bid amount in cents."""
-
- bid_strategy: Optional[
- Literal["LOWEST_COST_WITHOUT_CAP", "LOWEST_COST_WITH_BID_CAP", "COST_CAP", "LOWEST_COST_WITH_MIN_ROAS"]
- ]
- """Meta bid strategy."""
-
- billing_event: Optional[
- Literal[
- "APP_INSTALLS",
- "CLICKS",
- "IMPRESSIONS",
- "LINK_CLICKS",
- "NONE",
- "OFFER_CLAIMS",
- "PAGE_LIKES",
- "POST_ENGAGEMENT",
- "THRUPLAY",
- "PURCHASE",
- "LISTING_INTERACTION",
- ]
- ]
- """How you are billed on Meta."""
-
- brand_safety_content_filter_levels: Optional[SequenceNotStr[str]]
-
- budget_remaining: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- cost_per_result_goal: Optional[float]
- """
- Represents signed double-precision fractional values as specified by
- [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
- """
-
- created_time: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- daily_budget: Optional[int]
- """Daily budget in cents."""
-
- daily_min_spend_target: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- daily_spend_cap: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- destination_type: Optional[
- Literal[
- "UNDEFINED",
- "WEBSITE",
- "APP",
- "FACEBOOK",
- "MESSENGER",
- "WHATSAPP",
- "INSTAGRAM_DIRECT",
- "INSTAGRAM_PROFILE",
- "PHONE_CALL",
- "SHOP_AUTOMATIC",
- "APPLINKS_AUTOMATIC",
- "ON_AD",
- "ON_POST",
- "ON_VIDEO",
- "ON_PAGE",
- "ON_EVENT",
- "MESSAGING_MESSENGER_WHATSAPP",
- "MESSAGING_INSTAGRAM_DIRECT_MESSENGER",
- "MESSAGING_INSTAGRAM_DIRECT_WHATSAPP",
- "MESSAGING_INSTAGRAM_DIRECT_MESSENGER_WHATSAPP",
- "INSTAGRAM_PROFILE_AND_FACEBOOK_PAGE",
- "FACEBOOK_PAGE",
- "INSTAGRAM_LIVE",
- "FACEBOOK_LIVE",
- "IMAGINE",
- "LEAD_FROM_IG_DIRECT",
- "LEAD_FROM_MESSENGER",
- "LEAD_FORM_MESSENGER",
- "WEBSITE_AND_LEAD_FORM",
- "WEBSITE_AND_PHONE_CALL",
- "BROADCAST_CHANNEL",
- ]
- ]
- """Where ads in this ad set direct people."""
-
- dsa_beneficiary: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- dsa_payor: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- end_time: Optional[str]
- """End time (ISO8601). Required for lifetime budgets."""
-
- excluded_geo_locations: Optional[PlatformConfigMetaExcludedGeoLocations]
- """Geo locations to exclude."""
-
- facebook_positions: Optional[SequenceNotStr[str]]
- """Facebook ad placements (feed, reels, stories, etc.)."""
-
- frequency_control_count: Optional[int]
- """Represents non-fractional signed whole numeric values.
-
- Int can represent values between -(2^31) and 2^31 - 1.
- """
-
- frequency_control_days: Optional[int]
- """Represents non-fractional signed whole numeric values.
-
- Int can represent values between -(2^31) and 2^31 - 1.
- """
-
- frequency_control_type: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- geo_cities: Optional[Iterable[PlatformConfigMetaGeoCity]]
-
- geo_locations: Optional[PlatformConfigMetaGeoLocations]
- """Geo targeting (countries, regions, cities, zips)."""
-
- geo_regions: Optional[Iterable[PlatformConfigMetaGeoRegion]]
-
- geo_zips: Optional[SequenceNotStr[str]]
-
- instagram_actor_id: Optional[str]
- """Instagram account ID for this ad set."""
-
- instagram_positions: Optional[SequenceNotStr[str]]
- """Instagram ad placements (stream, story, reels, etc.)."""
-
- ios_devices: Optional[SequenceNotStr[str]]
-
- is_dynamic_creative: Optional[bool]
- """Represents `true` or `false` values."""
-
- lead_conversion_location: Optional[
- Literal["website", "instant_forms", "website_and_instant_forms", "messenger", "instagram", "calls", "app"]
- ]
-
- lead_form_config: Optional[PlatformConfigMetaLeadFormConfig]
- """Configuration for a Meta lead gen instant form."""
-
- lead_gen_form_id: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- lifetime_budget: Optional[int]
- """Lifetime budget in cents."""
-
- lifetime_min_spend_target: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- lifetime_spend_cap: Optional[str]
- """Represents textual data as UTF-8 character sequences.
+ """Budget amount in dollars.
- This type is most often used by GraphQL to represent free-form human-readable
- text.
+ The interpretation (daily or lifetime) follows the ad group's existing budget
+ type.
"""
- location_types: Optional[SequenceNotStr[str]]
-
- messenger_positions: Optional[SequenceNotStr[str]]
-
- optimization_goal: Optional[
- Literal[
- "NONE",
- "APP_INSTALLS",
- "AD_RECALL_LIFT",
- "ENGAGED_USERS",
- "EVENT_RESPONSES",
- "IMPRESSIONS",
- "LEAD_GENERATION",
- "QUALITY_LEAD",
- "LINK_CLICKS",
- "OFFSITE_CONVERSIONS",
- "PAGE_LIKES",
- "POST_ENGAGEMENT",
- "QUALITY_CALL",
- "REACH",
- "LANDING_PAGE_VIEWS",
- "VISIT_INSTAGRAM_PROFILE",
- "VALUE",
- "THRUPLAY",
- "DERIVED_EVENTS",
- "APP_INSTALLS_AND_OFFSITE_CONVERSIONS",
- "CONVERSATIONS",
- "IN_APP_VALUE",
- "MESSAGING_PURCHASE_CONVERSION",
- "SUBSCRIBERS",
- "REMINDERS_SET",
- "MEANINGFUL_CALL_ATTEMPT",
- "PROFILE_VISIT",
- "PROFILE_AND_PAGE_ENGAGEMENT",
- "TWO_SECOND_CONTINUOUS_VIDEO_VIEWS",
- "ENGAGED_REACH",
- "ENGAGED_PAGE_VIEWS",
- "MESSAGING_DEEP_CONVERSATION_AND_FOLLOW",
- "ADVERTISER_SILOED_VALUE",
- "AUTOMATIC_OBJECTIVE",
- "MESSAGING_APPOINTMENT_CONVERSION",
- ]
- ]
- """What this ad set optimizes for on Meta."""
-
- page_id: Optional[str]
- """Facebook Page ID for this ad set."""
-
- pixel_id: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- promoted_object: Optional[PlatformConfigMetaPromotedObject]
- """The object this ad set promotes (pixel, page, etc.)."""
-
- publisher_platforms: Optional[SequenceNotStr[str]]
- """Platforms to publish on (facebook, instagram, messenger, audience_network)."""
-
- source_adset_id: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- start_time: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- status: Optional[Literal["ACTIVE", "PAUSED"]]
-
- targeting_automation: Optional[PlatformConfigMetaTargetingAutomation]
- """Advantage+ audience expansion settings."""
-
- threads_positions: Optional[SequenceNotStr[str]]
-
- updated_time: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- user_device: Optional[SequenceNotStr[str]]
-
- user_os: Optional[SequenceNotStr[str]]
-
- whatsapp_phone_number: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- whatsapp_positions: Optional[SequenceNotStr[str]]
-
-
-class PlatformConfigTiktokAction(TypedDict, total=False):
- """A single TikTok behavioral targeting entry.
-
- One category of past user behavior (what they did, over what window, on which kind of content). See docs/tiktok_api/ad_group.md § actions.
- """
-
- action_category_ids: Optional[SequenceNotStr[str]]
- """Behavioral category IDs. Use /tool/action_category/ to list them."""
-
- action_period: Optional[int]
- """Lookback window in days. TikTok accepts 7, 15, 30, 60, 90, or 180."""
-
- action_scene: Optional[Literal["VIDEO_RELATED", "CREATOR_RELATED", "HASHTAG_RELATED", "LIVE_RELATED"]]
- """The category of TikTok content a behavioral targeting rule applies to.
-
- See docs/tiktok_api/ad_group.md § actions.
- """
-
- video_user_actions: Optional[
- List[Literal["WATCHED_TO_END", "LIKED", "COMMENTED", "SHARED", "FOLLOWED", "PROFILE_VISITED"]]
- ]
- """
- Specific video interactions (WATCHED_TO_END, LIKED, COMMENTED, SHARED, FOLLOWED,
- PROFILE_VISITED).
- """
-
-
-class PlatformConfigTiktokInstantFormConfigQuestion(TypedDict, total=False):
- """A question for a TikTok instant form."""
-
- field_type: Required[str]
- """Question type (EMAIL, PHONE_NUMBER, NAME, CUSTOM)."""
-
- label: Optional[str]
- """Custom label for the question."""
-
-
-class PlatformConfigTiktokInstantFormConfig(TypedDict, total=False):
- """Instant form configuration for lead generation campaigns."""
-
- privacy_policy_url: Required[str]
- """URL to your privacy policy."""
-
- questions: Required[Iterable[PlatformConfigTiktokInstantFormConfigQuestion]]
- """Form questions (at least one required)."""
-
- button_text: Optional[str]
- """Submit button text."""
-
- greeting: Optional[str]
- """Greeting text shown at the top of the form."""
-
- name: Optional[str]
- """Form name. Auto-generated if omitted."""
-
-
-class PlatformConfigTiktok(TypedDict, total=False):
- """TikTok ad group configuration."""
-
- actions: Optional[Iterable[PlatformConfigTiktokAction]]
-
- age_groups: Optional[List[Literal["AGE_13_17", "AGE_18_24", "AGE_25_34", "AGE_35_44", "AGE_45_54", "AGE_55_100"]]]
-
- app_id: Optional[str]
- """App ID for app promotion campaigns."""
-
- attribution_event_count: Optional[Literal["UNSET", "EVERY", "ONCE"]]
-
- audience_ids: Optional[SequenceNotStr[str]]
-
- audience_rule: Optional[Dict[str, object]]
- """Represents untyped JSON"""
-
- audience_type: Optional[Literal["NORMAL", "SMART_INTERESTS_BEHAVIORS"]]
-
- bid_price: Optional[float]
- """Bid price (cost per result for Cost Cap)."""
-
- bid_type: Optional[Literal["BID_TYPE_NO_BID", "BID_TYPE_CUSTOM"]]
- """Bidding strategy (BID_TYPE_NO_BID, BID_TYPE_CUSTOM)."""
-
- billing_event: Optional[Literal["CPC", "CPM", "OCPM", "CPV"]]
- """How you are billed on TikTok (CPC, CPM, OCPM, CPV)."""
-
- brand_safety_type: Optional[
- Literal["NO_BRAND_SAFETY", "STANDARD_INVENTORY", "LIMITED_INVENTORY", "FULL_INVENTORY", "EXPANDED_INVENTORY"]
- ]
-
- budget_mode: Optional[Literal["BUDGET_MODE_DAY", "BUDGET_MODE_TOTAL", "BUDGET_MODE_DYNAMIC_DAILY_BUDGET"]]
- """
- Budget mode (BUDGET_MODE_DAY, BUDGET_MODE_TOTAL,
- BUDGET_MODE_DYNAMIC_DAILY_BUDGET).
- """
-
- carrier_ids: Optional[SequenceNotStr[str]]
-
- category_exclusion_ids: Optional[SequenceNotStr[str]]
-
- click_attribution_window: Optional[Literal["OFF", "ONE_DAY", "SEVEN_DAYS", "FOURTEEN_DAYS", "TWENTY_EIGHT_DAYS"]]
-
- comment_disabled: Optional[bool]
- """Represents `true` or `false` values."""
-
- contextual_tag_ids: Optional[SequenceNotStr[str]]
-
- conversion_bid_price: Optional[float]
- """Target cost per conversion for oCPM."""
-
- creative_material_mode: Optional[str]
- """Creative delivery strategy."""
-
- dayparting: Optional[str]
- """Ad delivery schedule (48x7 character string)."""
-
- deep_funnel_event_source: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- deep_funnel_event_source_id: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- deep_funnel_optimization_status: Optional[Literal["ON", "OFF"]]
-
- device_model_ids: Optional[SequenceNotStr[str]]
-
- device_price_ranges: Optional[SequenceNotStr[str]]
-
- engaged_view_attribution_window: Optional[Literal["OFF", "ONE_DAY", "SEVEN_DAYS"]]
-
- excluded_audience_ids: Optional[SequenceNotStr[str]]
-
- excluded_location_ids: Optional[SequenceNotStr[str]]
- """TikTok location/region IDs to exclude."""
-
- frequency: Optional[int]
- """Represents non-fractional signed whole numeric values.
-
- Int can represent values between -(2^31) and 2^31 - 1.
- """
-
- frequency_schedule: Optional[int]
- """Represents non-fractional signed whole numeric values.
-
- Int can represent values between -(2^31) and 2^31 - 1.
- """
-
- gender: Optional[Literal["GENDER_UNLIMITED", "GENDER_MALE", "GENDER_FEMALE"]]
-
- identity_authorized_bc_id: Optional[str]
- """Business Center ID for BC_AUTH_TT identity."""
-
- identity_id: Optional[str]
- """TikTok identity ID for the ad group."""
-
- identity_type: Optional[str]
- """Identity type (AUTH_CODE, TT_USER, BC_AUTH_TT)."""
-
- instant_form_config: Optional[PlatformConfigTiktokInstantFormConfig]
- """Instant form configuration for lead generation campaigns."""
-
- instant_form_id: Optional[str]
- """
- TikTok instant form ID (set automatically when instant_form_config is provided).
- """
-
- interest_category_ids: Optional[SequenceNotStr[str]]
-
- interest_keyword_ids: Optional[SequenceNotStr[str]]
-
- inventory_filter_enabled: Optional[bool]
- """Represents `true` or `false` values."""
-
- ios14_targeting: Optional[Literal["UNSET", "IOS14_MINUS", "IOS14_PLUS", "ALL"]]
-
- isp_ids: Optional[SequenceNotStr[str]]
-
- languages: Optional[SequenceNotStr[str]]
-
- location_ids: Optional[SequenceNotStr[str]]
- """TikTok location/region IDs for geo targeting."""
-
- min_android_version: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- min_ios_version: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- network_types: Optional[SequenceNotStr[str]]
-
- operating_systems: Optional[List[Literal["ANDROID", "IOS"]]]
-
- operation_status: Optional[Literal["ENABLE", "DISABLE"]]
- """Initial status (ENABLE, DISABLE)."""
-
- optimization_event: Optional[str]
- """Conversion event (e.g., COMPLETE_PAYMENT)."""
-
- optimization_goal: Optional[
- Literal[
- "CLICK",
- "CONVERT",
- "INSTALL",
- "IN_APP_EVENT",
- "REACH",
- "SHOW",
- "VIDEO_VIEW",
- "ENGAGED_VIEW",
- "ENGAGED_VIEW_FIFTEEN",
- "LEAD_GENERATION",
- "PREFERRED_LEAD",
- "CONVERSATION",
- "FOLLOWERS",
- "PROFILE_VIEWS",
- "PAGE_VISIT",
- "VALUE",
- "AUTOMATIC_VALUE_OPTIMIZATION",
- "TRAFFIC_LANDING_PAGE_VIEW",
- "DESTINATION_VISIT",
- "MT_LIVE_ROOM",
- "PRODUCT_CLICK_IN_LIVE",
- ]
- ]
- """What this ad group optimizes for on TikTok."""
-
- pacing: Optional[Literal["PACING_MODE_SMOOTH", "PACING_MODE_FAST"]]
- """Budget pacing (PACING_MODE_SMOOTH, PACING_MODE_FAST)."""
-
- pangle_audience_package_exclude_ids: Optional[SequenceNotStr[str]]
-
- pangle_audience_package_include_ids: Optional[SequenceNotStr[str]]
-
- pangle_block_app_ids: Optional[SequenceNotStr[str]]
-
- pixel_id: Optional[str]
- """TikTok Pixel ID for conversion tracking."""
-
- placement_type: Optional[Literal["PLACEMENT_TYPE_AUTOMATIC", "PLACEMENT_TYPE_NORMAL"]]
- """Placement strategy (PLACEMENT_TYPE_AUTOMATIC, PLACEMENT_TYPE_NORMAL)."""
-
- placements: Optional[SequenceNotStr[str]]
- """Placements (PLACEMENT_TIKTOK, PLACEMENT_PANGLE, etc.)."""
-
- product_set_id: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- product_source: Optional[Literal["CATALOG", "STORE", "SHOWCASE"]]
-
- promotion_type: Optional[str]
- """Promotion type (optimization location)."""
-
- schedule_end_time: Optional[str]
- """Schedule end time (UTC, YYYY-MM-DD HH:MM:SS)."""
-
- schedule_start_time: Optional[str]
- """Schedule start time (UTC, YYYY-MM-DD HH:MM:SS)."""
-
- schedule_type: Optional[Literal["SCHEDULE_START_END", "SCHEDULE_FROM_NOW"]]
- """Schedule type (SCHEDULE_START_END, SCHEDULE_FROM_NOW)."""
-
- secondary_optimization_event: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- shopping_ads_retargeting_actions_days: Optional[int]
- """Represents non-fractional signed whole numeric values.
-
- Int can represent values between -(2^31) and 2^31 - 1.
- """
-
- shopping_ads_retargeting_type: Optional[Literal["OFF", "LAB1", "LAB2", "LAB3", "LAB4", "LAB5"]]
-
- spending_power: Optional[Literal["ALL", "HIGH"]]
-
- tiktok_subplacements: Optional[SequenceNotStr[str]]
- """TikTok subplacements (IN_FEED, SEARCH_FEED, etc.)."""
-
- vertical_sensitivity_id: Optional[str]
- """Represents textual data as UTF-8 character sequences.
-
- This type is most often used by GraphQL to represent free-form human-readable
- text.
- """
-
- video_download_disabled: Optional[bool]
- """Represents `true` or `false` values."""
-
- video_user_actions: Optional[SequenceNotStr[str]]
-
- view_attribution_window: Optional[Literal["OFF", "ONE_DAY", "SEVEN_DAYS"]]
-
-
-class PlatformConfig(TypedDict, total=False):
- """Platform-specific ad group configuration."""
-
- meta: Optional[PlatformConfigMeta]
- """Meta (Facebook/Instagram) ad set configuration."""
-
- tiktok: Optional[PlatformConfigTiktok]
- """TikTok ad group configuration."""
+ title: Optional[str]
+ """Human-readable ad group title. Max 255 characters."""
diff --git a/src/whop_sdk/types/ad_list_params.py b/src/whop_sdk/types/ad_list_params.py
index f89c77d2..7fbe33a3 100644
--- a/src/whop_sdk/types/ad_list_params.py
+++ b/src/whop_sdk/types/ad_list_params.py
@@ -6,6 +6,7 @@
from datetime import datetime
from typing_extensions import Literal, Annotated, TypedDict
+from .._types import SequenceNotStr
from .._utils import PropertyInfo
from .shared.direction import Direction
from .external_ad_status import ExternalAdStatus
@@ -14,10 +15,28 @@
class AdListParams(TypedDict, total=False):
+ ad_campaign_id: Optional[str]
+ """Filter by ad campaign.
+
+ Provide exactly one of ad_group_id, ad_campaign_id, or company_id.
+ """
+
+ ad_campaign_ids: Optional[SequenceNotStr[str]]
+ """Only return ads belonging to these ad campaigns (max 100).
+
+ Can be combined with companyId or used on its own.
+ """
+
ad_group_id: Optional[str]
"""Filter by ad group.
- Provide exactly one of ad_group_id, campaign_id, or company_id.
+ Provide exactly one of ad_group_id, ad_campaign_id, or company_id.
+ """
+
+ ad_group_ids: Optional[SequenceNotStr[str]]
+ """Only return ads belonging to these ad groups (max 100).
+
+ Can be combined with companyId or used on its own.
"""
after: Optional[str]
@@ -27,15 +46,12 @@ class AdListParams(TypedDict, total=False):
"""Returns the elements in the list that come before the specified cursor."""
campaign_id: Optional[str]
- """Filter by campaign.
-
- Provide exactly one of ad_group_id, campaign_id, or company_id.
- """
+ """Filter by campaign."""
company_id: Optional[str]
"""Filter by company.
- Provide exactly one of ad_group_id, campaign_id, or company_id.
+ Provide exactly one of ad_group_id, ad_campaign_id, or company_id.
"""
created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
@@ -44,32 +60,58 @@ class AdListParams(TypedDict, total=False):
created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""Only return ads created before this timestamp."""
+ direction: Optional[Direction]
+ """The direction of the sort."""
+
first: Optional[int]
"""Returns the first _n_ elements from the list."""
- include_paused: Optional[bool]
- """
- When false, excludes paused ads so pagination matches the dashboard's
- hide-paused toggle.
- """
-
last: Optional[int]
"""Returns the last _n_ elements from the list."""
- order_by: Optional[Literal["spend", "roas"]]
- """Columns that the listAds query can sort by."""
+ order: Optional[
+ Literal[
+ "created_at",
+ "spend",
+ "impressions",
+ "clicks",
+ "reach",
+ "unique_clicks",
+ "results",
+ "click_through_rate",
+ "cost_per_click",
+ "cost_per_mille",
+ "cost_per_result",
+ "frequency",
+ "return_on_ad_spend",
+ ]
+ ]
+ """The fields the ads dashboard lists (campaigns, ad sets) can be ordered by.
+
+ Stat columns are computed over the provided stats date range.
+ """
+
+ order_by: Optional[Literal["spend", "return_on_ad_spend", "roas"]]
+ """Columns that the listAds query can sort by. Deprecated — use AdStatOrder."""
order_direction: Optional[Direction]
"""The direction of the sort."""
query: Optional[str]
- """Case-insensitive substring match against the ad title or tag."""
+ """Case-insensitive substring match against the ad title or ID."""
stats_from: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Start of the stats date range used when order_by is a stats column."""
+ """
+ Inclusive start of the window for each ad's metric fields (spend, impressions,
+ …) and for stats-column sorting. Omit both statsFrom and statsTo for all-time
+ stats.
+ """
stats_to: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """End of the stats date range used when order_by is a stats column."""
+ """
+ Inclusive end of the window for each ad's metric fields and for stats-column
+ sorting. Omit both statsFrom and statsTo for all-time stats.
+ """
status: Optional[ExternalAdStatus]
"""The status of an external ad."""
diff --git a/src/whop_sdk/types/ad_list_response.py b/src/whop_sdk/types/ad_list_response.py
index f6a13bac..742a4b3d 100644
--- a/src/whop_sdk/types/ad_list_response.py
+++ b/src/whop_sdk/types/ad_list_response.py
@@ -1,13 +1,15 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
+from .shared.currency import Currency
from .external_ad_status import ExternalAdStatus
from .ad_campaign_platform import AdCampaignPlatform
-__all__ = ["AdListResponse", "AdCampaign", "AdGroup"]
+__all__ = ["AdListResponse", "AdCampaign", "AdGroup", "Issue"]
class AdCampaign(BaseModel):
@@ -24,6 +26,37 @@ class AdGroup(BaseModel):
"""The unique identifier for this ad group."""
+class Issue(BaseModel):
+ """A platform-reported issue on an ad object (rejection, policy flag, etc.)."""
+
+ category: Optional[Literal["policy_rejection", "creative_media", "audience_targeting", "ad_volume_limit"]] = None
+ """Whop's canonical category that a raw platform issue is bucketed into."""
+
+ created_at: datetime
+ """When the issue was first reported."""
+
+ resolution_status: Literal["open", "resolved", "acknowledged"]
+ """Current resolution status."""
+
+ resource_id: Optional[str] = None
+ """The Whop ID of the ad object this issue is on (the ad, ad group, or campaign).
+
+ Null when the issue isn't tied to a local object.
+ """
+
+ resource_type: str
+ """The kind of ad object this issue is on: `ad`, `ad_group`, or `ad_campaign`.
+
+ Pairs with `resourceId`.
+ """
+
+ subtype: Optional[str] = None
+ """Finer-grained sub-bucket within the category (e.g.
+
+ the specific Meta policy for a rejection).
+ """
+
+
class AdListResponse(BaseModel):
"""An ad belonging to an ad group."""
@@ -36,17 +69,101 @@ class AdListResponse(BaseModel):
ad_group: AdGroup
"""The parent ad group this ad belongs to."""
+ click_through_rate: float
+ """Click-through rate as a fraction of impressions (clicks / impressions, 0–1)."""
+
+ clicks: int
+ """Total clicks on this ad in the stats window."""
+
+ cost_per_click: float
+ """Cost per click in dollars (spend / clicks). 0 when there are no clicks."""
+
+ cost_per_lead: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed lead (spend / leads).
+
+ 0 when leads are tracked but none happened yet; null when leads are not a goal
+ and none were attributed.
+ """
+
+ cost_per_mille: float
+ """Cost per 1,000 impressions in dollars (spend / impressions × 1000).
+
+ 0 when there are no impressions.
+ """
+
+ cost_per_purchase: Optional[float] = None
+ """Cost in dollars per Whop pixel-attributed purchase (spend / purchases).
+
+ 0 when purchases are tracked but none happened yet; null when purchases are not
+ a goal and none were attributed.
+ """
+
+ cost_per_result: Optional[float] = None
+ """Cost in dollars per optimization result (spend / results).
+
+ 0 when a result is being optimized for but none happened yet; null when nothing
+ is being optimized for.
+ """
+
created_at: datetime
"""When the ad was created."""
+ frequency: Optional[float] = None
+ """
+ Average number of times each person saw an ad (impressions / reach), as reported
+ by the platform.
+ """
+
+ impressions: int
+ """Total impressions (views) on this ad in the stats window."""
+
+ issues: List[Issue]
+ """Open platform issues affecting this ad, deduplicated per object.
+
+ Empty when there are none.
+ """
+
+ leads: int
+ """Number of Whop pixel-attributed leads (last-click) in the stats window."""
+
platform: AdCampaignPlatform
"""The external ad platform this ad is running on (e.g., meta, tiktok)."""
+ purchase_value: float
+ """Total USD value of Whop pixel-attributed purchases in the stats window."""
+
+ purchases: int
+ """Number of Whop pixel-attributed purchases (last-click) in the stats window."""
+
+ reach: int
+ """Unique users reached in the stats window (deduplicated by the platform)."""
+
+ return_on_ad_spend: float
+ """
+ Return on ad spend as a ratio (purchaseValue / spend) — 2.5 means $2.50 of
+ attributed purchase value per $1 spent. 0 when there is no spend.
+ """
+
+ spend: float
+ """Amount charged in dollars in the stats window."""
+
+ spend_currency: Optional[Currency] = None
+ """The available currencies on the platform"""
+
status: ExternalAdStatus
"""Current delivery status of the ad."""
title: Optional[str] = None
"""The display title of the ad. Falls back to the creative set caption when unset."""
+ unique_click_through_rate: Optional[float] = None
+ """
+ Unique click-through rate as a fraction of impressions (unique clicks /
+ impressions, 0–1).
+ """
+
+ unique_clicks: int
+ """Unique clicks (deduplicated by the platform) in the stats window."""
+
updated_at: datetime
"""When the ad was last updated."""
diff --git a/src/whop_sdk/types/ad_report_retrieve_params.py b/src/whop_sdk/types/ad_report_retrieve_params.py
index 9a779523..2b66d934 100644
--- a/src/whop_sdk/types/ad_report_retrieve_params.py
+++ b/src/whop_sdk/types/ad_report_retrieve_params.py
@@ -6,6 +6,7 @@
from datetime import datetime
from typing_extensions import Literal, Required, Annotated, TypedDict
+from .._types import SequenceNotStr
from .._utils import PropertyInfo
from .granularities import Granularities
@@ -19,22 +20,22 @@ class AdReportRetrieveParams(TypedDict, total=False):
to: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]]
"""Inclusive end of the reporting window."""
- ad_campaign_id: Optional[str]
- """The unique identifier of an ad campaign.
+ ad_campaign_ids: Optional[SequenceNotStr[str]]
+ """Scope the report to these ad campaigns (max 100); stats are summed across them.
- Mutually exclusive with `companyId`, `adGroupId`, and `adId`.
+ Mutually exclusive with `companyId`, `adGroupIds`, and `adIds`.
"""
- ad_group_id: Optional[str]
- """The unique identifier of an ad group.
+ ad_group_ids: Optional[SequenceNotStr[str]]
+ """Scope the report to these ad groups (max 100); stats are summed across them.
- Mutually exclusive with `companyId`, `adCampaignId`, and `adId`.
+ Mutually exclusive with `companyId`, `adCampaignIds`, and `adIds`.
"""
- ad_id: Optional[str]
- """The unique identifier of an ad.
+ ad_ids: Optional[SequenceNotStr[str]]
+ """Scope the report to these ads (max 100); stats are summed across them.
- Mutually exclusive with `companyId`, `adCampaignId`, and `adGroupId`.
+ Mutually exclusive with `companyId`, `adCampaignIds`, and `adGroupIds`.
"""
breakdown: Optional[Literal["campaign", "ad_group", "ad"]]
@@ -43,7 +44,7 @@ class AdReportRetrieveParams(TypedDict, total=False):
company_id: Optional[str]
"""The unique identifier of a company.
- Mutually exclusive with `adCampaignId`, `adGroupId`, and `adId`. Use with
+ Mutually exclusive with `adCampaignIds`, `adGroupIds`, and `adIds`. Use with
`breakdown` to fan out across every campaign, ad group, or ad in the company
without paging.
"""
diff --git a/src/whop_sdk/types/ad_report_retrieve_response.py b/src/whop_sdk/types/ad_report_retrieve_response.py
index 56bf2ef4..7157cbef 100644
--- a/src/whop_sdk/types/ad_report_retrieve_response.py
+++ b/src/whop_sdk/types/ad_report_retrieve_response.py
@@ -36,7 +36,7 @@ class BreakdownGranularity(BaseModel):
"""Clicks in this bucket."""
granularity: Granularities
- """The bucket size of this row (`daily` or `hourly`)."""
+ """The bucket size of this row (`hourly`, `daily`, `weekly`, or `monthly`)."""
impressions: int
"""Impressions in this bucket."""
@@ -81,20 +81,20 @@ class BreakdownGranularity(BaseModel):
class BreakdownSummary(BaseModel):
"""Aggregate totals and rates for this entity over the date range."""
+ click_through_rate: float
+ """Click-through rate (clicks / impressions)."""
+
clicks: int
"""Total clicks over the date range."""
- cost_per_result: Optional[float] = None
- """Spend divided by `resultCount`. Null when there are no results."""
-
- cpc: float
+ cost_per_click: float
"""Cost per click in the requested reporting currency."""
- cpm: Optional[float] = None
+ cost_per_mille: Optional[float] = None
"""Cost per thousand impressions in the requested reporting currency."""
- ctr: float
- """Click-through rate (clicks / impressions)."""
+ cost_per_result: Optional[float] = None
+ """Spend divided by `resultCount`. Null when there are no results."""
frequency: Optional[float] = None
"""Average number of times each reached user saw an ad."""
@@ -117,10 +117,10 @@ class BreakdownSummary(BaseModel):
result_label_override: Optional[str] = None
"""Advertiser-defined label for the result when `resultLabelKey` is `custom`."""
- roas: Optional[float] = None
+ return_on_ad_spend: Optional[float] = None
"""
- Alias for `purchaseRoas` — return on ad spend for purchases, as reported by the
- external ad platform.
+ Alias for `purchaseReturnOnAdSpend` — return on ad spend for purchases, as
+ reported by the external ad platform.
"""
spend: float
@@ -173,7 +173,7 @@ class Granularity(BaseModel):
"""Clicks in this bucket."""
granularity: Granularities
- """The bucket size of this row (`daily` or `hourly`)."""
+ """The bucket size of this row (`hourly`, `daily`, `weekly`, or `monthly`)."""
impressions: int
"""Impressions in this bucket."""
@@ -218,20 +218,20 @@ class Granularity(BaseModel):
class Summary(BaseModel):
"""Aggregate totals and rates over the date range."""
+ click_through_rate: float
+ """Click-through rate (clicks / impressions)."""
+
clicks: int
"""Total clicks over the date range."""
- cost_per_result: Optional[float] = None
- """Spend divided by `resultCount`. Null when there are no results."""
-
- cpc: float
+ cost_per_click: float
"""Cost per click in the requested reporting currency."""
- cpm: Optional[float] = None
+ cost_per_mille: Optional[float] = None
"""Cost per thousand impressions in the requested reporting currency."""
- ctr: float
- """Click-through rate (clicks / impressions)."""
+ cost_per_result: Optional[float] = None
+ """Spend divided by `resultCount`. Null when there are no results."""
frequency: Optional[float] = None
"""Average number of times each reached user saw an ad."""
@@ -254,10 +254,10 @@ class Summary(BaseModel):
result_label_override: Optional[str] = None
"""Advertiser-defined label for the result when `resultLabelKey` is `custom`."""
- roas: Optional[float] = None
+ return_on_ad_spend: Optional[float] = None
"""
- Alias for `purchaseRoas` — return on ad spend for purchases, as reported by the
- external ad platform.
+ Alias for `purchaseReturnOnAdSpend` — return on ad spend for purchases, as
+ reported by the external ad platform.
"""
spend: float
diff --git a/src/whop_sdk/types/ad_retrieve_params.py b/src/whop_sdk/types/ad_retrieve_params.py
new file mode 100644
index 00000000..fc735f99
--- /dev/null
+++ b/src/whop_sdk/types/ad_retrieve_params.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["AdRetrieveParams"]
+
+
+class AdRetrieveParams(TypedDict, total=False):
+ stats_from: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """Inclusive start of the window for the ad's metric fields (spend, impressions,
+ …).
+
+ Omit both statsFrom and statsTo for all-time stats.
+ """
+
+ stats_to: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """Inclusive end of the window for the ad's metric fields.
+
+ Omit both statsFrom and statsTo for all-time stats.
+ """
diff --git a/src/whop_sdk/types/authorized_user_create_params.py b/src/whop_sdk/types/authorized_user_create_params.py
index b2b538a5..a412352b 100644
--- a/src/whop_sdk/types/authorized_user_create_params.py
+++ b/src/whop_sdk/types/authorized_user_create_params.py
@@ -7,7 +7,7 @@
from .shared.authorized_user_roles import AuthorizedUserRoles
-__all__ = ["AuthorizedUserCreateParams"]
+__all__ = ["AuthorizedUserCreateParams", "Elevation"]
class AuthorizedUserCreateParams(TypedDict, total=False):
@@ -23,5 +23,30 @@ class AuthorizedUserCreateParams(TypedDict, total=False):
user_id: Required[str]
"""The ID of the user to add as an authorized user."""
+ elevation: Optional[Elevation]
+ """Re-authentication proof required to perform this sensitive action."""
+
send_emails: Optional[bool]
"""Whether to send notification emails to the user on creation."""
+
+
+class Elevation(TypedDict, total=False):
+ """Re-authentication proof required to perform this sensitive action."""
+
+ authenticator_data: Optional[str]
+ """The WebAuthn authenticator data (base64)."""
+
+ client_data_json: Optional[str]
+ """The WebAuthn client data JSON (base64)."""
+
+ credential_id: Optional[str]
+ """The WebAuthn credential ID (base64)."""
+
+ signature: Optional[str]
+ """The WebAuthn signature (base64)."""
+
+ totp_code: Optional[str]
+ """The 6-digit code from the authenticator app or SMS."""
+
+ use_finance_session: Optional[bool]
+ """Reuse an existing elevated session (for SMS/email 2FA users)."""
diff --git a/src/whop_sdk/types/bounty_create_params.py b/src/whop_sdk/types/bounty_create_params.py
index de0e0fdb..277d4cc1 100644
--- a/src/whop_sdk/types/bounty_create_params.py
+++ b/src/whop_sdk/types/bounty_create_params.py
@@ -2,10 +2,12 @@
from __future__ import annotations
-from typing import Optional
-from typing_extensions import Required, TypedDict
+from typing import Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Required, Annotated, TypedDict
from .._types import SequenceNotStr
+from .._utils import PropertyInfo
from .shared.currency import Currency
__all__ = ["BountyCreateParams"]
@@ -39,6 +41,15 @@ class BountyCreateParams(TypedDict, total=False):
Empty means globally visible.
"""
+ business_goal_type: Optional[
+ Literal["clipping", "post_engagement", "owned_account_growth", "ugc_content", "local_activation", "other"]
+ ]
+ """What the poster is trying to accomplish with a workforce bounty.
+
+ Used for product taxonomy and analytics, separate from the bounty's
+ implementation type.
+ """
+
experience_id: Optional[str]
"""An optional experience to scope the bounty to."""
@@ -60,3 +71,19 @@ class BountyCreateParams(TypedDict, total=False):
Falls back to the bounty title when omitted.
"""
+
+ scheduled_frequency: Optional[Literal["once", "hourly", "daily", "weekly", "monthly"]]
+ """How often a scheduled bounty republishes a new bounty."""
+
+ scheduled_publish_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """When to publish the bounty.
+
+ When provided, the bounty is created as a hidden draft and published at this
+ time instead of immediately. Must be in the future.
+ """
+
+ scheduled_timezone: Optional[str]
+ """The IANA timezone used for recurring occurrences.
+
+ Required when scheduled_publish_at is provided.
+ """
diff --git a/src/whop_sdk/types/bounty_create_response.py b/src/whop_sdk/types/bounty_create_response.py
index 94c4f5e4..45e80b8a 100644
--- a/src/whop_sdk/types/bounty_create_response.py
+++ b/src/whop_sdk/types/bounty_create_response.py
@@ -27,7 +27,7 @@ class BountyCreateResponse(BaseModel):
description: str
"""The description of the bounty."""
- status: Literal["published", "archived"]
+ status: Literal["published", "archived", "scheduled"]
"""The current lifecycle status of the bounty."""
title: str
diff --git a/src/whop_sdk/types/bounty_list_params.py b/src/whop_sdk/types/bounty_list_params.py
index cb80eaba..08aa2311 100644
--- a/src/whop_sdk/types/bounty_list_params.py
+++ b/src/whop_sdk/types/bounty_list_params.py
@@ -32,5 +32,5 @@ class BountyListParams(TypedDict, total=False):
last: Optional[int]
"""Returns the last _n_ elements from the list."""
- status: Optional[Literal["published", "archived"]]
+ status: Optional[Literal["published", "archived", "scheduled"]]
"""The available bounty statuses to choose from."""
diff --git a/src/whop_sdk/types/bounty_list_response.py b/src/whop_sdk/types/bounty_list_response.py
index 0117a1ba..fcb7c54a 100644
--- a/src/whop_sdk/types/bounty_list_response.py
+++ b/src/whop_sdk/types/bounty_list_response.py
@@ -27,7 +27,7 @@ class BountyListResponse(BaseModel):
description: str
"""The description of the bounty."""
- status: Literal["published", "archived"]
+ status: Literal["published", "archived", "scheduled"]
"""The current lifecycle status of the bounty."""
title: str
diff --git a/src/whop_sdk/types/bounty_retrieve_response.py b/src/whop_sdk/types/bounty_retrieve_response.py
index d9df060a..56ffc09d 100644
--- a/src/whop_sdk/types/bounty_retrieve_response.py
+++ b/src/whop_sdk/types/bounty_retrieve_response.py
@@ -27,7 +27,7 @@ class BountyRetrieveResponse(BaseModel):
description: str
"""The description of the bounty."""
- status: Literal["published", "archived"]
+ status: Literal["published", "archived", "scheduled"]
"""The current lifecycle status of the bounty."""
title: str
diff --git a/src/whop_sdk/types/card_create_params.py b/src/whop_sdk/types/card_create_params.py
new file mode 100644
index 00000000..8f91ffac
--- /dev/null
+++ b/src/whop_sdk/types/card_create_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_extensions import Literal, TypedDict
+
+__all__ = ["CardCreateParams"]
+
+
+class CardCreateParams(TypedDict, total=False):
+ account_id: str
+ """The owning account ID (a biz\\__ identifier). Provide this or user_id."""
+
+ name: str
+ """A display name for the card."""
+
+ spend_limit: float
+ """Spending limit amount, in dollars."""
+
+ spend_limit_frequency: Literal["daily", "weekly", "monthly", "one_time"]
+ """The spending limit window."""
+
+ transaction_limit: float
+ """Per-transaction limit amount, in dollars."""
+
+ user_id: str
+ """The owning user ID (a user\\__ identifier). Provide this or account_id."""
diff --git a/src/whop_sdk/types/card_create_response.py b/src/whop_sdk/types/card_create_response.py
new file mode 100644
index 00000000..fe5e37dd
--- /dev/null
+++ b/src/whop_sdk/types/card_create_response.py
@@ -0,0 +1,96 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["CardCreateResponse", "Billing", "Limit", "Secrets"]
+
+
+class Billing(BaseModel):
+ """The billing address."""
+
+ city: Optional[str] = None
+
+ country_code: Optional[str] = None
+
+ line1: Optional[str] = None
+
+ line2: Optional[str] = None
+
+ postal_code: Optional[str] = None
+
+ region: Optional[str] = None
+
+
+class Limit(BaseModel):
+ """The spending limit configuration."""
+
+ amount: float
+ """The limit amount in dollars."""
+
+ frequency: str
+ """The limit window, for example per24HourPeriod or perAuthorization."""
+
+
+class Secrets(BaseModel):
+ """The card's sensitive details.
+
+ Only present on GET /cards/:card_id (retrieve); null for cards that are not active or whose details could not be retrieved.
+ """
+
+ card_number: str
+ """The full card number."""
+
+ cvc: str
+ """The card verification code."""
+
+ name_on_card: Optional[str] = None
+ """The cardholder name printed on the card."""
+
+
+class CardCreateResponse(BaseModel):
+ id: str
+ """The icrd\\__ identifier of the card."""
+
+ billing: Optional[Billing] = None
+ """The billing address."""
+
+ canceled_at: Optional[datetime] = None
+
+ created_at: Optional[datetime] = None
+
+ expiration_month: Optional[str] = None
+
+ expiration_year: Optional[str] = None
+
+ last4: Optional[str] = None
+ """The last 4 digits of the card number. Null for pending invitation cards."""
+
+ limit: Optional[Limit] = None
+ """The spending limit configuration."""
+
+ name: Optional[str] = None
+
+ object: Literal["card"]
+
+ spent_last_month: Optional[int] = None
+ """Total spend in the last 30 days, in cents."""
+
+ status: Optional[Literal["active", "frozen", "canceled", "invited"]] = None
+ """The card status."""
+
+ type: Optional[Literal["virtual", "physical"]] = None
+ """The card type."""
+
+ user_id: Optional[str] = None
+ """The user\\__ identifier of the cardholder, when assigned."""
+
+ secrets: Optional[Secrets] = None
+ """The card's sensitive details.
+
+ Only present on GET /cards/:card_id (retrieve); null for cards that are not
+ active or whose details could not be retrieved.
+ """
diff --git a/src/whop_sdk/types/card_list_params.py b/src/whop_sdk/types/card_list_params.py
new file mode 100644
index 00000000..2487fd2e
--- /dev/null
+++ b/src/whop_sdk/types/card_list_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 TypedDict
+
+__all__ = ["CardListParams"]
+
+
+class CardListParams(TypedDict, total=False):
+ account_id: str
+ """The owning account ID (a biz\\__ identifier). Provide this or user_id."""
+
+ user_id: str
+ """The owning user ID (a user\\__ identifier). Provide this or account_id."""
diff --git a/src/whop_sdk/types/card_list_response.py b/src/whop_sdk/types/card_list_response.py
new file mode 100644
index 00000000..7393af4e
--- /dev/null
+++ b/src/whop_sdk/types/card_list_response.py
@@ -0,0 +1,100 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["CardListResponse", "Data", "DataBilling", "DataLimit", "DataSecrets"]
+
+
+class DataBilling(BaseModel):
+ """The billing address."""
+
+ city: Optional[str] = None
+
+ country_code: Optional[str] = None
+
+ line1: Optional[str] = None
+
+ line2: Optional[str] = None
+
+ postal_code: Optional[str] = None
+
+ region: Optional[str] = None
+
+
+class DataLimit(BaseModel):
+ """The spending limit configuration."""
+
+ amount: float
+ """The limit amount in dollars."""
+
+ frequency: str
+ """The limit window, for example per24HourPeriod or perAuthorization."""
+
+
+class DataSecrets(BaseModel):
+ """The card's sensitive details.
+
+ Only present on GET /cards/:card_id (retrieve); null for cards that are not active or whose details could not be retrieved.
+ """
+
+ card_number: str
+ """The full card number."""
+
+ cvc: str
+ """The card verification code."""
+
+ name_on_card: Optional[str] = None
+ """The cardholder name printed on the card."""
+
+
+class Data(BaseModel):
+ id: str
+ """The icrd\\__ identifier of the card."""
+
+ billing: Optional[DataBilling] = None
+ """The billing address."""
+
+ canceled_at: Optional[datetime] = None
+
+ created_at: Optional[datetime] = None
+
+ expiration_month: Optional[str] = None
+
+ expiration_year: Optional[str] = None
+
+ last4: Optional[str] = None
+ """The last 4 digits of the card number. Null for pending invitation cards."""
+
+ limit: Optional[DataLimit] = None
+ """The spending limit configuration."""
+
+ name: Optional[str] = None
+
+ object: Literal["card"]
+
+ spent_last_month: Optional[int] = None
+ """Total spend in the last 30 days, in cents."""
+
+ status: Optional[Literal["active", "frozen", "canceled", "invited"]] = None
+ """The card status."""
+
+ type: Optional[Literal["virtual", "physical"]] = None
+ """The card type."""
+
+ user_id: Optional[str] = None
+ """The user\\__ identifier of the cardholder, when assigned."""
+
+ secrets: Optional[DataSecrets] = None
+ """The card's sensitive details.
+
+ Only present on GET /cards/:card_id (retrieve); null for cards that are not
+ active or whose details could not be retrieved.
+ """
+
+
+class CardListResponse(BaseModel):
+ data: List[Data]
diff --git a/src/whop_sdk/types/card_retrieve_params.py b/src/whop_sdk/types/card_retrieve_params.py
new file mode 100644
index 00000000..b325260c
--- /dev/null
+++ b/src/whop_sdk/types/card_retrieve_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 TypedDict
+
+__all__ = ["CardRetrieveParams"]
+
+
+class CardRetrieveParams(TypedDict, total=False):
+ account_id: str
+ """The owning account ID (a biz\\__ identifier). Provide this or user_id."""
+
+ user_id: str
+ """The owning user ID (a user\\__ identifier). Provide this or account_id."""
diff --git a/src/whop_sdk/types/card_retrieve_response.py b/src/whop_sdk/types/card_retrieve_response.py
new file mode 100644
index 00000000..937e2aa0
--- /dev/null
+++ b/src/whop_sdk/types/card_retrieve_response.py
@@ -0,0 +1,96 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["CardRetrieveResponse", "Billing", "Limit", "Secrets"]
+
+
+class Billing(BaseModel):
+ """The billing address."""
+
+ city: Optional[str] = None
+
+ country_code: Optional[str] = None
+
+ line1: Optional[str] = None
+
+ line2: Optional[str] = None
+
+ postal_code: Optional[str] = None
+
+ region: Optional[str] = None
+
+
+class Limit(BaseModel):
+ """The spending limit configuration."""
+
+ amount: float
+ """The limit amount in dollars."""
+
+ frequency: str
+ """The limit window, for example per24HourPeriod or perAuthorization."""
+
+
+class Secrets(BaseModel):
+ """The card's sensitive details.
+
+ Only present on GET /cards/:card_id (retrieve); null for cards that are not active or whose details could not be retrieved.
+ """
+
+ card_number: str
+ """The full card number."""
+
+ cvc: str
+ """The card verification code."""
+
+ name_on_card: Optional[str] = None
+ """The cardholder name printed on the card."""
+
+
+class CardRetrieveResponse(BaseModel):
+ id: str
+ """The icrd\\__ identifier of the card."""
+
+ billing: Optional[Billing] = None
+ """The billing address."""
+
+ canceled_at: Optional[datetime] = None
+
+ created_at: Optional[datetime] = None
+
+ expiration_month: Optional[str] = None
+
+ expiration_year: Optional[str] = None
+
+ last4: Optional[str] = None
+ """The last 4 digits of the card number. Null for pending invitation cards."""
+
+ limit: Optional[Limit] = None
+ """The spending limit configuration."""
+
+ name: Optional[str] = None
+
+ object: Literal["card"]
+
+ spent_last_month: Optional[int] = None
+ """Total spend in the last 30 days, in cents."""
+
+ status: Optional[Literal["active", "frozen", "canceled", "invited"]] = None
+ """The card status."""
+
+ type: Optional[Literal["virtual", "physical"]] = None
+ """The card type."""
+
+ user_id: Optional[str] = None
+ """The user\\__ identifier of the cardholder, when assigned."""
+
+ secrets: Optional[Secrets] = None
+ """The card's sensitive details.
+
+ Only present on GET /cards/:card_id (retrieve); null for cards that are not
+ active or whose details could not be retrieved.
+ """
diff --git a/src/whop_sdk/types/chat_message_created_webhook_event.py b/src/whop_sdk/types/chat_message_created_webhook_event.py
new file mode 100644
index 00000000..6f5c6493
--- /dev/null
+++ b/src/whop_sdk/types/chat_message_created_webhook_event.py
@@ -0,0 +1,54 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .shared.message import Message
+
+__all__ = ["ChatMessageCreatedWebhookEvent", "Data", "DataAudience", "DataChannel"]
+
+
+class DataAudience(BaseModel):
+ type: Literal["channel", "users"]
+
+ user_ids: Optional[List[str]] = None
+
+
+class DataChannel(BaseModel):
+ id: str
+
+ type: Literal["chat", "direct_message", "support"]
+
+ experience_id: Optional[str] = None
+
+
+class Data(BaseModel):
+ audience: DataAudience
+
+ channel: DataChannel
+
+ message: Message
+ """A message sent within an experience chat, direct message, or group chat."""
+
+ reason: str
+
+
+class ChatMessageCreatedWebhookEvent(BaseModel):
+ id: str
+ """A unique ID for every single webhook request"""
+
+ api_version: Literal["v1"]
+ """The API version for this webhook"""
+
+ data: Data
+
+ timestamp: datetime
+ """The timestamp in ISO 8601 format that the webhook was sent at on the server"""
+
+ type: Literal["chat.message.created"]
+ """The webhook event type"""
+
+ company_id: Optional[str] = None
+ """The company ID that this webhook event is associated with"""
diff --git a/src/whop_sdk/types/chat_reaction_created_webhook_event.py b/src/whop_sdk/types/chat_reaction_created_webhook_event.py
new file mode 100644
index 00000000..fe79585c
--- /dev/null
+++ b/src/whop_sdk/types/chat_reaction_created_webhook_event.py
@@ -0,0 +1,58 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .shared.message import Message
+from .shared.reaction import Reaction
+
+__all__ = ["ChatReactionCreatedWebhookEvent", "Data", "DataAudience", "DataChannel"]
+
+
+class DataAudience(BaseModel):
+ type: Literal["channel", "users"]
+
+ user_ids: Optional[List[str]] = None
+
+
+class DataChannel(BaseModel):
+ id: str
+
+ type: Literal["chat", "direct_message", "support"]
+
+ experience_id: Optional[str] = None
+
+
+class Data(BaseModel):
+ audience: DataAudience
+
+ channel: DataChannel
+
+ message: Message
+ """A message sent within an experience chat, direct message, or group chat."""
+
+ reaction: Reaction
+ """A single reaction left by a user on a feed post, such as a like or emoji."""
+
+ reason: str
+
+
+class ChatReactionCreatedWebhookEvent(BaseModel):
+ id: str
+ """A unique ID for every single webhook request"""
+
+ api_version: Literal["v1"]
+ """The API version for this webhook"""
+
+ data: Data
+
+ timestamp: datetime
+ """The timestamp in ISO 8601 format that the webhook was sent at on the server"""
+
+ type: Literal["chat.reaction.created"]
+ """The webhook event type"""
+
+ company_id: Optional[str] = None
+ """The company ID that this webhook event is associated with"""
diff --git a/src/whop_sdk/types/checkout_configuration_create_params.py b/src/whop_sdk/types/checkout_configuration_create_params.py
index de81ec08..42954cbc 100644
--- a/src/whop_sdk/types/checkout_configuration_create_params.py
+++ b/src/whop_sdk/types/checkout_configuration_create_params.py
@@ -2,539 +2,128 @@
from __future__ import annotations
-from typing import Dict, List, Union, Iterable, Optional
-from typing_extensions import Literal, Required, TypeAlias, TypedDict
-
-from .checkout_font import CheckoutFont
-from .checkout_shape import CheckoutShape
-from .shared.currency import Currency
-from .shared.tax_type import TaxType
-from .shared.plan_type import PlanType
-from .shared.visibility import Visibility
-from .payment_method_types import PaymentMethodTypes
-from .shared.release_method import ReleaseMethod
-from .shared.global_affiliate_status import GlobalAffiliateStatus
-
-__all__ = [
- "CheckoutConfigurationCreateParams",
- "CreateCheckoutSessionInputModePaymentWithPlan",
- "CreateCheckoutSessionInputModePaymentWithPlanPlan",
- "CreateCheckoutSessionInputModePaymentWithPlanPlanCustomField",
- "CreateCheckoutSessionInputModePaymentWithPlanPlanImage",
- "CreateCheckoutSessionInputModePaymentWithPlanPlanPaymentMethodConfiguration",
- "CreateCheckoutSessionInputModePaymentWithPlanPlanProduct",
- "CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling",
- "CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration",
- "CreateCheckoutSessionInputModePaymentWithPlanID",
- "CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling",
- "CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration",
- "CreateCheckoutSessionInputModeSetup",
- "CreateCheckoutSessionInputModeSetupCheckoutStyling",
- "CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration",
-]
-
-
-class CreateCheckoutSessionInputModePaymentWithPlan(TypedDict, total=False):
- plan: Required[CreateCheckoutSessionInputModePaymentWithPlanPlan]
- """
- The plan attributes to create a new plan inline for this checkout configuration.
- """
-
- affiliate_code: Optional[str]
- """An affiliate tracking code to attribute the checkout to a specific affiliate."""
-
- allow_promo_codes: Optional[bool]
- """
- Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
- """
-
- checkout_styling: Optional[CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling]
- """Checkout styling overrides for this session.
-
- Overrides plan and company defaults.
- """
-
- currency: Optional[Currency]
- """The available currencies on the platform"""
-
- metadata: Optional[Dict[str, object]]
- """Custom key-value metadata to attach to the checkout configuration."""
-
- mode: Literal["payment"]
-
- payment_method_configuration: Optional[CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration]
- """The explicit payment method configuration for the checkout session.
-
- Only applies to setup mode. If not provided, the platform or company defaults
- will apply.
- """
-
- redirect_url: Optional[str]
- """The URL to redirect the user to after checkout is completed."""
-
- source_url: Optional[str]
- """The URL of the page where the checkout is being initiated from."""
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanPlanCustomField(TypedDict, total=False):
- field_type: Required[Literal["text"]]
- """The type of the custom field."""
-
- name: Required[str]
- """The name of the custom field."""
-
- id: Optional[str]
- """The ID of the custom field (if being updated)"""
+from typing import Optional
+from typing_extensions import Literal, TypedDict
- order: Optional[int]
- """The order of the field."""
+from .._types import SequenceNotStr
- placeholder: Optional[str]
- """The placeholder value of the field."""
+__all__ = ["CheckoutConfigurationCreateParams", "PaymentMethodConfiguration", "Plan", "PlanPaymentMethodConfiguration"]
- required: Optional[bool]
- """Whether or not the field is required."""
+class CheckoutConfigurationCreateParams(TypedDict, total=False):
+ affiliate_code: Optional[str]
+ """An affiliate code to apply."""
-class CreateCheckoutSessionInputModePaymentWithPlanPlanImage(TypedDict, total=False):
- """An image for the plan. This will be visible on the product page to customers."""
-
- id: Required[str]
- """The ID of an existing file object."""
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanPlanPaymentMethodConfiguration(TypedDict, total=False):
- """The explicit payment method configuration for the plan.
-
- If not provided, the platform or company's defaults will apply.
- """
-
- disabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
-
- enabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly enabled.
-
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: Optional[bool]
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanPlanProduct(TypedDict, total=False):
- """Pass this object to create a new product for this plan.
-
- We will use the product external identifier to find or create an existing product.
- """
+ company_id: str
+ """The ID of the company."""
- external_identifier: Required[str]
- """A unique ID used to find or create a product.
+ currency: Optional[str]
+ """The currency code."""
- When provided during creation, we will look for an existing product with this
- external identifier — if found, it will be updated; otherwise, a new product
- will be created.
- """
+ metadata: Optional[object]
+ """Arbitrary key-value metadata."""
- title: Required[str]
- """The title of the product."""
+ mode: Literal["payment", "setup"]
+ """Checkout mode. Defaults to 'payment'."""
- collect_shipping_address: Optional[bool]
- """Whether or not to collect shipping information at checkout from the customer."""
+ payment_method_configuration: Optional[PaymentMethodConfiguration]
- custom_statement_descriptor: Optional[str]
- """The custom statement descriptor for the product i.e.
+ plan: Optional[Plan]
+ """Plan attributes to create a new plan inline for this checkout configuration.
- WHOP\\**SPORTS, must be between 5 and 22 characters, contain at least one letter,
- and not contain any of the following characters: <, >, \\,, ', "
+ Mutually exclusive with plan_id.
"""
- description: Optional[str]
- """A written description of the product."""
-
- global_affiliate_percentage: Optional[float]
- """The percentage of the revenue that goes to the global affiliate program."""
+ plan_id: Optional[str]
+ """The ID of an existing plan to attach."""
- global_affiliate_status: Optional[GlobalAffiliateStatus]
- """The different statuses of the global affiliate program for a product."""
+ redirect_url: Optional[str]
+ """URL to redirect after checkout."""
- headline: Optional[str]
- """The headline of the product."""
+ three_ds_level: Optional[str]
+ """3D Secure enforcement level."""
- product_tax_code_id: Optional[str]
- """The ID of the product tax code to apply to this product."""
- redirect_purchase_url: Optional[str]
- """The URL to redirect the customer to after a purchase."""
+class PaymentMethodConfiguration(TypedDict, total=False):
+ disabled: SequenceNotStr[str]
- route: Optional[str]
- """The route of the product."""
+ enabled: SequenceNotStr[str]
- visibility: Optional[Visibility]
- """Visibility of a resource"""
+ include_platform_defaults: bool
-class CreateCheckoutSessionInputModePaymentWithPlanPlan(TypedDict, total=False):
- """
- The plan attributes to create a new plan inline for this checkout configuration.
- """
+class PlanPaymentMethodConfiguration(TypedDict, total=False):
+ disabled: SequenceNotStr[str]
- company_id: Required[str]
- """The company the plan should be created for."""
+ enabled: SequenceNotStr[str]
- currency: Required[Currency]
- """The respective currency identifier for the plan."""
+ include_platform_defaults: bool
- adaptive_pricing_enabled: Optional[bool]
- """Whether this plan accepts local currency payments via adaptive pricing."""
- application_fee_amount: Optional[float]
- """The application fee amount collected by the platform from this connected
- account.
+class Plan(TypedDict, total=False):
+ """Plan attributes to create a new plan inline for this checkout configuration.
- Provided as a number in dollars (e.g., 5.00 for $5.00). Must be less than the
- total payment amount. Only valid for connected accounts with a parent company.
+ Mutually exclusive with plan_id.
"""
billing_period: Optional[int]
- """The interval in days at which the plan charges (renewal plans).
+ """The number of days between recurring charges."""
- For example, 30 for monthly billing.
+ company_id: Optional[str]
+ """The company the plan should be created for.
+
+ Defaults to the company resolved from the request.
"""
- custom_fields: Optional[Iterable[CreateCheckoutSessionInputModePaymentWithPlanPlanCustomField]]
- """An array of custom field objects."""
+ currency: Optional[str]
+ """The three-letter ISO currency code for the plan's pricing."""
description: Optional[str]
- """The description of the plan."""
+ """A text description of the plan displayed to customers."""
expiration_days: Optional[int]
- """The number of days until the membership expires (for expiration-based plans).
-
- For example, 365 for a one-year access pass.
- """
+ """The number of days until the membership expires."""
force_create_new_plan: Optional[bool]
- """
- Whether to force the creation of a new plan even if one with the same attributes
- already exists.
- """
-
- image: Optional[CreateCheckoutSessionInputModePaymentWithPlanPlanImage]
- """An image for the plan. This will be visible on the product page to customers."""
+ """Force creating a new plan even if one with the same attributes already exists."""
initial_price: Optional[float]
- """An additional amount charged upon first purchase.
+ """The amount charged on the first purchase, in the plan's currency."""
- Provided as a number in dollars (e.g., 10.00 for $10.00).
- """
+ metadata: Optional[object]
+ """Custom key-value metadata to store on the plan."""
- internal_notes: Optional[str]
- """A personal description or notes section for the business."""
+ override_tax_type: Optional[str]
+ """Override the default tax classification for this plan."""
- override_tax_type: Optional[TaxType]
- """
- Whether or not the tax is included in a plan's price (or if it hasn't been set
- up)
- """
+ payment_method_configuration: Optional[PlanPaymentMethodConfiguration]
- payment_method_configuration: Optional[CreateCheckoutSessionInputModePaymentWithPlanPlanPaymentMethodConfiguration]
- """The explicit payment method configuration for the plan.
-
- If not provided, the platform or company's defaults will apply.
- """
-
- plan_type: Optional[PlanType]
- """The type of plan that can be attached to a product"""
-
- product: Optional[CreateCheckoutSessionInputModePaymentWithPlanPlanProduct]
- """Pass this object to create a new product for this plan.
-
- We will use the product external identifier to find or create an existing
- product.
- """
+ plan_type: Optional[str]
+ """The billing model for the plan, e.g. 'one_time' or 'renewal'."""
product_id: Optional[str]
- """The product the plan is related to. Either this or product is required."""
+ """The ID of an existing product (access pass) to attach the plan to."""
- release_method: Optional[ReleaseMethod]
- """The methods of how a plan can be released."""
+ release_method: Optional[str]
+ """How the plan is sold, e.g. 'buy_now'."""
renewal_price: Optional[float]
- """The amount the customer is charged every billing period.
-
- Provided as a number in dollars (e.g., 9.99 for $9.99/period).
"""
-
- split_pay_required_payments: Optional[int]
- """The number of payments required before pausing the subscription."""
+ The amount charged each billing period for recurring plans, in the plan's
+ currency.
+ """
stock: Optional[int]
- """The number of units available for purchase.
-
- If not provided, stock is unlimited.
- """
+ """The maximum number of units available for purchase."""
title: Optional[str]
- """The title of the plan. This will be visible on the product page to customers."""
+ """The display name of the plan shown to customers."""
trial_period_days: Optional[int]
- """The number of free trial days added before a renewal plan."""
-
- visibility: Optional[Visibility]
- """Visibility of a resource"""
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanCheckoutStyling(TypedDict, total=False):
- """Checkout styling overrides for this session.
-
- Overrides plan and company defaults.
- """
-
- background_color: Optional[str]
- """
- A hex color code for the checkout page background, applied to the order summary
- panel (e.g. #F4F4F5).
- """
-
- border_style: Optional[CheckoutShape]
- """The different border-radius styles available for checkout pages."""
-
- button_color: Optional[str]
- """A hex color code for the button color (e.g. #FF5733)."""
-
- font_family: Optional[CheckoutFont]
- """The different font families available for checkout pages."""
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanPaymentMethodConfiguration(TypedDict, total=False):
- """The explicit payment method configuration for the checkout session.
-
- Only applies to setup mode. If not provided, the platform or company defaults will apply.
- """
-
- disabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
-
- enabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly enabled.
-
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: Optional[bool]
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanID(TypedDict, total=False):
- plan_id: Required[str]
- """
- The unique identifier of an existing plan to use for this checkout
- configuration.
- """
-
- affiliate_code: Optional[str]
- """An affiliate tracking code to attribute the checkout to a specific affiliate."""
-
- allow_promo_codes: Optional[bool]
- """
- Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
- """
-
- checkout_styling: Optional[CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling]
- """Checkout styling overrides for this session.
-
- Overrides plan and company defaults.
- """
-
- currency: Optional[Currency]
- """The available currencies on the platform"""
-
- metadata: Optional[Dict[str, object]]
- """Custom key-value metadata to attach to the checkout configuration."""
-
- mode: Literal["payment"]
-
- payment_method_configuration: Optional[CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration]
- """The explicit payment method configuration for the checkout session.
-
- Only applies to setup mode. If not provided, the platform or company defaults
- will apply.
- """
-
- redirect_url: Optional[str]
- """The URL to redirect the user to after checkout is completed."""
-
- source_url: Optional[str]
- """The URL of the page where the checkout is being initiated from."""
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanIDCheckoutStyling(TypedDict, total=False):
- """Checkout styling overrides for this session.
-
- Overrides plan and company defaults.
- """
-
- background_color: Optional[str]
- """
- A hex color code for the checkout page background, applied to the order summary
- panel (e.g. #F4F4F5).
- """
-
- border_style: Optional[CheckoutShape]
- """The different border-radius styles available for checkout pages."""
-
- button_color: Optional[str]
- """A hex color code for the button color (e.g. #FF5733)."""
-
- font_family: Optional[CheckoutFont]
- """The different font families available for checkout pages."""
-
-
-class CreateCheckoutSessionInputModePaymentWithPlanIDPaymentMethodConfiguration(TypedDict, total=False):
- """The explicit payment method configuration for the checkout session.
-
- Only applies to setup mode. If not provided, the platform or company defaults will apply.
- """
-
- disabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
-
- enabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly enabled.
-
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: Optional[bool]
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
-
-
-class CreateCheckoutSessionInputModeSetup(TypedDict, total=False):
- company_id: Required[str]
- """The unique identifier of the company to create the checkout configuration for.
-
- Only required in setup mode.
- """
-
- mode: Required[Literal["setup"]]
-
- allow_promo_codes: Optional[bool]
- """
- Whether the checkout should show the promo code input field and accept promo
- codes. Defaults to true.
- """
-
- checkout_styling: Optional[CreateCheckoutSessionInputModeSetupCheckoutStyling]
- """Checkout styling overrides for this session.
-
- Overrides plan and company defaults.
- """
-
- currency: Optional[Currency]
- """The available currencies on the platform"""
-
- metadata: Optional[Dict[str, object]]
- """Custom key-value metadata to attach to the checkout configuration."""
-
- payment_method_configuration: Optional[CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration]
- """The explicit payment method configuration for the checkout session.
-
- Only applies to setup mode. If not provided, the platform or company defaults
- will apply.
- """
-
- redirect_url: Optional[str]
- """The URL to redirect the user to after checkout is completed."""
-
- source_url: Optional[str]
- """The URL of the page where the checkout is being initiated from."""
-
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]]
- """The 3D Secure behavior for a plan."""
-
-
-class CreateCheckoutSessionInputModeSetupCheckoutStyling(TypedDict, total=False):
- """Checkout styling overrides for this session.
-
- Overrides plan and company defaults.
- """
-
- background_color: Optional[str]
- """
- A hex color code for the checkout page background, applied to the order summary
- panel (e.g. #F4F4F5).
- """
-
- border_style: Optional[CheckoutShape]
- """The different border-radius styles available for checkout pages."""
-
- button_color: Optional[str]
- """A hex color code for the button color (e.g. #FF5733)."""
-
- font_family: Optional[CheckoutFont]
- """The different font families available for checkout pages."""
-
-
-class CreateCheckoutSessionInputModeSetupPaymentMethodConfiguration(TypedDict, total=False):
- """The explicit payment method configuration for the checkout session.
-
- Only applies to setup mode. If not provided, the platform or company defaults will apply.
- """
-
- disabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
-
- enabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly enabled.
-
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: Optional[bool]
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
+ """The number of free trial days before the first charge."""
+ unlimited_stock: Optional[bool]
+ """Whether the plan has unlimited stock."""
-CheckoutConfigurationCreateParams: TypeAlias = Union[
- CreateCheckoutSessionInputModePaymentWithPlan,
- CreateCheckoutSessionInputModePaymentWithPlanID,
- CreateCheckoutSessionInputModeSetup,
-]
+ visibility: Optional[str]
+ """Whether the plan is visible to customers or hidden."""
diff --git a/src/whop_sdk/types/checkout_configuration_create_response.py b/src/whop_sdk/types/checkout_configuration_create_response.py
new file mode 100644
index 00000000..0e2c7e79
--- /dev/null
+++ b/src/whop_sdk/types/checkout_configuration_create_response.py
@@ -0,0 +1,52 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["CheckoutConfigurationCreateResponse"]
+
+
+class CheckoutConfigurationCreateResponse(BaseModel):
+ id: str
+ """The unique identifier of the checkout configuration."""
+
+ company_id: str
+ """The ID of the company that owns this checkout configuration."""
+
+ created_at: int
+ """Unix timestamp when the checkout configuration was created."""
+
+ mode: Literal["payment", "setup"]
+ """The checkout mode."""
+
+ updated_at: int
+ """Unix timestamp when the checkout configuration was last updated."""
+
+ affiliate_code: Optional[str] = None
+ """The affiliate code applied at checkout."""
+
+ currency: Optional[str] = None
+ """The currency for this checkout configuration."""
+
+ metadata: Optional[object] = None
+ """Arbitrary key-value metadata.
+
+ Only returned when caller has checkout_configuration:basic:read scope.
+ """
+
+ payment_method_configuration: Optional[object] = None
+ """Payment method configuration."""
+
+ plan: Optional[object] = None
+ """The plan associated with this checkout configuration."""
+
+ purchase_url: Optional[str] = None
+ """The URL for the checkout page."""
+
+ redirect_url: Optional[str] = None
+ """The URL to redirect after checkout."""
+
+ three_ds_level: Optional[str] = None
+ """The 3D Secure enforcement level."""
diff --git a/src/whop_sdk/types/checkout_configuration_list_params.py b/src/whop_sdk/types/checkout_configuration_list_params.py
index b2770334..bd593714 100644
--- a/src/whop_sdk/types/checkout_configuration_list_params.py
+++ b/src/whop_sdk/types/checkout_configuration_list_params.py
@@ -2,43 +2,29 @@
from __future__ import annotations
-from typing import Union, Optional
-from datetime import datetime
-from typing_extensions import Required, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-from .shared.direction import Direction
+from typing_extensions import Required, TypedDict
__all__ = ["CheckoutConfigurationListParams"]
class CheckoutConfigurationListParams(TypedDict, total=False):
company_id: Required[str]
- """The unique identifier of the company to list checkout configurations 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."""
+ """The ID of the company to list checkout configurations for."""
- created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Only return checkout configurations created after this timestamp."""
+ after: str
+ """Cursor for forward pagination."""
- created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Only return checkout configurations created before this timestamp."""
+ created_after: int
+ """Filter to configurations created after this Unix timestamp."""
- direction: Optional[Direction]
- """The direction of the sort."""
+ created_before: int
+ """Filter to configurations created before this Unix timestamp."""
- first: Optional[int]
- """Returns the first _n_ elements from the list."""
+ direction: str
+ """Sort direction: asc or desc. Defaults to desc."""
- last: Optional[int]
- """Returns the last _n_ elements from the list."""
+ first: int
+ """Number of results to return (forward pagination)."""
- plan_id: Optional[str]
- """
- Filter checkout configurations to only those associated with this plan
- identifier.
- """
+ plan_id: str
+ """Filter by plan ID."""
diff --git a/src/whop_sdk/types/checkout_configuration_list_response.py b/src/whop_sdk/types/checkout_configuration_list_response.py
index be80192b..5c1348c2 100644
--- a/src/whop_sdk/types/checkout_configuration_list_response.py
+++ b/src/whop_sdk/types/checkout_configuration_list_response.py
@@ -1,163 +1,52 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, List, Optional
+from typing import Optional
from typing_extensions import Literal
from .._models import BaseModel
-from .checkout_modes import CheckoutModes
-from .shared.currency import Currency
-from .shared.plan_type import PlanType
-from .shared.visibility import Visibility
-from .payment_method_types import PaymentMethodTypes
-from .shared.release_method import ReleaseMethod
-__all__ = ["CheckoutConfigurationListResponse", "PaymentMethodConfiguration", "Plan"]
-
-
-class PaymentMethodConfiguration(BaseModel):
- """The explicit payment method configuration for the session, if any.
-
- This currently only works in 'setup' mode. Use the plan's payment_method_configuration for payment method.
- """
-
- disabled: List[PaymentMethodTypes]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
-
- enabled: List[PaymentMethodTypes]
- """An array of payment method identifiers that are explicitly enabled.
-
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: bool
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
-
-
-class Plan(BaseModel):
- """The plan to use for the checkout configuration"""
-
- id: str
- """The unique identifier for the plan."""
-
- adaptive_pricing_enabled: bool
- """Whether the creator has turned on adaptive pricing for this plan.
-
- Raw setting — does not check processor compatibility or feature flags.
- """
-
- billing_period: Optional[int] = None
- """The number of days between each recurring charge.
-
- Null for one-time plans. For example, 30 for monthly or 365 for annual billing.
- """
-
- currency: Currency
- """The currency used for all prices on this plan (e.g., 'usd', 'eur').
-
- All monetary amounts on the plan are denominated in this currency.
- """
-
- expiration_days: Optional[int] = None
- """The number of days until the membership expires (for expiration-based plans).
-
- For example, 365 for a one-year access pass.
- """
-
- initial_price: float
- """The initial purchase price in the plan's base_currency (e.g., 49.99 for $49.99).
-
- For one-time plans, this is the full price. For renewal plans, this is charged
- on top of the first renewal_price.
- """
-
- plan_type: PlanType
- """
- The billing model for this plan: 'renewal' for recurring subscriptions or
- 'one_time' for single payments.
- """
-
- release_method: ReleaseMethod
- """
- The method used to sell this plan: 'buy_now' for immediate purchase or
- 'waitlist' for waitlist-based access.
- """
-
- renewal_price: float
- """
- The recurring price charged every billing_period in the plan's base_currency
- (e.g., 9.99 for $9.99/period). Zero for one-time plans.
- """
-
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] = None
- """The 3D Secure behavior for a plan."""
-
- trial_period_days: Optional[int] = None
- """The number of free trial days before the first charge on a renewal plan.
-
- Null if no trial is configured or the current user has already used a trial for
- this plan.
- """
-
- visibility: Visibility
- """Controls whether the plan is visible to customers.
-
- When set to 'hidden', the plan is only accessible via direct link.
- """
+__all__ = ["CheckoutConfigurationListResponse"]
class CheckoutConfigurationListResponse(BaseModel):
- """
- A checkout configuration is a reusable configuration for a checkout, including the plan, affiliate, and custom metadata. Payments and memberships created from a checkout session inherit its metadata.
- """
-
id: str
- """The unique identifier for the checkout session."""
-
- affiliate_code: Optional[str] = None
- """The affiliate code to use for the checkout configuration"""
+ """The unique identifier of the checkout configuration."""
- allow_promo_codes: bool
- """Whether the checkout configuration allows promo codes.
+ company_id: str
+ """The ID of the company that owns this checkout configuration."""
- When false, the promo code input is hidden and promo codes are rejected.
- """
+ created_at: int
+ """Unix timestamp when the checkout configuration was created."""
- company_id: str
- """The ID of the company to use for the checkout configuration"""
+ mode: Literal["payment", "setup"]
+ """The checkout mode."""
- currency: Optional[Currency] = None
- """The available currencies on the platform"""
+ updated_at: int
+ """Unix timestamp when the checkout configuration was last updated."""
- metadata: Optional[Dict[str, object]] = None
- """The metadata to use for the checkout configuration"""
+ affiliate_code: Optional[str] = None
+ """The affiliate code applied at checkout."""
- mode: CheckoutModes
- """The mode of the checkout session."""
+ currency: Optional[str] = None
+ """The currency for this checkout configuration."""
- payment_method_configuration: Optional[PaymentMethodConfiguration] = None
- """The explicit payment method configuration for the session, if any.
+ metadata: Optional[object] = None
+ """Arbitrary key-value metadata.
- This currently only works in 'setup' mode. Use the plan's
- payment_method_configuration for payment method.
+ Only returned when caller has checkout_configuration:basic:read scope.
"""
- plan: Optional[Plan] = None
- """The plan to use for the checkout configuration"""
+ payment_method_configuration: Optional[object] = None
+ """Payment method configuration."""
- purchase_url: str
- """A URL you can send to customers to complete a checkout.
+ plan: Optional[object] = None
+ """The plan associated with this checkout configuration."""
- It looks like `/checkout/plan_xxxx?session={id}`
- """
+ purchase_url: Optional[str] = None
+ """The URL for the checkout page."""
redirect_url: Optional[str] = None
- """The URL to redirect the user to after the checkout configuration is created"""
+ """The URL to redirect after checkout."""
+
+ three_ds_level: Optional[str] = None
+ """The 3D Secure enforcement level."""
diff --git a/src/whop_sdk/types/checkout_configuration_retrieve_response.py b/src/whop_sdk/types/checkout_configuration_retrieve_response.py
new file mode 100644
index 00000000..cbaf3704
--- /dev/null
+++ b/src/whop_sdk/types/checkout_configuration_retrieve_response.py
@@ -0,0 +1,52 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["CheckoutConfigurationRetrieveResponse"]
+
+
+class CheckoutConfigurationRetrieveResponse(BaseModel):
+ id: str
+ """The unique identifier of the checkout configuration."""
+
+ company_id: str
+ """The ID of the company that owns this checkout configuration."""
+
+ created_at: int
+ """Unix timestamp when the checkout configuration was created."""
+
+ mode: Literal["payment", "setup"]
+ """The checkout mode."""
+
+ updated_at: int
+ """Unix timestamp when the checkout configuration was last updated."""
+
+ affiliate_code: Optional[str] = None
+ """The affiliate code applied at checkout."""
+
+ currency: Optional[str] = None
+ """The currency for this checkout configuration."""
+
+ metadata: Optional[object] = None
+ """Arbitrary key-value metadata.
+
+ Only returned when caller has checkout_configuration:basic:read scope.
+ """
+
+ payment_method_configuration: Optional[object] = None
+ """Payment method configuration."""
+
+ plan: Optional[object] = None
+ """The plan associated with this checkout configuration."""
+
+ purchase_url: Optional[str] = None
+ """The URL for the checkout page."""
+
+ redirect_url: Optional[str] = None
+ """The URL to redirect after checkout."""
+
+ three_ds_level: Optional[str] = None
+ """The 3D Secure enforcement level."""
diff --git a/src/whop_sdk/types/conversion_create_params.py b/src/whop_sdk/types/conversion_create_params.py
index e833dba0..091a72f0 100644
--- a/src/whop_sdk/types/conversion_create_params.py
+++ b/src/whop_sdk/types/conversion_create_params.py
@@ -17,7 +17,17 @@ class ConversionCreateParams(TypedDict, total=False):
"""The company to associate with this event."""
event_name: Required[
- Literal["lead", "submit_application", "contact", "complete_registration", "schedule", "custom"]
+ Literal[
+ "lead",
+ "submit_application",
+ "contact",
+ "complete_registration",
+ "schedule",
+ "view_content",
+ "add_to_cart",
+ "custom",
+ "page",
+ ]
]
"""The type of event."""
@@ -43,7 +53,10 @@ class ConversionCreateParams(TypedDict, total=False):
"""The available currencies on the platform"""
custom_name: Optional[str]
- """Custom event name when event_name is 'custom'."""
+ """Custom event name when event_name is 'custom'. Maximum 35 chars for this value."""
+
+ duration: Optional[int]
+ """For 'leave' events: milliseconds the visitor spent on the page."""
event_id: Optional[str]
"""Client-provided identifier for deduplication. Generated if omitted."""
@@ -60,6 +73,18 @@ class ConversionCreateParams(TypedDict, total=False):
referrer_url: Optional[str]
"""The referring URL."""
+ resumed: Optional[bool]
+ """For 'page' events: true when the page was restored from the back/forward cache."""
+
+ source: Optional[str]
+ """
+ For 'identify' events: where the identity was captured (url, form, manual,
+ iframe).
+ """
+
+ title: Optional[str]
+ """For 'page' events: the document title."""
+
url: Optional[str]
"""The URL where the event occurred."""
@@ -82,15 +107,27 @@ class Context(TypedDict, total=False):
ad_set_id: Optional[str]
"""Ad set ID."""
+ fbc: Optional[str]
+ """Facebook click cookie (\\__fbc, format fb.1.{timestamp}.{fbclid})."""
+
fbclid: Optional[str]
"""Facebook click ID."""
fbp: Optional[str]
"""Facebook browser pixel ID."""
+ fingerprint: Optional[str]
+ """Client-side device fingerprint."""
+
+ fingerprint_confidence: Optional[float]
+ """Confidence score (0-1) for the device fingerprint."""
+
ga: Optional[str]
"""Google Analytics client ID."""
+ gbraid: Optional[str]
+ """Google Ads gbraid click ID (iOS privacy)."""
+
gclid: Optional[str]
"""Google click ID."""
@@ -100,12 +137,36 @@ class Context(TypedDict, total=False):
ip_address: Optional[str]
"""IP address."""
+ language: Optional[str]
+ """Browser language (e.g. en-US)."""
+
+ li_fat_id: Optional[str]
+ """LinkedIn click ID."""
+
+ msclkid: Optional[str]
+ """Microsoft Advertising (Bing) click ID."""
+
+ rdt_cid: Optional[str]
+ """Reddit click ID."""
+
+ sccid: Optional[str]
+ """Snapchat click ID."""
+
+ screen_resolution: Optional[str]
+ """Screen resolution (e.g. 1920x1080)."""
+
+ timezone: Optional[str]
+ """IANA timezone (e.g. America/New_York)."""
+
ttclid: Optional[str]
"""TikTok click ID."""
ttp: Optional[str]
"""TikTok pixel ID."""
+ twclid: Optional[str]
+ """X (Twitter) click ID."""
+
user_agent: Optional[str]
"""Browser user agent string."""
@@ -127,6 +188,9 @@ class Context(TypedDict, total=False):
utm_term: Optional[str]
"""UTM term parameter."""
+ wbraid: Optional[str]
+ """Google Ads wbraid click ID (iOS privacy)."""
+
class User(TypedDict, total=False):
"""User identity and profile data."""
@@ -158,6 +222,15 @@ class User(TypedDict, total=False):
last_name: Optional[str]
"""Last name."""
+ linked_anonymous_id: Optional[str]
+ """A second anonymous identifier to link to this user (e.g.
+
+ captured across an iframe boundary).
+ """
+
+ linked_wuid: Optional[str]
+ """A wuid from a linked frame, captured across an iframe boundary."""
+
member_id: Optional[str]
"""The Whop member ID."""
diff --git a/src/whop_sdk/types/deposit_create_params.py b/src/whop_sdk/types/deposit_create_params.py
index 6f6da819..164d1b72 100644
--- a/src/whop_sdk/types/deposit_create_params.py
+++ b/src/whop_sdk/types/deposit_create_params.py
@@ -9,15 +9,15 @@
class DepositCreateParams(TypedDict, total=False):
- amount: Required[float]
- """Amount to deposit."""
-
destination: Required[Destination]
"""Destination account ID or wallet address.
Object form is supported for compatibility.
"""
+ amount: float
+ """Optional amount to deposit."""
+
metadata: Dict[str, object]
"""Arbitrary metadata echoed in the response."""
diff --git a/src/whop_sdk/types/deposit_create_response.py b/src/whop_sdk/types/deposit_create_response.py
index f0221451..d079f82f 100644
--- a/src/whop_sdk/types/deposit_create_response.py
+++ b/src/whop_sdk/types/deposit_create_response.py
@@ -1,38 +1,68 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, Optional
+from typing import Dict, List, Optional
from typing_extensions import Literal
from .._models import BaseModel
-__all__ = ["DepositCreateResponse", "DepositAddress", "Destination"]
+__all__ = ["DepositCreateResponse", "Methods", "MethodsBank", "MethodsBankCurrency", "MethodsCrypto"]
-class DepositAddress(BaseModel):
+class MethodsBankCurrency(BaseModel):
+ account_number: Optional[str] = None
+
+ currency: str
+
+ deposit_bank_name: Optional[str] = None
+
+ deposit_beneficiary_name: Optional[str] = None
+
+ deposit_reference: Optional[str] = None
+
+ rails: List[str]
+ """Active deposit rails for this currency, e.g. ach, wire, sepa."""
+
+ routing_number: Optional[str] = None
+
+
+class MethodsBank(BaseModel):
+ """Bank deposit details.
+
+ Only present when bank deposits are active for the destination account.
+ """
+
+ currencies: List[MethodsBankCurrency]
+
+
+class MethodsCrypto(BaseModel):
evm: str
solana: str
+ wallet: str
-class Destination(BaseModel):
- address: str
- currency: str
+class Methods(BaseModel):
+ bank: Optional[MethodsBank] = None
+ """Bank deposit details.
- network: str
+ Only present when bank deposits are active for the destination account.
+ """
- account_id: Optional[str] = None
+ crypto: MethodsCrypto
class DepositCreateResponse(BaseModel):
- amount: str
-
- deposit_address: DepositAddress
-
- destination: Destination
+ account_id: Optional[str] = None
+ """Account ID of the destination owner. Null for raw wallet address destinations."""
hosted_url: Optional[str] = None
+ """URL of the hosted deposit page. Only present for business destinations."""
metadata: Dict[str, object]
+ methods: Methods
+
object: Literal["deposit"]
+
+ amount: Optional[str] = None
diff --git a/src/whop_sdk/types/deposit_list_params.py b/src/whop_sdk/types/deposit_list_params.py
new file mode 100644
index 00000000..4b74a28d
--- /dev/null
+++ b/src/whop_sdk/types/deposit_list_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["DepositListParams"]
+
+
+class DepositListParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Business account ID (biz\\__\\**)."""
diff --git a/src/whop_sdk/types/deposit_list_response.py b/src/whop_sdk/types/deposit_list_response.py
new file mode 100644
index 00000000..d72522c2
--- /dev/null
+++ b/src/whop_sdk/types/deposit_list_response.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["DepositListResponse", "Bank"]
+
+
+class Bank(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ destination_amount: Optional[str] = None
+
+ destination_currency: Optional[str] = None
+
+ source_amount: str
+
+ source_currency: str
+
+ status: str
+
+
+class DepositListResponse(BaseModel):
+ account_id: str
+
+ bank: List[Bank]
+
+ object: Literal["deposits"]
diff --git a/src/whop_sdk/types/financial_activity_list_params.py b/src/whop_sdk/types/financial_activity_list_params.py
new file mode 100644
index 00000000..623ab738
--- /dev/null
+++ b/src/whop_sdk/types/financial_activity_list_params.py
@@ -0,0 +1,56 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import date, datetime
+from typing_extensions import Annotated, TypedDict
+
+from .._types import SequenceNotStr
+from .._utils import PropertyInfo
+
+__all__ = ["FinancialActivityListParams"]
+
+
+class FinancialActivityListParams(TypedDict, total=False):
+ account_id: str
+ """The owning account ID (a biz\\__ identifier). Provide this or user_id."""
+
+ available_after: Annotated[Union[str, date], PropertyInfo(format="iso8601")]
+ """
+ Only include rows whose funds became withdrawable on or after this YYYY-MM-DD
+ settlement date (UTC), distinct from posted_at. Requires currency.
+ """
+
+ available_before: Annotated[Union[str, date], PropertyInfo(format="iso8601")]
+ """
+ Only include rows whose funds became withdrawable on or before this YYYY-MM-DD
+ settlement date (UTC). Set equal to available_after for a single day. Requires
+ currency.
+ """
+
+ currency: str
+ """Optional currency code filter, for example usd."""
+
+ cursor: str
+ """Cursor returned by the previous page."""
+
+ limit: int
+ """Maximum number of rows to return."""
+
+ line_types: SequenceNotStr[str]
+ """Optional ledger line categories to include.
+
+ Some categories (for example onchain_deposit, which covers inbound crypto
+ deposits such as MoonPay onramps) are only returned when explicitly requested
+ here.
+ """
+
+ posted_after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]
+ """Only include rows posted after this ISO 8601 timestamp."""
+
+ posted_before: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]
+ """Only include rows posted before this ISO 8601 timestamp."""
+
+ user_id: str
+ """The owning user ID (a user\\__ identifier). Provide this or account_id."""
diff --git a/src/whop_sdk/types/financial_activity_list_response.py b/src/whop_sdk/types/financial_activity_list_response.py
new file mode 100644
index 00000000..7b21b302
--- /dev/null
+++ b/src/whop_sdk/types/financial_activity_list_response.py
@@ -0,0 +1,352 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import builtins
+from typing import TYPE_CHECKING, Dict, List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, TypeAlias
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+
+__all__ = [
+ "FinancialActivityListResponse",
+ "Data",
+ "DataCurrency",
+ "DataResource",
+ "DataResourceUnionMember0",
+ "DataResourceUnionMember1",
+ "DataResourceUnionMember2",
+ "DataResourceUnionMember2Owner",
+ "DataResourceUnionMember2OwnerUnionMember0",
+ "DataResourceUnionMember2OwnerUnionMember1",
+ "DataResourceUnionMember3",
+ "DataResourceUnionMember3Bank",
+ "DataResourceUnionMember3Card",
+ "DataResourceUnionMember4",
+ "DataResourceUnionMember5",
+ "DataSource",
+ "DataSourcePayoutDestination",
+ "PageInfo",
+]
+
+
+class DataCurrency(BaseModel):
+ code: str
+
+ precision: str
+ """Precision factor for the currency, for example 100000000 for USD."""
+
+
+class DataResourceUnionMember0(BaseModel):
+ id: str
+
+ logo_url: Optional[str] = None
+
+ object: Literal["account"]
+
+ route: Optional[str] = None
+
+ title: Optional[str] = None
+
+
+class DataResourceUnionMember1(BaseModel):
+ id: str
+
+ name: Optional[str] = None
+
+ object: Literal["user"]
+
+ profile_picture_url: Optional[str] = None
+
+ username: Optional[str] = None
+
+
+class DataResourceUnionMember2OwnerUnionMember0(BaseModel):
+ id: str
+
+ logo_url: Optional[str] = None
+
+ object: Literal["account"]
+
+ route: Optional[str] = None
+
+ title: Optional[str] = None
+
+
+class DataResourceUnionMember2OwnerUnionMember1(BaseModel):
+ id: str
+
+ name: Optional[str] = None
+
+ object: Literal["user"]
+
+ profile_picture_url: Optional[str] = None
+
+ username: Optional[str] = None
+
+
+DataResourceUnionMember2Owner: TypeAlias = Union[
+ DataResourceUnionMember2OwnerUnionMember0, DataResourceUnionMember2OwnerUnionMember1, None
+]
+
+
+class DataResourceUnionMember2(BaseModel):
+ id: str
+
+ object: Literal["ledger_account"]
+
+ owner: Optional[DataResourceUnionMember2Owner] = None
+
+
+class DataResourceUnionMember3Bank(BaseModel):
+ account_name: Optional[str] = None
+
+ account_type: Optional[str] = None
+
+ bank_name: Optional[str] = None
+
+ last4: Optional[str] = None
+
+
+class DataResourceUnionMember3Card(BaseModel):
+ brand: Optional[str] = None
+
+ exp_month: Optional[int] = None
+
+ exp_year: Optional[int] = None
+
+ last4: Optional[str] = None
+
+
+class DataResourceUnionMember3(BaseModel):
+ id: str
+
+ bank: Optional[DataResourceUnionMember3Bank] = None
+
+ card: Optional[DataResourceUnionMember3Card] = None
+
+ email_identifier: Optional[str] = None
+
+ gateway_type: Optional[str] = None
+
+ object: Literal["payment_method"]
+
+ payment_method_type: Optional[str] = None
+
+
+class DataResourceUnionMember4(BaseModel):
+ id: str
+
+ account_reference: Optional[str] = None
+
+ destination_currency_code: Optional[str] = None
+
+ institution_name: Optional[str] = None
+
+ nickname: Optional[str] = None
+
+ object: Literal["payout_method"]
+
+ provider: Optional[str] = None
+
+
+class DataResourceUnionMember5(BaseModel):
+ id: str
+
+ authorized_at: Optional[datetime] = None
+ """ISO 8601 timestamp the transaction was authorized."""
+
+ card_id: Optional[str] = None
+ """Identifier of the card that the transaction was charged to."""
+
+ cashback_usd: Optional[str] = None
+ """Cashback earned on this transaction as a USD decimal string.
+
+ Zero for declined or ineligible transactions; null when cashback has not been
+ computed yet.
+ """
+
+ declined_reason: Optional[str] = None
+ """Reason the transaction was declined (when status is declined)."""
+
+ local_amount: Optional[str] = None
+ """Amount the merchant charged in their local currency, as a decimal string.
+
+ Pair with local_currency.
+ """
+
+ local_currency: Optional[str] = None
+ """ISO 4217 currency code of the merchant-charged amount in local_amount."""
+
+ merchant_category: Optional[str] = None
+
+ merchant_icon_url: Optional[str] = None
+
+ merchant_name: Optional[str] = None
+
+ object: Literal["card_transaction"]
+
+ posted_at: Optional[datetime] = None
+ """ISO 8601 timestamp the transaction was settled by the card network."""
+
+ status: Optional[str] = None
+
+ usd_amount: Optional[str] = None
+ """The processor-settled USD amount as a decimal string.
+
+ The ledger's USDT leg is posted 1:1 from this value.
+ """
+
+
+DataResource: TypeAlias = Union[
+ DataResourceUnionMember0,
+ DataResourceUnionMember1,
+ DataResourceUnionMember2,
+ DataResourceUnionMember3,
+ DataResourceUnionMember4,
+ DataResourceUnionMember5,
+ None,
+]
+
+
+class DataSourcePayoutDestination(BaseModel):
+ """Payout destination display info (withdrawal sources only)."""
+
+ icon_url: Optional[str] = None
+
+ payer_name: Optional[str] = None
+
+
+class DataSource(BaseModel):
+ id: str
+
+ object: str
+
+ amount_float: Optional[float] = None
+ """
+ Withdrawal amount as a decimal number in the destination currency (withdrawal
+ sources only; requires payout:withdrawal:read).
+ """
+
+ chain: Optional[str] = None
+ """
+ Chain the deposit landed on, for example plasma (onchain_transaction sources
+ only).
+ """
+
+ claim_url: Optional[str] = None
+ """Public claim URL for the airdrop link (airdrop_link sources only)."""
+
+ created_at: Optional[datetime] = None
+ """
+ Withdrawal creation time as an ISO 8601 timestamp (withdrawal sources only;
+ requires payout:withdrawal:read).
+ """
+
+ estimated_arrival: Optional[datetime] = None
+ """
+ Estimated arrival as an ISO 8601 timestamp (withdrawal sources only; requires
+ payout:withdrawal:read).
+ """
+
+ from_amount: Optional[str] = None
+ """Amount converted out of from_currency as a decimal string (swap sources only)."""
+
+ from_currency: Optional[str] = None
+ """Lowercase currency code converted from (swap sources only)."""
+
+ payer_name: Optional[str] = None
+ """
+ Name of the entity processing the payout (withdrawal sources only; requires
+ payout:withdrawal:read).
+ """
+
+ payout_destination: Optional[DataSourcePayoutDestination] = None
+ """Payout destination display info (withdrawal sources only)."""
+
+ payout_token_nickname: Optional[str] = None
+ """Saved payout destination nickname (withdrawal sources only)."""
+
+ sender_address: Optional[str] = None
+ """
+ Sender wallet address or onramp provider identifier (onchain_transaction sources
+ only).
+ """
+
+ status: Optional[str] = None
+ """Lifecycle status.
+
+ On withdrawal sources this is the withdrawal status (requires
+ payout:withdrawal:read); on airdrop_link sources it is the claim-link status
+ (ungated); on payment and top-up sources it is the friendly payment status such
+ as succeeded/pending/failed (ungated).
+ """
+
+ to_amount: Optional[str] = None
+ """Amount received in to_currency as a decimal string (swap sources only)."""
+
+ to_currency: Optional[str] = None
+ """Lowercase currency code converted to (swap sources only)."""
+
+ tx_hash: Optional[str] = None
+ """On-chain transaction hash (onchain_transaction and swap sources only)."""
+
+ if TYPE_CHECKING:
+ # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a
+ # value to this field, so for compatibility we avoid doing it at runtime.
+ __pydantic_extra__: Dict[str, builtins.object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> builtins.object: ...
+ else:
+ __pydantic_extra__: Dict[str, builtins.object]
+
+
+class Data(BaseModel):
+ id: str
+
+ amount: str
+ """Signed amount in the currency's smallest precision units."""
+
+ available_at: Optional[datetime] = None
+ """
+ ISO 8601 timestamp these funds became (or are scheduled to become) withdrawable:
+ the posted time for already-settled funds, or 00:00:00 UTC on the scheduled
+ release date for pending funds. Present only on inflows entering the balance
+ (payments, top-ups, incoming transfers/affiliate); null on withdrawals, refunds,
+ disputes and on-chain rows. The available_after/before filters window on its UTC
+ settlement date.
+ """
+
+ created_at: Optional[datetime] = None
+
+ currency: DataCurrency
+
+ line_type: str
+
+ object: Literal["ledger_activity"]
+
+ posted_at: datetime
+
+ resource: Optional[DataResource] = None
+
+ source: Optional[DataSource] = None
+
+
+class PageInfo(BaseModel):
+ end_cursor: Optional[str] = None
+
+ has_next_page: bool
+
+ has_previous_page: bool
+
+ start_cursor: Optional[str] = None
+
+
+class FinancialActivityListResponse(BaseModel):
+ data: List[Data]
+
+ page_info: PageInfo
diff --git a/src/whop_sdk/types/granularities.py b/src/whop_sdk/types/granularities.py
index 1a199166..62928b01 100644
--- a/src/whop_sdk/types/granularities.py
+++ b/src/whop_sdk/types/granularities.py
@@ -4,4 +4,4 @@
__all__ = ["Granularities"]
-Granularities: TypeAlias = Literal["daily", "hourly"]
+Granularities: TypeAlias = Literal["hourly", "daily", "weekly", "monthly"]
diff --git a/src/whop_sdk/types/identity_profile_approved_webhook_event.py b/src/whop_sdk/types/identity_profile_approved_webhook_event.py
index f498efd8..7a737ae0 100644
--- a/src/whop_sdk/types/identity_profile_approved_webhook_event.py
+++ b/src/whop_sdk/types/identity_profile_approved_webhook_event.py
@@ -135,9 +135,9 @@ class Data(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166-1 alpha-3 country code (e.g.
+ """ISO 3166-1 alpha-2 country code (e.g.
- `USA`, `GBR`). For individuals this is the country of citizenship or residence
+ `US`, `GB`). For individuals this is the country of citizenship or residence
reported by the identity provider; for businesses this is the country of
incorporation.
"""
diff --git a/src/whop_sdk/types/identity_profile_needs_action_webhook_event.py b/src/whop_sdk/types/identity_profile_needs_action_webhook_event.py
index 83b88252..7f67727b 100644
--- a/src/whop_sdk/types/identity_profile_needs_action_webhook_event.py
+++ b/src/whop_sdk/types/identity_profile_needs_action_webhook_event.py
@@ -135,9 +135,9 @@ class Data(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166-1 alpha-3 country code (e.g.
+ """ISO 3166-1 alpha-2 country code (e.g.
- `USA`, `GBR`). For individuals this is the country of citizenship or residence
+ `US`, `GB`). For individuals this is the country of citizenship or residence
reported by the identity provider; for businesses this is the country of
incorporation.
"""
diff --git a/src/whop_sdk/types/identity_profile_rejected_webhook_event.py b/src/whop_sdk/types/identity_profile_rejected_webhook_event.py
index d6188520..9de64813 100644
--- a/src/whop_sdk/types/identity_profile_rejected_webhook_event.py
+++ b/src/whop_sdk/types/identity_profile_rejected_webhook_event.py
@@ -135,9 +135,9 @@ class Data(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166-1 alpha-3 country code (e.g.
+ """ISO 3166-1 alpha-2 country code (e.g.
- `USA`, `GBR`). For individuals this is the country of citizenship or residence
+ `US`, `GB`). For individuals this is the country of citizenship or residence
reported by the identity provider; for businesses this is the country of
incorporation.
"""
diff --git a/src/whop_sdk/types/identity_profile_updated_webhook_event.py b/src/whop_sdk/types/identity_profile_updated_webhook_event.py
index 23b9a859..cea15a83 100644
--- a/src/whop_sdk/types/identity_profile_updated_webhook_event.py
+++ b/src/whop_sdk/types/identity_profile_updated_webhook_event.py
@@ -135,9 +135,9 @@ class Data(BaseModel):
"""
country: Optional[str] = None
- """ISO 3166-1 alpha-3 country code (e.g.
+ """ISO 3166-1 alpha-2 country code (e.g.
- `USA`, `GBR`). For individuals this is the country of citizenship or residence
+ `US`, `GB`). For individuals this is the country of citizenship or residence
reported by the identity provider; for businesses this is the country of
incorporation.
"""
diff --git a/src/whop_sdk/types/invoice_create_params.py b/src/whop_sdk/types/invoice_create_params.py
index 8ff9b337..5a55a12b 100644
--- a/src/whop_sdk/types/invoice_create_params.py
+++ b/src/whop_sdk/types/invoice_create_params.py
@@ -7,6 +7,7 @@
from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
from .._utils import PropertyInfo
+from .shared.currency import Currency
from .shared.plan_type import PlanType
from .shared.visibility import Visibility
from .tax_identifier_type import TaxIdentifierType
@@ -192,6 +193,9 @@ class CreateInvoiceInputWithProductPlan(TypedDict, total=False):
billing_period: Optional[int]
"""The interval in days at which the plan charges (renewal plans)."""
+ currency: Optional[Currency]
+ """The available currencies on the platform"""
+
custom_fields: Optional[Iterable[CreateInvoiceInputWithProductPlanCustomField]]
"""An array of custom field objects."""
@@ -478,6 +482,9 @@ class CreateInvoiceInputWithProductIDPlan(TypedDict, total=False):
billing_period: Optional[int]
"""The interval in days at which the plan charges (renewal plans)."""
+ currency: Optional[Currency]
+ """The available currencies on the platform"""
+
custom_fields: Optional[Iterable[CreateInvoiceInputWithProductIDPlanCustomField]]
"""An array of custom field objects."""
diff --git a/src/whop_sdk/types/invoice_update_params.py b/src/whop_sdk/types/invoice_update_params.py
index ba46184f..7889a003 100644
--- a/src/whop_sdk/types/invoice_update_params.py
+++ b/src/whop_sdk/types/invoice_update_params.py
@@ -7,6 +7,7 @@
from typing_extensions import Literal, Required, Annotated, TypedDict
from .._utils import PropertyInfo
+from .shared.currency import Currency
from .shared.plan_type import PlanType
from .shared.visibility import Visibility
from .tax_identifier_type import TaxIdentifierType
@@ -181,6 +182,9 @@ class Plan(TypedDict, total=False):
billing_period: Optional[int]
"""The interval in days at which the plan charges (renewal plans)."""
+ currency: Optional[Currency]
+ """The available currencies on the platform"""
+
custom_fields: Optional[Iterable[PlanCustomField]]
"""An array of custom field objects."""
diff --git a/src/whop_sdk/types/ledger_account_funds_available_webhook_event.py b/src/whop_sdk/types/ledger_account_funds_available_webhook_event.py
new file mode 100644
index 00000000..4deabdc1
--- /dev/null
+++ b/src/whop_sdk/types/ledger_account_funds_available_webhook_event.py
@@ -0,0 +1,253 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .shared.currency import Currency
+from .verification_status import VerificationStatus
+from .verification_error_code import VerificationErrorCode
+from .payout_account_calculated_statuses import PayoutAccountCalculatedStatuses
+
+__all__ = [
+ "LedgerAccountFundsAvailableWebhookEvent",
+ "Data",
+ "DataBalance",
+ "DataOwner",
+ "DataOwnerUser",
+ "DataOwnerCompany",
+ "DataPayoutAccountDetails",
+ "DataPayoutAccountDetailsAddress",
+ "DataPayoutAccountDetailsBusinessRepresentative",
+ "DataPayoutAccountDetailsLatestVerification",
+ "DataTreasuryBalance",
+]
+
+
+class DataBalance(BaseModel):
+ """A cached balance for a LedgerAccount in respect to a currency."""
+
+ balance: float
+ """The amount of the balance."""
+
+ currency: Currency
+ """The currency of the balance."""
+
+ pending_balance: float
+ """The amount of the balance that is pending."""
+
+ reserve_balance: float
+ """The amount of the balance that is reserved."""
+
+
+class DataOwnerUser(BaseModel):
+ """A user account on Whop.
+
+ Contains profile information, identity details, and social connections.
+ """
+
+ id: str
+ """The unique identifier for the user."""
+
+ name: Optional[str] = None
+ """The user's display name shown on their public profile."""
+
+ typename: Literal["User"]
+ """The typename of this object"""
+
+ username: str
+ """The user's unique username shown on their public profile."""
+
+
+class DataOwnerCompany(BaseModel):
+ """A company is a seller on Whop.
+
+ Companies own products, manage members, and receive payouts.
+ """
+
+ id: str
+ """The unique identifier for the company."""
+
+ route: str
+ """
+ The URL slug for the company's store page (e.g., 'pickaxe' in whop.com/pickaxe).
+ """
+
+ title: str
+ """The display name of the company shown to customers."""
+
+ typename: Literal["Company"]
+ """The typename of this object"""
+
+
+DataOwner: TypeAlias = Annotated[
+ Union[Optional[DataOwnerUser], Optional[DataOwnerCompany]], PropertyInfo(discriminator="typename")
+]
+
+
+class DataPayoutAccountDetailsAddress(BaseModel):
+ """The physical address associated with this payout account"""
+
+ 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."""
+
+ postal_code: Optional[str] = None
+ """The postal code of the address."""
+
+ state: Optional[str] = None
+ """The state of the address."""
+
+
+class DataPayoutAccountDetailsBusinessRepresentative(BaseModel):
+ """The business representative for this payout account"""
+
+ date_of_birth: Optional[str] = None
+ """
+ The date of birth of the business representative in ISO 8601 format
+ (YYYY-MM-DD).
+ """
+
+ first_name: Optional[str] = None
+ """The first name of the business representative."""
+
+ last_name: Optional[str] = None
+ """The last name of the business representative."""
+
+ middle_name: Optional[str] = None
+ """The middle name of the business representative."""
+
+
+class DataPayoutAccountDetailsLatestVerification(BaseModel):
+ """The latest verification for the connected account."""
+
+ id: str
+ """The numeric id of the verification record."""
+
+ last_error_code: Optional[VerificationErrorCode] = None
+ """An error code for a verification attempt."""
+
+ last_error_reason: Optional[str] = None
+ """A human-readable explanation of the most recent verification error.
+
+ Null if no error has occurred.
+ """
+
+ status: VerificationStatus
+ """The current status of this verification session."""
+
+
+class DataPayoutAccountDetails(BaseModel):
+ """The payout account associated with the LedgerAccount, if any."""
+
+ id: str
+ """The unique identifier for the payout account."""
+
+ address: Optional[DataPayoutAccountDetailsAddress] = None
+ """The physical address associated with this payout account"""
+
+ business_name: Optional[str] = None
+ """The company's legal name"""
+
+ business_representative: Optional[DataPayoutAccountDetailsBusinessRepresentative] = None
+ """The business representative for this payout account"""
+
+ email: Optional[str] = None
+ """The email address of the representative"""
+
+ latest_verification: Optional[DataPayoutAccountDetailsLatestVerification] = None
+ """The latest verification for the connected account."""
+
+ phone: Optional[str] = None
+ """The business representative's phone"""
+
+ status: Optional[PayoutAccountCalculatedStatuses] = None
+ """
+ The granular calculated statuses reflecting payout account KYC and withdrawal
+ readiness.
+ """
+
+
+class DataTreasuryBalance(BaseModel):
+ """The balance cache associated with the account by currency."""
+
+ balance: float
+ """The amount of the balance."""
+
+ balance_usd: float
+ """The balance converted to USD."""
+
+ currency: Currency
+ """The currency of the balance."""
+
+ pending_balance: float
+ """The amount of the balance that is pending."""
+
+ reserve_balance: float
+ """The amount of the balance that is reserved."""
+
+ total_withdrawable_balance: float
+ """The amount of the balance that is withdrawable."""
+
+
+class Data(BaseModel):
+ """
+ A ledger account represents a financial account on Whop that can hold many balances.
+ """
+
+ id: str
+ """The unique identifier for the ledger account."""
+
+ balances: List[DataBalance]
+ """The balances associated with the account."""
+
+ ledger_type: Literal["primary", "pool"]
+ """The type of ledger account."""
+
+ owner: DataOwner
+ """The owner of the ledger account."""
+
+ payments_approval_status: Optional[Literal["pending", "approved", "monitoring", "rejected"]] = None
+ """The different approval statuses an account can have."""
+
+ payout_account_details: Optional[DataPayoutAccountDetails] = None
+ """The payout account associated with the LedgerAccount, if any."""
+
+ transfer_fee: Optional[float] = None
+ """The fee for transfers, if applicable."""
+
+ treasury_balance: Optional[DataTreasuryBalance] = None
+ """The balance cache associated with the account by currency."""
+
+
+class LedgerAccountFundsAvailableWebhookEvent(BaseModel):
+ id: str
+ """A unique ID for every single webhook request"""
+
+ api_version: Literal["v1"]
+ """The API version for this webhook"""
+
+ data: Data
+ """
+ A ledger account represents a financial account on Whop that can hold many
+ balances.
+ """
+
+ timestamp: datetime
+ """The timestamp in ISO 8601 format that the webhook was sent at on the server"""
+
+ type: Literal["ledger_account.funds_available"]
+ """The webhook event type"""
+
+ company_id: Optional[str] = None
+ """The company ID that this webhook event is associated with"""
diff --git a/src/whop_sdk/types/membership_list_response.py b/src/whop_sdk/types/membership_list_response.py
index 89bccb93..2910aad0 100644
--- a/src/whop_sdk/types/membership_list_response.py
+++ b/src/whop_sdk/types/membership_list_response.py
@@ -40,7 +40,8 @@ class Plan(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the plan.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
@@ -53,7 +54,8 @@ class Product(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
title: str
@@ -170,7 +172,7 @@ class MembershipListResponse(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""
Custom key-value pairs for the membership (commonly used for software licensing,
- e.g., HWID). Max 50 keys, 500 chars per key, 5000 chars per value.
+ e.g., HWID). Max 50 keys, 100 chars per key, 500 chars per string value.
"""
payment_collection_paused: bool
diff --git a/src/whop_sdk/types/membership_trial_ending_soon_webhook_event.py b/src/whop_sdk/types/membership_trial_ending_soon_webhook_event.py
new file mode 100644
index 00000000..fc6d3b8e
--- /dev/null
+++ b/src/whop_sdk/types/membership_trial_ending_soon_webhook_event.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .shared.membership import Membership
+
+__all__ = ["MembershipTrialEndingSoonWebhookEvent"]
+
+
+class MembershipTrialEndingSoonWebhookEvent(BaseModel):
+ id: str
+ """A unique ID for every single webhook request"""
+
+ api_version: Literal["v1"]
+ """The API version for this webhook"""
+
+ data: Membership
+ """A membership represents an active relationship between a user and a product.
+
+ It tracks the user's access, billing status, and renewal schedule.
+ """
+
+ timestamp: datetime
+ """The timestamp in ISO 8601 format that the webhook was sent at on the server"""
+
+ type: Literal["membership.trial_ending_soon"]
+ """The webhook event type"""
+
+ company_id: Optional[str] = None
+ """The company ID that this webhook event is associated with"""
diff --git a/src/whop_sdk/types/payment_list_response.py b/src/whop_sdk/types/payment_list_response.py
index 44a2275d..25f09d10 100644
--- a/src/whop_sdk/types/payment_list_response.py
+++ b/src/whop_sdk/types/payment_list_response.py
@@ -167,7 +167,8 @@ class Plan(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the plan.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
@@ -180,7 +181,8 @@ class Product(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
route: str
diff --git a/src/whop_sdk/types/payout_list_params.py b/src/whop_sdk/types/payout_list_params.py
new file mode 100644
index 00000000..72274108
--- /dev/null
+++ b/src/whop_sdk/types/payout_list_params.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["PayoutListParams"]
+
+
+class PayoutListParams(TypedDict, total=False):
+ account_id: str
+ """The owning account ID (a biz\\__ identifier). Provide this or user_id."""
+
+ after: str
+ """Cursor to fetch the page after (from page_info.end_cursor)."""
+
+ before: str
+ """Cursor to fetch the page before (from page_info.start_cursor)."""
+
+ currency: str
+ """Optional currency code filter, for example usd."""
+
+ first: int
+ """Number of payouts to return from the start of the window."""
+
+ last: int
+ """Number of payouts to return from the end of the window."""
+
+ user_id: str
+ """The owning user ID (a user\\__ identifier). Provide this or account_id."""
diff --git a/src/whop_sdk/types/payout_list_response.py b/src/whop_sdk/types/payout_list_response.py
new file mode 100644
index 00000000..2e662c5b
--- /dev/null
+++ b/src/whop_sdk/types/payout_list_response.py
@@ -0,0 +1,58 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["PayoutListResponse", "PayoutToken", "PayoutTokenPayoutDestination"]
+
+
+class PayoutTokenPayoutDestination(BaseModel):
+ icon_url: Optional[str] = None
+
+ payer_name: Optional[str] = None
+
+
+class PayoutToken(BaseModel):
+ """The saved payout method used.
+
+ Requires payout:destination:read; null without it.
+ """
+
+ nickname: Optional[str] = None
+
+ payout_destination: Optional[PayoutTokenPayoutDestination] = None
+
+
+class PayoutListResponse(BaseModel):
+ id: str
+
+ amount: float
+ """The payout amount in whole currency units."""
+
+ created_at: datetime
+
+ currency: str
+
+ estimated_arrival: Optional[datetime] = None
+ """Estimated time the funds become available in the destination account."""
+
+ fee_amount: float
+ """The fee charged for the payout, in the payout currency."""
+
+ object: Literal["payout"]
+
+ payer_name: Optional[str] = None
+ """Name of the entity processing the payout."""
+
+ payout_token: Optional[PayoutToken] = None
+ """The saved payout method used.
+
+ Requires payout:destination:read; null without it.
+ """
+
+ speed: Literal["standard", "instant"]
+
+ status: Literal["requested", "awaiting_payment", "in_transit", "completed", "failed", "canceled", "denied"]
diff --git a/src/whop_sdk/types/plan_calculate_tax_params.py b/src/whop_sdk/types/plan_calculate_tax_params.py
new file mode 100644
index 00000000..d1b31405
--- /dev/null
+++ b/src/whop_sdk/types/plan_calculate_tax_params.py
@@ -0,0 +1,55 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable, Optional
+from typing_extensions import Required, TypedDict
+
+__all__ = ["PlanCalculateTaxParams", "Address", "TaxID"]
+
+
+class PlanCalculateTaxParams(TypedDict, total=False):
+ address: Optional[Address]
+ """The buyer's billing address. Provide this or ip_address."""
+
+ ip_address: str
+ """
+ The buyer's IP address, used to resolve their location when no address is
+ provided.
+ """
+
+ tax_ids: Optional[Iterable[TaxID]]
+ """
+ The buyer's tax IDs, such as a VAT number, used to apply B2B reverse-charge
+ exemptions.
+ """
+
+
+class Address(TypedDict, total=False):
+ """The buyer's billing address. Provide this or ip_address."""
+
+ country: Required[str]
+ """The two-letter ISO 3166-1 country code, for example US, DE, or GB."""
+
+ city: Optional[str]
+ """The city name."""
+
+ line1: Optional[str]
+ """The first line of the street address."""
+
+ line2: Optional[str]
+ """The second line of the street address."""
+
+ postal_code: Optional[str]
+ """The postal or ZIP code."""
+
+ state: Optional[str]
+ """The state, province, or region code, for example CA."""
+
+
+class TaxID(TypedDict, total=False):
+ type: str
+ """The tax ID type, for example eu_vat."""
+
+ value: str
+ """The tax ID number, for example DE123456789."""
diff --git a/src/whop_sdk/types/plan_calculate_tax_response.py b/src/whop_sdk/types/plan_calculate_tax_response.py
new file mode 100644
index 00000000..7201920e
--- /dev/null
+++ b/src/whop_sdk/types/plan_calculate_tax_response.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["PlanCalculateTaxResponse"]
+
+
+class PlanCalculateTaxResponse(BaseModel):
+ currency: str
+ """The three-letter ISO 4217 currency code of the amounts."""
+
+ status: Literal["calculated", "not_calculated"]
+ """Whether tax was successfully calculated.
+
+ Returns not_calculated when tax could not be determined.
+ """
+
+ subtotal: int
+ """The plan price in the currency's smallest unit, for example cents.
+
+ For exclusive tax this is the pre-tax amount; for inclusive tax it already
+ contains the tax and equals the total.
+ """
+
+ tax_amount: int
+ """The tax owed, in the currency's smallest unit.
+
+ For exclusive tax it is added on top of the subtotal; for inclusive tax it is
+ the portion already contained in the subtotal.
+ """
+
+ tax_behavior: Literal["exclusive", "inclusive"]
+ """
+ Whether tax is added on top of the price (exclusive) or already included in it
+ (inclusive).
+ """
+
+ total: int
+ """The total amount the buyer pays, in the currency's smallest unit."""
diff --git a/src/whop_sdk/types/plan_create_params.py b/src/whop_sdk/types/plan_create_params.py
index 34e9edc1..6e742c65 100644
--- a/src/whop_sdk/types/plan_create_params.py
+++ b/src/whop_sdk/types/plan_create_params.py
@@ -2,27 +2,20 @@
from __future__ import annotations
-from typing import Dict, List, Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing import Iterable, Optional
+from typing_extensions import Literal, TypedDict
-from .checkout_font import CheckoutFont
-from .checkout_shape import CheckoutShape
-from .shared.currency import Currency
-from .shared.tax_type import TaxType
-from .shared.plan_type import PlanType
-from .shared.visibility import Visibility
-from .payment_method_types import PaymentMethodTypes
-from .shared.release_method import ReleaseMethod
+from .._types import SequenceNotStr
-__all__ = ["PlanCreateParams", "CheckoutStyling", "CustomField", "Image", "PaymentMethodConfiguration"]
+__all__ = ["PlanCreateParams", "CustomField", "Image", "PaymentMethodConfiguration"]
class PlanCreateParams(TypedDict, total=False):
- company_id: Required[str]
- """The unique identifier of the company to create this plan for."""
+ account_id: str
+ """The unique identifier of the account to create this plan for.
- product_id: Required[str]
- """The unique identifier of the product to attach this plan to."""
+ Defaults to the caller's account.
+ """
adaptive_pricing_enabled: Optional[bool]
"""Whether this plan accepts local currency payments via adaptive pricing."""
@@ -33,36 +26,31 @@ class PlanCreateParams(TypedDict, total=False):
For example, 30 for monthly or 365 for yearly.
"""
- checkout_styling: Optional[CheckoutStyling]
- """Checkout styling overrides for this plan.
+ checkout_styling: Optional[object]
+ """Checkout styling overrides for this plan."""
- Pass null to inherit from the company default.
- """
-
- currency: Optional[Currency]
- """The available currencies on the platform"""
+ currency: str
+ """The three-letter ISO currency code for the plan's pricing. Defaults to USD."""
custom_fields: Optional[Iterable[CustomField]]
- """An array of custom field definitions to collect from customers at checkout."""
+ """An array of custom field definitions to collect from customers at checkout.
+
+ Omitting this field clears existing custom fields.
+ """
description: Optional[str]
"""A text description of the plan displayed to customers on the product page."""
expiration_days: Optional[int]
- """The number of days until the membership expires and access is revoked.
-
- Used for expiration-based plans.
- """
+ """The number of days until the membership expires and access is revoked."""
image: Optional[Image]
"""An image displayed on the product page to represent this plan."""
initial_price: Optional[float]
- """The amount charged on the first purchase.
-
- For one-time plans, this is the full price. For recurring plans, this is an
- additional charge on top of the renewal price. Provided in the plan's currency
- (e.g., 10.43 for $10.43).
+ """
+ The amount charged on the first purchase, in the plan's currency (e.g., 10.43
+ for $10.43).
"""
internal_notes: Optional[str]
@@ -71,35 +59,35 @@ class PlanCreateParams(TypedDict, total=False):
legacy_payment_method_controls: Optional[bool]
"""Whether this plan uses legacy payment method controls."""
- metadata: Optional[Dict[str, object]]
+ metadata: Optional[object]
"""Custom key-value pairs to store on the plan.
- Included in webhook payloads for payment and membership events. Max 50 keys, 500
- chars per key, 5000 chars per value.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
- override_tax_type: Optional[TaxType]
- """
- Whether or not the tax is included in a plan's price (or if it hasn't been set
- up)
- """
+ override_tax_type: str
+ """Override the default tax classification for this specific plan."""
payment_method_configuration: Optional[PaymentMethodConfiguration]
"""Explicit payment method configuration for the plan.
- When not provided, the company's defaults apply.
+ When not provided, the account's defaults apply.
"""
- plan_type: Optional[PlanType]
- """The type of plan that can be attached to a product"""
+ plan_type: str
+ """The billing type of the plan, such as one_time or renewal."""
- release_method: Optional[ReleaseMethod]
- """The methods of how a plan can be released."""
+ product_id: str
+ """The unique identifier of the product to attach this plan to."""
- renewal_price: Optional[float]
- """The amount charged each billing period for recurring plans.
+ release_method: str
+ """The method used to sell this plan (e.g., buy_now, waitlist)."""
- Provided in the plan's currency (e.g., 10.43 for $10.43).
+ renewal_price: Optional[float]
+ """
+ The amount charged each billing period for recurring plans, in the plan's
+ currency.
"""
split_pay_required_payments: Optional[int]
@@ -111,8 +99,8 @@ class PlanCreateParams(TypedDict, total=False):
Ignored when unlimited_stock is true.
"""
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]]
- """The 3D Secure behavior for a plan."""
+ three_ds_level: Literal["mandate_challenge", "frictionless"]
+ """The 3D Secure behavior for this plan. Send null to inherit the account default."""
title: Optional[str]
"""The display name of the plan shown to customers on the product page."""
@@ -121,87 +109,48 @@ class PlanCreateParams(TypedDict, total=False):
"""The number of free trial days before the first charge on a recurring plan."""
unlimited_stock: Optional[bool]
- """Whether the plan has unlimited stock.
-
- When true, the stock field is ignored. Defaults to true.
- """
-
- visibility: Optional[Visibility]
- """Visibility of a resource"""
+ """Whether the plan has unlimited stock. When true, the stock field is ignored."""
-
-class CheckoutStyling(TypedDict, total=False):
- """Checkout styling overrides for this plan.
-
- Pass null to inherit from the company default.
- """
-
- background_color: Optional[str]
- """
- A hex color code for the checkout page background, applied to the order summary
- panel (e.g. #F4F4F5).
- """
-
- border_style: Optional[CheckoutShape]
- """The different border-radius styles available for checkout pages."""
-
- button_color: Optional[str]
- """A hex color code for the button color (e.g. #FF5733)."""
-
- font_family: Optional[CheckoutFont]
- """The different font families available for checkout pages."""
+ visibility: str
+ """Whether the plan is visible to customers or hidden from public view."""
class CustomField(TypedDict, total=False):
- field_type: Required[Literal["text"]]
+ id: str
+ """The ID of the custom field (if being updated)."""
+
+ field_type: Literal["text"]
"""The type of the custom field."""
- name: Required[str]
+ name: str
"""The name of the custom field."""
- id: Optional[str]
- """The ID of the custom field (if being updated)"""
-
- order: Optional[int]
+ order: int
"""The order of the field."""
placeholder: Optional[str]
- """The placeholder value of the field."""
+ """An example response displayed in the input field."""
- required: Optional[bool]
+ required: bool
"""Whether or not the field is required."""
class Image(TypedDict, total=False):
"""An image displayed on the product page to represent this plan."""
- id: Required[str]
- """The ID of an existing file object."""
+ id: str
+
+ direct_upload_id: str
class PaymentMethodConfiguration(TypedDict, total=False):
"""Explicit payment method configuration for the plan.
- When not provided, the company's defaults apply.
+ When not provided, the account's defaults apply.
"""
- disabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
+ disabled: SequenceNotStr[str]
- enabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly enabled.
+ enabled: SequenceNotStr[str]
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: Optional[bool]
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
+ include_platform_defaults: bool
diff --git a/src/whop_sdk/types/plan_list_params.py b/src/whop_sdk/types/plan_list_params.py
index fc24663e..22581252 100644
--- a/src/whop_sdk/types/plan_list_params.py
+++ b/src/whop_sdk/types/plan_list_params.py
@@ -2,56 +2,49 @@
from __future__ import annotations
-from typing import List, Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, Required, Annotated, TypedDict
+from typing_extensions import Literal, Required, TypedDict
from .._types import SequenceNotStr
-from .._utils import PropertyInfo
-from .shared.direction import Direction
-from .shared.plan_type import PlanType
-from .shared.release_method import ReleaseMethod
-from .shared.visibility_filter import VisibilityFilter
__all__ = ["PlanListParams"]
class PlanListParams(TypedDict, total=False):
- company_id: Required[str]
- """The unique identifier of the company to list plans for."""
+ account_id: Required[str]
+ """The unique identifier of the account to list plans for."""
- after: Optional[str]
- """Returns the elements in the list that come after the specified cursor."""
+ after: str
+ """A cursor; returns plans after this position."""
- before: Optional[str]
- """Returns the elements in the list that come before the specified cursor."""
+ before: str
+ """A cursor; returns plans before this position."""
- created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ created_after: str
"""Only return plans created after this timestamp."""
- created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ created_before: str
"""Only return plans created before this timestamp."""
- direction: Optional[Direction]
- """The direction of the sort."""
+ direction: Literal["asc", "desc"]
+ """The sort direction for results. Defaults to descending."""
- first: Optional[int]
- """Returns the first _n_ elements from the list."""
+ first: int
+ """The number of plans to return (default and max 100)."""
- last: Optional[int]
- """Returns the last _n_ elements from the list."""
+ last: int
+ """The number of plans to return from the end of the range."""
- order: Optional[Literal["id", "active_members_count", "created_at", "internal_notes", "expires_at"]]
- """The ways a relation of Plans can be ordered"""
+ order: Literal["id", "active_members_count", "created_at", "internal_notes", "expires_at"]
+ """The field to sort results by. Defaults to created_at."""
- plan_types: Optional[List[PlanType]]
+ plan_types: SequenceNotStr[str]
"""Filter to only plans matching these billing types."""
- product_ids: Optional[SequenceNotStr[str]]
+ product_ids: SequenceNotStr[str]
"""Filter to only plans belonging to these product identifiers."""
- release_methods: Optional[List[ReleaseMethod]]
+ release_methods: SequenceNotStr[str]
"""Filter to only plans matching these release methods."""
- visibilities: Optional[List[VisibilityFilter]]
+ visibilities: SequenceNotStr[str]
"""Filter to only plans matching these visibility states."""
diff --git a/src/whop_sdk/types/plan_list_response.py b/src/whop_sdk/types/plan_list_response.py
index db577cf4..ac7af37a 100644
--- a/src/whop_sdk/types/plan_list_response.py
+++ b/src/whop_sdk/types/plan_list_response.py
@@ -1,240 +1,114 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, List, Optional
-from datetime import datetime
-from typing_extensions import Literal
+from typing import Optional
from .._models import BaseModel
-from .shared.currency import Currency
-from .shared.plan_type import PlanType
-from .shared.visibility import Visibility
-from .payment_method_types import PaymentMethodTypes
-from .shared.release_method import ReleaseMethod
-__all__ = ["PlanListResponse", "Company", "Invoice", "PaymentMethodConfiguration", "Product"]
-
-
-class Company(BaseModel):
- """The company that sells this plan.
-
- Null for standalone invoice plans not linked to a company.
- """
-
- id: str
- """The unique identifier for the company."""
-
- title: str
- """The display name of the company shown to customers."""
-
-
-class Invoice(BaseModel):
- """The invoice this plan was generated for.
-
- Null if the plan was not created for a specific invoice.
- """
-
- id: str
- """The unique identifier for the invoice."""
-
-
-class PaymentMethodConfiguration(BaseModel):
- """
- The explicit payment method configuration specifying which payment methods are enabled or disabled for this plan. Null if the plan uses default settings.
- """
-
- disabled: List[PaymentMethodTypes]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
-
- enabled: List[PaymentMethodTypes]
- """An array of payment method identifiers that are explicitly enabled.
-
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: bool
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
-
-
-class Product(BaseModel):
- """The product that this plan belongs to.
-
- Null for standalone one-off purchases not linked to a product.
- """
-
- id: str
- """The unique identifier for the product."""
-
- title: str
- """
- The display name of the product shown to customers on the product page and in
- search results.
- """
+__all__ = ["PlanListResponse"]
class PlanListResponse(BaseModel):
- """A plan defines pricing and billing terms for a checkout.
-
- Plans can optionally belong to a product, where they represent different pricing options such as one-time payments, recurring subscriptions, or free trials.
- """
-
id: str
- """The unique identifier for the plan."""
+ """The ID of the plan, which will look like plan\\__******\\********"""
- adaptive_pricing_enabled: bool
- """Whether the creator has turned on adaptive pricing for this plan.
+ account: Optional[object] = None
+ """The account that sells this plan, an object with an id and title.
- Raw setting — does not check processor compatibility or feature flags.
+ Null for standalone invoice plans
"""
- billing_period: Optional[int] = None
- """The number of days between each recurring charge.
-
- Null for one-time plans. For example, 30 for monthly or 365 for annual billing.
- """
-
- company: Optional[Company] = None
- """The company that sells this plan.
-
- Null for standalone invoice plans not linked to a company.
- """
+ adaptive_pricing_enabled: bool
+ """Whether this plan accepts local currency payments via adaptive pricing"""
- created_at: datetime
- """The datetime the plan was created."""
+ billing_period: Optional[float] = None
+ """The number of days between recurring charges. Null for one-time plans"""
- currency: Currency
- """The currency used for all prices on this plan (e.g., 'usd', 'eur').
+ created_at: str
+ """When the plan was created, as an ISO 8601 timestamp"""
- All monetary amounts on the plan are denominated in this currency.
- """
+ currency: str
+ """The three-letter ISO currency code all prices on this plan are denominated in"""
description: Optional[str] = None
- """A text description of the plan visible to customers.
-
- Maximum 1000 characters. Null if no description is set.
- """
+ """A text description of the plan visible to customers"""
- expiration_days: Optional[int] = None
- """The number of days until the membership expires (for expiration-based plans).
-
- For example, 365 for a one-year access pass.
- """
+ expiration_days: Optional[float] = None
+ """The number of days until the membership expires, for expiration-based plans"""
initial_price: float
- """The initial purchase price in the plan's base_currency (e.g., 49.99 for $49.99).
-
- For one-time plans, this is the full price. For renewal plans, this is charged
- on top of the first renewal_price.
- """
+ """The initial purchase price in the plan's currency"""
internal_notes: Optional[str] = None
- """Private notes visible only to the company owner and team members.
-
- Not shown to customers. Null if no notes have been added.
- """
+ """Private notes visible only to authorized team members"""
- invoice: Optional[Invoice] = None
- """The invoice this plan was generated for.
+ invoice: Optional[object] = None
+ """The invoice this plan was generated for, an object with an id.
- Null if the plan was not created for a specific invoice.
+ Null unless the plan was created for an invoice
"""
- member_count: Optional[int] = None
- """The number of users who currently hold an active membership through this plan.
+ member_count: Optional[float] = None
+ """The number of active memberships on this plan.
- Only visible to authorized team members.
+ Only visible to authorized team members
"""
- metadata: Optional[Dict[str, object]] = None
- """Custom key-value pairs stored on the plan.
+ metadata: Optional[object] = None
+ """Custom key-value pairs stored on the plan"""
- Included in webhook payloads for payment and membership events.
+ payment_method_configuration: Optional[object] = None
"""
-
- payment_method_configuration: Optional[PaymentMethodConfiguration] = None
- """
- The explicit payment method configuration specifying which payment methods are
- enabled or disabled for this plan. Null if the plan uses default settings.
+ The explicit payment method configuration for the plan, an object with enabled,
+ disabled and include_platform_defaults. Null if the plan uses default settings
"""
- plan_type: PlanType
+ plan_type: str
"""
The billing model for this plan: 'renewal' for recurring subscriptions or
- 'one_time' for single payments.
+ 'one_time' for single payments
"""
- product: Optional[Product] = None
- """The product that this plan belongs to.
+ product: Optional[object] = None
+ """The product this plan belongs to, an object with an id and title.
- Null for standalone one-off purchases not linked to a product.
+ Null for standalone plans
"""
purchase_url: str
- """
- The full URL where customers can purchase this plan directly, bypassing the
- product page.
- """
+ """The full URL where customers can purchase this plan directly"""
- release_method: ReleaseMethod
- """
- The method used to sell this plan: 'buy_now' for immediate purchase or
- 'waitlist' for waitlist-based access.
- """
+ release_method: str
+ """The method used to sell this plan, e.g. 'buy_now' or 'waitlist'"""
renewal_price: float
- """
- The recurring price charged every billing_period in the plan's base_currency
- (e.g., 9.99 for $9.99/period). Zero for one-time plans.
- """
-
- split_pay_required_payments: Optional[int] = None
- """The total number of installment payments required before the subscription
- pauses.
+ """The recurring price charged every billing period in the plan's currency"""
- Null if split pay is not configured. Must be greater than 1.
- """
+ split_pay_required_payments: Optional[float] = None
+ """The number of installment payments required before the subscription pauses"""
- stock: Optional[int] = None
+ stock: Optional[float] = None
"""The number of units available for purchase.
- Only visible to authorized team members. Null if the requester lacks permission.
+ Only visible to authorized team members
"""
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] = None
- """The 3D Secure behavior for a plan."""
+ three_ds_level: Optional[str] = None
+ """The 3D Secure behavior for this plan.
- title: Optional[str] = None
- """
- The display name of the plan shown to customers on the product page and at
- checkout. Maximum 30 characters. Null if no title has been set.
+ Null means the plan inherits the account default
"""
- trial_period_days: Optional[int] = None
- """The number of free trial days before the first charge on a renewal plan.
+ title: Optional[str] = None
+ """The display name of the plan shown to customers"""
- Null if no trial is configured or the current user has already used a trial for
- this plan.
- """
+ trial_period_days: Optional[float] = None
+ """The number of free trial days before the first charge on a recurring plan"""
unlimited_stock: bool
- """When true, the plan has unlimited stock (stock field is ignored).
+ """Whether the plan has unlimited stock"""
- When false, purchases are limited by the stock field.
- """
-
- updated_at: datetime
- """The datetime the plan was last updated."""
+ updated_at: str
+ """When the plan was last updated, as an ISO 8601 timestamp"""
- visibility: Visibility
- """Controls whether the plan is visible to customers.
-
- When set to 'hidden', the plan is only accessible via direct link.
- """
+ visibility: str
+ """Whether the plan is visible to customers or hidden from public view"""
diff --git a/src/whop_sdk/types/plan_update_params.py b/src/whop_sdk/types/plan_update_params.py
index 853a890f..335ffdf3 100644
--- a/src/whop_sdk/types/plan_update_params.py
+++ b/src/whop_sdk/types/plan_update_params.py
@@ -2,17 +2,12 @@
from __future__ import annotations
-from typing import Dict, List, Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing import Iterable, Optional
+from typing_extensions import Literal, TypedDict
-from .checkout_font import CheckoutFont
-from .checkout_shape import CheckoutShape
-from .shared.currency import Currency
-from .shared.tax_type import TaxType
-from .shared.visibility import Visibility
-from .payment_method_types import PaymentMethodTypes
+from .._types import SequenceNotStr
-__all__ = ["PlanUpdateParams", "CheckoutStyling", "CustomField", "Image", "PaymentMethodConfiguration"]
+__all__ = ["PlanUpdateParams", "CustomField", "Image", "PaymentMethodConfiguration"]
class PlanUpdateParams(TypedDict, total=False):
@@ -25,34 +20,31 @@ class PlanUpdateParams(TypedDict, total=False):
For example, 30 for monthly or 365 for yearly.
"""
- checkout_styling: Optional[CheckoutStyling]
- """Checkout styling overrides for this plan.
+ checkout_styling: Optional[object]
+ """Checkout styling overrides for this plan."""
- Pass null to remove all overrides and inherit from the company default.
- """
-
- currency: Optional[Currency]
- """The available currencies on the platform"""
+ currency: str
+ """The three-letter ISO currency code for the plan's pricing. Defaults to USD."""
custom_fields: Optional[Iterable[CustomField]]
- """An array of custom field definitions to collect from customers at checkout."""
+ """An array of custom field definitions to collect from customers at checkout.
+
+ Omitting this field clears existing custom fields.
+ """
description: Optional[str]
"""A text description of the plan displayed to customers on the product page."""
expiration_days: Optional[int]
- """The number of days until the membership expires and access is revoked.
-
- For example, 365 for one-year access.
- """
+ """The number of days until the membership expires and access is revoked."""
image: Optional[Image]
"""An image displayed on the product page to represent this plan."""
initial_price: Optional[float]
- """The amount charged on the first purchase.
-
- Provided in the plan's currency (e.g., 10.43 for $10.43).
+ """
+ The amount charged on the first purchase, in the plan's currency (e.g., 10.43
+ for $10.43).
"""
internal_notes: Optional[str]
@@ -61,32 +53,29 @@ class PlanUpdateParams(TypedDict, total=False):
legacy_payment_method_controls: Optional[bool]
"""Whether this plan uses legacy payment method controls."""
- metadata: Optional[Dict[str, object]]
+ metadata: Optional[object]
"""Custom key-value pairs to store on the plan.
- Included in webhook payloads for payment and membership events. Max 50 keys, 500
- chars per key, 5000 chars per value.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
offer_cancel_discount: Optional[bool]
"""Whether to offer a retention discount when a customer attempts to cancel."""
- override_tax_type: Optional[TaxType]
- """
- Whether or not the tax is included in a plan's price (or if it hasn't been set
- up)
- """
+ override_tax_type: str
+ """Override the default tax classification for this specific plan."""
payment_method_configuration: Optional[PaymentMethodConfiguration]
"""Explicit payment method configuration for the plan.
- Sending null removes any custom configuration.
+ When not provided, the account's defaults apply.
"""
renewal_price: Optional[float]
- """The amount charged each billing period for recurring plans.
-
- Provided in the plan's currency (e.g., 10.43 for $10.43).
+ """
+ The amount charged each billing period for recurring plans, in the plan's
+ currency.
"""
stock: Optional[int]
@@ -96,19 +85,13 @@ class PlanUpdateParams(TypedDict, total=False):
"""
strike_through_initial_price: Optional[float]
- """A comparison price displayed with a strikethrough for the initial price.
-
- Provided in the plan's currency (e.g., 19.99 for $19.99).
- """
+ """A comparison price displayed with a strikethrough for the initial price."""
strike_through_renewal_price: Optional[float]
- """A comparison price displayed with a strikethrough for the renewal price.
+ """A comparison price displayed with a strikethrough for the renewal price."""
- Provided in the plan's currency (e.g., 19.99 for $19.99).
- """
-
- three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]]
- """The 3D Secure behavior for a plan."""
+ three_ds_level: Literal["mandate_challenge", "frictionless"]
+ """The 3D Secure behavior for this plan. Send null to inherit the account default."""
title: Optional[str]
"""The display name of the plan shown to customers on the product page."""
@@ -119,82 +102,46 @@ class PlanUpdateParams(TypedDict, total=False):
unlimited_stock: Optional[bool]
"""Whether the plan has unlimited stock. When true, the stock field is ignored."""
- visibility: Optional[Visibility]
- """Visibility of a resource"""
-
-
-class CheckoutStyling(TypedDict, total=False):
- """Checkout styling overrides for this plan.
-
- Pass null to remove all overrides and inherit from the company default.
- """
-
- background_color: Optional[str]
- """
- A hex color code for the checkout page background, applied to the order summary
- panel (e.g. #F4F4F5).
- """
-
- border_style: Optional[CheckoutShape]
- """The different border-radius styles available for checkout pages."""
-
- button_color: Optional[str]
- """A hex color code for the button color (e.g. #FF5733)."""
-
- font_family: Optional[CheckoutFont]
- """The different font families available for checkout pages."""
+ visibility: str
+ """Whether the plan is visible to customers or hidden from public view."""
class CustomField(TypedDict, total=False):
- field_type: Required[Literal["text"]]
+ id: str
+ """The ID of the custom field (if being updated)."""
+
+ field_type: Literal["text"]
"""The type of the custom field."""
- name: Required[str]
+ name: str
"""The name of the custom field."""
- id: Optional[str]
- """The ID of the custom field (if being updated)"""
-
- order: Optional[int]
+ order: int
"""The order of the field."""
placeholder: Optional[str]
- """The placeholder value of the field."""
+ """An example response displayed in the input field."""
- required: Optional[bool]
+ required: bool
"""Whether or not the field is required."""
class Image(TypedDict, total=False):
"""An image displayed on the product page to represent this plan."""
- id: Required[str]
- """The ID of an existing file object."""
+ id: str
+
+ direct_upload_id: str
class PaymentMethodConfiguration(TypedDict, total=False):
"""Explicit payment method configuration for the plan.
- Sending null removes any custom configuration.
- """
-
- disabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
+ When not provided, the account's defaults apply.
"""
- enabled: Required[List[PaymentMethodTypes]]
- """An array of payment method identifiers that are explicitly enabled.
+ disabled: SequenceNotStr[str]
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
+ enabled: SequenceNotStr[str]
- include_platform_defaults: Optional[bool]
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
+ include_platform_defaults: bool
diff --git a/src/whop_sdk/types/product_create_params.py b/src/whop_sdk/types/product_create_params.py
index 103fbc3d..29597ede 100644
--- a/src/whop_sdk/types/product_create_params.py
+++ b/src/whop_sdk/types/product_create_params.py
@@ -2,151 +2,60 @@
from __future__ import annotations
-from typing import Dict, Iterable, Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing import Optional
+from typing_extensions import Required, TypedDict
-from .._types import SequenceNotStr
-from .shared.currency import Currency
-from .shared.plan_type import PlanType
-from .shared.custom_cta import CustomCta
-from .shared.visibility import Visibility
-from .shared.release_method import ReleaseMethod
-from .shared.global_affiliate_status import GlobalAffiliateStatus
-
-__all__ = ["ProductCreateParams", "PlanOptions", "PlanOptionsCustomField"]
+__all__ = ["ProductCreateParams"]
class ProductCreateParams(TypedDict, total=False):
- company_id: Required[str]
- """The unique identifier of the company to create this product for."""
-
title: Required[str]
"""The display name of the product. Maximum 80 characters."""
collect_shipping_address: Optional[bool]
- """Whether the checkout flow collects a shipping address from the customer."""
+ """Whether to collect a shipping address at checkout."""
+
+ company_id: str
+ """The unique identifier of the company to create this product for."""
- custom_cta: Optional[CustomCta]
- """The different types of custom CTAs that can be selected."""
+ custom_cta: Optional[str]
+ """The call-to-action button label."""
custom_cta_url: Optional[str]
- """
- A URL that the call-to-action button links to instead of the default checkout
- flow.
- """
+ """A URL the call-to-action button links to."""
custom_statement_descriptor: Optional[str]
- """A custom text label that appears on the customer's bank statement.
-
- Must be 5-22 characters, contain at least one letter, and not contain <, >, \\,,
- ', or " characters.
- """
+ """Custom bank statement descriptor. Must start with WHOP\\**."""
description: Optional[str]
- """A written description of the product displayed on its product page."""
-
- experience_ids: Optional[SequenceNotStr[str]]
- """The unique identifiers of experiences to connect to this product."""
+ """A written description displayed on the product page."""
global_affiliate_percentage: Optional[float]
- """
- The commission rate as a percentage that affiliates earn through the global
- affiliate program.
- """
+ """The commission rate affiliates earn."""
- global_affiliate_status: Optional[GlobalAffiliateStatus]
- """The different statuses of the global affiliate program for a product."""
+ global_affiliate_status: str
+ """The enrollment status in the global affiliate program."""
headline: Optional[str]
- """A short marketing headline displayed prominently on the product page."""
+ """A short marketing headline for the product page."""
member_affiliate_percentage: Optional[float]
- """
- The commission rate as a percentage that members earn through the member
- affiliate program.
- """
-
- member_affiliate_status: Optional[GlobalAffiliateStatus]
- """The different statuses of the global affiliate program for a product."""
+ """The commission rate members earn."""
- metadata: Optional[Dict[str, object]]
- """Custom key-value pairs to store on the product.
+ member_affiliate_status: str
+ """The enrollment status in the member affiliate program."""
- Included in webhook payloads for payment and membership events. Max 50 keys, 500
- chars per key, 5000 chars per value.
- """
-
- plan_options: Optional[PlanOptions]
- """Configuration for an automatically generated plan to attach to this product."""
+ metadata: Optional[object]
+ """Custom key-value pairs to store on the product."""
product_tax_code_id: Optional[str]
- """The unique identifier of the tax classification code to apply to this product."""
+ """The unique identifier of the tax classification code."""
redirect_purchase_url: Optional[str]
- """A URL to redirect the customer to after completing a purchase."""
+ """A URL to redirect the customer to after purchase."""
route: Optional[str]
"""The URL slug for the product's public link."""
- send_welcome_message: Optional[bool]
- """
- Whether to send an automated welcome message via support chat when a user joins
- this product. Defaults to true.
- """
-
- visibility: Optional[Visibility]
- """Visibility of a resource"""
-
-
-class PlanOptionsCustomField(TypedDict, total=False):
- field_type: Required[Literal["text"]]
- """The type of the custom field."""
-
- name: Required[str]
- """The name of the custom field."""
-
- id: Optional[str]
- """The ID of the custom field (if being updated)"""
-
- order: Optional[int]
- """The order of the field."""
-
- placeholder: Optional[str]
- """The placeholder value of the field."""
-
- required: Optional[bool]
- """Whether or not the field is required."""
-
-
-class PlanOptions(TypedDict, total=False):
- """Configuration for an automatically generated plan to attach to this product."""
-
- base_currency: Optional[Currency]
- """The available currencies on the platform"""
-
- billing_period: Optional[int]
- """The interval at which the plan charges (renewal plans)."""
-
- custom_fields: Optional[Iterable[PlanOptionsCustomField]]
- """An array of custom field objects."""
-
- initial_price: Optional[float]
- """An additional amount charged upon first purchase.
-
- Provided as a number in the specified currency. Eg: 10.43 for $10.43 USD.
- """
-
- plan_type: Optional[PlanType]
- """The type of plan that can be attached to a product"""
-
- release_method: Optional[ReleaseMethod]
- """The methods of how a plan can be released."""
-
- renewal_price: Optional[float]
- """The amount the customer is charged every billing period.
-
- Provided as a number in the specified currency. Eg: 10.43 for $10.43 USD.
- """
-
- visibility: Optional[Visibility]
- """Visibility of a resource"""
+ visibility: str
+ """Whether the product is visible to customers."""
diff --git a/src/whop_sdk/types/product_list_params.py b/src/whop_sdk/types/product_list_params.py
index 47862a61..5b666c38 100644
--- a/src/whop_sdk/types/product_list_params.py
+++ b/src/whop_sdk/types/product_list_params.py
@@ -2,14 +2,9 @@
from __future__ import annotations
-from typing import List, Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, Required, Annotated, TypedDict
+from typing_extensions import Literal, Required, TypedDict
-from .._utils import PropertyInfo
-from .shared.direction import Direction
-from .shared.access_pass_type import AccessPassType
-from .shared.visibility_filter import VisibilityFilter
+from .._types import SequenceNotStr
__all__ = ["ProductListParams"]
@@ -18,32 +13,26 @@ class ProductListParams(TypedDict, total=False):
company_id: Required[str]
"""The unique identifier of the company to list products for."""
- after: Optional[str]
- """Returns the elements in the list that come after the specified cursor."""
+ access_pass_types: SequenceNotStr[str]
+ """Filter to only products matching these types."""
- before: Optional[str]
- """Returns the elements in the list that come before the specified cursor."""
+ after: str
+ """A cursor; returns products after this position."""
- created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Only return products created after this timestamp."""
+ before: str
+ """A cursor; returns products before this position."""
- created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Only return products created before this timestamp."""
+ direction: Literal["asc", "desc"]
+ """The sort direction for results. Defaults to descending."""
- direction: Optional[Direction]
- """The direction of the sort."""
+ first: int
+ """The number of products to return (default and max 100)."""
- first: Optional[int]
- """Returns the first _n_ elements from the list."""
+ last: int
+ """The number of products to return from the end of the range."""
- last: Optional[int]
- """Returns the last _n_ elements from the list."""
+ order: str
+ """The field to sort results by. Defaults to created_at."""
- order: Optional[Literal["active_memberships_count", "created_at", "usd_gmv", "usd_gmv_30_days"]]
- """The ways a relation of AccessPasses can be ordered"""
-
- product_types: Optional[List[AccessPassType]]
- """Filter to only products matching these type classifications."""
-
- visibilities: Optional[List[VisibilityFilter]]
+ visibilities: SequenceNotStr[str]
"""Filter to only products matching these visibility states."""
diff --git a/src/whop_sdk/types/product_update_params.py b/src/whop_sdk/types/product_update_params.py
index 64a7c8c1..d9d48096 100644
--- a/src/whop_sdk/types/product_update_params.py
+++ b/src/whop_sdk/types/product_update_params.py
@@ -2,107 +2,24 @@
from __future__ import annotations
-from typing import Dict, Iterable, Optional
-from typing_extensions import Required, TypedDict
+from typing import Optional
+from typing_extensions import TypedDict
-from .shared.custom_cta import CustomCta
-from .shared.visibility import Visibility
-from .shared.global_affiliate_status import GlobalAffiliateStatus
-
-__all__ = ["ProductUpdateParams", "GalleryImage", "StorePageConfig"]
+__all__ = ["ProductUpdateParams"]
class ProductUpdateParams(TypedDict, total=False):
- collect_shipping_address: Optional[bool]
- """Whether the checkout flow collects a shipping address from the customer."""
-
- custom_cta: Optional[CustomCta]
- """The different types of custom CTAs that can be selected."""
-
- custom_cta_url: Optional[str]
- """
- A URL that the call-to-action button links to instead of the default checkout
- flow.
- """
-
- custom_statement_descriptor: Optional[str]
- """A custom text label that appears on the customer's bank statement.
-
- Must be 5-22 characters, contain at least one letter, and not contain <, >, \\,,
- ', or " characters.
- """
-
description: Optional[str]
- """A written description of the product displayed on its product page."""
-
- gallery_images: Optional[Iterable[GalleryImage]]
- """The gallery images for the product."""
-
- global_affiliate_percentage: Optional[float]
- """
- The commission rate as a percentage that affiliates earn through the global
- affiliate program.
- """
-
- global_affiliate_status: Optional[GlobalAffiliateStatus]
- """The different statuses of the global affiliate program for a product."""
+ """A written description displayed on the product page."""
headline: Optional[str]
- """A short marketing headline displayed prominently on the product page."""
-
- member_affiliate_percentage: Optional[float]
- """
- The commission rate as a percentage that members earn through the member
- affiliate program.
- """
-
- member_affiliate_status: Optional[GlobalAffiliateStatus]
- """The different statuses of the global affiliate program for a product."""
-
- metadata: Optional[Dict[str, object]]
- """Custom key-value pairs to store on the product.
-
- Included in webhook payloads for payment and membership events. Max 50 keys, 500
- chars per key, 5000 chars per value.
- """
-
- product_tax_code_id: Optional[str]
- """The unique identifier of the tax classification code to apply to this product."""
-
- redirect_purchase_url: Optional[str]
- """A URL to redirect the customer to after completing a purchase."""
-
- route: Optional[str]
- """The URL slug for the product's public link."""
-
- send_welcome_message: Optional[bool]
- """
- Whether to send an automated welcome message via support chat when a user joins
- this product.
- """
-
- store_page_config: Optional[StorePageConfig]
- """Layout and display configuration for this product on the company's store page."""
-
- title: Optional[str]
- """The display name of the product. Maximum 80 characters."""
-
- visibility: Optional[Visibility]
- """Visibility of a resource"""
-
-
-class GalleryImage(TypedDict, total=False):
- """Input for an attachment"""
-
- id: Required[str]
- """The ID of an existing file object."""
-
+ """A short marketing headline for the product page."""
-class StorePageConfig(TypedDict, total=False):
- """Layout and display configuration for this product on the company's store page."""
+ metadata: Optional[object]
+ """Custom key-value pairs to store on the product."""
- custom_cta: Optional[str]
- """Custom call-to-action text for the product's store page."""
+ title: str
+ """The display name of the product."""
- show_price: Optional[bool]
- """Whether or not to show the price on the product's store page."""
+ visibility: str
+ """Whether the product is visible to customers."""
diff --git a/src/whop_sdk/types/referrals/__init__.py b/src/whop_sdk/types/referrals/__init__.py
new file mode 100644
index 00000000..8900c156
--- /dev/null
+++ b/src/whop_sdk/types/referrals/__init__.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .business_list_params import BusinessListParams as BusinessListParams
+from .business_list_response import BusinessListResponse as BusinessListResponse
+from .business_retrieve_response import BusinessRetrieveResponse as BusinessRetrieveResponse
+from .business_list_earnings_params import BusinessListEarningsParams as BusinessListEarningsParams
+from .business_list_earnings_response import BusinessListEarningsResponse as BusinessListEarningsResponse
diff --git a/src/whop_sdk/types/referrals/business_list_earnings_params.py b/src/whop_sdk/types/referrals/business_list_earnings_params.py
new file mode 100644
index 00000000..5fc91692
--- /dev/null
+++ b/src/whop_sdk/types/referrals/business_list_earnings_params.py
@@ -0,0 +1,32 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["BusinessListEarningsParams"]
+
+
+class BusinessListEarningsParams(TypedDict, total=False):
+ after: str
+
+ before: str
+
+ first: int
+
+ include: Literal["receipt_fees"]
+ """Comma-separated extras to embed.
+
+ Supported: receipt_fees (adds amount_after_fees and the receipt_fees breakdown).
+ """
+
+ last: int
+
+ order: Literal["asc", "desc"]
+ """Sort direction."""
+
+ sort: Literal["created_at", "amount", "payout_at"]
+ """Field to sort earnings by."""
+
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"]
+ """Filter by earning status."""
diff --git a/src/whop_sdk/types/referrals/business_list_earnings_response.py b/src/whop_sdk/types/referrals/business_list_earnings_response.py
new file mode 100644
index 00000000..e76b2bfb
--- /dev/null
+++ b/src/whop_sdk/types/referrals/business_list_earnings_response.py
@@ -0,0 +1,112 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = [
+ "BusinessListEarningsResponse",
+ "AccessPass",
+ "Account",
+ "Receipt",
+ "ReceiptAlternativePaymentMethod",
+ "ReceiptReceiptFee",
+]
+
+
+class AccessPass(BaseModel):
+ id: str
+
+ route: str
+
+ title: str
+
+
+class Account(BaseModel):
+ id: str
+ """The referred business (a biz\\__ identifier)."""
+
+ logo_url: Optional[str] = None
+
+ route: str
+
+ title: str
+
+
+class ReceiptAlternativePaymentMethod(BaseModel):
+ image_url: Optional[str] = None
+
+ name: str
+
+
+class ReceiptReceiptFee(BaseModel):
+ currency: str
+
+ description: Optional[str] = None
+
+ label: str
+
+ raw_amount: float
+
+ specific_fee_origin: str
+
+ type_of_fee: str
+
+ value: str
+
+
+class Receipt(BaseModel):
+ id: str
+
+ alternative_payment_method: Optional[ReceiptAlternativePaymentMethod] = None
+
+ brand: Optional[str] = None
+
+ created_at: datetime
+
+ currency: str
+
+ last4: Optional[str] = None
+
+ payment_method_type: Optional[str] = None
+
+ processor: Optional[str] = None
+
+ amount_after_fees: Optional[float] = None
+ """Only present when include=receipt_fees."""
+
+ receipt_fees: Optional[List[ReceiptReceiptFee]] = None
+ """Only present when include=receipt_fees."""
+
+
+class BusinessListEarningsResponse(BaseModel):
+ id: Optional[str] = None
+
+ access_pass: Optional[AccessPass] = None
+
+ account: Optional[Account] = None
+
+ amount: Optional[float] = None
+ """What the referrer earns, in USD. Null until the earning settles."""
+
+ base_amount: float
+ """The seller payment the earning was calculated from, in USD."""
+
+ cancelation_reason: Optional[str] = None
+ """Why the earning was canceled or reversed, if applicable."""
+
+ created_at: datetime
+
+ currency: str
+
+ object: Literal["business_referral_earning"]
+
+ payout_at: Optional[datetime] = None
+
+ payout_percentage: Optional[float] = None
+
+ receipt: Optional[Receipt] = None
+
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"]
diff --git a/src/whop_sdk/types/referrals/business_list_params.py b/src/whop_sdk/types/referrals/business_list_params.py
new file mode 100644
index 00000000..574004a1
--- /dev/null
+++ b/src/whop_sdk/types/referrals/business_list_params.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["BusinessListParams"]
+
+
+class BusinessListParams(TypedDict, total=False):
+ after: str
+ """Cursor to fetch the page after (from page_info.end_cursor)."""
+
+ before: str
+ """Cursor to fetch the page before (from page_info.start_cursor)."""
+
+ first: int
+ """Number of business referrals to return from the start of the window."""
+
+ has_earnings: bool
+ """
+ When true, only businesses that have paid out at least one earning to the
+ caller.
+ """
+
+ last: int
+ """Number of business referrals to return from the end of the window."""
+
+ status: Literal["active", "removed"]
+ """Filter by referral status."""
diff --git a/src/whop_sdk/types/referrals/business_list_response.py b/src/whop_sdk/types/referrals/business_list_response.py
new file mode 100644
index 00000000..cba6a34b
--- /dev/null
+++ b/src/whop_sdk/types/referrals/business_list_response.py
@@ -0,0 +1,52 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["BusinessListResponse", "Account"]
+
+
+class Account(BaseModel):
+ id: str
+ """The referred business (a biz\\__ identifier)."""
+
+ logo_url: Optional[str] = None
+
+ route: str
+
+ title: str
+
+
+class BusinessListResponse(BaseModel):
+ id: str
+
+ account: Optional[Account] = None
+
+ completed_payout: float
+ """Earnings already paid out, in USD."""
+
+ created_at: datetime
+
+ currency: str
+
+ object: Literal["business_referral"]
+
+ payout_percentage: float
+
+ pending_payout: float
+ """Earnings awaiting payout, in USD."""
+
+ processing_volume: float
+ """All-time gross processing volume for the business, in USD."""
+
+ referral_expires_at: Optional[datetime] = None
+
+ referral_started_at: Optional[datetime] = None
+
+ status: Literal["active", "removed"]
+
+ total_earnings: float
+ """All-time affiliate earnings from this business (pending + completed), in USD."""
diff --git a/src/whop_sdk/types/referrals/business_retrieve_response.py b/src/whop_sdk/types/referrals/business_retrieve_response.py
new file mode 100644
index 00000000..08a4566c
--- /dev/null
+++ b/src/whop_sdk/types/referrals/business_retrieve_response.py
@@ -0,0 +1,52 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = ["BusinessRetrieveResponse", "Account"]
+
+
+class Account(BaseModel):
+ id: str
+ """The referred business (a biz\\__ identifier)."""
+
+ logo_url: Optional[str] = None
+
+ route: str
+
+ title: str
+
+
+class BusinessRetrieveResponse(BaseModel):
+ id: str
+
+ account: Optional[Account] = None
+
+ completed_payout: float
+ """Earnings already paid out, in USD."""
+
+ created_at: datetime
+
+ currency: str
+
+ object: Literal["business_referral"]
+
+ payout_percentage: float
+
+ pending_payout: float
+ """Earnings awaiting payout, in USD."""
+
+ processing_volume: float
+ """All-time gross processing volume for the business, in USD."""
+
+ referral_expires_at: Optional[datetime] = None
+
+ referral_started_at: Optional[datetime] = None
+
+ status: Literal["active", "removed"]
+
+ total_earnings: float
+ """All-time affiliate earnings from this business (pending + completed), in USD."""
diff --git a/src/whop_sdk/types/referrals/businesses/__init__.py b/src/whop_sdk/types/referrals/businesses/__init__.py
new file mode 100644
index 00000000..dc2fac39
--- /dev/null
+++ b/src/whop_sdk/types/referrals/businesses/__init__.py
@@ -0,0 +1,6 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .earning_list_params import EarningListParams as EarningListParams
+from .earning_list_response import EarningListResponse as EarningListResponse
diff --git a/src/whop_sdk/types/referrals/businesses/earning_list_params.py b/src/whop_sdk/types/referrals/businesses/earning_list_params.py
new file mode 100644
index 00000000..161ef59f
--- /dev/null
+++ b/src/whop_sdk/types/referrals/businesses/earning_list_params.py
@@ -0,0 +1,32 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, TypedDict
+
+__all__ = ["EarningListParams"]
+
+
+class EarningListParams(TypedDict, total=False):
+ after: str
+
+ before: str
+
+ first: int
+
+ include: Literal["receipt_fees"]
+ """Comma-separated extras to embed.
+
+ Supported: receipt_fees (adds amount_after_fees and the receipt_fees breakdown).
+ """
+
+ last: int
+
+ order: Literal["asc", "desc"]
+ """Sort direction."""
+
+ sort: Literal["created_at", "amount", "payout_at"]
+ """Field to sort earnings by."""
+
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"]
+ """Filter by earning status."""
diff --git a/src/whop_sdk/types/referrals/businesses/earning_list_response.py b/src/whop_sdk/types/referrals/businesses/earning_list_response.py
new file mode 100644
index 00000000..ee6cd30b
--- /dev/null
+++ b/src/whop_sdk/types/referrals/businesses/earning_list_response.py
@@ -0,0 +1,112 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = [
+ "EarningListResponse",
+ "AccessPass",
+ "Account",
+ "Receipt",
+ "ReceiptAlternativePaymentMethod",
+ "ReceiptReceiptFee",
+]
+
+
+class AccessPass(BaseModel):
+ id: str
+
+ route: str
+
+ title: str
+
+
+class Account(BaseModel):
+ id: str
+ """The referred business (a biz\\__ identifier)."""
+
+ logo_url: Optional[str] = None
+
+ route: str
+
+ title: str
+
+
+class ReceiptAlternativePaymentMethod(BaseModel):
+ image_url: Optional[str] = None
+
+ name: str
+
+
+class ReceiptReceiptFee(BaseModel):
+ currency: str
+
+ description: Optional[str] = None
+
+ label: str
+
+ raw_amount: float
+
+ specific_fee_origin: str
+
+ type_of_fee: str
+
+ value: str
+
+
+class Receipt(BaseModel):
+ id: str
+
+ alternative_payment_method: Optional[ReceiptAlternativePaymentMethod] = None
+
+ brand: Optional[str] = None
+
+ created_at: datetime
+
+ currency: str
+
+ last4: Optional[str] = None
+
+ payment_method_type: Optional[str] = None
+
+ processor: Optional[str] = None
+
+ amount_after_fees: Optional[float] = None
+ """Only present when include=receipt_fees."""
+
+ receipt_fees: Optional[List[ReceiptReceiptFee]] = None
+ """Only present when include=receipt_fees."""
+
+
+class EarningListResponse(BaseModel):
+ id: Optional[str] = None
+
+ access_pass: Optional[AccessPass] = None
+
+ account: Optional[Account] = None
+
+ amount: Optional[float] = None
+ """What the referrer earns, in USD. Null until the earning settles."""
+
+ base_amount: float
+ """The seller payment the earning was calculated from, in USD."""
+
+ cancelation_reason: Optional[str] = None
+ """Why the earning was canceled or reversed, if applicable."""
+
+ created_at: datetime
+
+ currency: str
+
+ object: Literal["business_referral_earning"]
+
+ payout_at: Optional[datetime] = None
+
+ payout_percentage: Optional[float] = None
+
+ receipt: Optional[Receipt] = None
+
+ status: Literal["awaiting_settlement", "pending", "completed", "canceled", "reversed"]
diff --git a/src/whop_sdk/types/refund_created_webhook_event.py b/src/whop_sdk/types/refund_created_webhook_event.py
index 611640f0..199467d7 100644
--- a/src/whop_sdk/types/refund_created_webhook_event.py
+++ b/src/whop_sdk/types/refund_created_webhook_event.py
@@ -57,7 +57,8 @@ class DataPaymentPlan(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the plan.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
@@ -70,7 +71,8 @@ class DataPaymentProduct(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
diff --git a/src/whop_sdk/types/refund_retrieve_response.py b/src/whop_sdk/types/refund_retrieve_response.py
index e1f0ad14..e09cbf69 100644
--- a/src/whop_sdk/types/refund_retrieve_response.py
+++ b/src/whop_sdk/types/refund_retrieve_response.py
@@ -55,7 +55,8 @@ class PaymentPlan(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the plan.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
@@ -68,7 +69,8 @@ class PaymentProduct(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
diff --git a/src/whop_sdk/types/refund_updated_webhook_event.py b/src/whop_sdk/types/refund_updated_webhook_event.py
index 9fbd5a1a..d73a908e 100644
--- a/src/whop_sdk/types/refund_updated_webhook_event.py
+++ b/src/whop_sdk/types/refund_updated_webhook_event.py
@@ -57,7 +57,8 @@ class DataPaymentPlan(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the plan.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
@@ -70,7 +71,8 @@ class DataPaymentProduct(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
diff --git a/src/whop_sdk/types/setup_intent.py b/src/whop_sdk/types/setup_intent.py
index a79a2b76..5f3f67b4 100644
--- a/src/whop_sdk/types/setup_intent.py
+++ b/src/whop_sdk/types/setup_intent.py
@@ -188,3 +188,9 @@ class SetupIntent(BaseModel):
status: SetupIntentStatus
"""The current status of the setup intent."""
+
+ three_ds_verified: bool
+ """
+ Whether 3D Secure authentication was completed when this payment method was set
+ up.
+ """
diff --git a/src/whop_sdk/types/shared/__init__.py b/src/whop_sdk/types/shared/__init__.py
index b1c4a467..249442f1 100644
--- a/src/whop_sdk/types/shared/__init__.py
+++ b/src/whop_sdk/types/shared/__init__.py
@@ -13,7 +13,6 @@
from .reaction import Reaction as Reaction
from .shipment import Shipment as Shipment
from .tax_type import TaxType as TaxType
-from .transfer import Transfer as Transfer
from .app_build import AppBuild as AppBuild
from .direction import Direction as Direction
from .page_info import PageInfo as PageInfo
diff --git a/src/whop_sdk/types/shared/checkout_configuration.py b/src/whop_sdk/types/shared/checkout_configuration.py
index d21bcd8f..8784af7e 100644
--- a/src/whop_sdk/types/shared/checkout_configuration.py
+++ b/src/whop_sdk/types/shared/checkout_configuration.py
@@ -125,12 +125,6 @@ class CheckoutConfiguration(BaseModel):
affiliate_code: Optional[str] = None
"""The affiliate code to use for the checkout configuration"""
- allow_promo_codes: bool
- """Whether the checkout configuration allows promo codes.
-
- When false, the promo code input is hidden and promo codes are rejected.
- """
-
company_id: str
"""The ID of the company to use for the checkout configuration"""
diff --git a/src/whop_sdk/types/shared/membership.py b/src/whop_sdk/types/shared/membership.py
index 4f8d3fd0..c37fd757 100644
--- a/src/whop_sdk/types/shared/membership.py
+++ b/src/whop_sdk/types/shared/membership.py
@@ -53,7 +53,8 @@ class Plan(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the plan.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
@@ -66,7 +67,8 @@ class Product(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
title: str
@@ -189,7 +191,7 @@ class Membership(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""
Custom key-value pairs for the membership (commonly used for software licensing,
- e.g., HWID). Max 50 keys, 500 chars per key, 5000 chars per value.
+ e.g., HWID). Max 50 keys, 100 chars per key, 500 chars per string value.
"""
payment_collection_paused: bool
diff --git a/src/whop_sdk/types/shared/payment.py b/src/whop_sdk/types/shared/payment.py
index 3c262c6d..551e9bf4 100644
--- a/src/whop_sdk/types/shared/payment.py
+++ b/src/whop_sdk/types/shared/payment.py
@@ -260,7 +260,8 @@ class Plan(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the plan.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
@@ -273,7 +274,8 @@ class Product(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
route: str
@@ -521,6 +523,20 @@ class Payment(BaseModel):
otherwise false. Used to decide if Whop can attempt the charge again.
"""
+ risk_score: Optional[int] = None
+ """
+ Whop's in-house fraud risk score for this payment, from 0 (lowest risk) to 100
+ (highest risk). Null when the payment has not been scored or scoring has not yet
+ completed.
+ """
+
+ risk_signals: Optional[Dict[str, object]] = None
+ """
+ A curated set of factors behind the risk score, grouped by category (business
+ transaction history, buyer, device). Each entry has a key, human-readable label,
+ category, and value. Null when there is no risk assessment for this payment.
+ """
+
settlement_amount: float
"""
The total amount charged to the customer for this payment, including taxes and
@@ -554,6 +570,9 @@ class Payment(BaseModel):
tax_refunded_amount: Optional[float] = None
"""The amount of tax that has been refunded (if applicable)."""
+ three_ds_verified: bool
+ """Whether 3D Secure authentication was completed for this payment."""
+
total: Optional[float] = None
"""The total to show to the creator (excluding buyer fees)."""
diff --git a/src/whop_sdk/types/shared/plan.py b/src/whop_sdk/types/shared/plan.py
index cf775d35..e708fec9 100644
--- a/src/whop_sdk/types/shared/plan.py
+++ b/src/whop_sdk/types/shared/plan.py
@@ -1,281 +1,218 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, List, Optional
-from datetime import datetime
+from typing import List, Optional
from typing_extensions import Literal
-from .currency import Currency
-from .tax_type import TaxType
from ..._models import BaseModel
-from .plan_type import PlanType
-from .visibility import Visibility
-from .release_method import ReleaseMethod
-from ..payment_method_types import PaymentMethodTypes
-__all__ = ["Plan", "Company", "CustomField", "Invoice", "PaymentMethodConfiguration", "Product"]
-
-
-class Company(BaseModel):
- """The company that sells this plan.
-
- Null for standalone invoice plans not linked to a company.
- """
-
- id: str
- """The unique identifier for the company."""
-
- title: str
- """The display name of the company shown to customers."""
-
-
-class CustomField(BaseModel):
- """An object representing a custom field for a plan."""
-
- id: str
- """The unique identifier for the custom field."""
-
- field_type: Literal["text"]
- """What type of input field to use."""
-
- name: str
- """The title/header of the custom field."""
-
- order: Optional[int] = None
- """How the custom field should be ordered when rendered on the checkout page."""
-
- placeholder: Optional[str] = None
- """An example response displayed in the input field."""
-
- required: bool
- """Whether or not the custom field is required."""
-
-
-class Invoice(BaseModel):
- """The invoice this plan was generated for.
-
- Null if the plan was not created for a specific invoice.
- """
-
- id: str
- """The unique identifier for the invoice."""
-
-
-class PaymentMethodConfiguration(BaseModel):
- """
- The explicit payment method configuration specifying which payment methods are enabled or disabled for this plan. Null if the plan uses default settings.
- """
-
- disabled: List[PaymentMethodTypes]
- """An array of payment method identifiers that are explicitly disabled.
-
- Only applies if the include_platform_defaults is true.
- """
-
- enabled: List[PaymentMethodTypes]
- """An array of payment method identifiers that are explicitly enabled.
-
- This means these payment methods will be shown on checkout. Example use case is
- to only enable a specific payment method like cashapp, or extending the platform
- defaults with additional methods.
- """
-
- include_platform_defaults: bool
- """
- Whether Whop's platform default payment method enablement settings are included
- in this configuration. The full list of default payment methods can be found in
- the documentation at docs.whop.com/payments.
- """
-
-
-class Product(BaseModel):
- """The product that this plan belongs to.
-
- Null for standalone one-off purchases not linked to a product.
- """
-
- id: str
- """The unique identifier for the product."""
-
- title: str
- """
- The display name of the product shown to customers on the product page and in
- search results.
- """
+__all__ = ["Plan"]
class Plan(BaseModel):
- """A plan defines pricing and billing terms for a checkout.
-
- Plans can optionally belong to a product, where they represent different pricing options such as one-time payments, recurring subscriptions, or free trials.
- """
-
id: str
- """The unique identifier for the plan."""
+ """The ID of the plan, which will look like plan\\__******\\********"""
- adaptive_pricing_enabled: bool
- """Whether the creator has turned on adaptive pricing for this plan.
+ account: Optional[object] = None
+ """The account that sells this plan, an object with an id and title.
- Raw setting — does not check processor compatibility or feature flags.
+ Null for standalone invoice plans
"""
- billing_period: Optional[int] = None
- """The number of days between each recurring charge.
+ adaptive_pricing_enabled: bool
+ """Whether this plan accepts local currency payments via adaptive pricing"""
- Null for one-time plans. For example, 30 for monthly or 365 for annual billing.
- """
+ billing_period: Optional[float] = None
+ """The number of days between recurring charges. Null for one-time plans"""
collect_tax: bool
- """
- Whether tax is collected on purchases of this plan, based on the company's tax
- configuration.
- """
-
- company: Optional[Company] = None
- """The company that sells this plan.
-
- Null for standalone invoice plans not linked to a company.
- """
-
- created_at: datetime
- """The datetime the plan was created."""
-
- currency: Currency
- """The currency used for all prices on this plan (e.g., 'usd', 'eur').
-
- All monetary amounts on the plan are denominated in this currency.
- """
-
- custom_fields: List[CustomField]
- """
- Custom input fields displayed on the checkout form that collect additional
- information from the buyer.
+ """Whether tax is collected on purchases of this plan"""
+
+ created_at: str
+ """When the plan was created, as an ISO 8601 timestamp"""
+
+ currency: Literal[
+ "usd",
+ "sgd",
+ "inr",
+ "aud",
+ "brl",
+ "cad",
+ "dkk",
+ "eur",
+ "nok",
+ "gbp",
+ "sek",
+ "chf",
+ "hkd",
+ "huf",
+ "jpy",
+ "mxn",
+ "myr",
+ "pln",
+ "czk",
+ "nzd",
+ "aed",
+ "eth",
+ "ape",
+ "cop",
+ "ron",
+ "thb",
+ "bgn",
+ "idr",
+ "dop",
+ "php",
+ "try",
+ "krw",
+ "twd",
+ "vnd",
+ "pkr",
+ "clp",
+ "uyu",
+ "ars",
+ "zar",
+ "dzd",
+ "tnd",
+ "mad",
+ "kes",
+ "kwd",
+ "jod",
+ "all",
+ "xcd",
+ "amd",
+ "bsd",
+ "bhd",
+ "bob",
+ "bam",
+ "khr",
+ "crc",
+ "xof",
+ "egp",
+ "etb",
+ "gmd",
+ "ghs",
+ "gtq",
+ "gyd",
+ "ils",
+ "jmd",
+ "mop",
+ "mga",
+ "mur",
+ "mdl",
+ "mnt",
+ "nad",
+ "ngn",
+ "mkd",
+ "omr",
+ "pyg",
+ "pen",
+ "qar",
+ "rwf",
+ "sar",
+ "rsd",
+ "lkr",
+ "tzs",
+ "ttd",
+ "uzs",
+ "rub",
+ "btc",
+ "cny",
+ "usdt",
+ "kzt",
+ "awg",
+ "whop_usd",
+ "xau",
+ ]
+ """The three-letter ISO currency code all prices on this plan are denominated in"""
+
+ custom_fields: List[object]
+ """
+ Custom input fields displayed on the checkout form, objects with id, field_type,
+ name, order, placeholder and required
"""
description: Optional[str] = None
- """A text description of the plan visible to customers.
+ """A text description of the plan visible to customers"""
- Maximum 1000 characters. Null if no description is set.
- """
-
- expiration_days: Optional[int] = None
- """The number of days until the membership expires (for expiration-based plans).
-
- For example, 365 for a one-year access pass.
- """
+ expiration_days: Optional[float] = None
+ """The number of days until the membership expires, for expiration-based plans"""
initial_price: float
- """The initial purchase price in the plan's base_currency (e.g., 49.99 for $49.99).
-
- For one-time plans, this is the full price. For renewal plans, this is charged
- on top of the first renewal_price.
- """
+ """The initial purchase price in the plan's currency"""
internal_notes: Optional[str] = None
- """Private notes visible only to the company owner and team members.
+ """Private notes visible only to authorized team members"""
- Not shown to customers. Null if no notes have been added.
- """
-
- invoice: Optional[Invoice] = None
- """The invoice this plan was generated for.
+ invoice: Optional[object] = None
+ """The invoice this plan was generated for, an object with an id.
- Null if the plan was not created for a specific invoice.
+ Null unless the plan was created for an invoice
"""
- member_count: Optional[int] = None
- """The number of users who currently hold an active membership through this plan.
+ member_count: Optional[float] = None
+ """The number of active memberships on this plan.
- Only visible to authorized team members.
+ Only visible to authorized team members
"""
- metadata: Optional[Dict[str, object]] = None
- """Custom key-value pairs stored on the plan.
-
- Included in webhook payloads for payment and membership events.
- """
+ metadata: Optional[object] = None
+ """Custom key-value pairs stored on the plan"""
- payment_method_configuration: Optional[PaymentMethodConfiguration] = None
+ payment_method_configuration: Optional[object] = None
"""
- The explicit payment method configuration specifying which payment methods are
- enabled or disabled for this plan. Null if the plan uses default settings.
+ The explicit payment method configuration for the plan, an object with enabled,
+ disabled and include_platform_defaults. Null if the plan uses default settings
"""
- plan_type: PlanType
+ plan_type: Literal["renewal", "one_time"]
"""
The billing model for this plan: 'renewal' for recurring subscriptions or
- 'one_time' for single payments.
+ 'one_time' for single payments
"""
- product: Optional[Product] = None
- """The product that this plan belongs to.
+ product: Optional[object] = None
+ """The product this plan belongs to, an object with an id and title.
- Null for standalone one-off purchases not linked to a product.
+ Null for standalone plans
"""
purchase_url: str
- """
- The full URL where customers can purchase this plan directly, bypassing the
- product page.
- """
+ """The full URL where customers can purchase this plan directly"""
- release_method: ReleaseMethod
- """
- The method used to sell this plan: 'buy_now' for immediate purchase or
- 'waitlist' for waitlist-based access.
- """
+ release_method: Literal["buy_now", "waitlist"]
+ """The method used to sell this plan, e.g. 'buy_now' or 'waitlist'"""
renewal_price: float
- """
- The recurring price charged every billing_period in the plan's base_currency
- (e.g., 9.99 for $9.99/period). Zero for one-time plans.
- """
-
- split_pay_required_payments: Optional[int] = None
- """The total number of installment payments required before the subscription
- pauses.
+ """The recurring price charged every billing period in the plan's currency"""
- Null if split pay is not configured. Must be greater than 1.
- """
+ split_pay_required_payments: Optional[float] = None
+ """The number of installment payments required before the subscription pauses"""
- stock: Optional[int] = None
+ stock: Optional[float] = None
"""The number of units available for purchase.
- Only visible to authorized team members. Null if the requester lacks permission.
+ Only visible to authorized team members
"""
- tax_type: TaxType
- """
- How tax is handled for this plan: 'inclusive' (tax included in price),
- 'exclusive' (tax added at checkout), or 'unspecified' (tax not configured).
- """
+ tax_type: str
+ """How tax is handled for this plan: 'inclusive', 'exclusive', or 'unspecified'"""
three_ds_level: Optional[Literal["mandate_challenge", "frictionless"]] = None
- """The 3D Secure behavior for a plan."""
+ """The 3D Secure behavior for this plan.
- title: Optional[str] = None
- """
- The display name of the plan shown to customers on the product page and at
- checkout. Maximum 30 characters. Null if no title has been set.
+ Null means the plan inherits the account default
"""
- trial_period_days: Optional[int] = None
- """The number of free trial days before the first charge on a renewal plan.
+ title: Optional[str] = None
+ """The display name of the plan shown to customers"""
- Null if no trial is configured or the current user has already used a trial for
- this plan.
- """
+ trial_period_days: Optional[float] = None
+ """The number of free trial days before the first charge on a recurring plan"""
unlimited_stock: bool
- """When true, the plan has unlimited stock (stock field is ignored).
-
- When false, purchases are limited by the stock field.
- """
+ """Whether the plan has unlimited stock"""
- updated_at: datetime
- """The datetime the plan was last updated."""
+ updated_at: str
+ """When the plan was last updated, as an ISO 8601 timestamp"""
- visibility: Visibility
- """Controls whether the plan is visible to customers.
-
- When set to 'hidden', the plan is only accessible via direct link.
- """
+ visibility: Literal["visible", "hidden", "archived", "quick_link"]
+ """Whether the plan is visible to customers or hidden from public view"""
diff --git a/src/whop_sdk/types/shared/product.py b/src/whop_sdk/types/shared/product.py
index ce6299b8..3b22f84b 100644
--- a/src/whop_sdk/types/shared/product.py
+++ b/src/whop_sdk/types/shared/product.py
@@ -162,7 +162,8 @@ class Product(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
owner_user: OwnerUser
diff --git a/src/whop_sdk/types/shared/product_list_item.py b/src/whop_sdk/types/shared/product_list_item.py
index af1e59d5..742b735b 100644
--- a/src/whop_sdk/types/shared/product_list_item.py
+++ b/src/whop_sdk/types/shared/product_list_item.py
@@ -40,7 +40,8 @@ class ProductListItem(BaseModel):
metadata: Optional[Dict[str, object]] = None
"""Custom key-value pairs stored on the product.
- Included in webhook payloads for payment and membership events.
+ Included in webhook payloads for payment and membership events. Max 50 keys, 100
+ chars per key, 500 chars per string value.
"""
published_reviews_count: int
diff --git a/src/whop_sdk/types/shared/transfer.py b/src/whop_sdk/types/shared/transfer.py
deleted file mode 100644
index 8668f9e1..00000000
--- a/src/whop_sdk/types/shared/transfer.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, Annotated, TypeAlias
-
-from ..._utils import PropertyInfo
-from .currency import Currency
-from ..._models import BaseModel
-
-__all__ = ["Transfer", "Destination", "DestinationUser", "DestinationCompany", "Origin", "OriginUser", "OriginCompany"]
-
-
-class DestinationUser(BaseModel):
- """A user account on Whop.
-
- Contains profile information, identity details, and social connections.
- """
-
- id: str
- """The unique identifier for the user."""
-
- name: Optional[str] = None
- """The user's display name shown on their public profile."""
-
- typename: Literal["User"]
- """The typename of this object"""
-
- username: str
- """The user's unique username shown on their public profile."""
-
-
-class DestinationCompany(BaseModel):
- """A company is a seller on Whop.
-
- Companies own products, manage members, and receive payouts.
- """
-
- id: str
- """The unique identifier for the company."""
-
- route: str
- """
- The URL slug for the company's store page (e.g., 'pickaxe' in whop.com/pickaxe).
- """
-
- title: str
- """The display name of the company shown to customers."""
-
- typename: Literal["Company"]
- """The typename of this object"""
-
-
-Destination: TypeAlias = Annotated[
- Union[Optional[DestinationUser], Optional[DestinationCompany]], PropertyInfo(discriminator="typename")
-]
-
-
-class OriginUser(BaseModel):
- """A user account on Whop.
-
- Contains profile information, identity details, and social connections.
- """
-
- id: str
- """The unique identifier for the user."""
-
- name: Optional[str] = None
- """The user's display name shown on their public profile."""
-
- typename: Literal["User"]
- """The typename of this object"""
-
- username: str
- """The user's unique username shown on their public profile."""
-
-
-class OriginCompany(BaseModel):
- """A company is a seller on Whop.
-
- Companies own products, manage members, and receive payouts.
- """
-
- id: str
- """The unique identifier for the company."""
-
- route: str
- """
- The URL slug for the company's store page (e.g., 'pickaxe' in whop.com/pickaxe).
- """
-
- title: str
- """The display name of the company shown to customers."""
-
- typename: Literal["Company"]
- """The typename of this object"""
-
-
-Origin: TypeAlias = Annotated[
- Union[Optional[OriginUser], Optional[OriginCompany]], PropertyInfo(discriminator="typename")
-]
-
-
-class Transfer(BaseModel):
- """A transfer of credit between two ledger accounts."""
-
- id: str
- """The unique identifier for the credit transaction transfer."""
-
- amount: float
- """The transfer amount in the currency specified by the currency field.
-
- For example, 10.43 represents $10.43 USD.
- """
-
- created_at: datetime
- """The datetime the credit transaction transfer was created."""
-
- currency: Currency
- """The currency in which this transfer amount is denominated."""
-
- destination: Destination
- """The entity receiving the transferred funds."""
-
- destination_ledger_account_id: str
- """The unique identifier of the ledger account receiving the funds."""
-
- fee_amount: Optional[float] = None
- """The flat fee amount deducted from this transfer, in the transfer's currency.
-
- Null if no flat fee was applied.
- """
-
- metadata: Optional[Dict[str, object]] = None
- """Custom key-value pairs attached to this transfer.
-
- Maximum 50 keys, 500 characters per key, 5000 characters per value.
- """
-
- notes: Optional[str] = None
- """A free-text note attached to this transfer by the sender.
-
- Null if no note was provided.
- """
-
- origin: Origin
- """The entity that sent the transferred funds."""
-
- origin_ledger_account_id: str
- """The unique identifier of the ledger account that sent the funds."""
diff --git a/src/whop_sdk/types/shared_params/__init__.py b/src/whop_sdk/types/shared_params/__init__.py
index eb838c16..e2000124 100644
--- a/src/whop_sdk/types/shared_params/__init__.py
+++ b/src/whop_sdk/types/shared_params/__init__.py
@@ -1,10 +1,8 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from .currency import Currency as Currency
-from .tax_type import TaxType as TaxType
from .direction import Direction as Direction
from .plan_type import PlanType as PlanType
-from .custom_cta import CustomCta as CustomCta
from .promo_type import PromoType as PromoType
from .visibility import Visibility as Visibility
from .access_level import AccessLevel as AccessLevel
@@ -17,10 +15,8 @@
from .receipt_status import ReceiptStatus as ReceiptStatus
from .release_method import ReleaseMethod as ReleaseMethod
from .member_statuses import MemberStatuses as MemberStatuses
-from .access_pass_type import AccessPassType as AccessPassType
from .collection_method import CollectionMethod as CollectionMethod
from .membership_status import MembershipStatus as MembershipStatus
-from .visibility_filter import VisibilityFilter as VisibilityFilter
from .app_build_statuses import AppBuildStatuses as AppBuildStatuses
from .who_can_post_types import WhoCanPostTypes as WhoCanPostTypes
from .app_build_platforms import AppBuildPlatforms as AppBuildPlatforms
diff --git a/src/whop_sdk/types/shared_params/access_pass_type.py b/src/whop_sdk/types/shared_params/access_pass_type.py
deleted file mode 100644
index 3f760c67..00000000
--- a/src/whop_sdk/types/shared_params/access_pass_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypeAlias
-
-__all__ = ["AccessPassType"]
-
-AccessPassType: TypeAlias = Literal["regular", "app", "experience_upsell", "api_only"]
diff --git a/src/whop_sdk/types/shared_params/custom_cta.py b/src/whop_sdk/types/shared_params/custom_cta.py
deleted file mode 100644
index 0c2f5d19..00000000
--- a/src/whop_sdk/types/shared_params/custom_cta.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypeAlias
-
-__all__ = ["CustomCta"]
-
-CustomCta: TypeAlias = Literal[
- "get_access",
- "join",
- "order_now",
- "shop_now",
- "call_now",
- "donate_now",
- "contact_us",
- "sign_up",
- "subscribe",
- "purchase",
- "get_offer",
- "apply_now",
- "complete_order",
-]
diff --git a/src/whop_sdk/types/shared_params/tax_type.py b/src/whop_sdk/types/shared_params/tax_type.py
deleted file mode 100644
index bae01a1a..00000000
--- a/src/whop_sdk/types/shared_params/tax_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypeAlias
-
-__all__ = ["TaxType"]
-
-TaxType: TypeAlias = Literal["inclusive", "exclusive", "unspecified"]
diff --git a/src/whop_sdk/types/shared_params/visibility_filter.py b/src/whop_sdk/types/shared_params/visibility_filter.py
deleted file mode 100644
index d01e6cb1..00000000
--- a/src/whop_sdk/types/shared_params/visibility_filter.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, TypeAlias
-
-__all__ = ["VisibilityFilter"]
-
-VisibilityFilter: TypeAlias = Literal[
- "visible", "hidden", "archived", "quick_link", "all", "not_quick_link", "not_archived"
-]
diff --git a/src/whop_sdk/types/swap_create_params.py b/src/whop_sdk/types/swap_create_params.py
new file mode 100644
index 00000000..f8335f49
--- /dev/null
+++ b/src/whop_sdk/types/swap_create_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 Union, Optional
+from typing_extensions import Required, TypedDict
+
+__all__ = ["SwapCreateParams"]
+
+
+class SwapCreateParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Business or user account ID (biz*\\** / user*\\**)."""
+
+ amount: Required[str]
+ """Input token amount."""
+
+ from_token: Required[str]
+ """Source token, by contract address or ticker symbol (e.g. "USDT")."""
+
+ to_token: Required[str]
+ """Destination token, by contract address or ticker symbol (e.g. "XAUT")."""
+
+ from_chain: Union[str, int, None]
+
+ slippage_bps: Optional[int]
+
+ to_chain: Union[str, int, None]
diff --git a/src/whop_sdk/types/swap_create_quote_params.py b/src/whop_sdk/types/swap_create_quote_params.py
index 9fc72c96..6343bbde 100644
--- a/src/whop_sdk/types/swap_create_quote_params.py
+++ b/src/whop_sdk/types/swap_create_quote_params.py
@@ -13,10 +13,10 @@ class SwapCreateQuoteParams(TypedDict, total=False):
"""Input token amount."""
from_token: Required[str]
- """Source token contract address."""
+ """Source token, by contract address or ticker symbol (e.g. "USDT")."""
to_token: Required[str]
- """Destination token contract address."""
+ """Destination token, by contract address or ticker symbol (e.g. "XAUT")."""
from_address: Optional[str]
diff --git a/src/whop_sdk/types/swap_create_response.py b/src/whop_sdk/types/swap_create_response.py
new file mode 100644
index 00000000..10a62e85
--- /dev/null
+++ b/src/whop_sdk/types/swap_create_response.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["SwapCreateResponse"]
+
+
+class SwapCreateResponse(BaseModel):
+ id: str
+ """Swap ID — poll GET /swaps/{id} for status."""
+
+ account_id: str
+
+ object: Literal["swap"]
+
+ status: str
+
+ amount_out_expected: Optional[str] = None
+
+ amount_out_min: Optional[str] = None
+
+ rate: Optional[str] = None
+
+ to_chain: Optional[str] = None
diff --git a/src/whop_sdk/types/swap_list_params.py b/src/whop_sdk/types/swap_list_params.py
new file mode 100644
index 00000000..8a5123a2
--- /dev/null
+++ b/src/whop_sdk/types/swap_list_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["SwapListParams"]
+
+
+class SwapListParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Business or user account ID (biz*\\** / user*\\**)."""
diff --git a/src/whop_sdk/types/swap_list_response.py b/src/whop_sdk/types/swap_list_response.py
new file mode 100644
index 00000000..e1c02d5f
--- /dev/null
+++ b/src/whop_sdk/types/swap_list_response.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["SwapListResponse", "Data"]
+
+
+class Data(BaseModel):
+ id: str
+
+ account_id: str
+
+ object: Literal["swap"]
+
+ status: str
+
+ tx_hashes: List[str]
+
+ error: Optional[str] = None
+
+
+class SwapListResponse(BaseModel):
+ data: List[Data]
diff --git a/src/whop_sdk/types/swap_retrieve_response.py b/src/whop_sdk/types/swap_retrieve_response.py
new file mode 100644
index 00000000..cd161b34
--- /dev/null
+++ b/src/whop_sdk/types/swap_retrieve_response.py
@@ -0,0 +1,22 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["SwapRetrieveResponse"]
+
+
+class SwapRetrieveResponse(BaseModel):
+ id: str
+
+ account_id: str
+
+ object: Literal["swap"]
+
+ status: str
+
+ tx_hashes: List[str]
+
+ error: Optional[str] = None
diff --git a/src/whop_sdk/types/tax_identifier_type.py b/src/whop_sdk/types/tax_identifier_type.py
index 6b186a3c..92c4dbb9 100644
--- a/src/whop_sdk/types/tax_identifier_type.py
+++ b/src/whop_sdk/types/tax_identifier_type.py
@@ -8,6 +8,7 @@
"ad_nrt",
"ao_tin",
"ar_cuit",
+ "al_tin",
"am_tin",
"aw_tin",
"au_abn",
@@ -48,6 +49,7 @@
"et_tin",
"eu_oss_vat",
"ge_vat",
+ "gh_tin",
"de_stn",
"gb_vat",
"gn_nif",
diff --git a/src/whop_sdk/types/transfer_create_params.py b/src/whop_sdk/types/transfer_create_params.py
index f1729e58..1718177e 100644
--- a/src/whop_sdk/types/transfer_create_params.py
+++ b/src/whop_sdk/types/transfer_create_params.py
@@ -2,50 +2,56 @@
from __future__ import annotations
-from typing import Dict, Optional
-from typing_extensions import Required, TypedDict
+from typing import Dict, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Required, Annotated, TypedDict
-from .shared.currency import Currency
+from .._utils import PropertyInfo
__all__ = ["TransferCreateParams"]
class TransferCreateParams(TypedDict, total=False):
amount: Required[float]
- """The amount to transfer in the specified currency.
+ """The amount to move, in the transfer currency. For example 25.00."""
- For example, 25.00 for $25.00 USD.
+ origin_id: Required[str]
+ """The account sending the funds.
+
+ A user ID (user_xxx), account ID (biz_xxx), or ledger account ID (ldgr_xxx).
"""
- currency: Required[Currency]
- """The currency of the transfer amount, such as 'usd'."""
+ currency: str
+ """The currency, such as usd. Required for ledger transfers."""
- destination_id: Required[str]
- """The identifier of the account receiving the funds.
+ destination_id: str
+ """The recipient.
- Accepts a user ID ('user_xxx'), company ID ('biz_xxx'), ledger account ID
- ('ldgr_xxx'), or an email address — emails without an existing Whop user trigger
- a placeholder-user signup.
+ Required for ledger and wallet*send (a user*/biz*/ldgr* ID, or — for sends — an
+ email). Omit for claim_link.
"""
- origin_id: Required[str]
- """The identifier of the account sending the funds.
+ expires_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
+ """claim_link only.
- Accepts a user ID ('user_xxx'), company ID ('biz_xxx'), or ledger account ID
- ('ldgr_xxx').
+ Link expiry as an ISO 8601 timestamp. Defaults to 24 hours from creation.
"""
idempotence_key: Optional[str]
- """A unique key to prevent duplicate transfers.
-
- Use a UUID or similar unique string.
- """
+ """Ledger transfers only. A unique key to prevent duplicate transfers."""
metadata: Optional[Dict[str, object]]
- """
- A JSON object of custom metadata to attach to the transfer for tracking
- purposes.
+ """Ledger transfers only.
+
+ Custom key-value pairs attached to the transfer. Max 50 keys, 100 chars per key,
+ 500 chars per string value.
"""
notes: Optional[str]
- """A short note describing the transfer, up to 50 characters."""
+ """Ledger transfers only. A short note describing the transfer."""
+
+ redeemable_count: int
+ """claim_link only. How many different users can claim the link. Defaults to 1."""
+
+ type: Literal["ledger", "wallet_send", "claim_link"]
+ """The kind of money movement. Defaults to ledger."""
diff --git a/src/whop_sdk/types/transfer_create_response.py b/src/whop_sdk/types/transfer_create_response.py
new file mode 100644
index 00000000..dd6d5e70
--- /dev/null
+++ b/src/whop_sdk/types/transfer_create_response.py
@@ -0,0 +1,157 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+
+__all__ = [
+ "TransferCreateResponse",
+ "Transfer",
+ "TransferDestination",
+ "TransferDestinationCompany",
+ "TransferDestinationUser",
+ "TransferOrigin",
+ "TransferOriginCompany",
+ "TransferOriginUser",
+ "Send",
+ "SendDestination",
+ "SendSource",
+ "ClaimLink",
+ "ClaimLinkSource",
+]
+
+
+class TransferDestinationCompany(BaseModel):
+ id: str
+
+ typename: Literal["Company"]
+
+ route: Optional[str] = None
+
+ title: Optional[str] = None
+
+
+class TransferDestinationUser(BaseModel):
+ id: str
+
+ typename: Literal["User"]
+
+ name: Optional[str] = None
+
+ username: Optional[str] = None
+
+
+TransferDestination: TypeAlias = Annotated[
+ Union[TransferDestinationCompany, TransferDestinationUser], PropertyInfo(discriminator="typename")
+]
+
+
+class TransferOriginCompany(BaseModel):
+ id: str
+
+ typename: Literal["Company"]
+
+ route: Optional[str] = None
+
+ title: Optional[str] = None
+
+
+class TransferOriginUser(BaseModel):
+ id: str
+
+ typename: Literal["User"]
+
+ name: Optional[str] = None
+
+ username: Optional[str] = None
+
+
+TransferOrigin: TypeAlias = Annotated[
+ Union[TransferOriginCompany, TransferOriginUser], PropertyInfo(discriminator="typename")
+]
+
+
+class Transfer(BaseModel):
+ """A transfer of credit between two ledger accounts."""
+
+ id: str
+
+ amount: float
+
+ created_at: datetime
+
+ currency: str
+
+ destination: TransferDestination
+
+ destination_ledger_account_id: str
+
+ origin: TransferOrigin
+
+ origin_ledger_account_id: str
+
+ fee_amount: Optional[float] = None
+
+ metadata: Optional[Dict[str, object]] = None
+
+ notes: Optional[str] = None
+
+
+class SendDestination(BaseModel):
+ account_id: str
+
+ address: str
+
+
+class SendSource(BaseModel):
+ account_id: str
+
+ address: str
+
+
+class Send(BaseModel):
+ """Returned for a wallet_send: an onchain USDT send to a recipient."""
+
+ amount: str
+
+ currency: str
+
+ destination: SendDestination
+
+ object: Literal["send"]
+
+ source: SendSource
+
+ tx_hash: str
+
+
+class ClaimLinkSource(BaseModel):
+ account_id: str
+
+
+class ClaimLink(BaseModel):
+ """Returned for a claim_link: a shareable URL anyone can open to claim the funds."""
+
+ id: str
+
+ amount: str
+
+ claim_url: str
+
+ currency: str
+
+ expires_at: Optional[datetime] = None
+
+ object: Literal["claim_link"]
+
+ redeemable_count: int
+
+ source: ClaimLinkSource
+
+ status: str
+
+
+TransferCreateResponse: TypeAlias = Union[Transfer, Send, ClaimLink]
diff --git a/src/whop_sdk/types/transfer_list_params.py b/src/whop_sdk/types/transfer_list_params.py
index aedb7b41..2f6bd493 100644
--- a/src/whop_sdk/types/transfer_list_params.py
+++ b/src/whop_sdk/types/transfer_list_params.py
@@ -2,49 +2,38 @@
from __future__ import annotations
-from typing import Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, Annotated, TypedDict
-
-from .._utils import PropertyInfo
-from .shared.direction import Direction
+from typing_extensions import Literal, TypedDict
__all__ = ["TransferListParams"]
class TransferListParams(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."""
-
- created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Only return transfers created after this timestamp."""
+ after: str
+ """Cursor to fetch the page after (from page_info.end_cursor)."""
- created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """Only return transfers created before this timestamp."""
+ before: str
+ """Cursor to fetch the page before (from page_info.start_cursor)."""
- destination_id: Optional[str]
- """Filter to transfers received by this account.
+ created_after: str
+ """Only transfers created strictly after this ISO 8601 timestamp."""
- Accepts a user, company, or ledger account ID.
- """
+ created_before: str
+ """Only transfers created strictly before this ISO 8601 timestamp."""
- direction: Optional[Direction]
- """The direction of the sort."""
+ destination_id: str
+ """Filter to transfers received by this account."""
- first: Optional[int]
- """Returns the first _n_ elements from the list."""
+ direction: Literal["asc", "desc"]
+ """Sort direction. Defaults to desc."""
- last: Optional[int]
- """Returns the last _n_ elements from the list."""
+ first: int
+ """Number of transfers to return from the start of the window."""
- order: Optional[Literal["amount", "created_at"]]
- """Which columns can be used to sort."""
+ last: int
+ """Number of transfers to return from the end of the window."""
- origin_id: Optional[str]
- """Filter to transfers sent from this account.
+ order: Literal["created_at", "amount"]
+ """Sort column. Defaults to created_at."""
- Accepts a user, company, or ledger account ID.
- """
+ origin_id: str
+ """Filter to transfers sent from this account."""
diff --git a/src/whop_sdk/types/transfer_list_response.py b/src/whop_sdk/types/transfer_list_response.py
index 7e1530a3..5a167016 100644
--- a/src/whop_sdk/types/transfer_list_response.py
+++ b/src/whop_sdk/types/transfer_list_response.py
@@ -4,7 +4,6 @@
from datetime import datetime
from .._models import BaseModel
-from .shared.currency import Currency
__all__ = ["TransferListResponse"]
@@ -13,40 +12,19 @@ class TransferListResponse(BaseModel):
"""A transfer of credit between two ledger accounts."""
id: str
- """The unique identifier for the credit transaction transfer."""
amount: float
- """The transfer amount in the currency specified by the currency field.
-
- For example, 10.43 represents $10.43 USD.
- """
created_at: datetime
- """The datetime the credit transaction transfer was created."""
- currency: Currency
- """The currency in which this transfer amount is denominated."""
+ currency: str
destination_ledger_account_id: str
- """The unique identifier of the ledger account receiving the funds."""
- fee_amount: Optional[float] = None
- """The flat fee amount deducted from this transfer, in the transfer's currency.
+ origin_ledger_account_id: str
- Null if no flat fee was applied.
- """
+ fee_amount: Optional[float] = None
metadata: Optional[Dict[str, object]] = None
- """Custom key-value pairs attached to this transfer.
-
- Maximum 50 keys, 500 characters per key, 5000 characters per value.
- """
notes: Optional[str] = None
- """A free-text note attached to this transfer by the sender.
-
- Null if no note was provided.
- """
-
- origin_ledger_account_id: str
- """The unique identifier of the ledger account that sent the funds."""
diff --git a/src/whop_sdk/types/transfer_retrieve_response.py b/src/whop_sdk/types/transfer_retrieve_response.py
new file mode 100644
index 00000000..c06cef55
--- /dev/null
+++ b/src/whop_sdk/types/transfer_retrieve_response.py
@@ -0,0 +1,90 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+
+__all__ = [
+ "TransferRetrieveResponse",
+ "Destination",
+ "DestinationCompany",
+ "DestinationUser",
+ "Origin",
+ "OriginCompany",
+ "OriginUser",
+]
+
+
+class DestinationCompany(BaseModel):
+ id: str
+
+ typename: Literal["Company"]
+
+ route: Optional[str] = None
+
+ title: Optional[str] = None
+
+
+class DestinationUser(BaseModel):
+ id: str
+
+ typename: Literal["User"]
+
+ name: Optional[str] = None
+
+ username: Optional[str] = None
+
+
+Destination: TypeAlias = Annotated[Union[DestinationCompany, DestinationUser], PropertyInfo(discriminator="typename")]
+
+
+class OriginCompany(BaseModel):
+ id: str
+
+ typename: Literal["Company"]
+
+ route: Optional[str] = None
+
+ title: Optional[str] = None
+
+
+class OriginUser(BaseModel):
+ id: str
+
+ typename: Literal["User"]
+
+ name: Optional[str] = None
+
+ username: Optional[str] = None
+
+
+Origin: TypeAlias = Annotated[Union[OriginCompany, OriginUser], PropertyInfo(discriminator="typename")]
+
+
+class TransferRetrieveResponse(BaseModel):
+ """A transfer of credit between two ledger accounts."""
+
+ id: str
+
+ amount: float
+
+ created_at: datetime
+
+ currency: str
+
+ destination: Destination
+
+ destination_ledger_account_id: str
+
+ origin: Origin
+
+ origin_ledger_account_id: str
+
+ fee_amount: Optional[float] = None
+
+ metadata: Optional[Dict[str, object]] = None
+
+ notes: Optional[str] = None
diff --git a/src/whop_sdk/types/unwrap_webhook_event.py b/src/whop_sdk/types/unwrap_webhook_event.py
index dde154cc..dc6ad61b 100644
--- a/src/whop_sdk/types/unwrap_webhook_event.py
+++ b/src/whop_sdk/types/unwrap_webhook_event.py
@@ -22,7 +22,9 @@
from .payment_succeeded_webhook_event import PaymentSucceededWebhookEvent
from .withdrawal_created_webhook_event import WithdrawalCreatedWebhookEvent
from .withdrawal_updated_webhook_event import WithdrawalUpdatedWebhookEvent
+from .chat_message_created_webhook_event import ChatMessageCreatedWebhookEvent
from .membership_activated_webhook_event import MembershipActivatedWebhookEvent
+from .chat_reaction_created_webhook_event import ChatReactionCreatedWebhookEvent
from .dispute_alert_created_webhook_event import DisputeAlertCreatedWebhookEvent
from .payout_method_created_webhook_event import PayoutMethodCreatedWebhookEvent
from .setup_intent_canceled_webhook_event import SetupIntentCanceledWebhookEvent
@@ -33,9 +35,11 @@
from .identity_profile_approved_webhook_event import IdentityProfileApprovedWebhookEvent
from .identity_profile_rejected_webhook_event import IdentityProfileRejectedWebhookEvent
from .invoice_marked_uncollectible_webhook_event import InvoiceMarkedUncollectibleWebhookEvent
+from .membership_trial_ending_soon_webhook_event import MembershipTrialEndingSoonWebhookEvent
from .setup_intent_requires_action_webhook_event import SetupIntentRequiresActionWebhookEvent
from .identity_profile_needs_action_webhook_event import IdentityProfileNeedsActionWebhookEvent
from .payout_account_status_updated_webhook_event import PayoutAccountStatusUpdatedWebhookEvent
+from .ledger_account_funds_available_webhook_event import LedgerAccountFundsAvailableWebhookEvent
from .resolution_center_case_created_webhook_event import ResolutionCenterCaseCreatedWebhookEvent
from .resolution_center_case_decided_webhook_event import ResolutionCenterCaseDecidedWebhookEvent
from .resolution_center_case_updated_webhook_event import ResolutionCenterCaseUpdatedWebhookEvent
@@ -46,6 +50,8 @@
UnwrapWebhookEvent: TypeAlias = Annotated[
Union[
+ ChatMessageCreatedWebhookEvent,
+ ChatReactionCreatedWebhookEvent,
CourseLessonInteractionCompletedWebhookEvent,
DisputeCreatedWebhookEvent,
DisputeUpdatedWebhookEvent,
@@ -63,9 +69,11 @@
InvoicePaidWebhookEvent,
InvoicePastDueWebhookEvent,
InvoiceVoidedWebhookEvent,
+ LedgerAccountFundsAvailableWebhookEvent,
MembershipActivatedWebhookEvent,
MembershipCancelAtPeriodEndChangedWebhookEvent,
MembershipDeactivatedWebhookEvent,
+ MembershipTrialEndingSoonWebhookEvent,
PaymentCreatedWebhookEvent,
PaymentFailedWebhookEvent,
PaymentPendingWebhookEvent,
diff --git a/src/whop_sdk/types/user.py b/src/whop_sdk/types/user.py
index 4e52982f..9295b603 100644
--- a/src/whop_sdk/types/user.py
+++ b/src/whop_sdk/types/user.py
@@ -1,49 +1,77 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
-from datetime import datetime
+from typing import List, Optional
from .._models import BaseModel
-__all__ = ["User", "ProfilePicture"]
+__all__ = ["User", "Balance"]
-class ProfilePicture(BaseModel):
- """The user's profile picture attachment with URL, content type, and file metadata.
+class Balance(BaseModel):
+ """The user's holdings (crypto and fiat), each with its USD value.
- Null if using a legacy profile picture.
+ Empty when total_usd is null (not computed)
"""
- url: Optional[str] = None
- """A pre-optimized URL for rendering this attachment on the client.
+ balance: str
+ """The total amount held in native units, as a decimal string"""
- This should be used for displaying attachments in apps.
+ breakdown: object
+ """
+ The holding split into available, pending, and reserve amounts (native-unit
+ decimal strings). On-chain crypto is entirely available; good_funds and fiat
+ cash can have pending/reserve portions
"""
+ icon_url: Optional[str] = None
+ """The URL of the holding's icon, when available"""
-class User(BaseModel):
- """A user account on Whop.
+ name: str
+ """The holding's display name"""
+
+ price_usd: Optional[float] = None
+ """The USD price per unit, or null when no exchange rate is available"""
+
+ symbol: str
+ """The holding's display symbol, e.g. USDT, cbBTC, or EUR"""
+
+ value_usd: Optional[str] = None
+ """The total USD value of the holding, or null when no exchange rate is available"""
- Contains profile information, identity details, and social connections.
- """
+class User(BaseModel):
id: str
- """The unique identifier for the user."""
+ """The ID of the user, which will look like user\\__******\\********"""
+
+ balances: List[Balance]
bio: Optional[str] = None
- """A short biography written by the user, displayed on their public profile."""
+ """The user's biography"""
- created_at: datetime
- """The datetime the user was created."""
+ created_at: str
+ """When the user was created, as an ISO 8601 timestamp"""
name: Optional[str] = None
- """The user's display name shown on their public profile."""
+ """The user's display name"""
+
+ profile_picture: Optional[object] = None
+ """The user's profile picture, an object with a url"""
- profile_picture: Optional[ProfilePicture] = None
- """The user's profile picture attachment with URL, content type, and file metadata.
+ total_usd: Optional[str] = None
+ """Total USD value across all balances with a known exchange rate.
- Null if using a legacy profile picture.
+ Only computed on the self-view (GET /users/me) for callers with the balance-read
+ scope; null (with an empty balances array) otherwise and when the balance source
+ is unavailable
"""
username: str
- """The user's unique username shown on their public profile."""
+ """The user's unique username"""
+
+ verification: object
+ """The user's identity-verification status.
+
+ `individual` is KYC, `business` is KYB; each is null when that profile has not
+ been created, otherwise { status } where status is one of not_started, pending,
+ approved, rejected
+ """
diff --git a/src/whop_sdk/types/user_check_access_response.py b/src/whop_sdk/types/user_check_access_response.py
index 270d822a..ad8fb2fe 100644
--- a/src/whop_sdk/types/user_check_access_response.py
+++ b/src/whop_sdk/types/user_check_access_response.py
@@ -1,16 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from typing_extensions import Literal
+
from .._models import BaseModel
-from .shared.access_level import AccessLevel
__all__ = ["UserCheckAccessResponse"]
class UserCheckAccessResponse(BaseModel):
- """The result of a has access check for the developer API"""
-
- access_level: AccessLevel
- """The permission level of the user"""
+ access_level: Literal["no_access", "admin", "customer"]
has_access: bool
- """Whether the user has access to the resource"""
diff --git a/src/whop_sdk/types/user_list_params.py b/src/whop_sdk/types/user_list_params.py
index bce47d6c..14d3e4fa 100644
--- a/src/whop_sdk/types/user_list_params.py
+++ b/src/whop_sdk/types/user_list_params.py
@@ -2,24 +2,23 @@
from __future__ import annotations
-from typing import Optional
from typing_extensions import TypedDict
__all__ = ["UserListParams"]
class UserListParams(TypedDict, total=False):
- after: Optional[str]
- """Returns the elements in the list that come after the specified cursor."""
+ after: str
+ """A cursor; returns users after this position."""
- before: Optional[str]
- """Returns the elements in the list that come before the specified cursor."""
+ before: str
+ """A cursor; returns users before this position."""
- first: Optional[int]
- """Returns the first _n_ elements from the list."""
+ first: int
+ """The number of users to return (max 50)."""
- last: Optional[int]
- """Returns the last _n_ elements from the list."""
+ last: int
+ """The number of users to return from the end of the range."""
- query: Optional[str]
- """Search term to filter by name or username."""
+ query: str
+ """A search term to filter users by name or username."""
diff --git a/src/whop_sdk/types/user_list_response.py b/src/whop_sdk/types/user_list_response.py
deleted file mode 100644
index 1621e20c..00000000
--- a/src/whop_sdk/types/user_list_response.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-from datetime import datetime
-
-from .._models import BaseModel
-
-__all__ = ["UserListResponse", "ProfilePicture"]
-
-
-class ProfilePicture(BaseModel):
- """The user's profile picture attachment with URL, content type, and file metadata.
-
- Null if using a legacy profile picture.
- """
-
- url: Optional[str] = None
- """A pre-optimized URL for rendering this attachment on the client.
-
- This should be used for displaying attachments in apps.
- """
-
-
-class UserListResponse(BaseModel):
- """A user account on Whop.
-
- Contains profile information, identity details, and social connections.
- """
-
- id: str
- """The unique identifier for the user."""
-
- bio: Optional[str] = None
- """A short biography written by the user, displayed on their public profile."""
-
- created_at: datetime
- """The datetime the user was created."""
-
- name: Optional[str] = None
- """The user's display name shown on their public profile."""
-
- profile_picture: Optional[ProfilePicture] = None
- """The user's profile picture attachment with URL, content type, and file metadata.
-
- Null if using a legacy profile picture.
- """
-
- username: str
- """The user's unique username shown on their public profile."""
diff --git a/src/whop_sdk/types/user_retrieve_params.py b/src/whop_sdk/types/user_retrieve_params.py
index 8534761b..afb9ca68 100644
--- a/src/whop_sdk/types/user_retrieve_params.py
+++ b/src/whop_sdk/types/user_retrieve_params.py
@@ -2,15 +2,14 @@
from __future__ import annotations
-from typing import Optional
from typing_extensions import TypedDict
__all__ = ["UserRetrieveParams"]
class UserRetrieveParams(TypedDict, total=False):
- company_id: Optional[str]
+ account_id: str
"""
- When provided, returns the user's company-specific profile overrides (name,
- profile picture) instead of their global profile.
+ When set, returns the user's account-specific profile overrides for this
+ account.
"""
diff --git a/src/whop_sdk/types/user_update_me_params.py b/src/whop_sdk/types/user_update_me_params.py
new file mode 100644
index 00000000..63a6a725
--- /dev/null
+++ b/src/whop_sdk/types/user_update_me_params.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["UserUpdateMeParams", "ProfilePicture"]
+
+
+class UserUpdateMeParams(TypedDict, total=False):
+ account_id: str
+ """
+ When set, updates the authenticated user's profile override for this account
+ instead of their global profile.
+ """
+
+ bio: str
+
+ name: str
+
+ profile_picture: ProfilePicture
+
+ username: str
+
+
+class ProfilePicture(TypedDict, total=False):
+ id: str
+
+ direct_upload_id: str
diff --git a/src/whop_sdk/types/user_update_params.py b/src/whop_sdk/types/user_update_params.py
index a1c8572a..c957a3c6 100644
--- a/src/whop_sdk/types/user_update_params.py
+++ b/src/whop_sdk/types/user_update_params.py
@@ -2,38 +2,25 @@
from __future__ import annotations
-from typing import Optional
-from typing_extensions import Required, TypedDict
+from typing_extensions import TypedDict
__all__ = ["UserUpdateParams", "ProfilePicture"]
class UserUpdateParams(TypedDict, total=False):
- bio: Optional[str]
- """A short biography displayed on the user's public profile."""
+ account_id: str
+ """The account whose profile override to update. Required for API key callers."""
- company_id: Optional[str]
- """
- When provided, updates the user's profile overrides for this company instead of
- the global profile. Pass name and profile_picture to set overrides, or null to
- clear them.
- """
+ bio: str
- name: Optional[str]
- """The user's display name shown on their public profile. Maximum 100 characters."""
+ name: str
- profile_picture: Optional[ProfilePicture]
- """The user's profile picture image attachment."""
+ profile_picture: ProfilePicture
- username: Optional[str]
- """The user's unique username.
-
- Alphanumeric characters and hyphens only. Maximum 42 characters.
- """
+ username: str
class ProfilePicture(TypedDict, total=False):
- """The user's profile picture image attachment."""
+ id: str
- id: Required[str]
- """The ID of an existing file object."""
+ direct_upload_id: str
diff --git a/src/whop_sdk/types/verification_create_params.py b/src/whop_sdk/types/verification_create_params.py
new file mode 100644
index 00000000..792d5488
--- /dev/null
+++ b/src/whop_sdk/types/verification_create_params.py
@@ -0,0 +1,77 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["VerificationCreateParams"]
+
+
+class VerificationCreateParams(TypedDict, total=False):
+ account_id: Required[str]
+ """The account ID to verify (biz\\__ tag)."""
+
+ address: Dict[str, object]
+ """Optional pre-fill claim. Address (line1, city, state, postal_code)."""
+
+ business_name: str
+ """Optional pre-fill claim for businesses."""
+
+ business_structure: str
+ """Optional. Business structure (e.g. llc, corporation)."""
+
+ business_website: str
+ """Optional.
+
+ Business website URL. Accepted for both individual and business verifications on
+ company accounts; persisted to the account's metadata and used to provision the
+ payout account on approval. Whop store pages are rejected.
+ """
+
+ country: str
+ """Optional pre-fill claim.
+
+ Country code; for businesses, the country of incorporation.
+ """
+
+ date_of_birth: str
+ """Optional pre-fill claim.
+
+ Seeds the Sumsub session; attested values come from Sumsub on approval.
+ """
+
+ first_name: str
+ """Optional pre-fill claim.
+
+ Seeds the Sumsub session; attested values come from Sumsub on approval.
+ """
+
+ kind: Literal["individual", "business"]
+ """The verification type. Defaults to individual."""
+
+ last_name: str
+ """Optional pre-fill claim.
+
+ Seeds the Sumsub session; attested values come from Sumsub on approval.
+ """
+
+ phone: str
+ """Optional pre-fill claim — phone number."""
+
+ place_of_incorporation: str
+ """Optional.
+
+ Place of incorporation (state/region); maps to the business address state.
+ """
+
+ restart: bool
+ """Whether to restart an in-flight verification."""
+
+ tax_identification_number: str
+ """Optional.
+
+ Tax identification number — SSN for individuals, EIN for businesses. Tokenized
+ in transit, never stored raw; stored on the profile so the payout account,
+ provisioned on approval, doesn't raise a tax-id RFI.
+ """
diff --git a/src/whop_sdk/types/verification_create_response.py b/src/whop_sdk/types/verification_create_response.py
new file mode 100644
index 00000000..ac7a1faa
--- /dev/null
+++ b/src/whop_sdk/types/verification_create_response.py
@@ -0,0 +1,73 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["VerificationCreateResponse", "Rfi", "RfiRequestedFile"]
+
+
+class RfiRequestedFile(BaseModel):
+ category: Optional[str] = None
+
+ is_optional: Optional[bool] = None
+
+ kind: Optional[str] = None
+
+
+class Rfi(BaseModel):
+ id: Optional[str] = None
+
+ created_at: Optional[str] = None
+
+ description: Optional[str] = None
+
+ error_message: Optional[str] = None
+
+ requested_files: Optional[List[RfiRequestedFile]] = None
+ """Documents the provider is requesting (file-upload RFIs).
+
+ The `kind` is what to send back when answering.
+ """
+
+ status: Optional[Literal["outstanding", "invalid"]] = None
+
+ type: Optional[str] = None
+
+
+class VerificationCreateResponse(BaseModel):
+ id: Optional[str] = None
+ """The verification ID, e.g. idpf\\__\\**"""
+
+ address: Optional[object] = None
+
+ business_name: Optional[str] = None
+
+ business_structure: Optional[str] = None
+
+ country: Optional[str] = None
+ """ISO 3166-1 alpha-2 country code (e.g.
+
+ `US`, `GB`). For individuals this is the country of citizenship or residence
+ reported by the identity provider; for businesses this is the country of
+ incorporation.
+ """
+
+ created_at: Optional[str] = None
+
+ date_of_birth: Optional[str] = None
+
+ first_name: Optional[str] = None
+
+ kind: Optional[Literal["individual", "business"]] = None
+
+ last_name: Optional[str] = None
+
+ rfis: Optional[List[Rfi]] = None
+
+ session_url: Optional[str] = None
+
+ status: Optional[Literal["not_started", "pending", "approved", "rejected", "action_required"]] = None
+
+ updated_at: Optional[str] = None
diff --git a/src/whop_sdk/types/verification_delete_response.py b/src/whop_sdk/types/verification_delete_response.py
new file mode 100644
index 00000000..3448aef4
--- /dev/null
+++ b/src/whop_sdk/types/verification_delete_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+
+__all__ = ["VerificationDeleteResponse"]
+
+
+class VerificationDeleteResponse(BaseModel):
+ id: Optional[str] = None
+
+ deleted: Optional[bool] = None
diff --git a/src/whop_sdk/types/verification_list_params.py b/src/whop_sdk/types/verification_list_params.py
index 64ad9314..9b376d72 100644
--- a/src/whop_sdk/types/verification_list_params.py
+++ b/src/whop_sdk/types/verification_list_params.py
@@ -2,24 +2,11 @@
from __future__ import annotations
-from typing import Optional
from typing_extensions import Required, TypedDict
__all__ = ["VerificationListParams"]
class VerificationListParams(TypedDict, total=False):
- payout_account_id: Required[str]
- """The unique identifier of the payout account to list verifications 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."""
-
- first: Optional[int]
- """Returns the first _n_ elements from the list."""
-
- last: Optional[int]
- """Returns the last _n_ elements from the list."""
+ account_id: Required[str]
+ """The account ID to list verifications for (biz\\__ tag)."""
diff --git a/src/whop_sdk/types/verification_list_response.py b/src/whop_sdk/types/verification_list_response.py
index 25d3f1e6..0bd21076 100644
--- a/src/whop_sdk/types/verification_list_response.py
+++ b/src/whop_sdk/types/verification_list_response.py
@@ -1,30 +1,77 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
+from typing_extensions import Literal
from .._models import BaseModel
-from .verification_status import VerificationStatus
-from .verification_error_code import VerificationErrorCode
-__all__ = ["VerificationListResponse"]
+__all__ = ["VerificationListResponse", "Data", "DataRfi", "DataRfiRequestedFile"]
-class VerificationListResponse(BaseModel):
- """
- An identity verification session used to confirm a person or entity's identity for payout account eligibility.
+class DataRfiRequestedFile(BaseModel):
+ category: Optional[str] = None
+
+ is_optional: Optional[bool] = None
+
+ kind: Optional[str] = None
+
+
+class DataRfi(BaseModel):
+ id: Optional[str] = None
+
+ created_at: Optional[str] = None
+
+ description: Optional[str] = None
+
+ error_message: Optional[str] = None
+
+ requested_files: Optional[List[DataRfiRequestedFile]] = None
+ """Documents the provider is requesting (file-upload RFIs).
+
+ The `kind` is what to send back when answering.
"""
- id: str
- """The numeric id of the verification record."""
+ status: Optional[Literal["outstanding", "invalid"]] = None
+
+ type: Optional[str] = None
+
+
+class Data(BaseModel):
+ id: Optional[str] = None
+ """The verification ID, e.g. idpf\\__\\**"""
- last_error_code: Optional[VerificationErrorCode] = None
- """An error code for a verification attempt."""
+ address: Optional[object] = None
- last_error_reason: Optional[str] = None
- """A human-readable explanation of the most recent verification error.
+ business_name: Optional[str] = None
- Null if no error has occurred.
+ business_structure: Optional[str] = None
+
+ country: Optional[str] = None
+ """ISO 3166-1 alpha-2 country code (e.g.
+
+ `US`, `GB`). For individuals this is the country of citizenship or residence
+ reported by the identity provider; for businesses this is the country of
+ incorporation.
"""
- status: VerificationStatus
- """The current status of this verification session."""
+ created_at: Optional[str] = None
+
+ date_of_birth: Optional[str] = None
+
+ first_name: Optional[str] = None
+
+ kind: Optional[Literal["individual", "business"]] = None
+
+ last_name: Optional[str] = None
+
+ rfis: Optional[List[DataRfi]] = None
+
+ session_url: Optional[str] = None
+
+ status: Optional[Literal["not_started", "pending", "approved", "rejected", "action_required"]] = None
+
+ updated_at: Optional[str] = None
+
+
+class VerificationListResponse(BaseModel):
+ data: Optional[List[Data]] = None
diff --git a/src/whop_sdk/types/verification_retrieve_response.py b/src/whop_sdk/types/verification_retrieve_response.py
index 9228eef9..2b37ff1e 100644
--- a/src/whop_sdk/types/verification_retrieve_response.py
+++ b/src/whop_sdk/types/verification_retrieve_response.py
@@ -1,30 +1,73 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
+from typing_extensions import Literal
from .._models import BaseModel
-from .verification_status import VerificationStatus
-from .verification_error_code import VerificationErrorCode
-__all__ = ["VerificationRetrieveResponse"]
+__all__ = ["VerificationRetrieveResponse", "Rfi", "RfiRequestedFile"]
-class VerificationRetrieveResponse(BaseModel):
- """
- An identity verification session used to confirm a person or entity's identity for payout account eligibility.
+class RfiRequestedFile(BaseModel):
+ category: Optional[str] = None
+
+ is_optional: Optional[bool] = None
+
+ kind: Optional[str] = None
+
+
+class Rfi(BaseModel):
+ id: Optional[str] = None
+
+ created_at: Optional[str] = None
+
+ description: Optional[str] = None
+
+ error_message: Optional[str] = None
+
+ requested_files: Optional[List[RfiRequestedFile]] = None
+ """Documents the provider is requesting (file-upload RFIs).
+
+ The `kind` is what to send back when answering.
"""
- id: str
- """The numeric id of the verification record."""
+ status: Optional[Literal["outstanding", "invalid"]] = None
+
+ type: Optional[str] = None
- last_error_code: Optional[VerificationErrorCode] = None
- """An error code for a verification attempt."""
- last_error_reason: Optional[str] = None
- """A human-readable explanation of the most recent verification error.
+class VerificationRetrieveResponse(BaseModel):
+ id: Optional[str] = None
+ """The verification ID, e.g. idpf\\__\\**"""
- Null if no error has occurred.
+ address: Optional[object] = None
+
+ business_name: Optional[str] = None
+
+ business_structure: Optional[str] = None
+
+ country: Optional[str] = None
+ """ISO 3166-1 alpha-2 country code (e.g.
+
+ `US`, `GB`). For individuals this is the country of citizenship or residence
+ reported by the identity provider; for businesses this is the country of
+ incorporation.
"""
- status: VerificationStatus
- """The current status of this verification session."""
+ created_at: Optional[str] = None
+
+ date_of_birth: Optional[str] = None
+
+ first_name: Optional[str] = None
+
+ kind: Optional[Literal["individual", "business"]] = None
+
+ last_name: Optional[str] = None
+
+ rfis: Optional[List[Rfi]] = None
+
+ session_url: Optional[str] = None
+
+ status: Optional[Literal["not_started", "pending", "approved", "rejected", "action_required"]] = None
+
+ updated_at: Optional[str] = None
diff --git a/src/whop_sdk/types/verification_update_params.py b/src/whop_sdk/types/verification_update_params.py
new file mode 100644
index 00000000..1e1b3b3e
--- /dev/null
+++ b/src/whop_sdk/types/verification_update_params.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Iterable
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["VerificationUpdateParams", "Rfi"]
+
+
+class VerificationUpdateParams(TypedDict, total=False):
+ business_address: Dict[str, object]
+ """The business address."""
+
+ business_name: str
+ """The business name."""
+
+ business_structure: str
+ """The business structure."""
+
+ country: str
+ """The country code."""
+
+ date_of_birth: str
+ """The date of birth."""
+
+ first_name: str
+ """The first name on the verification."""
+
+ last_name: str
+ """The last name on the verification."""
+
+ personal_address: Dict[str, object]
+ """The personal address."""
+
+ rfis: Iterable[Rfi]
+ """RFI responses.
+
+ Each entry must include id and a value, address, or files payload.
+ """
+
+
+class Rfi(TypedDict, total=False):
+ id: Required[str]
+ """The RFI tag (paa\\__\\**)."""
+
+ address: Dict[str, object]
+ """Address payload for address RFIs."""
+
+ files: Iterable[object]
+ """File upload payload for document RFIs."""
+
+ value: str
+ """The value for text/date/phone RFIs."""
+
+ value_type: Literal["raw", "vault_token"]
+ """Defaults to raw."""
diff --git a/src/whop_sdk/types/verification_update_response.py b/src/whop_sdk/types/verification_update_response.py
new file mode 100644
index 00000000..a75097ee
--- /dev/null
+++ b/src/whop_sdk/types/verification_update_response.py
@@ -0,0 +1,73 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["VerificationUpdateResponse", "Rfi", "RfiRequestedFile"]
+
+
+class RfiRequestedFile(BaseModel):
+ category: Optional[str] = None
+
+ is_optional: Optional[bool] = None
+
+ kind: Optional[str] = None
+
+
+class Rfi(BaseModel):
+ id: Optional[str] = None
+
+ created_at: Optional[str] = None
+
+ description: Optional[str] = None
+
+ error_message: Optional[str] = None
+
+ requested_files: Optional[List[RfiRequestedFile]] = None
+ """Documents the provider is requesting (file-upload RFIs).
+
+ The `kind` is what to send back when answering.
+ """
+
+ status: Optional[Literal["outstanding", "invalid"]] = None
+
+ type: Optional[str] = None
+
+
+class VerificationUpdateResponse(BaseModel):
+ id: Optional[str] = None
+ """The verification ID, e.g. idpf\\__\\**"""
+
+ address: Optional[object] = None
+
+ business_name: Optional[str] = None
+
+ business_structure: Optional[str] = None
+
+ country: Optional[str] = None
+ """ISO 3166-1 alpha-2 country code (e.g.
+
+ `US`, `GB`). For individuals this is the country of citizenship or residence
+ reported by the identity provider; for businesses this is the country of
+ incorporation.
+ """
+
+ created_at: Optional[str] = None
+
+ date_of_birth: Optional[str] = None
+
+ first_name: Optional[str] = None
+
+ kind: Optional[Literal["individual", "business"]] = None
+
+ last_name: Optional[str] = None
+
+ rfis: Optional[List[Rfi]] = None
+
+ session_url: Optional[str] = None
+
+ status: Optional[Literal["not_started", "pending", "approved", "rejected", "action_required"]] = None
+
+ updated_at: Optional[str] = None
diff --git a/src/whop_sdk/types/wallet_balance_response.py b/src/whop_sdk/types/wallet_balance_response.py
deleted file mode 100644
index c88cc393..00000000
--- a/src/whop_sdk/types/wallet_balance_response.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-from typing_extensions import Literal
-
-from .._models import BaseModel
-
-__all__ = ["WalletBalanceResponse", "Token"]
-
-
-class Token(BaseModel):
- balance: str
-
- icon_url: Optional[str] = None
-
- name: str
-
- price_usd: float
-
- symbol: str
-
- token_address: Optional[str] = None
-
- value_usd: str
-
-
-class WalletBalanceResponse(BaseModel):
- object: Literal["balance"]
-
- tokens: List[Token]
-
- total_usd: str
diff --git a/src/whop_sdk/types/wallet_list_response.py b/src/whop_sdk/types/wallet_list_response.py
deleted file mode 100644
index 2527d869..00000000
--- a/src/whop_sdk/types/wallet_list_response.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List
-
-from .._models import BaseModel
-
-__all__ = ["WalletListResponse", "Wallet"]
-
-
-class Wallet(BaseModel):
- address: str
-
- balance_usd: str
-
- network: str
-
-
-class WalletListResponse(BaseModel):
- wallets: List[Wallet]
diff --git a/src/whop_sdk/types/wallet_send_params.py b/src/whop_sdk/types/wallet_send_params.py
deleted file mode 100644
index 03889c27..00000000
--- a/src/whop_sdk/types/wallet_send_params.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-__all__ = ["WalletSendParams"]
-
-
-class WalletSendParams(TypedDict, total=False):
- amount: Required[str]
- """USDT amount to send."""
-
- to: Required[str]
- """Recipient user ID, business account ID, ledger account ID, or email."""
diff --git a/src/whop_sdk/types/wallet_send_response.py b/src/whop_sdk/types/wallet_send_response.py
deleted file mode 100644
index 5db26b85..00000000
--- a/src/whop_sdk/types/wallet_send_response.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal
-
-from .._models import BaseModel
-
-__all__ = ["WalletSendResponse", "Destination", "Source"]
-
-
-class Destination(BaseModel):
- account_id: str
-
- address: str
-
-
-class Source(BaseModel):
- account_id: str
-
- address: str
-
-
-class WalletSendResponse(BaseModel):
- amount: str
-
- currency: str
-
- destination: Destination
-
- object: Literal["send"]
-
- source: Source
-
- tx_hash: str
diff --git a/src/whop_sdk/types/webhook_event.py b/src/whop_sdk/types/webhook_event.py
index 3b76647a..7167e81a 100644
--- a/src/whop_sdk/types/webhook_event.py
+++ b/src/whop_sdk/types/webhook_event.py
@@ -12,6 +12,7 @@
"invoice.voided",
"membership.activated",
"membership.deactivated",
+ "membership.trial_ending_soon",
"entry.created",
"entry.approved",
"entry.denied",
@@ -19,6 +20,7 @@
"setup_intent.requires_action",
"setup_intent.succeeded",
"setup_intent.canceled",
+ "ledger_account.funds_available",
"withdrawal.created",
"withdrawal.updated",
"course_lesson_interaction.completed",
@@ -32,6 +34,8 @@
"resolution_center_case.created",
"resolution_center_case.updated",
"resolution_center_case.decided",
+ "chat.message.created",
+ "chat.reaction.created",
"payment.created",
"payment.succeeded",
"payment.failed",
diff --git a/src/whop_sdk/types/withdrawal_create_params.py b/src/whop_sdk/types/withdrawal_create_params.py
index 46d134f2..3345abab 100644
--- a/src/whop_sdk/types/withdrawal_create_params.py
+++ b/src/whop_sdk/types/withdrawal_create_params.py
@@ -24,7 +24,7 @@ class WithdrawalCreateParams(TypedDict, total=False):
"""The ID of the payout method to use for the withdrawal."""
platform_covers_fees: Optional[bool]
- """Whether the platform covers the payout fees instead of the connected account."""
+ """Whether the platform covers the payout fees."""
statement_descriptor: Optional[str]
"""Custom statement descriptor for the withdrawal.
diff --git a/tests/api_resources/referrals/__init__.py b/tests/api_resources/referrals/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/referrals/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/referrals/businesses/__init__.py b/tests/api_resources/referrals/businesses/__init__.py
new file mode 100644
index 00000000..fd8019a9
--- /dev/null
+++ b/tests/api_resources/referrals/businesses/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/referrals/businesses/test_earnings.py b/tests/api_resources/referrals/businesses/test_earnings.py
new file mode 100644
index 00000000..5625938a
--- /dev/null
+++ b/tests/api_resources/referrals/businesses/test_earnings.py
@@ -0,0 +1,141 @@
+# 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.referrals.businesses import EarningListResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestEarnings:
+ 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_list(self, client: Whop) -> None:
+ earning = client.referrals.businesses.earnings.list(
+ id="id",
+ )
+ assert_matches_type(SyncCursorPage[EarningListResponse], earning, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Whop) -> None:
+ earning = client.referrals.businesses.earnings.list(
+ id="id",
+ after="after",
+ before="before",
+ first=100,
+ include="receipt_fees",
+ last=100,
+ order="asc",
+ sort="created_at",
+ status="awaiting_settlement",
+ )
+ assert_matches_type(SyncCursorPage[EarningListResponse], earning, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.referrals.businesses.earnings.with_raw_response.list(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ earning = response.parse()
+ assert_matches_type(SyncCursorPage[EarningListResponse], earning, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.referrals.businesses.earnings.with_streaming_response.list(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ earning = response.parse()
+ assert_matches_type(SyncCursorPage[EarningListResponse], earning, 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.referrals.businesses.earnings.with_raw_response.list(
+ id="",
+ )
+
+
+class TestAsyncEarnings:
+ 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_list(self, async_client: AsyncWhop) -> None:
+ earning = await async_client.referrals.businesses.earnings.list(
+ id="id",
+ )
+ assert_matches_type(AsyncCursorPage[EarningListResponse], earning, 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:
+ earning = await async_client.referrals.businesses.earnings.list(
+ id="id",
+ after="after",
+ before="before",
+ first=100,
+ include="receipt_fees",
+ last=100,
+ order="asc",
+ sort="created_at",
+ status="awaiting_settlement",
+ )
+ assert_matches_type(AsyncCursorPage[EarningListResponse], earning, 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.referrals.businesses.earnings.with_raw_response.list(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ earning = await response.parse()
+ assert_matches_type(AsyncCursorPage[EarningListResponse], earning, 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.referrals.businesses.earnings.with_streaming_response.list(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ earning = await response.parse()
+ assert_matches_type(AsyncCursorPage[EarningListResponse], earning, 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.referrals.businesses.earnings.with_raw_response.list(
+ id="",
+ )
diff --git a/tests/api_resources/referrals/test_businesses.py b/tests/api_resources/referrals/test_businesses.py
new file mode 100644
index 00000000..51c774a5
--- /dev/null
+++ b/tests/api_resources/referrals/test_businesses.py
@@ -0,0 +1,281 @@
+# 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.referrals import (
+ BusinessListResponse,
+ BusinessRetrieveResponse,
+ BusinessListEarningsResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestBusinesses:
+ 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_retrieve(self, client: Whop) -> None:
+ business = client.referrals.businesses.retrieve(
+ "id",
+ )
+ assert_matches_type(BusinessRetrieveResponse, business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Whop) -> None:
+ response = client.referrals.businesses.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ business = response.parse()
+ assert_matches_type(BusinessRetrieveResponse, business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Whop) -> None:
+ with client.referrals.businesses.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ business = response.parse()
+ assert_matches_type(BusinessRetrieveResponse, business, 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.referrals.businesses.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Whop) -> None:
+ business = client.referrals.businesses.list()
+ assert_matches_type(SyncCursorPage[BusinessListResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Whop) -> None:
+ business = client.referrals.businesses.list(
+ after="after",
+ before="before",
+ first=100,
+ has_earnings=True,
+ last=100,
+ status="active",
+ )
+ assert_matches_type(SyncCursorPage[BusinessListResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.referrals.businesses.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ business = response.parse()
+ assert_matches_type(SyncCursorPage[BusinessListResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.referrals.businesses.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ business = response.parse()
+ assert_matches_type(SyncCursorPage[BusinessListResponse], business, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_earnings(self, client: Whop) -> None:
+ business = client.referrals.businesses.list_earnings()
+ assert_matches_type(SyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_earnings_with_all_params(self, client: Whop) -> None:
+ business = client.referrals.businesses.list_earnings(
+ after="after",
+ before="before",
+ first=100,
+ include="receipt_fees",
+ last=100,
+ order="asc",
+ sort="created_at",
+ status="awaiting_settlement",
+ )
+ assert_matches_type(SyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list_earnings(self, client: Whop) -> None:
+ response = client.referrals.businesses.with_raw_response.list_earnings()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ business = response.parse()
+ assert_matches_type(SyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list_earnings(self, client: Whop) -> None:
+ with client.referrals.businesses.with_streaming_response.list_earnings() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ business = response.parse()
+ assert_matches_type(SyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncBusinesses:
+ 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_retrieve(self, async_client: AsyncWhop) -> None:
+ business = await async_client.referrals.businesses.retrieve(
+ "id",
+ )
+ assert_matches_type(BusinessRetrieveResponse, business, 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.referrals.businesses.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ business = await response.parse()
+ assert_matches_type(BusinessRetrieveResponse, business, 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.referrals.businesses.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ business = await response.parse()
+ assert_matches_type(BusinessRetrieveResponse, business, 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.referrals.businesses.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncWhop) -> None:
+ business = await async_client.referrals.businesses.list()
+ assert_matches_type(AsyncCursorPage[BusinessListResponse], business, 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:
+ business = await async_client.referrals.businesses.list(
+ after="after",
+ before="before",
+ first=100,
+ has_earnings=True,
+ last=100,
+ status="active",
+ )
+ assert_matches_type(AsyncCursorPage[BusinessListResponse], business, 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.referrals.businesses.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ business = await response.parse()
+ assert_matches_type(AsyncCursorPage[BusinessListResponse], business, 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.referrals.businesses.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ business = await response.parse()
+ assert_matches_type(AsyncCursorPage[BusinessListResponse], business, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_earnings(self, async_client: AsyncWhop) -> None:
+ business = await async_client.referrals.businesses.list_earnings()
+ assert_matches_type(AsyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list_earnings_with_all_params(self, async_client: AsyncWhop) -> None:
+ business = await async_client.referrals.businesses.list_earnings(
+ after="after",
+ before="before",
+ first=100,
+ include="receipt_fees",
+ last=100,
+ order="asc",
+ sort="created_at",
+ status="awaiting_settlement",
+ )
+ assert_matches_type(AsyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_list_earnings(self, async_client: AsyncWhop) -> None:
+ response = await async_client.referrals.businesses.with_raw_response.list_earnings()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ business = await response.parse()
+ assert_matches_type(AsyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_list_earnings(self, async_client: AsyncWhop) -> None:
+ async with async_client.referrals.businesses.with_streaming_response.list_earnings() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ business = await response.parse()
+ assert_matches_type(AsyncCursorPage[BusinessListEarningsResponse], business, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_accounts.py b/tests/api_resources/test_accounts.py
index 11810569..d57ce2c0 100644
--- a/tests/api_resources/test_accounts.py
+++ b/tests/api_resources/test_accounts.py
@@ -9,10 +9,8 @@
from whop_sdk import Whop, AsyncWhop
from tests.utils import assert_matches_type
-from whop_sdk.types import (
- Account,
- AccountListResponse,
-)
+from whop_sdk.types import Account
+from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -116,17 +114,31 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
affiliate_instructions="affiliate_instructions",
banner_image={"foo": "bar"},
business_type="business_type",
+ country="country",
description="description",
featured_affiliate_product_id="featured_affiliate_product_id",
+ home_preferences=["string"],
industry_group="industry_group",
industry_type="industry_type",
+ invoice_prefix="invoice_prefix",
logo={"foo": "bar"},
metadata={"foo": "bar"},
+ onboarding_type="onboarding_type",
+ opengraph_image={"foo": "bar"},
+ opengraph_image_variant="opengraph_image_variant",
+ other_business_description="other_business_description",
+ other_industry_description="other_industry_description",
+ require_2fa=True,
route="route",
send_customer_emails=True,
+ show_joined_whops=True,
+ show_reviews_dtc=True,
+ show_user_directory=True,
social_links=[{"foo": "bar"}],
+ store_page_config={"foo": "bar"},
target_audience="target_audience",
title="title",
+ use_logo_as_opengraph_image_fallback=True,
)
assert_matches_type(Account, account, path=["response"])
@@ -168,16 +180,18 @@ def test_path_params_update(self, client: Whop) -> None:
@parametrize
def test_method_list(self, client: Whop) -> None:
account = client.accounts.list()
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(SyncCursorPage[Account], account, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_list_with_all_params(self, client: Whop) -> None:
account = client.accounts.list(
- page=0,
- per=0,
+ after="after",
+ before="before",
+ first=0,
+ last=0,
)
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(SyncCursorPage[Account], account, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -187,7 +201,7 @@ def test_raw_response_list(self, client: Whop) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
account = response.parse()
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(SyncCursorPage[Account], account, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -197,7 +211,7 @@ def test_streaming_response_list(self, client: Whop) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
account = response.parse()
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(SyncCursorPage[Account], account, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -331,17 +345,31 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
affiliate_instructions="affiliate_instructions",
banner_image={"foo": "bar"},
business_type="business_type",
+ country="country",
description="description",
featured_affiliate_product_id="featured_affiliate_product_id",
+ home_preferences=["string"],
industry_group="industry_group",
industry_type="industry_type",
+ invoice_prefix="invoice_prefix",
logo={"foo": "bar"},
metadata={"foo": "bar"},
+ onboarding_type="onboarding_type",
+ opengraph_image={"foo": "bar"},
+ opengraph_image_variant="opengraph_image_variant",
+ other_business_description="other_business_description",
+ other_industry_description="other_industry_description",
+ require_2fa=True,
route="route",
send_customer_emails=True,
+ show_joined_whops=True,
+ show_reviews_dtc=True,
+ show_user_directory=True,
social_links=[{"foo": "bar"}],
+ store_page_config={"foo": "bar"},
target_audience="target_audience",
title="title",
+ use_logo_as_opengraph_image_fallback=True,
)
assert_matches_type(Account, account, path=["response"])
@@ -383,16 +411,18 @@ async def test_path_params_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncWhop) -> None:
account = await async_client.accounts.list()
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(AsyncCursorPage[Account], account, 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:
account = await async_client.accounts.list(
- page=0,
- per=0,
+ after="after",
+ before="before",
+ first=0,
+ last=0,
)
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(AsyncCursorPage[Account], account, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -402,7 +432,7 @@ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
account = await response.parse()
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(AsyncCursorPage[Account], account, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -412,7 +442,7 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
account = await response.parse()
- assert_matches_type(AccountListResponse, account, path=["response"])
+ assert_matches_type(AsyncCursorPage[Account], account, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_ad_campaigns.py b/tests/api_resources/test_ad_campaigns.py
index 4c818bf8..7a23db43 100644
--- a/tests/api_resources/test_ad_campaigns.py
+++ b/tests/api_resources/test_ad_campaigns.py
@@ -26,7 +26,17 @@ class TestAdCampaigns:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
ad_campaign = client.ad_campaigns.retrieve(
- "adcamp_xxxxxxxxxxx",
+ id="adcamp_xxxxxxxxxxx",
+ )
+ assert_matches_type(AdCampaign, ad_campaign, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Whop) -> None:
+ ad_campaign = client.ad_campaigns.retrieve(
+ id="adcamp_xxxxxxxxxxx",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
)
assert_matches_type(AdCampaign, ad_campaign, path=["response"])
@@ -34,7 +44,7 @@ def test_method_retrieve(self, client: Whop) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.ad_campaigns.with_raw_response.retrieve(
- "adcamp_xxxxxxxxxxx",
+ id="adcamp_xxxxxxxxxxx",
)
assert response.is_closed is True
@@ -46,7 +56,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.ad_campaigns.with_streaming_response.retrieve(
- "adcamp_xxxxxxxxxxx",
+ id="adcamp_xxxxxxxxxxx",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -61,7 +71,7 @@ def test_streaming_response_retrieve(self, client: Whop) -> None:
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.ad_campaigns.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -78,6 +88,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
ad_campaign = client.ad_campaigns.update(
id="adcamp_xxxxxxxxxxx",
budget=6.9,
+ desired_cpr=6.9,
)
assert_matches_type(AdCampaign, ad_campaign, path=["response"])
@@ -130,9 +141,13 @@ def test_method_list_with_all_params(self, client: Whop) -> None:
company_id="biz_xxxxxxxxxxxxxx",
created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ direction="asc",
first=42,
last=42,
+ order="created_at",
query="query",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
status="active",
)
assert_matches_type(SyncCursorPage[AdCampaignListResponse], ad_campaign, path=["response"])
@@ -253,7 +268,17 @@ class TestAsyncAdCampaigns:
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
ad_campaign = await async_client.ad_campaigns.retrieve(
- "adcamp_xxxxxxxxxxx",
+ id="adcamp_xxxxxxxxxxx",
+ )
+ assert_matches_type(AdCampaign, ad_campaign, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) -> None:
+ ad_campaign = await async_client.ad_campaigns.retrieve(
+ id="adcamp_xxxxxxxxxxx",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
)
assert_matches_type(AdCampaign, ad_campaign, path=["response"])
@@ -261,7 +286,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
response = await async_client.ad_campaigns.with_raw_response.retrieve(
- "adcamp_xxxxxxxxxxx",
+ id="adcamp_xxxxxxxxxxx",
)
assert response.is_closed is True
@@ -273,7 +298,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
async with async_client.ad_campaigns.with_streaming_response.retrieve(
- "adcamp_xxxxxxxxxxx",
+ id="adcamp_xxxxxxxxxxx",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -288,7 +313,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> Non
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.ad_campaigns.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -305,6 +330,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
ad_campaign = await async_client.ad_campaigns.update(
id="adcamp_xxxxxxxxxxx",
budget=6.9,
+ desired_cpr=6.9,
)
assert_matches_type(AdCampaign, ad_campaign, path=["response"])
@@ -357,9 +383,13 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non
company_id="biz_xxxxxxxxxxxxxx",
created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ direction="asc",
first=42,
last=42,
+ order="created_at",
query="query",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
status="active",
)
assert_matches_type(AsyncCursorPage[AdCampaignListResponse], ad_campaign, path=["response"])
diff --git a/tests/api_resources/test_ad_groups.py b/tests/api_resources/test_ad_groups.py
index ebbda82c..275e8edf 100644
--- a/tests/api_resources/test_ad_groups.py
+++ b/tests/api_resources/test_ad_groups.py
@@ -27,7 +27,17 @@ class TestAdGroups:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
ad_group = client.ad_groups.retrieve(
- "adgrp_xxxxxxxxxxxx",
+ id="adgrp_xxxxxxxxxxxx",
+ )
+ assert_matches_type(AdGroup, ad_group, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Whop) -> None:
+ ad_group = client.ad_groups.retrieve(
+ id="adgrp_xxxxxxxxxxxx",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
)
assert_matches_type(AdGroup, ad_group, path=["response"])
@@ -35,7 +45,7 @@ def test_method_retrieve(self, client: Whop) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.ad_groups.with_raw_response.retrieve(
- "adgrp_xxxxxxxxxxxx",
+ id="adgrp_xxxxxxxxxxxx",
)
assert response.is_closed is True
@@ -47,7 +57,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.ad_groups.with_streaming_response.retrieve(
- "adgrp_xxxxxxxxxxxx",
+ id="adgrp_xxxxxxxxxxxx",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -62,7 +72,7 @@ def test_streaming_response_retrieve(self, client: Whop) -> None:
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.ad_groups.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -79,346 +89,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
ad_group = client.ad_groups.update(
id="adgrp_xxxxxxxxxxxx",
budget=6.9,
- budget_type="daily",
- config={
- "bid_amount": 42,
- "bid_strategy": "lowest_cost",
- "billing_event": "impressions",
- "end_time": "end_time",
- "frequency_cap": 42,
- "frequency_cap_interval_days": 42,
- "optimization_goal": "conversions",
- "pacing": "standard",
- "start_time": "start_time",
- "targeting": {
- "age_max": 42,
- "age_min": 42,
- "countries": ["string"],
- "device_platforms": ["mobile"],
- "exclude_audience_ids": ["string"],
- "genders": ["male"],
- "include_audience_ids": ["string"],
- "interest_ids": ["string"],
- "languages": ["string"],
- "placement_type": "automatic",
- },
- },
- daily_budget=6.9,
- name="name",
- platform_config={
- "meta": {
- "android_devices": ["string"],
- "attribution_setting": "attribution_setting",
- "attribution_spec": [
- {
- "event_type": "event_type",
- "window_days": 42,
- }
- ],
- "audience_network_positions": ["string"],
- "audience_type": "audience_type",
- "bid_amount": 42,
- "bid_strategy": "LOWEST_COST_WITHOUT_CAP",
- "billing_event": "APP_INSTALLS",
- "brand_safety_content_filter_levels": ["string"],
- "budget_remaining": "budget_remaining",
- "cost_per_result_goal": 6.9,
- "created_time": "created_time",
- "daily_budget": 42,
- "daily_min_spend_target": "daily_min_spend_target",
- "daily_spend_cap": "daily_spend_cap",
- "destination_type": "UNDEFINED",
- "dsa_beneficiary": "dsa_beneficiary",
- "dsa_payor": "dsa_payor",
- "end_time": "end_time",
- "excluded_geo_locations": {
- "cities": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "countries": ["string"],
- "location_types": ["string"],
- "regions": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "zips": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- },
- "facebook_positions": ["string"],
- "frequency_control_count": 42,
- "frequency_control_days": 42,
- "frequency_control_type": "frequency_control_type",
- "geo_cities": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "geo_locations": {
- "cities": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "countries": ["string"],
- "location_types": ["string"],
- "regions": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "zips": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- },
- "geo_regions": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "geo_zips": ["string"],
- "instagram_actor_id": "instagram_actor_id",
- "instagram_positions": ["string"],
- "ios_devices": ["string"],
- "is_dynamic_creative": True,
- "lead_conversion_location": "website",
- "lead_form_config": {
- "name": "name",
- "privacy_policy_url": "privacy_policy_url",
- "questions": [
- {
- "type": "type",
- "conditional_questions_group_id": "conditional_questions_group_id",
- "dependent_conditional_questions": [
- {
- "type": "type",
- "inline_context": "inline_context",
- "key": "key",
- "label": "label",
- "options": [
- {
- "key": "key",
- "value": "value",
- "logic": {
- "type": "type",
- "target_end_page_index": 42,
- "target_question_index": 42,
- },
- }
- ],
- }
- ],
- "inline_context": "inline_context",
- "key": "key",
- "label": "label",
- "options": [
- {
- "key": "key",
- "value": "value",
- "logic": {
- "type": "type",
- "target_end_page_index": 42,
- "target_question_index": 42,
- },
- }
- ],
- "question_format": "question_format",
- }
- ],
- "background_image_source": "background_image_source",
- "background_image_url": "background_image_url",
- "conditional_logic_enabled": True,
- "context_card_button_text": "context_card_button_text",
- "context_card_content": ["string"],
- "context_card_style": "context_card_style",
- "context_card_title": "context_card_title",
- "custom_disclaimer_body": "custom_disclaimer_body",
- "custom_disclaimer_checkboxes": [
- {
- "key": "key",
- "text": "text",
- "is_checked_by_default": True,
- "is_required": True,
- }
- ],
- "custom_disclaimer_title": "custom_disclaimer_title",
- "form_type": "form_type",
- "messenger_enabled": True,
- "phone_verification_enabled": True,
- "privacy_policy_link_text": "privacy_policy_link_text",
- "question_page_custom_headline": "question_page_custom_headline",
- "rich_creative_headline": "rich_creative_headline",
- "rich_creative_overview": "rich_creative_overview",
- "rich_creative_url": "rich_creative_url",
- "thank_you_pages": [
- {
- "body": "body",
- "business_phone": "business_phone",
- "button_text": "button_text",
- "button_type": "button_type",
- "conditional_question_group_id": "conditional_question_group_id",
- "enable_messenger": True,
- "gated_file_url": "gated_file_url",
- "link": "link",
- "name": "name",
- "title": "title",
- }
- ],
- },
- "lead_gen_form_id": "lead_gen_form_id",
- "lifetime_budget": 42,
- "lifetime_min_spend_target": "lifetime_min_spend_target",
- "lifetime_spend_cap": "lifetime_spend_cap",
- "location_types": ["string"],
- "messenger_positions": ["string"],
- "optimization_goal": "NONE",
- "page_id": "page_id",
- "pixel_id": "pixel_id",
- "promoted_object": {
- "custom_conversion_id": "custom_conversion_id",
- "custom_event_str": "custom_event_str",
- "custom_event_type": "custom_event_type",
- "page_id": "page_id",
- "pixel_id": "pixel_id",
- "whatsapp_phone_number": "whatsapp_phone_number",
- },
- "publisher_platforms": ["string"],
- "source_adset_id": "source_adset_id",
- "start_time": "start_time",
- "status": "ACTIVE",
- "targeting_automation": {"advantage_audience": 42},
- "threads_positions": ["string"],
- "updated_time": "updated_time",
- "user_device": ["string"],
- "user_os": ["string"],
- "whatsapp_phone_number": "whatsapp_phone_number",
- "whatsapp_positions": ["string"],
- },
- "tiktok": {
- "actions": [
- {
- "action_category_ids": ["string"],
- "action_period": 42,
- "action_scene": "VIDEO_RELATED",
- "video_user_actions": ["WATCHED_TO_END"],
- }
- ],
- "age_groups": ["AGE_13_17"],
- "app_id": "app_xxxxxxxxxxxxxx",
- "attribution_event_count": "UNSET",
- "audience_ids": ["string"],
- "audience_rule": {"foo": "bar"},
- "audience_type": "NORMAL",
- "bid_price": 6.9,
- "bid_type": "BID_TYPE_NO_BID",
- "billing_event": "CPC",
- "brand_safety_type": "NO_BRAND_SAFETY",
- "budget_mode": "BUDGET_MODE_DAY",
- "carrier_ids": ["string"],
- "category_exclusion_ids": ["string"],
- "click_attribution_window": "OFF",
- "comment_disabled": True,
- "contextual_tag_ids": ["string"],
- "conversion_bid_price": 6.9,
- "creative_material_mode": "creative_material_mode",
- "dayparting": "dayparting",
- "deep_funnel_event_source": "deep_funnel_event_source",
- "deep_funnel_event_source_id": "deep_funnel_event_source_id",
- "deep_funnel_optimization_status": "ON",
- "device_model_ids": ["string"],
- "device_price_ranges": ["string"],
- "engaged_view_attribution_window": "OFF",
- "excluded_audience_ids": ["string"],
- "excluded_location_ids": ["string"],
- "frequency": 42,
- "frequency_schedule": 42,
- "gender": "GENDER_UNLIMITED",
- "identity_authorized_bc_id": "identity_authorized_bc_id",
- "identity_id": "identity_id",
- "identity_type": "identity_type",
- "instant_form_config": {
- "privacy_policy_url": "privacy_policy_url",
- "questions": [
- {
- "field_type": "field_type",
- "label": "label",
- }
- ],
- "button_text": "button_text",
- "greeting": "greeting",
- "name": "name",
- },
- "instant_form_id": "instant_form_id",
- "interest_category_ids": ["string"],
- "interest_keyword_ids": ["string"],
- "inventory_filter_enabled": True,
- "ios14_targeting": "UNSET",
- "isp_ids": ["string"],
- "languages": ["string"],
- "location_ids": ["string"],
- "min_android_version": "min_android_version",
- "min_ios_version": "min_ios_version",
- "network_types": ["string"],
- "operating_systems": ["ANDROID"],
- "operation_status": "ENABLE",
- "optimization_event": "optimization_event",
- "optimization_goal": "CLICK",
- "pacing": "PACING_MODE_SMOOTH",
- "pangle_audience_package_exclude_ids": ["string"],
- "pangle_audience_package_include_ids": ["string"],
- "pangle_block_app_ids": ["string"],
- "pixel_id": "pixel_id",
- "placement_type": "PLACEMENT_TYPE_AUTOMATIC",
- "placements": ["string"],
- "product_set_id": "product_set_id",
- "product_source": "CATALOG",
- "promotion_type": "promotion_type",
- "schedule_end_time": "schedule_end_time",
- "schedule_start_time": "schedule_start_time",
- "schedule_type": "SCHEDULE_START_END",
- "secondary_optimization_event": "secondary_optimization_event",
- "shopping_ads_retargeting_actions_days": 42,
- "shopping_ads_retargeting_type": "OFF",
- "spending_power": "ALL",
- "tiktok_subplacements": ["string"],
- "vertical_sensitivity_id": "vertical_sensitivity_id",
- "video_download_disabled": True,
- "video_user_actions": ["string"],
- "view_attribution_window": "OFF",
- },
- },
- status="active",
+ title="title",
)
assert_matches_type(AdGroup, ad_group, path=["response"])
@@ -466,16 +137,21 @@ def test_method_list(self, client: Whop) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Whop) -> None:
ad_group = client.ad_groups.list(
+ ad_campaign_id="ad_campaign_id",
+ ad_campaign_ids=["string"],
after="after",
before="before",
campaign_id="campaign_id",
company_id="biz_xxxxxxxxxxxxxx",
created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ direction="asc",
first=42,
- include_paused=True,
last=42,
+ order="created_at",
query="query",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
status="active",
)
assert_matches_type(SyncCursorPage[AdGroupListResponse], ad_group, path=["response"])
@@ -638,7 +314,17 @@ class TestAsyncAdGroups:
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
ad_group = await async_client.ad_groups.retrieve(
- "adgrp_xxxxxxxxxxxx",
+ id="adgrp_xxxxxxxxxxxx",
+ )
+ assert_matches_type(AdGroup, ad_group, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) -> None:
+ ad_group = await async_client.ad_groups.retrieve(
+ id="adgrp_xxxxxxxxxxxx",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
)
assert_matches_type(AdGroup, ad_group, path=["response"])
@@ -646,7 +332,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
response = await async_client.ad_groups.with_raw_response.retrieve(
- "adgrp_xxxxxxxxxxxx",
+ id="adgrp_xxxxxxxxxxxx",
)
assert response.is_closed is True
@@ -658,7 +344,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
async with async_client.ad_groups.with_streaming_response.retrieve(
- "adgrp_xxxxxxxxxxxx",
+ id="adgrp_xxxxxxxxxxxx",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -673,7 +359,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> Non
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.ad_groups.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -690,346 +376,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
ad_group = await async_client.ad_groups.update(
id="adgrp_xxxxxxxxxxxx",
budget=6.9,
- budget_type="daily",
- config={
- "bid_amount": 42,
- "bid_strategy": "lowest_cost",
- "billing_event": "impressions",
- "end_time": "end_time",
- "frequency_cap": 42,
- "frequency_cap_interval_days": 42,
- "optimization_goal": "conversions",
- "pacing": "standard",
- "start_time": "start_time",
- "targeting": {
- "age_max": 42,
- "age_min": 42,
- "countries": ["string"],
- "device_platforms": ["mobile"],
- "exclude_audience_ids": ["string"],
- "genders": ["male"],
- "include_audience_ids": ["string"],
- "interest_ids": ["string"],
- "languages": ["string"],
- "placement_type": "automatic",
- },
- },
- daily_budget=6.9,
- name="name",
- platform_config={
- "meta": {
- "android_devices": ["string"],
- "attribution_setting": "attribution_setting",
- "attribution_spec": [
- {
- "event_type": "event_type",
- "window_days": 42,
- }
- ],
- "audience_network_positions": ["string"],
- "audience_type": "audience_type",
- "bid_amount": 42,
- "bid_strategy": "LOWEST_COST_WITHOUT_CAP",
- "billing_event": "APP_INSTALLS",
- "brand_safety_content_filter_levels": ["string"],
- "budget_remaining": "budget_remaining",
- "cost_per_result_goal": 6.9,
- "created_time": "created_time",
- "daily_budget": 42,
- "daily_min_spend_target": "daily_min_spend_target",
- "daily_spend_cap": "daily_spend_cap",
- "destination_type": "UNDEFINED",
- "dsa_beneficiary": "dsa_beneficiary",
- "dsa_payor": "dsa_payor",
- "end_time": "end_time",
- "excluded_geo_locations": {
- "cities": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "countries": ["string"],
- "location_types": ["string"],
- "regions": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "zips": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- },
- "facebook_positions": ["string"],
- "frequency_control_count": 42,
- "frequency_control_days": 42,
- "frequency_control_type": "frequency_control_type",
- "geo_cities": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "geo_locations": {
- "cities": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "countries": ["string"],
- "location_types": ["string"],
- "regions": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "zips": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- },
- "geo_regions": [
- {
- "key": "key",
- "country": "country",
- "name": "name",
- "radius": 42,
- }
- ],
- "geo_zips": ["string"],
- "instagram_actor_id": "instagram_actor_id",
- "instagram_positions": ["string"],
- "ios_devices": ["string"],
- "is_dynamic_creative": True,
- "lead_conversion_location": "website",
- "lead_form_config": {
- "name": "name",
- "privacy_policy_url": "privacy_policy_url",
- "questions": [
- {
- "type": "type",
- "conditional_questions_group_id": "conditional_questions_group_id",
- "dependent_conditional_questions": [
- {
- "type": "type",
- "inline_context": "inline_context",
- "key": "key",
- "label": "label",
- "options": [
- {
- "key": "key",
- "value": "value",
- "logic": {
- "type": "type",
- "target_end_page_index": 42,
- "target_question_index": 42,
- },
- }
- ],
- }
- ],
- "inline_context": "inline_context",
- "key": "key",
- "label": "label",
- "options": [
- {
- "key": "key",
- "value": "value",
- "logic": {
- "type": "type",
- "target_end_page_index": 42,
- "target_question_index": 42,
- },
- }
- ],
- "question_format": "question_format",
- }
- ],
- "background_image_source": "background_image_source",
- "background_image_url": "background_image_url",
- "conditional_logic_enabled": True,
- "context_card_button_text": "context_card_button_text",
- "context_card_content": ["string"],
- "context_card_style": "context_card_style",
- "context_card_title": "context_card_title",
- "custom_disclaimer_body": "custom_disclaimer_body",
- "custom_disclaimer_checkboxes": [
- {
- "key": "key",
- "text": "text",
- "is_checked_by_default": True,
- "is_required": True,
- }
- ],
- "custom_disclaimer_title": "custom_disclaimer_title",
- "form_type": "form_type",
- "messenger_enabled": True,
- "phone_verification_enabled": True,
- "privacy_policy_link_text": "privacy_policy_link_text",
- "question_page_custom_headline": "question_page_custom_headline",
- "rich_creative_headline": "rich_creative_headline",
- "rich_creative_overview": "rich_creative_overview",
- "rich_creative_url": "rich_creative_url",
- "thank_you_pages": [
- {
- "body": "body",
- "business_phone": "business_phone",
- "button_text": "button_text",
- "button_type": "button_type",
- "conditional_question_group_id": "conditional_question_group_id",
- "enable_messenger": True,
- "gated_file_url": "gated_file_url",
- "link": "link",
- "name": "name",
- "title": "title",
- }
- ],
- },
- "lead_gen_form_id": "lead_gen_form_id",
- "lifetime_budget": 42,
- "lifetime_min_spend_target": "lifetime_min_spend_target",
- "lifetime_spend_cap": "lifetime_spend_cap",
- "location_types": ["string"],
- "messenger_positions": ["string"],
- "optimization_goal": "NONE",
- "page_id": "page_id",
- "pixel_id": "pixel_id",
- "promoted_object": {
- "custom_conversion_id": "custom_conversion_id",
- "custom_event_str": "custom_event_str",
- "custom_event_type": "custom_event_type",
- "page_id": "page_id",
- "pixel_id": "pixel_id",
- "whatsapp_phone_number": "whatsapp_phone_number",
- },
- "publisher_platforms": ["string"],
- "source_adset_id": "source_adset_id",
- "start_time": "start_time",
- "status": "ACTIVE",
- "targeting_automation": {"advantage_audience": 42},
- "threads_positions": ["string"],
- "updated_time": "updated_time",
- "user_device": ["string"],
- "user_os": ["string"],
- "whatsapp_phone_number": "whatsapp_phone_number",
- "whatsapp_positions": ["string"],
- },
- "tiktok": {
- "actions": [
- {
- "action_category_ids": ["string"],
- "action_period": 42,
- "action_scene": "VIDEO_RELATED",
- "video_user_actions": ["WATCHED_TO_END"],
- }
- ],
- "age_groups": ["AGE_13_17"],
- "app_id": "app_xxxxxxxxxxxxxx",
- "attribution_event_count": "UNSET",
- "audience_ids": ["string"],
- "audience_rule": {"foo": "bar"},
- "audience_type": "NORMAL",
- "bid_price": 6.9,
- "bid_type": "BID_TYPE_NO_BID",
- "billing_event": "CPC",
- "brand_safety_type": "NO_BRAND_SAFETY",
- "budget_mode": "BUDGET_MODE_DAY",
- "carrier_ids": ["string"],
- "category_exclusion_ids": ["string"],
- "click_attribution_window": "OFF",
- "comment_disabled": True,
- "contextual_tag_ids": ["string"],
- "conversion_bid_price": 6.9,
- "creative_material_mode": "creative_material_mode",
- "dayparting": "dayparting",
- "deep_funnel_event_source": "deep_funnel_event_source",
- "deep_funnel_event_source_id": "deep_funnel_event_source_id",
- "deep_funnel_optimization_status": "ON",
- "device_model_ids": ["string"],
- "device_price_ranges": ["string"],
- "engaged_view_attribution_window": "OFF",
- "excluded_audience_ids": ["string"],
- "excluded_location_ids": ["string"],
- "frequency": 42,
- "frequency_schedule": 42,
- "gender": "GENDER_UNLIMITED",
- "identity_authorized_bc_id": "identity_authorized_bc_id",
- "identity_id": "identity_id",
- "identity_type": "identity_type",
- "instant_form_config": {
- "privacy_policy_url": "privacy_policy_url",
- "questions": [
- {
- "field_type": "field_type",
- "label": "label",
- }
- ],
- "button_text": "button_text",
- "greeting": "greeting",
- "name": "name",
- },
- "instant_form_id": "instant_form_id",
- "interest_category_ids": ["string"],
- "interest_keyword_ids": ["string"],
- "inventory_filter_enabled": True,
- "ios14_targeting": "UNSET",
- "isp_ids": ["string"],
- "languages": ["string"],
- "location_ids": ["string"],
- "min_android_version": "min_android_version",
- "min_ios_version": "min_ios_version",
- "network_types": ["string"],
- "operating_systems": ["ANDROID"],
- "operation_status": "ENABLE",
- "optimization_event": "optimization_event",
- "optimization_goal": "CLICK",
- "pacing": "PACING_MODE_SMOOTH",
- "pangle_audience_package_exclude_ids": ["string"],
- "pangle_audience_package_include_ids": ["string"],
- "pangle_block_app_ids": ["string"],
- "pixel_id": "pixel_id",
- "placement_type": "PLACEMENT_TYPE_AUTOMATIC",
- "placements": ["string"],
- "product_set_id": "product_set_id",
- "product_source": "CATALOG",
- "promotion_type": "promotion_type",
- "schedule_end_time": "schedule_end_time",
- "schedule_start_time": "schedule_start_time",
- "schedule_type": "SCHEDULE_START_END",
- "secondary_optimization_event": "secondary_optimization_event",
- "shopping_ads_retargeting_actions_days": 42,
- "shopping_ads_retargeting_type": "OFF",
- "spending_power": "ALL",
- "tiktok_subplacements": ["string"],
- "vertical_sensitivity_id": "vertical_sensitivity_id",
- "video_download_disabled": True,
- "video_user_actions": ["string"],
- "view_attribution_window": "OFF",
- },
- },
- status="active",
+ title="title",
)
assert_matches_type(AdGroup, ad_group, path=["response"])
@@ -1077,16 +424,21 @@ async def test_method_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
ad_group = await async_client.ad_groups.list(
+ ad_campaign_id="ad_campaign_id",
+ ad_campaign_ids=["string"],
after="after",
before="before",
campaign_id="campaign_id",
company_id="biz_xxxxxxxxxxxxxx",
created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ direction="asc",
first=42,
- include_paused=True,
last=42,
+ order="created_at",
query="query",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
status="active",
)
assert_matches_type(AsyncCursorPage[AdGroupListResponse], ad_group, path=["response"])
diff --git a/tests/api_resources/test_ad_reports.py b/tests/api_resources/test_ad_reports.py
index a5b76624..861f56da 100644
--- a/tests/api_resources/test_ad_reports.py
+++ b/tests/api_resources/test_ad_reports.py
@@ -33,13 +33,13 @@ def test_method_retrieve_with_all_params(self, client: Whop) -> None:
ad_report = client.ad_reports.retrieve(
from_=parse_datetime("2023-12-01T05:00:00.401Z"),
to=parse_datetime("2023-12-01T05:00:00.401Z"),
- ad_campaign_id="ad_campaign_id",
- ad_group_id="ad_group_id",
- ad_id="ad_id",
+ ad_campaign_ids=["string"],
+ ad_group_ids=["string"],
+ ad_ids=["string"],
breakdown="campaign",
company_id="biz_xxxxxxxxxxxxxx",
currency="currency",
- granularity="daily",
+ granularity="hourly",
)
assert_matches_type(AdReportRetrieveResponse, ad_report, path=["response"])
@@ -92,13 +92,13 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) ->
ad_report = await async_client.ad_reports.retrieve(
from_=parse_datetime("2023-12-01T05:00:00.401Z"),
to=parse_datetime("2023-12-01T05:00:00.401Z"),
- ad_campaign_id="ad_campaign_id",
- ad_group_id="ad_group_id",
- ad_id="ad_id",
+ ad_campaign_ids=["string"],
+ ad_group_ids=["string"],
+ ad_ids=["string"],
breakdown="campaign",
company_id="biz_xxxxxxxxxxxxxx",
currency="currency",
- granularity="daily",
+ granularity="hourly",
)
assert_matches_type(AdReportRetrieveResponse, ad_report, path=["response"])
diff --git a/tests/api_resources/test_ads.py b/tests/api_resources/test_ads.py
index 0b0f229e..4fc25ed4 100644
--- a/tests/api_resources/test_ads.py
+++ b/tests/api_resources/test_ads.py
@@ -23,7 +23,17 @@ class TestAds:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
ad = client.ads.retrieve(
- "ad_xxxxxxxxxxxxxxx",
+ id="ad_xxxxxxxxxxxxxxx",
+ )
+ assert_matches_type(Ad, ad, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Whop) -> None:
+ ad = client.ads.retrieve(
+ id="ad_xxxxxxxxxxxxxxx",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
)
assert_matches_type(Ad, ad, path=["response"])
@@ -31,7 +41,7 @@ def test_method_retrieve(self, client: Whop) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.ads.with_raw_response.retrieve(
- "ad_xxxxxxxxxxxxxxx",
+ id="ad_xxxxxxxxxxxxxxx",
)
assert response.is_closed is True
@@ -43,7 +53,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.ads.with_streaming_response.retrieve(
- "ad_xxxxxxxxxxxxxxx",
+ id="ad_xxxxxxxxxxxxxxx",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -58,7 +68,7 @@ def test_streaming_response_retrieve(self, client: Whop) -> None:
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.ads.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -71,16 +81,20 @@ def test_method_list(self, client: Whop) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Whop) -> None:
ad = client.ads.list(
+ ad_campaign_id="ad_campaign_id",
+ ad_campaign_ids=["string"],
ad_group_id="ad_group_id",
+ ad_group_ids=["string"],
after="after",
before="before",
campaign_id="campaign_id",
company_id="biz_xxxxxxxxxxxxxx",
created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ direction="asc",
first=42,
- include_paused=True,
last=42,
+ order="created_at",
order_by="spend",
order_direction="asc",
query="query",
@@ -206,7 +220,17 @@ class TestAsyncAds:
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
ad = await async_client.ads.retrieve(
- "ad_xxxxxxxxxxxxxxx",
+ id="ad_xxxxxxxxxxxxxxx",
+ )
+ assert_matches_type(Ad, ad, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) -> None:
+ ad = await async_client.ads.retrieve(
+ id="ad_xxxxxxxxxxxxxxx",
+ stats_from=parse_datetime("2023-12-01T05:00:00.401Z"),
+ stats_to=parse_datetime("2023-12-01T05:00:00.401Z"),
)
assert_matches_type(Ad, ad, path=["response"])
@@ -214,7 +238,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
response = await async_client.ads.with_raw_response.retrieve(
- "ad_xxxxxxxxxxxxxxx",
+ id="ad_xxxxxxxxxxxxxxx",
)
assert response.is_closed is True
@@ -226,7 +250,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
async with async_client.ads.with_streaming_response.retrieve(
- "ad_xxxxxxxxxxxxxxx",
+ id="ad_xxxxxxxxxxxxxxx",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -241,7 +265,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> Non
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.ads.with_raw_response.retrieve(
- "",
+ id="",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@@ -254,16 +278,20 @@ async def test_method_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
ad = await async_client.ads.list(
+ ad_campaign_id="ad_campaign_id",
+ ad_campaign_ids=["string"],
ad_group_id="ad_group_id",
+ ad_group_ids=["string"],
after="after",
before="before",
campaign_id="campaign_id",
company_id="biz_xxxxxxxxxxxxxx",
created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ direction="asc",
first=42,
- include_paused=True,
last=42,
+ order="created_at",
order_by="spend",
order_direction="asc",
query="query",
diff --git a/tests/api_resources/test_authorized_users.py b/tests/api_resources/test_authorized_users.py
index 007f3d47..95bb59b6 100644
--- a/tests/api_resources/test_authorized_users.py
+++ b/tests/api_resources/test_authorized_users.py
@@ -40,6 +40,14 @@ def test_method_create_with_all_params(self, client: Whop) -> None:
company_id="biz_xxxxxxxxxxxxxx",
role="owner",
user_id="user_xxxxxxxxxxxxx",
+ elevation={
+ "authenticator_data": "authenticator_data",
+ "client_data_json": "client_data_json",
+ "credential_id": "credential_id",
+ "signature": "signature",
+ "totp_code": "totp_code",
+ "use_finance_session": True,
+ },
send_emails=True,
)
assert_matches_type(AuthorizedUser, authorized_user, path=["response"])
@@ -234,6 +242,14 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N
company_id="biz_xxxxxxxxxxxxxx",
role="owner",
user_id="user_xxxxxxxxxxxxx",
+ elevation={
+ "authenticator_data": "authenticator_data",
+ "client_data_json": "client_data_json",
+ "credential_id": "credential_id",
+ "signature": "signature",
+ "totp_code": "totp_code",
+ "use_finance_session": True,
+ },
send_emails=True,
)
assert_matches_type(AuthorizedUser, authorized_user, path=["response"])
diff --git a/tests/api_resources/test_bounties.py b/tests/api_resources/test_bounties.py
index d76ec837..99ac9142 100644
--- a/tests/api_resources/test_bounties.py
+++ b/tests/api_resources/test_bounties.py
@@ -14,6 +14,7 @@
BountyCreateResponse,
BountyRetrieveResponse,
)
+from whop_sdk._utils import parse_datetime
from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -43,10 +44,14 @@ def test_method_create_with_all_params(self, client: Whop) -> None:
title="title",
accepted_submissions_limit=42,
allowed_country_codes=["string"],
+ business_goal_type="clipping",
experience_id="exp_xxxxxxxxxxxxxx",
origin_account_id="origin_account_id",
post_markdown_content="post_markdown_content",
post_title="post_title",
+ scheduled_frequency="once",
+ scheduled_publish_at=parse_datetime("2023-12-01T05:00:00.401Z"),
+ scheduled_timezone="scheduled_timezone",
)
assert_matches_type(BountyCreateResponse, bounty, path=["response"])
@@ -193,10 +198,14 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N
title="title",
accepted_submissions_limit=42,
allowed_country_codes=["string"],
+ business_goal_type="clipping",
experience_id="exp_xxxxxxxxxxxxxx",
origin_account_id="origin_account_id",
post_markdown_content="post_markdown_content",
post_title="post_title",
+ scheduled_frequency="once",
+ scheduled_publish_at=parse_datetime("2023-12-01T05:00:00.401Z"),
+ scheduled_timezone="scheduled_timezone",
)
assert_matches_type(BountyCreateResponse, bounty, path=["response"])
diff --git a/tests/api_resources/test_cards.py b/tests/api_resources/test_cards.py
new file mode 100644
index 00000000..f56dc4c6
--- /dev/null
+++ b/tests/api_resources/test_cards.py
@@ -0,0 +1,288 @@
+# 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 (
+ CardListResponse,
+ CardCreateResponse,
+ CardRetrieveResponse,
+)
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestCards:
+ 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:
+ card = client.cards.create()
+ assert_matches_type(CardCreateResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Whop) -> None:
+ card = client.cards.create(
+ account_id="account_id",
+ name="name",
+ spend_limit=0,
+ spend_limit_frequency="daily",
+ transaction_limit=0,
+ user_id="user_id",
+ )
+ assert_matches_type(CardCreateResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Whop) -> None:
+ response = client.cards.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ card = response.parse()
+ assert_matches_type(CardCreateResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Whop) -> None:
+ with client.cards.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ card = response.parse()
+ assert_matches_type(CardCreateResponse, card, 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:
+ card = client.cards.retrieve(
+ card_id="card_id",
+ )
+ assert_matches_type(CardRetrieveResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve_with_all_params(self, client: Whop) -> None:
+ card = client.cards.retrieve(
+ card_id="card_id",
+ account_id="account_id",
+ user_id="user_id",
+ )
+ assert_matches_type(CardRetrieveResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Whop) -> None:
+ response = client.cards.with_raw_response.retrieve(
+ card_id="card_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ card = response.parse()
+ assert_matches_type(CardRetrieveResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Whop) -> None:
+ with client.cards.with_streaming_response.retrieve(
+ card_id="card_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ card = response.parse()
+ assert_matches_type(CardRetrieveResponse, card, 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 `card_id` but received ''"):
+ client.cards.with_raw_response.retrieve(
+ card_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Whop) -> None:
+ card = client.cards.list()
+ assert_matches_type(CardListResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Whop) -> None:
+ card = client.cards.list(
+ account_id="account_id",
+ user_id="user_id",
+ )
+ assert_matches_type(CardListResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.cards.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ card = response.parse()
+ assert_matches_type(CardListResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.cards.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ card = response.parse()
+ assert_matches_type(CardListResponse, card, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncCards:
+ 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:
+ card = await async_client.cards.create()
+ assert_matches_type(CardCreateResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
+ card = await async_client.cards.create(
+ account_id="account_id",
+ name="name",
+ spend_limit=0,
+ spend_limit_frequency="daily",
+ transaction_limit=0,
+ user_id="user_id",
+ )
+ assert_matches_type(CardCreateResponse, card, 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.cards.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ card = await response.parse()
+ assert_matches_type(CardCreateResponse, card, 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.cards.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ card = await response.parse()
+ assert_matches_type(CardCreateResponse, card, 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:
+ card = await async_client.cards.retrieve(
+ card_id="card_id",
+ )
+ assert_matches_type(CardRetrieveResponse, card, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) -> None:
+ card = await async_client.cards.retrieve(
+ card_id="card_id",
+ account_id="account_id",
+ user_id="user_id",
+ )
+ assert_matches_type(CardRetrieveResponse, card, 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.cards.with_raw_response.retrieve(
+ card_id="card_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ card = await response.parse()
+ assert_matches_type(CardRetrieveResponse, card, 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.cards.with_streaming_response.retrieve(
+ card_id="card_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ card = await response.parse()
+ assert_matches_type(CardRetrieveResponse, card, 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 `card_id` but received ''"):
+ await async_client.cards.with_raw_response.retrieve(
+ card_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncWhop) -> None:
+ card = await async_client.cards.list()
+ assert_matches_type(CardListResponse, card, 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:
+ card = await async_client.cards.list(
+ account_id="account_id",
+ user_id="user_id",
+ )
+ assert_matches_type(CardListResponse, card, 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.cards.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ card = await response.parse()
+ assert_matches_type(CardListResponse, card, 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.cards.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ card = await response.parse()
+ assert_matches_type(CardListResponse, card, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_checkout_configurations.py b/tests/api_resources/test_checkout_configurations.py
index 76ccdb32..acdcd76b 100644
--- a/tests/api_resources/test_checkout_configurations.py
+++ b/tests/api_resources/test_checkout_configurations.py
@@ -11,10 +11,10 @@
from tests.utils import assert_matches_type
from whop_sdk.types import (
CheckoutConfigurationListResponse,
+ CheckoutConfigurationCreateResponse,
+ CheckoutConfigurationRetrieveResponse,
)
-from whop_sdk._utils import parse_datetime
from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
-from whop_sdk.types.shared import CheckoutConfiguration
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -24,244 +24,74 @@ class TestCheckoutConfigurations:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- def test_method_create_overload_1(self, client: Whop) -> None:
- checkout_configuration = client.checkout_configurations.create(
- plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- },
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ def test_method_create(self, client: Whop) -> None:
+ checkout_configuration = client.checkout_configurations.create()
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, 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:
+ def test_method_create_with_all_params(self, client: Whop) -> None:
checkout_configuration = client.checkout_configurations.create(
+ affiliate_code="affiliate_code",
+ company_id="company_id",
+ currency="currency",
+ metadata={},
+ mode="payment",
+ payment_method_configuration={
+ "disabled": ["string"],
+ "enabled": ["string"],
+ "include_platform_defaults": True,
+ },
plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- "adaptive_pricing_enabled": True,
- "application_fee_amount": 6.9,
- "billing_period": 42,
- "custom_fields": [
- {
- "field_type": "text",
- "name": "name",
- "id": "id",
- "order": 42,
- "placeholder": "placeholder",
- "required": True,
- }
- ],
+ "billing_period": 0,
+ "company_id": "company_id",
+ "currency": "currency",
"description": "description",
- "expiration_days": 42,
+ "expiration_days": 0,
"force_create_new_plan": True,
- "image": {"id": "id"},
- "initial_price": 6.9,
- "internal_notes": "internal_notes",
- "override_tax_type": "inclusive",
+ "initial_price": 0,
+ "metadata": {},
+ "override_tax_type": "override_tax_type",
"payment_method_configuration": {
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
+ "disabled": ["string"],
+ "enabled": ["string"],
"include_platform_defaults": True,
},
- "plan_type": "renewal",
- "product": {
- "external_identifier": "external_identifier",
- "title": "title",
- "collect_shipping_address": True,
- "custom_statement_descriptor": "custom_statement_descriptor",
- "description": "description",
- "global_affiliate_percentage": 6.9,
- "global_affiliate_status": "enabled",
- "headline": "headline",
- "product_tax_code_id": "ptc_xxxxxxxxxxxxxx",
- "redirect_purchase_url": "redirect_purchase_url",
- "route": "route",
- "visibility": "visible",
- },
- "product_id": "prod_xxxxxxxxxxxxx",
- "release_method": "buy_now",
- "renewal_price": 6.9,
- "split_pay_required_payments": 42,
- "stock": 42,
+ "plan_type": "plan_type",
+ "product_id": "product_id",
+ "release_method": "release_method",
+ "renewal_price": 0,
+ "stock": 0,
"title": "title",
- "trial_period_days": 42,
- "visibility": "visible",
- },
- affiliate_code="affiliate_code",
- allow_promo_codes=True,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
- metadata={"foo": "bar"},
- mode="payment",
- payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
- "include_platform_defaults": True,
- },
- redirect_url="redirect_url",
- source_url="source_url",
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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.checkout_configurations.with_raw_response.create(
- plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- },
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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.checkout_configurations.with_streaming_response.create(
- plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- },
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_create_overload_2(self, client: Whop) -> None:
- checkout_configuration = client.checkout_configurations.create(
- plan_id="plan_xxxxxxxxxxxxx",
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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:
- checkout_configuration = client.checkout_configurations.create(
- plan_id="plan_xxxxxxxxxxxxx",
- affiliate_code="affiliate_code",
- allow_promo_codes=True,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
- metadata={"foo": "bar"},
- mode="payment",
- payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
- "include_platform_defaults": True,
- },
- redirect_url="redirect_url",
- source_url="source_url",
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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.checkout_configurations.with_raw_response.create(
- plan_id="plan_xxxxxxxxxxxxx",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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.checkout_configurations.with_streaming_response.create(
- plan_id="plan_xxxxxxxxxxxxx",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_create_overload_3(self, client: Whop) -> None:
- checkout_configuration = client.checkout_configurations.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_create_with_all_params_overload_3(self, client: Whop) -> None:
- checkout_configuration = client.checkout_configurations.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- allow_promo_codes=True,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
- metadata={"foo": "bar"},
- payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
- "include_platform_defaults": True,
+ "trial_period_days": 0,
+ "unlimited_stock": True,
+ "visibility": "visibility",
},
+ plan_id="plan_id",
redirect_url="redirect_url",
- source_url="source_url",
- three_ds_level="mandate_challenge",
+ three_ds_level="three_ds_level",
)
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- def test_raw_response_create_overload_3(self, client: Whop) -> None:
- response = client.checkout_configurations.with_raw_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- )
+ def test_raw_response_create(self, client: Whop) -> None:
+ response = client.checkout_configurations.with_raw_response.create()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- def test_streaming_response_create_overload_3(self, client: Whop) -> None:
- with client.checkout_configurations.with_streaming_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- ) as response:
+ def test_streaming_response_create(self, client: Whop) -> None:
+ with client.checkout_configurations.with_streaming_response.create() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -269,33 +99,33 @@ def test_streaming_response_create_overload_3(self, client: Whop) -> None:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
checkout_configuration = client.checkout_configurations.retrieve(
- "ch_xxxxxxxxxxxxxxx",
+ "id",
)
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationRetrieveResponse, checkout_configuration, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.checkout_configurations.with_raw_response.retrieve(
- "ch_xxxxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationRetrieveResponse, checkout_configuration, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.checkout_configurations.with_streaming_response.retrieve(
- "ch_xxxxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationRetrieveResponse, checkout_configuration, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -311,7 +141,7 @@ def test_path_params_retrieve(self, client: Whop) -> None:
@parametrize
def test_method_list(self, client: Whop) -> None:
checkout_configuration = client.checkout_configurations.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert_matches_type(
SyncCursorPage[CheckoutConfigurationListResponse], checkout_configuration, path=["response"]
@@ -321,15 +151,13 @@ def test_method_list(self, client: Whop) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Whop) -> None:
checkout_configuration = client.checkout_configurations.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
after="after",
- before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
- direction="asc",
- first=42,
- last=42,
- plan_id="plan_xxxxxxxxxxxxx",
+ created_after=0,
+ created_before=0,
+ direction="direction",
+ first=0,
+ plan_id="plan_id",
)
assert_matches_type(
SyncCursorPage[CheckoutConfigurationListResponse], checkout_configuration, path=["response"]
@@ -339,7 +167,7 @@ def test_method_list_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_list(self, client: Whop) -> None:
response = client.checkout_configurations.with_raw_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert response.is_closed is True
@@ -353,7 +181,7 @@ def test_raw_response_list(self, client: Whop) -> None:
@parametrize
def test_streaming_response_list(self, client: Whop) -> None:
with client.checkout_configurations.with_streaming_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -365,252 +193,124 @@ def test_streaming_response_list(self, client: Whop) -> None:
assert cast(Any, response.is_closed) is True
-
-class TestAsyncCheckoutConfigurations:
- 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:
- checkout_configuration = await async_client.checkout_configurations.create(
- plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- },
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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:
- checkout_configuration = await async_client.checkout_configurations.create(
- plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- "adaptive_pricing_enabled": True,
- "application_fee_amount": 6.9,
- "billing_period": 42,
- "custom_fields": [
- {
- "field_type": "text",
- "name": "name",
- "id": "id",
- "order": 42,
- "placeholder": "placeholder",
- "required": True,
- }
- ],
- "description": "description",
- "expiration_days": 42,
- "force_create_new_plan": True,
- "image": {"id": "id"},
- "initial_price": 6.9,
- "internal_notes": "internal_notes",
- "override_tax_type": "inclusive",
- "payment_method_configuration": {
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
- "include_platform_defaults": True,
- },
- "plan_type": "renewal",
- "product": {
- "external_identifier": "external_identifier",
- "title": "title",
- "collect_shipping_address": True,
- "custom_statement_descriptor": "custom_statement_descriptor",
- "description": "description",
- "global_affiliate_percentage": 6.9,
- "global_affiliate_status": "enabled",
- "headline": "headline",
- "product_tax_code_id": "ptc_xxxxxxxxxxxxxx",
- "redirect_purchase_url": "redirect_purchase_url",
- "route": "route",
- "visibility": "visible",
- },
- "product_id": "prod_xxxxxxxxxxxxx",
- "release_method": "buy_now",
- "renewal_price": 6.9,
- "split_pay_required_payments": 42,
- "stock": 42,
- "title": "title",
- "trial_period_days": 42,
- "visibility": "visible",
- },
- affiliate_code="affiliate_code",
- allow_promo_codes=True,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
- metadata={"foo": "bar"},
- mode="payment",
- payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
- "include_platform_defaults": True,
- },
- redirect_url="redirect_url",
- source_url="source_url",
+ def test_method_delete(self, client: Whop) -> None:
+ checkout_configuration = client.checkout_configurations.delete(
+ "id",
)
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert checkout_configuration is None
@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.checkout_configurations.with_raw_response.create(
- plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- },
+ def test_raw_response_delete(self, client: Whop) -> None:
+ response = client.checkout_configurations.with_raw_response.delete(
+ "id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ checkout_configuration = response.parse()
+ assert checkout_configuration is None
@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.checkout_configurations.with_streaming_response.create(
- plan={
- "company_id": "biz_xxxxxxxxxxxxxx",
- "currency": "usd",
- },
+ def test_streaming_response_delete(self, client: Whop) -> None:
+ with client.checkout_configurations.with_streaming_response.delete(
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ checkout_configuration = response.parse()
+ assert checkout_configuration is None
assert cast(Any, response.is_closed) is True
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- async def test_method_create_overload_2(self, async_client: AsyncWhop) -> None:
- checkout_configuration = await async_client.checkout_configurations.create(
- plan_id="plan_xxxxxxxxxxxxx",
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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:
- checkout_configuration = await async_client.checkout_configurations.create(
- plan_id="plan_xxxxxxxxxxxxx",
- affiliate_code="affiliate_code",
- allow_promo_codes=True,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
- metadata={"foo": "bar"},
- mode="payment",
- payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
- "include_platform_defaults": True,
- },
- redirect_url="redirect_url",
- source_url="source_url",
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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.checkout_configurations.with_raw_response.create(
- plan_id="plan_xxxxxxxxxxxxx",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, 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.checkout_configurations.with_streaming_response.create(
- plan_id="plan_xxxxxxxxxxxxx",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ 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.checkout_configurations.with_raw_response.delete(
+ "",
+ )
- checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
- assert cast(Any, response.is_closed) is True
+class TestAsyncCheckoutConfigurations:
+ 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_3(self, async_client: AsyncWhop) -> None:
- checkout_configuration = await async_client.checkout_configurations.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- )
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ async def test_method_create(self, async_client: AsyncWhop) -> None:
+ checkout_configuration = await async_client.checkout_configurations.create()
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- async def test_method_create_with_all_params_overload_3(self, async_client: AsyncWhop) -> None:
+ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
checkout_configuration = await async_client.checkout_configurations.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- allow_promo_codes=True,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
- metadata={"foo": "bar"},
+ affiliate_code="affiliate_code",
+ company_id="company_id",
+ currency="currency",
+ metadata={},
+ mode="payment",
payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
+ "disabled": ["string"],
+ "enabled": ["string"],
"include_platform_defaults": True,
},
+ plan={
+ "billing_period": 0,
+ "company_id": "company_id",
+ "currency": "currency",
+ "description": "description",
+ "expiration_days": 0,
+ "force_create_new_plan": True,
+ "initial_price": 0,
+ "metadata": {},
+ "override_tax_type": "override_tax_type",
+ "payment_method_configuration": {
+ "disabled": ["string"],
+ "enabled": ["string"],
+ "include_platform_defaults": True,
+ },
+ "plan_type": "plan_type",
+ "product_id": "product_id",
+ "release_method": "release_method",
+ "renewal_price": 0,
+ "stock": 0,
+ "title": "title",
+ "trial_period_days": 0,
+ "unlimited_stock": True,
+ "visibility": "visibility",
+ },
+ plan_id="plan_id",
redirect_url="redirect_url",
- source_url="source_url",
- three_ds_level="mandate_challenge",
+ three_ds_level="three_ds_level",
)
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- async def test_raw_response_create_overload_3(self, async_client: AsyncWhop) -> None:
- response = await async_client.checkout_configurations.with_raw_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- )
+ async def test_raw_response_create(self, async_client: AsyncWhop) -> None:
+ response = await async_client.checkout_configurations.with_raw_response.create()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- async def test_streaming_response_create_overload_3(self, async_client: AsyncWhop) -> None:
- async with async_client.checkout_configurations.with_streaming_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- mode="setup",
- ) as response:
+ async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
+ async with async_client.checkout_configurations.with_streaming_response.create() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationCreateResponse, checkout_configuration, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -618,33 +318,33 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncWho
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
checkout_configuration = await async_client.checkout_configurations.retrieve(
- "ch_xxxxxxxxxxxxxxx",
+ "id",
)
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationRetrieveResponse, checkout_configuration, 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.checkout_configurations.with_raw_response.retrieve(
- "ch_xxxxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationRetrieveResponse, checkout_configuration, 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.checkout_configurations.with_streaming_response.retrieve(
- "ch_xxxxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
checkout_configuration = await response.parse()
- assert_matches_type(CheckoutConfiguration, checkout_configuration, path=["response"])
+ assert_matches_type(CheckoutConfigurationRetrieveResponse, checkout_configuration, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -660,7 +360,7 @@ async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncWhop) -> None:
checkout_configuration = await async_client.checkout_configurations.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert_matches_type(
AsyncCursorPage[CheckoutConfigurationListResponse], checkout_configuration, path=["response"]
@@ -670,15 +370,13 @@ async def test_method_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
checkout_configuration = await async_client.checkout_configurations.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
after="after",
- before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
- direction="asc",
- first=42,
- last=42,
- plan_id="plan_xxxxxxxxxxxxx",
+ created_after=0,
+ created_before=0,
+ direction="direction",
+ first=0,
+ plan_id="plan_id",
)
assert_matches_type(
AsyncCursorPage[CheckoutConfigurationListResponse], checkout_configuration, path=["response"]
@@ -688,7 +386,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non
@parametrize
async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
response = await async_client.checkout_configurations.with_raw_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert response.is_closed is True
@@ -702,7 +400,7 @@ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
async with async_client.checkout_configurations.with_streaming_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -713,3 +411,45 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
)
assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncWhop) -> None:
+ checkout_configuration = await async_client.checkout_configurations.delete(
+ "id",
+ )
+ assert checkout_configuration is None
+
+ @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.checkout_configurations.with_raw_response.delete(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ checkout_configuration = await response.parse()
+ assert checkout_configuration is None
+
+ @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.checkout_configurations.with_streaming_response.delete(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ checkout_configuration = await response.parse()
+ assert checkout_configuration is None
+
+ 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.checkout_configurations.with_raw_response.delete(
+ "",
+ )
diff --git a/tests/api_resources/test_conversions.py b/tests/api_resources/test_conversions.py
index 3b63db11..e0903c3e 100644
--- a/tests/api_resources/test_conversions.py
+++ b/tests/api_resources/test_conversions.py
@@ -38,14 +38,26 @@ def test_method_create_with_all_params(self, client: Whop) -> None:
"ad_campaign_id": "ad_campaign_id",
"ad_id": "ad_id",
"ad_set_id": "ad_set_id",
+ "fbc": "fbc",
"fbclid": "fbclid",
"fbp": "fbp",
+ "fingerprint": "fingerprint",
+ "fingerprint_confidence": 6.9,
"ga": "ga",
+ "gbraid": "gbraid",
"gclid": "gclid",
"ig_sid": "ig_sid",
"ip_address": "ip_address",
+ "language": "language",
+ "li_fat_id": "li_fat_id",
+ "msclkid": "msclkid",
+ "rdt_cid": "rdt_cid",
+ "sccid": "sccid",
+ "screen_resolution": "screen_resolution",
+ "timezone": "timezone",
"ttclid": "ttclid",
"ttp": "ttp",
+ "twclid": "twclid",
"user_agent": "user_agent",
"utm_campaign": "utm_campaign",
"utm_content": "utm_content",
@@ -53,14 +65,19 @@ def test_method_create_with_all_params(self, client: Whop) -> None:
"utm_medium": "utm_medium",
"utm_source": "utm_source",
"utm_term": "utm_term",
+ "wbraid": "wbraid",
},
currency="usd",
custom_name="custom_name",
+ duration=42,
event_id="evnt_xxxxxxxxxxxxx",
event_time=parse_datetime("2023-12-01T05:00:00.401Z"),
plan_id="plan_xxxxxxxxxxxxx",
product_id="prod_xxxxxxxxxxxxx",
referrer_url="referrer_url",
+ resumed=True,
+ source="source",
+ title="title",
url="url",
user={
"anonymous_id": "anonymous_id",
@@ -72,6 +89,8 @@ def test_method_create_with_all_params(self, client: Whop) -> None:
"first_name": "first_name",
"gender": "male",
"last_name": "last_name",
+ "linked_anonymous_id": "linked_anonymous_id",
+ "linked_wuid": "linked_wuid",
"member_id": "mber_xxxxxxxxxxxxx",
"membership_id": "mem_xxxxxxxxxxxxxx",
"name": "name",
@@ -139,14 +158,26 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N
"ad_campaign_id": "ad_campaign_id",
"ad_id": "ad_id",
"ad_set_id": "ad_set_id",
+ "fbc": "fbc",
"fbclid": "fbclid",
"fbp": "fbp",
+ "fingerprint": "fingerprint",
+ "fingerprint_confidence": 6.9,
"ga": "ga",
+ "gbraid": "gbraid",
"gclid": "gclid",
"ig_sid": "ig_sid",
"ip_address": "ip_address",
+ "language": "language",
+ "li_fat_id": "li_fat_id",
+ "msclkid": "msclkid",
+ "rdt_cid": "rdt_cid",
+ "sccid": "sccid",
+ "screen_resolution": "screen_resolution",
+ "timezone": "timezone",
"ttclid": "ttclid",
"ttp": "ttp",
+ "twclid": "twclid",
"user_agent": "user_agent",
"utm_campaign": "utm_campaign",
"utm_content": "utm_content",
@@ -154,14 +185,19 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N
"utm_medium": "utm_medium",
"utm_source": "utm_source",
"utm_term": "utm_term",
+ "wbraid": "wbraid",
},
currency="usd",
custom_name="custom_name",
+ duration=42,
event_id="evnt_xxxxxxxxxxxxx",
event_time=parse_datetime("2023-12-01T05:00:00.401Z"),
plan_id="plan_xxxxxxxxxxxxx",
product_id="prod_xxxxxxxxxxxxx",
referrer_url="referrer_url",
+ resumed=True,
+ source="source",
+ title="title",
url="url",
user={
"anonymous_id": "anonymous_id",
@@ -173,6 +209,8 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N
"first_name": "first_name",
"gender": "male",
"last_name": "last_name",
+ "linked_anonymous_id": "linked_anonymous_id",
+ "linked_wuid": "linked_wuid",
"member_id": "mber_xxxxxxxxxxxxx",
"membership_id": "mem_xxxxxxxxxxxxxx",
"name": "name",
diff --git a/tests/api_resources/test_deposits.py b/tests/api_resources/test_deposits.py
index 7786dbc8..e26f749e 100644
--- a/tests/api_resources/test_deposits.py
+++ b/tests/api_resources/test_deposits.py
@@ -9,7 +9,7 @@
from whop_sdk import Whop, AsyncWhop
from tests.utils import assert_matches_type
-from whop_sdk.types import DepositCreateResponse
+from whop_sdk.types import DepositListResponse, DepositCreateResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -21,7 +21,6 @@ class TestDeposits:
@parametrize
def test_method_create(self, client: Whop) -> None:
deposit = client.deposits.create(
- amount=0,
destination="string",
)
assert_matches_type(DepositCreateResponse, deposit, path=["response"])
@@ -30,8 +29,8 @@ def test_method_create(self, client: Whop) -> None:
@parametrize
def test_method_create_with_all_params(self, client: Whop) -> None:
deposit = client.deposits.create(
- amount=0,
destination="string",
+ amount=0,
metadata={"foo": "bar"},
network="network",
)
@@ -41,7 +40,6 @@ def test_method_create_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_create(self, client: Whop) -> None:
response = client.deposits.with_raw_response.create(
- amount=0,
destination="string",
)
@@ -54,7 +52,6 @@ def test_raw_response_create(self, client: Whop) -> None:
@parametrize
def test_streaming_response_create(self, client: Whop) -> None:
with client.deposits.with_streaming_response.create(
- amount=0,
destination="string",
) as response:
assert not response.is_closed
@@ -65,6 +62,40 @@ def test_streaming_response_create(self, client: Whop) -> None:
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Whop) -> None:
+ deposit = client.deposits.list(
+ account_id="account_id",
+ )
+ assert_matches_type(DepositListResponse, deposit, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.deposits.with_raw_response.list(
+ account_id="account_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ deposit = response.parse()
+ assert_matches_type(DepositListResponse, deposit, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.deposits.with_streaming_response.list(
+ account_id="account_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ deposit = response.parse()
+ assert_matches_type(DepositListResponse, deposit, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncDeposits:
parametrize = pytest.mark.parametrize(
@@ -75,7 +106,6 @@ class TestAsyncDeposits:
@parametrize
async def test_method_create(self, async_client: AsyncWhop) -> None:
deposit = await async_client.deposits.create(
- amount=0,
destination="string",
)
assert_matches_type(DepositCreateResponse, deposit, path=["response"])
@@ -84,8 +114,8 @@ async def test_method_create(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
deposit = await async_client.deposits.create(
- amount=0,
destination="string",
+ amount=0,
metadata={"foo": "bar"},
network="network",
)
@@ -95,7 +125,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N
@parametrize
async def test_raw_response_create(self, async_client: AsyncWhop) -> None:
response = await async_client.deposits.with_raw_response.create(
- amount=0,
destination="string",
)
@@ -108,7 +137,6 @@ async def test_raw_response_create(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
async with async_client.deposits.with_streaming_response.create(
- amount=0,
destination="string",
) as response:
assert not response.is_closed
@@ -118,3 +146,37 @@ async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
assert_matches_type(DepositCreateResponse, deposit, path=["response"])
assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncWhop) -> None:
+ deposit = await async_client.deposits.list(
+ account_id="account_id",
+ )
+ assert_matches_type(DepositListResponse, deposit, 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.deposits.with_raw_response.list(
+ account_id="account_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ deposit = await response.parse()
+ assert_matches_type(DepositListResponse, deposit, 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.deposits.with_streaming_response.list(
+ account_id="account_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ deposit = await response.parse()
+ assert_matches_type(DepositListResponse, deposit, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_financial_activity.py b/tests/api_resources/test_financial_activity.py
new file mode 100644
index 00000000..985c2c85
--- /dev/null
+++ b/tests/api_resources/test_financial_activity.py
@@ -0,0 +1,115 @@
+# 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 FinancialActivityListResponse
+from whop_sdk._utils import parse_date, parse_datetime
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestFinancialActivity:
+ 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_list(self, client: Whop) -> None:
+ financial_activity = client.financial_activity.list()
+ assert_matches_type(FinancialActivityListResponse, financial_activity, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Whop) -> None:
+ financial_activity = client.financial_activity.list(
+ account_id="account_id",
+ available_after=parse_date("2019-12-27"),
+ available_before=parse_date("2019-12-27"),
+ currency="currency",
+ cursor="cursor",
+ limit=100,
+ line_types=["string"],
+ posted_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ posted_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ user_id="user_id",
+ )
+ assert_matches_type(FinancialActivityListResponse, financial_activity, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.financial_activity.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ financial_activity = response.parse()
+ assert_matches_type(FinancialActivityListResponse, financial_activity, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.financial_activity.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ financial_activity = response.parse()
+ assert_matches_type(FinancialActivityListResponse, financial_activity, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncFinancialActivity:
+ 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_list(self, async_client: AsyncWhop) -> None:
+ financial_activity = await async_client.financial_activity.list()
+ assert_matches_type(FinancialActivityListResponse, financial_activity, 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:
+ financial_activity = await async_client.financial_activity.list(
+ account_id="account_id",
+ available_after=parse_date("2019-12-27"),
+ available_before=parse_date("2019-12-27"),
+ currency="currency",
+ cursor="cursor",
+ limit=100,
+ line_types=["string"],
+ posted_after=parse_datetime("2019-12-27T18:11:19.117Z"),
+ posted_before=parse_datetime("2019-12-27T18:11:19.117Z"),
+ user_id="user_id",
+ )
+ assert_matches_type(FinancialActivityListResponse, financial_activity, 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.financial_activity.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ financial_activity = await response.parse()
+ assert_matches_type(FinancialActivityListResponse, financial_activity, 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.financial_activity.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ financial_activity = await response.parse()
+ assert_matches_type(FinancialActivityListResponse, financial_activity, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_invoices.py b/tests/api_resources/test_invoices.py
index 30be40a0..e4e13939 100644
--- a/tests/api_resources/test_invoices.py
+++ b/tests/api_resources/test_invoices.py
@@ -44,6 +44,7 @@ def test_method_create_with_all_params_overload_1(self, client: Whop) -> None:
company_id="biz_xxxxxxxxxxxxxx",
plan={
"billing_period": 42,
+ "currency": "usd",
"custom_fields": [
{
"field_type": "text",
@@ -160,6 +161,7 @@ def test_method_create_with_all_params_overload_2(self, client: Whop) -> None:
company_id="biz_xxxxxxxxxxxxxx",
plan={
"billing_period": 42,
+ "currency": "usd",
"custom_fields": [
{
"field_type": "text",
@@ -339,6 +341,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
payment_method_id="pmt_xxxxxxxxxxxxxx",
plan={
"billing_period": 42,
+ "currency": "usd",
"custom_fields": [
{
"field_type": "text",
@@ -646,6 +649,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn
company_id="biz_xxxxxxxxxxxxxx",
plan={
"billing_period": 42,
+ "currency": "usd",
"custom_fields": [
{
"field_type": "text",
@@ -762,6 +766,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn
company_id="biz_xxxxxxxxxxxxxx",
plan={
"billing_period": 42,
+ "currency": "usd",
"custom_fields": [
{
"field_type": "text",
@@ -941,6 +946,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
payment_method_id="pmt_xxxxxxxxxxxxxx",
plan={
"billing_period": 42,
+ "currency": "usd",
"custom_fields": [
{
"field_type": "text",
diff --git a/tests/api_resources/test_payouts.py b/tests/api_resources/test_payouts.py
new file mode 100644
index 00000000..df377533
--- /dev/null
+++ b/tests/api_resources/test_payouts.py
@@ -0,0 +1,109 @@
+# 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 PayoutListResponse
+from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestPayouts:
+ 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_list(self, client: Whop) -> None:
+ payout = client.payouts.list()
+ assert_matches_type(SyncCursorPage[PayoutListResponse], payout, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list_with_all_params(self, client: Whop) -> None:
+ payout = client.payouts.list(
+ account_id="account_id",
+ after="after",
+ before="before",
+ currency="currency",
+ first=100,
+ last=100,
+ user_id="user_id",
+ )
+ assert_matches_type(SyncCursorPage[PayoutListResponse], payout, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.payouts.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ payout = response.parse()
+ assert_matches_type(SyncCursorPage[PayoutListResponse], payout, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.payouts.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ payout = response.parse()
+ assert_matches_type(SyncCursorPage[PayoutListResponse], payout, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncPayouts:
+ 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_list(self, async_client: AsyncWhop) -> None:
+ payout = await async_client.payouts.list()
+ assert_matches_type(AsyncCursorPage[PayoutListResponse], payout, 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:
+ payout = await async_client.payouts.list(
+ account_id="account_id",
+ after="after",
+ before="before",
+ currency="currency",
+ first=100,
+ last=100,
+ user_id="user_id",
+ )
+ assert_matches_type(AsyncCursorPage[PayoutListResponse], payout, 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.payouts.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ payout = await response.parse()
+ assert_matches_type(AsyncCursorPage[PayoutListResponse], payout, 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.payouts.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ payout = await response.parse()
+ assert_matches_type(AsyncCursorPage[PayoutListResponse], payout, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_plans.py b/tests/api_resources/test_plans.py
index 1a92b368..32e2cec2 100644
--- a/tests/api_resources/test_plans.py
+++ b/tests/api_resources/test_plans.py
@@ -12,8 +12,8 @@
from whop_sdk.types import (
PlanListResponse,
PlanDeleteResponse,
+ PlanCalculateTaxResponse,
)
-from whop_sdk._utils import parse_datetime
from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
from whop_sdk.types.shared import Plan
@@ -26,70 +26,62 @@ class TestPlans:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_create(self, client: Whop) -> None:
- plan = client.plans.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
- )
+ plan = client.plans.create()
assert_matches_type(Plan, plan, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_create_with_all_params(self, client: Whop) -> None:
plan = client.plans.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
+ account_id="account_id",
adaptive_pricing_enabled=True,
- billing_period=42,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
+ billing_period=0,
+ checkout_styling={},
+ currency="currency",
custom_fields=[
{
+ "id": "id",
"field_type": "text",
"name": "name",
- "id": "id",
- "order": 42,
+ "order": 0,
"placeholder": "placeholder",
"required": True,
}
],
description="description",
- expiration_days=42,
- image={"id": "id"},
- initial_price=6.9,
+ expiration_days=0,
+ image={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
+ initial_price=0,
internal_notes="internal_notes",
legacy_payment_method_controls=True,
- metadata={"foo": "bar"},
- override_tax_type="inclusive",
+ metadata={},
+ override_tax_type="override_tax_type",
payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
+ "disabled": ["string"],
+ "enabled": ["string"],
"include_platform_defaults": True,
},
- plan_type="renewal",
- release_method="buy_now",
- renewal_price=6.9,
- split_pay_required_payments=42,
- stock=42,
+ plan_type="plan_type",
+ product_id="product_id",
+ release_method="release_method",
+ renewal_price=0,
+ split_pay_required_payments=0,
+ stock=0,
three_ds_level="mandate_challenge",
title="title",
- trial_period_days=42,
+ trial_period_days=0,
unlimited_stock=True,
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Plan, plan, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_create(self, client: Whop) -> None:
- response = client.plans.with_raw_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
- )
+ response = client.plans.with_raw_response.create()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -99,10 +91,7 @@ def test_raw_response_create(self, client: Whop) -> None:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_streaming_response_create(self, client: Whop) -> None:
- with client.plans.with_streaming_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
- ) as response:
+ with client.plans.with_streaming_response.create() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -115,7 +104,7 @@ def test_streaming_response_create(self, client: Whop) -> None:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
plan = client.plans.retrieve(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(Plan, plan, path=["response"])
@@ -123,7 +112,7 @@ def test_method_retrieve(self, client: Whop) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.plans.with_raw_response.retrieve(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -135,7 +124,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.plans.with_streaming_response.retrieve(
- "plan_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -157,7 +146,7 @@ def test_path_params_retrieve(self, client: Whop) -> None:
@parametrize
def test_method_update(self, client: Whop) -> None:
plan = client.plans.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(Plan, plan, path=["response"])
@@ -165,49 +154,47 @@ def test_method_update(self, client: Whop) -> None:
@parametrize
def test_method_update_with_all_params(self, client: Whop) -> None:
plan = client.plans.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
adaptive_pricing_enabled=True,
- billing_period=42,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
+ billing_period=0,
+ checkout_styling={},
+ currency="currency",
custom_fields=[
{
+ "id": "id",
"field_type": "text",
"name": "name",
- "id": "id",
- "order": 42,
+ "order": 0,
"placeholder": "placeholder",
"required": True,
}
],
description="description",
- expiration_days=42,
- image={"id": "id"},
- initial_price=6.9,
+ expiration_days=0,
+ image={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
+ initial_price=0,
internal_notes="internal_notes",
legacy_payment_method_controls=True,
- metadata={"foo": "bar"},
+ metadata={},
offer_cancel_discount=True,
- override_tax_type="inclusive",
+ override_tax_type="override_tax_type",
payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
+ "disabled": ["string"],
+ "enabled": ["string"],
"include_platform_defaults": True,
},
- renewal_price=6.9,
- stock=42,
- strike_through_initial_price=6.9,
- strike_through_renewal_price=6.9,
+ renewal_price=0,
+ stock=0,
+ strike_through_initial_price=0,
+ strike_through_renewal_price=0,
three_ds_level="mandate_challenge",
title="title",
- trial_period_days=42,
+ trial_period_days=0,
unlimited_stock=True,
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Plan, plan, path=["response"])
@@ -215,7 +202,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_update(self, client: Whop) -> None:
response = client.plans.with_raw_response.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -227,7 +214,7 @@ def test_raw_response_update(self, client: Whop) -> None:
@parametrize
def test_streaming_response_update(self, client: Whop) -> None:
with client.plans.with_streaming_response.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -249,7 +236,7 @@ def test_path_params_update(self, client: Whop) -> None:
@parametrize
def test_method_list(self, client: Whop) -> None:
plan = client.plans.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
)
assert_matches_type(SyncCursorPage[PlanListResponse], plan, path=["response"])
@@ -257,19 +244,19 @@ def test_method_list(self, client: Whop) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Whop) -> None:
plan = client.plans.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
after="after",
before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ created_after="created_after",
+ created_before="created_before",
direction="asc",
- first=42,
- last=42,
+ first=0,
+ last=0,
order="id",
- plan_types=["renewal"],
+ plan_types=["string"],
product_ids=["string"],
- release_methods=["buy_now"],
- visibilities=["visible"],
+ release_methods=["string"],
+ visibilities=["string"],
)
assert_matches_type(SyncCursorPage[PlanListResponse], plan, path=["response"])
@@ -277,7 +264,7 @@ def test_method_list_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_list(self, client: Whop) -> None:
response = client.plans.with_raw_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
)
assert response.is_closed is True
@@ -289,7 +276,7 @@ def test_raw_response_list(self, client: Whop) -> None:
@parametrize
def test_streaming_response_list(self, client: Whop) -> None:
with client.plans.with_streaming_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -303,7 +290,7 @@ def test_streaming_response_list(self, client: Whop) -> None:
@parametrize
def test_method_delete(self, client: Whop) -> None:
plan = client.plans.delete(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(PlanDeleteResponse, plan, path=["response"])
@@ -311,7 +298,7 @@ def test_method_delete(self, client: Whop) -> None:
@parametrize
def test_raw_response_delete(self, client: Whop) -> None:
response = client.plans.with_raw_response.delete(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -323,7 +310,7 @@ def test_raw_response_delete(self, client: Whop) -> None:
@parametrize
def test_streaming_response_delete(self, client: Whop) -> None:
with client.plans.with_streaming_response.delete(
- "plan_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -341,6 +328,71 @@ def test_path_params_delete(self, client: Whop) -> None:
"",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_calculate_tax(self, client: Whop) -> None:
+ plan = client.plans.calculate_tax(
+ id="id",
+ )
+ assert_matches_type(PlanCalculateTaxResponse, plan, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_calculate_tax_with_all_params(self, client: Whop) -> None:
+ plan = client.plans.calculate_tax(
+ id="id",
+ address={
+ "country": "country",
+ "city": "city",
+ "line1": "line1",
+ "line2": "line2",
+ "postal_code": "postal_code",
+ "state": "state",
+ },
+ ip_address="ip_address",
+ tax_ids=[
+ {
+ "type": "type",
+ "value": "value",
+ }
+ ],
+ )
+ assert_matches_type(PlanCalculateTaxResponse, plan, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_calculate_tax(self, client: Whop) -> None:
+ response = client.plans.with_raw_response.calculate_tax(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ plan = response.parse()
+ assert_matches_type(PlanCalculateTaxResponse, plan, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_calculate_tax(self, client: Whop) -> None:
+ with client.plans.with_streaming_response.calculate_tax(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ plan = response.parse()
+ assert_matches_type(PlanCalculateTaxResponse, plan, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_calculate_tax(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.plans.with_raw_response.calculate_tax(
+ id="",
+ )
+
class TestAsyncPlans:
parametrize = pytest.mark.parametrize(
@@ -350,70 +402,62 @@ class TestAsyncPlans:
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_create(self, async_client: AsyncWhop) -> None:
- plan = await async_client.plans.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
- )
+ plan = await async_client.plans.create()
assert_matches_type(Plan, plan, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
plan = await async_client.plans.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
+ account_id="account_id",
adaptive_pricing_enabled=True,
- billing_period=42,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
+ billing_period=0,
+ checkout_styling={},
+ currency="currency",
custom_fields=[
{
+ "id": "id",
"field_type": "text",
"name": "name",
- "id": "id",
- "order": 42,
+ "order": 0,
"placeholder": "placeholder",
"required": True,
}
],
description="description",
- expiration_days=42,
- image={"id": "id"},
- initial_price=6.9,
+ expiration_days=0,
+ image={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
+ initial_price=0,
internal_notes="internal_notes",
legacy_payment_method_controls=True,
- metadata={"foo": "bar"},
- override_tax_type="inclusive",
+ metadata={},
+ override_tax_type="override_tax_type",
payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
+ "disabled": ["string"],
+ "enabled": ["string"],
"include_platform_defaults": True,
},
- plan_type="renewal",
- release_method="buy_now",
- renewal_price=6.9,
- split_pay_required_payments=42,
- stock=42,
+ plan_type="plan_type",
+ product_id="product_id",
+ release_method="release_method",
+ renewal_price=0,
+ split_pay_required_payments=0,
+ stock=0,
three_ds_level="mandate_challenge",
title="title",
- trial_period_days=42,
+ trial_period_days=0,
unlimited_stock=True,
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Plan, plan, 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.plans.with_raw_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
- )
+ response = await async_client.plans.with_raw_response.create()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -423,10 +467,7 @@ async def test_raw_response_create(self, async_client: AsyncWhop) -> None:
@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.plans.with_streaming_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
- product_id="prod_xxxxxxxxxxxxx",
- ) as response:
+ async with async_client.plans.with_streaming_response.create() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -439,7 +480,7 @@ async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
plan = await async_client.plans.retrieve(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(Plan, plan, path=["response"])
@@ -447,7 +488,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
response = await async_client.plans.with_raw_response.retrieve(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -459,7 +500,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
async with async_client.plans.with_streaming_response.retrieve(
- "plan_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -481,7 +522,7 @@ async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_update(self, async_client: AsyncWhop) -> None:
plan = await async_client.plans.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(Plan, plan, path=["response"])
@@ -489,49 +530,47 @@ async def test_method_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> None:
plan = await async_client.plans.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
adaptive_pricing_enabled=True,
- billing_period=42,
- checkout_styling={
- "background_color": "background_color",
- "border_style": "rounded",
- "button_color": "button_color",
- "font_family": "system",
- },
- currency="usd",
+ billing_period=0,
+ checkout_styling={},
+ currency="currency",
custom_fields=[
{
+ "id": "id",
"field_type": "text",
"name": "name",
- "id": "id",
- "order": 42,
+ "order": 0,
"placeholder": "placeholder",
"required": True,
}
],
description="description",
- expiration_days=42,
- image={"id": "id"},
- initial_price=6.9,
+ expiration_days=0,
+ image={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
+ initial_price=0,
internal_notes="internal_notes",
legacy_payment_method_controls=True,
- metadata={"foo": "bar"},
+ metadata={},
offer_cancel_discount=True,
- override_tax_type="inclusive",
+ override_tax_type="override_tax_type",
payment_method_configuration={
- "disabled": ["acss_debit"],
- "enabled": ["acss_debit"],
+ "disabled": ["string"],
+ "enabled": ["string"],
"include_platform_defaults": True,
},
- renewal_price=6.9,
- stock=42,
- strike_through_initial_price=6.9,
- strike_through_renewal_price=6.9,
+ renewal_price=0,
+ stock=0,
+ strike_through_initial_price=0,
+ strike_through_renewal_price=0,
three_ds_level="mandate_challenge",
title="title",
- trial_period_days=42,
+ trial_period_days=0,
unlimited_stock=True,
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Plan, plan, path=["response"])
@@ -539,7 +578,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
@parametrize
async def test_raw_response_update(self, async_client: AsyncWhop) -> None:
response = await async_client.plans.with_raw_response.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -551,7 +590,7 @@ async def test_raw_response_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_update(self, async_client: AsyncWhop) -> None:
async with async_client.plans.with_streaming_response.update(
- id="plan_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -573,7 +612,7 @@ async def test_path_params_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncWhop) -> None:
plan = await async_client.plans.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
)
assert_matches_type(AsyncCursorPage[PlanListResponse], plan, path=["response"])
@@ -581,19 +620,19 @@ async def test_method_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
plan = await async_client.plans.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
after="after",
before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ created_after="created_after",
+ created_before="created_before",
direction="asc",
- first=42,
- last=42,
+ first=0,
+ last=0,
order="id",
- plan_types=["renewal"],
+ plan_types=["string"],
product_ids=["string"],
- release_methods=["buy_now"],
- visibilities=["visible"],
+ release_methods=["string"],
+ visibilities=["string"],
)
assert_matches_type(AsyncCursorPage[PlanListResponse], plan, path=["response"])
@@ -601,7 +640,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non
@parametrize
async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
response = await async_client.plans.with_raw_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
)
assert response.is_closed is True
@@ -613,7 +652,7 @@ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
async with async_client.plans.with_streaming_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ account_id="account_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -627,7 +666,7 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_delete(self, async_client: AsyncWhop) -> None:
plan = await async_client.plans.delete(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(PlanDeleteResponse, plan, path=["response"])
@@ -635,7 +674,7 @@ async def test_method_delete(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_delete(self, async_client: AsyncWhop) -> None:
response = await async_client.plans.with_raw_response.delete(
- "plan_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -647,7 +686,7 @@ async def test_raw_response_delete(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_delete(self, async_client: AsyncWhop) -> None:
async with async_client.plans.with_streaming_response.delete(
- "plan_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -664,3 +703,68 @@ async def test_path_params_delete(self, async_client: AsyncWhop) -> None:
await async_client.plans.with_raw_response.delete(
"",
)
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_calculate_tax(self, async_client: AsyncWhop) -> None:
+ plan = await async_client.plans.calculate_tax(
+ id="id",
+ )
+ assert_matches_type(PlanCalculateTaxResponse, plan, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_calculate_tax_with_all_params(self, async_client: AsyncWhop) -> None:
+ plan = await async_client.plans.calculate_tax(
+ id="id",
+ address={
+ "country": "country",
+ "city": "city",
+ "line1": "line1",
+ "line2": "line2",
+ "postal_code": "postal_code",
+ "state": "state",
+ },
+ ip_address="ip_address",
+ tax_ids=[
+ {
+ "type": "type",
+ "value": "value",
+ }
+ ],
+ )
+ assert_matches_type(PlanCalculateTaxResponse, plan, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_calculate_tax(self, async_client: AsyncWhop) -> None:
+ response = await async_client.plans.with_raw_response.calculate_tax(
+ id="id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ plan = await response.parse()
+ assert_matches_type(PlanCalculateTaxResponse, plan, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_calculate_tax(self, async_client: AsyncWhop) -> None:
+ async with async_client.plans.with_streaming_response.calculate_tax(
+ id="id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ plan = await response.parse()
+ assert_matches_type(PlanCalculateTaxResponse, plan, 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_calculate_tax(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.plans.with_raw_response.calculate_tax(
+ id="",
+ )
diff --git a/tests/api_resources/test_products.py b/tests/api_resources/test_products.py
index b9a1c329..10201f78 100644
--- a/tests/api_resources/test_products.py
+++ b/tests/api_resources/test_products.py
@@ -9,10 +9,7 @@
from whop_sdk import Whop, AsyncWhop
from tests.utils import assert_matches_type
-from whop_sdk.types import (
- ProductDeleteResponse,
-)
-from whop_sdk._utils import parse_datetime
+from whop_sdk.types import ProductDeleteResponse
from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
from whop_sdk.types.shared import Product, ProductListItem
@@ -26,7 +23,6 @@ class TestProducts:
@parametrize
def test_method_create(self, client: Whop) -> None:
product = client.products.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
)
assert_matches_type(Product, product, path=["response"])
@@ -35,44 +31,23 @@ def test_method_create(self, client: Whop) -> None:
@parametrize
def test_method_create_with_all_params(self, client: Whop) -> None:
product = client.products.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
collect_shipping_address=True,
- custom_cta="get_access",
+ company_id="company_id",
+ custom_cta="custom_cta",
custom_cta_url="custom_cta_url",
custom_statement_descriptor="custom_statement_descriptor",
description="description",
- experience_ids=["string"],
- global_affiliate_percentage=6.9,
- global_affiliate_status="enabled",
+ global_affiliate_percentage=0,
+ global_affiliate_status="global_affiliate_status",
headline="headline",
- member_affiliate_percentage=6.9,
- member_affiliate_status="enabled",
- metadata={"foo": "bar"},
- plan_options={
- "base_currency": "usd",
- "billing_period": 42,
- "custom_fields": [
- {
- "field_type": "text",
- "name": "name",
- "id": "id",
- "order": 42,
- "placeholder": "placeholder",
- "required": True,
- }
- ],
- "initial_price": 6.9,
- "plan_type": "renewal",
- "release_method": "buy_now",
- "renewal_price": 6.9,
- "visibility": "visible",
- },
- product_tax_code_id="ptc_xxxxxxxxxxxxxx",
+ member_affiliate_percentage=0,
+ member_affiliate_status="member_affiliate_status",
+ metadata={},
+ product_tax_code_id="product_tax_code_id",
redirect_purchase_url="redirect_purchase_url",
route="route",
- send_welcome_message=True,
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Product, product, path=["response"])
@@ -80,7 +55,6 @@ def test_method_create_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_create(self, client: Whop) -> None:
response = client.products.with_raw_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
)
@@ -93,7 +67,6 @@ def test_raw_response_create(self, client: Whop) -> None:
@parametrize
def test_streaming_response_create(self, client: Whop) -> None:
with client.products.with_streaming_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
) as response:
assert not response.is_closed
@@ -108,7 +81,7 @@ def test_streaming_response_create(self, client: Whop) -> None:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
product = client.products.retrieve(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(Product, product, path=["response"])
@@ -116,7 +89,7 @@ def test_method_retrieve(self, client: Whop) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.products.with_raw_response.retrieve(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -128,7 +101,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.products.with_streaming_response.retrieve(
- "prod_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -150,7 +123,7 @@ def test_path_params_retrieve(self, client: Whop) -> None:
@parametrize
def test_method_update(self, client: Whop) -> None:
product = client.products.update(
- id="prod_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(Product, product, path=["response"])
@@ -158,29 +131,12 @@ def test_method_update(self, client: Whop) -> None:
@parametrize
def test_method_update_with_all_params(self, client: Whop) -> None:
product = client.products.update(
- id="prod_xxxxxxxxxxxxx",
- collect_shipping_address=True,
- custom_cta="get_access",
- custom_cta_url="custom_cta_url",
- custom_statement_descriptor="custom_statement_descriptor",
+ id="id",
description="description",
- gallery_images=[{"id": "id"}],
- global_affiliate_percentage=6.9,
- global_affiliate_status="enabled",
headline="headline",
- member_affiliate_percentage=6.9,
- member_affiliate_status="enabled",
- metadata={"foo": "bar"},
- product_tax_code_id="ptc_xxxxxxxxxxxxxx",
- redirect_purchase_url="redirect_purchase_url",
- route="route",
- send_welcome_message=True,
- store_page_config={
- "custom_cta": "custom_cta",
- "show_price": True,
- },
+ metadata={},
title="title",
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Product, product, path=["response"])
@@ -188,7 +144,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_update(self, client: Whop) -> None:
response = client.products.with_raw_response.update(
- id="prod_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -200,7 +156,7 @@ def test_raw_response_update(self, client: Whop) -> None:
@parametrize
def test_streaming_response_update(self, client: Whop) -> None:
with client.products.with_streaming_response.update(
- id="prod_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -222,7 +178,7 @@ def test_path_params_update(self, client: Whop) -> None:
@parametrize
def test_method_list(self, client: Whop) -> None:
product = client.products.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert_matches_type(SyncCursorPage[ProductListItem], product, path=["response"])
@@ -230,17 +186,15 @@ def test_method_list(self, client: Whop) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Whop) -> None:
product = client.products.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
+ access_pass_types=["string"],
after="after",
before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
direction="asc",
- first=42,
- last=42,
- order="active_memberships_count",
- product_types=["regular"],
- visibilities=["visible"],
+ first=0,
+ last=0,
+ order="order",
+ visibilities=["string"],
)
assert_matches_type(SyncCursorPage[ProductListItem], product, path=["response"])
@@ -248,7 +202,7 @@ def test_method_list_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_list(self, client: Whop) -> None:
response = client.products.with_raw_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert response.is_closed is True
@@ -260,7 +214,7 @@ def test_raw_response_list(self, client: Whop) -> None:
@parametrize
def test_streaming_response_list(self, client: Whop) -> None:
with client.products.with_streaming_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -274,7 +228,7 @@ def test_streaming_response_list(self, client: Whop) -> None:
@parametrize
def test_method_delete(self, client: Whop) -> None:
product = client.products.delete(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(ProductDeleteResponse, product, path=["response"])
@@ -282,7 +236,7 @@ def test_method_delete(self, client: Whop) -> None:
@parametrize
def test_raw_response_delete(self, client: Whop) -> None:
response = client.products.with_raw_response.delete(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -294,7 +248,7 @@ def test_raw_response_delete(self, client: Whop) -> None:
@parametrize
def test_streaming_response_delete(self, client: Whop) -> None:
with client.products.with_streaming_response.delete(
- "prod_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -322,7 +276,6 @@ class TestAsyncProducts:
@parametrize
async def test_method_create(self, async_client: AsyncWhop) -> None:
product = await async_client.products.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
)
assert_matches_type(Product, product, path=["response"])
@@ -331,44 +284,23 @@ async def test_method_create(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
product = await async_client.products.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
collect_shipping_address=True,
- custom_cta="get_access",
+ company_id="company_id",
+ custom_cta="custom_cta",
custom_cta_url="custom_cta_url",
custom_statement_descriptor="custom_statement_descriptor",
description="description",
- experience_ids=["string"],
- global_affiliate_percentage=6.9,
- global_affiliate_status="enabled",
+ global_affiliate_percentage=0,
+ global_affiliate_status="global_affiliate_status",
headline="headline",
- member_affiliate_percentage=6.9,
- member_affiliate_status="enabled",
- metadata={"foo": "bar"},
- plan_options={
- "base_currency": "usd",
- "billing_period": 42,
- "custom_fields": [
- {
- "field_type": "text",
- "name": "name",
- "id": "id",
- "order": 42,
- "placeholder": "placeholder",
- "required": True,
- }
- ],
- "initial_price": 6.9,
- "plan_type": "renewal",
- "release_method": "buy_now",
- "renewal_price": 6.9,
- "visibility": "visible",
- },
- product_tax_code_id="ptc_xxxxxxxxxxxxxx",
+ member_affiliate_percentage=0,
+ member_affiliate_status="member_affiliate_status",
+ metadata={},
+ product_tax_code_id="product_tax_code_id",
redirect_purchase_url="redirect_purchase_url",
route="route",
- send_welcome_message=True,
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Product, product, path=["response"])
@@ -376,7 +308,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N
@parametrize
async def test_raw_response_create(self, async_client: AsyncWhop) -> None:
response = await async_client.products.with_raw_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
)
@@ -389,7 +320,6 @@ async def test_raw_response_create(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
async with async_client.products.with_streaming_response.create(
- company_id="biz_xxxxxxxxxxxxxx",
title="title",
) as response:
assert not response.is_closed
@@ -404,7 +334,7 @@ async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
product = await async_client.products.retrieve(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(Product, product, path=["response"])
@@ -412,7 +342,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
response = await async_client.products.with_raw_response.retrieve(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -424,7 +354,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
async with async_client.products.with_streaming_response.retrieve(
- "prod_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -446,7 +376,7 @@ async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_update(self, async_client: AsyncWhop) -> None:
product = await async_client.products.update(
- id="prod_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(Product, product, path=["response"])
@@ -454,29 +384,12 @@ async def test_method_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> None:
product = await async_client.products.update(
- id="prod_xxxxxxxxxxxxx",
- collect_shipping_address=True,
- custom_cta="get_access",
- custom_cta_url="custom_cta_url",
- custom_statement_descriptor="custom_statement_descriptor",
+ id="id",
description="description",
- gallery_images=[{"id": "id"}],
- global_affiliate_percentage=6.9,
- global_affiliate_status="enabled",
headline="headline",
- member_affiliate_percentage=6.9,
- member_affiliate_status="enabled",
- metadata={"foo": "bar"},
- product_tax_code_id="ptc_xxxxxxxxxxxxxx",
- redirect_purchase_url="redirect_purchase_url",
- route="route",
- send_welcome_message=True,
- store_page_config={
- "custom_cta": "custom_cta",
- "show_price": True,
- },
+ metadata={},
title="title",
- visibility="visible",
+ visibility="visibility",
)
assert_matches_type(Product, product, path=["response"])
@@ -484,7 +397,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
@parametrize
async def test_raw_response_update(self, async_client: AsyncWhop) -> None:
response = await async_client.products.with_raw_response.update(
- id="prod_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -496,7 +409,7 @@ async def test_raw_response_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_update(self, async_client: AsyncWhop) -> None:
async with async_client.products.with_streaming_response.update(
- id="prod_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -518,7 +431,7 @@ async def test_path_params_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncWhop) -> None:
product = await async_client.products.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert_matches_type(AsyncCursorPage[ProductListItem], product, path=["response"])
@@ -526,17 +439,15 @@ async def test_method_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
product = await async_client.products.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
+ access_pass_types=["string"],
after="after",
before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
direction="asc",
- first=42,
- last=42,
- order="active_memberships_count",
- product_types=["regular"],
- visibilities=["visible"],
+ first=0,
+ last=0,
+ order="order",
+ visibilities=["string"],
)
assert_matches_type(AsyncCursorPage[ProductListItem], product, path=["response"])
@@ -544,7 +455,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non
@parametrize
async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
response = await async_client.products.with_raw_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
)
assert response.is_closed is True
@@ -556,7 +467,7 @@ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
async with async_client.products.with_streaming_response.list(
- company_id="biz_xxxxxxxxxxxxxx",
+ company_id="company_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -570,7 +481,7 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_delete(self, async_client: AsyncWhop) -> None:
product = await async_client.products.delete(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert_matches_type(ProductDeleteResponse, product, path=["response"])
@@ -578,7 +489,7 @@ async def test_method_delete(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_delete(self, async_client: AsyncWhop) -> None:
response = await async_client.products.with_raw_response.delete(
- "prod_xxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
@@ -590,7 +501,7 @@ async def test_raw_response_delete(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_delete(self, async_client: AsyncWhop) -> None:
async with async_client.products.with_streaming_response.delete(
- "prod_xxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_swaps.py b/tests/api_resources/test_swaps.py
index 26dee794..9972efc2 100644
--- a/tests/api_resources/test_swaps.py
+++ b/tests/api_resources/test_swaps.py
@@ -9,7 +9,12 @@
from whop_sdk import Whop, AsyncWhop
from tests.utils import assert_matches_type
-from whop_sdk.types import SwapCreateQuoteResponse
+from whop_sdk.types import (
+ SwapListResponse,
+ SwapCreateResponse,
+ SwapRetrieveResponse,
+ SwapCreateQuoteResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -17,6 +22,139 @@
class TestSwaps:
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:
+ swap = client.swaps.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ )
+ assert_matches_type(SwapCreateResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Whop) -> None:
+ swap = client.swaps.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ from_chain="string",
+ slippage_bps=0,
+ to_chain="string",
+ )
+ assert_matches_type(SwapCreateResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Whop) -> None:
+ response = client.swaps.with_raw_response.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ swap = response.parse()
+ assert_matches_type(SwapCreateResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Whop) -> None:
+ with client.swaps.with_streaming_response.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ swap = response.parse()
+ assert_matches_type(SwapCreateResponse, swap, 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:
+ swap = client.swaps.retrieve(
+ "id",
+ )
+ assert_matches_type(SwapRetrieveResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve(self, client: Whop) -> None:
+ response = client.swaps.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ swap = response.parse()
+ assert_matches_type(SwapRetrieveResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve(self, client: Whop) -> None:
+ with client.swaps.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ swap = response.parse()
+ assert_matches_type(SwapRetrieveResponse, swap, 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.swaps.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Whop) -> None:
+ swap = client.swaps.list(
+ account_id="account_id",
+ )
+ assert_matches_type(SwapListResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Whop) -> None:
+ response = client.swaps.with_raw_response.list(
+ account_id="account_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ swap = response.parse()
+ assert_matches_type(SwapListResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Whop) -> None:
+ with client.swaps.with_streaming_response.list(
+ account_id="account_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ swap = response.parse()
+ assert_matches_type(SwapListResponse, swap, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_create_quote(self, client: Whop) -> None:
@@ -79,6 +217,139 @@ class TestAsyncSwaps:
"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:
+ swap = await async_client.swaps.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ )
+ assert_matches_type(SwapCreateResponse, swap, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
+ swap = await async_client.swaps.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ from_chain="string",
+ slippage_bps=0,
+ to_chain="string",
+ )
+ assert_matches_type(SwapCreateResponse, swap, 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.swaps.with_raw_response.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ swap = await response.parse()
+ assert_matches_type(SwapCreateResponse, swap, 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.swaps.with_streaming_response.create(
+ account_id="account_id",
+ amount="amount",
+ from_token="from_token",
+ to_token="to_token",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ swap = await response.parse()
+ assert_matches_type(SwapCreateResponse, swap, 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:
+ swap = await async_client.swaps.retrieve(
+ "id",
+ )
+ assert_matches_type(SwapRetrieveResponse, swap, 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.swaps.with_raw_response.retrieve(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ swap = await response.parse()
+ assert_matches_type(SwapRetrieveResponse, swap, 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.swaps.with_streaming_response.retrieve(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ swap = await response.parse()
+ assert_matches_type(SwapRetrieveResponse, swap, 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.swaps.with_raw_response.retrieve(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncWhop) -> None:
+ swap = await async_client.swaps.list(
+ account_id="account_id",
+ )
+ assert_matches_type(SwapListResponse, swap, 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.swaps.with_raw_response.list(
+ account_id="account_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ swap = await response.parse()
+ assert_matches_type(SwapListResponse, swap, 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.swaps.with_streaming_response.list(
+ account_id="account_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ swap = await response.parse()
+ assert_matches_type(SwapListResponse, swap, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_create_quote(self, async_client: AsyncWhop) -> None:
diff --git a/tests/api_resources/test_transfers.py b/tests/api_resources/test_transfers.py
index 0b2c1c1d..95586346 100644
--- a/tests/api_resources/test_transfers.py
+++ b/tests/api_resources/test_transfers.py
@@ -9,10 +9,13 @@
from whop_sdk import Whop, AsyncWhop
from tests.utils import assert_matches_type
-from whop_sdk.types import TransferListResponse
+from whop_sdk.types import (
+ TransferListResponse,
+ TransferCreateResponse,
+ TransferRetrieveResponse,
+)
from whop_sdk._utils import parse_datetime
from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
-from whop_sdk.types.shared import Transfer
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -24,56 +27,53 @@ class TestTransfers:
@parametrize
def test_method_create(self, client: Whop) -> None:
transfer = client.transfers.create(
- amount=6.9,
- currency="usd",
- destination_id="destination_id",
+ amount=0,
origin_id="origin_id",
)
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_method_create_with_all_params(self, client: Whop) -> None:
transfer = client.transfers.create(
- amount=6.9,
+ amount=0,
+ origin_id="origin_id",
currency="usd",
destination_id="destination_id",
- origin_id="origin_id",
+ expires_at=parse_datetime("2019-12-27T18:11:19.117Z"),
idempotence_key="idempotence_key",
metadata={"foo": "bar"},
notes="notes",
+ redeemable_count=0,
+ type="ledger",
)
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_create(self, client: Whop) -> None:
response = client.transfers.with_raw_response.create(
- amount=6.9,
- currency="usd",
- destination_id="destination_id",
+ amount=0,
origin_id="origin_id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_streaming_response_create(self, client: Whop) -> None:
with client.transfers.with_streaming_response.create(
- amount=6.9,
- currency="usd",
- destination_id="destination_id",
+ amount=0,
origin_id="origin_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -81,33 +81,33 @@ def test_streaming_response_create(self, client: Whop) -> None:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
transfer = client.transfers.retrieve(
- "ctt_xxxxxxxxxxxxxx",
+ "id",
)
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferRetrieveResponse, transfer, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.transfers.with_raw_response.retrieve(
- "ctt_xxxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferRetrieveResponse, transfer, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.transfers.with_streaming_response.retrieve(
- "ctt_xxxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferRetrieveResponse, transfer, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -131,13 +131,13 @@ def test_method_list_with_all_params(self, client: Whop) -> None:
transfer = client.transfers.list(
after="after",
before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ created_after="created_after",
+ created_before="created_before",
destination_id="destination_id",
direction="asc",
- first=42,
- last=42,
- order="amount",
+ first=50,
+ last=50,
+ order="created_at",
origin_id="origin_id",
)
assert_matches_type(SyncCursorPage[TransferListResponse], transfer, path=["response"])
@@ -174,56 +174,53 @@ class TestAsyncTransfers:
@parametrize
async def test_method_create(self, async_client: AsyncWhop) -> None:
transfer = await async_client.transfers.create(
- amount=6.9,
- currency="usd",
- destination_id="destination_id",
+ amount=0,
origin_id="origin_id",
)
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
transfer = await async_client.transfers.create(
- amount=6.9,
+ amount=0,
+ origin_id="origin_id",
currency="usd",
destination_id="destination_id",
- origin_id="origin_id",
+ expires_at=parse_datetime("2019-12-27T18:11:19.117Z"),
idempotence_key="idempotence_key",
metadata={"foo": "bar"},
notes="notes",
+ redeemable_count=0,
+ type="ledger",
)
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, 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.transfers.with_raw_response.create(
- amount=6.9,
- currency="usd",
- destination_id="destination_id",
+ amount=0,
origin_id="origin_id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = await response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, 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.transfers.with_streaming_response.create(
- amount=6.9,
- currency="usd",
- destination_id="destination_id",
+ amount=0,
origin_id="origin_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = await response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferCreateResponse, transfer, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -231,33 +228,33 @@ async def test_streaming_response_create(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
transfer = await async_client.transfers.retrieve(
- "ctt_xxxxxxxxxxxxxx",
+ "id",
)
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferRetrieveResponse, transfer, 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.transfers.with_raw_response.retrieve(
- "ctt_xxxxxxxxxxxxxx",
+ "id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = await response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferRetrieveResponse, transfer, 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.transfers.with_streaming_response.retrieve(
- "ctt_xxxxxxxxxxxxxx",
+ "id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
transfer = await response.parse()
- assert_matches_type(Transfer, transfer, path=["response"])
+ assert_matches_type(TransferRetrieveResponse, transfer, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -281,13 +278,13 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non
transfer = await async_client.transfers.list(
after="after",
before="before",
- created_after=parse_datetime("2023-12-01T05:00:00.401Z"),
- created_before=parse_datetime("2023-12-01T05:00:00.401Z"),
+ created_after="created_after",
+ created_before="created_before",
destination_id="destination_id",
direction="asc",
- first=42,
- last=42,
- order="amount",
+ first=50,
+ last=50,
+ order="created_at",
origin_id="origin_id",
)
assert_matches_type(AsyncCursorPage[TransferListResponse], transfer, path=["response"])
diff --git a/tests/api_resources/test_users.py b/tests/api_resources/test_users.py
index ee565217..9b0014ac 100644
--- a/tests/api_resources/test_users.py
+++ b/tests/api_resources/test_users.py
@@ -11,7 +11,6 @@
from tests.utils import assert_matches_type
from whop_sdk.types import (
User,
- UserListResponse,
UserCheckAccessResponse,
)
from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
@@ -26,7 +25,7 @@ class TestUsers:
@parametrize
def test_method_retrieve(self, client: Whop) -> None:
user = client.users.retrieve(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(User, user, path=["response"])
@@ -34,8 +33,8 @@ def test_method_retrieve(self, client: Whop) -> None:
@parametrize
def test_method_retrieve_with_all_params(self, client: Whop) -> None:
user = client.users.retrieve(
- id="user_xxxxxxxxxxxxx",
- company_id="biz_xxxxxxxxxxxxxx",
+ id="id",
+ account_id="account_id",
)
assert_matches_type(User, user, path=["response"])
@@ -43,7 +42,7 @@ def test_method_retrieve_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.users.with_raw_response.retrieve(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -55,7 +54,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.users.with_streaming_response.retrieve(
- id="user_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -77,7 +76,7 @@ def test_path_params_retrieve(self, client: Whop) -> None:
@parametrize
def test_method_update(self, client: Whop) -> None:
user = client.users.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(User, user, path=["response"])
@@ -85,11 +84,14 @@ def test_method_update(self, client: Whop) -> None:
@parametrize
def test_method_update_with_all_params(self, client: Whop) -> None:
user = client.users.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
+ account_id="account_id",
bio="bio",
- company_id="biz_xxxxxxxxxxxxxx",
name="name",
- profile_picture={"id": "id"},
+ profile_picture={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
username="username",
)
assert_matches_type(User, user, path=["response"])
@@ -98,7 +100,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None:
@parametrize
def test_raw_response_update(self, client: Whop) -> None:
response = client.users.with_raw_response.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -110,7 +112,7 @@ def test_raw_response_update(self, client: Whop) -> None:
@parametrize
def test_streaming_response_update(self, client: Whop) -> None:
with client.users.with_streaming_response.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -132,7 +134,7 @@ def test_path_params_update(self, client: Whop) -> None:
@parametrize
def test_method_list(self, client: Whop) -> None:
user = client.users.list()
- assert_matches_type(SyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(SyncCursorPage[User], user, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -140,11 +142,11 @@ def test_method_list_with_all_params(self, client: Whop) -> None:
user = client.users.list(
after="after",
before="before",
- first=42,
- last=42,
+ first=0,
+ last=0,
query="query",
)
- assert_matches_type(SyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(SyncCursorPage[User], user, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -154,7 +156,7 @@ def test_raw_response_list(self, client: Whop) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
user = response.parse()
- assert_matches_type(SyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(SyncCursorPage[User], user, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -164,7 +166,7 @@ def test_streaming_response_list(self, client: Whop) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
user = response.parse()
- assert_matches_type(SyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(SyncCursorPage[User], user, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -173,7 +175,7 @@ def test_streaming_response_list(self, client: Whop) -> None:
def test_method_check_access(self, client: Whop) -> None:
user = client.users.check_access(
resource_id="resource_id",
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(UserCheckAccessResponse, user, path=["response"])
@@ -182,7 +184,7 @@ def test_method_check_access(self, client: Whop) -> None:
def test_raw_response_check_access(self, client: Whop) -> None:
response = client.users.with_raw_response.check_access(
resource_id="resource_id",
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -195,7 +197,7 @@ def test_raw_response_check_access(self, client: Whop) -> None:
def test_streaming_response_check_access(self, client: Whop) -> None:
with client.users.with_streaming_response.check_access(
resource_id="resource_id",
- id="user_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -217,9 +219,52 @@ def test_path_params_check_access(self, client: Whop) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_id` but received ''"):
client.users.with_raw_response.check_access(
resource_id="",
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_me(self, client: Whop) -> None:
+ user = client.users.update_me()
+ assert_matches_type(User, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_me_with_all_params(self, client: Whop) -> None:
+ user = client.users.update_me(
+ account_id="account_id",
+ bio="bio",
+ name="name",
+ profile_picture={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
+ username="username",
+ )
+ assert_matches_type(User, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update_me(self, client: Whop) -> None:
+ response = client.users.with_raw_response.update_me()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(User, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update_me(self, client: Whop) -> None:
+ with client.users.with_streaming_response.update_me() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(User, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncUsers:
parametrize = pytest.mark.parametrize(
@@ -230,7 +275,7 @@ class TestAsyncUsers:
@parametrize
async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
user = await async_client.users.retrieve(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(User, user, path=["response"])
@@ -238,8 +283,8 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) -> None:
user = await async_client.users.retrieve(
- id="user_xxxxxxxxxxxxx",
- company_id="biz_xxxxxxxxxxxxxx",
+ id="id",
+ account_id="account_id",
)
assert_matches_type(User, user, path=["response"])
@@ -247,7 +292,7 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) ->
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
response = await async_client.users.with_raw_response.retrieve(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -259,7 +304,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
async with async_client.users.with_streaming_response.retrieve(
- id="user_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -281,7 +326,7 @@ async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_update(self, async_client: AsyncWhop) -> None:
user = await async_client.users.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(User, user, path=["response"])
@@ -289,11 +334,14 @@ async def test_method_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> None:
user = await async_client.users.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
+ account_id="account_id",
bio="bio",
- company_id="biz_xxxxxxxxxxxxxx",
name="name",
- profile_picture={"id": "id"},
+ profile_picture={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
username="username",
)
assert_matches_type(User, user, path=["response"])
@@ -302,7 +350,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N
@parametrize
async def test_raw_response_update(self, async_client: AsyncWhop) -> None:
response = await async_client.users.with_raw_response.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -314,7 +362,7 @@ async def test_raw_response_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_update(self, async_client: AsyncWhop) -> None:
async with async_client.users.with_streaming_response.update(
- id="user_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -336,7 +384,7 @@ async def test_path_params_update(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncWhop) -> None:
user = await async_client.users.list()
- assert_matches_type(AsyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(AsyncCursorPage[User], user, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -344,11 +392,11 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non
user = await async_client.users.list(
after="after",
before="before",
- first=42,
- last=42,
+ first=0,
+ last=0,
query="query",
)
- assert_matches_type(AsyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(AsyncCursorPage[User], user, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -358,7 +406,7 @@ async def test_raw_response_list(self, async_client: AsyncWhop) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
user = await response.parse()
- assert_matches_type(AsyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(AsyncCursorPage[User], user, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -368,7 +416,7 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
user = await response.parse()
- assert_matches_type(AsyncCursorPage[UserListResponse], user, path=["response"])
+ assert_matches_type(AsyncCursorPage[User], user, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -377,7 +425,7 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None:
async def test_method_check_access(self, async_client: AsyncWhop) -> None:
user = await async_client.users.check_access(
resource_id="resource_id",
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert_matches_type(UserCheckAccessResponse, user, path=["response"])
@@ -386,7 +434,7 @@ async def test_method_check_access(self, async_client: AsyncWhop) -> None:
async def test_raw_response_check_access(self, async_client: AsyncWhop) -> None:
response = await async_client.users.with_raw_response.check_access(
resource_id="resource_id",
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
assert response.is_closed is True
@@ -399,7 +447,7 @@ async def test_raw_response_check_access(self, async_client: AsyncWhop) -> None:
async def test_streaming_response_check_access(self, async_client: AsyncWhop) -> None:
async with async_client.users.with_streaming_response.check_access(
resource_id="resource_id",
- id="user_xxxxxxxxxxxxx",
+ id="id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -421,5 +469,48 @@ async def test_path_params_check_access(self, async_client: AsyncWhop) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `resource_id` but received ''"):
await async_client.users.with_raw_response.check_access(
resource_id="",
- id="user_xxxxxxxxxxxxx",
+ id="id",
)
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update_me(self, async_client: AsyncWhop) -> None:
+ user = await async_client.users.update_me()
+ assert_matches_type(User, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_update_me_with_all_params(self, async_client: AsyncWhop) -> None:
+ user = await async_client.users.update_me(
+ account_id="account_id",
+ bio="bio",
+ name="name",
+ profile_picture={
+ "id": "id",
+ "direct_upload_id": "direct_upload_id",
+ },
+ username="username",
+ )
+ assert_matches_type(User, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_update_me(self, async_client: AsyncWhop) -> None:
+ response = await async_client.users.with_raw_response.update_me()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(User, user, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_update_me(self, async_client: AsyncWhop) -> None:
+ async with async_client.users.with_streaming_response.update_me() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(User, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_verifications.py b/tests/api_resources/test_verifications.py
index e1499aed..1cb41c09 100644
--- a/tests/api_resources/test_verifications.py
+++ b/tests/api_resources/test_verifications.py
@@ -9,8 +9,13 @@
from whop_sdk import Whop, AsyncWhop
from tests.utils import assert_matches_type
-from whop_sdk.types import VerificationListResponse, VerificationRetrieveResponse
-from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage
+from whop_sdk.types import (
+ VerificationListResponse,
+ VerificationCreateResponse,
+ VerificationDeleteResponse,
+ VerificationUpdateResponse,
+ VerificationRetrieveResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -18,11 +23,66 @@
class TestVerifications:
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:
+ verification = client.verifications.create(
+ account_id="account_id",
+ )
+ assert_matches_type(VerificationCreateResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Whop) -> None:
+ verification = client.verifications.create(
+ account_id="account_id",
+ address={"foo": "bar"},
+ business_name="business_name",
+ business_structure="business_structure",
+ business_website="business_website",
+ country="country",
+ date_of_birth="date_of_birth",
+ first_name="first_name",
+ kind="individual",
+ last_name="last_name",
+ phone="phone",
+ place_of_incorporation="place_of_incorporation",
+ restart=True,
+ tax_identification_number="tax_identification_number",
+ )
+ assert_matches_type(VerificationCreateResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Whop) -> None:
+ response = client.verifications.with_raw_response.create(
+ account_id="account_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ verification = response.parse()
+ assert_matches_type(VerificationCreateResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Whop) -> None:
+ with client.verifications.with_streaming_response.create(
+ account_id="account_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ verification = response.parse()
+ assert_matches_type(VerificationCreateResponse, verification, 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:
verification = client.verifications.retrieve(
- "verf_xxxxxxxxxxxxx",
+ "verification_id",
)
assert_matches_type(VerificationRetrieveResponse, verification, path=["response"])
@@ -30,7 +90,7 @@ def test_method_retrieve(self, client: Whop) -> None:
@parametrize
def test_raw_response_retrieve(self, client: Whop) -> None:
response = client.verifications.with_raw_response.retrieve(
- "verf_xxxxxxxxxxxxx",
+ "verification_id",
)
assert response.is_closed is True
@@ -42,7 +102,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None:
@parametrize
def test_streaming_response_retrieve(self, client: Whop) -> None:
with client.verifications.with_streaming_response.retrieve(
- "verf_xxxxxxxxxxxxx",
+ "verification_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -55,68 +115,220 @@ def test_streaming_response_retrieve(self, client: Whop) -> None:
@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 ''"):
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `verification_id` but received ''"):
client.verifications.with_raw_response.retrieve(
"",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- def test_method_list(self, client: Whop) -> None:
- verification = client.verifications.list(
- payout_account_id="poact_xxxxxxxxxxxx",
+ def test_method_update(self, client: Whop) -> None:
+ verification = client.verifications.update(
+ verification_id="verification_id",
+ )
+ assert_matches_type(VerificationUpdateResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_update_with_all_params(self, client: Whop) -> None:
+ verification = client.verifications.update(
+ verification_id="verification_id",
+ business_address={"foo": "bar"},
+ business_name="business_name",
+ business_structure="business_structure",
+ country="country",
+ date_of_birth="date_of_birth",
+ first_name="first_name",
+ last_name="last_name",
+ personal_address={"foo": "bar"},
+ rfis=[
+ {
+ "id": "id",
+ "address": {"foo": "bar"},
+ "files": [{}],
+ "value": "value",
+ "value_type": "raw",
+ }
+ ],
+ )
+ assert_matches_type(VerificationUpdateResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_update(self, client: Whop) -> None:
+ response = client.verifications.with_raw_response.update(
+ verification_id="verification_id",
)
- assert_matches_type(SyncCursorPage[VerificationListResponse], verification, path=["response"])
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ verification = response.parse()
+ assert_matches_type(VerificationUpdateResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_update(self, client: Whop) -> None:
+ with client.verifications.with_streaming_response.update(
+ verification_id="verification_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ verification = response.parse()
+ assert_matches_type(VerificationUpdateResponse, verification, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- def test_method_list_with_all_params(self, client: Whop) -> None:
+ def test_path_params_update(self, client: Whop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `verification_id` but received ''"):
+ client.verifications.with_raw_response.update(
+ verification_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Whop) -> None:
verification = client.verifications.list(
- payout_account_id="poact_xxxxxxxxxxxx",
- after="after",
- before="before",
- first=42,
- last=42,
+ account_id="account_id",
)
- assert_matches_type(SyncCursorPage[VerificationListResponse], verification, path=["response"])
+ assert_matches_type(VerificationListResponse, verification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_raw_response_list(self, client: Whop) -> None:
response = client.verifications.with_raw_response.list(
- payout_account_id="poact_xxxxxxxxxxxx",
+ account_id="account_id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
verification = response.parse()
- assert_matches_type(SyncCursorPage[VerificationListResponse], verification, path=["response"])
+ assert_matches_type(VerificationListResponse, verification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
def test_streaming_response_list(self, client: Whop) -> None:
with client.verifications.with_streaming_response.list(
- payout_account_id="poact_xxxxxxxxxxxx",
+ account_id="account_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
verification = response.parse()
- assert_matches_type(SyncCursorPage[VerificationListResponse], verification, path=["response"])
+ assert_matches_type(VerificationListResponse, verification, path=["response"])
assert cast(Any, response.is_closed) is True
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_delete(self, client: Whop) -> None:
+ verification = client.verifications.delete(
+ "verification_id",
+ )
+ assert_matches_type(VerificationDeleteResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete(self, client: Whop) -> None:
+ response = client.verifications.with_raw_response.delete(
+ "verification_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ verification = response.parse()
+ assert_matches_type(VerificationDeleteResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete(self, client: Whop) -> None:
+ with client.verifications.with_streaming_response.delete(
+ "verification_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ verification = response.parse()
+ assert_matches_type(VerificationDeleteResponse, verification, 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 `verification_id` but received ''"):
+ client.verifications.with_raw_response.delete(
+ "",
+ )
+
class TestAsyncVerifications:
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:
+ verification = await async_client.verifications.create(
+ account_id="account_id",
+ )
+ assert_matches_type(VerificationCreateResponse, verification, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> None:
+ verification = await async_client.verifications.create(
+ account_id="account_id",
+ address={"foo": "bar"},
+ business_name="business_name",
+ business_structure="business_structure",
+ business_website="business_website",
+ country="country",
+ date_of_birth="date_of_birth",
+ first_name="first_name",
+ kind="individual",
+ last_name="last_name",
+ phone="phone",
+ place_of_incorporation="place_of_incorporation",
+ restart=True,
+ tax_identification_number="tax_identification_number",
+ )
+ assert_matches_type(VerificationCreateResponse, verification, 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.verifications.with_raw_response.create(
+ account_id="account_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ verification = await response.parse()
+ assert_matches_type(VerificationCreateResponse, verification, 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.verifications.with_streaming_response.create(
+ account_id="account_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ verification = await response.parse()
+ assert_matches_type(VerificationCreateResponse, verification, 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:
verification = await async_client.verifications.retrieve(
- "verf_xxxxxxxxxxxxx",
+ "verification_id",
)
assert_matches_type(VerificationRetrieveResponse, verification, path=["response"])
@@ -124,7 +336,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
response = await async_client.verifications.with_raw_response.retrieve(
- "verf_xxxxxxxxxxxxx",
+ "verification_id",
)
assert response.is_closed is True
@@ -136,7 +348,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None:
@parametrize
async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None:
async with async_client.verifications.with_streaming_response.retrieve(
- "verf_xxxxxxxxxxxxx",
+ "verification_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -149,53 +361,150 @@ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> Non
@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 ''"):
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `verification_id` but received ''"):
await async_client.verifications.with_raw_response.retrieve(
"",
)
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- async def test_method_list(self, async_client: AsyncWhop) -> None:
- verification = await async_client.verifications.list(
- payout_account_id="poact_xxxxxxxxxxxx",
+ async def test_method_update(self, async_client: AsyncWhop) -> None:
+ verification = await async_client.verifications.update(
+ verification_id="verification_id",
+ )
+ assert_matches_type(VerificationUpdateResponse, verification, 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:
+ verification = await async_client.verifications.update(
+ verification_id="verification_id",
+ business_address={"foo": "bar"},
+ business_name="business_name",
+ business_structure="business_structure",
+ country="country",
+ date_of_birth="date_of_birth",
+ first_name="first_name",
+ last_name="last_name",
+ personal_address={"foo": "bar"},
+ rfis=[
+ {
+ "id": "id",
+ "address": {"foo": "bar"},
+ "files": [{}],
+ "value": "value",
+ "value_type": "raw",
+ }
+ ],
+ )
+ assert_matches_type(VerificationUpdateResponse, verification, 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.verifications.with_raw_response.update(
+ verification_id="verification_id",
)
- assert_matches_type(AsyncCursorPage[VerificationListResponse], verification, path=["response"])
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ verification = await response.parse()
+ assert_matches_type(VerificationUpdateResponse, verification, 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.verifications.with_streaming_response.update(
+ verification_id="verification_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ verification = await response.parse()
+ assert_matches_type(VerificationUpdateResponse, verification, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None:
+ async def test_path_params_update(self, async_client: AsyncWhop) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `verification_id` but received ''"):
+ await async_client.verifications.with_raw_response.update(
+ verification_id="",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncWhop) -> None:
verification = await async_client.verifications.list(
- payout_account_id="poact_xxxxxxxxxxxx",
- after="after",
- before="before",
- first=42,
- last=42,
+ account_id="account_id",
)
- assert_matches_type(AsyncCursorPage[VerificationListResponse], verification, path=["response"])
+ assert_matches_type(VerificationListResponse, verification, 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.verifications.with_raw_response.list(
- payout_account_id="poact_xxxxxxxxxxxx",
+ account_id="account_id",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
verification = await response.parse()
- assert_matches_type(AsyncCursorPage[VerificationListResponse], verification, path=["response"])
+ assert_matches_type(VerificationListResponse, verification, 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.verifications.with_streaming_response.list(
- payout_account_id="poact_xxxxxxxxxxxx",
+ account_id="account_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
verification = await response.parse()
- assert_matches_type(AsyncCursorPage[VerificationListResponse], verification, path=["response"])
+ assert_matches_type(VerificationListResponse, verification, path=["response"])
assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncWhop) -> None:
+ verification = await async_client.verifications.delete(
+ "verification_id",
+ )
+ assert_matches_type(VerificationDeleteResponse, verification, 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.verifications.with_raw_response.delete(
+ "verification_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ verification = await response.parse()
+ assert_matches_type(VerificationDeleteResponse, verification, 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.verifications.with_streaming_response.delete(
+ "verification_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ verification = await response.parse()
+ assert_matches_type(VerificationDeleteResponse, verification, 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 `verification_id` but received ''"):
+ await async_client.verifications.with_raw_response.delete(
+ "",
+ )
diff --git a/tests/api_resources/test_wallets.py b/tests/api_resources/test_wallets.py
deleted file mode 100644
index abc5ad15..00000000
--- a/tests/api_resources/test_wallets.py
+++ /dev/null
@@ -1,264 +0,0 @@
-# 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 WalletListResponse, WalletSendResponse, WalletBalanceResponse
-
-base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
-
-
-class TestWallets:
- 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_list(self, client: Whop) -> None:
- wallet = client.wallets.list()
- assert_matches_type(WalletListResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_list(self, client: Whop) -> None:
- response = client.wallets.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- wallet = response.parse()
- assert_matches_type(WalletListResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_list(self, client: Whop) -> None:
- with client.wallets.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- wallet = response.parse()
- assert_matches_type(WalletListResponse, wallet, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_balance(self, client: Whop) -> None:
- wallet = client.wallets.balance(
- "account_id",
- )
- assert_matches_type(WalletBalanceResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_balance(self, client: Whop) -> None:
- response = client.wallets.with_raw_response.balance(
- "account_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- wallet = response.parse()
- assert_matches_type(WalletBalanceResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_balance(self, client: Whop) -> None:
- with client.wallets.with_streaming_response.balance(
- "account_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- wallet = response.parse()
- assert_matches_type(WalletBalanceResponse, wallet, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_balance(self, client: Whop) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
- client.wallets.with_raw_response.balance(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_method_send(self, client: Whop) -> None:
- wallet = client.wallets.send(
- account_id="account_id",
- amount="amount",
- to="to",
- )
- assert_matches_type(WalletSendResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_raw_response_send(self, client: Whop) -> None:
- response = client.wallets.with_raw_response.send(
- account_id="account_id",
- amount="amount",
- to="to",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- wallet = response.parse()
- assert_matches_type(WalletSendResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_streaming_response_send(self, client: Whop) -> None:
- with client.wallets.with_streaming_response.send(
- account_id="account_id",
- amount="amount",
- to="to",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- wallet = response.parse()
- assert_matches_type(WalletSendResponse, wallet, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- def test_path_params_send(self, client: Whop) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
- client.wallets.with_raw_response.send(
- account_id="",
- amount="amount",
- to="to",
- )
-
-
-class TestAsyncWallets:
- 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_list(self, async_client: AsyncWhop) -> None:
- wallet = await async_client.wallets.list()
- assert_matches_type(WalletListResponse, wallet, 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.wallets.with_raw_response.list()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- wallet = await response.parse()
- assert_matches_type(WalletListResponse, wallet, 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.wallets.with_streaming_response.list() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- wallet = await response.parse()
- assert_matches_type(WalletListResponse, wallet, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_balance(self, async_client: AsyncWhop) -> None:
- wallet = await async_client.wallets.balance(
- "account_id",
- )
- assert_matches_type(WalletBalanceResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_balance(self, async_client: AsyncWhop) -> None:
- response = await async_client.wallets.with_raw_response.balance(
- "account_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- wallet = await response.parse()
- assert_matches_type(WalletBalanceResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_balance(self, async_client: AsyncWhop) -> None:
- async with async_client.wallets.with_streaming_response.balance(
- "account_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- wallet = await response.parse()
- assert_matches_type(WalletBalanceResponse, wallet, 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_balance(self, async_client: AsyncWhop) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
- await async_client.wallets.with_raw_response.balance(
- "",
- )
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_method_send(self, async_client: AsyncWhop) -> None:
- wallet = await async_client.wallets.send(
- account_id="account_id",
- amount="amount",
- to="to",
- )
- assert_matches_type(WalletSendResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_raw_response_send(self, async_client: AsyncWhop) -> None:
- response = await async_client.wallets.with_raw_response.send(
- account_id="account_id",
- amount="amount",
- to="to",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- wallet = await response.parse()
- assert_matches_type(WalletSendResponse, wallet, path=["response"])
-
- @pytest.mark.skip(reason="Mock server tests are disabled")
- @parametrize
- async def test_streaming_response_send(self, async_client: AsyncWhop) -> None:
- async with async_client.wallets.with_streaming_response.send(
- account_id="account_id",
- amount="amount",
- to="to",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- wallet = await response.parse()
- assert_matches_type(WalletSendResponse, wallet, 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_send(self, async_client: AsyncWhop) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
- await async_client.wallets.with_raw_response.send(
- account_id="",
- amount="amount",
- to="to",
- )
diff --git a/tests/api_resources/test_webhooks.py b/tests/api_resources/test_webhooks.py
index 61e0d357..ab622922 100644
--- a/tests/api_resources/test_webhooks.py
+++ b/tests/api_resources/test_webhooks.py
@@ -272,7 +272,7 @@ def test_method_unwrap(self, client: Whop, client_opt: str | None, method_opt: s
client = client.with_options(webhook_key=client_opt)
- data = """{"id":"msg_xxxxxxxxxxxxxxxxxxxxxxxx","api_version":"v1","data":{"id":"crsli_xxxxxxxxxxxx","completed":true,"course":{"id":"cors_xxxxxxxxxxxxx","experience":{"id":"exp_xxxxxxxxxxxxxx"},"title":"Introduction to Technical Analysis"},"created_at":"2023-12-01T05:00:00.401Z","lesson":{"id":"lesn_xxxxxxxxxxxxx","chapter":{"id":"chap_xxxxxxxxxxxxx"},"title":"Understanding Candlestick Patterns"},"user":{"id":"user_xxxxxxxxxxxxx","name":"John Doe","username":"johndoe42"}},"timestamp":"2025-01-01T00:00:00.000Z","type":"course_lesson_interaction.completed","company_id":"biz_xxxxxxxxxxxxxx"}"""
+ data = """{"id":"msg_xxxxxxxxxxxxxxxxxxxxxxxx","api_version":"v1","data":{"audience":{"type":"channel","user_ids":["user_xxxxxxxxxxxxxx"]},"channel":{"id":"feed_xxxxxxxxxxxxxx","type":"chat","experience_id":"exp_xxxxxxxxxxxxxx"},"message":{"id":"id","content":"Hey, are you available for a **quick call**?","created_at":"2023-12-01T05:00:00.401Z","is_edited":true,"is_pinned":true,"mentions":["string"],"mentions_everyone":true,"message_type":"regular","poll":{"options":[{"id":"id","text":"text"}]},"poll_votes":[{"count":42,"option_id":"option_id"}],"reaction_counts":[{"count":42,"emoji":"emoji"}],"replying_to_message_id":"replying_to_message_id","updated_at":"2023-12-01T05:00:00.401Z","user":{"id":"user_xxxxxxxxxxxxx","name":"John Doe","username":"johndoe42"},"view_count":42},"reason":"channel_message"},"timestamp":"2025-01-01T00:00:00.000Z","type":"chat.message.created","company_id":"biz_xxxxxxxxxxxxxx"}"""
msg_id = "1"
timestamp = datetime.now(tz=timezone.utc)
sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data)
@@ -549,7 +549,7 @@ def test_method_unwrap(self, async_client: Whop, client_opt: str | None, method_
async_client = async_client.with_options(webhook_key=client_opt)
- data = """{"id":"msg_xxxxxxxxxxxxxxxxxxxxxxxx","api_version":"v1","data":{"id":"crsli_xxxxxxxxxxxx","completed":true,"course":{"id":"cors_xxxxxxxxxxxxx","experience":{"id":"exp_xxxxxxxxxxxxxx"},"title":"Introduction to Technical Analysis"},"created_at":"2023-12-01T05:00:00.401Z","lesson":{"id":"lesn_xxxxxxxxxxxxx","chapter":{"id":"chap_xxxxxxxxxxxxx"},"title":"Understanding Candlestick Patterns"},"user":{"id":"user_xxxxxxxxxxxxx","name":"John Doe","username":"johndoe42"}},"timestamp":"2025-01-01T00:00:00.000Z","type":"course_lesson_interaction.completed","company_id":"biz_xxxxxxxxxxxxxx"}"""
+ data = """{"id":"msg_xxxxxxxxxxxxxxxxxxxxxxxx","api_version":"v1","data":{"audience":{"type":"channel","user_ids":["user_xxxxxxxxxxxxxx"]},"channel":{"id":"feed_xxxxxxxxxxxxxx","type":"chat","experience_id":"exp_xxxxxxxxxxxxxx"},"message":{"id":"id","content":"Hey, are you available for a **quick call**?","created_at":"2023-12-01T05:00:00.401Z","is_edited":true,"is_pinned":true,"mentions":["string"],"mentions_everyone":true,"message_type":"regular","poll":{"options":[{"id":"id","text":"text"}]},"poll_votes":[{"count":42,"option_id":"option_id"}],"reaction_counts":[{"count":42,"emoji":"emoji"}],"replying_to_message_id":"replying_to_message_id","updated_at":"2023-12-01T05:00:00.401Z","user":{"id":"user_xxxxxxxxxxxxx","name":"John Doe","username":"johndoe42"},"view_count":42},"reason":"channel_message"},"timestamp":"2025-01-01T00:00:00.000Z","type":"chat.message.created","company_id":"biz_xxxxxxxxxxxxxx"}"""
msg_id = "1"
timestamp = datetime.now(tz=timezone.utc)
sig = hook.sign(msg_id=msg_id, timestamp=timestamp, data=data)