diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba9deff1..b669a2ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/whopsdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -46,7 +46,7 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/whopsdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -65,7 +65,7 @@ jobs: - name: Get GitHub OIDC Token if: github.repository == 'stainless-sdks/whopsdk-python' id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -83,7 +83,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/whopsdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 37d87246..bfa16f2b 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index dde36c96..007e38eb 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'whopio/whopsdk-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f4cb1d13..3d2ac0bd 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.39" + ".": "0.1.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 88c851eb..0308bd5a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 212 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc/whopsdk-da82dade0c316b9abd0320bf7b1b5f3472c265106a1c53ffbb78611eacc16617.yml -openapi_spec_hash: 2454acce3b15eaed1c5ad8554c0d4a2e -config_hash: b4bea15093f9a57475d1d98f9b8464ca +configured_endpoints: 216 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc/whopsdk-77d442782c147823e694535b49ff86e2da9fb6ffc967b4da744515d124542ee0.yml +openapi_spec_hash: 47acea152482ed8697146d2c00952aa7 +config_hash: 64788a41b95ec090d1222da96d7c46d4 diff --git a/CHANGELOG.md b/CHANGELOG.md index bfa4a149..ec03bf53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 0.1.0 (2026-05-21) + +Full Changelog: [v0.0.39...v0.1.0](https://github.com/whopio/whopsdk-python/compare/v0.0.39...v0.1.0) + +### Features + +* **api:** api update ([597a090](https://github.com/whopio/whopsdk-python/commit/597a090c3b9fb3d0c0bcbd2651cd6ed844a531dc)) +* **api:** api update ([f7f9255](https://github.com/whopio/whopsdk-python/commit/f7f92557d76ebcc308c7391784e5274da99dd4ca)) +* **api:** api update ([f24dd5c](https://github.com/whopio/whopsdk-python/commit/f24dd5c1ce252c81c6194563ed0f06146e0723fa)) +* **api:** api update ([4329164](https://github.com/whopio/whopsdk-python/commit/4329164d5d23c20362ee2dad2cab182a2637b449)) +* **api:** api update ([686383a](https://github.com/whopio/whopsdk-python/commit/686383a7a800fdcd2df43f64145d6ef0ab377406)) +* **api:** api update ([d6080a2](https://github.com/whopio/whopsdk-python/commit/d6080a2aff41da44fab43334f3279d8f08a26a70)) +* **api:** api update ([8debdf1](https://github.com/whopio/whopsdk-python/commit/8debdf1e3c142c5c2421351378e54c6379e49b39)) +* **api:** api update ([cdbeba1](https://github.com/whopio/whopsdk-python/commit/cdbeba15f45931f55299108192063c18f3afc17e)) +* **api:** api update ([341bae2](https://github.com/whopio/whopsdk-python/commit/341bae28098d3a4561569ff89a599baf85d25717)) +* **api:** manual updates ([2dff73b](https://github.com/whopio/whopsdk-python/commit/2dff73ba93aa8e9108c0f1fece5ca322246095e0)) + ## 0.0.39 (2026-05-12) Full Changelog: [v0.0.38...v0.0.39](https://github.com/whopio/whopsdk-python/compare/v0.0.38...v0.0.39) diff --git a/api.md b/api.md index 6285ef9b..8fee676c 100644 --- a/api.md +++ b/api.md @@ -811,7 +811,7 @@ Methods: Types: ```python -from whop_sdk.types import UploadStatus, FileCreateResponse, FileRetrieveResponse +from whop_sdk.types import FileVisibility, UploadStatus, FileCreateResponse, FileRetrieveResponse ``` Methods: @@ -1005,22 +1005,16 @@ Methods: Types: ```python -from whop_sdk.types import ( - AdCampaignRetrieveResponse, - AdCampaignUpdateResponse, - AdCampaignListResponse, - AdCampaignPauseResponse, - AdCampaignUnpauseResponse, -) +from whop_sdk.types import AdCampaign, AdCampaignPlatform, AdCampaignStatus, AdCampaignListResponse ``` Methods: -- client.ad_campaigns.retrieve(id) -> AdCampaignRetrieveResponse -- client.ad_campaigns.update(id, \*\*params) -> AdCampaignUpdateResponse +- client.ad_campaigns.retrieve(id) -> AdCampaign +- client.ad_campaigns.update(id, \*\*params) -> AdCampaign - client.ad_campaigns.list(\*\*params) -> SyncCursorPage[AdCampaignListResponse] -- client.ad_campaigns.pause(id) -> AdCampaignPauseResponse -- client.ad_campaigns.unpause(id) -> AdCampaignUnpauseResponse +- client.ad_campaigns.pause(id) -> AdCampaign +- client.ad_campaigns.unpause(id) -> AdCampaign # AdGroups @@ -1028,8 +1022,9 @@ Types: ```python from whop_sdk.types import ( - AdGroupRetrieveResponse, - AdGroupUpdateResponse, + AdBudgetType, + AdGroup, + AdGroupStatus, AdGroupListResponse, AdGroupDeleteResponse, ) @@ -1037,23 +1032,27 @@ from whop_sdk.types import ( Methods: -- client.ad_groups.retrieve(id) -> AdGroupRetrieveResponse -- client.ad_groups.update(id, \*\*params) -> AdGroupUpdateResponse +- client.ad_groups.retrieve(id) -> AdGroup +- client.ad_groups.update(id, \*\*params) -> AdGroup - client.ad_groups.list(\*\*params) -> SyncCursorPage[AdGroupListResponse] - client.ad_groups.delete(id) -> AdGroupDeleteResponse +- client.ad_groups.pause(id) -> AdGroup +- client.ad_groups.unpause(id) -> AdGroup # Ads Types: ```python -from whop_sdk.types import AdRetrieveResponse, AdListResponse +from whop_sdk.types import Ad, ExternalAdStatus, AdListResponse ``` Methods: -- client.ads.retrieve(id) -> AdRetrieveResponse +- client.ads.retrieve(id) -> Ad - client.ads.list(\*\*params) -> SyncCursorPage[AdListResponse] +- client.ads.pause(id) -> Ad +- client.ads.unpause(id) -> Ad # Conversions @@ -1072,7 +1071,7 @@ Methods: Types: ```python -from whop_sdk.types import AdReportRetrieveResponse +from whop_sdk.types import Granularities, ResultLabelKeys, AdReportRetrieveResponse ``` Methods: diff --git a/pyproject.toml b/pyproject.toml index 4846b0bc..9212ce8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "whop-sdk" -version = "0.0.39" +version = "0.1.0" description = "The official Python library for the Whop API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/whop_sdk/_version.py b/src/whop_sdk/_version.py index 4a1fb7f2..162053b4 100644 --- a/src/whop_sdk/_version.py +++ b/src/whop_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "whop_sdk" -__version__ = "0.0.39" # x-release-please-version +__version__ = "0.1.0" # x-release-please-version diff --git a/src/whop_sdk/resources/ad_campaigns.py b/src/whop_sdk/resources/ad_campaigns.py index 9c911f3b..b9dba4d7 100644 --- a/src/whop_sdk/resources/ad_campaigns.py +++ b/src/whop_sdk/resources/ad_campaigns.py @@ -4,11 +4,10 @@ from typing import Union, Optional from datetime import datetime -from typing_extensions import Literal import httpx -from ..types import ad_campaign_list_params, ad_campaign_update_params +from ..types import AdCampaignStatus, ad_campaign_list_params, ad_campaign_update_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,11 +20,9 @@ ) from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options +from ..types.ad_campaign import AdCampaign +from ..types.ad_campaign_status import AdCampaignStatus from ..types.ad_campaign_list_response import AdCampaignListResponse -from ..types.ad_campaign_pause_response import AdCampaignPauseResponse -from ..types.ad_campaign_update_response import AdCampaignUpdateResponse -from ..types.ad_campaign_unpause_response import AdCampaignUnpauseResponse -from ..types.ad_campaign_retrieve_response import AdCampaignRetrieveResponse __all__ = ["AdCampaignsResource", "AsyncAdCampaignsResource"] @@ -62,7 +59,7 @@ def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignRetrieveResponse: + ) -> AdCampaign: """ Retrieves a single ad campaign by its unique identifier. @@ -86,7 +83,7 @@ def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignRetrieveResponse, + cast_to=AdCampaign, ) def update( @@ -100,7 +97,7 @@ def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignUpdateResponse: + ) -> AdCampaign: """ Updates an ad campaign synchronously. @@ -128,7 +125,7 @@ def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignUpdateResponse, + cast_to=AdCampaign, ) def list( @@ -142,7 +139,7 @@ def list( first: Optional[int] | Omit = omit, last: Optional[int] | Omit = omit, query: Optional[str] | Omit = omit, - status: Optional[Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"]] | 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. extra_headers: Headers | None = None, @@ -221,7 +218,7 @@ def pause( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignPauseResponse: + ) -> AdCampaign: """ Pauses an ad campaign, optionally until a specific date. @@ -245,7 +242,7 @@ def pause( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignPauseResponse, + cast_to=AdCampaign, ) def unpause( @@ -258,7 +255,7 @@ def unpause( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignUnpauseResponse: + ) -> AdCampaign: """ Resumes a paused ad campaign. @@ -282,7 +279,7 @@ def unpause( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignUnpauseResponse, + cast_to=AdCampaign, ) @@ -318,7 +315,7 @@ async def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignRetrieveResponse: + ) -> AdCampaign: """ Retrieves a single ad campaign by its unique identifier. @@ -342,7 +339,7 @@ async def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignRetrieveResponse, + cast_to=AdCampaign, ) async def update( @@ -356,7 +353,7 @@ async def update( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignUpdateResponse: + ) -> AdCampaign: """ Updates an ad campaign synchronously. @@ -384,7 +381,7 @@ async def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignUpdateResponse, + cast_to=AdCampaign, ) def list( @@ -398,7 +395,7 @@ def list( first: Optional[int] | Omit = omit, last: Optional[int] | Omit = omit, query: Optional[str] | Omit = omit, - status: Optional[Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"]] | 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. extra_headers: Headers | None = None, @@ -477,7 +474,7 @@ async def pause( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignPauseResponse: + ) -> AdCampaign: """ Pauses an ad campaign, optionally until a specific date. @@ -501,7 +498,7 @@ async def pause( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignPauseResponse, + cast_to=AdCampaign, ) async def unpause( @@ -514,7 +511,7 @@ async def unpause( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdCampaignUnpauseResponse: + ) -> AdCampaign: """ Resumes a paused ad campaign. @@ -538,7 +535,7 @@ async def unpause( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdCampaignUnpauseResponse, + cast_to=AdCampaign, ) diff --git a/src/whop_sdk/resources/ad_groups.py b/src/whop_sdk/resources/ad_groups.py index f52c476d..21834e7c 100644 --- a/src/whop_sdk/resources/ad_groups.py +++ b/src/whop_sdk/resources/ad_groups.py @@ -4,11 +4,10 @@ from typing import Union, Optional from datetime import datetime -from typing_extensions import Literal import httpx -from ..types import ad_group_list_params, ad_group_update_params +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 .._utils import path_template, maybe_transform, async_maybe_transform from .._compat import cached_property @@ -21,10 +20,11 @@ ) 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.ad_group_list_response import AdGroupListResponse from ..types.ad_group_delete_response import AdGroupDeleteResponse -from ..types.ad_group_update_response import AdGroupUpdateResponse -from ..types.ad_group_retrieve_response import AdGroupRetrieveResponse __all__ = ["AdGroupsResource", "AsyncAdGroupsResource"] @@ -61,7 +61,7 @@ def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdGroupRetrieveResponse: + ) -> AdGroup: """ Retrieves a single ad group by its unique identifier. @@ -85,7 +85,7 @@ def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdGroupRetrieveResponse, + cast_to=AdGroup, ) def update( @@ -93,19 +93,19 @@ def update( id: str, *, budget: Optional[float] | Omit = omit, - budget_type: Optional[Literal["daily", "lifetime"]] | 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[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] | 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. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdGroupUpdateResponse: + ) -> AdGroup: """ Updates an existing ad group. @@ -156,7 +156,7 @@ def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdGroupUpdateResponse, + cast_to=AdGroup, ) def list( @@ -171,7 +171,7 @@ def list( first: Optional[int] | Omit = omit, last: Optional[int] | Omit = omit, query: Optional[str] | Omit = omit, - status: Optional[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] | 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. extra_headers: Headers | None = None, @@ -280,6 +280,82 @@ def delete( cast_to=AdGroupDeleteResponse, ) + def pause( + 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, + ) -> AdGroup: + """ + Pauses an ad group. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/ad_groups/{id}/pause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AdGroup, + ) + + def unpause( + 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, + ) -> AdGroup: + """ + Resumes a paused ad group. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/ad_groups/{id}/unpause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AdGroup, + ) + class AsyncAdGroupsResource(AsyncAPIResource): """Ad groups""" @@ -313,7 +389,7 @@ async def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdGroupRetrieveResponse: + ) -> AdGroup: """ Retrieves a single ad group by its unique identifier. @@ -337,7 +413,7 @@ async def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdGroupRetrieveResponse, + cast_to=AdGroup, ) async def update( @@ -345,19 +421,19 @@ async def update( id: str, *, budget: Optional[float] | Omit = omit, - budget_type: Optional[Literal["daily", "lifetime"]] | 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[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] | 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. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdGroupUpdateResponse: + ) -> AdGroup: """ Updates an existing ad group. @@ -408,7 +484,7 @@ async def update( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdGroupUpdateResponse, + cast_to=AdGroup, ) def list( @@ -423,7 +499,7 @@ def list( first: Optional[int] | Omit = omit, last: Optional[int] | Omit = omit, query: Optional[str] | Omit = omit, - status: Optional[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] | 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. extra_headers: Headers | None = None, @@ -532,6 +608,82 @@ async def delete( cast_to=AdGroupDeleteResponse, ) + async def pause( + 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, + ) -> AdGroup: + """ + Pauses an ad group. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/ad_groups/{id}/pause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AdGroup, + ) + + async def unpause( + 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, + ) -> AdGroup: + """ + Resumes a paused ad group. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/ad_groups/{id}/unpause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AdGroup, + ) + class AdGroupsResourceWithRawResponse: def __init__(self, ad_groups: AdGroupsResource) -> None: @@ -549,6 +701,12 @@ def __init__(self, ad_groups: AdGroupsResource) -> None: self.delete = to_raw_response_wrapper( ad_groups.delete, ) + self.pause = to_raw_response_wrapper( + ad_groups.pause, + ) + self.unpause = to_raw_response_wrapper( + ad_groups.unpause, + ) class AsyncAdGroupsResourceWithRawResponse: @@ -567,6 +725,12 @@ def __init__(self, ad_groups: AsyncAdGroupsResource) -> None: self.delete = async_to_raw_response_wrapper( ad_groups.delete, ) + self.pause = async_to_raw_response_wrapper( + ad_groups.pause, + ) + self.unpause = async_to_raw_response_wrapper( + ad_groups.unpause, + ) class AdGroupsResourceWithStreamingResponse: @@ -585,6 +749,12 @@ def __init__(self, ad_groups: AdGroupsResource) -> None: self.delete = to_streamed_response_wrapper( ad_groups.delete, ) + self.pause = to_streamed_response_wrapper( + ad_groups.pause, + ) + self.unpause = to_streamed_response_wrapper( + ad_groups.unpause, + ) class AsyncAdGroupsResourceWithStreamingResponse: @@ -603,3 +773,9 @@ def __init__(self, ad_groups: AsyncAdGroupsResource) -> None: self.delete = async_to_streamed_response_wrapper( ad_groups.delete, ) + self.pause = async_to_streamed_response_wrapper( + ad_groups.pause, + ) + self.unpause = async_to_streamed_response_wrapper( + ad_groups.unpause, + ) diff --git a/src/whop_sdk/resources/ad_reports.py b/src/whop_sdk/resources/ad_reports.py index 380cb9e8..1c8cbd81 100644 --- a/src/whop_sdk/resources/ad_reports.py +++ b/src/whop_sdk/resources/ad_reports.py @@ -4,10 +4,11 @@ from typing import Union, Optional from datetime import datetime +from typing_extensions import Literal import httpx -from ..types import ad_report_retrieve_params +from ..types import Granularities, ad_report_retrieve_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 @@ -19,6 +20,7 @@ async_to_streamed_response_wrapper, ) from .._base_client import make_request_options +from ..types.granularities import Granularities from ..types.ad_report_retrieve_response import AdReportRetrieveResponse __all__ = ["AdReportsResource", "AsyncAdReportsResource"] @@ -54,8 +56,10 @@ def retrieve( ad_campaign_id: Optional[str] | Omit = omit, ad_group_id: Optional[str] | Omit = omit, ad_id: Optional[str] | Omit = omit, + breakdown: Optional[Literal["campaign", "ad_group", "ad"]] | Omit = omit, + company_id: Optional[str] | Omit = omit, currency: Optional[str] | Omit = omit, - include_daily: Optional[bool] | Omit = omit, + granularity: Optional[Granularities] | 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, @@ -63,11 +67,13 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AdReportRetrieveResponse: - """Performance report for an ad campaign, ad group, or ad. + """Performance report for a company, ad campaign, ad group, or ad. - Returns aggregate totals - and an optional per-day breakdown. Exactly one of `adCampaignId`, `adGroupId`, - or `adId` must be provided. + 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. Required permissions: @@ -78,19 +84,25 @@ def retrieve( to: Inclusive end of the reporting window. - ad_campaign_id: The unique identifier of an ad campaign. Mutually exclusive with `adGroupId` and - `adId`. + ad_campaign_id: The unique identifier of an ad campaign. Mutually exclusive with `companyId`, + `adGroupId`, and `adId`. - ad_group_id: The unique identifier of an ad group. Mutually exclusive with `adCampaignId` and - `adId`. + ad_group_id: The unique identifier of an ad group. Mutually exclusive with `companyId`, + `adCampaignId`, and `adId`. - ad_id: The unique identifier of an ad. Mutually exclusive with `adCampaignId` and - `adGroupId`. + ad_id: The unique identifier of an ad. Mutually exclusive with `companyId`, + `adCampaignId`, and `adGroupId`. + + 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. currency: ISO 4217 currency code to report `spend` in. Defaults to the company's ads reporting currency. - include_daily: When true, includes a per-day breakdown alongside the summary. + granularity: Bucket size for external ad stat rows. extra_headers: Send extra headers @@ -114,8 +126,10 @@ def retrieve( "ad_campaign_id": ad_campaign_id, "ad_group_id": ad_group_id, "ad_id": ad_id, + "breakdown": breakdown, + "company_id": company_id, "currency": currency, - "include_daily": include_daily, + "granularity": granularity, }, ad_report_retrieve_params.AdReportRetrieveParams, ), @@ -154,8 +168,10 @@ async def retrieve( ad_campaign_id: Optional[str] | Omit = omit, ad_group_id: Optional[str] | Omit = omit, ad_id: Optional[str] | Omit = omit, + breakdown: Optional[Literal["campaign", "ad_group", "ad"]] | Omit = omit, + company_id: Optional[str] | Omit = omit, currency: Optional[str] | Omit = omit, - include_daily: Optional[bool] | Omit = omit, + granularity: Optional[Granularities] | 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, @@ -163,11 +179,13 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AdReportRetrieveResponse: - """Performance report for an ad campaign, ad group, or ad. + """Performance report for a company, ad campaign, ad group, or ad. - Returns aggregate totals - and an optional per-day breakdown. Exactly one of `adCampaignId`, `adGroupId`, - or `adId` must be provided. + 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. Required permissions: @@ -178,19 +196,25 @@ async def retrieve( to: Inclusive end of the reporting window. - ad_campaign_id: The unique identifier of an ad campaign. Mutually exclusive with `adGroupId` and - `adId`. + ad_campaign_id: The unique identifier of an ad campaign. Mutually exclusive with `companyId`, + `adGroupId`, and `adId`. + + ad_group_id: The unique identifier of an ad group. Mutually exclusive with `companyId`, + `adCampaignId`, and `adId`. + + ad_id: The unique identifier of an ad. Mutually exclusive with `companyId`, + `adCampaignId`, and `adGroupId`. - ad_group_id: The unique identifier of an ad group. Mutually exclusive with `adCampaignId` and - `adId`. + breakdown: Entity level to group an ad report by. - ad_id: The unique identifier of an ad. Mutually exclusive with `adCampaignId` and - `adGroupId`. + 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. currency: ISO 4217 currency code to report `spend` in. Defaults to the company's ads reporting currency. - include_daily: When true, includes a per-day breakdown alongside the summary. + granularity: Bucket size for external ad stat rows. extra_headers: Send extra headers @@ -214,8 +238,10 @@ async def retrieve( "ad_campaign_id": ad_campaign_id, "ad_group_id": ad_group_id, "ad_id": ad_id, + "breakdown": breakdown, + "company_id": company_id, "currency": currency, - "include_daily": include_daily, + "granularity": granularity, }, ad_report_retrieve_params.AdReportRetrieveParams, ), diff --git a/src/whop_sdk/resources/ads.py b/src/whop_sdk/resources/ads.py index 910446f0..883318d6 100644 --- a/src/whop_sdk/resources/ads.py +++ b/src/whop_sdk/resources/ads.py @@ -4,14 +4,14 @@ from typing import Union, Optional from datetime import datetime -from typing_extensions import Literal import httpx -from ..types import ad_list_params +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 .._compat import cached_property +from ..types.ad import Ad from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( to_raw_response_wrapper, @@ -22,7 +22,7 @@ from ..pagination import SyncCursorPage, AsyncCursorPage from .._base_client import AsyncPaginator, make_request_options from ..types.ad_list_response import AdListResponse -from ..types.ad_retrieve_response import AdRetrieveResponse +from ..types.external_ad_status import ExternalAdStatus __all__ = ["AdsResource", "AsyncAdsResource"] @@ -59,7 +59,7 @@ def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdRetrieveResponse: + ) -> Ad: """ Retrieve an ad by its unique identifier. @@ -83,7 +83,7 @@ def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdRetrieveResponse, + cast_to=Ad, ) def list( @@ -98,7 +98,7 @@ def list( created_before: Union[str, datetime, None] | Omit = omit, first: Optional[int] | Omit = omit, last: Optional[int] | Omit = omit, - status: Optional[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] | Omit = omit, + status: Optional[ExternalAdStatus] | 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, @@ -172,6 +172,82 @@ def list( model=AdListResponse, ) + def pause( + 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, + ) -> Ad: + """ + Pauses an ad. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/ads/{id}/pause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Ad, + ) + + def unpause( + 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, + ) -> Ad: + """ + Resumes a paused ad. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/ads/{id}/unpause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Ad, + ) + class AsyncAdsResource(AsyncAPIResource): """Ads""" @@ -205,7 +281,7 @@ async def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AdRetrieveResponse: + ) -> Ad: """ Retrieve an ad by its unique identifier. @@ -229,7 +305,7 @@ async def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=AdRetrieveResponse, + cast_to=Ad, ) def list( @@ -244,7 +320,7 @@ def list( created_before: Union[str, datetime, None] | Omit = omit, first: Optional[int] | Omit = omit, last: Optional[int] | Omit = omit, - status: Optional[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] | Omit = omit, + status: Optional[ExternalAdStatus] | 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, @@ -318,6 +394,82 @@ def list( model=AdListResponse, ) + async def pause( + 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, + ) -> Ad: + """ + Pauses an ad. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/ads/{id}/pause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Ad, + ) + + async def unpause( + 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, + ) -> Ad: + """ + Resumes a paused ad. + + Required permissions: + + - `ad_campaign:update` + - `ad_campaign:basic:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/ads/{id}/unpause", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Ad, + ) + class AdsResourceWithRawResponse: def __init__(self, ads: AdsResource) -> None: @@ -329,6 +481,12 @@ def __init__(self, ads: AdsResource) -> None: self.list = to_raw_response_wrapper( ads.list, ) + self.pause = to_raw_response_wrapper( + ads.pause, + ) + self.unpause = to_raw_response_wrapper( + ads.unpause, + ) class AsyncAdsResourceWithRawResponse: @@ -341,6 +499,12 @@ def __init__(self, ads: AsyncAdsResource) -> None: self.list = async_to_raw_response_wrapper( ads.list, ) + self.pause = async_to_raw_response_wrapper( + ads.pause, + ) + self.unpause = async_to_raw_response_wrapper( + ads.unpause, + ) class AdsResourceWithStreamingResponse: @@ -353,6 +517,12 @@ def __init__(self, ads: AdsResource) -> None: self.list = to_streamed_response_wrapper( ads.list, ) + self.pause = to_streamed_response_wrapper( + ads.pause, + ) + self.unpause = to_streamed_response_wrapper( + ads.unpause, + ) class AsyncAdsResourceWithStreamingResponse: @@ -365,3 +535,9 @@ def __init__(self, ads: AsyncAdsResource) -> None: self.list = async_to_streamed_response_wrapper( ads.list, ) + self.pause = async_to_streamed_response_wrapper( + ads.pause, + ) + self.unpause = async_to_streamed_response_wrapper( + ads.unpause, + ) diff --git a/src/whop_sdk/resources/files.py b/src/whop_sdk/resources/files.py index a27e5e6b..e12ed960 100644 --- a/src/whop_sdk/resources/files.py +++ b/src/whop_sdk/resources/files.py @@ -3,11 +3,10 @@ from __future__ import annotations from typing import Optional -from typing_extensions import Literal import httpx -from ..types import file_create_params +from ..types import FileVisibility, file_create_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 @@ -19,6 +18,7 @@ async_to_streamed_response_wrapper, ) from .._base_client import make_request_options +from ..types.file_visibility import FileVisibility from ..types.file_create_response import FileCreateResponse from ..types.file_retrieve_response import FileRetrieveResponse @@ -49,7 +49,7 @@ def create( self, *, filename: str, - visibility: Optional[Literal["public", "private"]] | Omit = omit, + visibility: Optional[FileVisibility] | 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, @@ -149,7 +149,7 @@ async def create( self, *, filename: str, - visibility: Optional[Literal["public", "private"]] | Omit = omit, + visibility: Optional[FileVisibility] | 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/payments.py b/src/whop_sdk/resources/payments.py index b3435328..207981f5 100644 --- a/src/whop_sdk/resources/payments.py +++ b/src/whop_sdk/resources/payments.py @@ -263,6 +263,7 @@ def list( after: Optional[str] | Omit = omit, before: Optional[str] | Omit = omit, billing_reasons: Optional[List[BillingReasons]] | Omit = omit, + checkout_configuration_ids: Optional[SequenceNotStr[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, @@ -307,6 +308,8 @@ def list( billing_reasons: Filter payments by their billing reason. + checkout_configuration_ids: Only return payments from these checkout configurations. + company_id: The unique identifier of the company to list payments for. created_after: Only return payments created after this timestamp. @@ -362,6 +365,7 @@ def list( "after": after, "before": before, "billing_reasons": billing_reasons, + "checkout_configuration_ids": checkout_configuration_ids, "company_id": company_id, "created_after": created_after, "created_before": created_before, @@ -826,6 +830,7 @@ def list( after: Optional[str] | Omit = omit, before: Optional[str] | Omit = omit, billing_reasons: Optional[List[BillingReasons]] | Omit = omit, + checkout_configuration_ids: Optional[SequenceNotStr[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, @@ -870,6 +875,8 @@ def list( billing_reasons: Filter payments by their billing reason. + checkout_configuration_ids: Only return payments from these checkout configurations. + company_id: The unique identifier of the company to list payments for. created_after: Only return payments created after this timestamp. @@ -925,6 +932,7 @@ def list( "after": after, "before": before, "billing_reasons": billing_reasons, + "checkout_configuration_ids": checkout_configuration_ids, "company_id": company_id, "created_after": created_after, "created_before": created_before, diff --git a/src/whop_sdk/resources/plans.py b/src/whop_sdk/resources/plans.py index 8885f8b6..0ff46a6f 100644 --- a/src/whop_sdk/resources/plans.py +++ b/src/whop_sdk/resources/plans.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Union, Iterable, Optional +from typing import Dict, List, Union, Iterable, Optional from datetime import datetime from typing_extensions import Literal @@ -71,6 +71,7 @@ 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, payment_method_configuration: Optional[plan_create_params.PaymentMethodConfiguration] | Omit = omit, plan_type: Optional[PlanType] | Omit = omit, @@ -132,6 +133,10 @@ def create( 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. + override_tax_type: Whether or not the tax is included in a plan's price (or if it hasn't been set up) @@ -184,6 +189,7 @@ def create( "initial_price": initial_price, "internal_notes": internal_notes, "legacy_payment_method_controls": legacy_payment_method_controls, + "metadata": metadata, "override_tax_type": override_tax_type, "payment_method_configuration": payment_method_configuration, "plan_type": plan_type, @@ -256,6 +262,7 @@ 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, offer_cancel_discount: Optional[bool] | Omit = omit, override_tax_type: Optional[TaxType] | Omit = omit, payment_method_configuration: Optional[plan_update_params.PaymentMethodConfiguration] | Omit = omit, @@ -311,6 +318,10 @@ def update( 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. + 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 @@ -364,6 +375,7 @@ def update( "initial_price": initial_price, "internal_notes": internal_notes, "legacy_payment_method_controls": legacy_payment_method_controls, + "metadata": metadata, "offer_cancel_discount": offer_cancel_discount, "override_tax_type": override_tax_type, "payment_method_configuration": payment_method_configuration, @@ -557,6 +569,7 @@ 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, payment_method_configuration: Optional[plan_create_params.PaymentMethodConfiguration] | Omit = omit, plan_type: Optional[PlanType] | Omit = omit, @@ -618,6 +631,10 @@ async def create( 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. + override_tax_type: Whether or not the tax is included in a plan's price (or if it hasn't been set up) @@ -670,6 +687,7 @@ async def create( "initial_price": initial_price, "internal_notes": internal_notes, "legacy_payment_method_controls": legacy_payment_method_controls, + "metadata": metadata, "override_tax_type": override_tax_type, "payment_method_configuration": payment_method_configuration, "plan_type": plan_type, @@ -742,6 +760,7 @@ 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, offer_cancel_discount: Optional[bool] | Omit = omit, override_tax_type: Optional[TaxType] | Omit = omit, payment_method_configuration: Optional[plan_update_params.PaymentMethodConfiguration] | Omit = omit, @@ -797,6 +816,10 @@ async def update( 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. + 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 @@ -850,6 +873,7 @@ async def update( "initial_price": initial_price, "internal_notes": internal_notes, "legacy_payment_method_controls": legacy_payment_method_controls, + "metadata": metadata, "offer_cancel_discount": offer_cancel_discount, "override_tax_type": override_tax_type, "payment_method_configuration": payment_method_configuration, diff --git a/src/whop_sdk/resources/products.py b/src/whop_sdk/resources/products.py index f2dce526..5c4c4d0d 100644 --- a/src/whop_sdk/resources/products.py +++ b/src/whop_sdk/resources/products.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Union, Iterable, Optional +from typing import Dict, List, Union, Iterable, Optional from datetime import datetime from typing_extensions import Literal @@ -70,6 +70,7 @@ def create( 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, product_tax_code_id: Optional[str] | Omit = omit, redirect_purchase_url: Optional[str] | Omit = omit, @@ -125,6 +126,10 @@ def create( 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. + plan_options: Configuration for an automatically generated plan to attach to this product. product_tax_code_id: The unique identifier of the tax classification code to apply to this product. @@ -163,6 +168,7 @@ def create( "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, @@ -230,6 +236,7 @@ def update( 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, @@ -280,6 +287,10 @@ def update( 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. @@ -320,6 +331,7 @@ def update( "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, @@ -498,6 +510,7 @@ async def create( 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, product_tax_code_id: Optional[str] | Omit = omit, redirect_purchase_url: Optional[str] | Omit = omit, @@ -553,6 +566,10 @@ async def create( 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. + plan_options: Configuration for an automatically generated plan to attach to this product. product_tax_code_id: The unique identifier of the tax classification code to apply to this product. @@ -591,6 +608,7 @@ async def create( "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, @@ -658,6 +676,7 @@ async def update( 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, @@ -708,6 +727,10 @@ async def update( 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. @@ -748,6 +771,7 @@ async def update( "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, diff --git a/src/whop_sdk/resources/refunds.py b/src/whop_sdk/resources/refunds.py index d845816d..7aa67e77 100644 --- a/src/whop_sdk/resources/refunds.py +++ b/src/whop_sdk/resources/refunds.py @@ -64,6 +64,8 @@ def retrieve( Required permissions: - `payment:basic:read` + - `plan:basic:read` + - `access_pass:basic:read` - `member:email:read` - `member:basic:read` - `member:phone:read` @@ -209,6 +211,8 @@ async def retrieve( Required permissions: - `payment:basic:read` + - `plan:basic:read` + - `access_pass:basic:read` - `member:email:read` - `member:basic:read` - `member:phone:read` diff --git a/src/whop_sdk/types/__init__.py b/src/whop_sdk/types/__init__.py index 3329ac6f..727b2d2e 100644 --- a/src/whop_sdk/types/__init__.py +++ b/src/whop_sdk/types/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .ad import Ad as Ad from .lead import Lead as Lead from .user import User as User from .course import Course as Course @@ -70,6 +71,7 @@ from .ai_chat import AIChat as AIChat from .dispute import Dispute as Dispute from .webhook import Webhook as Webhook +from .ad_group import AdGroup as AdGroup from .app_type import AppType as AppType from .affiliate import Affiliate as Affiliate from .dm_member import DmMember as DmMember @@ -78,25 +80,30 @@ from .embed_type import EmbedType as EmbedType from .promo_code import PromoCode as PromoCode from .withdrawal import Withdrawal as Withdrawal +from .ad_campaign import AdCampaign as AdCampaign from .api_version import APIVersion as APIVersion from .card_brands import CardBrands as CardBrands from .lesson_types import LessonTypes as LessonTypes from .setup_intent import SetupIntent as SetupIntent from .checkout_font import CheckoutFont as CheckoutFont +from .granularities import Granularities as Granularities from .refund_status import RefundStatus as RefundStatus from .review_status import ReviewStatus as ReviewStatus from .upload_status import UploadStatus as UploadStatus from .webhook_event import WebhookEvent as WebhookEvent +from .ad_budget_type import AdBudgetType as AdBudgetType from .ad_list_params import AdListParams as AdListParams from .cancel_options import CancelOptions as CancelOptions from .checkout_modes import CheckoutModes as CheckoutModes from .checkout_shape import CheckoutShape as CheckoutShape from .course_chapter import CourseChapter as CourseChapter from .promo_duration import PromoDuration as PromoDuration +from .ad_group_status import AdGroupStatus as AdGroupStatus from .app_list_params import AppListParams as AppListParams from .authorized_user import AuthorizedUser as AuthorizedUser from .billing_reasons import BillingReasons as BillingReasons from .fee_markup_type import FeeMarkupType as FeeMarkupType +from .file_visibility import FileVisibility as FileVisibility from .ad_list_response import AdListResponse as AdListResponse from .dispute_statuses import DisputeStatuses as DisputeStatuses from .lead_list_params import LeadListParams as LeadListParams @@ -109,11 +116,14 @@ from .entry_list_params import EntryListParams as EntryListParams from .forum_list_params import ForumListParams as ForumListParams from .promo_code_status import PromoCodeStatus as PromoCodeStatus +from .result_label_keys import ResultLabelKeys as ResultLabelKeys from .withdrawal_speeds import WithdrawalSpeeds as WithdrawalSpeeds from .withdrawal_status import WithdrawalStatus as WithdrawalStatus +from .ad_campaign_status import AdCampaignStatus as AdCampaignStatus from .bounty_list_params import BountyListParams as BountyListParams from .course_list_params import CourseListParams as CourseListParams from .dispute_alert_type import DisputeAlertType as DisputeAlertType +from .external_ad_status import ExternalAdStatus as ExternalAdStatus from .file_create_params import FileCreateParams as FileCreateParams from .lead_create_params import LeadCreateParams as LeadCreateParams from .lead_list_response import LeadListResponse as LeadListResponse @@ -143,8 +153,8 @@ from .topup_create_params import TopupCreateParams as TopupCreateParams from .verification_status import VerificationStatus as VerificationStatus from .webhook_list_params import WebhookListParams as WebhookListParams +from .ad_campaign_platform import AdCampaignPlatform as AdCampaignPlatform from .ad_group_list_params import AdGroupListParams as AdGroupListParams -from .ad_retrieve_response import AdRetrieveResponse as AdRetrieveResponse from .bounty_create_params import BountyCreateParams as BountyCreateParams from .bounty_list_response import BountyListResponse as BountyListResponse from .course_create_params import CourseCreateParams as CourseCreateParams @@ -229,7 +239,6 @@ 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_update_response import AdGroupUpdateResponse as AdGroupUpdateResponse 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 @@ -272,8 +281,6 @@ from .payout_method_list_params import PayoutMethodListParams as PayoutMethodListParams from .access_token_create_params import AccessTokenCreateParams as AccessTokenCreateParams from .account_link_create_params import AccountLinkCreateParams as AccountLinkCreateParams -from .ad_campaign_pause_response import AdCampaignPauseResponse as AdCampaignPauseResponse -from .ad_group_retrieve_response import AdGroupRetrieveResponse as AdGroupRetrieveResponse from .affiliate_archive_response import AffiliateArchiveResponse as AffiliateArchiveResponse from .chat_channel_list_response import ChatChannelListResponse as ChatChannelListResponse from .chat_channel_update_params import ChatChannelUpdateParams as ChatChannelUpdateParams @@ -295,7 +302,6 @@ from .setup_intent_list_response import SetupIntentListResponse as SetupIntentListResponse from .user_check_access_response import UserCheckAccessResponse as UserCheckAccessResponse from .verification_list_response import VerificationListResponse as VerificationListResponse -from .ad_campaign_update_response import AdCampaignUpdateResponse as AdCampaignUpdateResponse 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 @@ -310,7 +316,6 @@ from .support_channel_list_params import SupportChannelListParams as SupportChannelListParams from .access_token_create_response import AccessTokenCreateResponse as AccessTokenCreateResponse from .account_link_create_response import AccountLinkCreateResponse as AccountLinkCreateResponse -from .ad_campaign_unpause_response import AdCampaignUnpauseResponse as AdCampaignUnpauseResponse from .affiliate_unarchive_response import AffiliateUnarchiveResponse as AffiliateUnarchiveResponse from .course_chapter_create_params import CourseChapterCreateParams as CourseChapterCreateParams from .course_chapter_list_response import CourseChapterListResponse as CourseChapterListResponse @@ -324,7 +329,6 @@ 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 .ad_campaign_retrieve_response import AdCampaignRetrieveResponse as AdCampaignRetrieveResponse 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 diff --git a/src/whop_sdk/types/ad_retrieve_response.py b/src/whop_sdk/types/ad.py similarity index 80% rename from src/whop_sdk/types/ad_retrieve_response.py rename to src/whop_sdk/types/ad.py index b7f9897c..e2a1a0bd 100644 --- a/src/whop_sdk/types/ad_retrieve_response.py +++ b/src/whop_sdk/types/ad.py @@ -2,11 +2,12 @@ from typing import Optional from datetime import datetime -from typing_extensions import Literal from .._models import BaseModel +from .external_ad_status import ExternalAdStatus +from .ad_campaign_platform import AdCampaignPlatform -__all__ = ["AdRetrieveResponse", "AdCampaign", "AdGroup"] +__all__ = ["Ad", "AdCampaign", "AdGroup"] class AdCampaign(BaseModel): @@ -23,7 +24,7 @@ class AdGroup(BaseModel): """The unique identifier for this ad group.""" -class AdRetrieveResponse(BaseModel): +class Ad(BaseModel): """An ad belonging to an ad group.""" id: str @@ -38,10 +39,10 @@ class AdRetrieveResponse(BaseModel): created_at: datetime """When the ad was created.""" - platform: Literal["meta", "tiktok"] + platform: AdCampaignPlatform """The external ad platform this ad is running on (e.g., meta, tiktok).""" - status: Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"] + status: ExternalAdStatus """Current delivery status of the ad.""" title: Optional[str] = None diff --git a/src/whop_sdk/types/ad_budget_type.py b/src/whop_sdk/types/ad_budget_type.py new file mode 100644 index 00000000..d3eee5dd --- /dev/null +++ b/src/whop_sdk/types/ad_budget_type.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["AdBudgetType"] + +AdBudgetType: TypeAlias = Literal["daily", "lifetime"] diff --git a/src/whop_sdk/types/ad_campaign_pause_response.py b/src/whop_sdk/types/ad_campaign.py similarity index 89% rename from src/whop_sdk/types/ad_campaign_pause_response.py rename to src/whop_sdk/types/ad_campaign.py index 125620f3..6d201157 100644 --- a/src/whop_sdk/types/ad_campaign_pause_response.py +++ b/src/whop_sdk/types/ad_campaign.py @@ -5,8 +5,11 @@ from typing_extensions import Literal from .._models import BaseModel +from .ad_budget_type import AdBudgetType +from .ad_campaign_status import AdCampaignStatus +from .ad_campaign_platform import AdCampaignPlatform -__all__ = ["AdCampaignPauseResponse", "CreatedByUser", "MetaConfig"] +__all__ = ["AdCampaign", "CreatedByUser", "MetaConfig"] class CreatedByUser(BaseModel): @@ -65,7 +68,7 @@ class MetaConfig(BaseModel): """The campaign status as set by the advertiser (active or paused).""" -class AdCampaignPauseResponse(BaseModel): +class AdCampaign(BaseModel): """An advertising campaign running on an external platform or within Whop.""" id: str @@ -74,7 +77,7 @@ class AdCampaignPauseResponse(BaseModel): budget: Optional[float] = None """Total budget in dollars.""" - budget_type: Optional[Literal["daily", "lifetime"]] = None + budget_type: Optional[AdBudgetType] = None """The budget type for an ad campaign or ad group.""" created_at: datetime @@ -89,10 +92,10 @@ class AdCampaignPauseResponse(BaseModel): Null for non-Meta campaigns. """ - platform: Literal["meta", "tiktok"] + platform: AdCampaignPlatform """The external ad platform this campaign is running on (e.g., meta, tiktok).""" - status: Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"] + status: AdCampaignStatus """Current status of the campaign (active, paused, or inactive).""" title: str diff --git a/src/whop_sdk/types/ad_campaign_list_params.py b/src/whop_sdk/types/ad_campaign_list_params.py index 9f983f7d..021afde0 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 Literal, Required, Annotated, TypedDict +from typing_extensions import Required, Annotated, TypedDict from .._utils import PropertyInfo +from .ad_campaign_status import AdCampaignStatus __all__ = ["AdCampaignListParams"] @@ -36,5 +37,5 @@ class AdCampaignListParams(TypedDict, total=False): query: Optional[str] """Case-insensitive substring match against the campaign title.""" - status: Optional[Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"]] + 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 e99ca67a..7123408d 100644 --- a/src/whop_sdk/types/ad_campaign_list_response.py +++ b/src/whop_sdk/types/ad_campaign_list_response.py @@ -2,9 +2,11 @@ from typing import Optional from datetime import datetime -from typing_extensions import Literal from .._models import BaseModel +from .ad_budget_type import AdBudgetType +from .ad_campaign_status import AdCampaignStatus +from .ad_campaign_platform import AdCampaignPlatform __all__ = ["AdCampaignListResponse"] @@ -18,16 +20,16 @@ class AdCampaignListResponse(BaseModel): budget: Optional[float] = None """Total budget in dollars.""" - budget_type: Optional[Literal["daily", "lifetime"]] = None + budget_type: Optional[AdBudgetType] = None """The budget type for an ad campaign or ad group.""" created_at: datetime """When the ad campaign was created.""" - platform: Literal["meta", "tiktok"] + platform: AdCampaignPlatform """The external ad platform this campaign is running on (e.g., meta, tiktok).""" - status: Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"] + status: AdCampaignStatus """Current status of the campaign (active, paused, or inactive).""" title: str diff --git a/src/whop_sdk/types/ad_campaign_platform.py b/src/whop_sdk/types/ad_campaign_platform.py new file mode 100644 index 00000000..1e841130 --- /dev/null +++ b/src/whop_sdk/types/ad_campaign_platform.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["AdCampaignPlatform"] + +AdCampaignPlatform: TypeAlias = Literal["meta", "tiktok"] diff --git a/src/whop_sdk/types/ad_campaign_retrieve_response.py b/src/whop_sdk/types/ad_campaign_retrieve_response.py deleted file mode 100644 index 372ceba0..00000000 --- a/src/whop_sdk/types/ad_campaign_retrieve_response.py +++ /dev/null @@ -1,105 +0,0 @@ -# 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__ = ["AdCampaignRetrieveResponse", "CreatedByUser", "MetaConfig"] - - -class CreatedByUser(BaseModel): - """The user who created this ad campaign.""" - - id: str - """The unique identifier for the user.""" - - name: Optional[str] = None - """The user's display name shown on their public profile.""" - - username: str - """The user's unique username shown on their public profile.""" - - -class MetaConfig(BaseModel): - """Meta-specific campaign configuration (objective, budget mode, etc.). - - Null for non-Meta campaigns. - """ - - bid_amount: Optional[int] = None - """Bid cap amount in cents. Only used when bid_strategy is bid_cap.""" - - 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. - """ - - 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.""" - - special_categories: Optional[List[str]] = None - """ - 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 AdCampaignRetrieveResponse(BaseModel): - """An advertising campaign running on an external platform or within Whop.""" - - id: str - """The unique identifier for this ad campaign.""" - - budget: Optional[float] = None - """Total budget in dollars.""" - - budget_type: Optional[Literal["daily", "lifetime"]] = None - """The budget type for an ad campaign or ad group.""" - - created_at: datetime - """When the ad campaign was created.""" - - created_by_user: CreatedByUser - """The user who created this ad campaign.""" - - meta_config: Optional[MetaConfig] = None - """Meta-specific campaign configuration (objective, budget mode, etc.). - - Null for non-Meta campaigns. - """ - - platform: Literal["meta", "tiktok"] - """The external ad platform this campaign is running on (e.g., meta, tiktok).""" - - status: Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"] - """Current status of the campaign (active, paused, or inactive).""" - - title: str - """The campaign name shown in the Whop dashboard.""" - - total_spend: float - """Total amount spent in dollars.""" - - updated_at: datetime - """When the ad campaign was last updated.""" diff --git a/src/whop_sdk/types/ad_campaign_status.py b/src/whop_sdk/types/ad_campaign_status.py new file mode 100644 index 00000000..ddfbdf4e --- /dev/null +++ b/src/whop_sdk/types/ad_campaign_status.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["AdCampaignStatus"] + +AdCampaignStatus: TypeAlias = Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"] diff --git a/src/whop_sdk/types/ad_campaign_unpause_response.py b/src/whop_sdk/types/ad_campaign_unpause_response.py deleted file mode 100644 index dd83dea4..00000000 --- a/src/whop_sdk/types/ad_campaign_unpause_response.py +++ /dev/null @@ -1,105 +0,0 @@ -# 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__ = ["AdCampaignUnpauseResponse", "CreatedByUser", "MetaConfig"] - - -class CreatedByUser(BaseModel): - """The user who created this ad campaign.""" - - id: str - """The unique identifier for the user.""" - - name: Optional[str] = None - """The user's display name shown on their public profile.""" - - username: str - """The user's unique username shown on their public profile.""" - - -class MetaConfig(BaseModel): - """Meta-specific campaign configuration (objective, budget mode, etc.). - - Null for non-Meta campaigns. - """ - - bid_amount: Optional[int] = None - """Bid cap amount in cents. Only used when bid_strategy is bid_cap.""" - - 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. - """ - - 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.""" - - special_categories: Optional[List[str]] = None - """ - 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 AdCampaignUnpauseResponse(BaseModel): - """An advertising campaign running on an external platform or within Whop.""" - - id: str - """The unique identifier for this ad campaign.""" - - budget: Optional[float] = None - """Total budget in dollars.""" - - budget_type: Optional[Literal["daily", "lifetime"]] = None - """The budget type for an ad campaign or ad group.""" - - created_at: datetime - """When the ad campaign was created.""" - - created_by_user: CreatedByUser - """The user who created this ad campaign.""" - - meta_config: Optional[MetaConfig] = None - """Meta-specific campaign configuration (objective, budget mode, etc.). - - Null for non-Meta campaigns. - """ - - platform: Literal["meta", "tiktok"] - """The external ad platform this campaign is running on (e.g., meta, tiktok).""" - - status: Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"] - """Current status of the campaign (active, paused, or inactive).""" - - title: str - """The campaign name shown in the Whop dashboard.""" - - total_spend: float - """Total amount spent in dollars.""" - - updated_at: datetime - """When the ad campaign was last updated.""" diff --git a/src/whop_sdk/types/ad_campaign_update_response.py b/src/whop_sdk/types/ad_campaign_update_response.py deleted file mode 100644 index b7f5c437..00000000 --- a/src/whop_sdk/types/ad_campaign_update_response.py +++ /dev/null @@ -1,105 +0,0 @@ -# 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__ = ["AdCampaignUpdateResponse", "CreatedByUser", "MetaConfig"] - - -class CreatedByUser(BaseModel): - """The user who created this ad campaign.""" - - id: str - """The unique identifier for the user.""" - - name: Optional[str] = None - """The user's display name shown on their public profile.""" - - username: str - """The user's unique username shown on their public profile.""" - - -class MetaConfig(BaseModel): - """Meta-specific campaign configuration (objective, budget mode, etc.). - - Null for non-Meta campaigns. - """ - - bid_amount: Optional[int] = None - """Bid cap amount in cents. Only used when bid_strategy is bid_cap.""" - - 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. - """ - - 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.""" - - special_categories: Optional[List[str]] = None - """ - 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 AdCampaignUpdateResponse(BaseModel): - """An advertising campaign running on an external platform or within Whop.""" - - id: str - """The unique identifier for this ad campaign.""" - - budget: Optional[float] = None - """Total budget in dollars.""" - - budget_type: Optional[Literal["daily", "lifetime"]] = None - """The budget type for an ad campaign or ad group.""" - - created_at: datetime - """When the ad campaign was created.""" - - created_by_user: CreatedByUser - """The user who created this ad campaign.""" - - meta_config: Optional[MetaConfig] = None - """Meta-specific campaign configuration (objective, budget mode, etc.). - - Null for non-Meta campaigns. - """ - - platform: Literal["meta", "tiktok"] - """The external ad platform this campaign is running on (e.g., meta, tiktok).""" - - status: Literal["active", "paused", "payment_failed", "draft", "in_review", "flagged"] - """Current status of the campaign (active, paused, or inactive).""" - - title: str - """The campaign name shown in the Whop dashboard.""" - - total_spend: float - """Total amount spent in dollars.""" - - updated_at: datetime - """When the ad campaign was last updated.""" diff --git a/src/whop_sdk/types/ad_group_update_response.py b/src/whop_sdk/types/ad_group.py similarity index 76% rename from src/whop_sdk/types/ad_group_update_response.py rename to src/whop_sdk/types/ad_group.py index 5a079222..384dbf5f 100644 --- a/src/whop_sdk/types/ad_group_update_response.py +++ b/src/whop_sdk/types/ad_group.py @@ -2,11 +2,13 @@ from typing import 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 .ad_campaign_platform import AdCampaignPlatform -__all__ = ["AdGroupUpdateResponse", "AdCampaign"] +__all__ = ["AdGroup", "AdCampaign"] class AdCampaign(BaseModel): @@ -16,7 +18,7 @@ class AdCampaign(BaseModel): """The unique identifier for this ad campaign.""" -class AdGroupUpdateResponse(BaseModel): +class AdGroup(BaseModel): """An ad group (ad set) belonging to an ad campaign.""" id: str @@ -28,16 +30,16 @@ class AdGroupUpdateResponse(BaseModel): budget: Optional[float] = None """Budget amount in dollars.""" - budget_type: Optional[Literal["daily", "lifetime"]] = None + budget_type: Optional[AdBudgetType] = None """The budget type for an ad campaign or ad group.""" created_at: datetime """When the ad group was created.""" - platform: Literal["meta", "tiktok"] + platform: AdCampaignPlatform """The external ad platform this ad group is running on (e.g., meta, tiktok).""" - status: Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"] + status: AdGroupStatus """Current operational status of the ad group.""" title: Optional[str] = None diff --git a/src/whop_sdk/types/ad_group_list_params.py b/src/whop_sdk/types/ad_group_list_params.py index cde96fb8..05757db0 100644 --- a/src/whop_sdk/types/ad_group_list_params.py +++ b/src/whop_sdk/types/ad_group_list_params.py @@ -4,9 +4,10 @@ from typing import Union, Optional from datetime import datetime -from typing_extensions import Literal, Annotated, TypedDict +from typing_extensions import Annotated, TypedDict from .._utils import PropertyInfo +from .ad_group_status import AdGroupStatus __all__ = ["AdGroupListParams"] @@ -39,5 +40,5 @@ class AdGroupListParams(TypedDict, total=False): query: Optional[str] """Case-insensitive substring match against the ad group name.""" - status: Optional[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] + 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 093da1e8..dac01854 100644 --- a/src/whop_sdk/types/ad_group_list_response.py +++ b/src/whop_sdk/types/ad_group_list_response.py @@ -2,11 +2,20 @@ from typing import 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 .ad_campaign_platform import AdCampaignPlatform -__all__ = ["AdGroupListResponse"] +__all__ = ["AdGroupListResponse", "AdCampaign"] + + +class AdCampaign(BaseModel): + """The ad campaign this ad group belongs to.""" + + id: str + """The unique identifier for this ad campaign.""" class AdGroupListResponse(BaseModel): @@ -15,19 +24,22 @@ class AdGroupListResponse(BaseModel): id: str """The unique identifier for this ad group.""" + ad_campaign: AdCampaign + """The ad campaign this ad group belongs to.""" + budget: Optional[float] = None """Budget amount in dollars.""" - budget_type: Optional[Literal["daily", "lifetime"]] = None + budget_type: Optional[AdBudgetType] = None """The budget type for an ad campaign or ad group.""" created_at: datetime """When the ad group was created.""" - platform: Literal["meta", "tiktok"] + platform: AdCampaignPlatform """The external ad platform this ad group is running on (e.g., meta, tiktok).""" - status: Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"] + status: AdGroupStatus """Current operational status of the ad group.""" title: Optional[str] = None diff --git a/src/whop_sdk/types/ad_group_retrieve_response.py b/src/whop_sdk/types/ad_group_retrieve_response.py deleted file mode 100644 index 7b447725..00000000 --- a/src/whop_sdk/types/ad_group_retrieve_response.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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__ = ["AdGroupRetrieveResponse", "AdCampaign"] - - -class AdCampaign(BaseModel): - """The ad campaign this ad group belongs to.""" - - id: str - """The unique identifier for this ad campaign.""" - - -class AdGroupRetrieveResponse(BaseModel): - """An ad group (ad set) belonging to an ad campaign.""" - - id: str - """The unique identifier for this ad group.""" - - ad_campaign: AdCampaign - """The ad campaign this ad group belongs to.""" - - budget: Optional[float] = None - """Budget amount in dollars.""" - - budget_type: Optional[Literal["daily", "lifetime"]] = None - """The budget type for an ad campaign or ad group.""" - - created_at: datetime - """When the ad group was created.""" - - platform: Literal["meta", "tiktok"] - """The external ad platform this ad group is running on (e.g., meta, tiktok).""" - - status: Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"] - """Current operational status of the ad group.""" - - title: Optional[str] = None - """Human-readable name shown on the external platform.""" - - updated_at: datetime - """When the ad group was last updated.""" diff --git a/src/whop_sdk/types/ad_group_status.py b/src/whop_sdk/types/ad_group_status.py new file mode 100644 index 00000000..625dbfda --- /dev/null +++ b/src/whop_sdk/types/ad_group_status.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["AdGroupStatus"] + +AdGroupStatus: TypeAlias = Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"] diff --git a/src/whop_sdk/types/ad_group_update_params.py b/src/whop_sdk/types/ad_group_update_params.py index bb7e7265..d97cab88 100644 --- a/src/whop_sdk/types/ad_group_update_params.py +++ b/src/whop_sdk/types/ad_group_update_params.py @@ -6,6 +6,8 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr +from .ad_budget_type import AdBudgetType +from .ad_group_status import AdGroupStatus __all__ = [ "AdGroupUpdateParams", @@ -46,7 +48,7 @@ class AdGroupUpdateParams(TypedDict, total=False): budget: Optional[float] """Budget amount in dollars.""" - budget_type: Optional[Literal["daily", "lifetime"]] + budget_type: Optional[AdBudgetType] """The budget type for an ad campaign or ad group.""" config: Optional[Config] @@ -61,7 +63,7 @@ class AdGroupUpdateParams(TypedDict, total=False): platform_config: Optional[PlatformConfig] """Platform-specific ad group configuration.""" - status: Optional[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] + status: Optional[AdGroupStatus] """The status of an external ad group.""" diff --git a/src/whop_sdk/types/ad_list_params.py b/src/whop_sdk/types/ad_list_params.py index 17c36e1b..febd6591 100644 --- a/src/whop_sdk/types/ad_list_params.py +++ b/src/whop_sdk/types/ad_list_params.py @@ -4,9 +4,10 @@ from typing import Union, Optional from datetime import datetime -from typing_extensions import Literal, Annotated, TypedDict +from typing_extensions import Annotated, TypedDict from .._utils import PropertyInfo +from .external_ad_status import ExternalAdStatus __all__ = ["AdListParams"] @@ -48,5 +49,5 @@ class AdListParams(TypedDict, total=False): last: Optional[int] """Returns the last _n_ elements from the list.""" - status: Optional[Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"]] + 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 2982e4b1..f6a13bac 100644 --- a/src/whop_sdk/types/ad_list_response.py +++ b/src/whop_sdk/types/ad_list_response.py @@ -2,11 +2,26 @@ from typing import Optional from datetime import datetime -from typing_extensions import Literal from .._models import BaseModel +from .external_ad_status import ExternalAdStatus +from .ad_campaign_platform import AdCampaignPlatform -__all__ = ["AdListResponse"] +__all__ = ["AdListResponse", "AdCampaign", "AdGroup"] + + +class AdCampaign(BaseModel): + """The ad campaign this ad belongs to.""" + + id: str + """The unique identifier for this ad campaign.""" + + +class AdGroup(BaseModel): + """The parent ad group this ad belongs to.""" + + id: str + """The unique identifier for this ad group.""" class AdListResponse(BaseModel): @@ -15,13 +30,19 @@ class AdListResponse(BaseModel): id: str """The unique identifier for this ad.""" + ad_campaign: AdCampaign + """The ad campaign this ad belongs to.""" + + ad_group: AdGroup + """The parent ad group this ad belongs to.""" + created_at: datetime """When the ad was created.""" - platform: Literal["meta", "tiktok"] + platform: AdCampaignPlatform """The external ad platform this ad is running on (e.g., meta, tiktok).""" - status: Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"] + status: ExternalAdStatus """Current delivery status of the ad.""" title: Optional[str] = None diff --git a/src/whop_sdk/types/ad_report_retrieve_params.py b/src/whop_sdk/types/ad_report_retrieve_params.py index 87fe683c..9a779523 100644 --- a/src/whop_sdk/types/ad_report_retrieve_params.py +++ b/src/whop_sdk/types/ad_report_retrieve_params.py @@ -4,9 +4,10 @@ from typing import Union, Optional from datetime import datetime -from typing_extensions import Required, Annotated, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo +from .granularities import Granularities __all__ = ["AdReportRetrieveParams"] @@ -21,19 +22,30 @@ class AdReportRetrieveParams(TypedDict, total=False): ad_campaign_id: Optional[str] """The unique identifier of an ad campaign. - Mutually exclusive with `adGroupId` and `adId`. + Mutually exclusive with `companyId`, `adGroupId`, and `adId`. """ ad_group_id: Optional[str] """The unique identifier of an ad group. - Mutually exclusive with `adCampaignId` and `adId`. + Mutually exclusive with `companyId`, `adCampaignId`, and `adId`. """ ad_id: Optional[str] """The unique identifier of an ad. - Mutually exclusive with `adCampaignId` and `adGroupId`. + Mutually exclusive with `companyId`, `adCampaignId`, and `adGroupId`. + """ + + breakdown: Optional[Literal["campaign", "ad_group", "ad"]] + """Entity level to group an ad report by.""" + + company_id: Optional[str] + """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. """ currency: Optional[str] @@ -42,5 +54,5 @@ class AdReportRetrieveParams(TypedDict, total=False): Defaults to the company's ads reporting currency. """ - include_daily: Optional[bool] - """When true, includes a per-day breakdown alongside the summary.""" + granularity: Optional[Granularities] + """Bucket size for external ad stat rows.""" diff --git a/src/whop_sdk/types/ad_report_retrieve_response.py b/src/whop_sdk/types/ad_report_retrieve_response.py index 9aaf6599..56bf2ef4 100644 --- a/src/whop_sdk/types/ad_report_retrieve_response.py +++ b/src/whop_sdk/types/ad_report_retrieve_response.py @@ -5,54 +5,52 @@ from typing_extensions import Literal from .._models import BaseModel +from .granularities import Granularities from .shared.currency import Currency +from .result_label_keys import ResultLabelKeys -__all__ = ["AdReportRetrieveResponse", "Daily", "Summary"] +__all__ = [ + "AdReportRetrieveResponse", + "Breakdown", + "BreakdownGranularity", + "BreakdownSummary", + "Granularity", + "Summary", +] -class Daily(BaseModel): - """Per-day ad performance for an ad campaign, ad group, or ad.""" +class BreakdownGranularity(BaseModel): + """Per-bucket ad performance for an ad campaign, ad group, or ad. + + Bucket grain is set by the `ad_report` query's `granularity` argument. + """ + + bucket_start: datetime + """The bucket's start time as a real UTC instant. + + `(statDate, statHour)` resolved in the ad account's reporting timezone — render + this in the viewer's local timezone. + """ clicks: int - """Clicks on this date.""" + """Clicks in this bucket.""" + + granularity: Granularities + """The bucket size of this row (`daily` or `hourly`).""" impressions: int - """Impressions on this date.""" + """Impressions in this bucket.""" reach: int - """Unique users reached on this date.""" + """Unique users reached in this bucket. + + Always `0` for hourly rows (Meta does not return reach at hourly grain). + """ result_count: Optional[int] = None - """Count of the primary optimization result on this date.""" - - result_label_key: Optional[ - Literal[ - "app_installs", - "messaging_conversations_started", - "post_engagement", - "event_responses", - "impressions", - "website_purchases", - "landing_page_views", - "leads", - "link_clicks", - "quality_calls", - "appointments_booked", - "messaging_purchases", - "page_likes", - "instagram_profile_visits", - "reach", - "reminders_set", - "new_subscribers", - "video_views", - "registrations", - "content_views", - "searches", - "website_schedules", - "website_submit_applications", - "custom", - ] - ] = None + """Count of the primary optimization result in this bucket.""" + + result_label_key: Optional[ResultLabelKeys] = None """Types of optimization results tracked from external ad platforms""" result_label_override: Optional[str] = None @@ -60,7 +58,7 @@ class Daily(BaseModel): spend: float """ - Charged spend on this date in the requested reporting currency — the amount + Charged spend in this bucket in the requested reporting currency — the amount billed including platform fees, not the platform-side net spend. """ @@ -68,7 +66,153 @@ class Daily(BaseModel): """Currency of the `spend` value.""" stat_date: datetime - """The date these stats cover (midnight UTC).""" + """The date these stats cover (midnight UTC). + + For hourly rows, see `statHour` and `bucketStart`. + """ + + stat_hour: Optional[int] = None + """Hour of the day in the ad account's reporting timezone (0-23). + + `null` for daily rows. + """ + + +class BreakdownSummary(BaseModel): + """Aggregate totals and rates for this entity over the date range.""" + + 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 in the requested reporting currency.""" + + cpm: Optional[float] = None + """Cost per thousand impressions in the requested reporting currency.""" + + ctr: float + """Click-through rate (clicks / impressions).""" + + frequency: Optional[float] = None + """Average number of times each reached user saw an ad.""" + + impressions: int + """Total impressions over the date range.""" + + reach: int + """Unique users reached, deduplicated by the external ad platform.""" + + result_count: Optional[int] = None + """ + Count of the campaign's primary optimization result (purchases, clicks, etc.) — + see `resultLabelKey`. + """ + + result_label_key: Optional[ResultLabelKeys] = None + """Types of optimization results tracked from external ad platforms""" + + result_label_override: Optional[str] = None + """Advertiser-defined label for the result when `resultLabelKey` is `custom`.""" + + roas: Optional[float] = None + """ + Alias for `purchaseRoas` — return on ad spend for purchases, as reported by the + external ad platform. + """ + + spend: float + """Total spend over the date range in the requested reporting currency.""" + + spend_currency: Optional[Currency] = None + """The available currencies on the platform""" + + +class Breakdown(BaseModel): + """Per-entity ad performance row. + + Returned when the `breakdown` arg on `adReport` is set. + """ + + id: str + """Tag of the entity (ad campaign, ad group, or ad).""" + + granularity: Optional[List[BreakdownGranularity]] = None + """ + Per-bucket time series for this entity over the date range, ordered ascending by + `bucketStart`. `null` when the `granularity` arg on `adReport` is omitted; + otherwise contains rows at the requested grain (`daily` or `hourly`). + """ + + level: Literal["campaign", "ad_group", "ad"] + """The entity level of this row — matches the `breakdown` arg.""" + + name: Optional[str] = None + """Display name of the entity, when available.""" + + summary: BreakdownSummary + """Aggregate totals and rates for this entity over the date range.""" + + +class Granularity(BaseModel): + """Per-bucket ad performance for an ad campaign, ad group, or ad. + + Bucket grain is set by the `ad_report` query's `granularity` argument. + """ + + bucket_start: datetime + """The bucket's start time as a real UTC instant. + + `(statDate, statHour)` resolved in the ad account's reporting timezone — render + this in the viewer's local timezone. + """ + + clicks: int + """Clicks in this bucket.""" + + granularity: Granularities + """The bucket size of this row (`daily` or `hourly`).""" + + impressions: int + """Impressions in this bucket.""" + + reach: int + """Unique users reached in this bucket. + + Always `0` for hourly rows (Meta does not return reach at hourly grain). + """ + + result_count: Optional[int] = None + """Count of the primary optimization result in this bucket.""" + + result_label_key: Optional[ResultLabelKeys] = None + """Types of optimization results tracked from external ad platforms""" + + result_label_override: Optional[str] = None + """Advertiser-defined label for the result when `resultLabelKey` is `custom`.""" + + spend: float + """ + Charged spend in this bucket in the requested reporting currency — the amount + billed including platform fees, not the platform-side net spend. + """ + + spend_currency: Currency + """Currency of the `spend` value.""" + + stat_date: datetime + """The date these stats cover (midnight UTC). + + For hourly rows, see `statHour` and `bucketStart`. + """ + + stat_hour: Optional[int] = None + """Hour of the day in the ad account's reporting timezone (0-23). + + `null` for daily rows. + """ class Summary(BaseModel): @@ -104,34 +248,7 @@ class Summary(BaseModel): see `resultLabelKey`. """ - result_label_key: Optional[ - Literal[ - "app_installs", - "messaging_conversations_started", - "post_engagement", - "event_responses", - "impressions", - "website_purchases", - "landing_page_views", - "leads", - "link_clicks", - "quality_calls", - "appointments_booked", - "messaging_purchases", - "page_likes", - "instagram_profile_visits", - "reach", - "reminders_set", - "new_subscribers", - "video_views", - "registrations", - "content_views", - "searches", - "website_schedules", - "website_submit_applications", - "custom", - ] - ] = None + result_label_key: Optional[ResultLabelKeys] = None """Types of optimization results tracked from external ad platforms""" result_label_override: Optional[str] = None @@ -153,13 +270,22 @@ class Summary(BaseModel): class AdReportRetrieveResponse(BaseModel): """An ads performance report. - Returns a summary; daily breakdown is included when `includeDaily` is true. + Always returns a summary. The `granularity` field contains a per-bucket time series when the `granularity` arg is set; the `breakdown` field contains per-entity rows when the `breakdown` arg is set. + """ + + breakdown: Optional[List[Breakdown]] = None + """Per-entity rows over the date range. + + `null` when the `breakdown` arg on `adReport` is omitted; otherwise contains one + row per ad campaign, ad group, or ad inside the requested scope at the requested + level. """ - daily: Optional[List[Daily]] = None - """Per-day breakdown over the date range, ordered ascending. + granularity: Optional[List[Granularity]] = None + """Per-bucket time series over the date range, ordered ascending by `bucketStart`. - Null when `includeDaily` is false. + `null` when the `granularity` arg on `adReport` is omitted; otherwise contains + rows at the requested grain (`daily` or `hourly`). """ summary: Summary diff --git a/src/whop_sdk/types/dispute.py b/src/whop_sdk/types/dispute.py index 59efd690..b093b0c2 100644 --- a/src/whop_sdk/types/dispute.py +++ b/src/whop_sdk/types/dispute.py @@ -154,8 +154,8 @@ class Payment(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" @@ -335,10 +335,7 @@ class Dispute(BaseModel): """ editable: Optional[bool] = None - """Whether the dispute evidence can still be edited and submitted. - - Returns true only when the dispute status requires a response. - """ + """Whether the dispute evidence can still be edited and submitted.""" needs_response_by: Optional[datetime] = None """The deadline by which dispute evidence must be submitted. diff --git a/src/whop_sdk/types/dispute_alert_created_webhook_event.py b/src/whop_sdk/types/dispute_alert_created_webhook_event.py index e55b91df..5d527363 100644 --- a/src/whop_sdk/types/dispute_alert_created_webhook_event.py +++ b/src/whop_sdk/types/dispute_alert_created_webhook_event.py @@ -109,8 +109,8 @@ class DataPayment(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" diff --git a/src/whop_sdk/types/dispute_alert_retrieve_response.py b/src/whop_sdk/types/dispute_alert_retrieve_response.py index af101035..a9d78ef8 100644 --- a/src/whop_sdk/types/dispute_alert_retrieve_response.py +++ b/src/whop_sdk/types/dispute_alert_retrieve_response.py @@ -100,8 +100,8 @@ class Payment(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" diff --git a/src/whop_sdk/types/dispute_list_response.py b/src/whop_sdk/types/dispute_list_response.py index 11e58edd..46e665e2 100644 --- a/src/whop_sdk/types/dispute_list_response.py +++ b/src/whop_sdk/types/dispute_list_response.py @@ -74,10 +74,7 @@ class DisputeListResponse(BaseModel): """The three-letter ISO currency code for the disputed amount.""" editable: Optional[bool] = None - """Whether the dispute evidence can still be edited and submitted. - - Returns true only when the dispute status requires a response. - """ + """Whether the dispute evidence can still be edited and submitted.""" needs_response_by: Optional[datetime] = None """The deadline by which dispute evidence must be submitted. diff --git a/src/whop_sdk/types/external_ad_status.py b/src/whop_sdk/types/external_ad_status.py new file mode 100644 index 00000000..1fa97884 --- /dev/null +++ b/src/whop_sdk/types/external_ad_status.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["ExternalAdStatus"] + +ExternalAdStatus: TypeAlias = Literal["active", "paused", "inactive", "in_review", "rejected", "flagged"] diff --git a/src/whop_sdk/types/file_create_params.py b/src/whop_sdk/types/file_create_params.py index 6df14110..9419faf2 100644 --- a/src/whop_sdk/types/file_create_params.py +++ b/src/whop_sdk/types/file_create_params.py @@ -3,7 +3,9 @@ from __future__ import annotations from typing import Optional -from typing_extensions import Literal, Required, TypedDict +from typing_extensions import Required, TypedDict + +from .file_visibility import FileVisibility __all__ = ["FileCreateParams"] @@ -15,7 +17,7 @@ class FileCreateParams(TypedDict, total=False): "document.pdf"). """ - visibility: Optional[Literal["public", "private"]] + visibility: Optional[FileVisibility] """ Controls whether an uploaded file is publicly accessible or requires authentication to access. diff --git a/src/whop_sdk/types/file_create_response.py b/src/whop_sdk/types/file_create_response.py index 5c9e2fa4..b35c9d65 100644 --- a/src/whop_sdk/types/file_create_response.py +++ b/src/whop_sdk/types/file_create_response.py @@ -1,10 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Dict, Optional -from typing_extensions import Literal from .._models import BaseModel from .upload_status import UploadStatus +from .file_visibility import FileVisibility __all__ = ["FileCreateResponse"] @@ -46,5 +46,5 @@ class FileCreateResponse(BaseModel): signed URL that expires. Null if the file has not finished uploading. """ - visibility: Literal["public", "private"] + visibility: FileVisibility """Whether the file is publicly accessible or requires authentication.""" diff --git a/src/whop_sdk/types/file_retrieve_response.py b/src/whop_sdk/types/file_retrieve_response.py index c60e895e..27e8b1c0 100644 --- a/src/whop_sdk/types/file_retrieve_response.py +++ b/src/whop_sdk/types/file_retrieve_response.py @@ -1,10 +1,10 @@ # 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 from .upload_status import UploadStatus +from .file_visibility import FileVisibility __all__ = ["FileRetrieveResponse"] @@ -34,5 +34,5 @@ class FileRetrieveResponse(BaseModel): signed URL that expires. Null if the file has not finished uploading. """ - visibility: Literal["public", "private"] + visibility: FileVisibility """Whether the file is publicly accessible or requires authentication.""" diff --git a/src/whop_sdk/types/file_visibility.py b/src/whop_sdk/types/file_visibility.py new file mode 100644 index 00000000..7ba3bae2 --- /dev/null +++ b/src/whop_sdk/types/file_visibility.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["FileVisibility"] + +FileVisibility: TypeAlias = Literal["public", "private"] diff --git a/src/whop_sdk/types/granularities.py b/src/whop_sdk/types/granularities.py new file mode 100644 index 00000000..1a199166 --- /dev/null +++ b/src/whop_sdk/types/granularities.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["Granularities"] + +Granularities: TypeAlias = Literal["daily", "hourly"] diff --git a/src/whop_sdk/types/member_list_response.py b/src/whop_sdk/types/member_list_response.py index e45faf1d..0b3476f9 100644 --- a/src/whop_sdk/types/member_list_response.py +++ b/src/whop_sdk/types/member_list_response.py @@ -44,7 +44,10 @@ class MemberListResponse(BaseModel): """ company_token_balance: float - """The member's token balance for this company""" + """The member's token balance for this company. + + Computed live from the ledger, not from a cache. + """ created_at: datetime """The datetime the company member was created.""" diff --git a/src/whop_sdk/types/member_retrieve_response.py b/src/whop_sdk/types/member_retrieve_response.py index 6f428666..1f513422 100644 --- a/src/whop_sdk/types/member_retrieve_response.py +++ b/src/whop_sdk/types/member_retrieve_response.py @@ -60,7 +60,10 @@ class MemberRetrieveResponse(BaseModel): """The company for the member.""" company_token_balance: float - """The member's token balance for this company""" + """The member's token balance for this company. + + Computed live from the ledger, not from a cache. + """ created_at: datetime """The datetime the company member was created.""" diff --git a/src/whop_sdk/types/membership_list_response.py b/src/whop_sdk/types/membership_list_response.py index 683d67d7..89bccb93 100644 --- a/src/whop_sdk/types/membership_list_response.py +++ b/src/whop_sdk/types/membership_list_response.py @@ -37,6 +37,12 @@ class Plan(BaseModel): id: str """The unique identifier for the plan.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the plan. + + Included in webhook payloads for payment and membership events. + """ + class Product(BaseModel): """The product this membership grants access to.""" @@ -44,6 +50,12 @@ class Product(BaseModel): id: str """The unique identifier for the product.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + title: str """ The display name of the product shown to customers on the product page and in diff --git a/src/whop_sdk/types/payment_list_params.py b/src/whop_sdk/types/payment_list_params.py index 1fcc2a22..16e0cee1 100644 --- a/src/whop_sdk/types/payment_list_params.py +++ b/src/whop_sdk/types/payment_list_params.py @@ -27,6 +27,9 @@ class PaymentListParams(TypedDict, total=False): billing_reasons: Optional[List[BillingReasons]] """Filter payments by their billing reason.""" + checkout_configuration_ids: Optional[SequenceNotStr[str]] + """Only return payments from these checkout configurations.""" + company_id: Optional[str] """The unique identifier of the company to list payments for.""" diff --git a/src/whop_sdk/types/payment_list_response.py b/src/whop_sdk/types/payment_list_response.py index 2af1a1d6..20991eb4 100644 --- a/src/whop_sdk/types/payment_list_response.py +++ b/src/whop_sdk/types/payment_list_response.py @@ -160,6 +160,12 @@ class Plan(BaseModel): internal_notes: Optional[str] = None """A personal description or notes section for the business.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the plan. + + Included in webhook payloads for payment and membership events. + """ + class Product(BaseModel): """The product this payment was made for""" @@ -167,6 +173,12 @@ class Product(BaseModel): id: str """The unique identifier for the product.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + route: str """ The URL slug used in the product's public link (e.g., 'my-product' in @@ -271,8 +283,8 @@ class PaymentListResponse(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" @@ -345,12 +357,8 @@ class PaymentListResponse(BaseModel): otherwise false. Used to decide if Whop can attempt the charge again. """ - settlement_currency: str - """ - The currency in which the creator receives payouts and fees are charged (e.g., - 'usd', 'eur'). For multi-currency payments this differs from the payment - currency. - """ + settlement_currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" status: Optional[ReceiptStatus] = None """The status of a receipt""" diff --git a/src/whop_sdk/types/plan_create_params.py b/src/whop_sdk/types/plan_create_params.py index c0d6f89c..1a9d20b5 100644 --- a/src/whop_sdk/types/plan_create_params.py +++ b/src/whop_sdk/types/plan_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import Dict, List, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from .checkout_font import CheckoutFont @@ -71,6 +71,13 @@ class PlanCreateParams(TypedDict, total=False): legacy_payment_method_controls: Optional[bool] """Whether this plan uses legacy payment method controls.""" + metadata: Optional[Dict[str, 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. + """ + override_tax_type: Optional[TaxType] """ Whether or not the tax is included in a plan's price (or if it hasn't been set diff --git a/src/whop_sdk/types/plan_list_response.py b/src/whop_sdk/types/plan_list_response.py index b034018e..08ab9df8 100644 --- a/src/whop_sdk/types/plan_list_response.py +++ b/src/whop_sdk/types/plan_list_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from .._models import BaseModel @@ -152,6 +152,12 @@ class PlanListResponse(BaseModel): 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. + """ + payment_method_configuration: Optional[PaymentMethodConfiguration] = None """ The explicit payment method configuration specifying which payment methods are diff --git a/src/whop_sdk/types/plan_update_params.py b/src/whop_sdk/types/plan_update_params.py index d150d067..6707cead 100644 --- a/src/whop_sdk/types/plan_update_params.py +++ b/src/whop_sdk/types/plan_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Iterable, Optional +from typing import Dict, List, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from .checkout_font import CheckoutFont @@ -61,6 +61,13 @@ class PlanUpdateParams(TypedDict, total=False): legacy_payment_method_controls: Optional[bool] """Whether this plan uses legacy payment method controls.""" + metadata: Optional[Dict[str, 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. + """ + offer_cancel_discount: Optional[bool] """Whether to offer a retention discount when a customer attempts to cancel.""" diff --git a/src/whop_sdk/types/product_create_params.py b/src/whop_sdk/types/product_create_params.py index ed4c851c..103fbc3d 100644 --- a/src/whop_sdk/types/product_create_params.py +++ b/src/whop_sdk/types/product_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr @@ -69,6 +69,13 @@ class ProductCreateParams(TypedDict, total=False): 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. + """ + plan_options: Optional[PlanOptions] """Configuration for an automatically generated plan to attach to this product.""" diff --git a/src/whop_sdk/types/product_update_params.py b/src/whop_sdk/types/product_update_params.py index 6082edf2..64a7c8c1 100644 --- a/src/whop_sdk/types/product_update_params.py +++ b/src/whop_sdk/types/product_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Iterable, Optional +from typing import Dict, Iterable, Optional from typing_extensions import Required, TypedDict from .shared.custom_cta import CustomCta @@ -59,6 +59,13 @@ class ProductUpdateParams(TypedDict, total=False): 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.""" diff --git a/src/whop_sdk/types/refund_created_webhook_event.py b/src/whop_sdk/types/refund_created_webhook_event.py index cd83e28c..ccf930c2 100644 --- a/src/whop_sdk/types/refund_created_webhook_event.py +++ b/src/whop_sdk/types/refund_created_webhook_event.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Dict, Optional from datetime import datetime from typing_extensions import Literal @@ -21,6 +21,8 @@ "DataPayment", "DataPaymentMember", "DataPaymentMembership", + "DataPaymentPlan", + "DataPaymentProduct", "DataPaymentUser", ] @@ -45,6 +47,32 @@ class DataPaymentMembership(BaseModel): """The state of the membership.""" +class DataPaymentPlan(BaseModel): + """The plan attached to this payment.""" + + id: str + """The unique identifier for the plan.""" + + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the plan. + + Included in webhook payloads for payment and membership events. + """ + + +class DataPaymentProduct(BaseModel): + """The product this payment was made for""" + + id: str + """The unique identifier for the product.""" + + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + + class DataPaymentUser(BaseModel): """The user that made this payment.""" @@ -88,8 +116,8 @@ class DataPayment(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" @@ -100,6 +128,13 @@ class DataPayment(BaseModel): membership: Optional[DataPaymentMembership] = None """The membership attached to this payment.""" + metadata: Optional[Dict[str, object]] = None + """The custom metadata stored on this payment. + + This will be copied over to the checkout configuration for which this payment + was made + """ + paid_at: Optional[datetime] = None """The time at which this payment was successfully collected. @@ -109,6 +144,12 @@ class DataPayment(BaseModel): payment_method_type: Optional[PaymentMethodTypes] = None """The different types of payment methods that can be used.""" + plan: Optional[DataPaymentPlan] = None + """The plan attached to this payment.""" + + product: Optional[DataPaymentProduct] = None + """The product this payment was made for""" + subtotal: Optional[float] = None """The subtotal to show to the creator (excluding buyer fees).""" diff --git a/src/whop_sdk/types/refund_retrieve_response.py b/src/whop_sdk/types/refund_retrieve_response.py index 973ec6c3..209d6d6d 100644 --- a/src/whop_sdk/types/refund_retrieve_response.py +++ b/src/whop_sdk/types/refund_retrieve_response.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Dict, Optional from datetime import datetime from .._models import BaseModel @@ -14,7 +14,15 @@ from .refund_reference_status import RefundReferenceStatus from .shared.membership_status import MembershipStatus -__all__ = ["RefundRetrieveResponse", "Payment", "PaymentMember", "PaymentMembership", "PaymentUser"] +__all__ = [ + "RefundRetrieveResponse", + "Payment", + "PaymentMember", + "PaymentMembership", + "PaymentPlan", + "PaymentProduct", + "PaymentUser", +] class PaymentMember(BaseModel): @@ -37,6 +45,32 @@ class PaymentMembership(BaseModel): """The state of the membership.""" +class PaymentPlan(BaseModel): + """The plan attached to this payment.""" + + id: str + """The unique identifier for the plan.""" + + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the plan. + + Included in webhook payloads for payment and membership events. + """ + + +class PaymentProduct(BaseModel): + """The product this payment was made for""" + + id: str + """The unique identifier for the product.""" + + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + + class PaymentUser(BaseModel): """The user that made this payment.""" @@ -80,8 +114,8 @@ class Payment(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" @@ -92,6 +126,13 @@ class Payment(BaseModel): membership: Optional[PaymentMembership] = None """The membership attached to this payment.""" + metadata: Optional[Dict[str, object]] = None + """The custom metadata stored on this payment. + + This will be copied over to the checkout configuration for which this payment + was made + """ + paid_at: Optional[datetime] = None """The time at which this payment was successfully collected. @@ -101,6 +142,12 @@ class Payment(BaseModel): payment_method_type: Optional[PaymentMethodTypes] = None """The different types of payment methods that can be used.""" + plan: Optional[PaymentPlan] = None + """The plan attached to this payment.""" + + product: Optional[PaymentProduct] = None + """The product this payment was made for""" + subtotal: Optional[float] = None """The subtotal to show to the creator (excluding buyer fees).""" diff --git a/src/whop_sdk/types/refund_updated_webhook_event.py b/src/whop_sdk/types/refund_updated_webhook_event.py index c7d7c86e..6650626c 100644 --- a/src/whop_sdk/types/refund_updated_webhook_event.py +++ b/src/whop_sdk/types/refund_updated_webhook_event.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Dict, Optional from datetime import datetime from typing_extensions import Literal @@ -21,6 +21,8 @@ "DataPayment", "DataPaymentMember", "DataPaymentMembership", + "DataPaymentPlan", + "DataPaymentProduct", "DataPaymentUser", ] @@ -45,6 +47,32 @@ class DataPaymentMembership(BaseModel): """The state of the membership.""" +class DataPaymentPlan(BaseModel): + """The plan attached to this payment.""" + + id: str + """The unique identifier for the plan.""" + + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the plan. + + Included in webhook payloads for payment and membership events. + """ + + +class DataPaymentProduct(BaseModel): + """The product this payment was made for""" + + id: str + """The unique identifier for the product.""" + + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + + class DataPaymentUser(BaseModel): """The user that made this payment.""" @@ -88,8 +116,8 @@ class DataPayment(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" @@ -100,6 +128,13 @@ class DataPayment(BaseModel): membership: Optional[DataPaymentMembership] = None """The membership attached to this payment.""" + metadata: Optional[Dict[str, object]] = None + """The custom metadata stored on this payment. + + This will be copied over to the checkout configuration for which this payment + was made + """ + paid_at: Optional[datetime] = None """The time at which this payment was successfully collected. @@ -109,6 +144,12 @@ class DataPayment(BaseModel): payment_method_type: Optional[PaymentMethodTypes] = None """The different types of payment methods that can be used.""" + plan: Optional[DataPaymentPlan] = None + """The plan attached to this payment.""" + + product: Optional[DataPaymentProduct] = None + """The product this payment was made for""" + subtotal: Optional[float] = None """The subtotal to show to the creator (excluding buyer fees).""" diff --git a/src/whop_sdk/types/resolution_center_case_platform_response.py b/src/whop_sdk/types/resolution_center_case_platform_response.py index 0dce38a9..e039d6f0 100644 --- a/src/whop_sdk/types/resolution_center_case_platform_response.py +++ b/src/whop_sdk/types/resolution_center_case_platform_response.py @@ -5,5 +5,5 @@ __all__ = ["ResolutionCenterCasePlatformResponse"] ResolutionCenterCasePlatformResponse: TypeAlias = Literal[ - "request_buyer_info", "request_merchant_info", "merchant_wins", "platform_refund", "merchant_refund" + "request_buyer_info", "request_merchant_info", "merchant_wins", "merchant_refund" ] diff --git a/src/whop_sdk/types/result_label_keys.py b/src/whop_sdk/types/result_label_keys.py new file mode 100644 index 00000000..4a4d4657 --- /dev/null +++ b/src/whop_sdk/types/result_label_keys.py @@ -0,0 +1,32 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["ResultLabelKeys"] + +ResultLabelKeys: TypeAlias = Literal[ + "app_installs", + "messaging_conversations_started", + "post_engagement", + "event_responses", + "impressions", + "website_purchases", + "landing_page_views", + "leads", + "link_clicks", + "quality_calls", + "appointments_booked", + "messaging_purchases", + "page_likes", + "instagram_profile_visits", + "reach", + "reminders_set", + "new_subscribers", + "video_views", + "registrations", + "content_views", + "searches", + "website_schedules", + "website_submit_applications", + "custom", +] diff --git a/src/whop_sdk/types/shared/membership.py b/src/whop_sdk/types/shared/membership.py index c2bcea69..4f8d3fd0 100644 --- a/src/whop_sdk/types/shared/membership.py +++ b/src/whop_sdk/types/shared/membership.py @@ -50,6 +50,12 @@ class Plan(BaseModel): id: str """The unique identifier for the plan.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the plan. + + Included in webhook payloads for payment and membership events. + """ + class Product(BaseModel): """The product this membership grants access to.""" @@ -57,6 +63,12 @@ class Product(BaseModel): id: str """The unique identifier for the product.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + title: str """ The display name of the product shown to customers on the product page and in diff --git a/src/whop_sdk/types/shared/payment.py b/src/whop_sdk/types/shared/payment.py index bc9a6dcb..d424133c 100644 --- a/src/whop_sdk/types/shared/payment.py +++ b/src/whop_sdk/types/shared/payment.py @@ -114,10 +114,7 @@ class Dispute(BaseModel): """The three-letter ISO currency code for the disputed amount.""" editable: Optional[bool] = None - """Whether the dispute evidence can still be edited and submitted. - - Returns true only when the dispute status requires a response. - """ + """Whether the dispute evidence can still be edited and submitted.""" needs_response_by: Optional[datetime] = None """The deadline by which dispute evidence must be submitted. @@ -256,6 +253,12 @@ class Plan(BaseModel): internal_notes: Optional[str] = None """A personal description or notes section for the business.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the plan. + + Included in webhook payloads for payment and membership events. + """ + class Product(BaseModel): """The product this payment was made for""" @@ -263,6 +266,12 @@ class Product(BaseModel): id: str """The unique identifier for the product.""" + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + route: str """ The URL slug used in the product's public link (e.g., 'my-product' in @@ -409,8 +418,8 @@ class Payment(BaseModel): created_at: datetime """The datetime the payment was created.""" - currency: Optional[Currency] = None - """The available currencies on the platform""" + currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" dispute_alerted_at: Optional[datetime] = None """When an alert came in that this transaction will be disputed""" @@ -510,22 +519,15 @@ class Payment(BaseModel): settlement_amount: float """ - The payment amount in the creator's settlement currency (what the creator priced - in). Equal to final_amount for single-currency payments. + The total amount charged to the customer for this payment, including taxes and + after any discounts. In the currency specified by the currency field. """ - settlement_currency: str - """ - The currency in which the creator receives payouts and fees are charged (e.g., - 'usd', 'eur'). For multi-currency payments this differs from the payment - currency. - """ + settlement_currency: Currency + """The three-letter ISO currency code for this payment (e.g., 'usd', 'eur').""" settlement_exchange_rate: Optional[float] = None - """ - The locked exchange rate used to convert from the buyer's payment currency to - the creator's settlement currency. Null for single-currency payments. - """ + """Deprecated. Always returns null.""" status: Optional[ReceiptStatus] = None """The status of a receipt""" diff --git a/src/whop_sdk/types/shared/plan.py b/src/whop_sdk/types/shared/plan.py index c603ac95..7651e947 100644 --- a/src/whop_sdk/types/shared/plan.py +++ b/src/whop_sdk/types/shared/plan.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal @@ -188,6 +188,12 @@ class Plan(BaseModel): 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. + """ + payment_method_configuration: Optional[PaymentMethodConfiguration] = None """ The explicit payment method configuration specifying which payment methods are diff --git a/src/whop_sdk/types/shared/product.py b/src/whop_sdk/types/shared/product.py index 5410a7c0..ce6299b8 100644 --- a/src/whop_sdk/types/shared/product.py +++ b/src/whop_sdk/types/shared/product.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal @@ -159,6 +159,12 @@ class Product(BaseModel): Returns 0 if the company has disabled public member counts. """ + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + owner_user: OwnerUser """The user who owns the company that sells this product.""" diff --git a/src/whop_sdk/types/shared/product_list_item.py b/src/whop_sdk/types/shared/product_list_item.py index e0afce7f..af1e59d5 100644 --- a/src/whop_sdk/types/shared/product_list_item.py +++ b/src/whop_sdk/types/shared/product_list_item.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Dict, Optional from datetime import datetime from ..._models import BaseModel @@ -37,6 +37,12 @@ class ProductListItem(BaseModel): Returns 0 if the company has disabled public member counts. """ + metadata: Optional[Dict[str, object]] = None + """Custom key-value pairs stored on the product. + + Included in webhook payloads for payment and membership events. + """ + published_reviews_count: int """The total number of published customer reviews for this product's company.""" diff --git a/tests/api_resources/test_ad_campaigns.py b/tests/api_resources/test_ad_campaigns.py index 63f382a7..cee5f625 100644 --- a/tests/api_resources/test_ad_campaigns.py +++ b/tests/api_resources/test_ad_campaigns.py @@ -10,11 +10,8 @@ from whop_sdk import Whop, AsyncWhop from tests.utils import assert_matches_type from whop_sdk.types import ( + AdCampaign, AdCampaignListResponse, - AdCampaignPauseResponse, - AdCampaignUpdateResponse, - AdCampaignUnpauseResponse, - AdCampaignRetrieveResponse, ) from whop_sdk._utils import parse_datetime from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage @@ -31,7 +28,7 @@ def test_method_retrieve(self, client: Whop) -> None: ad_campaign = client.ad_campaigns.retrieve( "adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignRetrieveResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -43,7 +40,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignRetrieveResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -55,7 +52,7 @@ def test_streaming_response_retrieve(self, client: Whop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignRetrieveResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True @@ -73,7 +70,7 @@ def test_method_update(self, client: Whop) -> None: ad_campaign = client.ad_campaigns.update( id="adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -82,7 +79,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None: id="adcamp_xxxxxxxxxxx", budget=6.9, ) - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -94,7 +91,7 @@ def test_raw_response_update(self, client: Whop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -106,7 +103,7 @@ def test_streaming_response_update(self, client: Whop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True @@ -174,7 +171,7 @@ def test_method_pause(self, client: Whop) -> None: ad_campaign = client.ad_campaigns.pause( "adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignPauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -186,7 +183,7 @@ def test_raw_response_pause(self, client: Whop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignPauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -198,7 +195,7 @@ def test_streaming_response_pause(self, client: Whop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignPauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True @@ -216,7 +213,7 @@ def test_method_unpause(self, client: Whop) -> None: ad_campaign = client.ad_campaigns.unpause( "adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignUnpauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -228,7 +225,7 @@ def test_raw_response_unpause(self, client: Whop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignUnpauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -240,7 +237,7 @@ def test_streaming_response_unpause(self, client: Whop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = response.parse() - assert_matches_type(AdCampaignUnpauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True @@ -264,7 +261,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None: ad_campaign = await async_client.ad_campaigns.retrieve( "adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignRetrieveResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -276,7 +273,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignRetrieveResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -288,7 +285,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignRetrieveResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True @@ -306,7 +303,7 @@ async def test_method_update(self, async_client: AsyncWhop) -> None: ad_campaign = await async_client.ad_campaigns.update( id="adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -315,7 +312,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N id="adcamp_xxxxxxxxxxx", budget=6.9, ) - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -327,7 +324,7 @@ async def test_raw_response_update(self, async_client: AsyncWhop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -339,7 +336,7 @@ async def test_streaming_response_update(self, async_client: AsyncWhop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignUpdateResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True @@ -407,7 +404,7 @@ async def test_method_pause(self, async_client: AsyncWhop) -> None: ad_campaign = await async_client.ad_campaigns.pause( "adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignPauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -419,7 +416,7 @@ async def test_raw_response_pause(self, async_client: AsyncWhop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignPauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -431,7 +428,7 @@ async def test_streaming_response_pause(self, async_client: AsyncWhop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignPauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True @@ -449,7 +446,7 @@ async def test_method_unpause(self, async_client: AsyncWhop) -> None: ad_campaign = await async_client.ad_campaigns.unpause( "adcamp_xxxxxxxxxxx", ) - assert_matches_type(AdCampaignUnpauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -461,7 +458,7 @@ async def test_raw_response_unpause(self, async_client: AsyncWhop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignUnpauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -473,7 +470,7 @@ async def test_streaming_response_unpause(self, async_client: AsyncWhop) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_campaign = await response.parse() - assert_matches_type(AdCampaignUnpauseResponse, ad_campaign, path=["response"]) + assert_matches_type(AdCampaign, ad_campaign, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_ad_groups.py b/tests/api_resources/test_ad_groups.py index 038841b8..023fd6b5 100644 --- a/tests/api_resources/test_ad_groups.py +++ b/tests/api_resources/test_ad_groups.py @@ -10,10 +10,9 @@ from whop_sdk import Whop, AsyncWhop from tests.utils import assert_matches_type from whop_sdk.types import ( + AdGroup, AdGroupListResponse, AdGroupDeleteResponse, - AdGroupUpdateResponse, - AdGroupRetrieveResponse, ) from whop_sdk._utils import parse_datetime from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage @@ -30,7 +29,7 @@ def test_method_retrieve(self, client: Whop) -> None: ad_group = client.ad_groups.retrieve( "adgrp_xxxxxxxxxxxx", ) - assert_matches_type(AdGroupRetrieveResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -42,7 +41,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = response.parse() - assert_matches_type(AdGroupRetrieveResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -54,7 +53,7 @@ def test_streaming_response_retrieve(self, client: Whop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = response.parse() - assert_matches_type(AdGroupRetrieveResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) assert cast(Any, response.is_closed) is True @@ -72,7 +71,7 @@ def test_method_update(self, client: Whop) -> None: ad_group = client.ad_groups.update( id="adgrp_xxxxxxxxxxxx", ) - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -421,7 +420,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None: }, status="active", ) - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -433,7 +432,7 @@ def test_raw_response_update(self, client: Whop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = response.parse() - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -445,7 +444,7 @@ def test_streaming_response_update(self, client: Whop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = response.parse() - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) assert cast(Any, response.is_closed) is True @@ -544,6 +543,90 @@ def test_path_params_delete(self, client: Whop) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_pause(self, client: Whop) -> None: + ad_group = client.ad_groups.pause( + "adgrp_xxxxxxxxxxxx", + ) + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_pause(self, client: Whop) -> None: + response = client.ad_groups.with_raw_response.pause( + "adgrp_xxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad_group = response.parse() + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_pause(self, client: Whop) -> None: + with client.ad_groups.with_streaming_response.pause( + "adgrp_xxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad_group = response.parse() + assert_matches_type(AdGroup, ad_group, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_pause(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.pause( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_unpause(self, client: Whop) -> None: + ad_group = client.ad_groups.unpause( + "adgrp_xxxxxxxxxxxx", + ) + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_unpause(self, client: Whop) -> None: + response = client.ad_groups.with_raw_response.unpause( + "adgrp_xxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad_group = response.parse() + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_unpause(self, client: Whop) -> None: + with client.ad_groups.with_streaming_response.unpause( + "adgrp_xxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad_group = response.parse() + assert_matches_type(AdGroup, ad_group, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_unpause(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.unpause( + "", + ) + class TestAsyncAdGroups: parametrize = pytest.mark.parametrize( @@ -556,7 +639,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None: ad_group = await async_client.ad_groups.retrieve( "adgrp_xxxxxxxxxxxx", ) - assert_matches_type(AdGroupRetrieveResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -568,7 +651,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = await response.parse() - assert_matches_type(AdGroupRetrieveResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -580,7 +663,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = await response.parse() - assert_matches_type(AdGroupRetrieveResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) assert cast(Any, response.is_closed) is True @@ -598,7 +681,7 @@ async def test_method_update(self, async_client: AsyncWhop) -> None: ad_group = await async_client.ad_groups.update( id="adgrp_xxxxxxxxxxxx", ) - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -947,7 +1030,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N }, status="active", ) - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -959,7 +1042,7 @@ async def test_raw_response_update(self, async_client: AsyncWhop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = await response.parse() - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -971,7 +1054,7 @@ async def test_streaming_response_update(self, async_client: AsyncWhop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad_group = await response.parse() - assert_matches_type(AdGroupUpdateResponse, ad_group, path=["response"]) + assert_matches_type(AdGroup, ad_group, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1069,3 +1152,87 @@ async def test_path_params_delete(self, async_client: AsyncWhop) -> None: await async_client.ad_groups.with_raw_response.delete( "", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_pause(self, async_client: AsyncWhop) -> None: + ad_group = await async_client.ad_groups.pause( + "adgrp_xxxxxxxxxxxx", + ) + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_pause(self, async_client: AsyncWhop) -> None: + response = await async_client.ad_groups.with_raw_response.pause( + "adgrp_xxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad_group = await response.parse() + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_pause(self, async_client: AsyncWhop) -> None: + async with async_client.ad_groups.with_streaming_response.pause( + "adgrp_xxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad_group = await response.parse() + assert_matches_type(AdGroup, ad_group, 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_pause(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.pause( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_unpause(self, async_client: AsyncWhop) -> None: + ad_group = await async_client.ad_groups.unpause( + "adgrp_xxxxxxxxxxxx", + ) + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_unpause(self, async_client: AsyncWhop) -> None: + response = await async_client.ad_groups.with_raw_response.unpause( + "adgrp_xxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad_group = await response.parse() + assert_matches_type(AdGroup, ad_group, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_unpause(self, async_client: AsyncWhop) -> None: + async with async_client.ad_groups.with_streaming_response.unpause( + "adgrp_xxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad_group = await response.parse() + assert_matches_type(AdGroup, ad_group, 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_unpause(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.unpause( + "", + ) diff --git a/tests/api_resources/test_ad_reports.py b/tests/api_resources/test_ad_reports.py index ea37e037..a5b76624 100644 --- a/tests/api_resources/test_ad_reports.py +++ b/tests/api_resources/test_ad_reports.py @@ -36,8 +36,10 @@ def test_method_retrieve_with_all_params(self, client: Whop) -> None: ad_campaign_id="ad_campaign_id", ad_group_id="ad_group_id", ad_id="ad_id", + breakdown="campaign", + company_id="biz_xxxxxxxxxxxxxx", currency="currency", - include_daily=True, + granularity="daily", ) assert_matches_type(AdReportRetrieveResponse, ad_report, path=["response"]) @@ -93,8 +95,10 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncWhop) -> ad_campaign_id="ad_campaign_id", ad_group_id="ad_group_id", ad_id="ad_id", + breakdown="campaign", + company_id="biz_xxxxxxxxxxxxxx", currency="currency", - include_daily=True, + granularity="daily", ) 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 68180402..2753ef42 100644 --- a/tests/api_resources/test_ads.py +++ b/tests/api_resources/test_ads.py @@ -9,7 +9,7 @@ from whop_sdk import Whop, AsyncWhop from tests.utils import assert_matches_type -from whop_sdk.types import AdListResponse, AdRetrieveResponse +from whop_sdk.types import Ad, AdListResponse from whop_sdk._utils import parse_datetime from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage @@ -25,7 +25,7 @@ def test_method_retrieve(self, client: Whop) -> None: ad = client.ads.retrieve( "ad_xxxxxxxxxxxxxxx", ) - assert_matches_type(AdRetrieveResponse, ad, path=["response"]) + assert_matches_type(Ad, ad, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -37,7 +37,7 @@ def test_raw_response_retrieve(self, client: Whop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad = response.parse() - assert_matches_type(AdRetrieveResponse, ad, path=["response"]) + assert_matches_type(Ad, ad, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -49,7 +49,7 @@ def test_streaming_response_retrieve(self, client: Whop) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad = response.parse() - assert_matches_type(AdRetrieveResponse, ad, path=["response"]) + assert_matches_type(Ad, ad, path=["response"]) assert cast(Any, response.is_closed) is True @@ -106,6 +106,90 @@ def test_streaming_response_list(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_pause(self, client: Whop) -> None: + ad = client.ads.pause( + "ad_xxxxxxxxxxxxxxx", + ) + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_pause(self, client: Whop) -> None: + response = client.ads.with_raw_response.pause( + "ad_xxxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad = response.parse() + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_pause(self, client: Whop) -> None: + with client.ads.with_streaming_response.pause( + "ad_xxxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad = response.parse() + assert_matches_type(Ad, ad, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_pause(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.ads.with_raw_response.pause( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_unpause(self, client: Whop) -> None: + ad = client.ads.unpause( + "ad_xxxxxxxxxxxxxxx", + ) + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_unpause(self, client: Whop) -> None: + response = client.ads.with_raw_response.unpause( + "ad_xxxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad = response.parse() + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_unpause(self, client: Whop) -> None: + with client.ads.with_streaming_response.unpause( + "ad_xxxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad = response.parse() + assert_matches_type(Ad, ad, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_unpause(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.ads.with_raw_response.unpause( + "", + ) + class TestAsyncAds: parametrize = pytest.mark.parametrize( @@ -118,7 +202,7 @@ async def test_method_retrieve(self, async_client: AsyncWhop) -> None: ad = await async_client.ads.retrieve( "ad_xxxxxxxxxxxxxxx", ) - assert_matches_type(AdRetrieveResponse, ad, path=["response"]) + assert_matches_type(Ad, ad, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -130,7 +214,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad = await response.parse() - assert_matches_type(AdRetrieveResponse, ad, path=["response"]) + assert_matches_type(Ad, ad, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -142,7 +226,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" ad = await response.parse() - assert_matches_type(AdRetrieveResponse, ad, path=["response"]) + assert_matches_type(Ad, ad, path=["response"]) assert cast(Any, response.is_closed) is True @@ -198,3 +282,87 @@ async def test_streaming_response_list(self, async_client: AsyncWhop) -> None: assert_matches_type(AsyncCursorPage[AdListResponse], ad, path=["response"]) assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_pause(self, async_client: AsyncWhop) -> None: + ad = await async_client.ads.pause( + "ad_xxxxxxxxxxxxxxx", + ) + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_pause(self, async_client: AsyncWhop) -> None: + response = await async_client.ads.with_raw_response.pause( + "ad_xxxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad = await response.parse() + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_pause(self, async_client: AsyncWhop) -> None: + async with async_client.ads.with_streaming_response.pause( + "ad_xxxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad = await response.parse() + assert_matches_type(Ad, ad, 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_pause(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.pause( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_unpause(self, async_client: AsyncWhop) -> None: + ad = await async_client.ads.unpause( + "ad_xxxxxxxxxxxxxxx", + ) + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_unpause(self, async_client: AsyncWhop) -> None: + response = await async_client.ads.with_raw_response.unpause( + "ad_xxxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + ad = await response.parse() + assert_matches_type(Ad, ad, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_unpause(self, async_client: AsyncWhop) -> None: + async with async_client.ads.with_streaming_response.unpause( + "ad_xxxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + ad = await response.parse() + assert_matches_type(Ad, ad, 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_unpause(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.unpause( + "", + ) diff --git a/tests/api_resources/test_payments.py b/tests/api_resources/test_payments.py index 628f7f75..fcdf8af8 100644 --- a/tests/api_resources/test_payments.py +++ b/tests/api_resources/test_payments.py @@ -217,6 +217,7 @@ def test_method_list_with_all_params(self, client: Whop) -> None: after="after", before="before", billing_reasons=["subscription_create"], + checkout_configuration_ids=["string"], company_id="biz_xxxxxxxxxxxxxx", created_after=parse_datetime("2023-12-01T05:00:00.401Z"), created_before=parse_datetime("2023-12-01T05:00:00.401Z"), @@ -647,6 +648,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> Non after="after", before="before", billing_reasons=["subscription_create"], + checkout_configuration_ids=["string"], company_id="biz_xxxxxxxxxxxxxx", created_after=parse_datetime("2023-12-01T05:00:00.401Z"), created_before=parse_datetime("2023-12-01T05:00:00.401Z"), diff --git a/tests/api_resources/test_plans.py b/tests/api_resources/test_plans.py index fbe3db1b..ae35df9a 100644 --- a/tests/api_resources/test_plans.py +++ b/tests/api_resources/test_plans.py @@ -63,6 +63,7 @@ def test_method_create_with_all_params(self, client: Whop) -> None: initial_price=6.9, internal_notes="internal_notes", legacy_payment_method_controls=True, + metadata={"foo": "bar"}, override_tax_type="inclusive", payment_method_configuration={ "disabled": ["acss_debit"], @@ -189,6 +190,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None: initial_price=6.9, internal_notes="internal_notes", legacy_payment_method_controls=True, + metadata={"foo": "bar"}, offer_cancel_discount=True, override_tax_type="inclusive", payment_method_configuration={ @@ -383,6 +385,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N initial_price=6.9, internal_notes="internal_notes", legacy_payment_method_controls=True, + metadata={"foo": "bar"}, override_tax_type="inclusive", payment_method_configuration={ "disabled": ["acss_debit"], @@ -509,6 +512,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N initial_price=6.9, internal_notes="internal_notes", legacy_payment_method_controls=True, + metadata={"foo": "bar"}, offer_cancel_discount=True, override_tax_type="inclusive", payment_method_configuration={ diff --git a/tests/api_resources/test_products.py b/tests/api_resources/test_products.py index 19403ed1..b9a1c329 100644 --- a/tests/api_resources/test_products.py +++ b/tests/api_resources/test_products.py @@ -48,6 +48,7 @@ def test_method_create_with_all_params(self, client: Whop) -> None: headline="headline", member_affiliate_percentage=6.9, member_affiliate_status="enabled", + metadata={"foo": "bar"}, plan_options={ "base_currency": "usd", "billing_period": 42, @@ -169,6 +170,7 @@ def test_method_update_with_all_params(self, client: Whop) -> None: 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", @@ -342,6 +344,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncWhop) -> N headline="headline", member_affiliate_percentage=6.9, member_affiliate_status="enabled", + metadata={"foo": "bar"}, plan_options={ "base_currency": "usd", "billing_period": 42, @@ -463,6 +466,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> N 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",